/*
* Copyright (C) 1994-1996 Bas Laarhoven,
* (C) 1996-1997 Claus-Justus Heine.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.c,v $
* $Revision: 1.9 $
* $Date: 1997/10/17 23:01:53 $
*
* This file contains the interrupt service routine and
* associated code for the QIC-40/80/3010/3020 floppy-tape driver
* "ftape" for Linux.
*/
#include <asm/io.h>
#include <asm/dma.h>
#define volatile /* */
#include <linux/ftape.h>
#include <linux/qic117.h>
#include "../lowlevel/ftape-tracing.h"
#include "../lowlevel/fdc-isr.h"
#include "../lowlevel/fdc-io.h"
#include "../lowlevel/ftape-ctl.h"
#include "../lowlevel/ftape-rw.h"
#include "../lowlevel/ftape-io.h"
#include "../lowlevel/ftape-calibr.h"
#include "../lowlevel/ftape-bsm.h"
/* Global vars.
*/
volatile int ft_expected_stray_interrupts;
volatile int ft_interrupt_seen;
volatile int ft_seek_completed;
volatile int ft_hide_interrupt;
/* Local vars.
*/
typedef enum {
no_error = 0, id_am_error = 0x01, id_crc_error = 0x02,
data_am_error = 0x04, data_crc_error = 0x08,
no_data_error = 0x10, overrun_error = 0x20,
} error_cause;
static int stop_read_ahead;
static void print_error_cause(int cause)
{
TRACE_FUN(ft_t_any);
switch (cause) {
case no_data_error:
TRACE(ft_t_noise, "no data error");
break;
case id_am_error:
TRACE(ft_t_noise, "id am error");
break;
case id_crc_error:
TRACE(ft_t_noise, "id crc error");
break;
case data_am_error:
TRACE(ft_t_noise, "data am error");
break;
case data_crc_error:
TRACE(ft_t_noise, "data crc error");
break;
case overrun_error:
TRACE(ft_t_noise, "overrun error");
break;
default:;
}
TRACE_EXIT;
}
static char *fdc_mode_txt(fdc_mode_enum mode)
{
switch (mode) {
case fdc_idle:
return "fdc_idle";
case fdc_reading_data:
return "fdc_reading_data";
case fdc_seeking:
return "fdc_seeking";
case fdc_writing_data:
return "fdc_writing_data";
case fdc_reading_id:
return "fdc_reading_id";
case fdc_recalibrating:
return "fdc_recalibrating";
case fdc_formatting:
return "fdc_formatting";
case fdc_verifying:
return "fdc_verifying";
default:
return "unknown";
}
}
static inline error_cause decode_irq_cause(fdc_mode_enum mode, __u8 st[])
{
error_cause cause = no_error;
TRACE_FUN(ft_t_any);
/* Valid st[], decode cause of interrupt.
*/
switch (st[0] & ST0_INT_MASK) {
case FDC_INT_NORMAL:
TRACE(ft_t_fdc_dma,"normal completion: %s",fdc_mode_txt(mode));
break;
case FDC_INT_ABNORMAL:
TRACE(ft_t_flow, "abnormal completion %s", fdc_mode_txt(mode));
TRACE(ft_t_fdc_dma, "ST0: 0x%02x, ST1: 0x%02x, ST2: 0x%02x",
st[0], st[1], st[2]);
TRACE(ft_t_fdc_dma,
"C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x",
st[3], st[4], st[5], st[6]);
if (st[1] & 0x01) {
if (