summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2016-03-23 21:10:22 +1100
committerMartin K. Petersen <martin.petersen@oracle.com>2016-04-11 16:57:09 -0400
commitc4ec6f924f0682e1f40107204152e977d6b1bd07 (patch)
tree63093bc0616f30e7a3d140923b9551a72d2f69cc /drivers
parente9db3198e08b6a01e2847f732e595bb8e89153c1 (diff)
downloadlinux-c4ec6f924f0682e1f40107204152e977d6b1bd07.tar.gz
linux-c4ec6f924f0682e1f40107204152e977d6b1bd07.tar.bz2
linux-c4ec6f924f0682e1f40107204152e977d6b1bd07.zip
ncr5380: Remove disused atari_NCR5380.c core driver
Now that atari_scsi and sun3_scsi have been converted to use the NCR5380.c core driver, remove atari_NCR5380.c. Also remove the last vestiges of its Tagged Command Queueing implementation from the wrapper drivers. The TCQ support in atari_NCR5380.c is abandoned by this patch. It is not merged into the remaining core driver because, 1) atari_scsi defines SUPPORT_TAGS but leaves FLAG_TAGGED_QUEUING disabled by default, which indicates that it is mostly undesirable. 2) I'm told that it doesn't work correctly when enabled. 3) The algorithm does not make use of block layer tags which it will have to do because scmd->tag is deprecated. 4) sun3_scsi doesn't define SUPPORT_TAGS at all, yet the the SUPPORT_TAGS macro interacts with the CONFIG_SUN3 macro in 'interesting' ways. 5) Compile-time configuration with macros like SUPPORT_TAGS caused the configuration space to explode, leading to untestable and unmaintainable code that is too hard to reason about. The merge_contiguous_buffers() code is also abandoned. This was unused by sun3_scsi. Only atari_scsi used it and then only on TT, because only TT supports scatter/gather. I suspect that the TT would work fine with ENABLE_CLUSTERING instead. If someone can benchmark the difference then perhaps the merge_contiguous_buffers() code can be be justified. Until then we are better off without the extra complexity. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Tested-by: Ondrej Zary <linux@rainbow-software.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers')
-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
-