summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/NCR5380.c22
-rw-r--r--drivers/scsi/NCR5380.h19
-rw-r--r--drivers/scsi/atari_NCR5380.c2632
-rw-r--r--drivers/scsi/atari_scsi.c11
-rw-r--r--drivers/scsi/mac_scsi.c8
-rw-r--r--drivers/scsi/sun3_scsi.c11
6 files changed, 4 insertions, 2699 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index a59b71f96365..305330b26349 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -34,13 +34,6 @@
/* Adapted for the Sun 3 by Sam Creasey. */
/*
- * Further development / testing that should be done :
- *
- * 4. Test SCSI-II tagged queueing (I have no devices which support
- * tagged queueing)
- */
-
-/*
* Design
*
* This is a generic 5380 driver. To use it on a different platform,
@@ -1257,14 +1250,6 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
* was true but before BSY was false during selection, the information
* transfer phase should be a MESSAGE OUT phase so that we can send the
* IDENTIFY message.
- *
- * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
- * message (2 bytes) with a tag ID that we increment with every command
- * until it wraps back to 0.
- *
- * XXX - it turns out that there are some broken SCSI-II devices,
- * which claim to support tagged queuing but fail when more than
- * some number of commands are issued at once.
*/
/* Wait for start of REQ/ACK handshake */
@@ -1287,9 +1272,6 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
len = 1;
- cmd->tag = 0;
-
- /* Send message(s) */
data = tmp;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data);
@@ -2256,8 +2238,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
hostdata->connected = tmp;
- dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n",
- scmd_id(tmp), tmp->device->lun, tmp->tag);
+ dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu\n",
+ scmd_id(tmp), tmp->device->lun);
}
/**
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 8adf7377de4c..5c2411f05852 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -199,13 +199,6 @@
#define PHASE_SR_TO_TCR(phase) ((phase) >> 2)
-/*
- * "Special" value for the (unsigned char) command tag, to indicate
- * I_T_L nexus instead of I_T_L_Q.
- */
-
-#define TAG_NONE 0xff
-
/*
* These are "special" values for the irq and dma_channel fields of the
* Scsi_Host structure
@@ -223,17 +216,8 @@
#define FLAG_DMA_FIXUP 1 /* Use DMA errata workarounds */
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
-#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
#define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */
-#ifdef SUPPORT_TAGS
-struct tag_alloc {
- DECLARE_BITMAP(allocated, MAX_TAGS);
- int nr_allocated;
- int queue_size;
-};
-#endif
-
struct NCR5380_hostdata {
NCR5380_implementation_fields; /* implementation specific */
struct Scsi_Host *host; /* Host backpointer */
@@ -254,9 +238,6 @@ struct NCR5380_hostdata {
int read_overruns; /* number of bytes to cut from a
* transfer to handle chip overruns */
struct work_struct main_task;
-#ifdef SUPPORT_TAGS
- struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */
-#endif
struct workqueue_struct *work_q;
unsigned long accesses_per_ms; /* chip register accesses per ms */
};
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
deleted file mode 100644
index 4101d2de4333..000000000000
--- a/drivers/scsi/atari_NCR5380.c
+++ /dev/null
@@ -1,2632 +0,0 @@
-/*
- * NCR 5380 generic driver routines. These should make it *trivial*
- * to implement 5380 SCSI drivers under Linux with a non-trantor
- * architecture.
- *
- * Note that these routines also work with NR53c400 family chips.
- *
- * Copyright 1993, Drew Eckhardt
- * Visionary Computing
- * (Unix and Linux consulting and custom programming)
- * drew@colorado.edu
- * +1 (303) 666-5836
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-/* Ported to Atari by Roman Hodek and others. */
-
-/* Adapted for the sun3 by Sam Creasey. */
-
-/*
- * Design
- *
- * 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
- * memory mapped) and drops this file in their 'C' wrapper.
- *
- * As far as command queueing, two queues are maintained for
- * each 5380 in the system - commands that haven't been issued yet,
- * and commands that are currently executing. This means that an
- * unlimited number of commands may be queued, letting
- * more commands propagate from the higher driver levels giving higher
- * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported,
- * allowing multiple commands to propagate all the way to a SCSI-II device
- * while a command is already executing.
- *
- *
- * Issues specific to the NCR5380 :
- *
- * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
- * piece of hardware that requires you to sit in a loop polling for
- * the REQ signal as long as you are connected. Some devices are
- * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
- * while doing long seek operations. [...] These
- * broken devices are the exception rather than the rule and I'd rather
- * spend my time optimizing for the normal case.
- *
- * Architecture :
- *
- * At the heart of the design is a coroutine, NCR5380_main,
- * 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 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
- * to reestablish a nexus. This will run main if necessary.
- *
- * On command termination, the done function will be called as
- * appropriate.
- *
- * SCSI pointers are maintained in the SCp field of SCSI command
- * structures, being initialized after the command is connected
- * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
- * Note that in violation of the standard, an implicit SAVE POINTERS operation
- * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS.
- */
-
-/*
- * Using this file :
- * This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips. To use it, you write an architecture specific functions
- * and macros and include this file in your driver.
- *
- * These macros control options :
- * 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.
- *
- * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
- *
- * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
- *
- * These macros MUST be defined :
- *
- * NCR5380_read(register) - read from the specified register
- *
- * 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
- * Note that the DMA setup functions should return the number of bytes
- * that they were able to program the controller for.
- *
- * NCR5380_dma_write_setup(instance, src, count) - initialize
- * NCR5380_dma_read_setup(instance, dst, count) - initialize
- * NCR5380_dma_residual(instance); - residual count
- *
- * PSEUDO functions :
- * NCR5380_pwrite(instance, src, count)
- * NCR5380_pread(instance, dst, count);
- *
- * 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 int do_abort(struct Scsi_Host *);
-static void do_reset(struct Scsi_Host *);
-
-#ifdef SUPPORT_TAGS
-
-/*
- * Functions for handling tagged queuing
- * =====================================
- *
- * ++roman (01/96): Now I've implemented SCSI-2 tagged queuing. Some notes:
- *
- * Using consecutive numbers for the tags is no good idea in my eyes. There
- * could be wrong re-usings if the counter (8 bit!) wraps and some early
- * command has been preempted for a long time. My solution: a bitfield for
- * remembering used tags.
- *
- * There's also the problem that each target has a certain queue size, but we
- * cannot know it in advance :-( We just see a QUEUE_FULL status being
- * returned. So, in this case, the driver internal queue size assumption is
- * reduced to the number of active tags if QUEUE_FULL is returned by the
- * target.
- *
- * We're also not allowed running tagged commands as long as an untagged
- * command is active. And REQUEST SENSE commands after a contingent allegiance
- * condition _must_ be untagged. To keep track whether an untagged command has
- * been issued, the host->busy array is still employed, as it is without
- * support for tagged queuing.
- *
- * One could suspect that there are possible race conditions between
- * is_lun_busy(), cmd_get_tag() and cmd_free_tag(). But I think this isn't the
- * case: is_lun_busy() and cmd_get_tag() are both called from NCR5380_main(),
- * which already guaranteed to be running at most once. It is also the only
- * place where tags/LUNs are allocated. So no other allocation can slip
- * between that pair, there could only happen a reselection, which can free a
- * tag, but that doesn't hurt. Only the sequence in cmd_free_tag() becomes
- * important: the tag bit must be cleared before 'nr_allocated' is decreased.
- */
-
-static void __init init_tags(struct NCR5380_hostdata *hostdata)
-{
- int target, lun;
- struct tag_alloc *ta;
-
- if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
- return;
-
- for (target = 0; target < 8; ++target) {
- for (lun = 0; lun < 8; ++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
- * support (MAX_TAGS). This value will be decreased if the target
- * returns QUEUE_FULL status.
- */
- ta->queue_size = MAX_TAGS;
- }
- }
-}
-
-
-/* Check if we can issue a command to this LUN: First see if the LUN is marked
- * busy by an untagged command. If the command should use tagged queuing, also
- * check that there is a free tag and the target's queue won't overflow. This
- * function should be called with interrupts disabled to avoid race
- * conditions.
- */
-
-static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged)
-{
- u8 lun = cmd->device->lun;
- struct Scsi_Host *instance = cmd->device->host;
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- if (hostdata->busy[cmd->device->id] & (1 << lun))
- return 1;
- if (!should_be_tagged ||
- !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
- !cmd->device->tagged_supported)
- return 0;
- if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >=
- hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) {
- dsprintk(NDEBUG_TAGS, instance, "target %d lun %d: no free tags\n",
- scmd_id(cmd), lun);
- return 1;
- }
- return 0;
-}
-
-
-/* Allocate a tag for a command (there are no checks anymore, check_lun_busy()
- * must be called before!), or reserve the LUN in 'busy' if the command is
- * untagged.
- */
-
-static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged)
-{
- u8 lun = cmd->device->lun;
- struct Scsi_Host *instance = cmd->device->host;
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- /* If we or the target don't support tagged queuing, allocate the LUN for
- * an untagged command.
- */
- if (!should_be_tagged ||
- !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
- !cmd->device->tagged_supported) {
- cmd->tag = TAG_NONE;
- hostdata->busy[cmd->device->id] |= (1 << lun);
- dsprintk(NDEBUG_TAGS, instance, "target %d lun %d now allocated by untagged command\n",
- scmd_id(cmd), lun);
- } else {
- 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);
- ta->nr_allocated++;
- dsprintk(NDEBUG_TAGS, instance, "using tag %d for target %d lun %d (%d tags allocated)\n",
- cmd->tag, scmd_id(cmd), lun, ta->nr_allocated);
- }
-}
-
-
-/* Mark the tag of command 'cmd' as free, or in case of an untagged command,
- * unlock the LUN.
- */
-
-static void cmd_free_tag(struct scsi_cmnd *cmd)
-{
- u8 lun = cmd->device->lun;
- struct Scsi_Host *instance = cmd->device->host;
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- if (cmd->tag == TAG_NONE) {
- hostdata->busy[cmd->device->id] &= ~(1 << lun);
- dsprintk(NDEBUG_TAGS, instance, "target %d lun %d untagged cmd freed\n",
- scmd_id(cmd), lun);
- } else if (cmd->tag >= MAX_TAGS) {
- shost_printk(KERN_NOTICE, instance,
- "trying to free bad tag %d!\n", cmd->tag);
- } else {
- struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
- clear_bit(cmd->tag, ta->allocated);
- ta->nr_allocated--;
- dsprintk(NDEBUG_TAGS, instance, "freed tag %d for target %d lun %d\n",
- cmd->tag, scmd_id(cmd), lun);
- }
-}
-
-
-static void free_all_tags(struct NCR5380_hostdata *hostdata)
-{
- int target, lun;
- struct tag_alloc *ta;
-
- if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
- return;
-
- for (target = 0; target < 8; ++target) {
- for (lun = 0; lun < 8; ++lun) {
- ta = &hostdata->TagAlloc[target][lun];
- bitmap_zero(ta->allocated, MAX_TAGS);
- ta->nr_allocated = 0;
- }
- }
-}
-
-#endif /* SUPPORT_TAGS */
-
-/**
- * merge_contiguous_buffers - coalesce scatter-gather list entries
- * @cmd: command requesting IO
- *
- * Try to merge several scatter-gather buffers into one DMA transfer.
- * This is possible if the scatter buffers lie on physically
- * contiguous addresses. The first scatter-gather buffer's data are
- * assumed to be already transferred into cmd->SCp.this_residual.
- * Every buffer merged avoids an interrupt and a DMA setup operation.
- */
-
-static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
-{
-#if !defined(CONFIG_SUN3)
- unsigned long endaddr;
-#if (NDEBUG & NDEBUG_MERGING)
- unsigned long oldlen = cmd->SCp.this_residual;
- int cnt = 1;
-#endif
-
- for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
- cmd->SCp.buffers_residual &&
- virt_to_phys(sg_virt(&cmd->SCp.buffer[1])) == endaddr;) {
- dprintk(NDEBUG_MERGING, "VTOP(%p) == %08lx -> merging\n",
- page_address(sg_page(&cmd->SCp.buffer[1])), endaddr);
-#if (NDEBUG & NDEBUG_MERGING)
- ++cnt;
-#endif
- ++cmd->SCp.buffer;
- --cmd->SCp.buffers_residual;
- cmd->SCp.this_residual += cmd->SCp.buffer->length;
- endaddr += cmd->SCp.buffer->length;
- }
-#if (NDEBUG & NDEBUG_MERGING)
- if (oldlen != cmd->SCp.this_residual)
- dprintk(NDEBUG_MERGING, "merged %d buffers from %p, new length %08x\n",
- cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
-#endif
-#endif /* !defined(CONFIG_SUN3) */
-}
-
-/**
- * initialize_SCp - init the scsi pointer field
- * @cmd: command block to set up
- *
- * Set up the internal fields in the SCSI command.
- */
-
-static inline void initialize_SCp(struct scsi_cmnd *cmd)
-{
- /*
- * Initialize the Scsi Pointer field so that all of the commands in the
- * various queues are valid.
- */
-
- if (scsi_bufflen(cmd)) {
- cmd->SCp.buffer = scsi_sglist(cmd);
- cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
- cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
- cmd->SCp.this_residual = cmd->SCp.buffer->length;
-
- merge_contiguous_buffers(cmd);
- } else {
- cmd->SCp.buffer = NULL;
- cmd->SCp.buffers_residual = 0;
- cmd->SCp.ptr = NULL;
- cmd->SCp.this_residual = 0;
- }
-
- cmd->SCp.Status = 0;
- cmd->SCp.Message = 0;
-}
-
-/**
- * NCR5380_poll_politely2 - wait for two chip register values
- * @instance: controller to poll
- * @reg1: 5380 register to poll
- * @bit1: Bitmask to check
- * @val1: Expected value
- * @reg2: Second 5380 register to poll
- * @bit2: Second bitmask to check
- * @val2: Second expected value
- * @wait: Time-out in jiffies
- *
- * Polls the chip in a reasonably efficient manner waiting for an
- * event to occur. After a short quick poll we begin to yield the CPU
- * (if possible). In irq contexts the time-out is arbitrarily limited.
- * Callers may hold locks as long as they are held in irq mode.
- *
- * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
- */
-
-static int NCR5380_poll_politely2(struct Scsi_Host *instance,
- int reg1, int bit1, int val1,
- int reg2, int bit2, int val2, int wait)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
- unsigned long deadline = jiffies + wait;
- unsigned long n;
-
- /* Busy-wait for up to 10 ms */
- n = min(10000U, jiffies_to_usecs(wait));
- n *= hostdata->accesses_per_ms;
- n /= 2000;
- do {
- if ((NCR5380_read(reg1) & bit1) == val1)
- return 0;
- if ((NCR5380_read(reg2) & bit2) == val2)
- return 0;
- cpu_relax();
- } while (n--);
-
- if (irqs_disabled() || in_interrupt())
- return -ETIMEDOUT;
-
- /* Repeatedly sleep for 1 ms until deadline */
- while (time_is_after_jiffies(deadline)) {
- schedule_timeout_uninterruptible(1);
- if ((NCR5380_read(reg1) & bit1) == val1)
- return 0;
- if ((NCR5380_read(reg2) & bit2) == val2)
- return 0;
- }
-
- return -ETIMEDOUT;
-}
-
-static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
- int reg, int bit, int val, int wait)
-{
- return NCR5380_poll_politely2(instance, reg, bit, val,
- reg, bit, val, wait);
-}
-
-#if NDEBUG
-static struct {
- unsigned char mask;
- const char *name;
-} signals[] = {
- {SR_DBP, "PARITY"},
- {SR_RST, "RST"},
- {SR_BSY, "BSY"},
- {SR_REQ, "REQ"},
- {SR_MSG, "MSG"},
- {SR_CD, "CD"},
- {SR_IO, "IO"},
- {SR_SEL, "SEL"},
- {0, NULL}
-},
-basrs[] = {
- {BASR_ATN, "ATN"},
- {BASR_ACK, "ACK"},
- {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"},
- {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"},
- {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"},
- {MR_ENABLE_EOP_INTR, "MODE EOP INTR"},
- {MR_MONITOR_BSY, "MODE MONITOR BSY"},
- {MR_DMA_MODE, "MODE DMA"},
- {MR_ARBITRATE, "MODE ARBITRATION"},
- {0, NULL}
-};
-
-/**
- * NCR5380_print - print scsi bus signals
- * @instance: adapter state to dump
- *
- * Print the SCSI bus signals for debugging purposes
- */
-
-static void NCR5380_print(struct Scsi_Host *instance)
-{
- unsigned char status, data, basr, mr, icr, i;
-
- data = NCR5380_read(CURRENT_SCSI_DATA_REG);
- status = NCR5380_read(STATUS_REG);
- mr = NCR5380_read(MODE_REG);
- icr = NCR5380_read(INITIATOR_COMMAND_REG);
- basr = NCR5380_read(BUS_AND_STATUS_REG);
-
- printk("STATUS_REG: %02x ", status);
- for (i = 0; signals[i].mask; ++i)
- if (status & signals[i].mask)
- printk(",%s", signals[i].name);
- printk("\nBASR: %02x ", basr);
- for (i = 0; basrs[i].mask; ++i)
- if (basr & basrs[i].mask)
- printk(",%s", basrs[i].name);
- printk("\nICR: %02x ", icr);
- for (i = 0; icrs[i].mask; ++i)
- if (icr & icrs[i].mask)
- printk(",%s", icrs[i].name);
- printk("\nMODE: %02x ", mr);
- for (i = 0; mrs[i].mask; ++i)
- if (mr & mrs[i].mask)
- printk(",%s", mrs[i].name);
- printk("\n");
-}
-
-static struct {
- unsigned char value;
- const char *name;
-} phases[] = {
- {PHASE_DATAOUT, "DATAOUT"},
- {PHASE_DATAIN, "DATAIN"},
- {PHASE_CMDOUT, "CMDOUT"},
- {PHASE_STATIN, "STATIN"},
- {PHASE_MSGOUT, "MSGOUT"},
- {PHASE_MSGIN, "MSGIN"},
- {PHASE_UNKNOWN, "UNKNOWN"}
-};
-
-/**
- * NCR5380_print_phase - show SCSI phase
- * @instance: adapter to dump
- *
- * Print the current SCSI phase for debugging purposes
- */
-
-static void NCR5380_print_phase(struct Scsi_Host *instance)
-{
- unsigned char status;
- int i;
-
- status = NCR5380_read(STATUS_REG);
- if (!(status & SR_REQ))
- shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n");
- else {
- for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
- (phases[i].value != (status & PHASE_MASK)); ++i)
- ;
- shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name);
- }
-}
-#endif
-
-/**
- * NCR58380_info - report driver and host information
- * @instance: relevant scsi host instance
- *
- * For use as the host template info() handler.
- */
-
-static const char *NCR5380_info(struct Scsi_Host *instance)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- return hostdata->info;
-}
-
-static void prepare_info(struct Scsi_Host *instance)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- snprintf(hostdata->info, sizeof(hostdata->info),
- "%s, io_port 0x%lx, n_io_port %d, "
- "base 0x%lx, irq %d, "
- "can_queue %d, cmd_per_lun %d, "
- "sg_tablesize %d, this_id %d, "
- "flags { %s%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 " : "",
- hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
-#ifdef DIFFERENTIAL
- "DIFFERENTIAL "
-#endif
-#ifdef PARITY
- "PARITY "
-#endif
-#ifdef SUPPORT_TAGS
- "SUPPORT_TAGS "
-#endif
- "");
-}
-
-/**
- * NCR5380_init - initialise an NCR5380
- * @instance: adapter to configure
- * @flags: control flags
- *
- * 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.
- *
- * Returns 0 for success
- */
-
-static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
- int i;
- unsigned long deadline;
-
- hostdata->host = instance;
- hostdata->id_mask = 1 << instance->this_id;
- hostdata->id_higher_mask = 0;
- for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
- if (i > hostdata->id_mask)
- hostdata->id_higher_mask |= i;
- for (i = 0; i < 8; ++i)
- hostdata->busy[i] = 0;
-#ifdef SUPPORT_TAGS
- init_tags(hostdata);
-#endif
- hostdata->dma_len = 0;
-
- spin_lock_init(&hostdata->lock);
- hostdata->connected = NULL;
- hostdata->sensing = NULL;
- INIT_LIST_HEAD(&hostdata->autosense);
- INIT_LIST_HEAD(&hostdata->unissued);
- INIT_LIST_HEAD(&hostdata->disconnected);
-
- hostdata->flags = flags;
-
- INIT_WORK(&hostdata->main_task, NCR5380_main);
- hostdata->work_q = alloc_workqueue("ncr5380_%d",
- WQ_UNBOUND | WQ_MEM_RECLAIM,
- 1, instance->host_no);
- if (!hostdata->work_q)
- return -ENOMEM;
-
- prepare_info(instance);
-
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(TARGET_COMMAND_REG, 0);
- NCR5380_write(SELECT_ENABLE_REG, 0);
-
- /* Calibrate register polling loop */
- i = 0;
- deadline = jiffies + 1;
- do {
- cpu_relax();
- } while (time_is_after_jiffies(deadline));
- deadline += msecs_to_jiffies(256);
- do {
- NCR5380_read(STATUS_REG);
- ++i;
- cpu_relax();
- } while (time_is_after_jiffies(deadline));
- hostdata->accesses_per_ms = i / 256;
-
- return 0;
-}
-
-/**
- * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems.
- * @instance: adapter to check
- *
- * If the system crashed, it may have crashed with a connected target and
- * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the
- * currently established nexus, which we know nothing about. Failing that
- * do a bus reset.
- *
- * Note that a bus reset will cause the chip to assert IRQ.
- *
- * Returns 0 if successful, otherwise -ENXIO.
- */
-
-static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
- int pass;
-
- for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
- switch (pass) {
- case 1:
- case 3:
- case 5:
- shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n");
- NCR5380_poll_politely(instance,
- STATUS_REG, SR_BSY, 0, 5 * HZ);
- break;
- case 2:
- shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n");
- do_abort(instance);
- break;
- case 4:
- shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n");
- do_reset(instance);
- /* Wait after a reset; the SCSI standard calls for
- * 250ms, we wait 500ms to be on the safe side.
- * But some Toshiba CD-ROMs need ten times that.
- */
- if (hostdata->flags & FLAG_TOSHIBA_DELAY)
- msleep(2500);
- else
- msleep(500);
- break;
- case 6:
- shost_printk(KERN_ERR, instance, "bus locked solid\n");
- return -ENXIO;
- }
- }
- 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)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- cancel_work_sync(&hostdata->main_task);
- destroy_workqueue(hostdata->work_q);
-}
-
-/**
- * complete_cmd - finish processing a command and return it to the SCSI ML
- * @instance: the host instance
- * @cmd: command to complete
- */
-
-static void complete_cmd(struct Scsi_Host *instance,
- struct scsi_cmnd *cmd)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd);
-
- if (hostdata->sensing == cmd) {
- /* Autosense processing ends here */
- if ((cmd->result & 0xff) != SAM_STAT_GOOD) {
- scsi_eh_restore_cmnd(cmd, &hostdata->ses);
- set_host_byte(cmd, DID_ERROR);
- } else
- scsi_eh_restore_cmnd(cmd, &hostdata->ses);
- hostdata->sensing = NULL;
- }
-
-#ifdef SUPPORT_TAGS
- cmd_free_tag(cmd);
-#else
- hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun);
-#endif
- cmd->scsi_done(cmd);
-}
-
-/**
- * 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,
- struct scsi_cmnd *cmd)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
- struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
- unsigned long flags;
-
-#if (NDEBUG & NDEBUG_NO_WRITE)
- switch (cmd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n");
- cmd->result = (DID_ERROR << 16);
- cmd->scsi_done(cmd);
- return 0;
- }
-#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
-
- cmd->result = 0;
-
- /*
- * ++roman: Just disabling the NCR interrupt isn't sufficient here,
- * because also a timer int can trigger an abort or reset, which would
- * alter queues and touch the lock.
- */
- if (!NCR5380_acquire_dma_irq(instance))
- return SCSI_MLQUEUE_HOST_BUSY;
-
- spin_lock_irqsave(&hostdata->lock, 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 (cmd->cmnd[0] == REQUEST_SENSE)
- list_add(&ncmd->list, &hostdata->unissued);
- else
- list_add_tail(&ncmd->list, &hostdata->unissued);
-
- spin_unlock_irqrestore(&hostdata->lock, flags);
-
- dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n",
- cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-
- /* Kick off command processing */
- queue_work(hostdata->work_q, &hostdata->main_task);
- return 0;
-}
-
-static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
-
- /* Caller does the locking needed to set & test these data atomically */
- if (list_empty(&hostdata->disconnected) &&
- list_empty(&hostdata->unissued) &&
- list_empty(&hostdata->autosense) &&
- !hostdata->connected &&
- !hostdata->selecting)
- NCR5380_release_dma_irq(instance);
-}
-
-/**
- * dequeue_next_cmd - dequeue a command for processing
- * @instance: the scsi host instance
- *
- * Priority is given to commands on the autosense queue. These commands
- * need autosense because of a CHECK CONDITION result.
- *
- * Returns a command pointer if a command is found for a target that is
- * not already busy. Otherwise returns NULL.
- */
-
-static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
- struct NCR5380_cmd *ncmd;
- struct scsi_cmnd *cmd;
-
- if (hostdata->sensing || list_empty(&hostdata->autosense)) {
- list_for_each_entry(ncmd, &hostdata->unissued, list) {
- cmd = NCR5380_to_scmd(ncmd);
- dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n",
- cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun);
-
- if (
-#ifdef SUPPORT_TAGS
- !is_lun_busy(cmd, 1)
-#else
- !(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun))
-#endif
- ) {
- list_del(&ncmd->list);
- dsprintk(NDEBUG_QUEUES, instance,
- "dequeue: removed %p from issue queue\n", cmd);
- return cmd;
- }
- }
- } else {
- /* Autosense processing begins here */
- ncmd = list_first_entry(&hostdata->autosense,
- struct NCR5380_cmd, list);
- list_del(&ncmd->list);
- cmd = NCR5380_to_scmd(ncmd);
- dsprintk(NDEBUG_QUEUES, instance,
- "dequeue: removed %p from autosense queue\n", cmd);
- scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
- hostdata->sensing = cmd;
- return cmd;
- }
- return NULL;
-}
-
-static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
-{
- struct NCR5380_hostdata *hostdata = shost_priv(instance);
- struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
-
- if (hostdata->sensing == cmd) {
- scsi_eh_restore_cmnd(cmd, &hostdata->ses);
- list_add(&ncmd->list, &hostdata->autosense);
- hostdata->sensing = NULL;
- } else
- list_add(&ncmd->list, &hostdata->unissued);
-}
-
-/**
- * NCR5380_main - NCR state machines
- *
- * 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.
- */
-
-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;
- int done;
-
- /*
- * ++roman: Just disabling the NCR interrupt isn't sufficient here,
- * because also a timer int can trigger an abort or reset, which can
- * alter queues and touch the Falcon lock.
- */
-
- do {
- done = 1;
-
- spin_lock_irq(&hostdata->lock);
- while (!hostdata->connected && !hostdata->selecting) {
- struct scsi_cmnd *cmd = dequeue_next_cmd(instance);
-
- if (!cmd)
- break;
-
- dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd);
-
- /*
- * Attempt to establish an I_T_L nexus here.
- * On success, instance->hostdata->connected is set.