Commit 3679a65c authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] un'fix' NCR scsi driver.

Linus,
 Current driver in your tree has been 'fixed' by someone without
understanding just how broken it was. Numerous fixes were done in 2.4
after the 2.5 split by Alan.

This patch reverts the damage the driver does in your tree, and brings
Alan's 2.4 bits over instead. Downside: It doesn't compile.
Upside: It doesn't pretend to work and corrupt data, and at least
is the right base for people to start fixing.
parent 0170bcbb
...@@ -83,8 +83,6 @@ ...@@ -83,8 +83,6 @@
* basically, transfer size needs to be reduced by one * basically, transfer size needs to be reduced by one
* and the last byte read as is done with PSEUDO_DMA. * and the last byte read as is done with PSEUDO_DMA.
* *
* 3. Test USLEEP code
*
* 4. Test SCSI-II tagged queueing (I have no devices which support * 4. Test SCSI-II tagged queueing (I have no devices which support
* tagged queueing) * tagged queueing)
* *
...@@ -110,6 +108,12 @@ ...@@ -110,6 +108,12 @@
#define READ_OVERRUNS #define READ_OVERRUNS
#endif #endif
#ifdef BOARD_REQUIRES_NO_DELAY
#define io_recovery_delay(x)
#else
#define io_recovery_delay(x) udelay(x)
#endif
/* /*
* Design * Design
* Issues : * Issues :
...@@ -192,9 +196,8 @@ ...@@ -192,9 +196,8 @@
* phase goes through the various phases as instructed by the target. * phase goes through the various phases as instructed by the target.
* if the target goes into MSG IN and sends a DISCONNECT message, * if the target goes into MSG IN and sends a DISCONNECT message,
* the command structure is placed into the per instance disconnected * the command structure is placed into the per instance disconnected
* queue, and NCR5380_main tries to find more work. If USLEEP * queue, and NCR5380_main tries to find more work. If the target is
* was defined, and the target is idle for too long, the system * idle for too long, the system will try to sleep.
* will try to sleep.
* *
* If a command has disconnected, eventually an interrupt will trigger, * If a command has disconnected, eventually an interrupt will trigger,
* calling NCR5380_intr() which will in turn call NCR5380_reselect * calling NCR5380_intr() which will in turn call NCR5380_reselect
...@@ -244,21 +247,14 @@ ...@@ -244,21 +247,14 @@
* rely on phase mismatch and EOP interrupts to determine end * rely on phase mismatch and EOP interrupts to determine end
* of phase. * of phase.
* *
* SCSI2 - if defined, SCSI-2 tagged queuing is used where possible
*
* UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You
* only really want to use this if you're having a problem with * only really want to use this if you're having a problem with
* dropped characters during high speed communications, and even * dropped characters during high speed communications, and even
* then, you're going to be better off twiddling with transfersize * then, you're going to be better off twiddling with transfersize
* in the high level code. * in the high level code.
* *
* USLEEP - if defined, on devices that aren't disconnecting from the * Defaults for these will be provided although the user may want to adjust
* bus, we will go to sleep so that the CPU can get real work done * these to allocate CPU resources to the SCSI driver or "real" code.
* when we run a command that won't complete immediately.
*
* Defaults for these will be provided if USLEEP is defined, although
* the user may want to adjust these to allocate CPU resources to
* the SCSI driver or "real" code.
* *
* USLEEP_SLEEP - amount of time, in jiffies, to sleep * USLEEP_SLEEP - amount of time, in jiffies, to sleep
* *
...@@ -322,18 +318,13 @@ static int do_abort(struct Scsi_Host *host); ...@@ -322,18 +318,13 @@ static int do_abort(struct Scsi_Host *host);
static void do_reset(struct Scsi_Host *host); static void do_reset(struct Scsi_Host *host);
static struct Scsi_Host *first_instance = NULL; static struct Scsi_Host *first_instance = NULL;
static Scsi_Host_Template *the_template = NULL; static Scsi_Host_Template *the_template = NULL;
static struct timer_list usleep_timer;
#ifdef USLEEP
struct timer_list usleep_timer;
#endif
/* /*
* Function : void initialize_SCp(Scsi_Cmnd *cmd) * initialize_SCp - init the scsi pointer field
* * @cmd: command block to set up
* Purpose : initialize the saved data pointers for cmd to point to the
* start of the buffer.
* *
* Inputs : cmd - Scsi_Cmnd structure to have pointers reset. * Set up the internal fields in the SCSI command.
*/ */
static __inline__ void initialize_SCp(Scsi_Cmnd * cmd) static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
...@@ -362,88 +353,49 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd) ...@@ -362,88 +353,49 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
static struct { static struct {
unsigned char mask; unsigned char mask;
const char *name; const char *name;
} signals[] = { { } signals[] = {
{SR_DBP, "PARITY"},
SR_DBP, "PARITY" {SR_RST, "RST"},
}, { {SR_BSY, "BSY"},
SR_RST, "RST" {SR_REQ, "REQ"},
}, { {SR_MSG, "MSG"},
SR_BSY, "BSY" {SR_CD, "CD"},
{SR_IO, "IO"},
{SR_SEL, "SEL"},
{0, NULL}
}, },
{ basrs[] = {
SR_REQ, "REQ" {BASR_ATN, "ATN"},
}, { {BASR_ACK, "ACK"},
SR_MSG, "MSG" {0, NULL}
}, {
SR_CD, "CD"
}, {
SR_IO, "IO"
},
{
SR_SEL, "SEL"
}, {
0, NULL
}
}, },
icrs[] = {
basrs[] = { { {ICR_ASSERT_RST, "ASSERT RST"},
BASR_ATN, "ATN" {ICR_ASSERT_ACK, "ASSERT ACK"},
}, { {ICR_ASSERT_BSY, "ASSERT BSY"},
BASR_ACK, "ACK" {ICR_ASSERT_SEL, "ASSERT SEL"},
}, { {ICR_ASSERT_ATN, "ASSERT ATN"},
0, NULL {ICR_ASSERT_DATA, "ASSERT DATA"},
} {0, NULL}
},
icrs[] = { {
ICR_ASSERT_RST, "ASSERT RST"
}, {
ICR_ASSERT_ACK, "ASSERT ACK"
},
{
ICR_ASSERT_BSY, "ASSERT BSY"
}, {
ICR_ASSERT_SEL, "ASSERT SEL"
},
{
ICR_ASSERT_ATN, "ASSERT ATN"
}, {
ICR_ASSERT_DATA, "ASSERT DATA"
},
{
0, NULL
}
},
mrs[] = { {
MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"
}, {
MR_TARGET, "MODE TARGET"
}, },
{ mrs[] = {
MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK" {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"},
}, { {MR_TARGET, "MODE TARGET"},
MR_ENABLE_PAR_INTR, {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"},
"MODE PARITY INTR" {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"},
}, { {MR_MONITOR_BSY, "MODE MONITOR BSY"},
MR_MONITOR_BSY, "MODE MONITOR BSY" {MR_DMA_MODE, "MODE DMA"},
}, {MR_ARBITRATE, "MODE ARBITRATION"},
{ {0, NULL}
MR_DMA_MODE, "MODE DMA"
}, {
MR_ARBITRATE, "MODE ARBITRATION"
},
{
0, NULL
}
}; };
/* /**
* Function : void NCR5380_print(struct Scsi_Host *instance) * NCR5380_print - print scsi bus signals
* @instance: adapter state to dump
* *
* Purpose : print the SCSI bus signals for debugging purposes * Print the SCSI bus signals for debugging purposes
* *
* Input : instance - which NCR5380 * Locks: none
*/ */
static void NCR5380_print(struct Scsi_Host *instance) static void NCR5380_print(struct Scsi_Host *instance)
...@@ -452,6 +404,7 @@ static void NCR5380_print(struct Scsi_Host *instance) ...@@ -452,6 +404,7 @@ static void NCR5380_print(struct Scsi_Host *instance)
unsigned long flags; unsigned long flags;
unsigned char status, data, basr, mr, icr, i; unsigned char status, data, basr, mr, icr, i;
NCR5380_setup(instance); NCR5380_setup(instance);
/* FIXME - this needs proper locking */
save_flags(flags); save_flags(flags);
cli(); cli();
data = NCR5380_read(CURRENT_SCSI_DATA_REG); data = NCR5380_read(CURRENT_SCSI_DATA_REG);
...@@ -483,32 +436,22 @@ static struct { ...@@ -483,32 +436,22 @@ static struct {
unsigned char value; unsigned char value;
const char *name; const char *name;
} phases[] = { } phases[] = {
{PHASE_DATAOUT, "DATAOUT"},
{ {PHASE_DATAIN, "DATAIN"},
PHASE_DATAOUT, "DATAOUT" {PHASE_CMDOUT, "CMDOUT"},
}, { {PHASE_STATIN, "STATIN"},
PHASE_DATAIN, "DATAIN" {PHASE_MSGOUT, "MSGOUT"},
}, { {PHASE_MSGIN, "MSGIN"},
PHASE_CMDOUT, "CMDOUT" {PHASE_UNKNOWN, "UNKNOWN"}
},
{
PHASE_STATIN, "STATIN"
}, {
PHASE_MSGOUT, "MSGOUT"
}, {
PHASE_MSGIN, "MSGIN"
},
{
PHASE_UNKNOWN, "UNKNOWN"
}
}; };
/* /*
* Function : void NCR5380_print_phase(struct Scsi_Host *instance) * NCR5380_print_phase - show SCSI phase
* @instance: adapter to dump
* *
* Purpose : print the current SCSI phase for debugging purposes * Print the current SCSI phase for debugging purposes
* *
* Input : instance - which NCR5380 * Locks: none
*/ */
static void NCR5380_print_phase(struct Scsi_Host *instance) static void NCR5380_print_phase(struct Scsi_Host *instance)
...@@ -520,11 +463,9 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) ...@@ -520,11 +463,9 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
status = NCR5380_read(STATUS_REG); status = NCR5380_read(STATUS_REG);
if (!(status & SR_REQ)) if (!(status & SR_REQ))
printk("scsi%d : REQ not asserted, phase unknown.\n", printk("scsi%d : REQ not asserted, phase unknown.\n", instance->host_no);
instance->host_no);
else { else {
for (i = 0; (phases[i].value != PHASE_UNKNOWN) && for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
(phases[i].value != (status & PHASE_MASK)); ++i);
printk("scsi%d : phase %s\n", instance->host_no, phases[i].name); printk("scsi%d : phase %s\n", instance->host_no, phases[i].name);
} }
} }
...@@ -549,7 +490,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) ...@@ -549,7 +490,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
* conditions are possible. * conditions are possible.
*/ */
static volatile int main_running = 0; static unsigned long main_running = 0;
/* /*
* Function : run_main(void) * Function : run_main(void)
...@@ -563,14 +504,10 @@ static volatile int main_running = 0; ...@@ -563,14 +504,10 @@ static volatile int main_running = 0;
static __inline__ void run_main(void) static __inline__ void run_main(void)
{ {
if (!main_running) { if (!test_and_set_bit(0, &main_running))
main_running = 1;
NCR5380_main(); NCR5380_main();
}
} }
#ifdef USLEEP
/* /*
* These need tweaking, and would probably work best as per-device * These need tweaking, and would probably work best as per-device
* flags initialized differently for disk, tape, cd, etc devices. * flags initialized differently for disk, tape, cd, etc devices.
...@@ -640,44 +577,48 @@ static int should_disconnect(unsigned char cmd) ...@@ -640,44 +577,48 @@ static int should_disconnect(unsigned char cmd)
/* /*
* Assumes instance->time_expires has been set in higher level code. * Assumes instance->time_expires has been set in higher level code.
*
* Locks: Caller must hold io_request_lock
*/ */
static int NCR5380_set_timer(struct Scsi_Host *instance) static int NCR5380_set_timer(struct Scsi_Host *instance)
{ {
unsigned long flags;
struct Scsi_Host *tmp, **prev; struct Scsi_Host *tmp, **prev;
save_flags(flags);
cli();
if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) { if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
restore_flags(flags);
return -1; return -1;
} }
for (prev = &expires_first, tmp = expires_first; tmp; for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
if (((struct NCR5380_hostdata *)instance->hostdata)->time_expires <
((struct NCR5380_hostdata *)tmp->hostdata)->time_expires)
break; break;
((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp; ((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp;
*prev = instance; *prev = instance;
mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires); mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
restore_flags(flags);
return 0; return 0;
} }
/* Doing something about unwanted reentrancy here might be useful */ /**
void NCR5380_timer_fn(unsigned long surplus_to_requirements) * NCR5380_timer_fn - handle polled timeouts
* @unused: unused
*
* Walk the list of controllers, find which controllers have exceeded
* their expiry timeout and then schedule the processing co-routine to
* do the real work.
*
* Doing something about unwanted reentrancy here might be useful
*
* Locks: disables irqs, takes and frees io_request_lock
*/
static void NCR5380_timer_fn(unsigned long unused)
{ {
unsigned long flags;
struct Scsi_Host *instance; struct Scsi_Host *instance;
save_flags(flags);
cli(); spin_lock_irq(&io_request_lock);
for (; expires_first &&
time_before_eq(((struct NCR5380_hostdata *)expires_first->hostdata)->time_expires, jiffies); ) for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) {
{
instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer; instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer;
((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL; ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL;
((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires = 0; ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires = 0;
...@@ -685,74 +626,76 @@ void NCR5380_timer_fn(unsigned long surplus_to_requirements) ...@@ -685,74 +626,76 @@ void NCR5380_timer_fn(unsigned long surplus_to_requirements)
} }
del_timer(&usleep_timer); del_timer(&usleep_timer);
if (expires_first) if (expires_first) {
{ usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
usleep_timer.expires = ((struct NCR5380_hostdata *)expires_first->hostdata)->time_expires;
add_timer(&usleep_timer); add_timer(&usleep_timer);
} }
restore_flags(flags);
spin_lock_irqsave(instance->host_lock, flags);
run_main(); run_main();
spin_unlock_irqrestore(instance->host_lock, flags); spin_unlock_irq(&io_request_lock);
} }
#endif /* def USLEEP */
/**
* NCR5380_all_init - global setup
*
* Set up the global values and timers needed by the NCR5380 driver
*/
static inline void NCR5380_all_init(void) static inline void NCR5380_all_init(void)
{ {
static int done = 0; static int done = 0;
if (!done) { if (!done) {
#if (NDEBUG & NDEBUG_INIT) dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
printk("scsi : NCR5380_all_init()\n");
#endif
done = 1; done = 1;
#ifdef USLEEP
init_timer(&usleep_timer); init_timer(&usleep_timer);
usleep_timer.function = NCR5380_timer_fn; usleep_timer.function = NCR5380_timer_fn;
#endif
} }
} }
#ifdef AUTOPROBE_IRQ
/*
* Function : int NCR5380_probe_irq (struct Scsi_Host *instance, int possible)
*
* Purpose : autoprobe for the IRQ line used by the NCR5380.
*
* Inputs : instance - pointer to this instance of the NCR5380 driver,
* possible - bitmask of permissible interrupts.
*
* Returns : number of the IRQ selected, IRQ_NONE if no interrupt fired.
*
* XXX no effort is made to deal with spurious interrupts.
*/
static int probe_irq __initdata = 0; static int probe_irq __initdata = 0;
/**
* probe_intr - helper for IRQ autoprobe
* @irq: interrupt number
* @dev_id: unused
* @regs: unused
*
* Set a flag to indicate the IRQ in question was received. This is
* used by the IRQ probe code.
*/
static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs) static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
probe_irq = irq; probe_irq = irq;
} }
/**
* NCR5380_probe_irq - find the IRQ of an NCR5380
* @instance: NCR5380 controller
* @possible: bitmask of ISA IRQ lines
*
* Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
* and then looking to see what interrupt actually turned up.
*
* Locks: none, irqs must be enabled on entry
*/
static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
{ {
NCR5380_local_declare(); NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
instance->hostdata;
unsigned long timeout; unsigned long timeout;
int trying_irqs, i, mask; int trying_irqs, i, mask;
NCR5380_setup(instance); NCR5380_setup(instance);
for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1) for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", instance) if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL) == 0))
== 0))
trying_irqs |= mask; trying_irqs |= mask;
timeout = jiffies + (250 * HZ / 1000); timeout = jiffies + (250 * HZ / 1000);
probe_irq = IRQ_NONE; probe_irq = IRQ_NONE;
/* /*
* A interrupt is triggered whenever BSY = false, SEL = true * A interrupt is triggered whenever BSY = false, SEL = true
* and a bit set in the SELECT_ENABLE_REG is asserted on the * and a bit set in the SELECT_ENABLE_REG is asserted on the
* SCSI bus. * SCSI bus.
...@@ -765,10 +708,9 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) ...@@ -765,10 +708,9 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(TARGET_COMMAND_REG, 0);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
ICR_ASSERT_SEL);
while (probe_irq == IRQ_NONE && time_before(jiffies,timeout)) while (probe_irq == IRQ_NONE && time_before(jiffies, timeout))
barrier(); barrier();
NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0);
...@@ -780,15 +722,16 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) ...@@ -780,15 +722,16 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
return probe_irq; return probe_irq;
} }
#endif /* AUTOPROBE_IRQ */
/* /**
* Function : void NCR58380_print_options (struct Scsi_Host *instance) * NCR58380_print_options - show options
* @instance: unused for now
* *
* Purpose : called by probe code indicating the NCR5380 driver * Called by probe code indicating the NCR5380 driver options that
* options that were selected. * were selected. At some point this will switch to runtime options
* read from the adapter in question
* *
* Inputs : instance, pointer to this instance. Unused. * Locks: none
*/ */
static void __init NCR5380_print_options(struct Scsi_Host *instance) static void __init NCR5380_print_options(struct Scsi_Host *instance)
...@@ -815,29 +758,25 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance) ...@@ -815,29 +758,25 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
#ifdef PSEUDO_DMA #ifdef PSEUDO_DMA
" PSEUDO DMA" " PSEUDO DMA"
#endif #endif
#ifdef SCSI2
" SCSI-2"
#endif
#ifdef UNSAFE #ifdef UNSAFE
" UNSAFE " " UNSAFE "
#endif #endif
); );
#ifdef USLEEP
printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP); printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
#endif
printk(" generic release=%d", NCR5380_PUBLIC_RELEASE); printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) { if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE); printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
} }
} }
/* /**
* Function : void NCR5380_print_status (struct Scsi_Host *instance) * NCR5380_print_status - dump controller info
* @instance: controller to dump
* *
* Purpose : print commands in the various queues, called from * Print commands in the various queues, called from NCR5380_abort
* NCR5380_abort and NCR5380_debug to aid debugging. * and NCR5380_debug to aid debugging.
* *
* Inputs : instance, pointer to this instance. * Locks: called functions disable irqs, missing queue lock in proc call
*/ */
static void NCR5380_print_status(struct Scsi_Host *instance) static void NCR5380_print_status(struct Scsi_Host *instance)
...@@ -846,16 +785,12 @@ static void NCR5380_print_status(struct Scsi_Host *instance) ...@@ -846,16 +785,12 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
char *start; char *start;
int len; int len;
printk("NCR5380 : coroutine is%s running.\n", printk("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
main_running ? "" : "n't");
#ifdef NDEBUG NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_print(instance); NCR5380_dprint_phase(NDEBUG_ANY, instance);
NCR5380_print_phase(instance);
#endif
len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr), len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr), instance->host_no, 0);
instance->host_no, 0);
pr_bfr[len] = 0; pr_bfr[len] = 0;
printk("\n%s\n", pr_bfr); printk("\n%s\n", pr_bfr);
} }
...@@ -886,18 +821,14 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length); ...@@ -886,18 +821,14 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
#ifndef NCR5380_proc_info #ifndef NCR5380_proc_info
static static
#endif #endif
int NCR5380_proc_info( int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
char *buffer, char **start, off_t offset,
int length, int hostno, int inout)
{ {
unsigned long flags;
char *pos = buffer; char *pos = buffer;
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata; struct NCR5380_hostdata *hostdata;
Scsi_Cmnd *ptr; Scsi_Cmnd *ptr;
for (instance = first_instance; instance && for (instance = first_instance; instance && instance->host_no != hostno; instance = instance->next);
instance->host_no != hostno; instance = instance->next);
if (!instance) if (!instance)
return (-ESRCH); return (-ESRCH);
hostdata = (struct NCR5380_hostdata *) instance->hostdata; hostdata = (struct NCR5380_hostdata *) instance->hostdata;
...@@ -935,32 +866,27 @@ int NCR5380_proc_info( ...@@ -935,32 +866,27 @@ int NCR5380_proc_info(
SPRINTF("IRQ: %d.\n", instance->irq); SPRINTF("IRQ: %d.\n", instance->irq);
#ifdef DTC_PUBLIC_RELEASE #ifdef DTC_PUBLIC_RELEASE
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", dtc_wmaxi, dtc_maxi);
dtc_wmaxi, dtc_maxi);
#endif #endif
#ifdef PAS16_PUBLIC_RELEASE #ifdef PAS16_PUBLIC_RELEASE
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
pas_wmaxi, pas_maxi);
#endif #endif
save_flags(flags); spin_lock_irq(&io_request_lock);
cli();
SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't"); SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
if (!hostdata->connected) if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no); SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
else else
pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, pos, buffer, length);
pos, buffer, length);
SPRINTF("scsi%d: issue_queue\n", instance->host_no); SPRINTF("scsi%d: issue_queue\n", instance->host_no);
for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
ptr = (Scsi_Cmnd *) ptr->host_scribble)
pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
SPRINTF("scsi%d: disconnected_queue\n", instance->host_no); SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
ptr = (Scsi_Cmnd *) ptr->host_scribble)
pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
restore_flags(flags); spin_unlock_irq(&io_request_lock);
*start = buffer; *start = buffer;
if (pos - buffer < offset) if (pos - buffer < offset)
return 0; return 0;
...@@ -972,16 +898,14 @@ int NCR5380_proc_info( ...@@ -972,16 +898,14 @@ int NCR5380_proc_info(
static static
char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length) char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
{ {
SPRINTF("scsi%d : destination target %d, lun %d\n", SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->host->host_no, cmd->target, cmd->lun);
cmd->host->host_no, cmd->target, cmd->lun);
SPRINTF(" command = "); SPRINTF(" command = ");
pos = lprint_command(cmd->cmnd, pos, buffer, length); pos = lprint_command(cmd->cmnd, pos, buffer, length);
return (pos); return (pos);
} }
static static
char *lprint_command(unsigned char *command, char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
char *pos, char *buffer, int length)
{ {
int i, s; int i, s;
pos = lprint_opcode(command[0], pos, buffer, length); pos = lprint_opcode(command[0], pos, buffer, length);
...@@ -999,17 +923,18 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length) ...@@ -999,17 +923,18 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
} }
/* /**
* Function : void NCR5380_init (struct Scsi_Host *instance, flags) * NCR5380_init - initialise an NCR5380
* @instance: adapter to configure
* @flags: control flags
* *
* Purpose : initializes *instance and corresponding 5380 chip, * Initializes *instance and corresponding 5380 chip,
* with flags OR'd into the initial flags value. * with flags OR'd into the initial flags value.
* *
* Inputs : instance - instantiation of the 5380 driver.
*
* Notes : I assume that the host, hostno, and id bits have been * Notes : I assume that the host, hostno, and id bits have been
* set correctly. I don't care about the irq and other fields. * set correctly. I don't care about the irq and other fields.
* *
* Locks: interrupts must be enabled when we are called
*/ */
static void __init NCR5380_init(struct Scsi_Host *instance, int flags) static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
...@@ -1017,9 +942,10 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1017,9 +942,10 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
NCR5380_local_declare(); NCR5380_local_declare();
int i, pass; int i, pass;
unsigned long timeout; unsigned long timeout;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
instance->hostdata;
if(in_interrupt())
printk(KERN_ERR "NCR5380_init called with interrupts off!\n");
/* /*
* On NCR53C400 boards, NCR5380 registers are mapped 8 past * On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address. * the base address.
...@@ -1031,7 +957,6 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1031,7 +957,6 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
#endif #endif
NCR5380_setup(instance); NCR5380_setup(instance);
NCR5380_all_init(); NCR5380_all_init();
hostdata->aborted = 0; hostdata->aborted = 0;
...@@ -1070,16 +995,12 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1070,16 +995,12 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
the_template = instance->hostt; the_template = instance->hostt;
first_instance = instance; first_instance = instance;
} }
#ifdef USLEEP
hostdata->time_expires = 0; hostdata->time_expires = 0;
hostdata->next_timer = NULL; hostdata->next_timer = NULL;
#endif
#ifndef AUTOSENSE #ifndef AUTOSENSE
if ((instance->cmd_per_lun > 1) || instance->can_queue > 1) if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
) printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" " without AUTOSENSE option, contingent allegiance conditions may\n"
printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n"
" without AUTOSENSE option, contingent allegiance conditions may\n"
" be incorrectly cleared.\n", instance->host_no); " be incorrectly cleared.\n", instance->host_no);
#endif /* def AUTOSENSE */ #endif /* def AUTOSENSE */
...@@ -1106,50 +1027,40 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1106,50 +1027,40 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
* failing, do a hard reset of the SCSI bus * failing, do a hard reset of the SCSI bus
*/ */
for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
pass <= 6; ++pass) {
switch (pass) { switch (pass) {
case 1: case 1:
case 3: case 3:
case 5: case 5:
printk("scsi%d: SCSI bus busy, waiting up to five seconds\n", printk("scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no);
instance->host_no);
timeout = jiffies + 5 * HZ; timeout = jiffies + 5 * HZ;
while (time_before(jiffies,timeout) && (NCR5380_read(STATUS_REG) & SR_BSY)); while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY));
break; break;
case 2: case 2:
printk("scsi%d: bus busy, attempting abort\n", printk("scsi%d: bus busy, attempting abort\n", instance->host_no);
instance->host_no);
do_abort(instance); do_abort(instance);
break; break;
case 4: case 4:
printk("scsi%d: bus busy, attempting reset\n", printk("scsi%d: bus busy, attempting reset\n", instance->host_no);
instance->host_no);
do_reset(instance); do_reset(instance);
break; break;
case 6: case 6:
printk("scsi%d: bus locked solid or invalid override\n", printk("scsi%d: bus locked solid or invalid override\n", instance->host_no);
instance->host_no);
} }
} }
} }
/* /**
* Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, * NCR5380_queue_command - queue a command
* void (*done)(Scsi_Cmnd *)) * @cmd: SCSI command
* @done: completion handler
* *
* Purpose : enqueues a SCSI command
*
* Inputs : cmd - SCSI command, done - function called on completion, with
* a pointer to the command descriptor.
*
* Returns : 0
*
* Side effects :
* cmd is added to the per instance issue_queue, with minor * cmd is added to the per instance issue_queue, with minor
* twiddling done to the host specific fields of cmd. If the * twiddling done to the host specific fields of cmd. If the
* main coroutine is not running, it is restarted. * main coroutine is not running, it is restarted.
* *
* Locks: io_request lock held by caller. Called functions drop and
* retake this lock. Called functions take dma lock.
*/ */
/* Only make static if a wrapper function is used */ /* Only make static if a wrapper function is used */
...@@ -1158,16 +1069,14 @@ static ...@@ -1158,16 +1069,14 @@ static
#endif #endif
int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
struct Scsi_Host *instance = cmd->host; struct Scsi_Host *instance = cmd->host;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
instance->hostdata;
Scsi_Cmnd *tmp; Scsi_Cmnd *tmp;
#if (NDEBUG & NDEBUG_NO_WRITE) #if (NDEBUG & NDEBUG_NO_WRITE)
switch (cmd->cmnd[0]) { switch (cmd->cmnd[0]) {
case WRITE_6: case WRITE_6:
case WRITE_10: case WRITE_10:
printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no);
instance->host_no);
cmd->result = (DID_ERROR << 16); cmd->result = (DID_ERROR << 16);
done(cmd); done(cmd);
return 0; return 0;
...@@ -1175,15 +1084,6 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1175,15 +1084,6 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
#ifdef NCR5380_STATS #ifdef NCR5380_STATS
#if 0
if (!hostdata->connected && !hostdata->issue_queue &&
!hostdata->disconnected_queue) {
hostdata->timebase = jiffies;
}
#endif
#ifdef NCR5380_STAT_LIMIT
if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
#endif
switch (cmd->cmnd[0]) { switch (cmd->cmnd[0]) {
case WRITE: case WRITE:
case WRITE_6: case WRITE_6:
...@@ -1209,10 +1109,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1209,10 +1109,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
cmd->host_scribble = NULL; cmd->host_scribble = NULL;
cmd->scsi_done = done; cmd->scsi_done = done;
cmd->result = 0; cmd->result = 0;
/* /*
* Insert the cmd into the issue queue. Note that REQUEST SENSE * Insert the cmd into the issue queue. Note that REQUEST SENSE
* commands are added to the head of the queue since any command will * commands are added to the head of the queue since any command will
...@@ -1225,31 +1123,28 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1225,31 +1123,28 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
cmd->host_scribble = (unsigned char *) hostdata->issue_queue; cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = cmd; hostdata->issue_queue = cmd;
} else { } else {
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble);
tmp = (Scsi_Cmnd *) tmp->host_scribble);
LIST(cmd, tmp); LIST(cmd, tmp);
tmp->host_scribble = (unsigned char *) cmd; tmp->host_scribble = (unsigned char *) cmd;
} }
#if (NDEBUG & NDEBUG_QUEUES) dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
printk("scsi%d : command added to %s of queue\n", instance->host_no,
(cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
#endif
/* Run the coroutine if it isn't already running. */ /* Run the coroutine if it isn't already running. */
run_main(); run_main();
return 0; return 0;
} }
/* /**
* Function : NCR5380_main (void) * NCR5380_main - NCR state machines
* *
* Purpose : NCR5380_main is a coroutine that runs as long as more work can * NCR5380_main is a coroutine that runs as long as more work can
* be done on the NCR5380 host adapters in a system. Both * be done on the NCR5380 host adapters in a system. Both
* NCR5380_queue_command() and NCR5380_intr() will try to start it * NCR5380_queue_command() and NCR5380_intr() will try to start it
* in case it is not running. * in case it is not running.
* *
* NOTE : NCR5380_main exits with interrupts *disabled*, the caller should * Locks; The caller must hold the io_request_lock. The lock will still be
* reenable them. This prevents reentrancy and kernel stack overflow. * held on return but may be dropped while running. Called functions take
* the DMA lock.
*/ */
static void NCR5380_main(void) { static void NCR5380_main(void) {
...@@ -1257,7 +1152,6 @@ static void NCR5380_main(void) { ...@@ -1257,7 +1152,6 @@ static void NCR5380_main(void) {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata; struct NCR5380_hostdata *hostdata;
int done; int done;
unsigned long flags;
/* /*
* We run (with interrupts disabled) until we're sure that none of * We run (with interrupts disabled) until we're sure that none of
...@@ -1271,43 +1165,22 @@ static void NCR5380_main(void) { ...@@ -1271,43 +1165,22 @@ static void NCR5380_main(void) {
* this should prevent any race conditions. * this should prevent any race conditions.
*/ */
spin_unlock_irq(instance->host_lock);
save_flags(flags);
do { do {
cli(); /* Freeze request queues */ /* Lock held here */
done = 1; done = 1;
for (instance = first_instance; instance && for (instance = first_instance; instance && instance->hostt == the_template; instance = instance->next) {
instance->hostt == the_template; instance = instance->next) {
hostdata = (struct NCR5380_hostdata *) instance->hostdata; hostdata = (struct NCR5380_hostdata *) instance->hostdata;
cli(); /* Lock held here */
#ifdef USLEEP
if (!hostdata->connected && !hostdata->selecting) { if (!hostdata->connected && !hostdata->selecting) {
#else dprintk(NDEBUG_MAIN, ("scsi%d : not connected\n", instance->host_no));
if (!hostdata->connected) {
#endif
#if (NDEBUG & NDEBUG_MAIN)
printk("scsi%d : not connected\n", instance->host_no);
#endif
/* /*
* Search through the issue_queue for a command destined * Search through the issue_queue for a command destined
* for a target that's not busy. * for a target that's not busy.
*/ */
#if (NDEBUG & NDEBUG_LISTS) for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp && (tmp != prev); prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble); {
/*printk("%p ", tmp); */
if ((tmp == prev) && tmp)
printk(" LOOP\n"); /* else printk("\n"); */
#endif
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *)
tmp->host_scribble) {
#if (NDEBUG & NDEBUG_LISTS)
if (prev != tmp) if (prev != tmp)
printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun); dprintk(NDEBUG_LISTS, ("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun));
#endif
/* When we find one, remove it from the issue queue. */ /* When we find one, remove it from the issue queue. */
if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) { if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {
if (prev) { if (prev) {
...@@ -1319,8 +1192,6 @@ static void NCR5380_main(void) { ...@@ -1319,8 +1192,6 @@ static void NCR5380_main(void) {
} }
tmp->host_scribble = NULL; tmp->host_scribble = NULL;
/* reenable interrupts after finding one */
restore_flags(flags);
/* /*
* Attempt to establish an I_T_L nexus here. * Attempt to establish an I_T_L nexus here.
...@@ -1328,10 +1199,7 @@ static void NCR5380_main(void) { ...@@ -1328,10 +1199,7 @@ static void NCR5380_main(void) {
* On failure, we must add the command back to the * On failure, we must add the command back to the
* issue queue so we can keep trying. * issue queue so we can keep trying.
*/ */
#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES)) dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun));
printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n",
instance->host_no, tmp->target, tmp->lun);
#endif
/* /*
* A successful selection is defined as one that * A successful selection is defined as one that
...@@ -1343,10 +1211,8 @@ static void NCR5380_main(void) { ...@@ -1343,10 +1211,8 @@ static void NCR5380_main(void) {
* and see if we can do an information transfer, * and see if we can do an information transfer,
* with failures we will restart. * with failures we will restart.
*/ */
#ifdef USLEEP hostdata->selecting = 0;
hostdata->selecting = 0; /* RvC: have to preset this /* RvC: have to preset this to indicate a new command is being performed */
to indicate a new command is being performed */
#endif
if (!NCR5380_select(instance, tmp, if (!NCR5380_select(instance, tmp,
/* /*
...@@ -1355,93 +1221,71 @@ static void NCR5380_main(void) { ...@@ -1355,93 +1221,71 @@ static void NCR5380_main(void) {
* contingent allegiance condition exists for the * contingent allegiance condition exists for the
* entire unit. * entire unit.
*/ */
(tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
TAG_NEXT)) {
break; break;
} else { } else {
cli();
LIST(tmp, hostdata->issue_queue); LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *) tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue;
hostdata->issue_queue = tmp; hostdata->issue_queue = tmp;
done = 0; done = 0;
restore_flags(flags); dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no));
#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
printk("scsi%d : main(): select() failed, returned to issue_queue\n",
instance->host_no);
#endif
} }
/* lock held here still */
} /* if target/lun is not busy */ } /* if target/lun is not busy */
} /* for */ } /* for */
/* exited locked */
} /* if (!hostdata->connected) */ } /* if (!hostdata->connected) */
#ifdef USLEEP if (hostdata->selecting) {
if (hostdata->selecting) tmp = (Scsi_Cmnd *) hostdata->selecting;
{ /* Selection will drop and retake the lock */
tmp = (Scsi_Cmnd *)hostdata->selecting; if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
if (!NCR5380_select(instance, tmp,
(tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT))
{
/* Ok ?? */ /* Ok ?? */
} } else {
else
{
/* RvC: device failed, so we wait a long time /* RvC: device failed, so we wait a long time
this is needed for Mustek scanners, that this is needed for Mustek scanners, that
do not respond to commands immediately do not respond to commands immediately
after a scan */ after a scan */
printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);
instance->host_no, tmp->target); //spin_lock_irq(&io_request_lock);
cli();
LIST(tmp, hostdata->issue_queue); LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *) hostdata->issue_queue; tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp; hostdata->issue_queue = tmp;
restore_flags(flags); //spin_unlock_irq(&io_request_lock);
hostdata->time_expires = jiffies + USLEEP_WAITLONG; hostdata->time_expires = jiffies + USLEEP_WAITLONG;
NCR5380_set_timer (instance); NCR5380_set_timer(instance);
} }
} /* if hostdata->selecting */ } /* if hostdata->selecting */
#endif
if (hostdata->connected if (hostdata->connected
#ifdef REAL_DMA #ifdef REAL_DMA
&& !hostdata->dmalen && !hostdata->dmalen
#endif #endif
#ifdef USLEEP
&& (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies)) && (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies))
#endif
) { ) {
restore_flags(flags); dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no));
#if (NDEBUG & NDEBUG_MAIN)
printk("scsi%d : main() : performing information transfer\n",
instance->host_no);
#endif
NCR5380_information_transfer(instance); NCR5380_information_transfer(instance);
#if (NDEBUG & NDEBUG_MAIN) dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no));
printk("scsi%d : main() : done set false\n", instance->host_no);
#endif
done = 0; done = 0;
} else } else
break; break;
} /* for instance */ } /* for instance */
} while (!done); } while (!done);
spin_lock_irq(instance->host_lock); /* Exit lock held */
/* cli();*/ clear_bit(0, &main_running);
main_running = 0;
} }
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
/* /**
* Function : void NCR5380_intr (int irq) * NCR5380_intr - generic NCR5380 irq handler
* *
* Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
* from the disconnected queue, and restarting NCR5380_main() * from the disconnected queue, and restarting NCR5380_main()
* as required. * as required.
* *
* Inputs : int irq, irq that caused this interrupt. * Locks: caller must hold the io_request lock.
*
*/ */
static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
...@@ -1449,17 +1293,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1449,17 +1293,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
struct Scsi_Host *instance; struct Scsi_Host *instance;
int done; int done;
unsigned char basr; unsigned char basr;
unsigned long flags;
save_flags(flags); dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
cli();
#if (NDEBUG & NDEBUG_INTR)
printk("scsi : NCR5380 irq %d triggered\n", irq);
#endif
do { do {
done = 1; done = 1;
for (instance = first_instance; instance && (instance->hostt == for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)
the_template); instance = instance->next)
if (instance->irq == irq) { if (instance->irq == irq) {
/* Look for pending interrupts */ /* Look for pending interrupts */
...@@ -1467,34 +1306,19 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1467,34 +1306,19 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
basr = NCR5380_read(BUS_AND_STATUS_REG); basr = NCR5380_read(BUS_AND_STATUS_REG);
/* XXX dispatch to appropriate routine if found and done=0 */ /* XXX dispatch to appropriate routine if found and done=0 */
if (basr & BASR_IRQ) { if (basr & BASR_IRQ) {
#if (NDEBUG & NDEBUG_INTR) NCR5380_dprint(NDEBUG_INTR, instance);
NCR5380_print(instance); if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
#endif
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
(SR_SEL | SR_IO)) {
done = 0; done = 0;
restore_flags(flags); dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));
#if (NDEBUG & NDEBUG_INTR)
printk("scsi%d : SEL interrupt\n", instance->host_no);
#endif
NCR5380_reselect(instance); NCR5380_reselect(instance);
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else if (basr & BASR_PARITY_ERROR) { } else if (basr & BASR_PARITY_ERROR) {
#if (NDEBUG & NDEBUG_INTR) dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));
printk("scsi%d : PARITY interrupt\n", instance->host_no);
#endif
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
#if (NDEBUG & NDEBUG_INTR) dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));
printk("scsi%d : RESET interrupt\n", instance->host_no);
#endif
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else { } else {
/*
* XXX the rest of the interrupt conditions should *only* occur during a
* DMA transfer, which I haven't gotten around to fixing yet.
*/
#if defined(REAL_DMA) #if defined(REAL_DMA)
/* /*
* We should only get PHASE MISMATCH and EOP interrupts * We should only get PHASE MISMATCH and EOP interrupts
...@@ -1502,14 +1326,11 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1502,14 +1326,11 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
* the current setting of the MODE register. * the current setting of the MODE register.
*/ */
if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) {
BASR_END_DMA_TRANSFER) ||
!(basr & BASR_PHASE_MATCH))) {
int transfered; int transfered;
if (!hostdata->connected) if (!hostdata->connected)
panic("scsi%d : received end of DMA interrupt with no connected cmd\n", panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno);
instance->hostno);
transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); transfered = (hostdata->dmalen - NCR5380_dma_residual(instance));
hostdata->connected->SCp.this_residual -= transferred; hostdata->connected->SCp.this_residual -= transferred;
...@@ -1521,14 +1342,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1521,14 +1342,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
{ {
unsigned long timeout = jiffies + NCR_TIMEOUT; unsigned long timeout = jiffies + NCR_TIMEOUT;
spin_unlock_irq(instance->host_lock); spin_unlock_irq(&io_request_lock);
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout));
&& time_before(jiffies, timeout)); spin_lock_irq(&io_request_lock);
spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout) ) if (time_after_eq(jiffies, timeout))
printk("scsi%d: timeout at NCR5380.c:%d\n", printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__);
host->host_no, __LINE__);
} }
#else /* NCR_TIMEOUT */ #else /* NCR_TIMEOUT */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
...@@ -1538,9 +1357,7 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1538,9 +1357,7 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
} }
#else #else
#if (NDEBUG & NDEBUG_INTR) dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));
printk("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
#endif
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
#endif #endif
} }
...@@ -1551,42 +1368,57 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1551,42 +1368,57 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
} while (!done); } while (!done);
} }
/**
* do_NCR5380_intr
* @irq: interrupt number
* @dev_id: device info
* @regs: registers (unused)
*
* Takes the io_request_lock and invokes the generic NCR5380 interrupt
* handler code
*
* Locks: takes and releases the io_request lock
*/
static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
unsigned long flags; unsigned long flags;
struct Scsi_Host *dev = dev_id; spin_lock_irqsave(&io_request_lock, flags);
spin_lock_irqsave(dev->host_lock, flags);
NCR5380_intr(irq, dev_id, regs); NCR5380_intr(irq, dev_id, regs);
spin_unlock_irqrestore(dev->host_lock, flags); spin_unlock_irqrestore(&io_request_lock, flags);
} }
#endif #endif
/**
* collect_stats - collect stats on a scsi command
* @hostdata: adapter
* @cmd: command being issued
*
* Update the statistical data by parsing the command in question
*/
static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
{
#ifdef NCR5380_STATS #ifdef NCR5380_STATS
static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
#ifdef NCR5380_STAT_LIMIT
if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
#endif
switch (cmd->cmnd[0]) { switch (cmd->cmnd[0]) {
case WRITE: case WRITE:
case WRITE_6: case WRITE_6:
case WRITE_10: case WRITE_10:
hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase); hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
/*hostdata->bytes_write[cmd->target] += cmd->request_bufflen; */
hostdata->pendingw--; hostdata->pendingw--;
break; break;
case READ: case READ:
case READ_6: case READ_6:
case READ_10: case READ_10:
hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase); hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
/*hostdata->bytes_read[cmd->target] += cmd->request_bufflen; */
hostdata->pendingr--; hostdata->pendingr--;
break; break;
} }
}
#endif #endif
}
/* /*
* Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
* int tag); * int tag);
...@@ -1616,38 +1448,30 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) { ...@@ -1616,38 +1448,30 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
* *
* If failed (no target) : cmd->scsi_done() will be called, and the * If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET. * cmd->result host byte set to DID_BAD_TARGET.
*
* Locks: caller holds io_request_lock
*/ */
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) {
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
{
NCR5380_local_declare(); NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
unsigned char tmp[3], phase; unsigned char tmp[3], phase;
unsigned char *data; unsigned char *data;
int len; int len;
unsigned long timeout; unsigned long timeout;
unsigned long flags;
#ifdef USLEEP
unsigned char value; unsigned char value;
#endif
NCR5380_setup(instance); NCR5380_setup(instance);
#ifdef USLEEP if (hostdata->selecting) {
if (hostdata->selecting)
{
goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the
rest of the code nearly the same */ rest of the code nearly the same */
} }
#endif
hostdata->restart_select = 0; hostdata->restart_select = 0;
#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION)
NCR5380_print(instance); NCR5380_dprint(NDEBUG_ARBITRATION, instance);
printk("scsi%d : starting arbitration, id = %d\n", instance->host_no, dprintk(NDEBUG_ARBITRATION, ("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id));
instance->this_id);
#endif
save_flags(flags);
cli();
/* /*
* Set the phase bits to 0, otherwise the NCR5380 won't drive the * Set the phase bits to 0, otherwise the NCR5380 won't drive the
...@@ -1656,7 +1480,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1656,7 +1480,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(TARGET_COMMAND_REG, 0);
/* /*
* Start arbitration. * Start arbitration.
*/ */
...@@ -1664,21 +1487,19 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1664,21 +1487,19 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE); NCR5380_write(MODE_REG, MR_ARBITRATE);
restore_flags(flags);
/* Wait for arbitration logic to complete */ /* Wait for arbitration logic to complete */
#if NCR_TIMEOUT #if NCR_TIMEOUT
{ {
unsigned long timeout = jiffies + 2 * NCR_TIMEOUT; unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;
spin_unlock_irq(instance->host_lock); spin_unlock_irq(&io_request_lock);
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
&& time_before(jiffies,timeout)); && time_before(jiffies, timeout));
spin_lock_irq(instance->host_lock); spin_lock_irq(&io_request_lock);
if (time_after_eq(jiffies,timeout)) { if (time_after_eq(jiffies, timeout)) {
printk("scsi: arbitration timeout at %d\n", __LINE__); printk("scsi: arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
...@@ -1689,11 +1510,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1689,11 +1510,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)); while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS));
#endif #endif
#if (NDEBUG & NDEBUG_ARBITRATION) dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no));
printk("scsi%d : arbitration complete\n", instance->host_no);
/* Avoid GCC 2.4.5 asm needs to many reloads error */
__asm__("nop");
#endif
/* /*
* The arbitration delay is 2.2us, but this is a minimum and there is * The arbitration delay is 2.2us, but this is a minimum and there is
...@@ -1705,14 +1522,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1705,14 +1522,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
udelay(3); udelay(3);
/* Check for lost arbitration */ /* Check for lost arbitration */
if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
(NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
#if (NDEBUG & NDEBUG_ARBITRATION) dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no));
printk("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n",
instance->host_no);
#endif
return -1; return -1;
} }
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);
...@@ -1722,14 +1534,10 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1722,14 +1534,10 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
* so we simply removed it. Seems to work with * so we simply removed it. Seems to work with
* only Mustek scanner attached * only Mustek scanner attached
*/ */
(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
{
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
#if (NDEBUG & NDEBUG_ARBITRATION) dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no));
printk("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n",
instance->host_no);
#endif
return -1; return -1;
} }
/* /*
...@@ -1739,10 +1547,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1739,10 +1547,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
udelay(2); udelay(2);
#if (NDEBUG & NDEBUG_ARBITRATION) dprintk(NDEBUG_ARBITRATION, ("scsi%d : won arbitration\n", instance->host_no));
printk("scsi%d : won arbitration\n", instance->host_no);
#endif
/* /*
* Now that we have won arbitration, start Selection process, asserting * Now that we have won arbitration, start Selection process, asserting
...@@ -1757,8 +1562,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1757,8 +1562,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
* phase immediately after selection. * phase immediately after selection.
*/ */
NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
/* /*
...@@ -1774,8 +1578,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1774,8 +1578,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */
/* Reset BSY */ /* Reset BSY */
NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
ICR_ASSERT_ATN | ICR_ASSERT_SEL));
/* /*
* Something weird happens when we cease to drive BSY - looks * Something weird happens when we cease to drive BSY - looks
...@@ -1796,9 +1599,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1796,9 +1599,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
udelay(1); udelay(1);
#if (NDEBUG & NDEBUG_SELECTION) dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, cmd->target));
printk("scsi%d : selecting target %d\n", instance->host_no, cmd->target);
#endif
/* /*
* The SCSI specification calls for a 250 ms timeout for the actual * The SCSI specification calls for a 250 ms timeout for the actual
...@@ -1813,7 +1614,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1813,7 +1614,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
* and it's detecting as true. Sigh. * and it's detecting as true. Sigh.
*/ */
#ifdef USLEEP
hostdata->select_time = 0; /* we count the clock ticks at which we polled */ hostdata->select_time = 0; /* we count the clock ticks at which we polled */
hostdata->selecting = cmd; hostdata->selecting = cmd;
...@@ -1823,8 +1623,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1823,8 +1623,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
we poll only once ech clock tick */ we poll only once ech clock tick */
value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO); value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO);
if (!value && (hostdata->select_time < 25)) if (!value && (hostdata->select_time < 25)) {
{
/* RvC: we still must wait for a device response */ /* RvC: we still must wait for a device response */
hostdata->select_time++; /* after 25 ticks the device has failed */ hostdata->select_time++; /* after 25 ticks the device has failed */
hostdata->time_expires = jiffies + 1; hostdata->time_expires = jiffies + 1;
...@@ -1835,18 +1634,10 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1835,18 +1634,10 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
hostdata->selecting = 0; /* clear this pointer, because we passed the hostdata->selecting = 0; /* clear this pointer, because we passed the
waiting period */ waiting period */
#else if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
spin_unlock_irq(instance->host_lock);
while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
(SR_BSY | SR_IO)));
spin_lock_irq(instance->host_lock);
#endif
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
(SR_SEL | SR_IO)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_reselect(instance); NCR5380_reselect(instance);
printk("scsi%d : reselection after won arbitration?\n", printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
instance->host_no);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1; return -1;
} }
...@@ -1866,22 +1657,15 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1866,22 +1657,15 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
printk("scsi%d : weirdness\n", instance->host_no); printk("scsi%d : weirdness\n", instance->host_no);
if (hostdata->restart_select) if (hostdata->restart_select)
printk("\trestart select\n"); printk("\trestart select\n");
#if (NDEBUG & NDEBUG_SELECTION) NCR5380_dprint(NDEBUG_SELECTION, instance);
NCR5380_print(instance);
#endif
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1; return -1;
} }
cmd->result = DID_BAD_TARGET << 16; cmd->result = DID_BAD_TARGET << 16;
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd); collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
#if (NDEBUG & NDEBUG_SELECTION) dprintk(NDEBUG_SELECTION, ("scsi%d : target did not respond within 250ms\n", instance->host_no));
printk("scsi%d : target did not respond within 250ms\n",
instance->host_no);
#endif
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return 0; return 0;
} }
...@@ -1907,9 +1691,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1907,9 +1691,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
{ {
unsigned long timeout = jiffies + NCR_TIMEOUT; unsigned long timeout = jiffies + NCR_TIMEOUT;
spin_unlock_irq(instance->host_lock); spin_unlock_irq(&io_request_lock);
while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout)); while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout));
spin_lock_irq(instance->host_lock); spin_lock_irq(&io_request_lock);
if (time_after_eq(jiffies, timeout)) { if (time_after_eq(jiffies, timeout)) {
printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
...@@ -1921,46 +1705,19 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1921,46 +1705,19 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
while (!(NCR5380_read(STATUS_REG) & SR_REQ)); while (!(NCR5380_read(STATUS_REG) & SR_REQ));
#endif /* def NCR_TIMEOUT */ #endif /* def NCR_TIMEOUT */
#if (NDEBUG & NDEBUG_SELECTION) dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n",
instance->host_no, cmd->target);
#endif
tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun); tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
#ifdef SCSI2
if (cmd->device->tagged_queue && (tag != TAG_NONE)) {
tmp[1] = SIMPLE_QUEUE_TAG;
if (tag == TAG_NEXT) {
/* 0 is TAG_NONE, used to imply no tag for this command */
if (cmd->device->current_tag == 0)
cmd->device->current_tag = 1;
cmd->tag = cmd->device->current_tag;
cmd->device->current_tag++;
} else
cmd->tag = (unsigned char) tag;
tmp[2] = cmd->tag;
hostdata->last_message = SIMPLE_QUEUE_TAG;
len = 3;
} else
#endif /* def SCSI2 */
{
len = 1; len = 1;
cmd->tag = 0; cmd->tag = 0;
}
/* Send message(s) */ /* Send message(s) */
data = tmp; data = tmp;
phase = PHASE_MSGOUT; phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
#if (NDEBUG & NDEBUG_SELECTION) dprintk(NDEBUG_SELECTION, ("scsi%d : nexus established.\n", instance->host_no));
printk("scsi%d : nexus established.\n", instance->host_no);
#endif
/* XXX need to handle errors here */ /* XXX need to handle errors here */
hostdata->connected = cmd; hostdata->connected = cmd;
#ifdef SCSI2
if (!cmd->device->tagged_queue)
#endif
hostdata->busy[cmd->target] |= (1 << cmd->lun); hostdata->busy[cmd->target] |= (1 << cmd->lun);
initialize_SCp(cmd); initialize_SCp(cmd);
...@@ -1994,27 +1751,22 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1994,27 +1751,22 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
* counts, we will always do a pseudo DMA or DMA transfer. * counts, we will always do a pseudo DMA or DMA transfer.
*/ */
static int NCR5380_transfer_pio(struct Scsi_Host *instance, static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
unsigned char *phase, int *count, unsigned char **data) {
NCR5380_local_declare(); NCR5380_local_declare();
register unsigned char p = *phase, tmp; unsigned char p = *phase, tmp;
register int c = *count; int c = *count;
register unsigned char *d = *data; unsigned char *d = *data;
#ifdef USLEEP
/* /*
* RvC: some administrative data to process polling time * RvC: some administrative data to process polling time
*/ */
int break_allowed = 0; int break_allowed = 0;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
#endif
NCR5380_setup(instance); NCR5380_setup(instance);
#if (NDEBUG & NDEBUG_PIO)
if (!(p & SR_IO)) if (!(p & SR_IO))
printk("scsi%d : pio write %d bytes\n", instance->host_no, c); dprintk(NDEBUG_PIO, ("scsi%d : pio write %d bytes\n", instance->host_no, c));
else else
printk("scsi%d : pio read %d bytes\n", instance->host_no, c); dprintk(NDEBUG_PIO, ("scsi%d : pio read %d bytes\n", instance->host_no, c));
#endif
/* /*
* The NCR5380 chip will only drive the SCSI bus when the * The NCR5380 chip will only drive the SCSI bus when the
...@@ -2024,55 +1776,41 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, ...@@ -2024,55 +1776,41 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
#ifdef USLEEP
/* RvC: don't know if this is necessary, but other SCSI I/O is short /* RvC: don't know if this is necessary, but other SCSI I/O is short
* so breaks are not necessary there * so breaks are not necessary there
*/ */
if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) {
{
break_allowed = 1; break_allowed = 1;
} }
#endif
do { do {
/* /*
* Wait for assertion of REQ, after which the phase bits will be * Wait for assertion of REQ, after which the phase bits will be
* valid * valid
*/ */
#ifdef USLEEP
/* RvC: we simply poll once, after that we stop temporarily /* RvC: we simply poll once, after that we stop temporarily
* and let the device buffer fill up * and let the device buffer fill up
* if breaking is not allowed, we keep polling as long as needed * if breaking is not allowed, we keep polling as long as needed
*/ */
while ( !((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
!break_allowed ); if (!(tmp & SR_REQ)) {
if (!(tmp & SR_REQ))
{
/* timeout condition */ /* timeout condition */
hostdata->time_expires = jiffies + USLEEP_SLEEP; hostdata->time_expires = jiffies + USLEEP_SLEEP;
NCR5380_set_timer (instance); NCR5380_set_timer(instance);
break; break;
} }
#else
while ( !((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) );
#endif
#if (NDEBUG & NDEBUG_HANDSHAKE) dprintk(NDEBUG_HANDSHAKE, ("scsi%d : REQ detected\n", instance->host_no));
printk("scsi%d : REQ detected\n", instance->host_no);
#endif
/* Check for phase mismatch */ /* Check for phase mismatch */
if ((tmp & PHASE_MASK) != p) { if ((tmp & PHASE_MASK) != p) {
#if (NDEBUG & NDEBUG_PIO) dprintk(NDEBUG_HANDSHAKE, ("scsi%d : phase mismatch\n", instance->host_no));
printk("scsi%d : phase mismatch\n", instance->host_no); NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance);
NCR5380_print_phase(instance);
#endif
break; break;
} }
/* Do actual transfer from SCSI bus to / from memory */ if (!(p & SR_IO)) /* Do actual transfer from SCSI bus to / from memory */
if (!(p & SR_IO))
NCR5380_write(OUTPUT_DATA_REG, *d); NCR5380_write(OUTPUT_DATA_REG, *d);
else else
*d = NCR5380_read(CURRENT_SCSI_DATA_REG); *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
...@@ -2088,34 +1826,22 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, ...@@ -2088,34 +1826,22 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
if (!(p & SR_IO)) { if (!(p & SR_IO)) {
if (!((p & SR_MSG) && c > 1)) { if (!((p & SR_MSG) && c > 1)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
ICR_ASSERT_DATA); NCR5380_dprint(NDEBUG_PIO, instance);
#if (NDEBUG & NDEBUG_PIO) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);
NCR5380_print(instance);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA | ICR_ASSERT_ACK);
} else { } else {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);
ICR_ASSERT_DATA | ICR_ASSERT_ATN); NCR5380_dprint(NDEBUG_PIO, instance);
#if (NDEBUG & NDEBUG_PIO) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
NCR5380_print(instance);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
} }
} else { } else {
#if (NDEBUG & NDEBUG_PIO) NCR5380_dprint(NDEBUG_PIO, instance);
NCR5380_print(instance);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
} }
while (NCR5380_read(STATUS_REG) & SR_REQ); while (NCR5380_read(STATUS_REG) & SR_REQ);
#if (NDEBUG & NDEBUG_HANDSHAKE) dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no));
printk("scsi%d : req false, handshake complete\n", instance->host_no);
#endif
/* /*
* We have several special cases to consider during REQ/ACK handshaking : * We have several special cases to consider during REQ/ACK handshaking :
...@@ -2136,9 +1862,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, ...@@ -2136,9 +1862,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
} }
} while (--c); } while (--c);
#if (NDEBUG & NDEBUG_PIO) dprintk(NDEBUG_PIO, ("scsi%d : residual %d\n", instance->host_no, c));
printk("scsi%d : residual %d\n", instance->host_no, c);
#endif
*count = c; *count = c;
*data = d; *data = d;
...@@ -2154,28 +1878,38 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, ...@@ -2154,28 +1878,38 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
return -1; return -1;
} }
/**
* do_reset - issue a reset command
* @host: adapter to reset
*
* Issue a reset sequence to the NCR5380 and try and get the bus
* back into sane shape.
*
* Locks: caller holds io_request lock
*/
static void do_reset(struct Scsi_Host *host) { static void do_reset(struct Scsi_Host *host) {
unsigned long flags;
NCR5380_local_declare(); NCR5380_local_declare();
NCR5380_setup(host); NCR5380_setup(host);
save_flags(flags); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
cli();
NCR5380_write(TARGET_COMMAND_REG,
PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
udelay(25); udelay(25);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
restore_flags(flags); }
} /*
/*
* Function : do_abort (Scsi_Host *host) * Function : do_abort (Scsi_Host *host)
* *
* Purpose : abort the currently established nexus. Should only be * Purpose : abort the currently established nexus. Should only be
* called from a routine which can drop into a * called from a routine which can drop into a
* *
* Returns : 0 on success, -1 on failure. * Returns : 0 on success, -1 on failure.
*/ static int do_abort(struct Scsi_Host *host) { *
* Locks: io_request lock held by caller
*/
static int do_abort(struct Scsi_Host *host) {
NCR5380_local_declare(); NCR5380_local_declare();
unsigned char tmp, *msgptr, phase; unsigned char tmp, *msgptr, phase;
int len; int len;
...@@ -2200,8 +1934,7 @@ static void do_reset(struct Scsi_Host *host) { ...@@ -2200,8 +1934,7 @@ static void do_reset(struct Scsi_Host *host) {
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
ICR_ASSERT_ACK);
while (NCR5380_read(STATUS_REG) & SR_REQ); while (NCR5380_read(STATUS_REG) & SR_REQ);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
} }
...@@ -2237,27 +1970,23 @@ static void do_reset(struct Scsi_Host *host) { ...@@ -2237,27 +1970,23 @@ static void do_reset(struct Scsi_Host *host) {
* *
* Also, *phase, *count, *data are modified in place. * Also, *phase, *count, *data are modified in place.
* *
* Locks: io_request lock held by caller
*/ */
static int NCR5380_transfer_dma(struct Scsi_Host *instance, static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
unsigned char *phase, int *count, unsigned char **data) {
NCR5380_local_declare(); NCR5380_local_declare();
register int c = *count; register int c = *count;
register unsigned char p = *phase; register unsigned char p = *phase;
register unsigned char *d = *data; register unsigned char *d = *data;
unsigned char tmp; unsigned char tmp;
#if defined(PSEUDO_DMA) && !defined(UNSAFE)
unsigned long flags;
#endif
int foo; int foo;
#if defined(REAL_DMA_POLL) #if defined(REAL_DMA_POLL)
int cnt, toPIO; int cnt, toPIO;
unsigned char saved_data = 0, overrun = 0, residue; unsigned char saved_data = 0, overrun = 0, residue;
#endif #endif
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
instance->hostdata;
NCR5380_setup(instance); NCR5380_setup(instance);
...@@ -2267,24 +1996,20 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, ...@@ -2267,24 +1996,20 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
} }
#if defined(REAL_DMA) || defined(REAL_DMA_POLL) #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
#ifdef READ_OVERRUNS #ifdef READ_OVERRUNS
if (p & SR_IO) { c -= 2; } if (p & SR_IO) {
#endif c -= 2;
#if (NDEBUG & NDEBUG_DMA) }
printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n",
instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" :
"writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
#endif #endif
hostdata->dma_len = (p & SR_IO) ? dprintk(NDEBUG_DMA, ("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d));
NCR5380_dma_read_setup(instance, d, c) : hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);
NCR5380_dma_write_setup(instance, d, c);
#endif #endif
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
#ifdef REAL_DMA #ifdef REAL_DMA
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
#elif defined(REAL_DMA_POLL) #elif defined(REAL_DMA_POLL)
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
#else #else
/* /*
* Note : on my sample board, watch-dog timeouts occurred when interrupts * Note : on my sample board, watch-dog timeouts occurred when interrupts
...@@ -2292,58 +2017,38 @@ NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); ...@@ -2292,58 +2017,38 @@ NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
* before the setting of DMA mode to after transfer of the last byte. * before the setting of DMA mode to after transfer of the last byte.
*/ */
#if defined(PSEUDO_DMA) && !defined(UNSAFE) #if defined(PSEUDO_DMA) && defined(UNSAFE)
save_flags(flags); spin_unlock_irq(&io_request_lock);
cli();
#endif #endif
/* KLL May need eop and parity in 53c400 */ /* KLL May need eop and parity in 53c400 */
if (hostdata->flags & FLAG_NCR53C400) if (hostdata->flags & FLAG_NCR53C400)
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE | MR_MONITOR_BSY);
| MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE else
| MR_MONITOR_BSY);
else
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
#endif /* def REAL_DMA */ #endif /* def REAL_DMA */
#if (NDEBUG & NDEBUG_DMA) & 0 dprintk(NDEBUG_DMA, ("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)));
printk("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
#endif
/* /*
* FOO stuff. For some UNAPPARENT reason, I'm getting * On the PAS16 at least I/O recovery delays are not needed here.
* watchdog timers fired on bootup for NO APPARENT REASON, meaning it's * Everyone else seems to want them.
* probably a timing problem.
*
* Since this is the only place I have back-to-back writes, perhaps this
* is the problem?
*/ */
if (p & SR_IO) if (p & SR_IO) {
{ io_recovery_delay(1);
#ifndef FOO NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
udelay(1); } else {
#endif io_recovery_delay(1);
NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
} else {
#ifndef FOO
udelay(1);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
#ifndef FOO io_recovery_delay(1);
udelay(1);
#endif
NCR5380_write(START_DMA_SEND_REG, 0); NCR5380_write(START_DMA_SEND_REG, 0);
#ifndef FOO io_recovery_delay(1);
udelay(1); }
#endif
}
#if defined(REAL_DMA_POLL) #if defined(REAL_DMA_POLL)
do { do {
tmp = NCR5380_read(BUS_AND_STATUS_REG); tmp = NCR5380_read(BUS_AND_STATUS_REG);
} while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | } while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER)));
BASR_END_DMA_TRANSFER)));
/* /*
At this point, either we've completed DMA, or we have a phase mismatch, At this point, either we've completed DMA, or we have a phase mismatch,
...@@ -2381,74 +2086,60 @@ do { ...@@ -2381,74 +2086,60 @@ do {
request. request.
*/ */
if (p & SR_IO) { if (p & SR_IO) {
#ifdef READ_OVERRUNS #ifdef READ_OVERRUNS
udelay(10); udelay(10);
if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == (BASR_PHASE_MATCH | BASR_ACK))) {
(BASR_PHASE_MATCH | BASR_ACK))) {
saved_data = NCR5380_read(INPUT_DATA_REGISTER); saved_data = NCR5380_read(INPUT_DATA_REGISTER);
overrun = 1; overrun = 1;
} }
#endif #endif
} else { } else {
int limit = 100; int limit = 100;
while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) {
(NCR5380_read(STATUS_REG) & SR_REQ)) {
if (!(tmp & BASR_PHASE_MATCH)) if (!(tmp & BASR_PHASE_MATCH))
break; break;
if (--limit < 0) if (--limit < 0)
break; break;
} }
} }
dprintk(NDEBUG_DMA, ("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG)));
#if (NDEBUG & NDEBUG_DMA) NCR5380_write(MODE_REG, MR_BASE);
printk("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
instance->host_no, tmp, NCR5380_read(STATUS_REG));
#endif
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
residue = NCR5380_dma_residual(instance); residue = NCR5380_dma_residual(instance);
c -= residue; c -= residue;
*count -= c; *count -= c;
*data += c; *data += c;
*phase = NCR5380_read(STATUS_REG) & PHASE_MASK; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
#ifdef READ_OVERRUNS #ifdef READ_OVERRUNS
if (*phase == p && (p & SR_IO) && residue == 0) if (*phase == p && (p & SR_IO) && residue == 0) {
{ if (overrun) {
if (overrun) { dprintk(NDEBUG_DMA, ("Got an input overrun, using saved byte\n"));
#if (NDEBUG & NDEBUG_DMA)
printk("Got an input overrun, using saved byte\n");
#endif
**data = saved_data; **data = saved_data;
*data += 1; *data += 1;
*count -= 1; *count -= 1;
cnt = toPIO = 1; cnt = toPIO = 1;
} else { } else {
printk("No overrun??\n"); printk("No overrun??\n");
cnt = toPIO = 2; cnt = toPIO = 2;
} }
#if (NDEBUG & NDEBUG_DMA) dprintk(NDEBUG_DMA, ("Doing %d-byte PIO to 0x%X\n", cnt, *data));
printk("Doing %d-byte PIO to 0x%X\n", cnt, *data); NCR5380_transfer_pio(instance, phase, &cnt, data);
#endif *count -= toPIO - cnt;
NCR5380_transfer_pio(instance, phase, &cnt, data); }
*count -= toPIO - cnt;
}
#endif #endif
#if (NDEBUG & NDEBUG_DMA) dprintk(NDEBUG_DMA, ("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)));
printk("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", return 0;
*data, *count, *(*data + *count - 1), *(*data + *count));
#endif
return 0;
#elif defined(REAL_DMA) #elif defined(REAL_DMA)
return 0; return 0;
#else /* defined(REAL_DMA_POLL) */ #else /* defined(REAL_DMA_POLL) */
if (p & SR_IO) { if (p & SR_IO) {
#ifdef DMA_WORKS_RIGHT #ifdef DMA_WORKS_RIGHT
foo = NCR5380_pread(instance, d, c); foo = NCR5380_pread(instance, d, c);
#else #else
...@@ -2487,14 +2178,12 @@ if (p & SR_IO) { ...@@ -2487,14 +2178,12 @@ if (p & SR_IO) {
} }
} }
#endif #endif
} else { } else {
#ifdef DMA_WORKS_RIGHT #ifdef DMA_WORKS_RIGHT
foo = NCR5380_pwrite(instance, d, c); foo = NCR5380_pwrite(instance, d, c);
#else #else
int timeout; int timeout;
#if (NDEBUG & NDEBUG_C400_PWRITE) dprintk(NDEBUG_C400_PWRITE, ("About to pwrite %d bytes\n", c));
printk("About to pwrite %d bytes\n", c);
#endif
if (!(foo = NCR5380_pwrite(instance, d, c))) { if (!(foo = NCR5380_pwrite(instance, d, c))) {
/* /*
* Wait for the last byte to be sent. If REQ is being asserted for * Wait for the last byte to be sent. If REQ is being asserted for
...@@ -2502,51 +2191,23 @@ if (p & SR_IO) { ...@@ -2502,51 +2191,23 @@ if (p & SR_IO) {
*/ */
if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) { if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) {
timeout = 20000; timeout = 20000;
#if 1 while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH));
#if 1
while (!(NCR5380_read(BUS_AND_STATUS_REG) &
BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) &
BASR_PHASE_MATCH));
#else
if (NCR5380_read(STATUS_REG) & SR_REQ) {
for (; timeout &&
!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
--timeout);
for (; timeout && (NCR5380_read(STATUS_REG) & SR_REQ);
--timeout);
}
#endif
#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
if (!timeout) if (!timeout)
printk("scsi%d : timed out on last byte\n", dprintk(NDEBUG_LAST_BYTE_SENT, ("scsi%d : timed out on last byte\n", instance->host_no));
instance->host_no);
#endif
if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) { if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) {
hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT; hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT;
if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) { if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) {
hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT; hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT;
#if (NDEBUG & NDEBUG_LAST_BYTE_SENT) dprintk(NDEBUG_LAST_WRITE_SENT, ("scsi%d : last bit sent works\n", instance->host_no));
printk("scsi%d : last bit sent works\n",
instance->host_no);
#endif
} }
} }
} else { } else {
#if (NDEBUG & NDEBUG_C400_PWRITE) dprintk(NDEBUG_C400_PWRITE, ("Waiting for LASTBYTE\n"));
printk("Waiting for LASTBYTE\n");
#endif
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)); while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));
#if (NDEBUG & NDEBUG_C400_PWRITE) dprintk(NDEBUG_C400_PWRITE, ("Got LASTBYTE\n"));
printk("Got LASTBYTE\n");
#endif
} }
#else
udelay(5);
#endif
} }
#endif #endif
} }
...@@ -2554,13 +2215,9 @@ if (p & SR_IO) { ...@@ -2554,13 +2215,9 @@ if (p & SR_IO) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) { if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) {
#if (NDEBUG & NDEBUG_C400_PWRITE) dprintk(NDEBUG_C400_PWRITE, ("53C400w: Checking for IRQ\n"));
printk("53C400w: Checking for IRQ\n");
#endif
if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) { if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) {
#if (NDEBUG & NDEBUG_C400_PWRITE) dprintk(NDEBUG_C400_PWRITE, ("53C400w: got it, reading reset interrupt reg\n"));
printk("53C400w: got it, reading reset interrupt reg\n");
#endif
NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else { } else {
printk("53C400w: IRQ NOT THERE!\n"); printk("53C400w: IRQ NOT THERE!\n");
...@@ -2569,11 +2226,8 @@ if (p & SR_IO) { ...@@ -2569,11 +2226,8 @@ if (p & SR_IO) {
*data = d + c; *data = d + c;
*count = 0; *count = 0;
*phase = NCR5380_read(STATUS_REG) & PHASE_MASK; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
#if 0 #if defined(PSEUDO_DMA) && defined(UNSAFE)
NCR5380_print_phase(instance); spin_lock_irq(&io_request_lock);
#endif
#if defined(PSEUDO_DMA) && !defined(UNSAFE)
restore_flags(flags);
#endif /* defined(REAL_DMA_POLL) */ #endif /* defined(REAL_DMA_POLL) */
return foo; return foo;
#endif /* def REAL_DMA */ #endif /* def REAL_DMA */
...@@ -2595,12 +2249,13 @@ if (p & SR_IO) { ...@@ -2595,12 +2249,13 @@ if (p & SR_IO) {
* *
* XXX Note : we need to watch for bus free or a reset condition here * XXX Note : we need to watch for bus free or a reset condition here
* to recover from an unexpected bus free condition. * to recover from an unexpected bus free condition.
*
* Locks: io_request_lock held by caller
*/ */
static void NCR5380_information_transfer(struct Scsi_Host *instance) { static void NCR5380_information_transfer(struct Scsi_Host *instance) {
NCR5380_local_declare(); NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
instance->hostdata;
unsigned char msgout = NOP; unsigned char msgout = NOP;
int sink = 0; int sink = 0;
int len; int len;
...@@ -2610,10 +2265,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2610,10 +2265,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
unsigned char *data; unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected; Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
#ifdef USLEEP
/* RvC: we need to set the end of the polling time */ /* RvC: we need to set the end of the polling time */
unsigned long poll_time = jiffies + USLEEP_POLL; unsigned long poll_time = jiffies + USLEEP_POLL;
#endif
NCR5380_setup(instance); NCR5380_setup(instance);
...@@ -2624,18 +2277,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2624,18 +2277,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
phase = (tmp & PHASE_MASK); phase = (tmp & PHASE_MASK);
if (phase != old_phase) { if (phase != old_phase) {
old_phase = phase; old_phase = phase;
#if (NDEBUG & NDEBUG_INFORMATION) NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
NCR5380_print_phase(instance);
#endif
} }
if (sink && (phase != PHASE_MSGOUT)) { if (sink && (phase != PHASE_MSGOUT)) {
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
ICR_ASSERT_ACK);
while (NCR5380_read(STATUS_REG) & SR_REQ); while (NCR5380_read(STATUS_REG) & SR_REQ);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
ICR_ASSERT_ATN);
sink = 0; sink = 0;
continue; continue;
} }
...@@ -2643,8 +2292,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2643,8 +2292,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
case PHASE_DATAIN: case PHASE_DATAIN:
case PHASE_DATAOUT: case PHASE_DATAOUT:
#if (NDEBUG & NDEBUG_NO_DATAOUT) #if (NDEBUG & NDEBUG_NO_DATAOUT)
printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", instance->host_no);
instance->host_no);
sink = 1; sink = 1;
do_abort(instance); do_abort(instance);
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
...@@ -2661,11 +2309,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2661,11 +2309,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
--cmd->SCp.buffers_residual; --cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.this_residual = cmd->SCp.buffer->length;
cmd->SCp.ptr = cmd->SCp.buffer->address; cmd->SCp.ptr = cmd->SCp.buffer->address;
#if (NDEBUG & NDEBUG_INFORMATION) dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
printk("scsi%d : %d bytes and %d buffers left\n",
instance->host_no, cmd->SCp.this_residual,
cmd->SCp.buffers_residual);
#endif
} }
/* /*
* The preferred transfer method is going to be * The preferred transfer method is going to be
...@@ -2686,9 +2330,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2686,9 +2330,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* We supplement these 2 if's with the flag. * We supplement these 2 if's with the flag.
*/ */
#ifdef NCR5380_dma_xfer_len #ifdef NCR5380_dma_xfer_len
if (!cmd->device->borken && if (!cmd->device->borken && !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {
!(hostdata->flags & FLAG_NO_PSEUDO_DMA) &&
(transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {
#else #else
transfersize = cmd->transfersize; transfersize = cmd->transfersize;
...@@ -2697,27 +2339,21 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2697,27 +2339,21 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
transfersize = 512; transfersize = 512;
#endif /* LIMIT_TRANSFERSIZE */ #endif /* LIMIT_TRANSFERSIZE */
if (!cmd->device->borken && transfersize && if (!cmd->device->borken && transfersize && !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && cmd->SCp.this_residual && !(cmd->SCp.this_residual % transfersize)) {
!(hostdata->flags & FLAG_NO_PSEUDO_DMA) &&
cmd->SCp.this_residual && !(cmd->SCp.this_residual %
transfersize)) {
/* Limit transfers to 32K, for xx400 & xx406 /* Limit transfers to 32K, for xx400 & xx406
* pseudoDMA that transfers in 128 bytes blocks. */ * pseudoDMA that transfers in 128 bytes blocks. */
if (transfersize > 32 * 1024) if (transfersize > 32 * 1024)
transfersize = 32 * 1024; transfersize = 32 * 1024;
#endif #endif
len = transfersize; len = transfersize;
if (NCR5380_transfer_dma(instance, &phase, if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **) &cmd->SCp.ptr)) {
&len, (unsigned char **) &cmd->SCp.ptr)) {
/* /*
* If the watchdog timer fires, all future accesses to this * If the watchdog timer fires, all future accesses to this
* device will use the polled-IO. * device will use the polled-IO.
*/ */
printk("scsi%d : switching target %d lun %d to slow handshake\n", printk("scsi%d : switching target %d lun %d to slow handshake\n", instance->host_no, cmd->target, cmd->lun);
instance->host_no, cmd->target, cmd->lun);
cmd->device->borken = 1; cmd->device->borken = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
ICR_ASSERT_ATN);
sink = 1; sink = 1;
do_abort(instance); do_abort(instance);
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
...@@ -2727,8 +2363,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2727,8 +2363,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
cmd->SCp.this_residual -= transfersize - len; cmd->SCp.this_residual -= transfersize - len;
} else } else
#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ #endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
NCR5380_transfer_pio(instance, &phase, NCR5380_transfer_pio(instance, &phase, (int *) &cmd->SCp.this_residual, (unsigned char **)
(int *) &cmd->SCp.this_residual, (unsigned char **)
&cmd->SCp.ptr); &cmd->SCp.ptr);
break; break;
case PHASE_MSGIN: case PHASE_MSGIN:
...@@ -2753,20 +2388,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2753,20 +2388,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
case LINKED_FLG_CMD_COMPLETE: case LINKED_FLG_CMD_COMPLETE:
/* Accept message by clearing ACK */ /* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->target, cmd->lun));
#if (NDEBUG & NDEBUG_LINKED)
printk("scsi%d : target %d lun %d linked command complete.\n",
instance->host_no, cmd->target, cmd->lun);
#endif
/* /*
* Sanity check : A linked command should only terminate with * Sanity check : A linked command should only terminate with
* one of these messages if there are more linked commands * one of these messages if there are more linked commands
* available. * available.
*/ */
if (!cmd->next_link) { if (!cmd->next_link) {
printk("scsi%d : target %d lun %d linked command complete, no next_link\n" printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->target, cmd->lun);
instance->host_no, cmd->target, cmd->lun);
sink = 1; sink = 1;
do_abort(instance); do_abort(instance);
return; return;
...@@ -2775,13 +2404,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2775,13 +2404,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* The next command is still part of this process */ /* The next command is still part of this process */
cmd->next_link->tag = cmd->tag; cmd->next_link->tag = cmd->tag;
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
#if (NDEBUG & NDEBUG_LINKED) dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->target, cmd->lun));
printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n",
instance->host_no, cmd->target, cmd->lun);
#endif
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd); collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
cmd = hostdata->connected; cmd = hostdata->connected;
break; break;
...@@ -2792,10 +2416,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2792,10 +2416,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
sink = 1; sink = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
hostdata->connected = NULL; hostdata->connected = NULL;
#if (NDEBUG & NDEBUG_QUEUES) dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->target, cmd->lun));
printk("scsi%d : command for target %d, lun %d completed\n",
instance->host_no, cmd->target, cmd->lun);
#endif
hostdata->busy[cmd->target] &= ~(1 << cmd->lun); hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
/* /*
...@@ -2820,13 +2441,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2820,13 +2441,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
#ifdef AUTOSENSE #ifdef AUTOSENSE
if ((cmd->cmnd[0] != REQUEST_SENSE) && if ((cmd->cmnd[0] != REQUEST_SENSE) && (cmd->SCp.Status == CHECK_CONDITION)) {
(cmd->SCp.Status == CHECK_CONDITION)) { dprintk(NDEBUG_AUTOSENSE, ("scsi%d : performing request sense\n", instance->host_no));
unsigned long flags;
#if (NDEBUG & NDEBUG_AUTOSENSE)
printk("scsi%d : performing request sense\n",
instance->host_no);
#endif
cmd->cmnd[0] = REQUEST_SENSE; cmd->cmnd[0] = REQUEST_SENSE;
cmd->cmnd[1] &= 0xe0; cmd->cmnd[1] &= 0xe0;
cmd->cmnd[2] = 0; cmd->cmnd[2] = 0;
...@@ -2839,21 +2455,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2839,21 +2455,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
cmd->SCp.ptr = (char *) cmd->sense_buffer; cmd->SCp.ptr = (char *) cmd->sense_buffer;
cmd->SCp.this_residual = sizeof(cmd->sense_buffer); cmd->SCp.this_residual = sizeof(cmd->sense_buffer);
save_flags(flags);
cli();
LIST(cmd, hostdata->issue_queue); LIST(cmd, hostdata->issue_queue);
cmd->host_scribble = (unsigned char *) cmd->host_scribble = (unsigned char *)
hostdata->issue_queue; hostdata->issue_queue;
hostdata->issue_queue = (Scsi_Cmnd *) cmd; hostdata->issue_queue = (Scsi_Cmnd *) cmd;
restore_flags(flags); dprintk(NDEBUG_QUEUES, ("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no));
#if (NDEBUG & NDEBUG_QUEUES)
printk("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
#endif
} else { } else {
#endif /* def AUTOSENSE */ #endif /* def AUTOSENSE */
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd); collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
} }
...@@ -2880,24 +2489,16 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2880,24 +2489,16 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
default: default:
break; break;
} }
case DISCONNECT: { case DISCONNECT:{
unsigned long flags;
/* Accept message by clearing ACK */ /* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
cmd->device->disconnect = 1; cmd->device->disconnect = 1;
save_flags(flags);
cli();
LIST(cmd, hostdata->disconnected_queue); LIST(cmd, hostdata->disconnected_queue);
cmd->host_scribble = (unsigned char *) cmd->host_scribble = (unsigned char *)
hostdata->disconnected_queue; hostdata->disconnected_queue;
hostdata->connected = NULL; hostdata->connected = NULL;
hostdata->disconnected_queue = cmd; hostdata->disconnected_queue = cmd;
restore_flags(flags); dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d lun %d was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->target, cmd->lun));
#if (NDEBUG & NDEBUG_QUEUES)
printk("scsi%d : command for target %d lun %d was moved from connected to"
" the disconnected_queue\n", instance->host_no,
cmd->target, cmd->lun);
#endif
/* /*
* Restore phase bits to 0 so an interrupted selection, * Restore phase bits to 0 so an interrupted selection,
* arbitration can resume. * arbitration can resume.
...@@ -2909,9 +2510,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2909,9 +2510,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* Wait for bus free to avoid nasty timeouts */ /* Wait for bus free to avoid nasty timeouts */
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
barrier(); barrier();
#if 0
NCR5380_print_status(instance);
#endif
return; return;
} }
/* /*
...@@ -2945,25 +2543,16 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2945,25 +2543,16 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
extended_msg[0] = EXTENDED_MESSAGE; extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */ /* Accept first byte by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
dprintk(NDEBUG_EXTENDED, ("scsi%d : receiving extended message\n", instance->host_no));
#if (NDEBUG & NDEBUG_EXTENDED)
printk("scsi%d : receiving extended message\n",
instance->host_no);
#endif
len = 2; len = 2;
data = extended_msg + 1; data = extended_msg + 1;
phase = PHASE_MSGIN; phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
#if (NDEBUG & NDEBUG_EXTENDED) dprintk(NDEBUG_EXTENDED, ("scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]));
printk("scsi%d : length=%d, code=0x%02x\n",
instance->host_no, (int) extended_msg[1],
(int) extended_msg[2]);
#endif
if (!len && extended_msg[1] <= if (!len && extended_msg[1] <= (sizeof(extended_msg) - 1)) {
(sizeof(extended_msg) - 1)) {
/* Accept third byte by clearing ACK */ /* Accept third byte by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
len = extended_msg[1] - 1; len = extended_msg[1] - 1;
...@@ -2971,11 +2560,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2971,11 +2560,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
phase = PHASE_MSGIN; phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
dprintk(NDEBUG_EXTENDED, ("scsi%d : message received, residual %d\n", instance->host_no, len));
#if (NDEBUG & NDEBUG_EXTENDED)
printk("scsi%d : message received, residual %d\n",
instance->host_no, len);
#endif
switch (extended_msg[2]) { switch (extended_msg[2]) {
case EXTENDED_SDTR: case EXTENDED_SDTR:
...@@ -2985,12 +2570,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2985,12 +2570,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
tmp = 0; tmp = 0;
} }
} else if (len) { } else if (len) {
printk("scsi%d: error receiving extended message\n", printk("scsi%d: error receiving extended message\n", instance->host_no);
instance->host_no);
tmp = 0; tmp = 0;
} else { } else {
printk("scsi%d: extended message code %02x length %d is too long\n", printk("scsi%d: extended message code %02x length %d is too long\n", instance->host_no, extended_msg[2], extended_msg[1]);
instance->host_no, extended_msg[2], extended_msg[1]);
tmp = 0; tmp = 0;
} }
/* Fall through to reject message */ /* Fall through to reject message */
...@@ -3005,15 +2588,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -3005,15 +2588,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
print_msg(extended_msg); print_msg(extended_msg);
printk("\n"); printk("\n");
} else if (tmp != EXTENDED_MESSAGE) } else if (tmp != EXTENDED_MESSAGE)
printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n", printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n", instance->host_no, tmp, cmd->target, cmd->lun);
instance->host_no, tmp, cmd->target, cmd->lun);
else else
printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n", printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n", instance->host_no, extended_msg[1], extended_msg[0], cmd->target, cmd->lun);
instance->host_no, extended_msg[1], extended_msg[0], cmd->target, cmd->lun);
msgout = MESSAGE_REJECT; msgout = MESSAGE_REJECT;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
ICR_ASSERT_ATN);
break; break;
} /* switch (tmp) */ } /* switch (tmp) */
break; break;
...@@ -3026,9 +2606,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -3026,9 +2606,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
hostdata->busy[cmd->target] &= ~(1 << cmd->lun); hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->connected = NULL; hostdata->connected = NULL;
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd); collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return; return;
...@@ -3043,21 +2621,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -3043,21 +2621,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* PSEUDO-DMA architecture we should probably * PSEUDO-DMA architecture we should probably
* use the dma transfer function. * use the dma transfer function.
*/ */
NCR5380_transfer_pio(instance, &phase, &len, NCR5380_transfer_pio(instance, &phase, &len, &data);
&data); if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
#ifdef USLEEP
if (!cmd->device->disconnect &&
should_disconnect(cmd->cmnd[0]))
{
hostdata->time_expires = jiffies + USLEEP_SLEEP; hostdata->time_expires = jiffies + USLEEP_SLEEP;
#if (NDEBUG & NDEBUG_USLEEP) dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
printk("scsi%d : issued command, sleeping until %ul\n", instance->host_no,
hostdata->time_expires);
#endif
NCR5380_set_timer(instance); NCR5380_set_timer(instance);
return; return;
} }
#endif /* def USLEEP */
break; break;
case PHASE_STATIN: case PHASE_STATIN:
len = 1; len = 1;
...@@ -3067,28 +2637,19 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -3067,28 +2637,19 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
break; break;
default: default:
printk("scsi%d : unknown phase\n", instance->host_no); printk("scsi%d : unknown phase\n", instance->host_no);
#ifdef NDEBUG NCR5380_dprint(NDEBUG_ALL, instance);
NCR5380_print(instance);
#endif
} /* switch(phase) */ } /* switch(phase) */
} /* if (tmp * SR_REQ) */ } /* if (tmp * SR_REQ) */
#ifdef USLEEP else {
else
{
/* RvC: go to sleep if polling time expired /* RvC: go to sleep if polling time expired
*/ */
if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
{
hostdata->time_expires = jiffies + USLEEP_SLEEP; hostdata->time_expires = jiffies + USLEEP_SLEEP;
#if (NDEBUG & NDEBUG_USLEEP) dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
printk("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no,
hostdata->time_expires);
#endif
NCR5380_set_timer(instance); NCR5380_set_timer(instance);
return; return;
} }
} }
#endif
} /* while (1) */ } /* while (1) */
} }
...@@ -3101,9 +2662,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -3101,9 +2662,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* *
* Inputs : instance - this instance of the NCR5380. * Inputs : instance - this instance of the NCR5380.
* *
* Locks: io_request_lock held by caller
*/ */
static void NCR5380_reselect(struct Scsi_Host *instance) { static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_local_declare(); NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
...@@ -3111,9 +2672,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3111,9 +2672,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
unsigned char target_mask; unsigned char target_mask;
unsigned char lun, phase; unsigned char lun, phase;
int len; int len;
#ifdef SCSI2
unsigned char tag;
#endif
unsigned char msg[3]; unsigned char msg[3];
unsigned char *data; unsigned char *data;
Scsi_Cmnd *tmp = NULL, *prev; Scsi_Cmnd *tmp = NULL, *prev;
...@@ -3129,10 +2687,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3129,10 +2687,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
hostdata->restart_select = 1; hostdata->restart_select = 1;
target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
dprintk(NDEBUG_SELECTION, ("scsi%d : reselect\n", instance->host_no));
#if (NDEBUG & NDEBUG_RESELECTION)
printk("scsi%d : reselect\n", instance->host_no);
#endif
/* /*
* At this point, we have detected that our SCSI ID is on the bus, * At this point, we have detected that our SCSI ID is on the bus,
...@@ -3159,10 +2714,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3159,10 +2714,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
phase = PHASE_MSGIN; phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
if (!msg[0] & 0x80) { if (!msg[0] & 0x80) {
printk("scsi%d : expecting IDENTIFY message, got ", printk("scsi%d : expecting IDENTIFY message, got ", instance->host_no);
instance->host_no);
print_msg(msg); print_msg(msg);
abort = 1; abort = 1;
} else { } else {
...@@ -3176,22 +2729,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3176,22 +2729,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
* nexuses so we can chose to do additional data transfer. * nexuses so we can chose to do additional data transfer.
*/ */
#ifdef SCSI2
#error "SCSI-II tagged queueing is not supported yet"
#endif
/* /*
* Find the command corresponding to the I_T_L or I_T_L_Q nexus we * Find the command corresponding to the I_T_L or I_T_L_Q nexus we
* just reestablished, and remove it from the disconnected queue. * just reestablished, and remove it from the disconnected queue.
*/ */
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun) if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun)
#ifdef SCSI2
&& (tag == tmp->tag)
#endif
) { ) {
if (prev) { if (prev) {
REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
...@@ -3204,13 +2749,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3204,13 +2749,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
break; break;
} }
if (!tmp) { if (!tmp) {
#ifdef SCSI2 printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun);
printk("scsi%d : warning : target bitmask %02x lun %d tag %d not in disconnect_queue.\n",
instance->host_no, target_mask, lun, tag);
#else
printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n",
instance->host_no, target_mask, lun);
#endif
/* /*
* Since we have an established nexus that we can't do anything with, * Since we have an established nexus that we can't do anything with,
* we must abort it. * we must abort it.
...@@ -3223,10 +2762,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3223,10 +2762,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
do_abort(instance); do_abort(instance);
} else { } else {
hostdata->connected = tmp; hostdata->connected = tmp;
#if (NDEBUG & NDEBUG_RESELECTION) dprintk(NDEBUG_RESELECTION, ("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->target, tmp->lun, tmp->tag));
printk("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n",
instance->host_no, tmp->target, tmp->lun, tmp->tag);
#endif
} }
} }
...@@ -3245,8 +2781,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -3245,8 +2781,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
#ifdef REAL_DMA #ifdef REAL_DMA
static void NCR5380_dma_complete(NCR5380_instance * instance) { static void NCR5380_dma_complete(NCR5380_instance * instance) {
NCR5380_local_declare(); NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * instance->hostdata);
instance->hostdata);
int transferred; int transferred;
NCR5380_setup(instance); NCR5380_setup(instance);
...@@ -3293,6 +2828,8 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { ...@@ -3293,6 +2828,8 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
* connected, you have to wait for it to complete. If this is * connected, you have to wait for it to complete. If this is
* a problem, we could implement longjmp() / setjmp(), setjmp() * a problem, we could implement longjmp() / setjmp(), setjmp()
* called where the loop started in NCR5380_main(). * called where the loop started in NCR5380_main().
*
* Locks: io_request_lock held by caller
*/ */
#ifndef NCR5380_abort #ifndef NCR5380_abort
...@@ -3300,10 +2837,8 @@ static ...@@ -3300,10 +2837,8 @@ static
#endif #endif
int NCR5380_abort(Scsi_Cmnd * cmd) { int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_local_declare(); NCR5380_local_declare();
unsigned long flags;
struct Scsi_Host *instance = cmd->host; struct Scsi_Host *instance = cmd->host;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
instance->hostdata;
Scsi_Cmnd *tmp, **prev; Scsi_Cmnd *tmp, **prev;
printk("scsi%d : aborting command\n", instance->host_no); printk("scsi%d : aborting command\n", instance->host_no);
...@@ -3316,15 +2851,10 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3316,15 +2851,10 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_print_status(instance); NCR5380_print_status(instance);
save_flags(flags);
cli();
NCR5380_setup(instance); NCR5380_setup(instance);
#if (NDEBUG & NDEBUG_ABORT) dprintk(NDEBUG_ABORT, ("scsi%d : abort called\n", instance->host_no));
printk("scsi%d : abort called\n", instance->host_no); dprintk(NDEBUG_ABORT, (" basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)));
printk(" basr 0x%X, sr 0x%X\n",
NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG));
#endif
#if 0 #if 0
/* /*
...@@ -3334,9 +2864,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3334,9 +2864,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*/ */
if (hostdata->connected == cmd) { if (hostdata->connected == cmd) {
#if (NDEBUG & NDEBUG_ABORT) dprintk(NDEBUG_ABORT, ("scsi%d : aborting connected command\n", instance->host_no));
printk("scsi%d : aborting connected command\n", instance->host_no);
#endif
hostdata->aborted = 1; hostdata->aborted = 1;
/* /*
* We should perform BSY checking, and make sure we haven't slipped * We should perform BSY checking, and make sure we haven't slipped
...@@ -3363,24 +2891,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3363,24 +2891,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* Case 2 : If the command hasn't been issued yet, we simply remove it * Case 2 : If the command hasn't been issued yet, we simply remove it
* from the issue queue. * from the issue queue.
*/ */
#if (NDEBUG & NDEBUG_ABORT)
/* KLL */ /* KLL */
printk("scsi%d : abort going into loop.\n", instance->host_no); dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
#endif for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue),
tmp = (Scsi_Cmnd *) hostdata->issue_queue;
tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp =
(Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) { if (cmd == tmp) {
REMOVE(5, *prev, tmp, tmp->host_scribble); REMOVE(5, *prev, tmp, tmp->host_scribble);
(*prev) = (Scsi_Cmnd *) tmp->host_scribble; (*prev) = (Scsi_Cmnd *) tmp->host_scribble;
tmp->host_scribble = NULL; tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16; tmp->result = DID_ABORT << 16;
restore_flags(flags); dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
#if (NDEBUG & NDEBUG_ABORT)
printk("scsi%d : abort removed command from issue queue.\n",
instance->host_no);
#endif
tmp->done(tmp); tmp->done(tmp);
return SCSI_ABORT_SUCCESS; return SCSI_ABORT_SUCCESS;
} }
...@@ -3402,10 +2921,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3402,10 +2921,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*/ */
if (hostdata->connected) { if (hostdata->connected) {
restore_flags(flags); dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
#if (NDEBUG & NDEBUG_ABORT)
printk("scsi%d : abort failed, command connected.\n", instance->host_no);
#endif
return SCSI_ABORT_NOT_RUNNING; return SCSI_ABORT_NOT_RUNNING;
} }
/* /*
...@@ -3433,34 +2949,22 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3433,34 +2949,22 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* it from the disconnected queue. * it from the disconnected queue.
*/ */
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
tmp = (Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) { if (cmd == tmp) {
restore_flags(flags); dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no));
#if (NDEBUG & NDEBUG_ABORT)
printk("scsi%d : aborting disconnected command.\n", instance->host_no);
#endif
if (NCR5380_select(instance, cmd, (int) cmd->tag)) if (NCR5380_select(instance, cmd, (int) cmd->tag))
return SCSI_ABORT_BUSY; return SCSI_ABORT_BUSY;
dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no));
#if (NDEBUG & NDEBUG_ABORT)
printk("scsi%d : nexus reestablished.\n", instance->host_no);
#endif
do_abort(instance); do_abort(instance);
cli(); for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue),
tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp =
(Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) { if (cmd == tmp) {
REMOVE(5, *prev, tmp, tmp->host_scribble); REMOVE(5, *prev, tmp, tmp->host_scribble);
*prev = (Scsi_Cmnd *) tmp->host_scribble; *prev = (Scsi_Cmnd *) tmp->host_scribble;
tmp->host_scribble = NULL; tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16; tmp->result = DID_ABORT << 16;
restore_flags(flags);
tmp->done(tmp); tmp->done(tmp);
return SCSI_ABORT_SUCCESS; return SCSI_ABORT_SUCCESS;
} }
...@@ -3474,10 +2978,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3474,10 +2978,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* so we won't panic, but we will notify the user in case something really * so we won't panic, but we will notify the user in case something really
* broke. * broke.
*/ */
printk("scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no);
restore_flags(flags);
printk("scsi%d : warning : SCSI command probably completed successfully\n"
" before abortion\n", instance->host_no);
return SCSI_ABORT_NOT_RUNNING; return SCSI_ABORT_NOT_RUNNING;
} }
...@@ -3489,6 +2990,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -3489,6 +2990,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* *
* Returns : SCSI_RESET_WAKEUP * Returns : SCSI_RESET_WAKEUP
* *
* Locks: io_request_lock held by caller
*/ */
#ifndef NCR5380_reset #ifndef NCR5380_reset
......
...@@ -55,6 +55,8 @@ ...@@ -55,6 +55,8 @@
#define NDEBUG_C400_PWRITE 0x200000 #define NDEBUG_C400_PWRITE 0x200000
#define NDEBUG_LISTS 0x400000 #define NDEBUG_LISTS 0x400000
#define NDEBUG_ANY 0xFFFFFFFFUL
/* /*
* The contents of the OUTPUT DATA register are asserted on the bus when * The contents of the OUTPUT DATA register are asserted on the bus when
* either arbitration is occurring or the phase-indicating signals ( * either arbitration is occurring or the phase-indicating signals (
...@@ -263,12 +265,10 @@ struct NCR5380_hostdata { ...@@ -263,12 +265,10 @@ struct NCR5380_hostdata {
NCR5380_select() */ NCR5380_select() */
volatile unsigned aborted:1; /* flag, says aborted */ volatile unsigned aborted:1; /* flag, says aborted */
int flags; int flags;
#ifdef USLEEP
unsigned long time_expires; /* in jiffies, set prior to sleeping */ unsigned long time_expires; /* in jiffies, set prior to sleeping */
struct Scsi_Host *next_timer; struct Scsi_Host *next_timer;
int select_time; /* timer in select for target response */ int select_time; /* timer in select for target response */
volatile Scsi_Cmnd *selecting; volatile Scsi_Cmnd *selecting;
#endif
#ifdef NCR5380_STATS #ifdef NCR5380_STATS
unsigned timebase; /* Base for time calcs */ unsigned timebase; /* Base for time calcs */
long time_read[8]; /* time to do reads */ long time_read[8]; /* time to do reads */
...@@ -283,92 +283,148 @@ struct NCR5380_hostdata { ...@@ -283,92 +283,148 @@ struct NCR5380_hostdata {
#ifdef __KERNEL__ #ifdef __KERNEL__
static struct Scsi_Host *first_instance; /* linked list of 5380's */ static struct Scsi_Host *first_instance; /* linked list of 5380's */
#define dprintk(a,b) do {} while(0)
#define NCR5380_dprint(a,b) do {} while(0)
#define NCR5380_dprint_phase(a,b) do {} while(0)
#if defined(AUTOPROBE_IRQ) #if defined(AUTOPROBE_IRQ)
static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible); static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
#endif #endif
static void NCR5380_init (struct Scsi_Host *instance, int flags); static void NCR5380_init(struct Scsi_Host *instance, int flags);
static void NCR5380_information_transfer (struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance);
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
static void NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs); static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
static void do_NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs); static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
#endif #endif
static void NCR5380_main (void); static void NCR5380_main(void);
static void NCR5380_print_options (struct Scsi_Host *instance); static void NCR5380_print_options(struct Scsi_Host *instance);
static void NCR5380_print_phase (struct Scsi_Host *instance); static void NCR5380_print_phase(struct Scsi_Host *instance);
static void NCR5380_print (struct Scsi_Host *instance); static void NCR5380_print(struct Scsi_Host *instance);
#ifndef NCR5380_abort #ifndef NCR5380_abort
static static
#endif #endif
int NCR5380_abort (Scsi_Cmnd *cmd); int NCR5380_abort(Scsi_Cmnd * cmd);
#ifndef NCR5380_reset #ifndef NCR5380_reset
static static
#endif #endif
int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags); int NCR5380_reset(Scsi_Cmnd * cmd, unsigned int reset_flags);
#ifndef NCR5380_queue_command #ifndef NCR5380_queue_command
static static
#endif #endif
int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
static void NCR5380_reselect (struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance);
static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag); static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL) #if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL)
static int NCR5380_transfer_dma (struct Scsi_Host *instance, static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
unsigned char *phase, int *count, unsigned char **data);
#endif #endif
static int NCR5380_transfer_pio (struct Scsi_Host *instance, static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
unsigned char *phase, int *count, unsigned char **data);
#if (defined(REAL_DMA) || defined(REAL_DMA_POLL)) #if (defined(REAL_DMA) || defined(REAL_DMA_POLL))
#if defined(i386) || defined(__alpha__) #if defined(i386) || defined(__alpha__)
static __inline__ int NCR5380_pc_dma_setup (struct Scsi_Host *instance, /**
unsigned char *ptr, unsigned int count, unsigned char mode) { * NCR5380_pc_dma_setup - setup ISA DMA
* @instance: adapter to set up
* @ptr: block to transfer (virtual address)
* @count: number of bytes to transfer
* @mode: DMA controller mode to use
*
* Program the DMA controller ready to perform an ISA DMA transfer
* on this chip.
*
* Locks: takes and releases the ISA DMA lock.
*/
static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned char *ptr, unsigned int count, unsigned char mode)
{
unsigned limit; unsigned limit;
unsigned long bus_addr = virt_to_bus(ptr); unsigned long bus_addr = virt_to_bus(ptr);
unsigned long flags;
if (instance->dma_channel <=3) { if (instance->dma_channel <= 3) {
if (count > 65536) if (count > 65536)
count = 65536; count = 65536;
limit = 65536 - (bus_addr & 0xFFFF); limit = 65536 - (bus_addr & 0xFFFF);
} else { } else {
if (count > 65536 * 2) if (count > 65536 * 2)
count = 65536 * 2; count = 65536 * 2;
limit = 65536* 2 - (bus_addr & 0x1FFFF); limit = 65536 * 2 - (bus_addr & 0x1FFFF);
} }
if (count > limit) count = limit; if (count > limit)
count = limit;
if ((count & 1) || (bus_addr & 1)) if ((count & 1) || (bus_addr & 1))
panic ("scsi%d : attempted unaligned DMA transfer\n", instance->host_no); panic("scsi%d : attempted unaligned DMA transfer\n", instance->host_no);
cli();
flags=claim_dma_lock();
disable_dma(instance->dma_channel); disable_dma(instance->dma_channel);
clear_dma_ff(instance->dma_channel); clear_dma_ff(instance->dma_channel);
set_dma_addr(instance->dma_channel, bus_addr); set_dma_addr(instance->dma_channel, bus_addr);
set_dma_count(instance->dma_channel, count); set_dma_count(instance->dma_channel, count);
set_dma_mode(instance->dma_channel, mode); set_dma_mode(instance->dma_channel, mode);
enable_dma(instance->dma_channel); enable_dma(instance->dma_channel);
sti(); release_dma_lock(flags);
return count; return count;
} }
static __inline__ int NCR5380_pc_dma_write_setup (struct Scsi_Host *instance, /**
unsigned char *src, unsigned int count) { * NCR5380_pc_dma_write_setup - setup ISA DMA write
return NCR5380_pc_dma_setup (instance, src, count, DMA_MODE_WRITE); * @instance: adapter to set up
* @ptr: block to transfer (virtual address)
* @count: number of bytes to transfer
*
* Program the DMA controller ready to perform an ISA DMA write to the
* SCSI controller.
*
* Locks: called routines take and release the ISA DMA lock.
*/
static __inline__ int NCR5380_pc_dma_write_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
{
return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_WRITE);
} }
static __inline__ int NCR5380_pc_dma_read_setup (struct Scsi_Host *instance, /**
unsigned char *src, unsigned int count) { * NCR5380_pc_dma_read_setup - setup ISA DMA read
return NCR5380_pc_dma_setup (instance, src, count, DMA_MODE_READ); * @instance: adapter to set up
* @ptr: block to transfer (virtual address)
* @count: number of bytes to transfer
*
* Program the DMA controller ready to perform an ISA DMA read from the
* SCSI controller.
*
* Locks: called routines take and release the ISA DMA lock.
*/
static __inline__ int NCR5380_pc_dma_read_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
{
return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_READ);
} }
static __inline__ int NCR5380_pc_dma_residual (struct Scsi_Host *instance) { /**
register int tmp; * NCR5380_pc_dma_residual - return bytes left
cli(); * @instance: adapter
*
* Reports the number of bytes left over after the DMA was terminated.
*
* Locks: takes and releases the ISA DMA lock.
*/
static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance)
{
unsigned long flags;
int tmp;
flags = claim_dma_lock();
clear_dma_ff(instance->dma_channel); clear_dma_ff(instance->dma_channel);
tmp = get_dma_residue(instance->dma_channel); tmp = get_dma_residue(instance->dma_channel);
sti(); release_dma_lock(flags);
return tmp; return tmp;
} }
#endif /* defined(i386) || defined(__alpha__) */ #endif /* defined(i386) || defined(__alpha__) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment