Commit 98fb18b1 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] NCR5380 port to 2.5 first pass

There is still more work to do, the driver sucks in 2.4 and 2.5 but 2.5 has a
lot more of what is needed to make it work nicely. Basically NCR5380_main
probably has to become a thread in the next generation of the code.

This however seems to get it up and crawling
parent 99916cf4
...@@ -396,24 +396,21 @@ mrs[] = { ...@@ -396,24 +396,21 @@ mrs[] = {
* *
* Print the SCSI bus signals for debugging purposes * Print the SCSI bus signals for debugging purposes
* *
* Locks: none * Locks: caller holds hostdata lock (not essential)
*/ */
static void NCR5380_print(struct Scsi_Host *instance) static void NCR5380_print(struct Scsi_Host *instance)
{ {
NCR5380_local_declare(); NCR5380_local_declare();
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);
cli();
data = NCR5380_read(CURRENT_SCSI_DATA_REG); data = NCR5380_read(CURRENT_SCSI_DATA_REG);
status = NCR5380_read(STATUS_REG); status = NCR5380_read(STATUS_REG);
mr = NCR5380_read(MODE_REG); mr = NCR5380_read(MODE_REG);
icr = NCR5380_read(INITIATOR_COMMAND_REG); icr = NCR5380_read(INITIATOR_COMMAND_REG);
basr = NCR5380_read(BUS_AND_STATUS_REG); basr = NCR5380_read(BUS_AND_STATUS_REG);
restore_flags(flags);
printk("STATUS_REG: %02x ", status); printk("STATUS_REG: %02x ", status);
for (i = 0; signals[i].mask; ++i) for (i = 0; signals[i].mask; ++i)
if (status & signals[i].mask) if (status & signals[i].mask)
...@@ -500,7 +497,8 @@ static unsigned long main_running = 0; ...@@ -500,7 +497,8 @@ static unsigned long main_running = 0;
* request. main_running is checked/set here (in an inline function) * request. main_running is checked/set here (in an inline function)
* rather than in NCR5380_main itself to reduce the chances of stack * rather than in NCR5380_main itself to reduce the chances of stack
* overflow. * overflow.
* * FIXME: NCR5380_main should probably be run with schedule_task or be a
* thread.
*/ */
static __inline__ void run_main(void) static __inline__ void run_main(void)
...@@ -533,6 +531,7 @@ static __inline__ void run_main(void) ...@@ -533,6 +531,7 @@ static __inline__ void run_main(void)
#endif #endif
static struct Scsi_Host *expires_first = NULL; static struct Scsi_Host *expires_first = NULL;
static spinlock_t timer_lock; /* Guards expires list */
/* /*
* Function : int should_disconnect (unsigned char cmd) * Function : int should_disconnect (unsigned char cmd)
...@@ -578,17 +577,21 @@ static int should_disconnect(unsigned char cmd) ...@@ -578,17 +577,21 @@ 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.
* We should move to a timer per host
* *
* Locks: Caller must hold io_request_lock * Locks: Takes the timer queue lock
*/ */
static int NCR5380_set_timer(struct Scsi_Host *instance) static int NCR5380_set_timer(struct Scsi_Host *instance)
{ {
struct Scsi_Host *tmp, **prev; struct Scsi_Host *tmp, **prev;
unsigned long flags;
if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) { if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
return -1; return -1;
} }
spin_lock_irqsave(&timer_lock, flags);
for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer) for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires) if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
break; break;
...@@ -597,6 +600,8 @@ static int NCR5380_set_timer(struct Scsi_Host *instance) ...@@ -597,6 +600,8 @@ static int NCR5380_set_timer(struct Scsi_Host *instance)
*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);
spin_unlock_irqrestore(&timer_lock, flags);
return 0; return 0;
} }
...@@ -610,15 +615,15 @@ static int NCR5380_set_timer(struct Scsi_Host *instance) ...@@ -610,15 +615,15 @@ static int NCR5380_set_timer(struct Scsi_Host *instance)
* *
* Doing something about unwanted reentrancy here might be useful * Doing something about unwanted reentrancy here might be useful
* *
* Locks: disables irqs, takes and frees io_request_lock * Locks: disables irqs, takes and frees the timer lock
*/ */
static void NCR5380_timer_fn(unsigned long unused) static void NCR5380_timer_fn(unsigned long unused)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
unsigned long flags;
spin_lock_irq(&io_request_lock); spin_lock_irqsave(&timer_lock, flags);
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;
...@@ -631,8 +636,10 @@ static void NCR5380_timer_fn(unsigned long unused) ...@@ -631,8 +636,10 @@ static void NCR5380_timer_fn(unsigned long unused)
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);
} }
spin_unlock_irqrestore(&timer_lock, flags);
run_main(); run_main();
spin_unlock_irq(&io_request_lock);
} }
/** /**
...@@ -648,6 +655,7 @@ static inline void NCR5380_all_init(void) ...@@ -648,6 +655,7 @@ static inline void NCR5380_all_init(void)
dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n")); dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
done = 1; done = 1;
init_timer(&usleep_timer); init_timer(&usleep_timer);
spin_lock_init(&timer_lock);
usleep_timer.function = NCR5380_timer_fn; usleep_timer.function = NCR5380_timer_fn;
} }
} }
...@@ -777,7 +785,7 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance) ...@@ -777,7 +785,7 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
* Print commands in the various queues, called from NCR5380_abort * Print commands in the various queues, called from NCR5380_abort
* and NCR5380_debug to aid debugging. * and NCR5380_debug to aid debugging.
* *
* Locks: called functions disable irqs, missing queue lock in proc call * Locks: called functions disable irqs
*/ */
static void NCR5380_print_status(struct Scsi_Host *instance) static void NCR5380_print_status(struct Scsi_Host *instance)
...@@ -872,7 +880,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int ...@@ -872,7 +880,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
#ifdef PAS16_PUBLIC_RELEASE #ifdef PAS16_PUBLIC_RELEASE
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi); SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
#endif #endif
spin_lock_irq(&io_request_lock); spin_lock_irq(instance->host_lock);
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);
...@@ -886,7 +894,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int ...@@ -886,7 +894,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
spin_unlock_irq(&io_request_lock); spin_unlock_irq(instance->host_lock);
*start = buffer; *start = buffer;
if (pos - buffer < offset) if (pos - buffer < offset)
...@@ -1131,6 +1139,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1131,6 +1139,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail")); dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
/* Run the coroutine if it isn't already running. */ /* Run the coroutine if it isn't already running. */
/* FIMXE: drop any locks here */
run_main(); run_main();
return 0; return 0;
} }
...@@ -1276,20 +1286,22 @@ static void NCR5380_main(void) { ...@@ -1276,20 +1286,22 @@ static void NCR5380_main(void) {
} }
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
#include <linux/blk.h>
#include <linux/spinlock.h>
/** /**
* NCR5380_intr - generic NCR5380 irq handler * NCR5380_intr - generic NCR5380 irq handler
* @irq: interrupt number
* @dev_id: device info
* @regs: registers (unused)
* *
* 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.
* *
* Locks: caller must hold the io_request lock. * Locks: takes the needed instance locks
*/ */
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)
{
NCR5380_local_declare(); NCR5380_local_declare();
struct Scsi_Host *instance; struct Scsi_Host *instance;
int done; int done;
...@@ -1299,9 +1311,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1299,9 +1311,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
do { do {
done = 1; done = 1;
/* The instance list is constant while the driver is
loaded */
for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next) for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)
{
if (instance->irq == irq) { if (instance->irq == irq) {
spin_lock_irq(instance->host_lock);
/* Look for pending interrupts */ /* Look for pending interrupts */
NCR5380_setup(instance); NCR5380_setup(instance);
basr = NCR5380_read(BUS_AND_STATUS_REG); basr = NCR5380_read(BUS_AND_STATUS_REG);
...@@ -1343,15 +1358,19 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1343,15 +1358,19 @@ 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(&io_request_lock); spin_unlock_irq(instance->host_lock);
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout)); /* FIXME: prove timer is always running here! */
spin_lock_irq(&io_request_lock); while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout))
cpu_relax();
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", host->host_no, __LINE__); printk("scsi%d: timeout at NCR5380.c:%d\n", 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)
cpu_relax();
#endif #endif
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
...@@ -1363,33 +1382,15 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1363,33 +1382,15 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
#endif #endif
} }
} /* if BASR_IRQ */ } /* if BASR_IRQ */
spin_unlock_irq(instance->host_lock);
if (!done) if (!done)
run_main(); run_main();
} /* if (instance->irq == irq) */ } /* if (instance->irq == irq) */
}
} while (!done); } while (!done);
} }
/** #endif
* 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) {
unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags);
NCR5380_intr(irq, dev_id, regs);
spin_unlock_irqrestore(&io_request_lock, flags);
}
#endif
/** /**
* collect_stats - collect stats on a scsi command * collect_stats - collect stats on a scsi command
...@@ -1450,7 +1451,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) ...@@ -1450,7 +1451,7 @@ 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 * Locks: caller holds hostdata 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)
...@@ -1493,12 +1494,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1493,12 +1494,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
{ {
unsigned long timeout = jiffies + 2 * NCR_TIMEOUT; unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;
spin_unlock_irq(&io_request_lock); spin_unlock_irq(instance->host_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))
cpu_relax();
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: arbitration timeout at %d\n", __LINE__); printk("scsi: arbitration timeout at %d\n", __LINE__);
...@@ -1624,6 +1626,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1624,6 +1626,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);
/* FIXME HZ=100 assumption ? */
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 */
...@@ -1692,9 +1695,10 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1692,9 +1695,10 @@ 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(&io_request_lock); spin_unlock_irq(instance->host_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(&io_request_lock); cpu_relax();
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", instance->host_no, __LINE__); printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
...@@ -1703,7 +1707,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1703,7 +1707,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
} }
} }
#else /* NCR_TIMEOUT */ #else /* NCR_TIMEOUT */
while (!(NCR5380_read(STATUS_REG) & SR_REQ)); while (!(NCR5380_read(STATUS_REG) & SR_REQ))
cpu_relax();
#endif /* def NCR_TIMEOUT */ #endif /* def NCR_TIMEOUT */
dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target)); dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
...@@ -1886,7 +1891,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase ...@@ -1886,7 +1891,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
* Issue a reset sequence to the NCR5380 and try and get the bus * Issue a reset sequence to the NCR5380 and try and get the bus
* back into sane shape. * back into sane shape.
* *
* Locks: caller holds io_request lock * Locks: caller holds queue lock
* FIXME: sort this out and get new_eh running
*/ */
static void do_reset(struct Scsi_Host *host) { static void do_reset(struct Scsi_Host *host) {
...@@ -1907,7 +1913,8 @@ static void do_reset(struct Scsi_Host *host) { ...@@ -1907,7 +1913,8 @@ static void do_reset(struct Scsi_Host *host) {
* *
* Returns : 0 on success, -1 on failure. * Returns : 0 on success, -1 on failure.
* *
* Locks: io_request lock held by caller * Locks: queue lock held by caller
* FIXME: sort this out and get new_eh running
*/ */
static int do_abort(struct Scsi_Host *host) { static int do_abort(struct Scsi_Host *host) {
...@@ -1930,7 +1937,8 @@ static int do_abort(struct Scsi_Host *host) { ...@@ -1930,7 +1937,8 @@ static int do_abort(struct Scsi_Host *host) {
* the target sees, so we just handshake. * the target sees, so we just handshake.
*/ */
while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ); while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
cpu_relax();
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
...@@ -2019,7 +2027,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase ...@@ -2019,7 +2027,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
*/ */
#if defined(PSEUDO_DMA) && defined(UNSAFE) #if defined(PSEUDO_DMA) && defined(UNSAFE)
spin_unlock_irq(&io_request_lock); spin_unlock_irq(instance->host_lock);
#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)
...@@ -2228,7 +2236,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase ...@@ -2228,7 +2236,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
*count = 0; *count = 0;
*phase = NCR5380_read(STATUS_REG) & PHASE_MASK; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
#if defined(PSEUDO_DMA) && defined(UNSAFE) #if defined(PSEUDO_DMA) && defined(UNSAFE)
spin_lock_irq(&io_request_lock); spin_lock_irq(instance->host_lock);
#endif /* defined(REAL_DMA_POLL) */ #endif /* defined(REAL_DMA_POLL) */
return foo; return foo;
#endif /* def REAL_DMA */ #endif /* def REAL_DMA */
...@@ -2707,9 +2715,11 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -2707,9 +2715,11 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
/* /*
* Wait for target to go into MSGIN. * Wait for target to go into MSGIN.
* FIXME: timeout needed
*/ */
while (!(NCR5380_read(STATUS_REG) & SR_REQ)); while (!(NCR5380_read(STATUS_REG) & SR_REQ))
cpu_relax();
len = 1; len = 1;
data = msg; data = msg;
...@@ -2843,12 +2853,12 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2843,12 +2853,12 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
Scsi_Cmnd *tmp, **prev; Scsi_Cmnd *tmp, **prev;
printk("scsi%d : aborting command\n", instance->host_no); printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
print_Scsi_Cmnd(cmd); print_Scsi_Cmnd(cmd);
NCR5380_print_status(instance); NCR5380_print_status(instance);
printk("scsi%d : aborting command\n", instance->host_no); printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
print_Scsi_Cmnd(cmd); print_Scsi_Cmnd(cmd);
NCR5380_print_status(instance); NCR5380_print_status(instance);
...@@ -2893,6 +2903,8 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2893,6 +2903,8 @@ 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.
*/ */
/* FIXME: check - I think we need the hostdata lock here */
/* KLL */ /* KLL */
dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
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)
...@@ -2903,12 +2915,12 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2903,12 +2915,12 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->result = DID_ABORT << 16; tmp->result = DID_ABORT << 16;
dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
tmp->done(tmp); tmp->done(tmp);
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
#if (NDEBUG & NDEBUG_ABORT) #if (NDEBUG & NDEBUG_ABORT)
/* KLL */ /* KLL */
else if (prev == tmp) else if (prev == tmp)
printk("scsi%d : LOOP\n", instance->host_no); printk(KERN_ERR "scsi%d : LOOP\n", instance->host_no);
#endif #endif
/* /*
...@@ -2924,7 +2936,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2924,7 +2936,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
if (hostdata->connected) { if (hostdata->connected) {
dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
return SCSI_ABORT_NOT_RUNNING; return FAILED;
} }
/* /*
* Case 4: If the command is currently disconnected from the bus, and * Case 4: If the command is currently disconnected from the bus, and
...@@ -2956,7 +2968,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2956,7 +2968,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no));
if (NCR5380_select(instance, cmd, (int) cmd->tag)) if (NCR5380_select(instance, cmd, (int) cmd->tag))
return SCSI_ABORT_BUSY; return FAILED;
dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no));
do_abort(instance); do_abort(instance);
...@@ -2968,7 +2980,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2968,7 +2980,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->host_scribble = NULL; tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16; tmp->result = DID_ABORT << 16;
tmp->done(tmp); tmp->done(tmp);
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
} }
/* /*
...@@ -2980,30 +2992,68 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2980,30 +2992,68 @@ 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); printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no);
return SCSI_ABORT_NOT_RUNNING; return FAILED;
} }
/* /*
* Function : int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) * Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd)
* *
* Purpose : reset the SCSI bus. * Purpose : reset the SCSI bus.
* *
* Returns : SCSI_RESET_WAKEUP * Returns : SUCCESS
* *
* Locks: io_request_lock held by caller * Locks: io_request_lock held by caller
*/ */
#ifndef NCR5380_reset #ifndef NCR5380_bus_reset
static static
#endif #endif
int NCR5380_reset(Scsi_Cmnd * cmd, unsigned int dummy) { int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare(); NCR5380_local_declare();
NCR5380_setup(cmd->host); NCR5380_setup(cmd->host);
NCR5380_print_status(cmd->host); NCR5380_print_status(cmd->host);
do_reset(cmd->host); do_reset(cmd->host);
return SCSI_RESET_WAKEUP; return SUCCESS;
}
/*
* Function : int NCR5380_device_reset (Scsi_Cmnd *cmd)
*
* Purpose : reset a SCSI device
*
* Returns : FAILED
*
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_device_reset
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
return FAILED;
}
/*
* Function : int NCR5380_host_reset (Scsi_Cmnd *cmd)
*
* Purpose : reset a SCSI device
*
* Returns : FAILED
*
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_host_reset
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
return FAILED;
} }
...@@ -304,10 +304,18 @@ static void NCR5380_print(struct Scsi_Host *instance); ...@@ -304,10 +304,18 @@ static void NCR5380_print(struct Scsi_Host *instance);
static static
#endif #endif
int NCR5380_abort(Scsi_Cmnd * cmd); int NCR5380_abort(Scsi_Cmnd * cmd);
#ifndef NCR5380_reset #ifndef NCR5380_bus_reset
static static
#endif #endif
int NCR5380_reset(Scsi_Cmnd * cmd, unsigned int reset_flags); int NCR5380_bus_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_host_reset
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_device_reset
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_queue_command #ifndef NCR5380_queue_command
static static
#endif #endif
......
...@@ -779,15 +779,15 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng ...@@ -779,15 +779,15 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng
Scsi_Device *dev; Scsi_Device *dev;
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#endif #endif
save_flags(flags);
cli();
/* For now this is constant so we may walk it */
for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr = scsi_ptr->next) for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr = scsi_ptr->next)
if (scsi_ptr->host_no == hostno) if (scsi_ptr->host_no == hostno)
break; break;
NCR5380_setup(scsi_ptr); NCR5380_setup(scsi_ptr);
hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata; hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
spin_lock_irqsave(scsi_ptr->host_lock, flags);
PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name); PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE); PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE); PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
...@@ -874,7 +874,7 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng ...@@ -874,7 +874,7 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng
len -= offset; len -= offset;
if (len > length) if (len > length)
len = length; len = length;
restore_flags(flags); spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
return len; return len;
} }
......
...@@ -48,7 +48,9 @@ int generic_NCR5380_abort(Scsi_Cmnd *); ...@@ -48,7 +48,9 @@ int generic_NCR5380_abort(Scsi_Cmnd *);
int generic_NCR5380_detect(Scsi_Host_Template *); int generic_NCR5380_detect(Scsi_Host_Template *);
int generic_NCR5380_release_resources(struct Scsi_Host *); int generic_NCR5380_release_resources(struct Scsi_Host *);
int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int generic_NCR5380_reset(Scsi_Cmnd *, unsigned int); int generic_NCR5380_bus_reset(Scsi_Cmnd *);
int generic_NCR5380_host_reset(Scsi_Cmnd *);
int generic_NCR5380_device_reset(Scsi_Cmnd *);
int notyet_generic_proc_info (char *buffer ,char **start, off_t offset, int notyet_generic_proc_info (char *buffer ,char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
const char* generic_NCR5380_info(struct Scsi_Host *); const char* generic_NCR5380_info(struct Scsi_Host *);
...@@ -77,8 +79,10 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng ...@@ -77,8 +79,10 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
release: generic_NCR5380_release_resources, \ release: generic_NCR5380_release_resources, \
info: (void *)generic_NCR5380_info, \ info: (void *)generic_NCR5380_info, \
queuecommand: generic_NCR5380_queue_command, \ queuecommand: generic_NCR5380_queue_command, \
abort: generic_NCR5380_abort, \ eh_abort_handler:generic_NCR5380_abort, \
reset: generic_NCR5380_reset, \ eh_bus_reset_handler:generic_NCR5380_bus_reset, \
eh_device_reset_handler:generic_NCR5380_device_reset, \
eh_host_reset_handler:generic_NCR5380_host_reset, \
bios_param: NCR5380_BIOSPARAM, \ bios_param: NCR5380_BIOSPARAM, \
can_queue: CAN_QUEUE, \ can_queue: CAN_QUEUE, \
this_id: 7, \ this_id: 7, \
...@@ -154,7 +158,9 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng ...@@ -154,7 +158,9 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
#define do_NCR5380_intr do_generic_NCR5380_intr #define do_NCR5380_intr do_generic_NCR5380_intr
#define NCR5380_queue_command generic_NCR5380_queue_command #define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort #define NCR5380_abort generic_NCR5380_abort
#define NCR5380_reset generic_NCR5380_reset #define NCR5380_bus_reset generic_NCR5380_bus_reset
#define NCR5380_device_reset generic_NCR5380_device_reset
#define NCR5380_host_reset generic_NCR5380_host_reset
#define NCR5380_pread generic_NCR5380_pread #define NCR5380_pread generic_NCR5380_pread
#define NCR5380_pwrite generic_NCR5380_pwrite #define NCR5380_pwrite generic_NCR5380_pwrite
#define NCR5380_proc_info notyet_generic_proc_info #define NCR5380_proc_info notyet_generic_proc_info
......
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