atari_NCR5380: Merge from NCR5380.c

The NCR5380.c core driver has moved on since the atari_NCR5380.c fork.
Some of those changes are also relevant to atari_NCR5380.c so apply them
there as well.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Finn Thain 2014-11-12 16:12:18 +11:00 committed by Christoph Hellwig
parent 8dad0c51da
commit ff50f9ed0f
1 changed files with 85 additions and 120 deletions

View File

@ -104,27 +104,7 @@
/* /*
* Design * 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, * This is a generic 5380 driver. To use it on a different platform,
* one simply writes appropriate system specific macros (ie, data * one simply writes appropriate system specific macros (ie, data
* transfer - some PC's will use the I/O bus, 68K's must use * transfer - some PC's will use the I/O bus, 68K's must use
@ -139,11 +119,6 @@
* allowing multiple commands to propagate all the way to a SCSI-II device * allowing multiple commands to propagate all the way to a SCSI-II device
* while a command is already executing. * 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 : * Issues specific to the NCR5380 :
* *
@ -168,19 +143,17 @@
* Architecture : * Architecture :
* *
* At the heart of the design is a coroutine, NCR5380_main, * At the heart of the design is a coroutine, NCR5380_main,
* which is started when not running by the interrupt handler, * which is started from a workqueue for each NCR5380 host in the
* timer, and queue command function. It attempts to establish * system. It attempts to establish I_T_L or I_T_L_Q nexuses by
* I_T_L or I_T_L_Q nexuses by removing the commands from the * removing the commands from the issue queue and calling
* issue queue and calling NCR5380_select() if a nexus * NCR5380_select() if a nexus is not established.
* is not established.
* *
* Once a nexus is established, the NCR5380_information_transfer() * Once a nexus is established, the NCR5380_information_transfer()
* phase goes through the various phases as instructed by the target. * phase goes through the various phases as instructed by the target.
* if the target goes into MSG IN and sends a DISCONNECT message, * if the target goes into MSG IN and sends a DISCONNECT message,
* the command structure is placed into the per instance disconnected * the command structure is placed into the per instance disconnected
* queue, and NCR5380_main tries to find more work. If USLEEP * queue, and NCR5380_main tries to find more work. If the target is
* was defined, and the target is idle for too long, the system * idle for too long, the system will try to sleep.
* will try to sleep.
* *
* If a command has disconnected, eventually an interrupt will trigger, * If a command has disconnected, eventually an interrupt will trigger,
* calling NCR5380_intr() which will in turn call NCR5380_reselect * calling NCR5380_intr() which will in turn call NCR5380_reselect
@ -206,6 +179,9 @@
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
* for commands that return with a CHECK CONDITION status. * 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. * LINKED - if defined, linked commands are supported.
* *
* REAL_DMA - if defined, REAL DMA is used during the data transfer phases. * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
@ -218,6 +194,9 @@
* *
* NCR5380_write(register, value) - write to the specific 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 * Either real DMA *or* pseudo DMA may be implemented
* REAL functions : * REAL functions :
* NCR5380_REAL_DMA should be defined if real DMA is to be used. * NCR5380_REAL_DMA should be defined if real DMA is to be used.
@ -236,20 +215,6 @@
* NCR5380_pwrite(instance, src, count) * NCR5380_pwrite(instance, src, count)
* NCR5380_pread(instance, dst, 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), * The generic driver is initialized by calling NCR5380_init(instance),
* after setting the appropriate host specific fields and ID. If the * after setting the appropriate host specific fields and ID. If the
* driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
@ -489,13 +454,11 @@ static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
#endif /* !defined(CONFIG_SUN3) */ #endif /* !defined(CONFIG_SUN3) */
} }
/* /**
* Function : void initialize_SCp(struct scsi_cmnd *cmd) * initialize_SCp - init the scsi pointer field
* @cmd: command block to set up
* *
* Purpose : initialize the saved data pointers for cmd to point to the * Set up the internal fields in the SCSI command.
* start of the buffer.
*
* Inputs : cmd - scsi_cmnd structure to have pointers reset.
*/ */
static inline void initialize_SCp(struct scsi_cmnd *cmd) static inline void initialize_SCp(struct scsi_cmnd *cmd)
@ -548,12 +511,11 @@ static struct {
{0, NULL} {0, NULL}
}; };
/* /**
* Function : void NCR5380_print(struct Scsi_Host *instance) * NCR5380_print - print scsi bus signals
* @instance: adapter state to dump
* *
* Purpose : print the SCSI bus signals for debugging purposes * Print the SCSI bus signals for debugging purposes
*
* Input : instance - which NCR5380
*/ */
static void NCR5380_print(struct Scsi_Host *instance) static void NCR5380_print(struct Scsi_Host *instance)
@ -596,12 +558,13 @@ static struct {
{PHASE_UNKNOWN, "UNKNOWN"} {PHASE_UNKNOWN, "UNKNOWN"}
}; };
/* /**
* Function : void NCR5380_print_phase(struct Scsi_Host *instance) * NCR5380_print_phase - show SCSI phase
* @instance: adapter to dump
* *
* Purpose : print the current SCSI phase for debugging purposes * Print the current SCSI phase for debugging purposes
* *
* Input : instance - which NCR5380 * Locks: none
*/ */
static void NCR5380_print_phase(struct Scsi_Host *instance) static void NCR5380_print_phase(struct Scsi_Host *instance)
@ -710,13 +673,12 @@ static void prepare_info(struct Scsi_Host *instance)
""); "");
} }
/* /**
* Function : void NCR5380_print_status (struct Scsi_Host *instance) * NCR5380_print_status - dump controller info
* @instance: controller to dump
* *
* Purpose : print commands in the various queues, called from * Print commands in the various queues, called from NCR5380_abort
* NCR5380_abort and NCR5380_debug to aid debugging. * to aid debugging.
*
* Inputs : instance, pointer to this instance.
*/ */
static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd) static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd)
@ -807,16 +769,18 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
return 0; return 0;
} }
/* /**
* Function : void NCR5380_init (struct Scsi_Host *instance) * NCR5380_init - initialise an NCR5380
* @instance: adapter to configure
* @flags: control flags
* *
* Purpose : initializes *instance and corresponding 5380 chip. * Initializes *instance and corresponding 5380 chip,
* * with flags OR'd into the initial flags value.
* Inputs : instance - instantiation of the 5380 driver.
* *
* Notes : I assume that the host, hostno, and id bits have been * Notes : I assume that the host, hostno, and id bits have been
* set correctly. I don't care about the irq and other fields. * set correctly. I don't care about the irq and other fields.
* *
* Returns 0 for success
*/ */
static int __init NCR5380_init(struct Scsi_Host *instance, int flags) static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
@ -861,27 +825,26 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
return 0; 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) static void NCR5380_exit(struct Scsi_Host *instance)
{ {
/* Empty, as we didn't schedule any delayed work */ cancel_work_sync(&NCR5380_tqueue);
} }
/* /**
* Function : int NCR5380_queue_command (struct scsi_cmnd *cmd, * NCR5380_queue_command - queue a command
* void (*done)(struct scsi_cmnd *)) * @instance: the relevant SCSI adapter
* * @cmd: SCSI command
* 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.
* *
* 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, static int NCR5380_queue_command(struct Scsi_Host *instance,
@ -935,6 +898,13 @@ static int NCR5380_queue_command(struct Scsi_Host *instance,
local_irq_save(flags); 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)) { if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
LIST(cmd, hostdata->issue_queue); LIST(cmd, hostdata->issue_queue);
SET_NEXT(cmd, hostdata->issue_queue); SET_NEXT(cmd, hostdata->issue_queue);
@ -977,16 +947,15 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
NCR5380_release_dma_irq(instance); 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 * NCR5380_main is a coroutine that runs as long as more work can
* be done on the NCR5380 host adapters in a system. Both * be done on the NCR5380 host adapters in a system. Both
* NCR5380_queue_command() and NCR5380_intr() will try to start it * NCR5380_queue_command() and NCR5380_intr() will try to start it
* in case it is not running. * in case it is not running.
* *
* NOTE : NCR5380_main exits with interrupts *disabled*, the caller should * Locks: called as its own thread with no locks held.
* reenable them. This prevents reentrancy and kernel stack overflow.
*/ */
static void NCR5380_main(struct work_struct *work) static void NCR5380_main(struct work_struct *work)
@ -1239,15 +1208,14 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
#endif /* REAL_DMA */ #endif /* REAL_DMA */
/* /**
* Function : void NCR5380_intr (int irq) * NCR5380_intr - generic NCR5380 irq handler
* * @irq: interrupt number
* Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses * @dev_id: device info
* from the disconnected queue, and restarting NCR5380_main()
* as required.
*
* Inputs : int irq, irq that caused this interrupt.
* *
* 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) static irqreturn_t NCR5380_intr(int irq, void *dev_id)
@ -1540,7 +1508,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
* selection. * selection.
*/ */
timeout = jiffies + 25; timeout = jiffies + (250 * HZ / 1000);
/* /*
* XXX very interesting - we're seeing a bounce where the BSY we * XXX very interesting - we're seeing a bounce where the BSY we
@ -2123,9 +2091,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* If the watchdog timer fires, all future * If the watchdog timer fires, all future
* accesses to this device will use the * accesses to this device will use the
* polled-IO. */ * polled-IO. */
printk(KERN_NOTICE "scsi%d: switching target %d " scmd_printk(KERN_INFO, cmd,
"lun %llu to slow handshake\n", HOSTNO, "switching to slow handshake\n");
cmd->device->id, cmd->device->lun);
cmd->device->borken = 1; cmd->device->borken = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_ATN); ICR_ASSERT_ATN);
@ -2445,20 +2412,18 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/ */
default: default:
if (!tmp) { 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); spi_print_msg(extended_msg);
printk("\n"); printk("\n");
} else if (tmp != EXTENDED_MESSAGE) } else if (tmp != EXTENDED_MESSAGE)
printk(KERN_DEBUG "scsi%d: rejecting unknown " scmd_printk(KERN_INFO, cmd,
"message %02x from target %d, lun %llu\n", "rejecting unknown message %02x\n",
HOSTNO, tmp, cmd->device->id, cmd->device->lun); tmp);
else else
printk(KERN_DEBUG "scsi%d: rejecting unknown " scmd_printk(KERN_INFO, cmd,
"extended message " "rejecting unknown extended message code %02x, length %d\n",
"code %02x, length %d from target %d, lun %llu\n", extended_msg[1], extended_msg[0]);
HOSTNO, extended_msg[1], extended_msg[0],
cmd->device->id, cmd->device->lun);
msgout = MESSAGE_REJECT; msgout = MESSAGE_REJECT;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);