xref: /linux/drivers/scsi/NCR5380.c (revision b746545f8bb0c4280c247353d61ac93620f5ef17)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NCR 5380 generic driver routines.  These should make it *trivial*
31da177e4SLinus Torvalds  *      to implement 5380 SCSI drivers under Linux with a non-trantor
41da177e4SLinus Torvalds  *      architecture.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *      Note that these routines also work with NR53c400 family chips.
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * Copyright 1993, Drew Eckhardt
91da177e4SLinus Torvalds  *      Visionary Computing
101da177e4SLinus Torvalds  *      (Unix and Linux consulting and custom programming)
111da177e4SLinus Torvalds  *      drew@colorado.edu
121da177e4SLinus Torvalds  *      +1 (303) 666-5836
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * For more information, please consult
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  * NCR 5380 Family
171da177e4SLinus Torvalds  * SCSI Protocol Controller
181da177e4SLinus Torvalds  * Databook
191da177e4SLinus Torvalds  *
201da177e4SLinus Torvalds  * NCR Microelectronics
211da177e4SLinus Torvalds  * 1635 Aeroplaza Drive
221da177e4SLinus Torvalds  * Colorado Springs, CO 80916
231da177e4SLinus Torvalds  * 1+ (719) 578-3400
241da177e4SLinus Torvalds  * 1+ (800) 334-5454
251da177e4SLinus Torvalds  */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds /*
281da177e4SLinus Torvalds  * Revision 1.10 1998/9/2	Alan Cox
29fa195afeSAlan Cox  *				(alan@lxorguk.ukuu.org.uk)
301da177e4SLinus Torvalds  * Fixed up the timer lockups reported so far. Things still suck. Looking
311da177e4SLinus Torvalds  * forward to 2.3 and per device request queues. Then it'll be possible to
321da177e4SLinus Torvalds  * SMP thread this beast and improve life no end.
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds  * Revision 1.9  1997/7/27	Ronald van Cuijlenborg
351da177e4SLinus Torvalds  *				(ronald.van.cuijlenborg@tip.nl or nutty@dds.nl)
361da177e4SLinus Torvalds  * (hopefully) fixed and enhanced USLEEP
371da177e4SLinus Torvalds  * added support for DTC3181E card (for Mustek scanner)
381da177e4SLinus Torvalds  *
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds  * Revision 1.8			Ingmar Baumgart
411da177e4SLinus Torvalds  *				(ingmar@gonzo.schwaben.de)
421da177e4SLinus Torvalds  * added support for NCR53C400a card
431da177e4SLinus Torvalds  *
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds  * Revision 1.7  1996/3/2       Ray Van Tassle (rayvt@comm.mot.com)
461da177e4SLinus Torvalds  * added proc_info
471da177e4SLinus Torvalds  * added support needed for DTC 3180/3280
481da177e4SLinus Torvalds  * fixed a couple of bugs
491da177e4SLinus Torvalds  *
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds  * Revision 1.5  1994/01/19  09:14:57  drew
521da177e4SLinus Torvalds  * Fixed udelay() hack that was being used on DATAOUT phases
531da177e4SLinus Torvalds  * instead of a proper wait for the final handshake.
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  * Revision 1.4  1994/01/19  06:44:25  drew
561da177e4SLinus Torvalds  * *** empty log message ***
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  * Revision 1.3  1994/01/19  05:24:40  drew
591da177e4SLinus Torvalds  * Added support for TCR LAST_BYTE_SENT bit.
601da177e4SLinus Torvalds  *
611da177e4SLinus Torvalds  * Revision 1.2  1994/01/15  06:14:11  drew
621da177e4SLinus Torvalds  * REAL DMA support, bug fixes.
631da177e4SLinus Torvalds  *
641da177e4SLinus Torvalds  * Revision 1.1  1994/01/15  06:00:54  drew
651da177e4SLinus Torvalds  * Initial revision
661da177e4SLinus Torvalds  *
671da177e4SLinus Torvalds  */
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds /*
701da177e4SLinus Torvalds  * Further development / testing that should be done :
711da177e4SLinus Torvalds  * 1.  Cleanup the NCR5380_transfer_dma function and DMA operation complete
721da177e4SLinus Torvalds  *     code so that everything does the same thing that's done at the
731da177e4SLinus Torvalds  *     end of a pseudo-DMA read operation.
741da177e4SLinus Torvalds  *
751da177e4SLinus Torvalds  * 2.  Fix REAL_DMA (interrupt driven, polled works fine) -
761da177e4SLinus Torvalds  *     basically, transfer size needs to be reduced by one
771da177e4SLinus Torvalds  *     and the last byte read as is done with PSEUDO_DMA.
781da177e4SLinus Torvalds  *
791da177e4SLinus Torvalds  * 4.  Test SCSI-II tagged queueing (I have no devices which support
801da177e4SLinus Torvalds  *      tagged queueing)
811da177e4SLinus Torvalds  */
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds #ifndef notyet
841da177e4SLinus Torvalds #undef REAL_DMA
851da177e4SLinus Torvalds #endif
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds #ifdef BOARD_REQUIRES_NO_DELAY
881da177e4SLinus Torvalds #define io_recovery_delay(x)
891da177e4SLinus Torvalds #else
901da177e4SLinus Torvalds #define io_recovery_delay(x)	udelay(x)
911da177e4SLinus Torvalds #endif
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds /*
941da177e4SLinus Torvalds  * Design
951da177e4SLinus Torvalds  *
961da177e4SLinus Torvalds  * This is a generic 5380 driver.  To use it on a different platform,
971da177e4SLinus Torvalds  * one simply writes appropriate system specific macros (ie, data
981da177e4SLinus Torvalds  * transfer - some PC's will use the I/O bus, 68K's must use
991da177e4SLinus Torvalds  * memory mapped) and drops this file in their 'C' wrapper.
1001da177e4SLinus Torvalds  *
1011da177e4SLinus Torvalds  * (Note from hch:  unfortunately it was not enough for the different
1021da177e4SLinus Torvalds  * m68k folks and instead of improving this driver they copied it
1031da177e4SLinus Torvalds  * and hacked it up for their needs.  As a consequence they lost
1041da177e4SLinus Torvalds  * most updates to this driver.  Maybe someone will fix all these
1051da177e4SLinus Torvalds  * drivers to use a common core one day..)
1061da177e4SLinus Torvalds  *
1071da177e4SLinus Torvalds  * As far as command queueing, two queues are maintained for
1081da177e4SLinus Torvalds  * each 5380 in the system - commands that haven't been issued yet,
1091da177e4SLinus Torvalds  * and commands that are currently executing.  This means that an
1101da177e4SLinus Torvalds  * unlimited number of commands may be queued, letting
1111da177e4SLinus Torvalds  * more commands propagate from the higher driver levels giving higher
1121da177e4SLinus Torvalds  * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported,
1131da177e4SLinus Torvalds  * allowing multiple commands to propagate all the way to a SCSI-II device
1141da177e4SLinus Torvalds  * while a command is already executing.
1151da177e4SLinus Torvalds  *
1161da177e4SLinus Torvalds  *
1171da177e4SLinus Torvalds  * Issues specific to the NCR5380 :
1181da177e4SLinus Torvalds  *
1191da177e4SLinus Torvalds  * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
1201da177e4SLinus Torvalds  * piece of hardware that requires you to sit in a loop polling for
1211da177e4SLinus Torvalds  * the REQ signal as long as you are connected.  Some devices are
1221da177e4SLinus Torvalds  * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
123686f3990SFinn Thain  * while doing long seek operations. [...] These
1241da177e4SLinus Torvalds  * broken devices are the exception rather than the rule and I'd rather
1251da177e4SLinus Torvalds  * spend my time optimizing for the normal case.
1261da177e4SLinus Torvalds  *
1271da177e4SLinus Torvalds  * Architecture :
1281da177e4SLinus Torvalds  *
1291da177e4SLinus Torvalds  * At the heart of the design is a coroutine, NCR5380_main,
1301da177e4SLinus Torvalds  * which is started from a workqueue for each NCR5380 host in the
1311da177e4SLinus Torvalds  * system.  It attempts to establish I_T_L or I_T_L_Q nexuses by
1321da177e4SLinus Torvalds  * removing the commands from the issue queue and calling
1331da177e4SLinus Torvalds  * NCR5380_select() if a nexus is not established.
1341da177e4SLinus Torvalds  *
1351da177e4SLinus Torvalds  * Once a nexus is established, the NCR5380_information_transfer()
1361da177e4SLinus Torvalds  * phase goes through the various phases as instructed by the target.
1371da177e4SLinus Torvalds  * if the target goes into MSG IN and sends a DISCONNECT message,
1381da177e4SLinus Torvalds  * the command structure is placed into the per instance disconnected
1391da177e4SLinus Torvalds  * queue, and NCR5380_main tries to find more work.  If the target is
1401da177e4SLinus Torvalds  * idle for too long, the system will try to sleep.
1411da177e4SLinus Torvalds  *
1421da177e4SLinus Torvalds  * If a command has disconnected, eventually an interrupt will trigger,
1431da177e4SLinus Torvalds  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
1441da177e4SLinus Torvalds  * to reestablish a nexus.  This will run main if necessary.
1451da177e4SLinus Torvalds  *
1461da177e4SLinus Torvalds  * On command termination, the done function will be called as
1471da177e4SLinus Torvalds  * appropriate.
1481da177e4SLinus Torvalds  *
1491da177e4SLinus Torvalds  * SCSI pointers are maintained in the SCp field of SCSI command
1501da177e4SLinus Torvalds  * structures, being initialized after the command is connected
1511da177e4SLinus Torvalds  * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
1521da177e4SLinus Torvalds  * Note that in violation of the standard, an implicit SAVE POINTERS operation
1531da177e4SLinus Torvalds  * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS.
1541da177e4SLinus Torvalds  */
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds /*
1571da177e4SLinus Torvalds  * Using this file :
1581da177e4SLinus Torvalds  * This file a skeleton Linux SCSI driver for the NCR 5380 series
1591da177e4SLinus Torvalds  * of chips.  To use it, you write an architecture specific functions
1601da177e4SLinus Torvalds  * and macros and include this file in your driver.
1611da177e4SLinus Torvalds  *
1621da177e4SLinus Torvalds  * These macros control options :
1631da177e4SLinus Torvalds  * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be
1641da177e4SLinus Torvalds  *      defined.
1651da177e4SLinus Torvalds  *
1661da177e4SLinus Torvalds  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
1671da177e4SLinus Torvalds  *      for commands that return with a CHECK CONDITION status.
1681da177e4SLinus Torvalds  *
1691da177e4SLinus Torvalds  * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
1701da177e4SLinus Torvalds  *      transceivers.
1711da177e4SLinus Torvalds  *
1721da177e4SLinus Torvalds  * DONT_USE_INTR - if defined, never use interrupts, even if we probe or
1731da177e4SLinus Torvalds  *      override-configure an IRQ.
1741da177e4SLinus Torvalds  *
1751da177e4SLinus Torvalds  * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases.
1761da177e4SLinus Torvalds  *
1771da177e4SLinus Torvalds  * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
1781da177e4SLinus Torvalds  *
1791da177e4SLinus Torvalds  * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't
1801da177e4SLinus Torvalds  *      rely on phase mismatch and EOP interrupts to determine end
1811da177e4SLinus Torvalds  *      of phase.
1821da177e4SLinus Torvalds  *
1831da177e4SLinus Torvalds  * Defaults for these will be provided although the user may want to adjust
1841da177e4SLinus Torvalds  * these to allocate CPU resources to the SCSI driver or "real" code.
1851da177e4SLinus Torvalds  *
1861da177e4SLinus Torvalds  * These macros MUST be defined :
1871da177e4SLinus Torvalds  *
1881da177e4SLinus Torvalds  * NCR5380_read(register)  - read from the specified register
1891da177e4SLinus Torvalds  *
1901da177e4SLinus Torvalds  * NCR5380_write(register, value) - write to the specific register
1911da177e4SLinus Torvalds  *
1921da177e4SLinus Torvalds  * NCR5380_implementation_fields  - additional fields needed for this
1931da177e4SLinus Torvalds  *      specific implementation of the NCR5380
1941da177e4SLinus Torvalds  *
1951da177e4SLinus Torvalds  * Either real DMA *or* pseudo DMA may be implemented
1961da177e4SLinus Torvalds  * REAL functions :
1971da177e4SLinus Torvalds  * NCR5380_REAL_DMA should be defined if real DMA is to be used.
1981da177e4SLinus Torvalds  * Note that the DMA setup functions should return the number of bytes
1991da177e4SLinus Torvalds  *      that they were able to program the controller for.
2001da177e4SLinus Torvalds  *
2011da177e4SLinus Torvalds  * Also note that generic i386/PC versions of these macros are
2021da177e4SLinus Torvalds  *      available as NCR5380_i386_dma_write_setup,
2031da177e4SLinus Torvalds  *      NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual.
2041da177e4SLinus Torvalds  *
2051da177e4SLinus Torvalds  * NCR5380_dma_write_setup(instance, src, count) - initialize
2061da177e4SLinus Torvalds  * NCR5380_dma_read_setup(instance, dst, count) - initialize
2071da177e4SLinus Torvalds  * NCR5380_dma_residual(instance); - residual count
2081da177e4SLinus Torvalds  *
2091da177e4SLinus Torvalds  * PSEUDO functions :
2101da177e4SLinus Torvalds  * NCR5380_pwrite(instance, src, count)
2111da177e4SLinus Torvalds  * NCR5380_pread(instance, dst, count);
2121da177e4SLinus Torvalds  *
2131da177e4SLinus Torvalds  * The generic driver is initialized by calling NCR5380_init(instance),
2141da177e4SLinus Torvalds  * after setting the appropriate host specific fields and ID.  If the
2151da177e4SLinus Torvalds  * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
2161da177e4SLinus Torvalds  * possible) function may be used.
2171da177e4SLinus Torvalds  */
2181da177e4SLinus Torvalds 
21954d8fe44SFinn Thain static int do_abort(struct Scsi_Host *);
22054d8fe44SFinn Thain static void do_reset(struct Scsi_Host *);
2211da177e4SLinus Torvalds 
2221da177e4SLinus Torvalds /*
2231da177e4SLinus Torvalds  *	initialize_SCp		-	init the scsi pointer field
2241da177e4SLinus Torvalds  *	@cmd: command block to set up
2251da177e4SLinus Torvalds  *
2261da177e4SLinus Torvalds  *	Set up the internal fields in the SCSI command.
2271da177e4SLinus Torvalds  */
2281da177e4SLinus Torvalds 
229710ddd0dSFinn Thain static inline void initialize_SCp(struct scsi_cmnd *cmd)
2301da177e4SLinus Torvalds {
2311da177e4SLinus Torvalds 	/*
2321da177e4SLinus Torvalds 	 * Initialize the Scsi Pointer field so that all of the commands in the
2331da177e4SLinus Torvalds 	 * various queues are valid.
2341da177e4SLinus Torvalds 	 */
2351da177e4SLinus Torvalds 
2369e0fe44dSBoaz Harrosh 	if (scsi_bufflen(cmd)) {
2379e0fe44dSBoaz Harrosh 		cmd->SCp.buffer = scsi_sglist(cmd);
2389e0fe44dSBoaz Harrosh 		cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
23945711f1aSJens Axboe 		cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
2401da177e4SLinus Torvalds 		cmd->SCp.this_residual = cmd->SCp.buffer->length;
2411da177e4SLinus Torvalds 	} else {
2421da177e4SLinus Torvalds 		cmd->SCp.buffer = NULL;
2431da177e4SLinus Torvalds 		cmd->SCp.buffers_residual = 0;
2449e0fe44dSBoaz Harrosh 		cmd->SCp.ptr = NULL;
2459e0fe44dSBoaz Harrosh 		cmd->SCp.this_residual = 0;
2461da177e4SLinus Torvalds 	}
247f27db8ebSFinn Thain 
248f27db8ebSFinn Thain 	cmd->SCp.Status = 0;
249f27db8ebSFinn Thain 	cmd->SCp.Message = 0;
2501da177e4SLinus Torvalds }
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds /**
253b32ade12SFinn Thain  * NCR5380_poll_politely2 - wait for two chip register values
2541da177e4SLinus Torvalds  * @instance: controller to poll
255b32ade12SFinn Thain  * @reg1: 5380 register to poll
256b32ade12SFinn Thain  * @bit1: Bitmask to check
257b32ade12SFinn Thain  * @val1: Expected value
258b32ade12SFinn Thain  * @reg2: Second 5380 register to poll
259b32ade12SFinn Thain  * @bit2: Second bitmask to check
260b32ade12SFinn Thain  * @val2: Second expected value
2612f854b82SFinn Thain  * @wait: Time-out in jiffies
2621da177e4SLinus Torvalds  *
2632f854b82SFinn Thain  * Polls the chip in a reasonably efficient manner waiting for an
2642f854b82SFinn Thain  * event to occur. After a short quick poll we begin to yield the CPU
2652f854b82SFinn Thain  * (if possible). In irq contexts the time-out is arbitrarily limited.
2662f854b82SFinn Thain  * Callers may hold locks as long as they are held in irq mode.
2671da177e4SLinus Torvalds  *
268b32ade12SFinn Thain  * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
2691da177e4SLinus Torvalds  */
2701da177e4SLinus Torvalds 
271b32ade12SFinn Thain static int NCR5380_poll_politely2(struct Scsi_Host *instance,
272b32ade12SFinn Thain                                   int reg1, int bit1, int val1,
273b32ade12SFinn Thain                                   int reg2, int bit2, int val2, int wait)
2741da177e4SLinus Torvalds {
2752f854b82SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
2762f854b82SFinn Thain 	unsigned long deadline = jiffies + wait;
2772f854b82SFinn Thain 	unsigned long n;
2781da177e4SLinus Torvalds 
2792f854b82SFinn Thain 	/* Busy-wait for up to 10 ms */
2802f854b82SFinn Thain 	n = min(10000U, jiffies_to_usecs(wait));
2812f854b82SFinn Thain 	n *= hostdata->accesses_per_ms;
282b32ade12SFinn Thain 	n /= 2000;
2832f854b82SFinn Thain 	do {
284b32ade12SFinn Thain 		if ((NCR5380_read(reg1) & bit1) == val1)
285b32ade12SFinn Thain 			return 0;
286b32ade12SFinn Thain 		if ((NCR5380_read(reg2) & bit2) == val2)
2871da177e4SLinus Torvalds 			return 0;
2881da177e4SLinus Torvalds 		cpu_relax();
2892f854b82SFinn Thain 	} while (n--);
2902f854b82SFinn Thain 
2912f854b82SFinn Thain 	if (irqs_disabled() || in_interrupt())
2922f854b82SFinn Thain 		return -ETIMEDOUT;
2932f854b82SFinn Thain 
2942f854b82SFinn Thain 	/* Repeatedly sleep for 1 ms until deadline */
2952f854b82SFinn Thain 	while (time_is_after_jiffies(deadline)) {
2962f854b82SFinn Thain 		schedule_timeout_uninterruptible(1);
297b32ade12SFinn Thain 		if ((NCR5380_read(reg1) & bit1) == val1)
298b32ade12SFinn Thain 			return 0;
299b32ade12SFinn Thain 		if ((NCR5380_read(reg2) & bit2) == val2)
3002f854b82SFinn Thain 			return 0;
3011da177e4SLinus Torvalds 	}
3021da177e4SLinus Torvalds 
3031da177e4SLinus Torvalds 	return -ETIMEDOUT;
3041da177e4SLinus Torvalds }
3051da177e4SLinus Torvalds 
306b32ade12SFinn Thain static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
307b32ade12SFinn Thain                                         int reg, int bit, int val, int wait)
308b32ade12SFinn Thain {
309b32ade12SFinn Thain 	return NCR5380_poll_politely2(instance, reg, bit, val,
310b32ade12SFinn Thain 	                                        reg, bit, val, wait);
311b32ade12SFinn Thain }
312b32ade12SFinn Thain 
3131da177e4SLinus Torvalds static struct {
3141da177e4SLinus Torvalds 	unsigned char value;
3151da177e4SLinus Torvalds 	const char *name;
316702809ceSAndrew Morton } phases[] __maybe_unused = {
3171da177e4SLinus Torvalds 	{PHASE_DATAOUT, "DATAOUT"},
3181da177e4SLinus Torvalds 	{PHASE_DATAIN, "DATAIN"},
3191da177e4SLinus Torvalds 	{PHASE_CMDOUT, "CMDOUT"},
3201da177e4SLinus Torvalds 	{PHASE_STATIN, "STATIN"},
3211da177e4SLinus Torvalds 	{PHASE_MSGOUT, "MSGOUT"},
3221da177e4SLinus Torvalds 	{PHASE_MSGIN, "MSGIN"},
3231da177e4SLinus Torvalds 	{PHASE_UNKNOWN, "UNKNOWN"}
3241da177e4SLinus Torvalds };
3251da177e4SLinus Torvalds 
326185a7a1cSviro@ZenIV.linux.org.uk #if NDEBUG
3271da177e4SLinus Torvalds static struct {
3281da177e4SLinus Torvalds 	unsigned char mask;
3291da177e4SLinus Torvalds 	const char *name;
3301da177e4SLinus Torvalds } signals[] = {
3311da177e4SLinus Torvalds 	{SR_DBP, "PARITY"},
3321da177e4SLinus Torvalds 	{SR_RST, "RST"},
3331da177e4SLinus Torvalds 	{SR_BSY, "BSY"},
3341da177e4SLinus Torvalds 	{SR_REQ, "REQ"},
3351da177e4SLinus Torvalds 	{SR_MSG, "MSG"},
3361da177e4SLinus Torvalds 	{SR_CD, "CD"},
3371da177e4SLinus Torvalds 	{SR_IO, "IO"},
3381da177e4SLinus Torvalds 	{SR_SEL, "SEL"},
3391da177e4SLinus Torvalds 	{0, NULL}
3401da177e4SLinus Torvalds },
3411da177e4SLinus Torvalds basrs[] = {
3421da177e4SLinus Torvalds 	{BASR_ATN, "ATN"},
3431da177e4SLinus Torvalds 	{BASR_ACK, "ACK"},
3441da177e4SLinus Torvalds 	{0, NULL}
3451da177e4SLinus Torvalds },
3461da177e4SLinus Torvalds icrs[] = {
3471da177e4SLinus Torvalds 	{ICR_ASSERT_RST, "ASSERT RST"},
3481da177e4SLinus Torvalds 	{ICR_ASSERT_ACK, "ASSERT ACK"},
3491da177e4SLinus Torvalds 	{ICR_ASSERT_BSY, "ASSERT BSY"},
3501da177e4SLinus Torvalds 	{ICR_ASSERT_SEL, "ASSERT SEL"},
3511da177e4SLinus Torvalds 	{ICR_ASSERT_ATN, "ASSERT ATN"},
3521da177e4SLinus Torvalds 	{ICR_ASSERT_DATA, "ASSERT DATA"},
3531da177e4SLinus Torvalds 	{0, NULL}
3541da177e4SLinus Torvalds },
3551da177e4SLinus Torvalds mrs[] = {
3561da177e4SLinus Torvalds 	{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"},
3571da177e4SLinus Torvalds 	{MR_TARGET, "MODE TARGET"},
3581da177e4SLinus Torvalds 	{MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"},
3591da177e4SLinus Torvalds 	{MR_ENABLE_PAR_INTR, "MODE PARITY INTR"},
3601da177e4SLinus Torvalds 	{MR_MONITOR_BSY, "MODE MONITOR BSY"},
3611da177e4SLinus Torvalds 	{MR_DMA_MODE, "MODE DMA"},
3621da177e4SLinus Torvalds 	{MR_ARBITRATE, "MODE ARBITRATION"},
3631da177e4SLinus Torvalds 	{0, NULL}
3641da177e4SLinus Torvalds };
3651da177e4SLinus Torvalds 
3661da177e4SLinus Torvalds /**
3671da177e4SLinus Torvalds  *	NCR5380_print	-	print scsi bus signals
3681da177e4SLinus Torvalds  *	@instance:	adapter state to dump
3691da177e4SLinus Torvalds  *
3701da177e4SLinus Torvalds  *	Print the SCSI bus signals for debugging purposes
3711da177e4SLinus Torvalds  *
3721da177e4SLinus Torvalds  *	Locks: caller holds hostdata lock (not essential)
3731da177e4SLinus Torvalds  */
3741da177e4SLinus Torvalds 
3751da177e4SLinus Torvalds static void NCR5380_print(struct Scsi_Host *instance)
3761da177e4SLinus Torvalds {
3771da177e4SLinus Torvalds 	unsigned char status, data, basr, mr, icr, i;
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds 	data = NCR5380_read(CURRENT_SCSI_DATA_REG);
3801da177e4SLinus Torvalds 	status = NCR5380_read(STATUS_REG);
3811da177e4SLinus Torvalds 	mr = NCR5380_read(MODE_REG);
3821da177e4SLinus Torvalds 	icr = NCR5380_read(INITIATOR_COMMAND_REG);
3831da177e4SLinus Torvalds 	basr = NCR5380_read(BUS_AND_STATUS_REG);
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	printk("STATUS_REG: %02x ", status);
3861da177e4SLinus Torvalds 	for (i = 0; signals[i].mask; ++i)
3871da177e4SLinus Torvalds 		if (status & signals[i].mask)
3881da177e4SLinus Torvalds 			printk(",%s", signals[i].name);
3891da177e4SLinus Torvalds 	printk("\nBASR: %02x ", basr);
3901da177e4SLinus Torvalds 	for (i = 0; basrs[i].mask; ++i)
3911da177e4SLinus Torvalds 		if (basr & basrs[i].mask)
3921da177e4SLinus Torvalds 			printk(",%s", basrs[i].name);
3931da177e4SLinus Torvalds 	printk("\nICR: %02x ", icr);
3941da177e4SLinus Torvalds 	for (i = 0; icrs[i].mask; ++i)
3951da177e4SLinus Torvalds 		if (icr & icrs[i].mask)
3961da177e4SLinus Torvalds 			printk(",%s", icrs[i].name);
3971da177e4SLinus Torvalds 	printk("\nMODE: %02x ", mr);
3981da177e4SLinus Torvalds 	for (i = 0; mrs[i].mask; ++i)
3991da177e4SLinus Torvalds 		if (mr & mrs[i].mask)
4001da177e4SLinus Torvalds 			printk(",%s", mrs[i].name);
4011da177e4SLinus Torvalds 	printk("\n");
4021da177e4SLinus Torvalds }
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds 
4051da177e4SLinus Torvalds /*
4061da177e4SLinus Torvalds  *	NCR5380_print_phase	-	show SCSI phase
4071da177e4SLinus Torvalds  *	@instance: adapter to dump
4081da177e4SLinus Torvalds  *
4091da177e4SLinus Torvalds  * 	Print the current SCSI phase for debugging purposes
4101da177e4SLinus Torvalds  *
4111da177e4SLinus Torvalds  *	Locks: none
4121da177e4SLinus Torvalds  */
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds static void NCR5380_print_phase(struct Scsi_Host *instance)
4151da177e4SLinus Torvalds {
4161da177e4SLinus Torvalds 	unsigned char status;
4171da177e4SLinus Torvalds 	int i;
4181da177e4SLinus Torvalds 
4191da177e4SLinus Torvalds 	status = NCR5380_read(STATUS_REG);
4201da177e4SLinus Torvalds 	if (!(status & SR_REQ))
4216a6ff4acSFinn Thain 		shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n");
4221da177e4SLinus Torvalds 	else {
4231da177e4SLinus Torvalds 		for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
4246a6ff4acSFinn Thain 		shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name);
4251da177e4SLinus Torvalds 	}
4261da177e4SLinus Torvalds }
4271da177e4SLinus Torvalds #endif
4281da177e4SLinus Torvalds 
4291da177e4SLinus Torvalds 
430d5f7e65dSFinn Thain static int probe_irq __initdata;
4311da177e4SLinus Torvalds 
4321da177e4SLinus Torvalds /**
4331da177e4SLinus Torvalds  *	probe_intr	-	helper for IRQ autoprobe
4341da177e4SLinus Torvalds  *	@irq: interrupt number
4351da177e4SLinus Torvalds  *	@dev_id: unused
4361da177e4SLinus Torvalds  *	@regs: unused
4371da177e4SLinus Torvalds  *
4381da177e4SLinus Torvalds  *	Set a flag to indicate the IRQ in question was received. This is
4391da177e4SLinus Torvalds  *	used by the IRQ probe code.
4401da177e4SLinus Torvalds  */
4411da177e4SLinus Torvalds 
4427d12e780SDavid Howells static irqreturn_t __init probe_intr(int irq, void *dev_id)
4431da177e4SLinus Torvalds {
4441da177e4SLinus Torvalds 	probe_irq = irq;
4451da177e4SLinus Torvalds 	return IRQ_HANDLED;
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds /**
4491da177e4SLinus Torvalds  *	NCR5380_probe_irq	-	find the IRQ of an NCR5380
4501da177e4SLinus Torvalds  *	@instance: NCR5380 controller
4511da177e4SLinus Torvalds  *	@possible: bitmask of ISA IRQ lines
4521da177e4SLinus Torvalds  *
4531da177e4SLinus Torvalds  *	Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
4541da177e4SLinus Torvalds  *	and then looking to see what interrupt actually turned up.
4551da177e4SLinus Torvalds  *
4561da177e4SLinus Torvalds  *	Locks: none, irqs must be enabled on entry
4571da177e4SLinus Torvalds  */
4581da177e4SLinus Torvalds 
459702809ceSAndrew Morton static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
460702809ceSAndrew Morton 						int possible)
4611da177e4SLinus Torvalds {
462e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
4631da177e4SLinus Torvalds 	unsigned long timeout;
4641da177e4SLinus Torvalds 	int trying_irqs, i, mask;
4651da177e4SLinus Torvalds 
46622f5f10dSFinn Thain 	for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
4674909cc2bSMichael Opdenacker 		if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
4681da177e4SLinus Torvalds 			trying_irqs |= mask;
4691da177e4SLinus Torvalds 
4704e5a800cSNicholas Mc Guire 	timeout = jiffies + msecs_to_jiffies(250);
47122f5f10dSFinn Thain 	probe_irq = NO_IRQ;
4721da177e4SLinus Torvalds 
4731da177e4SLinus Torvalds 	/*
4741da177e4SLinus Torvalds 	 * A interrupt is triggered whenever BSY = false, SEL = true
4751da177e4SLinus Torvalds 	 * and a bit set in the SELECT_ENABLE_REG is asserted on the
4761da177e4SLinus Torvalds 	 * SCSI bus.
4771da177e4SLinus Torvalds 	 *
4781da177e4SLinus Torvalds 	 * Note that the bus is only driven when the phase control signals
4791da177e4SLinus Torvalds 	 * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
4801da177e4SLinus Torvalds 	 * to zero.
4811da177e4SLinus Torvalds 	 */
4821da177e4SLinus Torvalds 
4831da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, 0);
4841da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
4851da177e4SLinus Torvalds 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
4861da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
4871da177e4SLinus Torvalds 
48822f5f10dSFinn Thain 	while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
489a9a3047dSNishanth Aravamudan 		schedule_timeout_uninterruptible(1);
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, 0);
4921da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
4931da177e4SLinus Torvalds 
49422f5f10dSFinn Thain 	for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
4951da177e4SLinus Torvalds 		if (trying_irqs & mask)
4961da177e4SLinus Torvalds 			free_irq(i, NULL);
4971da177e4SLinus Torvalds 
4981da177e4SLinus Torvalds 	return probe_irq;
4991da177e4SLinus Torvalds }
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds /**
5028c32513bSFinn Thain  *	NCR58380_info - report driver and host information
5038c32513bSFinn Thain  *	@instance: relevant scsi host instance
5041da177e4SLinus Torvalds  *
5058c32513bSFinn Thain  *	For use as the host template info() handler.
5061da177e4SLinus Torvalds  *
5071da177e4SLinus Torvalds  *	Locks: none
5081da177e4SLinus Torvalds  */
5091da177e4SLinus Torvalds 
5108c32513bSFinn Thain static const char *NCR5380_info(struct Scsi_Host *instance)
5111da177e4SLinus Torvalds {
5128c32513bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
5138c32513bSFinn Thain 
5148c32513bSFinn Thain 	return hostdata->info;
5158c32513bSFinn Thain }
5168c32513bSFinn Thain 
5178c32513bSFinn Thain static void prepare_info(struct Scsi_Host *instance)
5188c32513bSFinn Thain {
5198c32513bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
5208c32513bSFinn Thain 
5218c32513bSFinn Thain 	snprintf(hostdata->info, sizeof(hostdata->info),
5228c32513bSFinn Thain 	         "%s, io_port 0x%lx, n_io_port %d, "
5238c32513bSFinn Thain 	         "base 0x%lx, irq %d, "
5248c32513bSFinn Thain 	         "can_queue %d, cmd_per_lun %d, "
5258c32513bSFinn Thain 	         "sg_tablesize %d, this_id %d, "
526be3f4121SFinn Thain 	         "flags { %s%s%s}, "
5278c32513bSFinn Thain 	         "options { %s} ",
5288c32513bSFinn Thain 	         instance->hostt->name, instance->io_port, instance->n_io_port,
5298c32513bSFinn Thain 	         instance->base, instance->irq,
5308c32513bSFinn Thain 	         instance->can_queue, instance->cmd_per_lun,
5318c32513bSFinn Thain 	         instance->sg_tablesize, instance->this_id,
53255181be8SFinn Thain 	         hostdata->flags & FLAG_NO_DMA_FIXUP  ? "NO_DMA_FIXUP "  : "",
5338c32513bSFinn Thain 	         hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
5349c3f0e2bSFinn Thain 	         hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY "  : "",
5351da177e4SLinus Torvalds #ifdef AUTOPROBE_IRQ
5361da177e4SLinus Torvalds 	         "AUTOPROBE_IRQ "
5371da177e4SLinus Torvalds #endif
5381da177e4SLinus Torvalds #ifdef DIFFERENTIAL
5391da177e4SLinus Torvalds 	         "DIFFERENTIAL "
5401da177e4SLinus Torvalds #endif
5411da177e4SLinus Torvalds #ifdef REAL_DMA
5428c32513bSFinn Thain 	         "REAL_DMA "
5431da177e4SLinus Torvalds #endif
5441da177e4SLinus Torvalds #ifdef REAL_DMA_POLL
5458c32513bSFinn Thain 	         "REAL_DMA_POLL "
5461da177e4SLinus Torvalds #endif
5471da177e4SLinus Torvalds #ifdef PARITY
5481da177e4SLinus Torvalds 	         "PARITY "
5491da177e4SLinus Torvalds #endif
5501da177e4SLinus Torvalds #ifdef PSEUDO_DMA
5518c32513bSFinn Thain 	         "PSEUDO_DMA "
5521da177e4SLinus Torvalds #endif
5538c32513bSFinn Thain 	         "");
5541da177e4SLinus Torvalds }
5551da177e4SLinus Torvalds 
556a9c2dc43SFinn Thain #ifdef PSEUDO_DMA
5571da177e4SLinus Torvalds /******************************************/
5581da177e4SLinus Torvalds /*
5591da177e4SLinus Torvalds  * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
5601da177e4SLinus Torvalds  *
5611da177e4SLinus Torvalds  * *buffer: I/O buffer
5621da177e4SLinus Torvalds  * **start: if inout == FALSE pointer into buffer where user read should start
5631da177e4SLinus Torvalds  * offset: current offset
5641da177e4SLinus Torvalds  * length: length of buffer
5651da177e4SLinus Torvalds  * hostno: Scsi_Host host_no
5661da177e4SLinus Torvalds  * inout: TRUE - user is writing; FALSE - user is reading
5671da177e4SLinus Torvalds  *
5681da177e4SLinus Torvalds  * Return the number of bytes read from or written
5691da177e4SLinus Torvalds  */
5701da177e4SLinus Torvalds 
571dd7ab71bSAl Viro static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
572dd7ab71bSAl Viro 	char *buffer, int length)
5731da177e4SLinus Torvalds {
574a9c2dc43SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
575a9c2dc43SFinn Thain 
576a9c2dc43SFinn Thain 	hostdata->spin_max_r = 0;
577a9c2dc43SFinn Thain 	hostdata->spin_max_w = 0;
578a9c2dc43SFinn Thain 	return 0;
5791da177e4SLinus Torvalds }
580dd7ab71bSAl Viro 
581dd7ab71bSAl Viro static int __maybe_unused NCR5380_show_info(struct seq_file *m,
582dd7ab71bSAl Viro 	struct Scsi_Host *instance)
583dd7ab71bSAl Viro {
584e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
585dd7ab71bSAl Viro 
5860c3de38fSRasmus Villemoes 	seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n",
587a9c2dc43SFinn Thain 	        hostdata->spin_max_w, hostdata->spin_max_r);
5881da177e4SLinus Torvalds 	return 0;
5891da177e4SLinus Torvalds }
590e5c3fddfSFinn Thain #endif
5911da177e4SLinus Torvalds 
5921da177e4SLinus Torvalds /**
5931da177e4SLinus Torvalds  *	NCR5380_init	-	initialise an NCR5380
5941da177e4SLinus Torvalds  *	@instance: adapter to configure
5951da177e4SLinus Torvalds  *	@flags: control flags
5961da177e4SLinus Torvalds  *
5971da177e4SLinus Torvalds  *	Initializes *instance and corresponding 5380 chip,
5981da177e4SLinus Torvalds  *      with flags OR'd into the initial flags value.
5991da177e4SLinus Torvalds  *
6001da177e4SLinus Torvalds  *	Notes : I assume that the host, hostno, and id bits have been
6011da177e4SLinus Torvalds  *      set correctly.  I don't care about the irq and other fields.
6021da177e4SLinus Torvalds  *
6031da177e4SLinus Torvalds  *	Returns 0 for success
6041da177e4SLinus Torvalds  *
6051da177e4SLinus Torvalds  *	Locks: interrupts must be enabled when we are called
6061da177e4SLinus Torvalds  */
6071da177e4SLinus Torvalds 
6086f039790SGreg Kroah-Hartman static int NCR5380_init(struct Scsi_Host *instance, int flags)
6091da177e4SLinus Torvalds {
610e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
611b6488f97SFinn Thain 	int i;
6122f854b82SFinn Thain 	unsigned long deadline;
6131da177e4SLinus Torvalds 
6141da177e4SLinus Torvalds 	if(in_interrupt())
6151da177e4SLinus Torvalds 		printk(KERN_ERR "NCR5380_init called with interrupts off!\n");
6161da177e4SLinus Torvalds 
6171da177e4SLinus Torvalds 	hostdata->id_mask = 1 << instance->this_id;
6181da177e4SLinus Torvalds 	for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
6191da177e4SLinus Torvalds 		if (i > hostdata->id_mask)
6201da177e4SLinus Torvalds 			hostdata->id_higher_mask |= i;
6211da177e4SLinus Torvalds 	for (i = 0; i < 8; ++i)
6221da177e4SLinus Torvalds 		hostdata->busy[i] = 0;
6231da177e4SLinus Torvalds #ifdef REAL_DMA
6241da177e4SLinus Torvalds 	hostdata->dmalen = 0;
6251da177e4SLinus Torvalds #endif
62611d2f63bSFinn Thain 	spin_lock_init(&hostdata->lock);
6271da177e4SLinus Torvalds 	hostdata->connected = NULL;
628f27db8ebSFinn Thain 	hostdata->sensing = NULL;
629f27db8ebSFinn Thain 	INIT_LIST_HEAD(&hostdata->autosense);
63032b26a10SFinn Thain 	INIT_LIST_HEAD(&hostdata->unissued);
63132b26a10SFinn Thain 	INIT_LIST_HEAD(&hostdata->disconnected);
63232b26a10SFinn Thain 
63355181be8SFinn Thain 	hostdata->flags = flags;
6341da177e4SLinus Torvalds 
6358d8601a7SFinn Thain 	INIT_WORK(&hostdata->main_task, NCR5380_main);
6360ad0eff9SFinn Thain 	hostdata->work_q = alloc_workqueue("ncr5380_%d",
6370ad0eff9SFinn Thain 	                        WQ_UNBOUND | WQ_MEM_RECLAIM,
6380ad0eff9SFinn Thain 	                        1, instance->host_no);
6390ad0eff9SFinn Thain 	if (!hostdata->work_q)
6400ad0eff9SFinn Thain 		return -ENOMEM;
6411da177e4SLinus Torvalds 
6421da177e4SLinus Torvalds 	hostdata->host = instance;
6431da177e4SLinus Torvalds 
6448c32513bSFinn Thain 	prepare_info(instance);
6458c32513bSFinn Thain 
6461da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
6471da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
6481da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, 0);
6491da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, 0);
6502f854b82SFinn Thain 
6512f854b82SFinn Thain 	/* Calibrate register polling loop */
6522f854b82SFinn Thain 	i = 0;
6532f854b82SFinn Thain 	deadline = jiffies + 1;
6542f854b82SFinn Thain 	do {
6552f854b82SFinn Thain 		cpu_relax();
6562f854b82SFinn Thain 	} while (time_is_after_jiffies(deadline));
6572f854b82SFinn Thain 	deadline += msecs_to_jiffies(256);
6582f854b82SFinn Thain 	do {
6592f854b82SFinn Thain 		NCR5380_read(STATUS_REG);
6602f854b82SFinn Thain 		++i;
6612f854b82SFinn Thain 		cpu_relax();
6622f854b82SFinn Thain 	} while (time_is_after_jiffies(deadline));
6632f854b82SFinn Thain 	hostdata->accesses_per_ms = i / 256;
6642f854b82SFinn Thain 
665b6488f97SFinn Thain 	return 0;
666b6488f97SFinn Thain }
6671da177e4SLinus Torvalds 
668b6488f97SFinn Thain /**
669b6488f97SFinn Thain  * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems.
670b6488f97SFinn Thain  * @instance: adapter to check
6711da177e4SLinus Torvalds  *
672b6488f97SFinn Thain  * If the system crashed, it may have crashed with a connected target and
673b6488f97SFinn Thain  * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the
674b6488f97SFinn Thain  * currently established nexus, which we know nothing about. Failing that
675b6488f97SFinn Thain  * do a bus reset.
6761da177e4SLinus Torvalds  *
677b6488f97SFinn Thain  * Note that a bus reset will cause the chip to assert IRQ.
678b6488f97SFinn Thain  *
679b6488f97SFinn Thain  * Returns 0 if successful, otherwise -ENXIO.
6801da177e4SLinus Torvalds  */
6811da177e4SLinus Torvalds 
682b6488f97SFinn Thain static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
683b6488f97SFinn Thain {
6849c3f0e2bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
685b6488f97SFinn Thain 	int pass;
686b6488f97SFinn Thain 
6871da177e4SLinus Torvalds 	for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
6881da177e4SLinus Torvalds 		switch (pass) {
6891da177e4SLinus Torvalds 		case 1:
6901da177e4SLinus Torvalds 		case 3:
6911da177e4SLinus Torvalds 		case 5:
692636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n");
693636b1ec8SFinn Thain 			NCR5380_poll_politely(instance,
694636b1ec8SFinn Thain 			                      STATUS_REG, SR_BSY, 0, 5 * HZ);
6951da177e4SLinus Torvalds 			break;
6961da177e4SLinus Torvalds 		case 2:
697636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n");
6981da177e4SLinus Torvalds 			do_abort(instance);
6991da177e4SLinus Torvalds 			break;
7001da177e4SLinus Torvalds 		case 4:
701636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n");
7021da177e4SLinus Torvalds 			do_reset(instance);
7039c3f0e2bSFinn Thain 			/* Wait after a reset; the SCSI standard calls for
7049c3f0e2bSFinn Thain 			 * 250ms, we wait 500ms to be on the safe side.
7059c3f0e2bSFinn Thain 			 * But some Toshiba CD-ROMs need ten times that.
7069c3f0e2bSFinn Thain 			 */
7079c3f0e2bSFinn Thain 			if (hostdata->flags & FLAG_TOSHIBA_DELAY)
7089c3f0e2bSFinn Thain 				msleep(2500);
7099c3f0e2bSFinn Thain 			else
7109c3f0e2bSFinn Thain 				msleep(500);
7111da177e4SLinus Torvalds 			break;
7121da177e4SLinus Torvalds 		case 6:
713636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "bus locked solid\n");
7141da177e4SLinus Torvalds 			return -ENXIO;
7151da177e4SLinus Torvalds 		}
7161da177e4SLinus Torvalds 	}
7171da177e4SLinus Torvalds 	return 0;
7181da177e4SLinus Torvalds }
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds /**
7211da177e4SLinus Torvalds  *	NCR5380_exit	-	remove an NCR5380
7221da177e4SLinus Torvalds  *	@instance: adapter to remove
7231da177e4SLinus Torvalds  */
7241da177e4SLinus Torvalds 
725a43cf0f3SRandy Dunlap static void NCR5380_exit(struct Scsi_Host *instance)
7261da177e4SLinus Torvalds {
727e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
7281da177e4SLinus Torvalds 
7298d8601a7SFinn Thain 	cancel_work_sync(&hostdata->main_task);
7300ad0eff9SFinn Thain 	destroy_workqueue(hostdata->work_q);
7311da177e4SLinus Torvalds }
7321da177e4SLinus Torvalds 
7331da177e4SLinus Torvalds /**
734677e0194SFinn Thain  * complete_cmd - finish processing a command and return it to the SCSI ML
735677e0194SFinn Thain  * @instance: the host instance
736677e0194SFinn Thain  * @cmd: command to complete
737677e0194SFinn Thain  */
738677e0194SFinn Thain 
739677e0194SFinn Thain static void complete_cmd(struct Scsi_Host *instance,
740677e0194SFinn Thain                          struct scsi_cmnd *cmd)
741677e0194SFinn Thain {
742677e0194SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
743677e0194SFinn Thain 
744677e0194SFinn Thain 	dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd);
745677e0194SFinn Thain 
746f27db8ebSFinn Thain 	if (hostdata->sensing == cmd) {
747f27db8ebSFinn Thain 		/* Autosense processing ends here */
748f27db8ebSFinn Thain 		if ((cmd->result & 0xff) != SAM_STAT_GOOD) {
749f27db8ebSFinn Thain 			scsi_eh_restore_cmnd(cmd, &hostdata->ses);
750f27db8ebSFinn Thain 			set_host_byte(cmd, DID_ERROR);
751f27db8ebSFinn Thain 		} else
752f27db8ebSFinn Thain 			scsi_eh_restore_cmnd(cmd, &hostdata->ses);
753f27db8ebSFinn Thain 		hostdata->sensing = NULL;
754f27db8ebSFinn Thain 	}
755f27db8ebSFinn Thain 
756677e0194SFinn Thain 	hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun);
757677e0194SFinn Thain 
758677e0194SFinn Thain 	cmd->scsi_done(cmd);
759677e0194SFinn Thain }
760677e0194SFinn Thain 
761677e0194SFinn Thain /**
7621da177e4SLinus Torvalds  * NCR5380_queue_command - queue a command
7631bb40589SFinn Thain  * @instance: the relevant SCSI adapter
7641da177e4SLinus Torvalds  * @cmd: SCSI command
7651da177e4SLinus Torvalds  *
7661bb40589SFinn Thain  * cmd is added to the per-instance issue queue, with minor
7671da177e4SLinus Torvalds  * twiddling done to the host specific fields of cmd.  If the
7681da177e4SLinus Torvalds  * main coroutine is not running, it is restarted.
7691da177e4SLinus Torvalds  */
7701da177e4SLinus Torvalds 
7711bb40589SFinn Thain static int NCR5380_queue_command(struct Scsi_Host *instance,
7721bb40589SFinn Thain                                  struct scsi_cmnd *cmd)
7731da177e4SLinus Torvalds {
7741bb40589SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
77532b26a10SFinn Thain 	struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
7761bb40589SFinn Thain 	unsigned long flags;
7771da177e4SLinus Torvalds 
7781da177e4SLinus Torvalds #if (NDEBUG & NDEBUG_NO_WRITE)
7791da177e4SLinus Torvalds 	switch (cmd->cmnd[0]) {
7801da177e4SLinus Torvalds 	case WRITE_6:
7811da177e4SLinus Torvalds 	case WRITE_10:
782dbb6b350SFinn Thain 		shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n");
7831da177e4SLinus Torvalds 		cmd->result = (DID_ERROR << 16);
7841bb40589SFinn Thain 		cmd->scsi_done(cmd);
7851da177e4SLinus Torvalds 		return 0;
7861da177e4SLinus Torvalds 	}
7871da177e4SLinus Torvalds #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
7881da177e4SLinus Torvalds 
7891da177e4SLinus Torvalds 	cmd->result = 0;
7901da177e4SLinus Torvalds 
79111d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
7921bb40589SFinn Thain 
7931da177e4SLinus Torvalds 	/*
7941da177e4SLinus Torvalds 	 * Insert the cmd into the issue queue. Note that REQUEST SENSE
7951da177e4SLinus Torvalds 	 * commands are added to the head of the queue since any command will
7961da177e4SLinus Torvalds 	 * clear the contingent allegiance condition that exists and the
7971da177e4SLinus Torvalds 	 * sense data is only guaranteed to be valid while the condition exists.
7981da177e4SLinus Torvalds 	 */
7991da177e4SLinus Torvalds 
80032b26a10SFinn Thain 	if (cmd->cmnd[0] == REQUEST_SENSE)
80132b26a10SFinn Thain 		list_add(&ncmd->list, &hostdata->unissued);
80232b26a10SFinn Thain 	else
80332b26a10SFinn Thain 		list_add_tail(&ncmd->list, &hostdata->unissued);
80432b26a10SFinn Thain 
80511d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
8061bb40589SFinn Thain 
807dbb6b350SFinn Thain 	dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n",
808dbb6b350SFinn Thain 	         cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
8091da177e4SLinus Torvalds 
8101da177e4SLinus Torvalds 	/* Kick off command processing */
8118d8601a7SFinn Thain 	queue_work(hostdata->work_q, &hostdata->main_task);
8121da177e4SLinus Torvalds 	return 0;
8131da177e4SLinus Torvalds }
8141da177e4SLinus Torvalds 
8151da177e4SLinus Torvalds /**
816f27db8ebSFinn Thain  * dequeue_next_cmd - dequeue a command for processing
817f27db8ebSFinn Thain  * @instance: the scsi host instance
818f27db8ebSFinn Thain  *
819f27db8ebSFinn Thain  * Priority is given to commands on the autosense queue. These commands
820f27db8ebSFinn Thain  * need autosense because of a CHECK CONDITION result.
821f27db8ebSFinn Thain  *
822f27db8ebSFinn Thain  * Returns a command pointer if a command is found for a target that is
823f27db8ebSFinn Thain  * not already busy. Otherwise returns NULL.
824f27db8ebSFinn Thain  */
825f27db8ebSFinn Thain 
826f27db8ebSFinn Thain static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance)
827f27db8ebSFinn Thain {
828f27db8ebSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
829f27db8ebSFinn Thain 	struct NCR5380_cmd *ncmd;
830f27db8ebSFinn Thain 	struct scsi_cmnd *cmd;
831f27db8ebSFinn Thain 
832f27db8ebSFinn Thain 	if (list_empty(&hostdata->autosense)) {
833f27db8ebSFinn Thain 		list_for_each_entry(ncmd, &hostdata->unissued, list) {
834f27db8ebSFinn Thain 			cmd = NCR5380_to_scmd(ncmd);
835f27db8ebSFinn Thain 			dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n",
836f27db8ebSFinn Thain 			         cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun);
837f27db8ebSFinn Thain 
838f27db8ebSFinn Thain 			if (!(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun))) {
839f27db8ebSFinn Thain 				list_del(&ncmd->list);
840f27db8ebSFinn Thain 				dsprintk(NDEBUG_QUEUES, instance,
841f27db8ebSFinn Thain 				         "dequeue: removed %p from issue queue\n", cmd);
842f27db8ebSFinn Thain 				return cmd;
843f27db8ebSFinn Thain 			}
844f27db8ebSFinn Thain 		}
845f27db8ebSFinn Thain 	} else {
846f27db8ebSFinn Thain 		/* Autosense processing begins here */
847f27db8ebSFinn Thain 		ncmd = list_first_entry(&hostdata->autosense,
848f27db8ebSFinn Thain 		                        struct NCR5380_cmd, list);
849f27db8ebSFinn Thain 		list_del(&ncmd->list);
850f27db8ebSFinn Thain 		cmd = NCR5380_to_scmd(ncmd);
851f27db8ebSFinn Thain 		dsprintk(NDEBUG_QUEUES, instance,
852f27db8ebSFinn Thain 		         "dequeue: removed %p from autosense queue\n", cmd);
853f27db8ebSFinn Thain 		scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
854f27db8ebSFinn Thain 		hostdata->sensing = cmd;
855f27db8ebSFinn Thain 		return cmd;
856f27db8ebSFinn Thain 	}
857f27db8ebSFinn Thain 	return NULL;
858f27db8ebSFinn Thain }
859f27db8ebSFinn Thain 
860f27db8ebSFinn Thain static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
861f27db8ebSFinn Thain {
862f27db8ebSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
863f27db8ebSFinn Thain 	struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
864f27db8ebSFinn Thain 
865f27db8ebSFinn Thain 	if (hostdata->sensing) {
866f27db8ebSFinn Thain 		scsi_eh_restore_cmnd(cmd, &hostdata->ses);
867f27db8ebSFinn Thain 		list_add(&ncmd->list, &hostdata->autosense);
868f27db8ebSFinn Thain 		hostdata->sensing = NULL;
869f27db8ebSFinn Thain 	} else
870f27db8ebSFinn Thain 		list_add(&ncmd->list, &hostdata->unissued);
871f27db8ebSFinn Thain }
872f27db8ebSFinn Thain 
873f27db8ebSFinn Thain /**
8741da177e4SLinus Torvalds  *	NCR5380_main	-	NCR state machines
8751da177e4SLinus Torvalds  *
8761da177e4SLinus Torvalds  *	NCR5380_main is a coroutine that runs as long as more work can
8771da177e4SLinus Torvalds  *      be done on the NCR5380 host adapters in a system.  Both
8781da177e4SLinus Torvalds  *      NCR5380_queue_command() and NCR5380_intr() will try to start it
8791da177e4SLinus Torvalds  *      in case it is not running.
8801da177e4SLinus Torvalds  *
8811da177e4SLinus Torvalds  *	Locks: called as its own thread with no locks held. Takes the
8821da177e4SLinus Torvalds  *	host lock and called routines may take the isa dma lock.
8831da177e4SLinus Torvalds  */
8841da177e4SLinus Torvalds 
885c4028958SDavid Howells static void NCR5380_main(struct work_struct *work)
8861da177e4SLinus Torvalds {
887c4028958SDavid Howells 	struct NCR5380_hostdata *hostdata =
8888d8601a7SFinn Thain 		container_of(work, struct NCR5380_hostdata, main_task);
8891da177e4SLinus Torvalds 	struct Scsi_Host *instance = hostdata->host;
890f27db8ebSFinn Thain 	struct scsi_cmnd *cmd;
8911da177e4SLinus Torvalds 	int done;
8921da177e4SLinus Torvalds 
89311d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
8941da177e4SLinus Torvalds 	do {
8951da177e4SLinus Torvalds 		done = 1;
89611d2f63bSFinn Thain 
897f27db8ebSFinn Thain 		while (!hostdata->connected &&
898f27db8ebSFinn Thain 		       (cmd = dequeue_next_cmd(instance))) {
89932b26a10SFinn Thain 
900f27db8ebSFinn Thain 			dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd);
9011da177e4SLinus Torvalds 
9021da177e4SLinus Torvalds 			/*
9031da177e4SLinus Torvalds 			 * Attempt to establish an I_T_L nexus here.
9041da177e4SLinus Torvalds 			 * On success, instance->hostdata->connected is set.
9051da177e4SLinus Torvalds 			 * On failure, we must add the command back to the
9061da177e4SLinus Torvalds 			 * issue queue so we can keep trying.
9071da177e4SLinus Torvalds 			 */
9081da177e4SLinus Torvalds 			/*
9091da177e4SLinus Torvalds 			 * REQUEST SENSE commands are issued without tagged
9101da177e4SLinus Torvalds 			 * queueing, even on SCSI-II devices because the
9111da177e4SLinus Torvalds 			 * contingent allegiance condition exists for the
9121da177e4SLinus Torvalds 			 * entire unit.
9131da177e4SLinus Torvalds 			 */
91476f13b93SFinn Thain 
915707d62b3SFinn Thain 			cmd = NCR5380_select(instance, cmd);
916707d62b3SFinn Thain 			if (!cmd) {
917707d62b3SFinn Thain 				dsprintk(NDEBUG_MAIN, instance, "main: select complete\n");
9181da177e4SLinus Torvalds 			} else {
919f27db8ebSFinn Thain 				dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance,
920f27db8ebSFinn Thain 				         "main: select failed, returning %p to queue\n", cmd);
921f27db8ebSFinn Thain 				requeue_cmd(instance, cmd);
9221da177e4SLinus Torvalds 			}
923f27db8ebSFinn Thain 		}
9241da177e4SLinus Torvalds 		if (hostdata->connected
9251da177e4SLinus Torvalds #ifdef REAL_DMA
9261da177e4SLinus Torvalds 		    && !hostdata->dmalen
9271da177e4SLinus Torvalds #endif
9281da177e4SLinus Torvalds 		    ) {
929*b746545fSFinn Thain 			dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n");
9301da177e4SLinus Torvalds 			NCR5380_information_transfer(instance);
9311da177e4SLinus Torvalds 			done = 0;
9321d3db59dSFinn Thain 		}
9331da177e4SLinus Torvalds 	} while (!done);
93411d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
9351da177e4SLinus Torvalds }
9361da177e4SLinus Torvalds 
9371da177e4SLinus Torvalds #ifndef DONT_USE_INTR
9381da177e4SLinus Torvalds 
9391da177e4SLinus Torvalds /**
9401da177e4SLinus Torvalds  * NCR5380_intr - generic NCR5380 irq handler
9411da177e4SLinus Torvalds  * @irq: interrupt number
9421da177e4SLinus Torvalds  * @dev_id: device info
9431da177e4SLinus Torvalds  *
9441da177e4SLinus Torvalds  * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
9451da177e4SLinus Torvalds  * from the disconnected queue, and restarting NCR5380_main()
9461da177e4SLinus Torvalds  * as required.
9471da177e4SLinus Torvalds  *
948cd400825SFinn Thain  * The chip can assert IRQ in any of six different conditions. The IRQ flag
949cd400825SFinn Thain  * is then cleared by reading the Reset Parity/Interrupt Register (RPIR).
950cd400825SFinn Thain  * Three of these six conditions are latched in the Bus and Status Register:
951cd400825SFinn Thain  * - End of DMA (cleared by ending DMA Mode)
952cd400825SFinn Thain  * - Parity error (cleared by reading RPIR)
953cd400825SFinn Thain  * - Loss of BSY (cleared by reading RPIR)
954cd400825SFinn Thain  * Two conditions have flag bits that are not latched:
955cd400825SFinn Thain  * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode)
956cd400825SFinn Thain  * - Bus reset (non-maskable)
957cd400825SFinn Thain  * The remaining condition has no flag bit at all:
958cd400825SFinn Thain  * - Selection/reselection
959cd400825SFinn Thain  *
960cd400825SFinn Thain  * Hence, establishing the cause(s) of any interrupt is partly guesswork.
961cd400825SFinn Thain  * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor
962cd400825SFinn Thain  * claimed that "the design of the [DP8490] interrupt logic ensures
963cd400825SFinn Thain  * interrupts will not be lost (they can be on the DP5380)."
964cd400825SFinn Thain  * The L5380/53C80 datasheet from LOGIC Devices has more details.
965cd400825SFinn Thain  *
966cd400825SFinn Thain  * Checking for bus reset by reading RST is futile because of interrupt
967cd400825SFinn Thain  * latency, but a bus reset will reset chip logic. Checking for parity error
968cd400825SFinn Thain  * is unnecessary because that interrupt is never enabled. A Loss of BSY
969cd400825SFinn Thain  * condition will clear DMA Mode. We can tell when this occurs because the
970cd400825SFinn Thain  * the Busy Monitor interrupt is enabled together with DMA Mode.
9711da177e4SLinus Torvalds  */
9721da177e4SLinus Torvalds 
973cd400825SFinn Thain static irqreturn_t NCR5380_intr(int irq, void *dev_id)
9741da177e4SLinus Torvalds {
975baa9aac6SJeff Garzik 	struct Scsi_Host *instance = dev_id;
976cd400825SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
977cd400825SFinn Thain 	int handled = 0;
9781da177e4SLinus Torvalds 	unsigned char basr;
9791da177e4SLinus Torvalds 	unsigned long flags;
9801da177e4SLinus Torvalds 
98111d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
982cd400825SFinn Thain 
9831da177e4SLinus Torvalds 	basr = NCR5380_read(BUS_AND_STATUS_REG);
9841da177e4SLinus Torvalds 	if (basr & BASR_IRQ) {
985cd400825SFinn Thain 		unsigned char mr = NCR5380_read(MODE_REG);
986cd400825SFinn Thain 		unsigned char sr = NCR5380_read(STATUS_REG);
987cd400825SFinn Thain 
988*b746545fSFinn Thain 		dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n",
989*b746545fSFinn Thain 		         irq, basr, sr, mr);
990cd400825SFinn Thain 
9911da177e4SLinus Torvalds #if defined(REAL_DMA)
992cd400825SFinn Thain 		if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) {
993cd400825SFinn Thain 			/* Probably End of DMA, Phase Mismatch or Loss of BSY.
994cd400825SFinn Thain 			 * We ack IRQ after clearing Mode Register. Workarounds
995cd400825SFinn Thain 			 * for End of DMA errata need to happen in DMA Mode.
9961da177e4SLinus Torvalds 			 */
9971da177e4SLinus Torvalds 
998*b746545fSFinn Thain 			dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n");
999cd400825SFinn Thain 
100025985edcSLucas De Marchi 			int transferred;
10011da177e4SLinus Torvalds 
10021da177e4SLinus Torvalds 			if (!hostdata->connected)
1003cd400825SFinn Thain 				panic("scsi%d : DMA interrupt with no connected cmd\n",
1004cd400825SFinn Thain 				      instance->hostno);
10051da177e4SLinus Torvalds 
1006cd400825SFinn Thain 			transferred = hostdata->dmalen - NCR5380_dma_residual(instance);
10071da177e4SLinus Torvalds 			hostdata->connected->SCp.this_residual -= transferred;
10081da177e4SLinus Torvalds 			hostdata->connected->SCp.ptr += transferred;
10091da177e4SLinus Torvalds 			hostdata->dmalen = 0;
10101da177e4SLinus Torvalds 
10111da177e4SLinus Torvalds 			/* FIXME: we need to poll briefly then defer a workqueue task ! */
10121da177e4SLinus Torvalds 			NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2 * HZ);
10131da177e4SLinus Torvalds 
10141da177e4SLinus Torvalds 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1015cd400825SFinn Thain 			NCR5380_write(MODE_REG, MR_BASE);
1016cd400825SFinn Thain 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
1017cd400825SFinn Thain 		} else
1018cd400825SFinn Thain #endif /* REAL_DMA */
1019cd400825SFinn Thain 		if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) &&
1020cd400825SFinn Thain 		    (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) {
1021cd400825SFinn Thain 			/* Probably reselected */
1022cd400825SFinn Thain 			NCR5380_write(SELECT_ENABLE_REG, 0);
1023cd400825SFinn Thain 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
1024cd400825SFinn Thain 
1025*b746545fSFinn Thain 			dsprintk(NDEBUG_INTR, instance, "interrupt with SEL and IO\n");
1026cd400825SFinn Thain 
1027cd400825SFinn Thain 			if (!hostdata->connected) {
1028cd400825SFinn Thain 				NCR5380_reselect(instance);
10298d8601a7SFinn Thain 				queue_work(hostdata->work_q, &hostdata->main_task);
1030cd400825SFinn Thain 			}
1031cd400825SFinn Thain 			if (!hostdata->connected)
1032cd400825SFinn Thain 				NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1033cd400825SFinn Thain 		} else {
1034cd400825SFinn Thain 			/* Probably Bus Reset */
1035cd400825SFinn Thain 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
1036cd400825SFinn Thain 
1037*b746545fSFinn Thain 			dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n");
1038cd400825SFinn Thain 		}
1039cd400825SFinn Thain 		handled = 1;
1040cd400825SFinn Thain 	} else {
1041cd400825SFinn Thain 		shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n");
1042cd400825SFinn Thain 	}
1043cd400825SFinn Thain 
104411d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
1045cd400825SFinn Thain 
1046cd400825SFinn Thain 	return IRQ_RETVAL(handled);
10471da177e4SLinus Torvalds }
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds #endif
10501da177e4SLinus Torvalds 
10511da177e4SLinus Torvalds /*
1052710ddd0dSFinn Thain  * Function : int NCR5380_select(struct Scsi_Host *instance,
1053710ddd0dSFinn Thain  *                               struct scsi_cmnd *cmd)
10541da177e4SLinus Torvalds  *
10551da177e4SLinus Torvalds  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
10561da177e4SLinus Torvalds  *      including ARBITRATION, SELECTION, and initial message out for
10571da177e4SLinus Torvalds  *      IDENTIFY and queue messages.
10581da177e4SLinus Torvalds  *
10591da177e4SLinus Torvalds  * Inputs : instance - instantiation of the 5380 driver on which this
106076f13b93SFinn Thain  *      target lives, cmd - SCSI command to execute.
10611da177e4SLinus Torvalds  *
1062707d62b3SFinn Thain  * Returns cmd if selection failed but should be retried,
1063707d62b3SFinn Thain  * NULL if selection failed and should not be retried, or
1064707d62b3SFinn Thain  * NULL if selection succeeded (hostdata->connected == cmd).
10651da177e4SLinus Torvalds  *
10661da177e4SLinus Torvalds  * Side effects :
10671da177e4SLinus Torvalds  *      If bus busy, arbitration failed, etc, NCR5380_select() will exit
10681da177e4SLinus Torvalds  *              with registers as they should have been on entry - ie
10691da177e4SLinus Torvalds  *              SELECT_ENABLE will be set appropriately, the NCR5380
10701da177e4SLinus Torvalds  *              will cease to drive any SCSI bus signals.
10711da177e4SLinus Torvalds  *
10721da177e4SLinus Torvalds  *      If successful : I_T_L or I_T_L_Q nexus will be established,
10731da177e4SLinus Torvalds  *              instance->connected will be set to cmd.
10741da177e4SLinus Torvalds  *              SELECT interrupt will be disabled.
10751da177e4SLinus Torvalds  *
10761da177e4SLinus Torvalds  *      If failed (no target) : cmd->scsi_done() will be called, and the
10771da177e4SLinus Torvalds  *              cmd->result host byte set to DID_BAD_TARGET.
10781da177e4SLinus Torvalds  *
10791da177e4SLinus Torvalds  *	Locks: caller holds hostdata lock in IRQ mode
10801da177e4SLinus Torvalds  */
10811da177e4SLinus Torvalds 
1082707d62b3SFinn Thain static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
1083707d62b3SFinn Thain                                         struct scsi_cmnd *cmd)
10841da177e4SLinus Torvalds {
1085e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
10861da177e4SLinus Torvalds 	unsigned char tmp[3], phase;
10871da177e4SLinus Torvalds 	unsigned char *data;
10881da177e4SLinus Torvalds 	int len;
10891da177e4SLinus Torvalds 	int err;
10901da177e4SLinus Torvalds 
10911da177e4SLinus Torvalds 	NCR5380_dprint(NDEBUG_ARBITRATION, instance);
1092*b746545fSFinn Thain 	dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n",
1093*b746545fSFinn Thain 	         instance->this_id);
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds 	/*
1096707d62b3SFinn Thain 	 * Arbitration and selection phases are slow and involve dropping the
1097707d62b3SFinn Thain 	 * lock, so we have to watch out for EH. An exception handler may
1098707d62b3SFinn Thain 	 * change 'selecting' to NULL. This function will then return NULL
1099707d62b3SFinn Thain 	 * so that the caller will forget about 'cmd'. (During information
1100707d62b3SFinn Thain 	 * transfer phases, EH may change 'connected' to NULL.)
1101707d62b3SFinn Thain 	 */
1102707d62b3SFinn Thain 	hostdata->selecting = cmd;
1103707d62b3SFinn Thain 
1104707d62b3SFinn Thain 	/*
11051da177e4SLinus Torvalds 	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the
11061da177e4SLinus Torvalds 	 * data bus during SELECTION.
11071da177e4SLinus Torvalds 	 */
11081da177e4SLinus Torvalds 
11091da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, 0);
11101da177e4SLinus Torvalds 
11111da177e4SLinus Torvalds 	/*
11121da177e4SLinus Torvalds 	 * Start arbitration.
11131da177e4SLinus Torvalds 	 */
11141da177e4SLinus Torvalds 
11151da177e4SLinus Torvalds 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
11161da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_ARBITRATE);
11171da177e4SLinus Torvalds 
111855500d9bSFinn Thain 	/* The chip now waits for BUS FREE phase. Then after the 800 ns
111955500d9bSFinn Thain 	 * Bus Free Delay, arbitration will begin.
11201da177e4SLinus Torvalds 	 */
11211da177e4SLinus Torvalds 
112211d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
1123b32ade12SFinn Thain 	err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
1124b32ade12SFinn Thain 	                INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
1125b32ade12SFinn Thain 	                                       ICR_ARBITRATION_PROGRESS, HZ);
112611d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
112755500d9bSFinn Thain 	if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
112855500d9bSFinn Thain 		/* Reselection interrupt */
1129707d62b3SFinn Thain 		goto out;
113055500d9bSFinn Thain 	}
1131b32ade12SFinn Thain 	if (err < 0) {
1132b32ade12SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE);
1133b32ade12SFinn Thain 		shost_printk(KERN_ERR, instance,
1134b32ade12SFinn Thain 		             "select: arbitration timeout\n");
1135707d62b3SFinn Thain 		goto out;
113655500d9bSFinn Thain 	}
113711d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
113855500d9bSFinn Thain 
113955500d9bSFinn Thain 	/* The SCSI-2 arbitration delay is 2.4 us */
11401da177e4SLinus Torvalds 	udelay(3);
11411da177e4SLinus Torvalds 
11421da177e4SLinus Torvalds 	/* Check for lost arbitration */
11431da177e4SLinus Torvalds 	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
11441da177e4SLinus Torvalds 		NCR5380_write(MODE_REG, MR_BASE);
1145*b746545fSFinn Thain 		dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n");
114611d2f63bSFinn Thain 		spin_lock_irq(&hostdata->lock);
1147707d62b3SFinn Thain 		goto out;
11481da177e4SLinus Torvalds 	}
1149cf13b083SFinn Thain 
1150cf13b083SFinn Thain 	/* After/during arbitration, BSY should be asserted.
1151cf13b083SFinn Thain 	 * IBM DPES-31080 Version S31Q works now
1152cf13b083SFinn Thain 	 * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman)
1153cf13b083SFinn Thain 	 */
1154cf13b083SFinn Thain 	NCR5380_write(INITIATOR_COMMAND_REG,
1155cf13b083SFinn Thain 		      ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
11561da177e4SLinus Torvalds 
11571da177e4SLinus Torvalds 	/*
11581da177e4SLinus Torvalds 	 * Again, bus clear + bus settle time is 1.2us, however, this is
11591da177e4SLinus Torvalds 	 * a minimum so we'll udelay ceil(1.2)
11601da177e4SLinus Torvalds 	 */
11611da177e4SLinus Torvalds 
11629c3f0e2bSFinn Thain 	if (hostdata->flags & FLAG_TOSHIBA_DELAY)
11639c3f0e2bSFinn Thain 		udelay(15);
11649c3f0e2bSFinn Thain 	else
11651da177e4SLinus Torvalds 		udelay(2);
11661da177e4SLinus Torvalds 
116711d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
116811d2f63bSFinn Thain 
116972064a78SFinn Thain 	/* NCR5380_reselect() clears MODE_REG after a reselection interrupt */
117072064a78SFinn Thain 	if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE))
1171707d62b3SFinn Thain 		goto out;
1172707d62b3SFinn Thain 
1173707d62b3SFinn Thain 	if (!hostdata->selecting) {
1174707d62b3SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE);
1175707d62b3SFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1176707d62b3SFinn Thain 		goto out;
1177707d62b3SFinn Thain 	}
117872064a78SFinn Thain 
1179*b746545fSFinn Thain 	dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n");
11801da177e4SLinus Torvalds 
11811da177e4SLinus Torvalds 	/*
11821da177e4SLinus Torvalds 	 * Now that we have won arbitration, start Selection process, asserting
11831da177e4SLinus Torvalds 	 * the host and target ID's on the SCSI bus.
11841da177e4SLinus Torvalds 	 */
11851da177e4SLinus Torvalds 
1186422c0d61SJeff Garzik 	NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << scmd_id(cmd))));
11871da177e4SLinus Torvalds 
11881da177e4SLinus Torvalds 	/*
11891da177e4SLinus Torvalds 	 * Raise ATN while SEL is true before BSY goes false from arbitration,
11901da177e4SLinus Torvalds 	 * since this is the only way to guarantee that we'll get a MESSAGE OUT
11911da177e4SLinus Torvalds 	 * phase immediately after selection.
11921da177e4SLinus Torvalds 	 */
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
11951da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
11961da177e4SLinus Torvalds 
11971da177e4SLinus Torvalds 	/*
11981da177e4SLinus Torvalds 	 * Reselect interrupts must be turned off prior to the dropping of BSY,
11991da177e4SLinus Torvalds 	 * otherwise we will trigger an interrupt.
12001da177e4SLinus Torvalds 	 */
12011da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, 0);
12021da177e4SLinus Torvalds 
120311d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
120411d2f63bSFinn Thain 
12051da177e4SLinus Torvalds 	/*
12061da177e4SLinus Torvalds 	 * The initiator shall then wait at least two deskew delays and release
12071da177e4SLinus Torvalds 	 * the BSY signal.
12081da177e4SLinus Torvalds 	 */
12091da177e4SLinus Torvalds 	udelay(1);		/* wingel -- wait two bus deskew delay >2*45ns */
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	/* Reset BSY */
12121da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
12131da177e4SLinus Torvalds 
12141da177e4SLinus Torvalds 	/*
12151da177e4SLinus Torvalds 	 * Something weird happens when we cease to drive BSY - looks
12161da177e4SLinus Torvalds 	 * like the board/chip is letting us do another read before the
12171da177e4SLinus Torvalds 	 * appropriate propagation delay has expired, and we're confusing
12181da177e4SLinus Torvalds 	 * a BSY signal from ourselves as the target's response to SELECTION.
12191da177e4SLinus Torvalds 	 *
12201da177e4SLinus Torvalds 	 * A small delay (the 'C++' frontend breaks the pipeline with an
12211da177e4SLinus Torvalds 	 * unnecessary jump, making it work on my 386-33/Trantor T128, the
12221da177e4SLinus Torvalds 	 * tighter 'C' code breaks and requires this) solves the problem -
12231da177e4SLinus Torvalds 	 * the 1 us delay is arbitrary, and only used because this delay will
12241da177e4SLinus Torvalds 	 * be the same on other platforms and since it works here, it should
12251da177e4SLinus Torvalds 	 * work there.
12261da177e4SLinus Torvalds 	 *
12271da177e4SLinus Torvalds 	 * wingel suggests that this could be due to failing to wait
12281da177e4SLinus Torvalds 	 * one deskew delay.
12291da177e4SLinus Torvalds 	 */
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds 	udelay(1);
12321da177e4SLinus Torvalds 
1233*b746545fSFinn Thain 	dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd));
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds 	/*
12361da177e4SLinus Torvalds 	 * The SCSI specification calls for a 250 ms timeout for the actual
12371da177e4SLinus Torvalds 	 * selection.
12381da177e4SLinus Torvalds 	 */
12391da177e4SLinus Torvalds 
1240ae753a33SFinn Thain 	err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY,
1241ae753a33SFinn Thain 	                            msecs_to_jiffies(250));
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds 	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
124411d2f63bSFinn Thain 		spin_lock_irq(&hostdata->lock);
12451da177e4SLinus Torvalds 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
12461da177e4SLinus Torvalds 		NCR5380_reselect(instance);
1247cd400825SFinn Thain 		if (!hostdata->connected)
12481da177e4SLinus Torvalds 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
12496a6ff4acSFinn Thain 		shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n");
1250707d62b3SFinn Thain 		goto out;
12511da177e4SLinus Torvalds 	}
1252ae753a33SFinn Thain 
1253ae753a33SFinn Thain 	if (err < 0) {
125411d2f63bSFinn Thain 		spin_lock_irq(&hostdata->lock);
1255ae753a33SFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1256707d62b3SFinn Thain 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1257707d62b3SFinn Thain 		/* Can't touch cmd if it has been reclaimed by the scsi ML */
1258707d62b3SFinn Thain 		if (hostdata->selecting) {
1259ae753a33SFinn Thain 			cmd->result = DID_BAD_TARGET << 16;
1260677e0194SFinn Thain 			complete_cmd(instance, cmd);
1261707d62b3SFinn Thain 			dsprintk(NDEBUG_SELECTION, instance, "target did not respond within 250ms\n");
1262707d62b3SFinn Thain 			cmd = NULL;
1263707d62b3SFinn Thain 		}
1264707d62b3SFinn Thain 		goto out;
1265ae753a33SFinn Thain 	}
1266ae753a33SFinn Thain 
12671da177e4SLinus Torvalds 	/*
12681da177e4SLinus Torvalds 	 * No less than two deskew delays after the initiator detects the
12691da177e4SLinus Torvalds 	 * BSY signal is true, it shall release the SEL signal and may
12701da177e4SLinus Torvalds 	 * change the DATA BUS.                                     -wingel
12711da177e4SLinus Torvalds 	 */
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 	udelay(1);
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
12761da177e4SLinus Torvalds 
12771da177e4SLinus Torvalds 	/*
12781da177e4SLinus Torvalds 	 * Since we followed the SCSI spec, and raised ATN while SEL
12791da177e4SLinus Torvalds 	 * was true but before BSY was false during selection, the information
12801da177e4SLinus Torvalds 	 * transfer phase should be a MESSAGE OUT phase so that we can send the
12811da177e4SLinus Torvalds 	 * IDENTIFY message.
12821da177e4SLinus Torvalds 	 *
12831da177e4SLinus Torvalds 	 * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
12841da177e4SLinus Torvalds 	 * message (2 bytes) with a tag ID that we increment with every command
12851da177e4SLinus Torvalds 	 * until it wraps back to 0.
12861da177e4SLinus Torvalds 	 *
12871da177e4SLinus Torvalds 	 * XXX - it turns out that there are some broken SCSI-II devices,
12881da177e4SLinus Torvalds 	 *       which claim to support tagged queuing but fail when more than
12891da177e4SLinus Torvalds 	 *       some number of commands are issued at once.
12901da177e4SLinus Torvalds 	 */
12911da177e4SLinus Torvalds 
12921da177e4SLinus Torvalds 	/* Wait for start of REQ/ACK handshake */
12931da177e4SLinus Torvalds 
12941da177e4SLinus Torvalds 	err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
129511d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
12961cc160e1SFinn Thain 	if (err < 0) {
129755500d9bSFinn Thain 		shost_printk(KERN_ERR, instance, "select: REQ timeout\n");
129855500d9bSFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
12991da177e4SLinus Torvalds 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1300707d62b3SFinn Thain 		goto out;
1301707d62b3SFinn Thain 	}
1302707d62b3SFinn Thain 	if (!hostdata->selecting) {
1303707d62b3SFinn Thain 		do_abort(instance);
1304707d62b3SFinn Thain 		goto out;
13051da177e4SLinus Torvalds 	}
13061da177e4SLinus Torvalds 
1307*b746545fSFinn Thain 	dsprintk(NDEBUG_SELECTION, instance, "target %d selected, going into MESSAGE OUT phase.\n",
1308*b746545fSFinn Thain 	         scmd_id(cmd));
130922f5f10dSFinn Thain 	tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
13101da177e4SLinus Torvalds 
13111da177e4SLinus Torvalds 	len = 1;
13121da177e4SLinus Torvalds 	cmd->tag = 0;
13131da177e4SLinus Torvalds 
13141da177e4SLinus Torvalds 	/* Send message(s) */
13151da177e4SLinus Torvalds 	data = tmp;
13161da177e4SLinus Torvalds 	phase = PHASE_MSGOUT;
13171da177e4SLinus Torvalds 	NCR5380_transfer_pio(instance, &phase, &len, &data);
1318*b746545fSFinn Thain 	dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n");
13191da177e4SLinus Torvalds 	/* XXX need to handle errors here */
132011d2f63bSFinn Thain 
13211da177e4SLinus Torvalds 	hostdata->connected = cmd;
13229cb78c16SHannes Reinecke 	hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 	initialize_SCp(cmd);
13251da177e4SLinus Torvalds 
1326707d62b3SFinn Thain 	cmd = NULL;
1327707d62b3SFinn Thain 
1328707d62b3SFinn Thain out:
1329707d62b3SFinn Thain 	if (!hostdata->selecting)
1330707d62b3SFinn Thain 		return NULL;
1331707d62b3SFinn Thain 	hostdata->selecting = NULL;
1332707d62b3SFinn Thain 	return cmd;
13331da177e4SLinus Torvalds }
13341da177e4SLinus Torvalds 
13351da177e4SLinus Torvalds /*
13361da177e4SLinus Torvalds  * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
13371da177e4SLinus Torvalds  *      unsigned char *phase, int *count, unsigned char **data)
13381da177e4SLinus Torvalds  *
13391da177e4SLinus Torvalds  * Purpose : transfers data in given phase using polled I/O
13401da177e4SLinus Torvalds  *
13411da177e4SLinus Torvalds  * Inputs : instance - instance of driver, *phase - pointer to
13421da177e4SLinus Torvalds  *      what phase is expected, *count - pointer to number of
13431da177e4SLinus Torvalds  *      bytes to transfer, **data - pointer to data pointer.
13441da177e4SLinus Torvalds  *
13451da177e4SLinus Torvalds  * Returns : -1 when different phase is entered without transferring
134625985edcSLucas De Marchi  *      maximum number of bytes, 0 if all bytes or transferred or exit
13471da177e4SLinus Torvalds  *      is in same phase.
13481da177e4SLinus Torvalds  *
13491da177e4SLinus Torvalds  *      Also, *phase, *count, *data are modified in place.
13501da177e4SLinus Torvalds  *
13511da177e4SLinus Torvalds  * XXX Note : handling for bus free may be useful.
13521da177e4SLinus Torvalds  */
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds /*
13551da177e4SLinus Torvalds  * Note : this code is not as quick as it could be, however it
13561da177e4SLinus Torvalds  * IS 100% reliable, and for the actual data transfer where speed
13571da177e4SLinus Torvalds  * counts, we will always do a pseudo DMA or DMA transfer.
13581da177e4SLinus Torvalds  */
13591da177e4SLinus Torvalds 
13601da177e4SLinus Torvalds static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
13611da177e4SLinus Torvalds 	unsigned char p = *phase, tmp;
13621da177e4SLinus Torvalds 	int c = *count;
13631da177e4SLinus Torvalds 	unsigned char *d = *data;
13641da177e4SLinus Torvalds 
13651da177e4SLinus Torvalds 	/*
13661da177e4SLinus Torvalds 	 * The NCR5380 chip will only drive the SCSI bus when the
13671da177e4SLinus Torvalds 	 * phase specified in the appropriate bits of the TARGET COMMAND
13681da177e4SLinus Torvalds 	 * REGISTER match the STATUS REGISTER
13691da177e4SLinus Torvalds 	 */
13701da177e4SLinus Torvalds 
13711da177e4SLinus Torvalds 	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
13721da177e4SLinus Torvalds 
13731da177e4SLinus Torvalds 	do {
13741da177e4SLinus Torvalds 		/*
13751da177e4SLinus Torvalds 		 * Wait for assertion of REQ, after which the phase bits will be
13761da177e4SLinus Torvalds 		 * valid
13771da177e4SLinus Torvalds 		 */
13781da177e4SLinus Torvalds 
1379686f3990SFinn Thain 		if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0)
13801da177e4SLinus Torvalds 			break;
13811da177e4SLinus Torvalds 
1382*b746545fSFinn Thain 		dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n");
13831da177e4SLinus Torvalds 
13841da177e4SLinus Torvalds 		/* Check for phase mismatch */
1385686f3990SFinn Thain 		if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) {
1386*b746545fSFinn Thain 			dsprintk(NDEBUG_PIO, instance, "phase mismatch\n");
1387*b746545fSFinn Thain 			NCR5380_dprint_phase(NDEBUG_PIO, instance);
13881da177e4SLinus Torvalds 			break;
13891da177e4SLinus Torvalds 		}
13901da177e4SLinus Torvalds 		/* Do actual transfer from SCSI bus to / from memory */
13911da177e4SLinus Torvalds 		if (!(p & SR_IO))
13921da177e4SLinus Torvalds 			NCR5380_write(OUTPUT_DATA_REG, *d);
13931da177e4SLinus Torvalds 		else
13941da177e4SLinus Torvalds 			*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
13951da177e4SLinus Torvalds 
13961da177e4SLinus Torvalds 		++d;
13971da177e4SLinus Torvalds 
13981da177e4SLinus Torvalds 		/*
13991da177e4SLinus Torvalds 		 * The SCSI standard suggests that in MSGOUT phase, the initiator
14001da177e4SLinus Torvalds 		 * should drop ATN on the last byte of the message phase
14011da177e4SLinus Torvalds 		 * after REQ has been asserted for the handshake but before
14021da177e4SLinus Torvalds 		 * the initiator raises ACK.
14031da177e4SLinus Torvalds 		 */
14041da177e4SLinus Torvalds 
14051da177e4SLinus Torvalds 		if (!(p & SR_IO)) {
14061da177e4SLinus Torvalds 			if (!((p & SR_MSG) && c > 1)) {
14071da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
14081da177e4SLinus Torvalds 				NCR5380_dprint(NDEBUG_PIO, instance);
14091da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);
14101da177e4SLinus Torvalds 			} else {
14111da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);
14121da177e4SLinus Torvalds 				NCR5380_dprint(NDEBUG_PIO, instance);
14131da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
14141da177e4SLinus Torvalds 			}
14151da177e4SLinus Torvalds 		} else {
14161da177e4SLinus Torvalds 			NCR5380_dprint(NDEBUG_PIO, instance);
14171da177e4SLinus Torvalds 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
14181da177e4SLinus Torvalds 		}
14191da177e4SLinus Torvalds 
1420a2edc4a6SFinn Thain 		if (NCR5380_poll_politely(instance,
1421a2edc4a6SFinn Thain 		                          STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
1422a2edc4a6SFinn Thain 			break;
1423a2edc4a6SFinn Thain 
1424*b746545fSFinn Thain 		dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n");
14251da177e4SLinus Torvalds 
14261da177e4SLinus Torvalds /*
14271da177e4SLinus Torvalds  * We have several special cases to consider during REQ/ACK handshaking :
14281da177e4SLinus Torvalds  * 1.  We were in MSGOUT phase, and we are on the last byte of the
14291da177e4SLinus Torvalds  *      message.  ATN must be dropped as ACK is dropped.
14301da177e4SLinus Torvalds  *
14311da177e4SLinus Torvalds  * 2.  We are in a MSGIN phase, and we are on the last byte of the
14321da177e4SLinus Torvalds  *      message.  We must exit with ACK asserted, so that the calling
14331da177e4SLinus Torvalds  *      code may raise ATN before dropping ACK to reject the message.
14341da177e4SLinus Torvalds  *
14351da177e4SLinus Torvalds  * 3.  ACK and ATN are clear and the target may proceed as normal.
14361da177e4SLinus Torvalds  */
14371da177e4SLinus Torvalds 		if (!(p == PHASE_MSGIN && c == 1)) {
14381da177e4SLinus Torvalds 			if (p == PHASE_MSGOUT && c > 1)
14391da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
14401da177e4SLinus Torvalds 			else
14411da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
14421da177e4SLinus Torvalds 		}
14431da177e4SLinus Torvalds 	} while (--c);
14441da177e4SLinus Torvalds 
1445*b746545fSFinn Thain 	dsprintk(NDEBUG_PIO, instance, "residual %d\n", c);
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	*count = c;
14481da177e4SLinus Torvalds 	*data = d;
14491da177e4SLinus Torvalds 	tmp = NCR5380_read(STATUS_REG);
1450a2edc4a6SFinn Thain 	/* The phase read from the bus is valid if either REQ is (already)
1451a2edc4a6SFinn Thain 	 * asserted or if ACK hasn't been released yet. The latter applies if
1452a2edc4a6SFinn Thain 	 * we're in MSG IN, DATA IN or STATUS and all bytes have been received.
1453a2edc4a6SFinn Thain 	 */
1454a2edc4a6SFinn Thain 	if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0))
14551da177e4SLinus Torvalds 		*phase = tmp & PHASE_MASK;
14561da177e4SLinus Torvalds 	else
14571da177e4SLinus Torvalds 		*phase = PHASE_UNKNOWN;
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds 	if (!c || (*phase == p))
14601da177e4SLinus Torvalds 		return 0;
14611da177e4SLinus Torvalds 	else
14621da177e4SLinus Torvalds 		return -1;
14631da177e4SLinus Torvalds }
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds /**
14661da177e4SLinus Torvalds  * do_reset - issue a reset command
1467636b1ec8SFinn Thain  * @instance: adapter to reset
14681da177e4SLinus Torvalds  *
14691da177e4SLinus Torvalds  * Issue a reset sequence to the NCR5380 and try and get the bus
14701da177e4SLinus Torvalds  * back into sane shape.
14711da177e4SLinus Torvalds  *
1472636b1ec8SFinn Thain  * This clears the reset interrupt flag because there may be no handler for
1473636b1ec8SFinn Thain  * it. When the driver is initialized, the NCR5380_intr() handler has not yet
1474636b1ec8SFinn Thain  * been installed. And when in EH we may have released the ST DMA interrupt.
14751da177e4SLinus Torvalds  */
14761da177e4SLinus Torvalds 
147754d8fe44SFinn Thain static void do_reset(struct Scsi_Host *instance)
147854d8fe44SFinn Thain {
1479636b1ec8SFinn Thain 	unsigned long flags;
1480636b1ec8SFinn Thain 
1481636b1ec8SFinn Thain 	local_irq_save(flags);
1482636b1ec8SFinn Thain 	NCR5380_write(TARGET_COMMAND_REG,
1483636b1ec8SFinn Thain 	              PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
14841da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
1485636b1ec8SFinn Thain 	udelay(50);
14861da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1487636b1ec8SFinn Thain 	(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
1488636b1ec8SFinn Thain 	local_irq_restore(flags);
14891da177e4SLinus Torvalds }
14901da177e4SLinus Torvalds 
149180d3eb6dSFinn Thain /**
149280d3eb6dSFinn Thain  * do_abort - abort the currently established nexus by going to
149380d3eb6dSFinn Thain  * MESSAGE OUT phase and sending an ABORT message.
149480d3eb6dSFinn Thain  * @instance: relevant scsi host instance
14951da177e4SLinus Torvalds  *
149680d3eb6dSFinn Thain  * Returns 0 on success, -1 on failure.
14971da177e4SLinus Torvalds  */
14981da177e4SLinus Torvalds 
149954d8fe44SFinn Thain static int do_abort(struct Scsi_Host *instance)
150054d8fe44SFinn Thain {
15011da177e4SLinus Torvalds 	unsigned char *msgptr, phase, tmp;
15021da177e4SLinus Torvalds 	int len;
15031da177e4SLinus Torvalds 	int rc;
15041da177e4SLinus Torvalds 
15051da177e4SLinus Torvalds 	/* Request message out phase */
15061da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
15071da177e4SLinus Torvalds 
15081da177e4SLinus Torvalds 	/*
15091da177e4SLinus Torvalds 	 * Wait for the target to indicate a valid phase by asserting
15101da177e4SLinus Torvalds 	 * REQ.  Once this happens, we'll have either a MSGOUT phase
15111da177e4SLinus Torvalds 	 * and can immediately send the ABORT message, or we'll have some
15121da177e4SLinus Torvalds 	 * other phase and will have to source/sink data.
15131da177e4SLinus Torvalds 	 *
15141da177e4SLinus Torvalds 	 * We really don't care what value was on the bus or what value
15151da177e4SLinus Torvalds 	 * the target sees, so we just handshake.
15161da177e4SLinus Torvalds 	 */
15171da177e4SLinus Torvalds 
151880d3eb6dSFinn Thain 	rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
15191da177e4SLinus Torvalds 	if (rc < 0)
152080d3eb6dSFinn Thain 		goto timeout;
15211da177e4SLinus Torvalds 
1522f35d3474SFinn Thain 	tmp = NCR5380_read(STATUS_REG) & PHASE_MASK;
15231da177e4SLinus Torvalds 
15241da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
15251da177e4SLinus Torvalds 
1526f35d3474SFinn Thain 	if (tmp != PHASE_MSGOUT) {
15271da177e4SLinus Torvalds 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
152854d8fe44SFinn Thain 		rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ);
15291cc160e1SFinn Thain 		if (rc < 0)
153080d3eb6dSFinn Thain 			goto timeout;
153180d3eb6dSFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
15321da177e4SLinus Torvalds 	}
15331da177e4SLinus Torvalds 	tmp = ABORT;
15341da177e4SLinus Torvalds 	msgptr = &tmp;
15351da177e4SLinus Torvalds 	len = 1;
15361da177e4SLinus Torvalds 	phase = PHASE_MSGOUT;
153754d8fe44SFinn Thain 	NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
15381da177e4SLinus Torvalds 
15391da177e4SLinus Torvalds 	/*
15401da177e4SLinus Torvalds 	 * If we got here, and the command completed successfully,
15411da177e4SLinus Torvalds 	 * we're about to go into bus free state.
15421da177e4SLinus Torvalds 	 */
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds 	return len ? -1 : 0;
154580d3eb6dSFinn Thain 
154680d3eb6dSFinn Thain timeout:
154780d3eb6dSFinn Thain 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
154880d3eb6dSFinn Thain 	return -1;
15491da177e4SLinus Torvalds }
15501da177e4SLinus Torvalds 
15511da177e4SLinus Torvalds #if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL)
15521da177e4SLinus Torvalds /*
15531da177e4SLinus Torvalds  * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
15541da177e4SLinus Torvalds  *      unsigned char *phase, int *count, unsigned char **data)
15551da177e4SLinus Torvalds  *
15561da177e4SLinus Torvalds  * Purpose : transfers data in given phase using either real
15571da177e4SLinus Torvalds  *      or pseudo DMA.
15581da177e4SLinus Torvalds  *
15591da177e4SLinus Torvalds  * Inputs : instance - instance of driver, *phase - pointer to
15601da177e4SLinus Torvalds  *      what phase is expected, *count - pointer to number of
15611da177e4SLinus Torvalds  *      bytes to transfer, **data - pointer to data pointer.
15621da177e4SLinus Torvalds  *
15631da177e4SLinus Torvalds  * Returns : -1 when different phase is entered without transferring
156425985edcSLucas De Marchi  *      maximum number of bytes, 0 if all bytes or transferred or exit
15651da177e4SLinus Torvalds  *      is in same phase.
15661da177e4SLinus Torvalds  *
15671da177e4SLinus Torvalds  *      Also, *phase, *count, *data are modified in place.
15681da177e4SLinus Torvalds  *
15691da177e4SLinus Torvalds  *	Locks: io_request lock held by caller
15701da177e4SLinus Torvalds  */
15711da177e4SLinus Torvalds 
15721da177e4SLinus Torvalds 
15731da177e4SLinus Torvalds static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
15741da177e4SLinus Torvalds 	register int c = *count;
15751da177e4SLinus Torvalds 	register unsigned char p = *phase;
15761da177e4SLinus Torvalds 	register unsigned char *d = *data;
15771da177e4SLinus Torvalds 	unsigned char tmp;
15781da177e4SLinus Torvalds 	int foo;
15791da177e4SLinus Torvalds #if defined(REAL_DMA_POLL)
15801da177e4SLinus Torvalds 	int cnt, toPIO;
15811da177e4SLinus Torvalds 	unsigned char saved_data = 0, overrun = 0, residue;
15821da177e4SLinus Torvalds #endif
15831da177e4SLinus Torvalds 
1584e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
15851da177e4SLinus Torvalds 
15861da177e4SLinus Torvalds 	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
15871da177e4SLinus Torvalds 		*phase = tmp;
15881da177e4SLinus Torvalds 		return -1;
15891da177e4SLinus Torvalds 	}
15901da177e4SLinus Torvalds #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
15911da177e4SLinus Torvalds 	if (p & SR_IO) {
15929db6024eSFinn Thain 		if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS))
15931da177e4SLinus Torvalds 			c -= 2;
15941da177e4SLinus Torvalds 	}
15951da177e4SLinus Torvalds 	hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);
1596*b746545fSFinn Thain 
1597*b746545fSFinn Thain 	dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n",
1598*b746545fSFinn Thain 	         (p & SR_IO) ? "receive" : "send", c, *data);
15991da177e4SLinus Torvalds #endif
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
16021da177e4SLinus Torvalds 
16031da177e4SLinus Torvalds #ifdef REAL_DMA
1604cd400825SFinn Thain 	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY |
1605cd400825SFinn Thain 	                        MR_ENABLE_EOP_INTR);
16061da177e4SLinus Torvalds #elif defined(REAL_DMA_POLL)
1607cd400825SFinn Thain 	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY);
16081da177e4SLinus Torvalds #else
16091da177e4SLinus Torvalds 	/*
16101da177e4SLinus Torvalds 	 * Note : on my sample board, watch-dog timeouts occurred when interrupts
16111da177e4SLinus Torvalds 	 * were not disabled for the duration of a single DMA transfer, from
16121da177e4SLinus Torvalds 	 * before the setting of DMA mode to after transfer of the last byte.
16131da177e4SLinus Torvalds 	 */
16141da177e4SLinus Torvalds 
161555181be8SFinn Thain 	if (hostdata->flags & FLAG_NO_DMA_FIXUP)
1616cd400825SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY |
1617cd400825SFinn Thain 		                        MR_ENABLE_EOP_INTR);
16181da177e4SLinus Torvalds 	else
1619cd400825SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY);
16201da177e4SLinus Torvalds #endif				/* def REAL_DMA */
16211da177e4SLinus Torvalds 
162252a6a1cbSFinn Thain 	dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
16231da177e4SLinus Torvalds 
16241da177e4SLinus Torvalds 	/*
16251da177e4SLinus Torvalds 	 *	On the PAS16 at least I/O recovery delays are not needed here.
16261da177e4SLinus Torvalds 	 *	Everyone else seems to want them.
16271da177e4SLinus Torvalds 	 */
16281da177e4SLinus Torvalds 
16291da177e4SLinus Torvalds 	if (p & SR_IO) {
16301da177e4SLinus Torvalds 		io_recovery_delay(1);
16311da177e4SLinus Torvalds 		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
16321da177e4SLinus Torvalds 	} else {
16331da177e4SLinus Torvalds 		io_recovery_delay(1);
16341da177e4SLinus Torvalds 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
16351da177e4SLinus Torvalds 		io_recovery_delay(1);
16361da177e4SLinus Torvalds 		NCR5380_write(START_DMA_SEND_REG, 0);
16371da177e4SLinus Torvalds 		io_recovery_delay(1);
16381da177e4SLinus Torvalds 	}
16391da177e4SLinus Torvalds 
16401da177e4SLinus Torvalds #if defined(REAL_DMA_POLL)
16411da177e4SLinus Torvalds 	do {
16421da177e4SLinus Torvalds 		tmp = NCR5380_read(BUS_AND_STATUS_REG);
16431da177e4SLinus Torvalds 	} while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER)));
16441da177e4SLinus Torvalds 
16451da177e4SLinus Torvalds /*
16461da177e4SLinus Torvalds    At this point, either we've completed DMA, or we have a phase mismatch,
16471da177e4SLinus Torvalds    or we've unexpectedly lost BUSY (which is a real error).
16481da177e4SLinus Torvalds 
16491da177e4SLinus Torvalds    For write DMAs, we want to wait until the last byte has been
16501da177e4SLinus Torvalds    transferred out over the bus before we turn off DMA mode.  Alas, there
16511da177e4SLinus Torvalds    seems to be no terribly good way of doing this on a 5380 under all
16521da177e4SLinus Torvalds    conditions.  For non-scatter-gather operations, we can wait until REQ
16531da177e4SLinus Torvalds    and ACK both go false, or until a phase mismatch occurs.  Gather-writes
16541da177e4SLinus Torvalds    are nastier, since the device will be expecting more data than we
16551da177e4SLinus Torvalds    are prepared to send it, and REQ will remain asserted.  On a 53C8[01] we
16561da177e4SLinus Torvalds    could test LAST BIT SENT to assure transfer (I imagine this is precisely
16571da177e4SLinus Torvalds    why this signal was added to the newer chips) but on the older 538[01]
16581da177e4SLinus Torvalds    this signal does not exist.  The workaround for this lack is a watchdog;
16591da177e4SLinus Torvalds    we bail out of the wait-loop after a modest amount of wait-time if
16601da177e4SLinus Torvalds    the usual exit conditions are not met.  Not a terribly clean or
16611da177e4SLinus Torvalds    correct solution :-%
16621da177e4SLinus Torvalds 
16631da177e4SLinus Torvalds    Reads are equally tricky due to a nasty characteristic of the NCR5380.
16641da177e4SLinus Torvalds    If the chip is in DMA mode for an READ, it will respond to a target's
16651da177e4SLinus Torvalds    REQ by latching the SCSI data into the INPUT DATA register and asserting
16661da177e4SLinus Torvalds    ACK, even if it has _already_ been notified by the DMA controller that
16671da177e4SLinus Torvalds    the current DMA transfer has completed!  If the NCR5380 is then taken
16681da177e4SLinus Torvalds    out of DMA mode, this already-acknowledged byte is lost.
16691da177e4SLinus Torvalds 
16701da177e4SLinus Torvalds    This is not a problem for "one DMA transfer per command" reads, because
16711da177e4SLinus Torvalds    the situation will never arise... either all of the data is DMA'ed
16721da177e4SLinus Torvalds    properly, or the target switches to MESSAGE IN phase to signal a
16731da177e4SLinus Torvalds    disconnection (either operation bringing the DMA to a clean halt).
16741da177e4SLinus Torvalds    However, in order to handle scatter-reads, we must work around the
16751da177e4SLinus Torvalds    problem.  The chosen fix is to DMA N-2 bytes, then check for the
16761da177e4SLinus Torvalds    condition before taking the NCR5380 out of DMA mode.  One or two extra
16771da177e4SLinus Torvalds    bytes are transferred via PIO as necessary to fill out the original
16781da177e4SLinus Torvalds    request.
16791da177e4SLinus Torvalds  */
16801da177e4SLinus Torvalds 
16811da177e4SLinus Torvalds 	if (p & SR_IO) {
16829db6024eSFinn Thain 		if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) {
16831da177e4SLinus Torvalds 			udelay(10);
16849db6024eSFinn Thain 			if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) ==
16859db6024eSFinn Thain 			    (BASR_PHASE_MATCH | BASR_ACK)) {
16861da177e4SLinus Torvalds 				saved_data = NCR5380_read(INPUT_DATA_REGISTER);
16871da177e4SLinus Torvalds 				overrun = 1;
16881da177e4SLinus Torvalds 			}
16899db6024eSFinn Thain 		}
16901da177e4SLinus Torvalds 	} else {
16911da177e4SLinus Torvalds 		int limit = 100;
16921da177e4SLinus Torvalds 		while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) {
16931da177e4SLinus Torvalds 			if (!(tmp & BASR_PHASE_MATCH))
16941da177e4SLinus Torvalds 				break;
16951da177e4SLinus Torvalds 			if (--limit < 0)
16961da177e4SLinus Torvalds 				break;
16971da177e4SLinus Torvalds 		}
16981da177e4SLinus Torvalds 	}
16991da177e4SLinus Torvalds 
1700*b746545fSFinn Thain 	dsprintk(NDEBUG_DMA, "polled DMA transfer complete, basr 0x%02x, sr 0x%02x\n",
1701*b746545fSFinn Thain 	         tmp, NCR5380_read(STATUS_REG));
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
17041da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
17051da177e4SLinus Torvalds 
17061da177e4SLinus Torvalds 	residue = NCR5380_dma_residual(instance);
17071da177e4SLinus Torvalds 	c -= residue;
17081da177e4SLinus Torvalds 	*count -= c;
17091da177e4SLinus Torvalds 	*data += c;
17101da177e4SLinus Torvalds 	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
17111da177e4SLinus Torvalds 
17129db6024eSFinn Thain 	if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS) &&
17139db6024eSFinn Thain 	    *phase == p && (p & SR_IO) && residue == 0) {
17141da177e4SLinus Torvalds 		if (overrun) {
171552a6a1cbSFinn Thain 			dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
17161da177e4SLinus Torvalds 			**data = saved_data;
17171da177e4SLinus Torvalds 			*data += 1;
17181da177e4SLinus Torvalds 			*count -= 1;
17191da177e4SLinus Torvalds 			cnt = toPIO = 1;
17201da177e4SLinus Torvalds 		} else {
17211da177e4SLinus Torvalds 			printk("No overrun??\n");
17221da177e4SLinus Torvalds 			cnt = toPIO = 2;
17231da177e4SLinus Torvalds 		}
172452a6a1cbSFinn Thain 		dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%X\n", cnt, *data);
17251da177e4SLinus Torvalds 		NCR5380_transfer_pio(instance, phase, &cnt, data);
17261da177e4SLinus Torvalds 		*count -= toPIO - cnt;
17271da177e4SLinus Torvalds 	}
17281da177e4SLinus Torvalds 
172952a6a1cbSFinn Thain 	dprintk(NDEBUG_DMA, "Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count));
17301da177e4SLinus Torvalds 	return 0;
17311da177e4SLinus Torvalds 
17321da177e4SLinus Torvalds #elif defined(REAL_DMA)
17331da177e4SLinus Torvalds 	return 0;
17341da177e4SLinus Torvalds #else				/* defined(REAL_DMA_POLL) */
17351da177e4SLinus Torvalds 	if (p & SR_IO) {
173655181be8SFinn Thain 		foo = NCR5380_pread(instance, d,
173755181be8SFinn Thain 			hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1);
173855181be8SFinn Thain 		if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) {
17391da177e4SLinus Torvalds 			/*
17401da177e4SLinus Torvalds 			 * We can't disable DMA mode after successfully transferring
17411da177e4SLinus Torvalds 			 * what we plan to be the last byte, since that would open up
17421da177e4SLinus Torvalds 			 * a race condition where if the target asserted REQ before
17431da177e4SLinus Torvalds 			 * we got the DMA mode reset, the NCR5380 would have latched
17441da177e4SLinus Torvalds 			 * an additional byte into the INPUT DATA register and we'd
17451da177e4SLinus Torvalds 			 * have dropped it.
17461da177e4SLinus Torvalds 			 *
17471da177e4SLinus Torvalds 			 * The workaround was to transfer one fewer bytes than we
17481da177e4SLinus Torvalds 			 * intended to with the pseudo-DMA read function, wait for
17491da177e4SLinus Torvalds 			 * the chip to latch the last byte, read it, and then disable
17501da177e4SLinus Torvalds 			 * pseudo-DMA mode.
17511da177e4SLinus Torvalds 			 *
17521da177e4SLinus Torvalds 			 * After REQ is asserted, the NCR5380 asserts DRQ and ACK.
17531da177e4SLinus Torvalds 			 * REQ is deasserted when ACK is asserted, and not reasserted
17541da177e4SLinus Torvalds 			 * until ACK goes false.  Since the NCR5380 won't lower ACK
17551da177e4SLinus Torvalds 			 * until DACK is asserted, which won't happen unless we twiddle
17561da177e4SLinus Torvalds 			 * the DMA port or we take the NCR5380 out of DMA mode, we
17571da177e4SLinus Torvalds 			 * can guarantee that we won't handshake another extra
17581da177e4SLinus Torvalds 			 * byte.
17591da177e4SLinus Torvalds 			 */
17601da177e4SLinus Torvalds 
176155181be8SFinn Thain 			if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG,
176255181be8SFinn Thain 			                          BASR_DRQ, BASR_DRQ, HZ) < 0) {
176355181be8SFinn Thain 				foo = -1;
176455181be8SFinn Thain 				shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
176555181be8SFinn Thain 			}
176655181be8SFinn Thain 			if (NCR5380_poll_politely(instance, STATUS_REG,
176755181be8SFinn Thain 			                          SR_REQ, 0, HZ) < 0) {
176855181be8SFinn Thain 				foo = -1;
176955181be8SFinn Thain 				shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
177055181be8SFinn Thain 			}
17711da177e4SLinus Torvalds 			d[c - 1] = NCR5380_read(INPUT_DATA_REG);
17721da177e4SLinus Torvalds 		}
17731da177e4SLinus Torvalds 	} else {
17741da177e4SLinus Torvalds 		foo = NCR5380_pwrite(instance, d, c);
177555181be8SFinn Thain 		if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) {
17761da177e4SLinus Torvalds 			/*
17771da177e4SLinus Torvalds 			 * Wait for the last byte to be sent.  If REQ is being asserted for
17781da177e4SLinus Torvalds 			 * the byte we're interested, we'll ACK it and it will go false.
17791da177e4SLinus Torvalds 			 */
178055181be8SFinn Thain 			if (NCR5380_poll_politely2(instance,
178155181be8SFinn Thain 			     BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
178255181be8SFinn Thain 			     BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) {
178355181be8SFinn Thain 				foo = -1;
178455181be8SFinn Thain 				shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n");
17851da177e4SLinus Torvalds 			}
17861da177e4SLinus Torvalds 		}
17871da177e4SLinus Torvalds 	}
17881da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
17891da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
17901da177e4SLinus Torvalds 	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
17911da177e4SLinus Torvalds 	*data = d + c;
17921da177e4SLinus Torvalds 	*count = 0;
17931da177e4SLinus Torvalds 	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
17941da177e4SLinus Torvalds 	return foo;
17951da177e4SLinus Torvalds #endif				/* def REAL_DMA */
17961da177e4SLinus Torvalds }
17971da177e4SLinus Torvalds #endif				/* defined(REAL_DMA) | defined(PSEUDO_DMA) */
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds /*
18001da177e4SLinus Torvalds  * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
18011da177e4SLinus Torvalds  *
18021da177e4SLinus Torvalds  * Purpose : run through the various SCSI phases and do as the target
18031da177e4SLinus Torvalds  *      directs us to.  Operates on the currently connected command,
18041da177e4SLinus Torvalds  *      instance->connected.
18051da177e4SLinus Torvalds  *
18061da177e4SLinus Torvalds  * Inputs : instance, instance for which we are doing commands
18071da177e4SLinus Torvalds  *
18081da177e4SLinus Torvalds  * Side effects : SCSI things happen, the disconnected queue will be
18091da177e4SLinus Torvalds  *      modified if a command disconnects, *instance->connected will
18101da177e4SLinus Torvalds  *      change.
18111da177e4SLinus Torvalds  *
18121da177e4SLinus Torvalds  * XXX Note : we need to watch for bus free or a reset condition here
18131da177e4SLinus Torvalds  *      to recover from an unexpected bus free condition.
18141da177e4SLinus Torvalds  *
18151da177e4SLinus Torvalds  * Locks: io_request_lock held by caller in IRQ mode
18161da177e4SLinus Torvalds  */
18171da177e4SLinus Torvalds 
18181da177e4SLinus Torvalds static void NCR5380_information_transfer(struct Scsi_Host *instance) {
1819e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
18201da177e4SLinus Torvalds 	unsigned char msgout = NOP;
18211da177e4SLinus Torvalds 	int sink = 0;
18221da177e4SLinus Torvalds 	int len;
18231da177e4SLinus Torvalds #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
18241da177e4SLinus Torvalds 	int transfersize;
18251da177e4SLinus Torvalds #endif
18261da177e4SLinus Torvalds 	unsigned char *data;
18271da177e4SLinus Torvalds 	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
182811d2f63bSFinn Thain 	struct scsi_cmnd *cmd;
18291da177e4SLinus Torvalds 
183011d2f63bSFinn Thain 	while ((cmd = hostdata->connected)) {
183132b26a10SFinn Thain 		struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
183232b26a10SFinn Thain 
18331da177e4SLinus Torvalds 		tmp = NCR5380_read(STATUS_REG);
18341da177e4SLinus Torvalds 		/* We only have a valid SCSI phase when REQ is asserted */
18351da177e4SLinus Torvalds 		if (tmp & SR_REQ) {
18361da177e4SLinus Torvalds 			phase = (tmp & PHASE_MASK);
18371da177e4SLinus Torvalds 			if (phase != old_phase) {
18381da177e4SLinus Torvalds 				old_phase = phase;
18391da177e4SLinus Torvalds 				NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
18401da177e4SLinus Torvalds 			}
18411da177e4SLinus Torvalds 			if (sink && (phase != PHASE_MSGOUT)) {
18421da177e4SLinus Torvalds 				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
18431da177e4SLinus Torvalds 
18441da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
18451da177e4SLinus Torvalds 				while (NCR5380_read(STATUS_REG) & SR_REQ);
18461da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
18471da177e4SLinus Torvalds 				sink = 0;
18481da177e4SLinus Torvalds 				continue;
18491da177e4SLinus Torvalds 			}
18501da177e4SLinus Torvalds 			switch (phase) {
18511da177e4SLinus Torvalds 			case PHASE_DATAOUT:
18521da177e4SLinus Torvalds #if (NDEBUG & NDEBUG_NO_DATAOUT)
18536a6ff4acSFinn Thain 				shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n");
18541da177e4SLinus Torvalds 				sink = 1;
18551da177e4SLinus Torvalds 				do_abort(instance);
18561da177e4SLinus Torvalds 				cmd->result = DID_ERROR << 16;
1857677e0194SFinn Thain 				complete_cmd(instance, cmd);
18581da177e4SLinus Torvalds 				return;
18591da177e4SLinus Torvalds #endif
1860bf1a0c6fSFinn Thain 			case PHASE_DATAIN:
18611da177e4SLinus Torvalds 				/*
18621da177e4SLinus Torvalds 				 * If there is no room left in the current buffer in the
18631da177e4SLinus Torvalds 				 * scatter-gather list, move onto the next one.
18641da177e4SLinus Torvalds 				 */
18651da177e4SLinus Torvalds 
18661da177e4SLinus Torvalds 				if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
18671da177e4SLinus Torvalds 					++cmd->SCp.buffer;
18681da177e4SLinus Torvalds 					--cmd->SCp.buffers_residual;
18691da177e4SLinus Torvalds 					cmd->SCp.this_residual = cmd->SCp.buffer->length;
187045711f1aSJens Axboe 					cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
1871*b746545fSFinn Thain 					dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n",
1872*b746545fSFinn Thain 					         cmd->SCp.this_residual,
1873*b746545fSFinn Thain 					         cmd->SCp.buffers_residual);
18741da177e4SLinus Torvalds 				}
18751da177e4SLinus Torvalds 				/*
18761da177e4SLinus Torvalds 				 * The preferred transfer method is going to be
18771da177e4SLinus Torvalds 				 * PSEUDO-DMA for systems that are strictly PIO,
18781da177e4SLinus Torvalds 				 * since we can let the hardware do the handshaking.
18791da177e4SLinus Torvalds 				 *
18801da177e4SLinus Torvalds 				 * For this to work, we need to know the transfersize
18811da177e4SLinus Torvalds 				 * ahead of time, since the pseudo-DMA code will sit
18821da177e4SLinus Torvalds 				 * in an unconditional loop.
18831da177e4SLinus Torvalds 				 */
18841da177e4SLinus Torvalds 
18851da177e4SLinus Torvalds #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
1886ff3d4578SFinn Thain 				transfersize = 0;
1887ff3d4578SFinn Thain 				if (!cmd->device->borken &&
1888ff3d4578SFinn Thain 				    !(hostdata->flags & FLAG_NO_PSEUDO_DMA))
1889ff3d4578SFinn Thain 					transfersize = NCR5380_dma_xfer_len(instance, cmd, phase);
18901da177e4SLinus Torvalds 
1891ff3d4578SFinn Thain 				if (transfersize) {
18921da177e4SLinus Torvalds 					len = transfersize;
18931da177e4SLinus Torvalds 					if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **) &cmd->SCp.ptr)) {
18941da177e4SLinus Torvalds 						/*
18951da177e4SLinus Torvalds 						 * If the watchdog timer fires, all future accesses to this
18961da177e4SLinus Torvalds 						 * device will use the polled-IO.
18971da177e4SLinus Torvalds 						 */
1898017560fcSJeff Garzik 						scmd_printk(KERN_INFO, cmd,
1899017560fcSJeff Garzik 							    "switching to slow handshake\n");
19001da177e4SLinus Torvalds 						cmd->device->borken = 1;
19011da177e4SLinus Torvalds 						sink = 1;
19021da177e4SLinus Torvalds 						do_abort(instance);
19031da177e4SLinus Torvalds 						cmd->result = DID_ERROR << 16;
1904677e0194SFinn Thain 						complete_cmd(instance, cmd);
19051da177e4SLinus Torvalds 						/* XXX - need to source or sink data here, as appropriate */
19061da177e4SLinus Torvalds 					} else
19071da177e4SLinus Torvalds 						cmd->SCp.this_residual -= transfersize - len;
19081da177e4SLinus Torvalds 				} else
19091da177e4SLinus Torvalds #endif				/* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
191011d2f63bSFinn Thain 				{
191111d2f63bSFinn Thain 					spin_unlock_irq(&hostdata->lock);
19121da177e4SLinus Torvalds 					NCR5380_transfer_pio(instance, &phase, (int *) &cmd->SCp.this_residual, (unsigned char **)
19131da177e4SLinus Torvalds 							     &cmd->SCp.ptr);
191411d2f63bSFinn Thain 					spin_lock_irq(&hostdata->lock);
191511d2f63bSFinn Thain 				}
19161da177e4SLinus Torvalds 				break;
19171da177e4SLinus Torvalds 			case PHASE_MSGIN:
19181da177e4SLinus Torvalds 				len = 1;
19191da177e4SLinus Torvalds 				data = &tmp;
19201da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
19211da177e4SLinus Torvalds 				cmd->SCp.Message = tmp;
19221da177e4SLinus Torvalds 
19231da177e4SLinus Torvalds 				switch (tmp) {
19241da177e4SLinus Torvalds 				case ABORT:
19251da177e4SLinus Torvalds 				case COMMAND_COMPLETE:
19261da177e4SLinus Torvalds 					/* Accept message by clearing ACK */
19271da177e4SLinus Torvalds 					sink = 1;
19281da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
19290d3d9a42SFinn Thain 					dsprintk(NDEBUG_QUEUES, instance,
19300d3d9a42SFinn Thain 					         "COMMAND COMPLETE %p target %d lun %llu\n",
19310d3d9a42SFinn Thain 					         cmd, scmd_id(cmd), cmd->device->lun);
19320d3d9a42SFinn Thain 
19331da177e4SLinus Torvalds 					hostdata->connected = NULL;
19341da177e4SLinus Torvalds 
1935f27db8ebSFinn Thain 					cmd->result &= ~0xffff;
1936f27db8ebSFinn Thain 					cmd->result |= cmd->SCp.Status;
1937f27db8ebSFinn Thain 					cmd->result |= cmd->SCp.Message << 8;
19381da177e4SLinus Torvalds 
1939f27db8ebSFinn Thain 					if (cmd->cmnd[0] == REQUEST_SENSE)
1940f27db8ebSFinn Thain 						complete_cmd(instance, cmd);
1941f27db8ebSFinn Thain 					else {
1942f27db8ebSFinn Thain 						if (cmd->SCp.Status == SAM_STAT_CHECK_CONDITION ||
1943f27db8ebSFinn Thain 						    cmd->SCp.Status == SAM_STAT_COMMAND_TERMINATED) {
1944f27db8ebSFinn Thain 							dsprintk(NDEBUG_QUEUES, instance, "autosense: adding cmd %p to tail of autosense queue\n",
1945dbb6b350SFinn Thain 							         cmd);
1946f27db8ebSFinn Thain 							list_add_tail(&ncmd->list,
1947f27db8ebSFinn Thain 							              &hostdata->autosense);
1948f27db8ebSFinn Thain 						} else
1949677e0194SFinn Thain 							complete_cmd(instance, cmd);
19501da177e4SLinus Torvalds 					}
19511da177e4SLinus Torvalds 
19521da177e4SLinus Torvalds 					/*
19531da177e4SLinus Torvalds 					 * Restore phase bits to 0 so an interrupted selection,
19541da177e4SLinus Torvalds 					 * arbitration can resume.
19551da177e4SLinus Torvalds 					 */
19561da177e4SLinus Torvalds 					NCR5380_write(TARGET_COMMAND_REG, 0);
195772064a78SFinn Thain 
195872064a78SFinn Thain 					/* Enable reselect interrupts */
195972064a78SFinn Thain 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
19601da177e4SLinus Torvalds 					return;
19611da177e4SLinus Torvalds 				case MESSAGE_REJECT:
19621da177e4SLinus Torvalds 					/* Accept message by clearing ACK */
19631da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
19641da177e4SLinus Torvalds 					switch (hostdata->last_message) {
19651da177e4SLinus Torvalds 					case HEAD_OF_QUEUE_TAG:
19661da177e4SLinus Torvalds 					case ORDERED_QUEUE_TAG:
19671da177e4SLinus Torvalds 					case SIMPLE_QUEUE_TAG:
19681da177e4SLinus Torvalds 						cmd->device->simple_tags = 0;
19699cb78c16SHannes Reinecke 						hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
19701da177e4SLinus Torvalds 						break;
19711da177e4SLinus Torvalds 					default:
19721da177e4SLinus Torvalds 						break;
19731da177e4SLinus Torvalds 					}
1974340b9612SFinn Thain 					break;
19751da177e4SLinus Torvalds 				case DISCONNECT:{
19761da177e4SLinus Torvalds 						/* Accept message by clearing ACK */
19771da177e4SLinus Torvalds 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
19781da177e4SLinus Torvalds 						hostdata->connected = NULL;
197932b26a10SFinn Thain 						list_add(&ncmd->list, &hostdata->disconnected);
19800d3d9a42SFinn Thain 						dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES,
19810d3d9a42SFinn Thain 						         instance, "connected command %p for target %d lun %llu moved to disconnected queue\n",
19820d3d9a42SFinn Thain 						         cmd, scmd_id(cmd), cmd->device->lun);
19830d3d9a42SFinn Thain 
19841da177e4SLinus Torvalds 						/*
19851da177e4SLinus Torvalds 						 * Restore phase bits to 0 so an interrupted selection,
19861da177e4SLinus Torvalds 						 * arbitration can resume.
19871da177e4SLinus Torvalds 						 */
19881da177e4SLinus Torvalds 						NCR5380_write(TARGET_COMMAND_REG, 0);
19891da177e4SLinus Torvalds 
19901da177e4SLinus Torvalds 						/* Enable reselect interrupts */
19911da177e4SLinus Torvalds 						NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
19921da177e4SLinus Torvalds 						return;
19931da177e4SLinus Torvalds 					}
19941da177e4SLinus Torvalds 					/*
19951da177e4SLinus Torvalds 					 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
19961da177e4SLinus Torvalds 					 * operation, in violation of the SCSI spec so we can safely
19971da177e4SLinus Torvalds 					 * ignore SAVE/RESTORE pointers calls.
19981da177e4SLinus Torvalds 					 *
19991da177e4SLinus Torvalds 					 * Unfortunately, some disks violate the SCSI spec and
20001da177e4SLinus Torvalds 					 * don't issue the required SAVE_POINTERS message before
20011da177e4SLinus Torvalds 					 * disconnecting, and we have to break spec to remain
20021da177e4SLinus Torvalds 					 * compatible.
20031da177e4SLinus Torvalds 					 */
20041da177e4SLinus Torvalds 				case SAVE_POINTERS:
20051da177e4SLinus Torvalds 				case RESTORE_POINTERS:
20061da177e4SLinus Torvalds 					/* Accept message by clearing ACK */
20071da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
20081da177e4SLinus Torvalds 					break;
20091da177e4SLinus Torvalds 				case EXTENDED_MESSAGE:
20101da177e4SLinus Torvalds /*
20111da177e4SLinus Torvalds  * Extended messages are sent in the following format :
20121da177e4SLinus Torvalds  * Byte
20131da177e4SLinus Torvalds  * 0            EXTENDED_MESSAGE == 1
20141da177e4SLinus Torvalds  * 1            length (includes one byte for code, doesn't
20151da177e4SLinus Torvalds  *              include first two bytes)
20161da177e4SLinus Torvalds  * 2            code
20171da177e4SLinus Torvalds  * 3..length+1  arguments
20181da177e4SLinus Torvalds  *
20191da177e4SLinus Torvalds  * Start the extended message buffer with the EXTENDED_MESSAGE
20201abfd370SMatthew Wilcox  * byte, since spi_print_msg() wants the whole thing.
20211da177e4SLinus Torvalds  */
20221da177e4SLinus Torvalds 					extended_msg[0] = EXTENDED_MESSAGE;
20231da177e4SLinus Torvalds 					/* Accept first byte by clearing ACK */
20241da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
202511d2f63bSFinn Thain 
202611d2f63bSFinn Thain 					spin_unlock_irq(&hostdata->lock);
202711d2f63bSFinn Thain 
2028*b746545fSFinn Thain 					dsprintk(NDEBUG_EXTENDED, instance, "receiving extended message\n");
20291da177e4SLinus Torvalds 
20301da177e4SLinus Torvalds 					len = 2;
20311da177e4SLinus Torvalds 					data = extended_msg + 1;
20321da177e4SLinus Torvalds 					phase = PHASE_MSGIN;
20331da177e4SLinus Torvalds 					NCR5380_transfer_pio(instance, &phase, &len, &data);
2034*b746545fSFinn Thain 					dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n",
2035*b746545fSFinn Thain 					         (int)extended_msg[1],
2036*b746545fSFinn Thain 					         (int)extended_msg[2]);
20371da177e4SLinus Torvalds 
2038e0783ed3SFinn Thain 					if (!len && extended_msg[1] > 0 &&
2039e0783ed3SFinn Thain 					    extended_msg[1] <= sizeof(extended_msg) - 2) {
20401da177e4SLinus Torvalds 						/* Accept third byte by clearing ACK */
20411da177e4SLinus Torvalds 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
20421da177e4SLinus Torvalds 						len = extended_msg[1] - 1;
20431da177e4SLinus Torvalds 						data = extended_msg + 3;
20441da177e4SLinus Torvalds 						phase = PHASE_MSGIN;
20451da177e4SLinus Torvalds 
20461da177e4SLinus Torvalds 						NCR5380_transfer_pio(instance, &phase, &len, &data);
2047*b746545fSFinn Thain 						dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n",
2048*b746545fSFinn Thain 						         len);
20491da177e4SLinus Torvalds 
20501da177e4SLinus Torvalds 						switch (extended_msg[2]) {
20511da177e4SLinus Torvalds 						case EXTENDED_SDTR:
20521da177e4SLinus Torvalds 						case EXTENDED_WDTR:
20531da177e4SLinus Torvalds 						case EXTENDED_MODIFY_DATA_POINTER:
20541da177e4SLinus Torvalds 						case EXTENDED_EXTENDED_IDENTIFY:
20551da177e4SLinus Torvalds 							tmp = 0;
20561da177e4SLinus Torvalds 						}
20571da177e4SLinus Torvalds 					} else if (len) {
20586a6ff4acSFinn Thain 						shost_printk(KERN_ERR, instance, "error receiving extended message\n");
20591da177e4SLinus Torvalds 						tmp = 0;
20601da177e4SLinus Torvalds 					} else {
20616a6ff4acSFinn Thain 						shost_printk(KERN_NOTICE, instance, "extended message code %02x length %d is too long\n",
20626a6ff4acSFinn Thain 						             extended_msg[2], extended_msg[1]);
20631da177e4SLinus Torvalds 						tmp = 0;
20641da177e4SLinus Torvalds 					}
206511d2f63bSFinn Thain 
206611d2f63bSFinn Thain 					spin_lock_irq(&hostdata->lock);
206711d2f63bSFinn Thain 					if (!hostdata->connected)
206811d2f63bSFinn Thain 						return;
206911d2f63bSFinn Thain 
20701da177e4SLinus Torvalds 					/* Fall through to reject message */
20711da177e4SLinus Torvalds 
20721da177e4SLinus Torvalds 					/*
20731da177e4SLinus Torvalds 					 * If we get something weird that we aren't expecting,
20741da177e4SLinus Torvalds 					 * reject it.
20751da177e4SLinus Torvalds 					 */
20761da177e4SLinus Torvalds 				default:
20771da177e4SLinus Torvalds 					if (!tmp) {
20786a6ff4acSFinn Thain 						shost_printk(KERN_ERR, instance, "rejecting message ");
20791abfd370SMatthew Wilcox 						spi_print_msg(extended_msg);
20801da177e4SLinus Torvalds 						printk("\n");
20811da177e4SLinus Torvalds 					} else if (tmp != EXTENDED_MESSAGE)
2082017560fcSJeff Garzik 						scmd_printk(KERN_INFO, cmd,
2083017560fcSJeff Garzik 							"rejecting unknown message %02x\n",tmp);
20841da177e4SLinus Torvalds 					else
2085017560fcSJeff Garzik 						scmd_printk(KERN_INFO, cmd,
2086017560fcSJeff Garzik 							"rejecting unknown extended message code %02x, length %d\n", extended_msg[1], extended_msg[0]);
20871da177e4SLinus Torvalds 
20881da177e4SLinus Torvalds 					msgout = MESSAGE_REJECT;
20891da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
20901da177e4SLinus Torvalds 					break;
20911da177e4SLinus Torvalds 				}	/* switch (tmp) */
20921da177e4SLinus Torvalds 				break;
20931da177e4SLinus Torvalds 			case PHASE_MSGOUT:
20941da177e4SLinus Torvalds 				len = 1;
20951da177e4SLinus Torvalds 				data = &msgout;
20961da177e4SLinus Torvalds 				hostdata->last_message = msgout;
20971da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
20981da177e4SLinus Torvalds 				if (msgout == ABORT) {
20991da177e4SLinus Torvalds 					hostdata->connected = NULL;
21001da177e4SLinus Torvalds 					cmd->result = DID_ERROR << 16;
2101677e0194SFinn Thain 					complete_cmd(instance, cmd);
21021da177e4SLinus Torvalds 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
21031da177e4SLinus Torvalds 					return;
21041da177e4SLinus Torvalds 				}
21051da177e4SLinus Torvalds 				msgout = NOP;
21061da177e4SLinus Torvalds 				break;
21071da177e4SLinus Torvalds 			case PHASE_CMDOUT:
21081da177e4SLinus Torvalds 				len = cmd->cmd_len;
21091da177e4SLinus Torvalds 				data = cmd->cmnd;
21101da177e4SLinus Torvalds 				/*
21111da177e4SLinus Torvalds 				 * XXX for performance reasons, on machines with a
21121da177e4SLinus Torvalds 				 * PSEUDO-DMA architecture we should probably
21131da177e4SLinus Torvalds 				 * use the dma transfer function.
21141da177e4SLinus Torvalds 				 */
21151da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
21161da177e4SLinus Torvalds 				break;
21171da177e4SLinus Torvalds 			case PHASE_STATIN:
21181da177e4SLinus Torvalds 				len = 1;
21191da177e4SLinus Torvalds 				data = &tmp;
21201da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
21211da177e4SLinus Torvalds 				cmd->SCp.Status = tmp;
21221da177e4SLinus Torvalds 				break;
21231da177e4SLinus Torvalds 			default:
21246a6ff4acSFinn Thain 				shost_printk(KERN_ERR, instance, "unknown phase\n");
21254dde8f7dSFinn Thain 				NCR5380_dprint(NDEBUG_ANY, instance);
21261da177e4SLinus Torvalds 			}	/* switch(phase) */
2127686f3990SFinn Thain 		} else {
212811d2f63bSFinn Thain 			spin_unlock_irq(&hostdata->lock);
2129686f3990SFinn Thain 			NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
213011d2f63bSFinn Thain 			spin_lock_irq(&hostdata->lock);
21311da177e4SLinus Torvalds 		}
213211d2f63bSFinn Thain 	}
21331da177e4SLinus Torvalds }
21341da177e4SLinus Torvalds 
21351da177e4SLinus Torvalds /*
21361da177e4SLinus Torvalds  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
21371da177e4SLinus Torvalds  *
21381da177e4SLinus Torvalds  * Purpose : does reselection, initializing the instance->connected
2139710ddd0dSFinn Thain  *      field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
21401da177e4SLinus Torvalds  *      nexus has been reestablished,
21411da177e4SLinus Torvalds  *
21421da177e4SLinus Torvalds  * Inputs : instance - this instance of the NCR5380.
21431da177e4SLinus Torvalds  *
21441da177e4SLinus Torvalds  * Locks: io_request_lock held by caller if IRQ driven
21451da177e4SLinus Torvalds  */
21461da177e4SLinus Torvalds 
21471da177e4SLinus Torvalds static void NCR5380_reselect(struct Scsi_Host *instance) {
2148e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
21491da177e4SLinus Torvalds 	unsigned char target_mask;
21501da177e4SLinus Torvalds 	unsigned char lun, phase;
21511da177e4SLinus Torvalds 	int len;
21521da177e4SLinus Torvalds 	unsigned char msg[3];
21531da177e4SLinus Torvalds 	unsigned char *data;
215432b26a10SFinn Thain 	struct NCR5380_cmd *ncmd;
215532b26a10SFinn Thain 	struct scsi_cmnd *tmp;
21561da177e4SLinus Torvalds 
21571da177e4SLinus Torvalds 	/*
21581da177e4SLinus Torvalds 	 * Disable arbitration, etc. since the host adapter obviously
21591da177e4SLinus Torvalds 	 * lost, and tell an interrupted NCR5380_select() to restart.
21601da177e4SLinus Torvalds 	 */
21611da177e4SLinus Torvalds 
21621da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
21631da177e4SLinus Torvalds 
21641da177e4SLinus Torvalds 	target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
2165*b746545fSFinn Thain 
2166*b746545fSFinn Thain 	dsprintk(NDEBUG_RESELECTION, instance, "reselect\n");
21671da177e4SLinus Torvalds 
21681da177e4SLinus Torvalds 	/*
21691da177e4SLinus Torvalds 	 * At this point, we have detected that our SCSI ID is on the bus,
21701da177e4SLinus Torvalds 	 * SEL is true and BSY was false for at least one bus settle delay
21711da177e4SLinus Torvalds 	 * (400 ns).
21721da177e4SLinus Torvalds 	 *
21731da177e4SLinus Torvalds 	 * We must assert BSY ourselves, until the target drops the SEL
21741da177e4SLinus Torvalds 	 * signal.
21751da177e4SLinus Torvalds 	 */
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
217872064a78SFinn Thain 	if (NCR5380_poll_politely(instance,
217972064a78SFinn Thain 	                          STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) {
218072064a78SFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
218172064a78SFinn Thain 		return;
218272064a78SFinn Thain 	}
21831da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
21841da177e4SLinus Torvalds 
21851da177e4SLinus Torvalds 	/*
21861da177e4SLinus Torvalds 	 * Wait for target to go into MSGIN.
21871da177e4SLinus Torvalds 	 */
21881da177e4SLinus Torvalds 
21891cc160e1SFinn Thain 	if (NCR5380_poll_politely(instance,
219072064a78SFinn Thain 	                          STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) {
219172064a78SFinn Thain 		do_abort(instance);
219272064a78SFinn Thain 		return;
219372064a78SFinn Thain 	}
21941da177e4SLinus Torvalds 
21951da177e4SLinus Torvalds 	len = 1;
21961da177e4SLinus Torvalds 	data = msg;
21971da177e4SLinus Torvalds 	phase = PHASE_MSGIN;
21981da177e4SLinus Torvalds 	NCR5380_transfer_pio(instance, &phase, &len, &data);
21991da177e4SLinus Torvalds 
220072064a78SFinn Thain 	if (len) {
220172064a78SFinn Thain 		do_abort(instance);
220272064a78SFinn Thain 		return;
220372064a78SFinn Thain 	}
220472064a78SFinn Thain 
22051da177e4SLinus Torvalds 	if (!(msg[0] & 0x80)) {
220672064a78SFinn Thain 		shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got ");
22071abfd370SMatthew Wilcox 		spi_print_msg(msg);
220872064a78SFinn Thain 		printk("\n");
220972064a78SFinn Thain 		do_abort(instance);
221072064a78SFinn Thain 		return;
221172064a78SFinn Thain 	}
221272064a78SFinn Thain 	lun = msg[0] & 0x07;
22131da177e4SLinus Torvalds 
22141da177e4SLinus Torvalds 	/*
22151da177e4SLinus Torvalds 	 * We need to add code for SCSI-II to track which devices have
22161da177e4SLinus Torvalds 	 * I_T_L_Q nexuses established, and which have simple I_T_L
22171da177e4SLinus Torvalds 	 * nexuses so we can chose to do additional data transfer.
22181da177e4SLinus Torvalds 	 */
22191da177e4SLinus Torvalds 
22201da177e4SLinus Torvalds 	/*
22211da177e4SLinus Torvalds 	 * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we
22221da177e4SLinus Torvalds 	 * just reestablished, and remove it from the disconnected queue.
22231da177e4SLinus Torvalds 	 */
22241da177e4SLinus Torvalds 
222532b26a10SFinn Thain 	tmp = NULL;
222632b26a10SFinn Thain 	list_for_each_entry(ncmd, &hostdata->disconnected, list) {
222732b26a10SFinn Thain 		struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
222832b26a10SFinn Thain 
222932b26a10SFinn Thain 		if (target_mask == (1 << scmd_id(cmd)) &&
223032b26a10SFinn Thain 		    lun == (u8)cmd->device->lun) {
223132b26a10SFinn Thain 			list_del(&ncmd->list);
223232b26a10SFinn Thain 			tmp = cmd;
22331da177e4SLinus Torvalds 			break;
22341da177e4SLinus Torvalds 		}
223572064a78SFinn Thain 	}
22360d3d9a42SFinn Thain 
22370d3d9a42SFinn Thain 	if (tmp) {
22380d3d9a42SFinn Thain 		dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance,
22390d3d9a42SFinn Thain 		         "reselect: removed %p from disconnected queue\n", tmp);
22400d3d9a42SFinn Thain 	} else {
224172064a78SFinn Thain 		shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n",
224272064a78SFinn Thain 		             target_mask, lun);
22431da177e4SLinus Torvalds 		/*
22441da177e4SLinus Torvalds 		 * Since we have an established nexus that we can't do anything with,
22451da177e4SLinus Torvalds 		 * we must abort it.
22461da177e4SLinus Torvalds 		 */
224772064a78SFinn Thain 		do_abort(instance);
224872064a78SFinn Thain 		return;
22491da177e4SLinus Torvalds 	}
22501da177e4SLinus Torvalds 
225172064a78SFinn Thain 	/* Accept message by clearing ACK */
225272064a78SFinn Thain 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
225372064a78SFinn Thain 
22541da177e4SLinus Torvalds 	hostdata->connected = tmp;
2255*b746545fSFinn Thain 	dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n",
2256*b746545fSFinn Thain 	         scmd_id(tmp), tmp->device->lun, tmp->tag);
22571da177e4SLinus Torvalds }
22581da177e4SLinus Torvalds 
22591da177e4SLinus Torvalds /*
22601da177e4SLinus Torvalds  * Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
22611da177e4SLinus Torvalds  *
22621da177e4SLinus Torvalds  * Purpose : called by interrupt handler when DMA finishes or a phase
22631da177e4SLinus Torvalds  *      mismatch occurs (which would finish the DMA transfer).
22641da177e4SLinus Torvalds  *
22651da177e4SLinus Torvalds  * Inputs : instance - this instance of the NCR5380.
22661da177e4SLinus Torvalds  *
2267710ddd0dSFinn Thain  * Returns : pointer to the scsi_cmnd structure for which the I_T_L
22681da177e4SLinus Torvalds  *      nexus has been reestablished, on failure NULL is returned.
22691da177e4SLinus Torvalds  */
22701da177e4SLinus Torvalds 
22711da177e4SLinus Torvalds #ifdef REAL_DMA
22721da177e4SLinus Torvalds static void NCR5380_dma_complete(NCR5380_instance * instance) {
2273e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
22741da177e4SLinus Torvalds 	int transferred;
22751da177e4SLinus Torvalds 
22761da177e4SLinus Torvalds 	/*
22771da177e4SLinus Torvalds 	 * XXX this might not be right.
22781da177e4SLinus Torvalds 	 *
22791da177e4SLinus Torvalds 	 * Wait for final byte to transfer, ie wait for ACK to go false.
22801da177e4SLinus Torvalds 	 *
22811da177e4SLinus Torvalds 	 * We should use the Last Byte Sent bit, unfortunately this is
22821da177e4SLinus Torvalds 	 * not available on the 5380/5381 (only the various CMOS chips)
22831da177e4SLinus Torvalds 	 *
22841da177e4SLinus Torvalds 	 * FIXME: timeout, and need to handle long timeout/irq case
22851da177e4SLinus Torvalds 	 */
22861da177e4SLinus Torvalds 
22871da177e4SLinus Torvalds 	NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ);
22881da177e4SLinus Torvalds 
22891da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
22901da177e4SLinus Torvalds 
22911da177e4SLinus Torvalds 	/*
22921da177e4SLinus Torvalds 	 * The only places we should see a phase mismatch and have to send
22931da177e4SLinus Torvalds 	 * data from the same set of pointers will be the data transfer
22941da177e4SLinus Torvalds 	 * phases.  So, residual, requested length are only important here.
22951da177e4SLinus Torvalds 	 */
22961da177e4SLinus Torvalds 
22971da177e4SLinus Torvalds 	if (!(hostdata->connected->SCp.phase & SR_CD)) {
22981da177e4SLinus Torvalds 		transferred = instance->dmalen - NCR5380_dma_residual();
22991da177e4SLinus Torvalds 		hostdata->connected->SCp.this_residual -= transferred;
23001da177e4SLinus Torvalds 		hostdata->connected->SCp.ptr += transferred;
23011da177e4SLinus Torvalds 	}
23021da177e4SLinus Torvalds }
23031da177e4SLinus Torvalds #endif				/* def REAL_DMA */
23041da177e4SLinus Torvalds 
23058b00c3d5SFinn Thain /**
23068b00c3d5SFinn Thain  * list_find_cmd - test for presence of a command in a linked list
23078b00c3d5SFinn Thain  * @haystack: list of commands
23088b00c3d5SFinn Thain  * @needle: command to search for
23098b00c3d5SFinn Thain  */
23108b00c3d5SFinn Thain 
23118b00c3d5SFinn Thain static bool list_find_cmd(struct list_head *haystack,
23128b00c3d5SFinn Thain                           struct scsi_cmnd *needle)
23138b00c3d5SFinn Thain {
23148b00c3d5SFinn Thain 	struct NCR5380_cmd *ncmd;
23158b00c3d5SFinn Thain 
23168b00c3d5SFinn Thain 	list_for_each_entry(ncmd, haystack, list)
23178b00c3d5SFinn Thain 		if (NCR5380_to_scmd(ncmd) == needle)
23188b00c3d5SFinn Thain 			return true;
23198b00c3d5SFinn Thain 	return false;
23208b00c3d5SFinn Thain }
23218b00c3d5SFinn Thain 
23228b00c3d5SFinn Thain /**
23238b00c3d5SFinn Thain  * list_remove_cmd - remove a command from linked list
23248b00c3d5SFinn Thain  * @haystack: list of commands
23258b00c3d5SFinn Thain  * @needle: command to remove
23268b00c3d5SFinn Thain  */
23278b00c3d5SFinn Thain 
23288b00c3d5SFinn Thain static bool list_del_cmd(struct list_head *haystack,
23298b00c3d5SFinn Thain                          struct scsi_cmnd *needle)
23308b00c3d5SFinn Thain {
23318b00c3d5SFinn Thain 	if (list_find_cmd(haystack, needle)) {
23328b00c3d5SFinn Thain 		struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle);
23338b00c3d5SFinn Thain 
23348b00c3d5SFinn Thain 		list_del(&ncmd->list);
23358b00c3d5SFinn Thain 		return true;
23368b00c3d5SFinn Thain 	}
23378b00c3d5SFinn Thain 	return false;
23388b00c3d5SFinn Thain }
23398b00c3d5SFinn Thain 
23408b00c3d5SFinn Thain /**
23418b00c3d5SFinn Thain  * NCR5380_abort - scsi host eh_abort_handler() method
23428b00c3d5SFinn Thain  * @cmd: the command to be aborted
23431da177e4SLinus Torvalds  *
23448b00c3d5SFinn Thain  * Try to abort a given command by removing it from queues and/or sending
23458b00c3d5SFinn Thain  * the target an abort message. This may not succeed in causing a target
23468b00c3d5SFinn Thain  * to abort the command. Nonetheless, the low-level driver must forget about
23478b00c3d5SFinn Thain  * the command because the mid-layer reclaims it and it may be re-issued.
23481da177e4SLinus Torvalds  *
23498b00c3d5SFinn Thain  * The normal path taken by a command is as follows. For EH we trace this
23508b00c3d5SFinn Thain  * same path to locate and abort the command.
23511da177e4SLinus Torvalds  *
23528b00c3d5SFinn Thain  * unissued -> selecting -> [unissued -> selecting ->]... connected ->
23538b00c3d5SFinn Thain  * [disconnected -> connected ->]...
23548b00c3d5SFinn Thain  * [autosense -> connected ->] done
23551da177e4SLinus Torvalds  *
23568b00c3d5SFinn Thain  * If cmd is unissued then just remove it.
23578b00c3d5SFinn Thain  * If cmd is disconnected, try to select the target.
23588b00c3d5SFinn Thain  * If cmd is connected, try to send an abort message.
23598b00c3d5SFinn Thain  * If cmd is waiting for autosense, give it a chance to complete but check
23608b00c3d5SFinn Thain  * that it isn't left connected.
23618b00c3d5SFinn Thain  * If cmd was not found at all then presumably it has already been completed,
23628b00c3d5SFinn Thain  * in which case return SUCCESS to try to avoid further EH measures.
23638b00c3d5SFinn Thain  * If the command has not completed yet, we must not fail to find it.
23641da177e4SLinus Torvalds  */
23651da177e4SLinus Torvalds 
2366710ddd0dSFinn Thain static int NCR5380_abort(struct scsi_cmnd *cmd)
2367710ddd0dSFinn Thain {
23681da177e4SLinus Torvalds 	struct Scsi_Host *instance = cmd->device->host;
2369e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
237011d2f63bSFinn Thain 	unsigned long flags;
23718b00c3d5SFinn Thain 	int result = SUCCESS;
23721da177e4SLinus Torvalds 
237311d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
237411d2f63bSFinn Thain 
237532b26a10SFinn Thain #if (NDEBUG & NDEBUG_ANY)
23768b00c3d5SFinn Thain 	scmd_printk(KERN_INFO, cmd, __func__);
237732b26a10SFinn Thain #endif
2378e5c3fddfSFinn Thain 	NCR5380_dprint(NDEBUG_ANY, instance);
2379e5c3fddfSFinn Thain 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
23801da177e4SLinus Torvalds 
23818b00c3d5SFinn Thain 	if (list_del_cmd(&hostdata->unissued, cmd)) {
23828b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance,
23838b00c3d5SFinn Thain 		         "abort: removed %p from issue queue\n", cmd);
23848b00c3d5SFinn Thain 		cmd->result = DID_ABORT << 16;
23858b00c3d5SFinn Thain 		cmd->scsi_done(cmd); /* No tag or busy flag to worry about */
23868b00c3d5SFinn Thain 	}
23878b00c3d5SFinn Thain 
2388707d62b3SFinn Thain 	if (hostdata->selecting == cmd) {
2389707d62b3SFinn Thain 		dsprintk(NDEBUG_ABORT, instance,
2390707d62b3SFinn Thain 		         "abort: cmd %p == selecting\n", cmd);
2391707d62b3SFinn Thain 		hostdata->selecting = NULL;
2392707d62b3SFinn Thain 		cmd->result = DID_ABORT << 16;
2393707d62b3SFinn Thain 		complete_cmd(instance, cmd);
2394707d62b3SFinn Thain 		goto out;
2395707d62b3SFinn Thain 	}
2396707d62b3SFinn Thain 
23978b00c3d5SFinn Thain 	if (list_del_cmd(&hostdata->disconnected, cmd)) {
23988b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance,
23998b00c3d5SFinn Thain 		         "abort: removed %p from disconnected list\n", cmd);
24008b00c3d5SFinn Thain 		cmd->result = DID_ERROR << 16;
24018b00c3d5SFinn Thain 		if (!hostdata->connected)
24028b00c3d5SFinn Thain 			NCR5380_select(instance, cmd);
24038b00c3d5SFinn Thain 		if (hostdata->connected != cmd) {
24048b00c3d5SFinn Thain 			complete_cmd(instance, cmd);
24058b00c3d5SFinn Thain 			result = FAILED;
24068b00c3d5SFinn Thain 			goto out;
24078b00c3d5SFinn Thain 		}
24088b00c3d5SFinn Thain 	}
24098b00c3d5SFinn Thain 
24108b00c3d5SFinn Thain 	if (hostdata->connected == cmd) {
24118b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
24128b00c3d5SFinn Thain 		hostdata->connected = NULL;
24138b00c3d5SFinn Thain 		if (do_abort(instance)) {
24148b00c3d5SFinn Thain 			set_host_byte(cmd, DID_ERROR);
24158b00c3d5SFinn Thain 			complete_cmd(instance, cmd);
24168b00c3d5SFinn Thain 			result = FAILED;
24178b00c3d5SFinn Thain 			goto out;
24188b00c3d5SFinn Thain 		}
24198b00c3d5SFinn Thain 		set_host_byte(cmd, DID_ABORT);
24208b00c3d5SFinn Thain #ifdef REAL_DMA
24218b00c3d5SFinn Thain 		hostdata->dma_len = 0;
24228b00c3d5SFinn Thain #endif
24238b00c3d5SFinn Thain 		if (cmd->cmnd[0] == REQUEST_SENSE)
24248b00c3d5SFinn Thain 			complete_cmd(instance, cmd);
24258b00c3d5SFinn Thain 		else {
24268b00c3d5SFinn Thain 			struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
24278b00c3d5SFinn Thain 
24288b00c3d5SFinn Thain 			/* Perform autosense for this command */
24298b00c3d5SFinn Thain 			list_add(&ncmd->list, &hostdata->autosense);
24308b00c3d5SFinn Thain 		}
24318b00c3d5SFinn Thain 	}
24328b00c3d5SFinn Thain 
24338b00c3d5SFinn Thain 	if (list_find_cmd(&hostdata->autosense, cmd)) {
24348b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance,
24358b00c3d5SFinn Thain 		         "abort: found %p on sense queue\n", cmd);
24368b00c3d5SFinn Thain 		spin_unlock_irqrestore(&hostdata->lock, flags);
24378b00c3d5SFinn Thain 		queue_work(hostdata->work_q, &hostdata->main_task);
24388b00c3d5SFinn Thain 		msleep(1000);
24398b00c3d5SFinn Thain 		spin_lock_irqsave(&hostdata->lock, flags);
24408b00c3d5SFinn Thain 		if (list_del_cmd(&hostdata->autosense, cmd)) {
24418b00c3d5SFinn Thain 			dsprintk(NDEBUG_ABORT, instance,
24428b00c3d5SFinn Thain 			         "abort: removed %p from sense queue\n", cmd);
24438b00c3d5SFinn Thain 			set_host_byte(cmd, DID_ABORT);
24448b00c3d5SFinn Thain 			complete_cmd(instance, cmd);
24458b00c3d5SFinn Thain 			goto out;
24468b00c3d5SFinn Thain 		}
24478b00c3d5SFinn Thain 	}
24488b00c3d5SFinn Thain 
24498b00c3d5SFinn Thain 	if (hostdata->connected == cmd) {
24508b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
24518b00c3d5SFinn Thain 		hostdata->connected = NULL;
24528b00c3d5SFinn Thain 		if (do_abort(instance)) {
24538b00c3d5SFinn Thain 			set_host_byte(cmd, DID_ERROR);
24548b00c3d5SFinn Thain 			complete_cmd(instance, cmd);
24558b00c3d5SFinn Thain 			result = FAILED;
24568b00c3d5SFinn Thain 			goto out;
24578b00c3d5SFinn Thain 		}
24588b00c3d5SFinn Thain 		set_host_byte(cmd, DID_ABORT);
24598b00c3d5SFinn Thain #ifdef REAL_DMA
24608b00c3d5SFinn Thain 		hostdata->dma_len = 0;
24618b00c3d5SFinn Thain #endif
24628b00c3d5SFinn Thain 		complete_cmd(instance, cmd);
24638b00c3d5SFinn Thain 	}
24648b00c3d5SFinn Thain 
24658b00c3d5SFinn Thain out:
24668b00c3d5SFinn Thain 	if (result == FAILED)
24678b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd);
24688b00c3d5SFinn Thain 	else
24698b00c3d5SFinn Thain 		dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd);
24708b00c3d5SFinn Thain 
24718b00c3d5SFinn Thain 	queue_work(hostdata->work_q, &hostdata->main_task);
247211d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
24731da177e4SLinus Torvalds 
24748b00c3d5SFinn Thain 	return result;
24751da177e4SLinus Torvalds }
24761da177e4SLinus Torvalds 
24771da177e4SLinus Torvalds 
24783be1b3eaSFinn Thain /**
24793be1b3eaSFinn Thain  * NCR5380_bus_reset - reset the SCSI bus
24803be1b3eaSFinn Thain  * @cmd: SCSI command undergoing EH
24811da177e4SLinus Torvalds  *
24823be1b3eaSFinn Thain  * Returns SUCCESS
24831da177e4SLinus Torvalds  */
24841da177e4SLinus Torvalds 
2485710ddd0dSFinn Thain static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
248668b3aa7cSJeff Garzik  {
248768b3aa7cSJeff Garzik  	struct Scsi_Host *instance = cmd->device->host;
248811d2f63bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
248962717f53SFinn Thain 	int i;
249011d2f63bSFinn Thain 	unsigned long flags;
249162717f53SFinn Thain 	struct NCR5380_cmd *ncmd;
24921da177e4SLinus Torvalds 
249311d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
24943be1b3eaSFinn Thain 
24953be1b3eaSFinn Thain #if (NDEBUG & NDEBUG_ANY)
249662717f53SFinn Thain 	scmd_printk(KERN_INFO, cmd, __func__);
24973be1b3eaSFinn Thain #endif
2498e5c3fddfSFinn Thain 	NCR5380_dprint(NDEBUG_ANY, instance);
2499e5c3fddfSFinn Thain 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
25003be1b3eaSFinn Thain 
250168b3aa7cSJeff Garzik  	do_reset(instance);
25023be1b3eaSFinn Thain 
250362717f53SFinn Thain 	/* reset NCR registers */
250462717f53SFinn Thain 	NCR5380_write(MODE_REG, MR_BASE);
250562717f53SFinn Thain 	NCR5380_write(TARGET_COMMAND_REG, 0);
250662717f53SFinn Thain 	NCR5380_write(SELECT_ENABLE_REG, 0);
250762717f53SFinn Thain 
250862717f53SFinn Thain 	/* After the reset, there are no more connected or disconnected commands
250962717f53SFinn Thain 	 * and no busy units; so clear the low-level status here to avoid
251062717f53SFinn Thain 	 * conflicts when the mid-level code tries to wake up the affected
251162717f53SFinn Thain 	 * commands!
251262717f53SFinn Thain 	 */
251362717f53SFinn Thain 
251462717f53SFinn Thain 	hostdata->selecting = NULL;
251562717f53SFinn Thain 
251662717f53SFinn Thain 	list_for_each_entry(ncmd, &hostdata->disconnected, list) {
251762717f53SFinn Thain 		struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
251862717f53SFinn Thain 
251962717f53SFinn Thain 		set_host_byte(cmd, DID_RESET);
252062717f53SFinn Thain 		cmd->scsi_done(cmd);
252162717f53SFinn Thain 	}
252262717f53SFinn Thain 
252362717f53SFinn Thain 	list_for_each_entry(ncmd, &hostdata->autosense, list) {
252462717f53SFinn Thain 		struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
252562717f53SFinn Thain 
252662717f53SFinn Thain 		set_host_byte(cmd, DID_RESET);
252762717f53SFinn Thain 		cmd->scsi_done(cmd);
252862717f53SFinn Thain 	}
252962717f53SFinn Thain 
253062717f53SFinn Thain 	if (hostdata->connected) {
253162717f53SFinn Thain 		set_host_byte(hostdata->connected, DID_RESET);
253262717f53SFinn Thain 		complete_cmd(instance, hostdata->connected);
253362717f53SFinn Thain 		hostdata->connected = NULL;
253462717f53SFinn Thain 	}
253562717f53SFinn Thain 
253662717f53SFinn Thain 	if (hostdata->sensing) {
253762717f53SFinn Thain 		set_host_byte(hostdata->connected, DID_RESET);
253862717f53SFinn Thain 		complete_cmd(instance, hostdata->sensing);
253962717f53SFinn Thain 		hostdata->sensing = NULL;
254062717f53SFinn Thain 	}
254162717f53SFinn Thain 
254262717f53SFinn Thain 	for (i = 0; i < 8; ++i)
254362717f53SFinn Thain 		hostdata->busy[i] = 0;
254462717f53SFinn Thain #ifdef REAL_DMA
254562717f53SFinn Thain 	hostdata->dma_len = 0;
254662717f53SFinn Thain #endif
254762717f53SFinn Thain 
254862717f53SFinn Thain 	queue_work(hostdata->work_q, &hostdata->main_task);
254911d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
255068b3aa7cSJeff Garzik  
25511da177e4SLinus Torvalds 	return SUCCESS;
25521da177e4SLinus Torvalds }
2553