/*
* Design
- * Issues :
*
- * The other Linux SCSI drivers were written when Linux was Intel PC-only,
- * and specifically for each board rather than each chip. This makes their
- * adaptation to platforms like the Mac (Some of which use NCR5380's)
- * more difficult than it has to be.
- *
- * Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued
- * commands were hacked on rather than designed in from the start.
- *
- * When I designed the Linux SCSI drivers I figured that
- * while having two different SCSI boards in a system might be useful
- * for debugging things, two of the same type wouldn't be used.
- * Well, I was wrong and a number of users have mailed me about running
- * multiple high-performance SCSI boards in a server.
- *
- * Finally, when I get questions from users, I have no idea what
- * revision of my driver they are running.
- *
- * This driver attempts to address these problems :
* This is a generic 5380 driver. To use it on a different platform,
* one simply writes appropriate system specific macros (ie, data
* transfer - some PC's will use the I/O bus, 68K's must use
* allowing multiple commands to propagate all the way to a SCSI-II device
* while a command is already executing.
*
- * To solve the multiple-boards-in-the-same-system problem,
- * there is a separate instance structure for each instance
- * of a 5380 in the system. So, multiple NCR5380 drivers will
- * be able to coexist with appropriate changes to the high level
- * SCSI code.
*
* Issues specific to the NCR5380 :
*
* Architecture :
*
* At the heart of the design is a coroutine, NCR5380_main,
- * which is started when not running by the interrupt handler,
- * timer, and queue command function. It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the
- * issue queue and calling NCR5380_select() if a nexus
- * is not established.
+ * which is started from a workqueue for each NCR5380 host in the
+ * system. It attempts to establish I_T_L or I_T_L_Q nexuses by
+ * removing the commands from the issue queue and calling
+ * NCR5380_select() if a nexus is not established.
*
* Once a nexus is established, the NCR5380_information_transfer()
* phase goes through the various phases as instructed by the target.
* if the target goes into MSG IN and sends a DISCONNECT message,
* the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work. If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
+ * queue, and NCR5380_main tries to find more work. If the target is
+ * idle for too long, the system will try to sleep.
*
* If a command has disconnected, eventually an interrupt will trigger,
* calling NCR5380_intr() which will in turn call NCR5380_reselect
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
* for commands that return with a CHECK CONDITION status.
*
+ * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
+ * transceivers.
+ *
* LINKED - if defined, linked commands are supported.
*
* REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
*
* NCR5380_write(register, value) - write to the specific register
*
+ * NCR5380_implementation_fields - additional fields needed for this
+ * specific implementation of the NCR5380
+ *
* Either real DMA *or* pseudo DMA may be implemented
* REAL functions :
* NCR5380_REAL_DMA should be defined if real DMA is to be used.
* NCR5380_pwrite(instance, src, count)
* NCR5380_pread(instance, dst, count);
*
- * If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define
- *
- * NCR5380_queue_command
- * NCR5380_reset
- * NCR5380_abort
- *
- * to be the global entry points into the specific driver, ie
- * #define NCR5380_queue_command t128_queue_command.
- *
- * If this is not done, the routines will be defined as static functions
- * with the NCR5380* names and the user must provide a globally
- * accessible wrapper function.
- *
* The generic driver is initialized by calling NCR5380_init(instance),
* after setting the appropriate host specific fields and ID. If the
* driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
* possible) function may be used.
*/
-static struct Scsi_Host *first_instance = NULL;
-static struct scsi_host_template *the_template = NULL;
-
/* Macros ease life... :-) */
#define SETUP_HOSTDATA(in) \
struct NCR5380_hostdata *hostdata = \
* important: the tag bit must be cleared before 'nr_allocated' is decreased.
*/
-typedef struct {
- DECLARE_BITMAP(allocated, MAX_TAGS);
- int nr_allocated;
- int queue_size;
-} TAG_ALLOC;
-
-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
-
-
-static void __init init_tags(void)
+static void __init init_tags(struct NCR5380_hostdata *hostdata)
{
int target, lun;
- TAG_ALLOC *ta;
+ struct tag_alloc *ta;
- if (!setup_use_tagged_queuing)
+ if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
return;
for (target = 0; target < 8; ++target) {
for (lun = 0; lun < 8; ++lun) {
- ta = &TagAlloc[target][lun];
+ ta = &hostdata->TagAlloc[target][lun];
bitmap_zero(ta->allocated, MAX_TAGS);
ta->nr_allocated = 0;
/* At the beginning, assume the maximum queue size we could
if (hostdata->busy[cmd->device->id] & (1 << lun))
return 1;
if (!should_be_tagged ||
- !setup_use_tagged_queuing || !cmd->device->tagged_supported)
+ !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
+ !cmd->device->tagged_supported)
return 0;
- if (TagAlloc[cmd->device->id][lun].nr_allocated >=
- TagAlloc[cmd->device->id][lun].queue_size) {
+ if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >=
+ hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) {
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n",
H_NO(cmd), cmd->device->id, lun);
return 1;
* an untagged command.
*/
if (!should_be_tagged ||
- !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+ !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
+ !cmd->device->tagged_supported) {
cmd->tag = TAG_NONE;
hostdata->busy[cmd->device->id] |= (1 << lun);
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged "
"command\n", H_NO(cmd), cmd->device->id, lun);
} else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
+ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
set_bit(cmd->tag, ta->allocated);
printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
H_NO(cmd), cmd->tag);
} else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
+ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
clear_bit(cmd->tag, ta->allocated);
ta->nr_allocated--;
dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n",
}
-static void free_all_tags(void)
+static void free_all_tags(struct NCR5380_hostdata *hostdata)
{
int target, lun;
- TAG_ALLOC *ta;
+ struct tag_alloc *ta;
- if (!setup_use_tagged_queuing)
+ if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
return;
for (target = 0; target < 8; ++target) {
for (lun = 0; lun < 8; ++lun) {
- ta = &TagAlloc[target][lun];
+ ta = &hostdata->TagAlloc[target][lun];
bitmap_zero(ta->allocated, MAX_TAGS);
ta->nr_allocated = 0;
}
#endif /* !defined(CONFIG_SUN3) */
}
-/*
- * Function : void initialize_SCp(struct scsi_cmnd *cmd)
- *
- * Purpose : initialize the saved data pointers for cmd to point to the
- * start of the buffer.
+/**
+ * initialize_SCp - init the scsi pointer field
+ * @cmd: command block to set up
*
- * Inputs : cmd - scsi_cmnd structure to have pointers reset.
+ * Set up the internal fields in the SCSI command.
*/
static inline void initialize_SCp(struct scsi_cmnd *cmd)
{0, NULL}
};
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
- *
- * Purpose : print the SCSI bus signals for debugging purposes
+/**
+ * NCR5380_print - print scsi bus signals
+ * @instance: adapter state to dump
*
- * Input : instance - which NCR5380
+ * Print the SCSI bus signals for debugging purposes
*/
static void NCR5380_print(struct Scsi_Host *instance)
{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)
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-static volatile int main_running;
-static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
-
-static inline void queue_main(void)
+static inline void queue_main(struct NCR5380_hostdata *hostdata)
{
- if (!main_running) {
+ if (!hostdata->main_running) {
/* If in interrupt and NCR5380_main() not already running,
queue it on the 'immediate' task queue, to be processed
immediately after the current interrupt processing has
finished. */
- schedule_work(&NCR5380_tqueue);
+ schedule_work(&hostdata->main_task);
}
/* else: nothing to do: the running NCR5380_main() will pick up
any newly queued command. */
}
-
-static inline void NCR5380_all_init(void)
-{
- static int done = 0;
- if (!done) {
- dprintk(NDEBUG_INIT, "scsi : NCR5380_all_init()\n");
- done = 1;
- }
-}
-
/**
* NCR58380_info - report driver and host information
* @instance: relevant scsi host instance
"base 0x%lx, irq %d, "
"can_queue %d, cmd_per_lun %d, "
"sg_tablesize %d, this_id %d, "
+ "flags { %s}, "
"options { %s} ",
instance->hostt->name, instance->io_port, instance->n_io_port,
instance->base, instance->irq,
instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
+ hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "",
#ifdef DIFFERENTIAL
"DIFFERENTIAL "
#endif
"");
}
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
- *
- * Purpose : print commands in the various queues, called from
- * NCR5380_abort and NCR5380_debug to aid debugging.
+/**
+ * NCR5380_print_status - dump controller info
+ * @instance: controller to dump
*
- * Inputs : instance, pointer to this instance.
+ * Print commands in the various queues, called from NCR5380_abort
+ * to aid debugging.
*/
static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd)
local_irq_save(flags);
printk("NCR5380: coroutine is%s running.\n",
- main_running ? "" : "n't");
+ hostdata->main_running ? "" : "n't");
if (!hostdata->connected)
printk("scsi%d: no currently connected command\n", HOSTNO);
else
local_irq_save(flags);
seq_printf(m, "NCR5380: coroutine is%s running.\n",
- main_running ? "" : "n't");
+ hostdata->main_running ? "" : "n't");
if (!hostdata->connected)
seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
else
return 0;
}
-/*
- * Function : void NCR5380_init (struct Scsi_Host *instance)
- *
- * Purpose : initializes *instance and corresponding 5380 chip.
+/**
+ * NCR5380_init - initialise an NCR5380
+ * @instance: adapter to configure
+ * @flags: control flags
*
- * Inputs : instance - instantiation of the 5380 driver.
+ * Initializes *instance and corresponding 5380 chip,
+ * with flags OR'd into the initial flags value.
*
* 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.
*
+ * Returns 0 for success
*/
static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
int i;
SETUP_HOSTDATA(instance);
- NCR5380_all_init();
-
+ hostdata->host = instance;
hostdata->aborted = 0;
hostdata->id_mask = 1 << instance->this_id;
hostdata->id_higher_mask = 0;
for (i = 0; i < 8; ++i)
hostdata->busy[i] = 0;
#ifdef SUPPORT_TAGS
- init_tags();
+ init_tags(hostdata);
#endif
#if defined (REAL_DMA)
hostdata->dma_len = 0;
hostdata->disconnected_queue = NULL;
hostdata->flags = flags;
- if (!the_template) {
- the_template = instance->hostt;
- first_instance = instance;
- }
+ INIT_WORK(&hostdata->main_task, NCR5380_main);
prepare_info(instance);
return 0;
}
+/**
+ * NCR5380_exit - remove an NCR5380
+ * @instance: adapter to remove
+ *
+ * Assumes that no more work can be queued (e.g. by NCR5380_intr).
+ */
+
static void NCR5380_exit(struct Scsi_Host *instance)
{
- /* Empty, as we didn't schedule any delayed work */
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ cancel_work_sync(&hostdata->main_task);
}
-/*
- * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd,
- * void (*done)(struct scsi_cmnd *))
- *
- * 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
- * twiddling done to the host specific fields of cmd. If the
- * main coroutine is not running, it is restarted.
+/**
+ * NCR5380_queue_command - queue a command
+ * @instance: the relevant SCSI adapter
+ * @cmd: SCSI command
*
+ * cmd is added to the per instance issue_queue, with minor
+ * twiddling done to the host specific fields of cmd. If the
+ * main coroutine is not running, it is restarted.
*/
static int NCR5380_queue_command(struct Scsi_Host *instance,
local_irq_save(flags);
+ /*
+ * Insert the cmd into the issue queue. Note that REQUEST SENSE
+ * commands are added to the head of the queue since any command will
+ * clear the contingent allegiance condition that exists and the
+ * sense data is only guaranteed to be valid while the condition exists.
+ */
+
if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
LIST(cmd, hostdata->issue_queue);
SET_NEXT(cmd, hostdata->issue_queue);
* unconditionally, because it cannot be already running.
*/
if (in_interrupt() || irqs_disabled())
- queue_main();
+ queue_main(hostdata);
else
- NCR5380_main(NULL);
+ NCR5380_main(&hostdata->main_task);
return 0;
}
NCR5380_release_dma_irq(instance);
}
-/*
- * Function : NCR5380_main (void)
+/**
+ * NCR5380_main - NCR state machines
*
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can
- * be done on the NCR5380 host adapters in a system. Both
- * NCR5380_queue_command() and NCR5380_intr() will try to start it
- * in case it is not running.
+ * NCR5380_main is a coroutine that runs as long as more work can
+ * be done on the NCR5380 host adapters in a system. Both
+ * NCR5380_queue_command() and NCR5380_intr() will try to start it
+ * in case it is not running.
*
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
- * reenable them. This prevents reentrancy and kernel stack overflow.
+ * Locks: called as its own thread with no locks held.
*/
static void NCR5380_main(struct work_struct *work)
{
+ struct NCR5380_hostdata *hostdata =
+ container_of(work, struct NCR5380_hostdata, main_task);
+ struct Scsi_Host *instance = hostdata->host;
struct scsi_cmnd *tmp, *prev;
- struct Scsi_Host *instance = first_instance;
- struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
int done;
unsigned long flags;
'main_running' is set here, and queues/executes main via the
task queue, it doesn't do any harm, just this instance of main
won't find any work left to do. */
- if (main_running)
+ if (hostdata->main_running)
return;
- main_running = 1;
+ hostdata->main_running = 1;
local_save_flags(flags);
do {
/* Better allow ints _after_ 'main_running' has been cleared, else
an interrupt could believe we'll pick up the work it left for
us, but we won't see it anymore here... */
- main_running = 0;
+ hostdata->main_running = 0;
local_irq_restore(flags);
}
static void NCR5380_dma_complete(struct Scsi_Host *instance)
{
SETUP_HOSTDATA(instance);
- int transfered;
+ int transferred;
unsigned char **data;
volatile int *count;
int saved_data = 0, overrun = 0;
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+ transferred = hostdata->dma_len - NCR5380_dma_residual(instance);
hostdata->dma_len = 0;
data = (unsigned char **)&hostdata->connected->SCp.ptr;
count = &hostdata->connected->SCp.this_residual;
- *data += transfered;
- *count -= transfered;
+ *data += transferred;
+ *count -= transferred;
if (hostdata->read_overruns) {
int cnt, toPIO;
#endif /* REAL_DMA */
-/*
- * Function : void NCR5380_intr (int irq)
- *
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- * from the disconnected queue, and restarting NCR5380_main()
- * as required.
- *
- * Inputs : int irq, irq that caused this interrupt.
+/**
+ * NCR5380_intr - generic NCR5380 irq handler
+ * @irq: interrupt number
+ * @dev_id: device info
*
+ * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+ * from the disconnected queue, and restarting NCR5380_main()
+ * as required.
*/
static irqreturn_t NCR5380_intr(int irq, void *dev_id)
{
- struct Scsi_Host *instance = first_instance;
+ struct Scsi_Host *instance = dev_id;
int done = 1, handled = 0;
unsigned char basr;
if (!done) {
dprintk(NDEBUG_INTR, "scsi%d: in int routine, calling main\n", HOSTNO);
/* Put a call to NCR5380_main() on the queue... */
- queue_main();
+ queue_main(shost_priv(instance));
}
return IRQ_RETVAL(handled);
}
* selection.
*/
- timeout = jiffies + 25;
+ timeout = jiffies + (250 * HZ / 1000);
/*
* XXX very interesting - we're seeing a bounce where the BSY we
* Returns : 0 on success, -1 on failure.
*/
-static int do_abort(struct Scsi_Host *host)
+static int do_abort(struct Scsi_Host *instance)
{
unsigned char tmp, *msgptr, phase;
int len;
msgptr = &tmp;
len = 1;
phase = PHASE_MSGOUT;
- NCR5380_transfer_pio(host, &phase, &len, &msgptr);
+ NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
/*
* If we got here, and the command completed successfully,
* If the watchdog timer fires, all future
* accesses to this device will use the
* polled-IO. */
- printk(KERN_NOTICE "scsi%d: switching target %d "
- "lun %llu to slow handshake\n", HOSTNO,
- cmd->device->id, cmd->device->lun);
+ scmd_printk(KERN_INFO, cmd,
+ "switching to slow handshake\n");
cmd->device->borken = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_ATN);
*/
/* ++Andreas: the mid level code knows about
QUEUE_FULL now. */
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][cmd->device->lun];
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
"QUEUE_FULL after %d commands\n",
HOSTNO, cmd->device->id, cmd->device->lun,
*/
default:
if (!tmp) {
- printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+ printk(KERN_INFO "scsi%d: rejecting message ",
+ instance->host_no);
spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
- printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "message %02x from target %d, lun %llu\n",
- HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+ scmd_printk(KERN_INFO, cmd,
+ "rejecting unknown message %02x\n",
+ tmp);
else
- printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "extended message "
- "code %02x, length %d from target %d, lun %llu\n",
- HOSTNO, extended_msg[1], extended_msg[0],
- cmd->device->id, cmd->device->lun);
-
+ scmd_printk(KERN_INFO, cmd,
+ "rejecting unknown extended message code %02x, length %d\n",
+ extended_msg[1], extended_msg[0]);
msgout = MESSAGE_REJECT;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
* SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
*/
tag = TAG_NONE;
- if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+ if (phase == PHASE_MSGIN && (hostdata->flags & FLAG_TAGGED_QUEUING)) {
/* Accept previous IDENTIFY message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
len = 2;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int i;
unsigned long flags;
-#if defined(RESET_RUN_DONE)
- struct scsi_cmnd *connected, *disconnected_queue;
-#endif
NCR5380_print_status(instance);
* through anymore ... */
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- /* MSch 20140115 - looking at the generic NCR5380 driver, all of this
- * should go.
- * Catch-22: if we don't clear all queues, the SCSI driver lock will
- * not be reset by atari_scsi_reset()!
- */
-
-#if defined(RESET_RUN_DONE)
- /* XXX Should now be done by midlevel code, but it's broken XXX */
- /* XXX see below XXX */
-
- /* MSch: old-style reset: actually abort all command processing here */
-
- /* After the reset, there are no more connected or disconnected commands
- * and no busy units; to avoid problems with re-inserting the commands
- * into the issue_queue (via scsi_done()), the aborted commands are
- * remembered in local variables first.
- */
- local_irq_save(flags);
- connected = (struct scsi_cmnd *)hostdata->connected;
- hostdata->connected = NULL;
- disconnected_queue = (struct scsi_cmnd *)hostdata->disconnected_queue;
- hostdata->disconnected_queue = NULL;
-#ifdef SUPPORT_TAGS
- free_all_tags();
-#endif
- for (i = 0; i < 8; ++i)
- hostdata->busy[i] = 0;
-#ifdef REAL_DMA
- hostdata->dma_len = 0;
-#endif
- local_irq_restore(flags);
-
- /* In order to tell the mid-level code which commands were aborted,
- * set the command status to DID_RESET and call scsi_done() !!!
- * This ultimately aborts processing of these commands in the mid-level.
- */
-
- if ((cmd = connected)) {
- dprintk(NDEBUG_ABORT, "scsi%d: reset aborted a connected command\n", H_NO(cmd));
- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
- cmd->scsi_done(cmd);
- }
-
- for (i = 0; (cmd = disconnected_queue); ++i) {
- disconnected_queue = NEXT(cmd);
- SET_NEXT(cmd, NULL);
- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
- cmd->scsi_done(cmd);
- }
- if (i > 0)
- dprintk(NDEBUG_ABORT, "scsi: reset aborted %d disconnected command(s)\n", i);
-
- /* The Falcon lock should be released after a reset...
- */
- /* ++guenther: moved to atari_scsi_reset(), to prevent a race between
- * unlocking and enabling dma interrupt.
- */
-/* falcon_release_lock_if_possible( hostdata );*/
-
- /* since all commands have been explicitly terminated, we need to tell
- * the midlevel code that the reset was SUCCESSFUL, and there is no
- * need to 'wake up' the commands by a request_sense
- */
- return SUCCESS;
-#else /* 1 */
-
- /* MSch: new-style reset handling: let the mid-level do what it can */
-
- /* ++guenther: MID-LEVEL IS STILL BROKEN.
- * Mid-level is supposed to requeue all commands that were active on the
- * various low-level queues. In fact it does this, but that's not enough
- * because all these commands are subject to timeout. And if a timeout
- * happens for any removed command, *_abort() is called but all queues
- * are now empty. Abort then gives up the falcon lock, which is fatal,
- * since the mid-level will queue more commands and must have the lock
- * (it's all happening inside timer interrupt handler!!).
- * Even worse, abort will return NOT_RUNNING for all those commands not
- * on any queue, so they won't be retried ...
- *
- * Conclusion: either scsi.c disables timeout for all resetted commands
- * immediately, or we lose! As of linux-2.0.20 it doesn't.
- */
-
/* After the reset, there are no more connected or disconnected commands
* and no busy units; so clear the low-level status here to avoid
* conflicts when the mid-level code tries to wake up the affected
hostdata->connected = NULL;
hostdata->disconnected_queue = NULL;
#ifdef SUPPORT_TAGS
- free_all_tags();
+ free_all_tags(hostdata);
#endif
for (i = 0; i < 8; ++i)
hostdata->busy[i] = 0;
maybe_release_dma_irq(instance);
local_irq_restore(flags);
- /* we did no complete reset of all commands, so a wakeup is required */
return SUCCESS;
-#endif /* 1 */
}