1
0
Fork 0

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>
hifive-unleashed-5.1
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
* 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
@ -139,11 +119,6 @@
* 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 :
*
@ -168,19 +143,17 @@
* 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
@ -206,6 +179,9 @@
* 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.
@ -218,6 +194,9 @@
*
* 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.
@ -236,20 +215,6 @@
* 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,
@ -489,13 +454,11 @@ static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
#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
* start of the buffer.
*
* 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)
@ -548,12 +511,11 @@ static struct {
{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
*
* Input : instance - which NCR5380
* Print the SCSI bus signals for debugging purposes
*/
static void NCR5380_print(struct Scsi_Host *instance)
@ -596,12 +558,13 @@ static struct {
{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)
@ -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
* NCR5380_abort and NCR5380_debug to aid debugging.
*
* 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)
@ -807,16 +769,18 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
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.
*
* 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)
@ -861,27 +825,26 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
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 */
cancel_work_sync(&NCR5380_tqueue);
}
/*
* 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,
@ -935,6 +898,13 @@ 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);
@ -977,16 +947,15 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *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
* 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)
@ -1239,15 +1208,14 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
#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)
@ -1540,7 +1508,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
* selection.
*/
timeout = jiffies + 25;
timeout = jiffies + (250 * HZ / 1000);
/*
* 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
* 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);
@ -2445,20 +2412,18 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/
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);