xref: /linux/drivers/scsi/NCR5380.c (revision 32b26a104237c1ba3575a6c8d47e46060cc416fb)
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 	}
2471da177e4SLinus Torvalds }
2481da177e4SLinus Torvalds 
2491da177e4SLinus Torvalds /**
250b32ade12SFinn Thain  * NCR5380_poll_politely2 - wait for two chip register values
2511da177e4SLinus Torvalds  * @instance: controller to poll
252b32ade12SFinn Thain  * @reg1: 5380 register to poll
253b32ade12SFinn Thain  * @bit1: Bitmask to check
254b32ade12SFinn Thain  * @val1: Expected value
255b32ade12SFinn Thain  * @reg2: Second 5380 register to poll
256b32ade12SFinn Thain  * @bit2: Second bitmask to check
257b32ade12SFinn Thain  * @val2: Second expected value
2582f854b82SFinn Thain  * @wait: Time-out in jiffies
2591da177e4SLinus Torvalds  *
2602f854b82SFinn Thain  * Polls the chip in a reasonably efficient manner waiting for an
2612f854b82SFinn Thain  * event to occur. After a short quick poll we begin to yield the CPU
2622f854b82SFinn Thain  * (if possible). In irq contexts the time-out is arbitrarily limited.
2632f854b82SFinn Thain  * Callers may hold locks as long as they are held in irq mode.
2641da177e4SLinus Torvalds  *
265b32ade12SFinn Thain  * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
2661da177e4SLinus Torvalds  */
2671da177e4SLinus Torvalds 
268b32ade12SFinn Thain static int NCR5380_poll_politely2(struct Scsi_Host *instance,
269b32ade12SFinn Thain                                   int reg1, int bit1, int val1,
270b32ade12SFinn Thain                                   int reg2, int bit2, int val2, int wait)
2711da177e4SLinus Torvalds {
2722f854b82SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
2732f854b82SFinn Thain 	unsigned long deadline = jiffies + wait;
2742f854b82SFinn Thain 	unsigned long n;
2751da177e4SLinus Torvalds 
2762f854b82SFinn Thain 	/* Busy-wait for up to 10 ms */
2772f854b82SFinn Thain 	n = min(10000U, jiffies_to_usecs(wait));
2782f854b82SFinn Thain 	n *= hostdata->accesses_per_ms;
279b32ade12SFinn Thain 	n /= 2000;
2802f854b82SFinn Thain 	do {
281b32ade12SFinn Thain 		if ((NCR5380_read(reg1) & bit1) == val1)
282b32ade12SFinn Thain 			return 0;
283b32ade12SFinn Thain 		if ((NCR5380_read(reg2) & bit2) == val2)
2841da177e4SLinus Torvalds 			return 0;
2851da177e4SLinus Torvalds 		cpu_relax();
2862f854b82SFinn Thain 	} while (n--);
2872f854b82SFinn Thain 
2882f854b82SFinn Thain 	if (irqs_disabled() || in_interrupt())
2892f854b82SFinn Thain 		return -ETIMEDOUT;
2902f854b82SFinn Thain 
2912f854b82SFinn Thain 	/* Repeatedly sleep for 1 ms until deadline */
2922f854b82SFinn Thain 	while (time_is_after_jiffies(deadline)) {
2932f854b82SFinn Thain 		schedule_timeout_uninterruptible(1);
294b32ade12SFinn Thain 		if ((NCR5380_read(reg1) & bit1) == val1)
295b32ade12SFinn Thain 			return 0;
296b32ade12SFinn Thain 		if ((NCR5380_read(reg2) & bit2) == val2)
2972f854b82SFinn Thain 			return 0;
2981da177e4SLinus Torvalds 	}
2991da177e4SLinus Torvalds 
3001da177e4SLinus Torvalds 	return -ETIMEDOUT;
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds 
303b32ade12SFinn Thain static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
304b32ade12SFinn Thain                                         int reg, int bit, int val, int wait)
305b32ade12SFinn Thain {
306b32ade12SFinn Thain 	return NCR5380_poll_politely2(instance, reg, bit, val,
307b32ade12SFinn Thain 	                                        reg, bit, val, wait);
308b32ade12SFinn Thain }
309b32ade12SFinn Thain 
3101da177e4SLinus Torvalds static struct {
3111da177e4SLinus Torvalds 	unsigned char value;
3121da177e4SLinus Torvalds 	const char *name;
313702809ceSAndrew Morton } phases[] __maybe_unused = {
3141da177e4SLinus Torvalds 	{PHASE_DATAOUT, "DATAOUT"},
3151da177e4SLinus Torvalds 	{PHASE_DATAIN, "DATAIN"},
3161da177e4SLinus Torvalds 	{PHASE_CMDOUT, "CMDOUT"},
3171da177e4SLinus Torvalds 	{PHASE_STATIN, "STATIN"},
3181da177e4SLinus Torvalds 	{PHASE_MSGOUT, "MSGOUT"},
3191da177e4SLinus Torvalds 	{PHASE_MSGIN, "MSGIN"},
3201da177e4SLinus Torvalds 	{PHASE_UNKNOWN, "UNKNOWN"}
3211da177e4SLinus Torvalds };
3221da177e4SLinus Torvalds 
323185a7a1cSviro@ZenIV.linux.org.uk #if NDEBUG
3241da177e4SLinus Torvalds static struct {
3251da177e4SLinus Torvalds 	unsigned char mask;
3261da177e4SLinus Torvalds 	const char *name;
3271da177e4SLinus Torvalds } signals[] = {
3281da177e4SLinus Torvalds 	{SR_DBP, "PARITY"},
3291da177e4SLinus Torvalds 	{SR_RST, "RST"},
3301da177e4SLinus Torvalds 	{SR_BSY, "BSY"},
3311da177e4SLinus Torvalds 	{SR_REQ, "REQ"},
3321da177e4SLinus Torvalds 	{SR_MSG, "MSG"},
3331da177e4SLinus Torvalds 	{SR_CD, "CD"},
3341da177e4SLinus Torvalds 	{SR_IO, "IO"},
3351da177e4SLinus Torvalds 	{SR_SEL, "SEL"},
3361da177e4SLinus Torvalds 	{0, NULL}
3371da177e4SLinus Torvalds },
3381da177e4SLinus Torvalds basrs[] = {
3391da177e4SLinus Torvalds 	{BASR_ATN, "ATN"},
3401da177e4SLinus Torvalds 	{BASR_ACK, "ACK"},
3411da177e4SLinus Torvalds 	{0, NULL}
3421da177e4SLinus Torvalds },
3431da177e4SLinus Torvalds icrs[] = {
3441da177e4SLinus Torvalds 	{ICR_ASSERT_RST, "ASSERT RST"},
3451da177e4SLinus Torvalds 	{ICR_ASSERT_ACK, "ASSERT ACK"},
3461da177e4SLinus Torvalds 	{ICR_ASSERT_BSY, "ASSERT BSY"},
3471da177e4SLinus Torvalds 	{ICR_ASSERT_SEL, "ASSERT SEL"},
3481da177e4SLinus Torvalds 	{ICR_ASSERT_ATN, "ASSERT ATN"},
3491da177e4SLinus Torvalds 	{ICR_ASSERT_DATA, "ASSERT DATA"},
3501da177e4SLinus Torvalds 	{0, NULL}
3511da177e4SLinus Torvalds },
3521da177e4SLinus Torvalds mrs[] = {
3531da177e4SLinus Torvalds 	{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"},
3541da177e4SLinus Torvalds 	{MR_TARGET, "MODE TARGET"},
3551da177e4SLinus Torvalds 	{MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"},
3561da177e4SLinus Torvalds 	{MR_ENABLE_PAR_INTR, "MODE PARITY INTR"},
3571da177e4SLinus Torvalds 	{MR_MONITOR_BSY, "MODE MONITOR BSY"},
3581da177e4SLinus Torvalds 	{MR_DMA_MODE, "MODE DMA"},
3591da177e4SLinus Torvalds 	{MR_ARBITRATE, "MODE ARBITRATION"},
3601da177e4SLinus Torvalds 	{0, NULL}
3611da177e4SLinus Torvalds };
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds /**
3641da177e4SLinus Torvalds  *	NCR5380_print	-	print scsi bus signals
3651da177e4SLinus Torvalds  *	@instance:	adapter state to dump
3661da177e4SLinus Torvalds  *
3671da177e4SLinus Torvalds  *	Print the SCSI bus signals for debugging purposes
3681da177e4SLinus Torvalds  *
3691da177e4SLinus Torvalds  *	Locks: caller holds hostdata lock (not essential)
3701da177e4SLinus Torvalds  */
3711da177e4SLinus Torvalds 
3721da177e4SLinus Torvalds static void NCR5380_print(struct Scsi_Host *instance)
3731da177e4SLinus Torvalds {
3741da177e4SLinus Torvalds 	unsigned char status, data, basr, mr, icr, i;
3751da177e4SLinus Torvalds 
3761da177e4SLinus Torvalds 	data = NCR5380_read(CURRENT_SCSI_DATA_REG);
3771da177e4SLinus Torvalds 	status = NCR5380_read(STATUS_REG);
3781da177e4SLinus Torvalds 	mr = NCR5380_read(MODE_REG);
3791da177e4SLinus Torvalds 	icr = NCR5380_read(INITIATOR_COMMAND_REG);
3801da177e4SLinus Torvalds 	basr = NCR5380_read(BUS_AND_STATUS_REG);
3811da177e4SLinus Torvalds 
3821da177e4SLinus Torvalds 	printk("STATUS_REG: %02x ", status);
3831da177e4SLinus Torvalds 	for (i = 0; signals[i].mask; ++i)
3841da177e4SLinus Torvalds 		if (status & signals[i].mask)
3851da177e4SLinus Torvalds 			printk(",%s", signals[i].name);
3861da177e4SLinus Torvalds 	printk("\nBASR: %02x ", basr);
3871da177e4SLinus Torvalds 	for (i = 0; basrs[i].mask; ++i)
3881da177e4SLinus Torvalds 		if (basr & basrs[i].mask)
3891da177e4SLinus Torvalds 			printk(",%s", basrs[i].name);
3901da177e4SLinus Torvalds 	printk("\nICR: %02x ", icr);
3911da177e4SLinus Torvalds 	for (i = 0; icrs[i].mask; ++i)
3921da177e4SLinus Torvalds 		if (icr & icrs[i].mask)
3931da177e4SLinus Torvalds 			printk(",%s", icrs[i].name);
3941da177e4SLinus Torvalds 	printk("\nMODE: %02x ", mr);
3951da177e4SLinus Torvalds 	for (i = 0; mrs[i].mask; ++i)
3961da177e4SLinus Torvalds 		if (mr & mrs[i].mask)
3971da177e4SLinus Torvalds 			printk(",%s", mrs[i].name);
3981da177e4SLinus Torvalds 	printk("\n");
3991da177e4SLinus Torvalds }
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds 
4021da177e4SLinus Torvalds /*
4031da177e4SLinus Torvalds  *	NCR5380_print_phase	-	show SCSI phase
4041da177e4SLinus Torvalds  *	@instance: adapter to dump
4051da177e4SLinus Torvalds  *
4061da177e4SLinus Torvalds  * 	Print the current SCSI phase for debugging purposes
4071da177e4SLinus Torvalds  *
4081da177e4SLinus Torvalds  *	Locks: none
4091da177e4SLinus Torvalds  */
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds static void NCR5380_print_phase(struct Scsi_Host *instance)
4121da177e4SLinus Torvalds {
4131da177e4SLinus Torvalds 	unsigned char status;
4141da177e4SLinus Torvalds 	int i;
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 	status = NCR5380_read(STATUS_REG);
4171da177e4SLinus Torvalds 	if (!(status & SR_REQ))
4181da177e4SLinus Torvalds 		printk("scsi%d : REQ not asserted, phase unknown.\n", instance->host_no);
4191da177e4SLinus Torvalds 	else {
4201da177e4SLinus Torvalds 		for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
4211da177e4SLinus Torvalds 		printk("scsi%d : phase %s\n", instance->host_no, phases[i].name);
4221da177e4SLinus Torvalds 	}
4231da177e4SLinus Torvalds }
4241da177e4SLinus Torvalds #endif
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds 
427d5f7e65dSFinn Thain static int probe_irq __initdata;
4281da177e4SLinus Torvalds 
4291da177e4SLinus Torvalds /**
4301da177e4SLinus Torvalds  *	probe_intr	-	helper for IRQ autoprobe
4311da177e4SLinus Torvalds  *	@irq: interrupt number
4321da177e4SLinus Torvalds  *	@dev_id: unused
4331da177e4SLinus Torvalds  *	@regs: unused
4341da177e4SLinus Torvalds  *
4351da177e4SLinus Torvalds  *	Set a flag to indicate the IRQ in question was received. This is
4361da177e4SLinus Torvalds  *	used by the IRQ probe code.
4371da177e4SLinus Torvalds  */
4381da177e4SLinus Torvalds 
4397d12e780SDavid Howells static irqreturn_t __init probe_intr(int irq, void *dev_id)
4401da177e4SLinus Torvalds {
4411da177e4SLinus Torvalds 	probe_irq = irq;
4421da177e4SLinus Torvalds 	return IRQ_HANDLED;
4431da177e4SLinus Torvalds }
4441da177e4SLinus Torvalds 
4451da177e4SLinus Torvalds /**
4461da177e4SLinus Torvalds  *	NCR5380_probe_irq	-	find the IRQ of an NCR5380
4471da177e4SLinus Torvalds  *	@instance: NCR5380 controller
4481da177e4SLinus Torvalds  *	@possible: bitmask of ISA IRQ lines
4491da177e4SLinus Torvalds  *
4501da177e4SLinus Torvalds  *	Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
4511da177e4SLinus Torvalds  *	and then looking to see what interrupt actually turned up.
4521da177e4SLinus Torvalds  *
4531da177e4SLinus Torvalds  *	Locks: none, irqs must be enabled on entry
4541da177e4SLinus Torvalds  */
4551da177e4SLinus Torvalds 
456702809ceSAndrew Morton static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
457702809ceSAndrew Morton 						int possible)
4581da177e4SLinus Torvalds {
459e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
4601da177e4SLinus Torvalds 	unsigned long timeout;
4611da177e4SLinus Torvalds 	int trying_irqs, i, mask;
4621da177e4SLinus Torvalds 
46322f5f10dSFinn Thain 	for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
4644909cc2bSMichael Opdenacker 		if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
4651da177e4SLinus Torvalds 			trying_irqs |= mask;
4661da177e4SLinus Torvalds 
4674e5a800cSNicholas Mc Guire 	timeout = jiffies + msecs_to_jiffies(250);
46822f5f10dSFinn Thain 	probe_irq = NO_IRQ;
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds 	/*
4711da177e4SLinus Torvalds 	 * A interrupt is triggered whenever BSY = false, SEL = true
4721da177e4SLinus Torvalds 	 * and a bit set in the SELECT_ENABLE_REG is asserted on the
4731da177e4SLinus Torvalds 	 * SCSI bus.
4741da177e4SLinus Torvalds 	 *
4751da177e4SLinus Torvalds 	 * Note that the bus is only driven when the phase control signals
4761da177e4SLinus Torvalds 	 * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
4771da177e4SLinus Torvalds 	 * to zero.
4781da177e4SLinus Torvalds 	 */
4791da177e4SLinus Torvalds 
4801da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, 0);
4811da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
4821da177e4SLinus Torvalds 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
4831da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
4841da177e4SLinus Torvalds 
48522f5f10dSFinn Thain 	while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
486a9a3047dSNishanth Aravamudan 		schedule_timeout_uninterruptible(1);
4871da177e4SLinus Torvalds 
4881da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, 0);
4891da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
4901da177e4SLinus Torvalds 
49122f5f10dSFinn Thain 	for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
4921da177e4SLinus Torvalds 		if (trying_irqs & mask)
4931da177e4SLinus Torvalds 			free_irq(i, NULL);
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds 	return probe_irq;
4961da177e4SLinus Torvalds }
4971da177e4SLinus Torvalds 
4981da177e4SLinus Torvalds /**
4998c32513bSFinn Thain  *	NCR58380_info - report driver and host information
5008c32513bSFinn Thain  *	@instance: relevant scsi host instance
5011da177e4SLinus Torvalds  *
5028c32513bSFinn Thain  *	For use as the host template info() handler.
5031da177e4SLinus Torvalds  *
5041da177e4SLinus Torvalds  *	Locks: none
5051da177e4SLinus Torvalds  */
5061da177e4SLinus Torvalds 
5078c32513bSFinn Thain static const char *NCR5380_info(struct Scsi_Host *instance)
5081da177e4SLinus Torvalds {
5098c32513bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
5108c32513bSFinn Thain 
5118c32513bSFinn Thain 	return hostdata->info;
5128c32513bSFinn Thain }
5138c32513bSFinn Thain 
5148c32513bSFinn Thain static void prepare_info(struct Scsi_Host *instance)
5158c32513bSFinn Thain {
5168c32513bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
5178c32513bSFinn Thain 
5188c32513bSFinn Thain 	snprintf(hostdata->info, sizeof(hostdata->info),
5198c32513bSFinn Thain 	         "%s, io_port 0x%lx, n_io_port %d, "
5208c32513bSFinn Thain 	         "base 0x%lx, irq %d, "
5218c32513bSFinn Thain 	         "can_queue %d, cmd_per_lun %d, "
5228c32513bSFinn Thain 	         "sg_tablesize %d, this_id %d, "
523be3f4121SFinn Thain 	         "flags { %s%s%s}, "
5248c32513bSFinn Thain 	         "options { %s} ",
5258c32513bSFinn Thain 	         instance->hostt->name, instance->io_port, instance->n_io_port,
5268c32513bSFinn Thain 	         instance->base, instance->irq,
5278c32513bSFinn Thain 	         instance->can_queue, instance->cmd_per_lun,
5288c32513bSFinn Thain 	         instance->sg_tablesize, instance->this_id,
52955181be8SFinn Thain 	         hostdata->flags & FLAG_NO_DMA_FIXUP  ? "NO_DMA_FIXUP "  : "",
5308c32513bSFinn Thain 	         hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
5319c3f0e2bSFinn Thain 	         hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY "  : "",
5321da177e4SLinus Torvalds #ifdef AUTOPROBE_IRQ
5331da177e4SLinus Torvalds 	         "AUTOPROBE_IRQ "
5341da177e4SLinus Torvalds #endif
5351da177e4SLinus Torvalds #ifdef DIFFERENTIAL
5361da177e4SLinus Torvalds 	         "DIFFERENTIAL "
5371da177e4SLinus Torvalds #endif
5381da177e4SLinus Torvalds #ifdef REAL_DMA
5398c32513bSFinn Thain 	         "REAL_DMA "
5401da177e4SLinus Torvalds #endif
5411da177e4SLinus Torvalds #ifdef REAL_DMA_POLL
5428c32513bSFinn Thain 	         "REAL_DMA_POLL "
5431da177e4SLinus Torvalds #endif
5441da177e4SLinus Torvalds #ifdef PARITY
5451da177e4SLinus Torvalds 	         "PARITY "
5461da177e4SLinus Torvalds #endif
5471da177e4SLinus Torvalds #ifdef PSEUDO_DMA
5488c32513bSFinn Thain 	         "PSEUDO_DMA "
5491da177e4SLinus Torvalds #endif
5508c32513bSFinn Thain 	         "");
5511da177e4SLinus Torvalds }
5521da177e4SLinus Torvalds 
553a9c2dc43SFinn Thain #ifdef PSEUDO_DMA
5541da177e4SLinus Torvalds /******************************************/
5551da177e4SLinus Torvalds /*
5561da177e4SLinus Torvalds  * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
5571da177e4SLinus Torvalds  *
5581da177e4SLinus Torvalds  * *buffer: I/O buffer
5591da177e4SLinus Torvalds  * **start: if inout == FALSE pointer into buffer where user read should start
5601da177e4SLinus Torvalds  * offset: current offset
5611da177e4SLinus Torvalds  * length: length of buffer
5621da177e4SLinus Torvalds  * hostno: Scsi_Host host_no
5631da177e4SLinus Torvalds  * inout: TRUE - user is writing; FALSE - user is reading
5641da177e4SLinus Torvalds  *
5651da177e4SLinus Torvalds  * Return the number of bytes read from or written
5661da177e4SLinus Torvalds  */
5671da177e4SLinus Torvalds 
568dd7ab71bSAl Viro static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
569dd7ab71bSAl Viro 	char *buffer, int length)
5701da177e4SLinus Torvalds {
571a9c2dc43SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
572a9c2dc43SFinn Thain 
573a9c2dc43SFinn Thain 	hostdata->spin_max_r = 0;
574a9c2dc43SFinn Thain 	hostdata->spin_max_w = 0;
575a9c2dc43SFinn Thain 	return 0;
5761da177e4SLinus Torvalds }
577dd7ab71bSAl Viro 
578dd7ab71bSAl Viro static int __maybe_unused NCR5380_show_info(struct seq_file *m,
579dd7ab71bSAl Viro 	struct Scsi_Host *instance)
580dd7ab71bSAl Viro {
581e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
582dd7ab71bSAl Viro 
5830c3de38fSRasmus Villemoes 	seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n",
584a9c2dc43SFinn Thain 	        hostdata->spin_max_w, hostdata->spin_max_r);
5851da177e4SLinus Torvalds 	return 0;
5861da177e4SLinus Torvalds }
587e5c3fddfSFinn Thain #endif
5881da177e4SLinus Torvalds 
5891da177e4SLinus Torvalds /**
5901da177e4SLinus Torvalds  *	NCR5380_init	-	initialise an NCR5380
5911da177e4SLinus Torvalds  *	@instance: adapter to configure
5921da177e4SLinus Torvalds  *	@flags: control flags
5931da177e4SLinus Torvalds  *
5941da177e4SLinus Torvalds  *	Initializes *instance and corresponding 5380 chip,
5951da177e4SLinus Torvalds  *      with flags OR'd into the initial flags value.
5961da177e4SLinus Torvalds  *
5971da177e4SLinus Torvalds  *	Notes : I assume that the host, hostno, and id bits have been
5981da177e4SLinus Torvalds  *      set correctly.  I don't care about the irq and other fields.
5991da177e4SLinus Torvalds  *
6001da177e4SLinus Torvalds  *	Returns 0 for success
6011da177e4SLinus Torvalds  *
6021da177e4SLinus Torvalds  *	Locks: interrupts must be enabled when we are called
6031da177e4SLinus Torvalds  */
6041da177e4SLinus Torvalds 
6056f039790SGreg Kroah-Hartman static int NCR5380_init(struct Scsi_Host *instance, int flags)
6061da177e4SLinus Torvalds {
607e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
608b6488f97SFinn Thain 	int i;
6092f854b82SFinn Thain 	unsigned long deadline;
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds 	if(in_interrupt())
6121da177e4SLinus Torvalds 		printk(KERN_ERR "NCR5380_init called with interrupts off!\n");
6131da177e4SLinus Torvalds 
6141da177e4SLinus Torvalds 	hostdata->id_mask = 1 << instance->this_id;
6151da177e4SLinus Torvalds 	for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
6161da177e4SLinus Torvalds 		if (i > hostdata->id_mask)
6171da177e4SLinus Torvalds 			hostdata->id_higher_mask |= i;
6181da177e4SLinus Torvalds 	for (i = 0; i < 8; ++i)
6191da177e4SLinus Torvalds 		hostdata->busy[i] = 0;
6201da177e4SLinus Torvalds #ifdef REAL_DMA
6211da177e4SLinus Torvalds 	hostdata->dmalen = 0;
6221da177e4SLinus Torvalds #endif
62311d2f63bSFinn Thain 	spin_lock_init(&hostdata->lock);
6241da177e4SLinus Torvalds 	hostdata->connected = NULL;
625*32b26a10SFinn Thain 	INIT_LIST_HEAD(&hostdata->unissued);
626*32b26a10SFinn Thain 	INIT_LIST_HEAD(&hostdata->disconnected);
627*32b26a10SFinn Thain 
62855181be8SFinn Thain 	hostdata->flags = flags;
6291da177e4SLinus Torvalds 
6308d8601a7SFinn Thain 	INIT_WORK(&hostdata->main_task, NCR5380_main);
6310ad0eff9SFinn Thain 	hostdata->work_q = alloc_workqueue("ncr5380_%d",
6320ad0eff9SFinn Thain 	                        WQ_UNBOUND | WQ_MEM_RECLAIM,
6330ad0eff9SFinn Thain 	                        1, instance->host_no);
6340ad0eff9SFinn Thain 	if (!hostdata->work_q)
6350ad0eff9SFinn Thain 		return -ENOMEM;
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds 	hostdata->host = instance;
6381da177e4SLinus Torvalds 
6398c32513bSFinn Thain 	prepare_info(instance);
6408c32513bSFinn Thain 
6411da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
6421da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
6431da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, 0);
6441da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, 0);
6452f854b82SFinn Thain 
6462f854b82SFinn Thain 	/* Calibrate register polling loop */
6472f854b82SFinn Thain 	i = 0;
6482f854b82SFinn Thain 	deadline = jiffies + 1;
6492f854b82SFinn Thain 	do {
6502f854b82SFinn Thain 		cpu_relax();
6512f854b82SFinn Thain 	} while (time_is_after_jiffies(deadline));
6522f854b82SFinn Thain 	deadline += msecs_to_jiffies(256);
6532f854b82SFinn Thain 	do {
6542f854b82SFinn Thain 		NCR5380_read(STATUS_REG);
6552f854b82SFinn Thain 		++i;
6562f854b82SFinn Thain 		cpu_relax();
6572f854b82SFinn Thain 	} while (time_is_after_jiffies(deadline));
6582f854b82SFinn Thain 	hostdata->accesses_per_ms = i / 256;
6592f854b82SFinn Thain 
660b6488f97SFinn Thain 	return 0;
661b6488f97SFinn Thain }
6621da177e4SLinus Torvalds 
663b6488f97SFinn Thain /**
664b6488f97SFinn Thain  * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems.
665b6488f97SFinn Thain  * @instance: adapter to check
6661da177e4SLinus Torvalds  *
667b6488f97SFinn Thain  * If the system crashed, it may have crashed with a connected target and
668b6488f97SFinn Thain  * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the
669b6488f97SFinn Thain  * currently established nexus, which we know nothing about. Failing that
670b6488f97SFinn Thain  * do a bus reset.
6711da177e4SLinus Torvalds  *
672b6488f97SFinn Thain  * Note that a bus reset will cause the chip to assert IRQ.
673b6488f97SFinn Thain  *
674b6488f97SFinn Thain  * Returns 0 if successful, otherwise -ENXIO.
6751da177e4SLinus Torvalds  */
6761da177e4SLinus Torvalds 
677b6488f97SFinn Thain static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
678b6488f97SFinn Thain {
6799c3f0e2bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
680b6488f97SFinn Thain 	int pass;
681b6488f97SFinn Thain 
6821da177e4SLinus Torvalds 	for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
6831da177e4SLinus Torvalds 		switch (pass) {
6841da177e4SLinus Torvalds 		case 1:
6851da177e4SLinus Torvalds 		case 3:
6861da177e4SLinus Torvalds 		case 5:
687636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n");
688636b1ec8SFinn Thain 			NCR5380_poll_politely(instance,
689636b1ec8SFinn Thain 			                      STATUS_REG, SR_BSY, 0, 5 * HZ);
6901da177e4SLinus Torvalds 			break;
6911da177e4SLinus Torvalds 		case 2:
692636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n");
6931da177e4SLinus Torvalds 			do_abort(instance);
6941da177e4SLinus Torvalds 			break;
6951da177e4SLinus Torvalds 		case 4:
696636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n");
6971da177e4SLinus Torvalds 			do_reset(instance);
6989c3f0e2bSFinn Thain 			/* Wait after a reset; the SCSI standard calls for
6999c3f0e2bSFinn Thain 			 * 250ms, we wait 500ms to be on the safe side.
7009c3f0e2bSFinn Thain 			 * But some Toshiba CD-ROMs need ten times that.
7019c3f0e2bSFinn Thain 			 */
7029c3f0e2bSFinn Thain 			if (hostdata->flags & FLAG_TOSHIBA_DELAY)
7039c3f0e2bSFinn Thain 				msleep(2500);
7049c3f0e2bSFinn Thain 			else
7059c3f0e2bSFinn Thain 				msleep(500);
7061da177e4SLinus Torvalds 			break;
7071da177e4SLinus Torvalds 		case 6:
708636b1ec8SFinn Thain 			shost_printk(KERN_ERR, instance, "bus locked solid\n");
7091da177e4SLinus Torvalds 			return -ENXIO;
7101da177e4SLinus Torvalds 		}
7111da177e4SLinus Torvalds 	}
7121da177e4SLinus Torvalds 	return 0;
7131da177e4SLinus Torvalds }
7141da177e4SLinus Torvalds 
7151da177e4SLinus Torvalds /**
7161da177e4SLinus Torvalds  *	NCR5380_exit	-	remove an NCR5380
7171da177e4SLinus Torvalds  *	@instance: adapter to remove
7181da177e4SLinus Torvalds  */
7191da177e4SLinus Torvalds 
720a43cf0f3SRandy Dunlap static void NCR5380_exit(struct Scsi_Host *instance)
7211da177e4SLinus Torvalds {
722e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
7231da177e4SLinus Torvalds 
7248d8601a7SFinn Thain 	cancel_work_sync(&hostdata->main_task);
7250ad0eff9SFinn Thain 	destroy_workqueue(hostdata->work_q);
7261da177e4SLinus Torvalds }
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds /**
7291da177e4SLinus Torvalds  * NCR5380_queue_command - queue a command
7301bb40589SFinn Thain  * @instance: the relevant SCSI adapter
7311da177e4SLinus Torvalds  * @cmd: SCSI command
7321da177e4SLinus Torvalds  *
7331bb40589SFinn Thain  * cmd is added to the per-instance issue queue, with minor
7341da177e4SLinus Torvalds  * twiddling done to the host specific fields of cmd.  If the
7351da177e4SLinus Torvalds  * main coroutine is not running, it is restarted.
7361da177e4SLinus Torvalds  */
7371da177e4SLinus Torvalds 
7381bb40589SFinn Thain static int NCR5380_queue_command(struct Scsi_Host *instance,
7391bb40589SFinn Thain                                  struct scsi_cmnd *cmd)
7401da177e4SLinus Torvalds {
7411bb40589SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
742*32b26a10SFinn Thain 	struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
7431bb40589SFinn Thain 	unsigned long flags;
7441da177e4SLinus Torvalds 
7451da177e4SLinus Torvalds #if (NDEBUG & NDEBUG_NO_WRITE)
7461da177e4SLinus Torvalds 	switch (cmd->cmnd[0]) {
7471da177e4SLinus Torvalds 	case WRITE_6:
7481da177e4SLinus Torvalds 	case WRITE_10:
749dbb6b350SFinn Thain 		shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n");
7501da177e4SLinus Torvalds 		cmd->result = (DID_ERROR << 16);
7511bb40589SFinn Thain 		cmd->scsi_done(cmd);
7521da177e4SLinus Torvalds 		return 0;
7531da177e4SLinus Torvalds 	}
7541da177e4SLinus Torvalds #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
7551da177e4SLinus Torvalds 
7561da177e4SLinus Torvalds 	cmd->result = 0;
7571da177e4SLinus Torvalds 
75811d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
7591bb40589SFinn Thain 
7601da177e4SLinus Torvalds 	/*
7611da177e4SLinus Torvalds 	 * Insert the cmd into the issue queue. Note that REQUEST SENSE
7621da177e4SLinus Torvalds 	 * commands are added to the head of the queue since any command will
7631da177e4SLinus Torvalds 	 * clear the contingent allegiance condition that exists and the
7641da177e4SLinus Torvalds 	 * sense data is only guaranteed to be valid while the condition exists.
7651da177e4SLinus Torvalds 	 */
7661da177e4SLinus Torvalds 
767*32b26a10SFinn Thain 	if (cmd->cmnd[0] == REQUEST_SENSE)
768*32b26a10SFinn Thain 		list_add(&ncmd->list, &hostdata->unissued);
769*32b26a10SFinn Thain 	else
770*32b26a10SFinn Thain 		list_add_tail(&ncmd->list, &hostdata->unissued);
771*32b26a10SFinn Thain 
77211d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
7731bb40589SFinn Thain 
774dbb6b350SFinn Thain 	dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n",
775dbb6b350SFinn Thain 	         cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds 	/* Kick off command processing */
7788d8601a7SFinn Thain 	queue_work(hostdata->work_q, &hostdata->main_task);
7791da177e4SLinus Torvalds 	return 0;
7801da177e4SLinus Torvalds }
7811da177e4SLinus Torvalds 
7821da177e4SLinus Torvalds /**
7831da177e4SLinus Torvalds  *	NCR5380_main	-	NCR state machines
7841da177e4SLinus Torvalds  *
7851da177e4SLinus Torvalds  *	NCR5380_main is a coroutine that runs as long as more work can
7861da177e4SLinus Torvalds  *      be done on the NCR5380 host adapters in a system.  Both
7871da177e4SLinus Torvalds  *      NCR5380_queue_command() and NCR5380_intr() will try to start it
7881da177e4SLinus Torvalds  *      in case it is not running.
7891da177e4SLinus Torvalds  *
7901da177e4SLinus Torvalds  *	Locks: called as its own thread with no locks held. Takes the
7911da177e4SLinus Torvalds  *	host lock and called routines may take the isa dma lock.
7921da177e4SLinus Torvalds  */
7931da177e4SLinus Torvalds 
794c4028958SDavid Howells static void NCR5380_main(struct work_struct *work)
7951da177e4SLinus Torvalds {
796c4028958SDavid Howells 	struct NCR5380_hostdata *hostdata =
7978d8601a7SFinn Thain 		container_of(work, struct NCR5380_hostdata, main_task);
7981da177e4SLinus Torvalds 	struct Scsi_Host *instance = hostdata->host;
799*32b26a10SFinn Thain 	struct NCR5380_cmd *ncmd, *n;
8001da177e4SLinus Torvalds 	int done;
8011da177e4SLinus Torvalds 
80211d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
8031da177e4SLinus Torvalds 	do {
8041da177e4SLinus Torvalds 		done = 1;
80511d2f63bSFinn Thain 
806ae753a33SFinn Thain 		if (!hostdata->connected) {
80752a6a1cbSFinn Thain 			dprintk(NDEBUG_MAIN, "scsi%d : not connected\n", instance->host_no);
8081da177e4SLinus Torvalds 			/*
8091da177e4SLinus Torvalds 			 * Search through the issue_queue for a command destined
8101da177e4SLinus Torvalds 			 * for a target that's not busy.
8111da177e4SLinus Torvalds 			 */
812*32b26a10SFinn Thain 			list_for_each_entry_safe(ncmd, n, &hostdata->unissued,
813*32b26a10SFinn Thain 			                         list) {
814*32b26a10SFinn Thain 				struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd);
815*32b26a10SFinn Thain 
8160d3d9a42SFinn Thain 				dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%llu\n",
8170d3d9a42SFinn Thain 				         tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)],
8180d3d9a42SFinn Thain 				         tmp->device->lun);
8191da177e4SLinus Torvalds 				/*  When we find one, remove it from the issue queue. */
8209cb78c16SHannes Reinecke 				if (!(hostdata->busy[tmp->device->id] &
8219cb78c16SHannes Reinecke 				      (1 << (u8)(tmp->device->lun & 0xff)))) {
822*32b26a10SFinn Thain 					list_del(&ncmd->list);
8230d3d9a42SFinn Thain 					dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES,
824*32b26a10SFinn Thain 					         instance, "main: removed %p from issue queue\n",
825*32b26a10SFinn Thain 					         tmp);
8261da177e4SLinus Torvalds 
8271da177e4SLinus Torvalds 					/*
8281da177e4SLinus Torvalds 					 * Attempt to establish an I_T_L nexus here.
8291da177e4SLinus Torvalds 					 * On success, instance->hostdata->connected is set.
8301da177e4SLinus Torvalds 					 * On failure, we must add the command back to the
8311da177e4SLinus Torvalds 					 *   issue queue so we can keep trying.
8321da177e4SLinus Torvalds 					 */
8331da177e4SLinus Torvalds 					/*
8341da177e4SLinus Torvalds 					 * REQUEST SENSE commands are issued without tagged
8351da177e4SLinus Torvalds 					 * queueing, even on SCSI-II devices because the
8361da177e4SLinus Torvalds 					 * contingent allegiance condition exists for the
8371da177e4SLinus Torvalds 					 * entire unit.
8381da177e4SLinus Torvalds 					 */
83976f13b93SFinn Thain 
84076f13b93SFinn Thain 					if (!NCR5380_select(instance, tmp)) {
8411f1b0c74SFinn Thain 						/* OK or bad target */
8421da177e4SLinus Torvalds 					} else {
8431f1b0c74SFinn Thain 						/* Need to retry */
844*32b26a10SFinn Thain 						list_add(&ncmd->list, &hostdata->unissued);
8450d3d9a42SFinn Thain 						dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES,
8460d3d9a42SFinn Thain 						         instance, "main: select() failed, %p returned to issue queue\n",
8470d3d9a42SFinn Thain 						         tmp);
8481da177e4SLinus Torvalds 						done = 0;
8491da177e4SLinus Torvalds 					}
850ae753a33SFinn Thain 					if (hostdata->connected)
8511f1b0c74SFinn Thain 						break;
8521da177e4SLinus Torvalds 				}	/* if target/lun is not busy */
8531da177e4SLinus Torvalds 			}	/* for */
8541da177e4SLinus Torvalds 		}	/* if (!hostdata->connected) */
85511d2f63bSFinn Thain 
8561da177e4SLinus Torvalds 		if (hostdata->connected
8571da177e4SLinus Torvalds #ifdef REAL_DMA
8581da177e4SLinus Torvalds 		    && !hostdata->dmalen
8591da177e4SLinus Torvalds #endif
8601da177e4SLinus Torvalds 		    ) {
86152a6a1cbSFinn Thain 			dprintk(NDEBUG_MAIN, "scsi%d : main() : performing information transfer\n", instance->host_no);
8621da177e4SLinus Torvalds 			NCR5380_information_transfer(instance);
86352a6a1cbSFinn Thain 			dprintk(NDEBUG_MAIN, "scsi%d : main() : done set false\n", instance->host_no);
8641da177e4SLinus Torvalds 			done = 0;
8651d3db59dSFinn Thain 		}
8661da177e4SLinus Torvalds 	} while (!done);
86711d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
8681da177e4SLinus Torvalds }
8691da177e4SLinus Torvalds 
8701da177e4SLinus Torvalds #ifndef DONT_USE_INTR
8711da177e4SLinus Torvalds 
8721da177e4SLinus Torvalds /**
8731da177e4SLinus Torvalds  * NCR5380_intr - generic NCR5380 irq handler
8741da177e4SLinus Torvalds  * @irq: interrupt number
8751da177e4SLinus Torvalds  * @dev_id: device info
8761da177e4SLinus Torvalds  *
8771da177e4SLinus Torvalds  * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
8781da177e4SLinus Torvalds  * from the disconnected queue, and restarting NCR5380_main()
8791da177e4SLinus Torvalds  * as required.
8801da177e4SLinus Torvalds  *
881cd400825SFinn Thain  * The chip can assert IRQ in any of six different conditions. The IRQ flag
882cd400825SFinn Thain  * is then cleared by reading the Reset Parity/Interrupt Register (RPIR).
883cd400825SFinn Thain  * Three of these six conditions are latched in the Bus and Status Register:
884cd400825SFinn Thain  * - End of DMA (cleared by ending DMA Mode)
885cd400825SFinn Thain  * - Parity error (cleared by reading RPIR)
886cd400825SFinn Thain  * - Loss of BSY (cleared by reading RPIR)
887cd400825SFinn Thain  * Two conditions have flag bits that are not latched:
888cd400825SFinn Thain  * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode)
889cd400825SFinn Thain  * - Bus reset (non-maskable)
890cd400825SFinn Thain  * The remaining condition has no flag bit at all:
891cd400825SFinn Thain  * - Selection/reselection
892cd400825SFinn Thain  *
893cd400825SFinn Thain  * Hence, establishing the cause(s) of any interrupt is partly guesswork.
894cd400825SFinn Thain  * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor
895cd400825SFinn Thain  * claimed that "the design of the [DP8490] interrupt logic ensures
896cd400825SFinn Thain  * interrupts will not be lost (they can be on the DP5380)."
897cd400825SFinn Thain  * The L5380/53C80 datasheet from LOGIC Devices has more details.
898cd400825SFinn Thain  *
899cd400825SFinn Thain  * Checking for bus reset by reading RST is futile because of interrupt
900cd400825SFinn Thain  * latency, but a bus reset will reset chip logic. Checking for parity error
901cd400825SFinn Thain  * is unnecessary because that interrupt is never enabled. A Loss of BSY
902cd400825SFinn Thain  * condition will clear DMA Mode. We can tell when this occurs because the
903cd400825SFinn Thain  * the Busy Monitor interrupt is enabled together with DMA Mode.
9041da177e4SLinus Torvalds  */
9051da177e4SLinus Torvalds 
906cd400825SFinn Thain static irqreturn_t NCR5380_intr(int irq, void *dev_id)
9071da177e4SLinus Torvalds {
908baa9aac6SJeff Garzik 	struct Scsi_Host *instance = dev_id;
909cd400825SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
910cd400825SFinn Thain 	int handled = 0;
9111da177e4SLinus Torvalds 	unsigned char basr;
9121da177e4SLinus Torvalds 	unsigned long flags;
9131da177e4SLinus Torvalds 
91411d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
915cd400825SFinn Thain 
9161da177e4SLinus Torvalds 	basr = NCR5380_read(BUS_AND_STATUS_REG);
9171da177e4SLinus Torvalds 	if (basr & BASR_IRQ) {
918cd400825SFinn Thain 		unsigned char mr = NCR5380_read(MODE_REG);
919cd400825SFinn Thain 		unsigned char sr = NCR5380_read(STATUS_REG);
920cd400825SFinn Thain 
921cd400825SFinn Thain 		dprintk(NDEBUG_INTR, "scsi%d: IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n",
922cd400825SFinn Thain 		        instance->host_no, irq, basr, sr, mr);
923cd400825SFinn Thain 
9241da177e4SLinus Torvalds #if defined(REAL_DMA)
925cd400825SFinn Thain 		if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) {
926cd400825SFinn Thain 			/* Probably End of DMA, Phase Mismatch or Loss of BSY.
927cd400825SFinn Thain 			 * We ack IRQ after clearing Mode Register. Workarounds
928cd400825SFinn Thain 			 * for End of DMA errata need to happen in DMA Mode.
9291da177e4SLinus Torvalds 			 */
9301da177e4SLinus Torvalds 
931cd400825SFinn Thain 			dprintk(NDEBUG_INTR, "scsi%d: interrupt in DMA mode\n", intance->host_no);
932cd400825SFinn Thain 
93325985edcSLucas De Marchi 			int transferred;
9341da177e4SLinus Torvalds 
9351da177e4SLinus Torvalds 			if (!hostdata->connected)
936cd400825SFinn Thain 				panic("scsi%d : DMA interrupt with no connected cmd\n",
937cd400825SFinn Thain 				      instance->hostno);
9381da177e4SLinus Torvalds 
939cd400825SFinn Thain 			transferred = hostdata->dmalen - NCR5380_dma_residual(instance);
9401da177e4SLinus Torvalds 			hostdata->connected->SCp.this_residual -= transferred;
9411da177e4SLinus Torvalds 			hostdata->connected->SCp.ptr += transferred;
9421da177e4SLinus Torvalds 			hostdata->dmalen = 0;
9431da177e4SLinus Torvalds 
9441da177e4SLinus Torvalds 			/* FIXME: we need to poll briefly then defer a workqueue task ! */
9451da177e4SLinus Torvalds 			NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2 * HZ);
9461da177e4SLinus Torvalds 
9471da177e4SLinus Torvalds 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
948cd400825SFinn Thain 			NCR5380_write(MODE_REG, MR_BASE);
949cd400825SFinn Thain 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
950cd400825SFinn Thain 		} else
951cd400825SFinn Thain #endif /* REAL_DMA */
952cd400825SFinn Thain 		if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) &&
953cd400825SFinn Thain 		    (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) {
954cd400825SFinn Thain 			/* Probably reselected */
955cd400825SFinn Thain 			NCR5380_write(SELECT_ENABLE_REG, 0);
956cd400825SFinn Thain 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
957cd400825SFinn Thain 
958cd400825SFinn Thain 			dprintk(NDEBUG_INTR, "scsi%d: interrupt with SEL and IO\n",
959cd400825SFinn Thain 			        instance->host_no);
960cd400825SFinn Thain 
961cd400825SFinn Thain 			if (!hostdata->connected) {
962cd400825SFinn Thain 				NCR5380_reselect(instance);
9638d8601a7SFinn Thain 				queue_work(hostdata->work_q, &hostdata->main_task);
964cd400825SFinn Thain 			}
965cd400825SFinn Thain 			if (!hostdata->connected)
966cd400825SFinn Thain 				NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
967cd400825SFinn Thain 		} else {
968cd400825SFinn Thain 			/* Probably Bus Reset */
969cd400825SFinn Thain 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
970cd400825SFinn Thain 
971cd400825SFinn Thain 			dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt\n", instance->host_no);
972cd400825SFinn Thain 		}
973cd400825SFinn Thain 		handled = 1;
974cd400825SFinn Thain 	} else {
975cd400825SFinn Thain 		shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n");
976cd400825SFinn Thain 	}
977cd400825SFinn Thain 
97811d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
979cd400825SFinn Thain 
980cd400825SFinn Thain 	return IRQ_RETVAL(handled);
9811da177e4SLinus Torvalds }
9821da177e4SLinus Torvalds 
9831da177e4SLinus Torvalds #endif
9841da177e4SLinus Torvalds 
9851da177e4SLinus Torvalds /*
986710ddd0dSFinn Thain  * Function : int NCR5380_select(struct Scsi_Host *instance,
987710ddd0dSFinn Thain  *                               struct scsi_cmnd *cmd)
9881da177e4SLinus Torvalds  *
9891da177e4SLinus Torvalds  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
9901da177e4SLinus Torvalds  *      including ARBITRATION, SELECTION, and initial message out for
9911da177e4SLinus Torvalds  *      IDENTIFY and queue messages.
9921da177e4SLinus Torvalds  *
9931da177e4SLinus Torvalds  * Inputs : instance - instantiation of the 5380 driver on which this
99476f13b93SFinn Thain  *      target lives, cmd - SCSI command to execute.
9951da177e4SLinus Torvalds  *
9966323876fSFinn Thain  * Returns : -1 if selection failed but should be retried.
9976323876fSFinn Thain  *      0 if selection failed and should not be retried.
9986323876fSFinn Thain  *      0 if selection succeeded completely (hostdata->connected == cmd).
9991da177e4SLinus Torvalds  *
10001da177e4SLinus Torvalds  * Side effects :
10011da177e4SLinus Torvalds  *      If bus busy, arbitration failed, etc, NCR5380_select() will exit
10021da177e4SLinus Torvalds  *              with registers as they should have been on entry - ie
10031da177e4SLinus Torvalds  *              SELECT_ENABLE will be set appropriately, the NCR5380
10041da177e4SLinus Torvalds  *              will cease to drive any SCSI bus signals.
10051da177e4SLinus Torvalds  *
10061da177e4SLinus Torvalds  *      If successful : I_T_L or I_T_L_Q nexus will be established,
10071da177e4SLinus Torvalds  *              instance->connected will be set to cmd.
10081da177e4SLinus Torvalds  *              SELECT interrupt will be disabled.
10091da177e4SLinus Torvalds  *
10101da177e4SLinus Torvalds  *      If failed (no target) : cmd->scsi_done() will be called, and the
10111da177e4SLinus Torvalds  *              cmd->result host byte set to DID_BAD_TARGET.
10121da177e4SLinus Torvalds  *
10131da177e4SLinus Torvalds  *	Locks: caller holds hostdata lock in IRQ mode
10141da177e4SLinus Torvalds  */
10151da177e4SLinus Torvalds 
1016710ddd0dSFinn Thain static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
10171da177e4SLinus Torvalds {
1018e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
10191da177e4SLinus Torvalds 	unsigned char tmp[3], phase;
10201da177e4SLinus Torvalds 	unsigned char *data;
10211da177e4SLinus Torvalds 	int len;
10221da177e4SLinus Torvalds 	int err;
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 	NCR5380_dprint(NDEBUG_ARBITRATION, instance);
102552a6a1cbSFinn Thain 	dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id);
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds 	/*
10281da177e4SLinus Torvalds 	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the
10291da177e4SLinus Torvalds 	 * data bus during SELECTION.
10301da177e4SLinus Torvalds 	 */
10311da177e4SLinus Torvalds 
10321da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, 0);
10331da177e4SLinus Torvalds 
10341da177e4SLinus Torvalds 	/*
10351da177e4SLinus Torvalds 	 * Start arbitration.
10361da177e4SLinus Torvalds 	 */
10371da177e4SLinus Torvalds 
10381da177e4SLinus Torvalds 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
10391da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_ARBITRATE);
10401da177e4SLinus Torvalds 
104155500d9bSFinn Thain 	/* The chip now waits for BUS FREE phase. Then after the 800 ns
104255500d9bSFinn Thain 	 * Bus Free Delay, arbitration will begin.
10431da177e4SLinus Torvalds 	 */
10441da177e4SLinus Torvalds 
104511d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
1046b32ade12SFinn Thain 	err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
1047b32ade12SFinn Thain 	                INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
1048b32ade12SFinn Thain 	                                       ICR_ARBITRATION_PROGRESS, HZ);
104911d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
105055500d9bSFinn Thain 	if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
105155500d9bSFinn Thain 		/* Reselection interrupt */
105255500d9bSFinn Thain 		return -1;
105355500d9bSFinn Thain 	}
1054b32ade12SFinn Thain 	if (err < 0) {
1055b32ade12SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE);
1056b32ade12SFinn Thain 		shost_printk(KERN_ERR, instance,
1057b32ade12SFinn Thain 		             "select: arbitration timeout\n");
1058b32ade12SFinn Thain 		return -1;
105955500d9bSFinn Thain 	}
106011d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
106155500d9bSFinn Thain 
106255500d9bSFinn Thain 	/* The SCSI-2 arbitration delay is 2.4 us */
10631da177e4SLinus Torvalds 	udelay(3);
10641da177e4SLinus Torvalds 
10651da177e4SLinus Torvalds 	/* Check for lost arbitration */
10661da177e4SLinus 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)) {
10671da177e4SLinus Torvalds 		NCR5380_write(MODE_REG, MR_BASE);
106852a6a1cbSFinn Thain 		dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no);
106911d2f63bSFinn Thain 		spin_lock_irq(&hostdata->lock);
10706323876fSFinn Thain 		return -1;
10711da177e4SLinus Torvalds 	}
1072cf13b083SFinn Thain 
1073cf13b083SFinn Thain 	/* After/during arbitration, BSY should be asserted.
1074cf13b083SFinn Thain 	 * IBM DPES-31080 Version S31Q works now
1075cf13b083SFinn Thain 	 * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman)
1076cf13b083SFinn Thain 	 */
1077cf13b083SFinn Thain 	NCR5380_write(INITIATOR_COMMAND_REG,
1078cf13b083SFinn Thain 		      ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
10791da177e4SLinus Torvalds 
10801da177e4SLinus Torvalds 	/*
10811da177e4SLinus Torvalds 	 * Again, bus clear + bus settle time is 1.2us, however, this is
10821da177e4SLinus Torvalds 	 * a minimum so we'll udelay ceil(1.2)
10831da177e4SLinus Torvalds 	 */
10841da177e4SLinus Torvalds 
10859c3f0e2bSFinn Thain 	if (hostdata->flags & FLAG_TOSHIBA_DELAY)
10869c3f0e2bSFinn Thain 		udelay(15);
10879c3f0e2bSFinn Thain 	else
10881da177e4SLinus Torvalds 		udelay(2);
10891da177e4SLinus Torvalds 
109011d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
109111d2f63bSFinn Thain 
109272064a78SFinn Thain 	/* NCR5380_reselect() clears MODE_REG after a reselection interrupt */
109372064a78SFinn Thain 	if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE))
109472064a78SFinn Thain 		return -1;
109572064a78SFinn Thain 
109652a6a1cbSFinn Thain 	dprintk(NDEBUG_ARBITRATION, "scsi%d : won arbitration\n", instance->host_no);
10971da177e4SLinus Torvalds 
10981da177e4SLinus Torvalds 	/*
10991da177e4SLinus Torvalds 	 * Now that we have won arbitration, start Selection process, asserting
11001da177e4SLinus Torvalds 	 * the host and target ID's on the SCSI bus.
11011da177e4SLinus Torvalds 	 */
11021da177e4SLinus Torvalds 
1103422c0d61SJeff Garzik 	NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << scmd_id(cmd))));
11041da177e4SLinus Torvalds 
11051da177e4SLinus Torvalds 	/*
11061da177e4SLinus Torvalds 	 * Raise ATN while SEL is true before BSY goes false from arbitration,
11071da177e4SLinus Torvalds 	 * since this is the only way to guarantee that we'll get a MESSAGE OUT
11081da177e4SLinus Torvalds 	 * phase immediately after selection.
11091da177e4SLinus Torvalds 	 */
11101da177e4SLinus Torvalds 
11111da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
11121da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
11131da177e4SLinus Torvalds 
11141da177e4SLinus Torvalds 	/*
11151da177e4SLinus Torvalds 	 * Reselect interrupts must be turned off prior to the dropping of BSY,
11161da177e4SLinus Torvalds 	 * otherwise we will trigger an interrupt.
11171da177e4SLinus Torvalds 	 */
11181da177e4SLinus Torvalds 	NCR5380_write(SELECT_ENABLE_REG, 0);
11191da177e4SLinus Torvalds 
112011d2f63bSFinn Thain 	spin_unlock_irq(&hostdata->lock);
112111d2f63bSFinn Thain 
11221da177e4SLinus Torvalds 	/*
11231da177e4SLinus Torvalds 	 * The initiator shall then wait at least two deskew delays and release
11241da177e4SLinus Torvalds 	 * the BSY signal.
11251da177e4SLinus Torvalds 	 */
11261da177e4SLinus Torvalds 	udelay(1);		/* wingel -- wait two bus deskew delay >2*45ns */
11271da177e4SLinus Torvalds 
11281da177e4SLinus Torvalds 	/* Reset BSY */
11291da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
11301da177e4SLinus Torvalds 
11311da177e4SLinus Torvalds 	/*
11321da177e4SLinus Torvalds 	 * Something weird happens when we cease to drive BSY - looks
11331da177e4SLinus Torvalds 	 * like the board/chip is letting us do another read before the
11341da177e4SLinus Torvalds 	 * appropriate propagation delay has expired, and we're confusing
11351da177e4SLinus Torvalds 	 * a BSY signal from ourselves as the target's response to SELECTION.
11361da177e4SLinus Torvalds 	 *
11371da177e4SLinus Torvalds 	 * A small delay (the 'C++' frontend breaks the pipeline with an
11381da177e4SLinus Torvalds 	 * unnecessary jump, making it work on my 386-33/Trantor T128, the
11391da177e4SLinus Torvalds 	 * tighter 'C' code breaks and requires this) solves the problem -
11401da177e4SLinus Torvalds 	 * the 1 us delay is arbitrary, and only used because this delay will
11411da177e4SLinus Torvalds 	 * be the same on other platforms and since it works here, it should
11421da177e4SLinus Torvalds 	 * work there.
11431da177e4SLinus Torvalds 	 *
11441da177e4SLinus Torvalds 	 * wingel suggests that this could be due to failing to wait
11451da177e4SLinus Torvalds 	 * one deskew delay.
11461da177e4SLinus Torvalds 	 */
11471da177e4SLinus Torvalds 
11481da177e4SLinus Torvalds 	udelay(1);
11491da177e4SLinus Torvalds 
115052a6a1cbSFinn Thain 	dprintk(NDEBUG_SELECTION, "scsi%d : selecting target %d\n", instance->host_no, scmd_id(cmd));
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds 	/*
11531da177e4SLinus Torvalds 	 * The SCSI specification calls for a 250 ms timeout for the actual
11541da177e4SLinus Torvalds 	 * selection.
11551da177e4SLinus Torvalds 	 */
11561da177e4SLinus Torvalds 
1157ae753a33SFinn Thain 	err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY,
1158ae753a33SFinn Thain 	                            msecs_to_jiffies(250));
11591da177e4SLinus Torvalds 
11601da177e4SLinus Torvalds 	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
116111d2f63bSFinn Thain 		spin_lock_irq(&hostdata->lock);
11621da177e4SLinus Torvalds 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
11631da177e4SLinus Torvalds 		NCR5380_reselect(instance);
1164cd400825SFinn Thain 		if (!hostdata->connected)
11651da177e4SLinus Torvalds 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1166cd400825SFinn Thain 		printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
11671da177e4SLinus Torvalds 		return -1;
11681da177e4SLinus Torvalds 	}
1169ae753a33SFinn Thain 
1170ae753a33SFinn Thain 	if (err < 0) {
117111d2f63bSFinn Thain 		spin_lock_irq(&hostdata->lock);
1172ae753a33SFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1173ae753a33SFinn Thain 		cmd->result = DID_BAD_TARGET << 16;
1174ae753a33SFinn Thain 		cmd->scsi_done(cmd);
1175ae753a33SFinn Thain 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1176ae753a33SFinn Thain 		dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n",
1177ae753a33SFinn Thain 		        instance->host_no);
1178ae753a33SFinn Thain 		return 0;
1179ae753a33SFinn Thain 	}
1180ae753a33SFinn Thain 
11811da177e4SLinus Torvalds 	/*
11821da177e4SLinus Torvalds 	 * No less than two deskew delays after the initiator detects the
11831da177e4SLinus Torvalds 	 * BSY signal is true, it shall release the SEL signal and may
11841da177e4SLinus Torvalds 	 * change the DATA BUS.                                     -wingel
11851da177e4SLinus Torvalds 	 */
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	udelay(1);
11881da177e4SLinus Torvalds 
11891da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds 	/*
11921da177e4SLinus Torvalds 	 * Since we followed the SCSI spec, and raised ATN while SEL
11931da177e4SLinus Torvalds 	 * was true but before BSY was false during selection, the information
11941da177e4SLinus Torvalds 	 * transfer phase should be a MESSAGE OUT phase so that we can send the
11951da177e4SLinus Torvalds 	 * IDENTIFY message.
11961da177e4SLinus Torvalds 	 *
11971da177e4SLinus Torvalds 	 * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
11981da177e4SLinus Torvalds 	 * message (2 bytes) with a tag ID that we increment with every command
11991da177e4SLinus Torvalds 	 * until it wraps back to 0.
12001da177e4SLinus Torvalds 	 *
12011da177e4SLinus Torvalds 	 * XXX - it turns out that there are some broken SCSI-II devices,
12021da177e4SLinus Torvalds 	 *       which claim to support tagged queuing but fail when more than
12031da177e4SLinus Torvalds 	 *       some number of commands are issued at once.
12041da177e4SLinus Torvalds 	 */
12051da177e4SLinus Torvalds 
12061da177e4SLinus Torvalds 	/* Wait for start of REQ/ACK handshake */
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds 	err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
120911d2f63bSFinn Thain 	spin_lock_irq(&hostdata->lock);
12101cc160e1SFinn Thain 	if (err < 0) {
121155500d9bSFinn Thain 		shost_printk(KERN_ERR, instance, "select: REQ timeout\n");
121255500d9bSFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
12131da177e4SLinus Torvalds 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
12146323876fSFinn Thain 		return -1;
12151da177e4SLinus Torvalds 	}
12161da177e4SLinus Torvalds 
121752a6a1cbSFinn Thain 	dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id);
121822f5f10dSFinn Thain 	tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
12191da177e4SLinus Torvalds 
12201da177e4SLinus Torvalds 	len = 1;
12211da177e4SLinus Torvalds 	cmd->tag = 0;
12221da177e4SLinus Torvalds 
12231da177e4SLinus Torvalds 	/* Send message(s) */
12241da177e4SLinus Torvalds 	data = tmp;
12251da177e4SLinus Torvalds 	phase = PHASE_MSGOUT;
12261da177e4SLinus Torvalds 	NCR5380_transfer_pio(instance, &phase, &len, &data);
122752a6a1cbSFinn Thain 	dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no);
12281da177e4SLinus Torvalds 	/* XXX need to handle errors here */
122911d2f63bSFinn Thain 
12301da177e4SLinus Torvalds 	hostdata->connected = cmd;
12319cb78c16SHannes Reinecke 	hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
12321da177e4SLinus Torvalds 
12331da177e4SLinus Torvalds 	initialize_SCp(cmd);
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds 	return 0;
12361da177e4SLinus Torvalds }
12371da177e4SLinus Torvalds 
12381da177e4SLinus Torvalds /*
12391da177e4SLinus Torvalds  * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
12401da177e4SLinus Torvalds  *      unsigned char *phase, int *count, unsigned char **data)
12411da177e4SLinus Torvalds  *
12421da177e4SLinus Torvalds  * Purpose : transfers data in given phase using polled I/O
12431da177e4SLinus Torvalds  *
12441da177e4SLinus Torvalds  * Inputs : instance - instance of driver, *phase - pointer to
12451da177e4SLinus Torvalds  *      what phase is expected, *count - pointer to number of
12461da177e4SLinus Torvalds  *      bytes to transfer, **data - pointer to data pointer.
12471da177e4SLinus Torvalds  *
12481da177e4SLinus Torvalds  * Returns : -1 when different phase is entered without transferring
124925985edcSLucas De Marchi  *      maximum number of bytes, 0 if all bytes or transferred or exit
12501da177e4SLinus Torvalds  *      is in same phase.
12511da177e4SLinus Torvalds  *
12521da177e4SLinus Torvalds  *      Also, *phase, *count, *data are modified in place.
12531da177e4SLinus Torvalds  *
12541da177e4SLinus Torvalds  * XXX Note : handling for bus free may be useful.
12551da177e4SLinus Torvalds  */
12561da177e4SLinus Torvalds 
12571da177e4SLinus Torvalds /*
12581da177e4SLinus Torvalds  * Note : this code is not as quick as it could be, however it
12591da177e4SLinus Torvalds  * IS 100% reliable, and for the actual data transfer where speed
12601da177e4SLinus Torvalds  * counts, we will always do a pseudo DMA or DMA transfer.
12611da177e4SLinus Torvalds  */
12621da177e4SLinus Torvalds 
12631da177e4SLinus Torvalds static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
12641da177e4SLinus Torvalds 	unsigned char p = *phase, tmp;
12651da177e4SLinus Torvalds 	int c = *count;
12661da177e4SLinus Torvalds 	unsigned char *d = *data;
12671da177e4SLinus Torvalds 
12681da177e4SLinus Torvalds 	if (!(p & SR_IO))
126952a6a1cbSFinn Thain 		dprintk(NDEBUG_PIO, "scsi%d : pio write %d bytes\n", instance->host_no, c);
12701da177e4SLinus Torvalds 	else
127152a6a1cbSFinn Thain 		dprintk(NDEBUG_PIO, "scsi%d : pio read %d bytes\n", instance->host_no, c);
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 	/*
12741da177e4SLinus Torvalds 	 * The NCR5380 chip will only drive the SCSI bus when the
12751da177e4SLinus Torvalds 	 * phase specified in the appropriate bits of the TARGET COMMAND
12761da177e4SLinus Torvalds 	 * REGISTER match the STATUS REGISTER
12771da177e4SLinus Torvalds 	 */
12781da177e4SLinus Torvalds 
12791da177e4SLinus Torvalds 	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
12801da177e4SLinus Torvalds 
12811da177e4SLinus Torvalds 	do {
12821da177e4SLinus Torvalds 		/*
12831da177e4SLinus Torvalds 		 * Wait for assertion of REQ, after which the phase bits will be
12841da177e4SLinus Torvalds 		 * valid
12851da177e4SLinus Torvalds 		 */
12861da177e4SLinus Torvalds 
1287686f3990SFinn Thain 		if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0)
12881da177e4SLinus Torvalds 			break;
12891da177e4SLinus Torvalds 
129052a6a1cbSFinn Thain 		dprintk(NDEBUG_HANDSHAKE, "scsi%d : REQ detected\n", instance->host_no);
12911da177e4SLinus Torvalds 
12921da177e4SLinus Torvalds 		/* Check for phase mismatch */
1293686f3990SFinn Thain 		if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) {
129452a6a1cbSFinn Thain 			dprintk(NDEBUG_HANDSHAKE, "scsi%d : phase mismatch\n", instance->host_no);
12951da177e4SLinus Torvalds 			NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance);
12961da177e4SLinus Torvalds 			break;
12971da177e4SLinus Torvalds 		}
12981da177e4SLinus Torvalds 		/* Do actual transfer from SCSI bus to / from memory */
12991da177e4SLinus Torvalds 		if (!(p & SR_IO))
13001da177e4SLinus Torvalds 			NCR5380_write(OUTPUT_DATA_REG, *d);
13011da177e4SLinus Torvalds 		else
13021da177e4SLinus Torvalds 			*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
13031da177e4SLinus Torvalds 
13041da177e4SLinus Torvalds 		++d;
13051da177e4SLinus Torvalds 
13061da177e4SLinus Torvalds 		/*
13071da177e4SLinus Torvalds 		 * The SCSI standard suggests that in MSGOUT phase, the initiator
13081da177e4SLinus Torvalds 		 * should drop ATN on the last byte of the message phase
13091da177e4SLinus Torvalds 		 * after REQ has been asserted for the handshake but before
13101da177e4SLinus Torvalds 		 * the initiator raises ACK.
13111da177e4SLinus Torvalds 		 */
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds 		if (!(p & SR_IO)) {
13141da177e4SLinus Torvalds 			if (!((p & SR_MSG) && c > 1)) {
13151da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
13161da177e4SLinus Torvalds 				NCR5380_dprint(NDEBUG_PIO, instance);
13171da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);
13181da177e4SLinus Torvalds 			} else {
13191da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);
13201da177e4SLinus Torvalds 				NCR5380_dprint(NDEBUG_PIO, instance);
13211da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
13221da177e4SLinus Torvalds 			}
13231da177e4SLinus Torvalds 		} else {
13241da177e4SLinus Torvalds 			NCR5380_dprint(NDEBUG_PIO, instance);
13251da177e4SLinus Torvalds 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
13261da177e4SLinus Torvalds 		}
13271da177e4SLinus Torvalds 
1328a2edc4a6SFinn Thain 		if (NCR5380_poll_politely(instance,
1329a2edc4a6SFinn Thain 		                          STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
1330a2edc4a6SFinn Thain 			break;
1331a2edc4a6SFinn Thain 
133252a6a1cbSFinn Thain 		dprintk(NDEBUG_HANDSHAKE, "scsi%d : req false, handshake complete\n", instance->host_no);
13331da177e4SLinus Torvalds 
13341da177e4SLinus Torvalds /*
13351da177e4SLinus Torvalds  * We have several special cases to consider during REQ/ACK handshaking :
13361da177e4SLinus Torvalds  * 1.  We were in MSGOUT phase, and we are on the last byte of the
13371da177e4SLinus Torvalds  *      message.  ATN must be dropped as ACK is dropped.
13381da177e4SLinus Torvalds  *
13391da177e4SLinus Torvalds  * 2.  We are in a MSGIN phase, and we are on the last byte of the
13401da177e4SLinus Torvalds  *      message.  We must exit with ACK asserted, so that the calling
13411da177e4SLinus Torvalds  *      code may raise ATN before dropping ACK to reject the message.
13421da177e4SLinus Torvalds  *
13431da177e4SLinus Torvalds  * 3.  ACK and ATN are clear and the target may proceed as normal.
13441da177e4SLinus Torvalds  */
13451da177e4SLinus Torvalds 		if (!(p == PHASE_MSGIN && c == 1)) {
13461da177e4SLinus Torvalds 			if (p == PHASE_MSGOUT && c > 1)
13471da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
13481da177e4SLinus Torvalds 			else
13491da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
13501da177e4SLinus Torvalds 		}
13511da177e4SLinus Torvalds 	} while (--c);
13521da177e4SLinus Torvalds 
135352a6a1cbSFinn Thain 	dprintk(NDEBUG_PIO, "scsi%d : residual %d\n", instance->host_no, c);
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds 	*count = c;
13561da177e4SLinus Torvalds 	*data = d;
13571da177e4SLinus Torvalds 	tmp = NCR5380_read(STATUS_REG);
1358a2edc4a6SFinn Thain 	/* The phase read from the bus is valid if either REQ is (already)
1359a2edc4a6SFinn Thain 	 * asserted or if ACK hasn't been released yet. The latter applies if
1360a2edc4a6SFinn Thain 	 * we're in MSG IN, DATA IN or STATUS and all bytes have been received.
1361a2edc4a6SFinn Thain 	 */
1362a2edc4a6SFinn Thain 	if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0))
13631da177e4SLinus Torvalds 		*phase = tmp & PHASE_MASK;
13641da177e4SLinus Torvalds 	else
13651da177e4SLinus Torvalds 		*phase = PHASE_UNKNOWN;
13661da177e4SLinus Torvalds 
13671da177e4SLinus Torvalds 	if (!c || (*phase == p))
13681da177e4SLinus Torvalds 		return 0;
13691da177e4SLinus Torvalds 	else
13701da177e4SLinus Torvalds 		return -1;
13711da177e4SLinus Torvalds }
13721da177e4SLinus Torvalds 
13731da177e4SLinus Torvalds /**
13741da177e4SLinus Torvalds  * do_reset - issue a reset command
1375636b1ec8SFinn Thain  * @instance: adapter to reset
13761da177e4SLinus Torvalds  *
13771da177e4SLinus Torvalds  * Issue a reset sequence to the NCR5380 and try and get the bus
13781da177e4SLinus Torvalds  * back into sane shape.
13791da177e4SLinus Torvalds  *
1380636b1ec8SFinn Thain  * This clears the reset interrupt flag because there may be no handler for
1381636b1ec8SFinn Thain  * it. When the driver is initialized, the NCR5380_intr() handler has not yet
1382636b1ec8SFinn Thain  * been installed. And when in EH we may have released the ST DMA interrupt.
13831da177e4SLinus Torvalds  */
13841da177e4SLinus Torvalds 
138554d8fe44SFinn Thain static void do_reset(struct Scsi_Host *instance)
138654d8fe44SFinn Thain {
1387636b1ec8SFinn Thain 	unsigned long flags;
1388636b1ec8SFinn Thain 
1389636b1ec8SFinn Thain 	local_irq_save(flags);
1390636b1ec8SFinn Thain 	NCR5380_write(TARGET_COMMAND_REG,
1391636b1ec8SFinn Thain 	              PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
13921da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
1393636b1ec8SFinn Thain 	udelay(50);
13941da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1395636b1ec8SFinn Thain 	(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
1396636b1ec8SFinn Thain 	local_irq_restore(flags);
13971da177e4SLinus Torvalds }
13981da177e4SLinus Torvalds 
139980d3eb6dSFinn Thain /**
140080d3eb6dSFinn Thain  * do_abort - abort the currently established nexus by going to
140180d3eb6dSFinn Thain  * MESSAGE OUT phase and sending an ABORT message.
140280d3eb6dSFinn Thain  * @instance: relevant scsi host instance
14031da177e4SLinus Torvalds  *
140480d3eb6dSFinn Thain  * Returns 0 on success, -1 on failure.
14051da177e4SLinus Torvalds  */
14061da177e4SLinus Torvalds 
140754d8fe44SFinn Thain static int do_abort(struct Scsi_Host *instance)
140854d8fe44SFinn Thain {
14091da177e4SLinus Torvalds 	unsigned char *msgptr, phase, tmp;
14101da177e4SLinus Torvalds 	int len;
14111da177e4SLinus Torvalds 	int rc;
14121da177e4SLinus Torvalds 
14131da177e4SLinus Torvalds 	/* Request message out phase */
14141da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
14151da177e4SLinus Torvalds 
14161da177e4SLinus Torvalds 	/*
14171da177e4SLinus Torvalds 	 * Wait for the target to indicate a valid phase by asserting
14181da177e4SLinus Torvalds 	 * REQ.  Once this happens, we'll have either a MSGOUT phase
14191da177e4SLinus Torvalds 	 * and can immediately send the ABORT message, or we'll have some
14201da177e4SLinus Torvalds 	 * other phase and will have to source/sink data.
14211da177e4SLinus Torvalds 	 *
14221da177e4SLinus Torvalds 	 * We really don't care what value was on the bus or what value
14231da177e4SLinus Torvalds 	 * the target sees, so we just handshake.
14241da177e4SLinus Torvalds 	 */
14251da177e4SLinus Torvalds 
142680d3eb6dSFinn Thain 	rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
14271da177e4SLinus Torvalds 	if (rc < 0)
142880d3eb6dSFinn Thain 		goto timeout;
14291da177e4SLinus Torvalds 
1430f35d3474SFinn Thain 	tmp = NCR5380_read(STATUS_REG) & PHASE_MASK;
14311da177e4SLinus Torvalds 
14321da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
14331da177e4SLinus Torvalds 
1434f35d3474SFinn Thain 	if (tmp != PHASE_MSGOUT) {
14351da177e4SLinus Torvalds 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
143654d8fe44SFinn Thain 		rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ);
14371cc160e1SFinn Thain 		if (rc < 0)
143880d3eb6dSFinn Thain 			goto timeout;
143980d3eb6dSFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
14401da177e4SLinus Torvalds 	}
14411da177e4SLinus Torvalds 	tmp = ABORT;
14421da177e4SLinus Torvalds 	msgptr = &tmp;
14431da177e4SLinus Torvalds 	len = 1;
14441da177e4SLinus Torvalds 	phase = PHASE_MSGOUT;
144554d8fe44SFinn Thain 	NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	/*
14481da177e4SLinus Torvalds 	 * If we got here, and the command completed successfully,
14491da177e4SLinus Torvalds 	 * we're about to go into bus free state.
14501da177e4SLinus Torvalds 	 */
14511da177e4SLinus Torvalds 
14521da177e4SLinus Torvalds 	return len ? -1 : 0;
145380d3eb6dSFinn Thain 
145480d3eb6dSFinn Thain timeout:
145580d3eb6dSFinn Thain 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
145680d3eb6dSFinn Thain 	return -1;
14571da177e4SLinus Torvalds }
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds #if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL)
14601da177e4SLinus Torvalds /*
14611da177e4SLinus Torvalds  * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
14621da177e4SLinus Torvalds  *      unsigned char *phase, int *count, unsigned char **data)
14631da177e4SLinus Torvalds  *
14641da177e4SLinus Torvalds  * Purpose : transfers data in given phase using either real
14651da177e4SLinus Torvalds  *      or pseudo DMA.
14661da177e4SLinus Torvalds  *
14671da177e4SLinus Torvalds  * Inputs : instance - instance of driver, *phase - pointer to
14681da177e4SLinus Torvalds  *      what phase is expected, *count - pointer to number of
14691da177e4SLinus Torvalds  *      bytes to transfer, **data - pointer to data pointer.
14701da177e4SLinus Torvalds  *
14711da177e4SLinus Torvalds  * Returns : -1 when different phase is entered without transferring
147225985edcSLucas De Marchi  *      maximum number of bytes, 0 if all bytes or transferred or exit
14731da177e4SLinus Torvalds  *      is in same phase.
14741da177e4SLinus Torvalds  *
14751da177e4SLinus Torvalds  *      Also, *phase, *count, *data are modified in place.
14761da177e4SLinus Torvalds  *
14771da177e4SLinus Torvalds  *	Locks: io_request lock held by caller
14781da177e4SLinus Torvalds  */
14791da177e4SLinus Torvalds 
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
14821da177e4SLinus Torvalds 	register int c = *count;
14831da177e4SLinus Torvalds 	register unsigned char p = *phase;
14841da177e4SLinus Torvalds 	register unsigned char *d = *data;
14851da177e4SLinus Torvalds 	unsigned char tmp;
14861da177e4SLinus Torvalds 	int foo;
14871da177e4SLinus Torvalds #if defined(REAL_DMA_POLL)
14881da177e4SLinus Torvalds 	int cnt, toPIO;
14891da177e4SLinus Torvalds 	unsigned char saved_data = 0, overrun = 0, residue;
14901da177e4SLinus Torvalds #endif
14911da177e4SLinus Torvalds 
1492e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
14931da177e4SLinus Torvalds 
14941da177e4SLinus Torvalds 	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
14951da177e4SLinus Torvalds 		*phase = tmp;
14961da177e4SLinus Torvalds 		return -1;
14971da177e4SLinus Torvalds 	}
14981da177e4SLinus Torvalds #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
14991da177e4SLinus Torvalds 	if (p & SR_IO) {
15009db6024eSFinn Thain 		if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS))
15011da177e4SLinus Torvalds 			c -= 2;
15021da177e4SLinus Torvalds 	}
150352a6a1cbSFinn Thain 	dprintk(NDEBUG_DMA, "scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
15041da177e4SLinus Torvalds 	hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);
15051da177e4SLinus Torvalds #endif
15061da177e4SLinus Torvalds 
15071da177e4SLinus Torvalds 	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
15081da177e4SLinus Torvalds 
15091da177e4SLinus Torvalds #ifdef REAL_DMA
1510cd400825SFinn Thain 	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY |
1511cd400825SFinn Thain 	                        MR_ENABLE_EOP_INTR);
15121da177e4SLinus Torvalds #elif defined(REAL_DMA_POLL)
1513cd400825SFinn Thain 	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY);
15141da177e4SLinus Torvalds #else
15151da177e4SLinus Torvalds 	/*
15161da177e4SLinus Torvalds 	 * Note : on my sample board, watch-dog timeouts occurred when interrupts
15171da177e4SLinus Torvalds 	 * were not disabled for the duration of a single DMA transfer, from
15181da177e4SLinus Torvalds 	 * before the setting of DMA mode to after transfer of the last byte.
15191da177e4SLinus Torvalds 	 */
15201da177e4SLinus Torvalds 
152155181be8SFinn Thain 	if (hostdata->flags & FLAG_NO_DMA_FIXUP)
1522cd400825SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY |
1523cd400825SFinn Thain 		                        MR_ENABLE_EOP_INTR);
15241da177e4SLinus Torvalds 	else
1525cd400825SFinn Thain 		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY);
15261da177e4SLinus Torvalds #endif				/* def REAL_DMA */
15271da177e4SLinus Torvalds 
152852a6a1cbSFinn Thain 	dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
15291da177e4SLinus Torvalds 
15301da177e4SLinus Torvalds 	/*
15311da177e4SLinus Torvalds 	 *	On the PAS16 at least I/O recovery delays are not needed here.
15321da177e4SLinus Torvalds 	 *	Everyone else seems to want them.
15331da177e4SLinus Torvalds 	 */
15341da177e4SLinus Torvalds 
15351da177e4SLinus Torvalds 	if (p & SR_IO) {
15361da177e4SLinus Torvalds 		io_recovery_delay(1);
15371da177e4SLinus Torvalds 		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
15381da177e4SLinus Torvalds 	} else {
15391da177e4SLinus Torvalds 		io_recovery_delay(1);
15401da177e4SLinus Torvalds 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
15411da177e4SLinus Torvalds 		io_recovery_delay(1);
15421da177e4SLinus Torvalds 		NCR5380_write(START_DMA_SEND_REG, 0);
15431da177e4SLinus Torvalds 		io_recovery_delay(1);
15441da177e4SLinus Torvalds 	}
15451da177e4SLinus Torvalds 
15461da177e4SLinus Torvalds #if defined(REAL_DMA_POLL)
15471da177e4SLinus Torvalds 	do {
15481da177e4SLinus Torvalds 		tmp = NCR5380_read(BUS_AND_STATUS_REG);
15491da177e4SLinus Torvalds 	} while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER)));
15501da177e4SLinus Torvalds 
15511da177e4SLinus Torvalds /*
15521da177e4SLinus Torvalds    At this point, either we've completed DMA, or we have a phase mismatch,
15531da177e4SLinus Torvalds    or we've unexpectedly lost BUSY (which is a real error).
15541da177e4SLinus Torvalds 
15551da177e4SLinus Torvalds    For write DMAs, we want to wait until the last byte has been
15561da177e4SLinus Torvalds    transferred out over the bus before we turn off DMA mode.  Alas, there
15571da177e4SLinus Torvalds    seems to be no terribly good way of doing this on a 5380 under all
15581da177e4SLinus Torvalds    conditions.  For non-scatter-gather operations, we can wait until REQ
15591da177e4SLinus Torvalds    and ACK both go false, or until a phase mismatch occurs.  Gather-writes
15601da177e4SLinus Torvalds    are nastier, since the device will be expecting more data than we
15611da177e4SLinus Torvalds    are prepared to send it, and REQ will remain asserted.  On a 53C8[01] we
15621da177e4SLinus Torvalds    could test LAST BIT SENT to assure transfer (I imagine this is precisely
15631da177e4SLinus Torvalds    why this signal was added to the newer chips) but on the older 538[01]
15641da177e4SLinus Torvalds    this signal does not exist.  The workaround for this lack is a watchdog;
15651da177e4SLinus Torvalds    we bail out of the wait-loop after a modest amount of wait-time if
15661da177e4SLinus Torvalds    the usual exit conditions are not met.  Not a terribly clean or
15671da177e4SLinus Torvalds    correct solution :-%
15681da177e4SLinus Torvalds 
15691da177e4SLinus Torvalds    Reads are equally tricky due to a nasty characteristic of the NCR5380.
15701da177e4SLinus Torvalds    If the chip is in DMA mode for an READ, it will respond to a target's
15711da177e4SLinus Torvalds    REQ by latching the SCSI data into the INPUT DATA register and asserting
15721da177e4SLinus Torvalds    ACK, even if it has _already_ been notified by the DMA controller that
15731da177e4SLinus Torvalds    the current DMA transfer has completed!  If the NCR5380 is then taken
15741da177e4SLinus Torvalds    out of DMA mode, this already-acknowledged byte is lost.
15751da177e4SLinus Torvalds 
15761da177e4SLinus Torvalds    This is not a problem for "one DMA transfer per command" reads, because
15771da177e4SLinus Torvalds    the situation will never arise... either all of the data is DMA'ed
15781da177e4SLinus Torvalds    properly, or the target switches to MESSAGE IN phase to signal a
15791da177e4SLinus Torvalds    disconnection (either operation bringing the DMA to a clean halt).
15801da177e4SLinus Torvalds    However, in order to handle scatter-reads, we must work around the
15811da177e4SLinus Torvalds    problem.  The chosen fix is to DMA N-2 bytes, then check for the
15821da177e4SLinus Torvalds    condition before taking the NCR5380 out of DMA mode.  One or two extra
15831da177e4SLinus Torvalds    bytes are transferred via PIO as necessary to fill out the original
15841da177e4SLinus Torvalds    request.
15851da177e4SLinus Torvalds  */
15861da177e4SLinus Torvalds 
15871da177e4SLinus Torvalds 	if (p & SR_IO) {
15889db6024eSFinn Thain 		if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) {
15891da177e4SLinus Torvalds 			udelay(10);
15909db6024eSFinn Thain 			if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) ==
15919db6024eSFinn Thain 			    (BASR_PHASE_MATCH | BASR_ACK)) {
15921da177e4SLinus Torvalds 				saved_data = NCR5380_read(INPUT_DATA_REGISTER);
15931da177e4SLinus Torvalds 				overrun = 1;
15941da177e4SLinus Torvalds 			}
15959db6024eSFinn Thain 		}
15961da177e4SLinus Torvalds 	} else {
15971da177e4SLinus Torvalds 		int limit = 100;
15981da177e4SLinus Torvalds 		while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) {
15991da177e4SLinus Torvalds 			if (!(tmp & BASR_PHASE_MATCH))
16001da177e4SLinus Torvalds 				break;
16011da177e4SLinus Torvalds 			if (--limit < 0)
16021da177e4SLinus Torvalds 				break;
16031da177e4SLinus Torvalds 		}
16041da177e4SLinus Torvalds 	}
16051da177e4SLinus Torvalds 
160652a6a1cbSFinn Thain 	dprintk(NDEBUG_DMA, "scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG));
16071da177e4SLinus Torvalds 
16081da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
16091da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
16101da177e4SLinus Torvalds 
16111da177e4SLinus Torvalds 	residue = NCR5380_dma_residual(instance);
16121da177e4SLinus Torvalds 	c -= residue;
16131da177e4SLinus Torvalds 	*count -= c;
16141da177e4SLinus Torvalds 	*data += c;
16151da177e4SLinus Torvalds 	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
16161da177e4SLinus Torvalds 
16179db6024eSFinn Thain 	if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS) &&
16189db6024eSFinn Thain 	    *phase == p && (p & SR_IO) && residue == 0) {
16191da177e4SLinus Torvalds 		if (overrun) {
162052a6a1cbSFinn Thain 			dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
16211da177e4SLinus Torvalds 			**data = saved_data;
16221da177e4SLinus Torvalds 			*data += 1;
16231da177e4SLinus Torvalds 			*count -= 1;
16241da177e4SLinus Torvalds 			cnt = toPIO = 1;
16251da177e4SLinus Torvalds 		} else {
16261da177e4SLinus Torvalds 			printk("No overrun??\n");
16271da177e4SLinus Torvalds 			cnt = toPIO = 2;
16281da177e4SLinus Torvalds 		}
162952a6a1cbSFinn Thain 		dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%X\n", cnt, *data);
16301da177e4SLinus Torvalds 		NCR5380_transfer_pio(instance, phase, &cnt, data);
16311da177e4SLinus Torvalds 		*count -= toPIO - cnt;
16321da177e4SLinus Torvalds 	}
16331da177e4SLinus Torvalds 
163452a6a1cbSFinn 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));
16351da177e4SLinus Torvalds 	return 0;
16361da177e4SLinus Torvalds 
16371da177e4SLinus Torvalds #elif defined(REAL_DMA)
16381da177e4SLinus Torvalds 	return 0;
16391da177e4SLinus Torvalds #else				/* defined(REAL_DMA_POLL) */
16401da177e4SLinus Torvalds 	if (p & SR_IO) {
164155181be8SFinn Thain 		foo = NCR5380_pread(instance, d,
164255181be8SFinn Thain 			hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1);
164355181be8SFinn Thain 		if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) {
16441da177e4SLinus Torvalds 			/*
16451da177e4SLinus Torvalds 			 * We can't disable DMA mode after successfully transferring
16461da177e4SLinus Torvalds 			 * what we plan to be the last byte, since that would open up
16471da177e4SLinus Torvalds 			 * a race condition where if the target asserted REQ before
16481da177e4SLinus Torvalds 			 * we got the DMA mode reset, the NCR5380 would have latched
16491da177e4SLinus Torvalds 			 * an additional byte into the INPUT DATA register and we'd
16501da177e4SLinus Torvalds 			 * have dropped it.
16511da177e4SLinus Torvalds 			 *
16521da177e4SLinus Torvalds 			 * The workaround was to transfer one fewer bytes than we
16531da177e4SLinus Torvalds 			 * intended to with the pseudo-DMA read function, wait for
16541da177e4SLinus Torvalds 			 * the chip to latch the last byte, read it, and then disable
16551da177e4SLinus Torvalds 			 * pseudo-DMA mode.
16561da177e4SLinus Torvalds 			 *
16571da177e4SLinus Torvalds 			 * After REQ is asserted, the NCR5380 asserts DRQ and ACK.
16581da177e4SLinus Torvalds 			 * REQ is deasserted when ACK is asserted, and not reasserted
16591da177e4SLinus Torvalds 			 * until ACK goes false.  Since the NCR5380 won't lower ACK
16601da177e4SLinus Torvalds 			 * until DACK is asserted, which won't happen unless we twiddle
16611da177e4SLinus Torvalds 			 * the DMA port or we take the NCR5380 out of DMA mode, we
16621da177e4SLinus Torvalds 			 * can guarantee that we won't handshake another extra
16631da177e4SLinus Torvalds 			 * byte.
16641da177e4SLinus Torvalds 			 */
16651da177e4SLinus Torvalds 
166655181be8SFinn Thain 			if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG,
166755181be8SFinn Thain 			                          BASR_DRQ, BASR_DRQ, HZ) < 0) {
166855181be8SFinn Thain 				foo = -1;
166955181be8SFinn Thain 				shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
167055181be8SFinn Thain 			}
167155181be8SFinn Thain 			if (NCR5380_poll_politely(instance, STATUS_REG,
167255181be8SFinn Thain 			                          SR_REQ, 0, HZ) < 0) {
167355181be8SFinn Thain 				foo = -1;
167455181be8SFinn Thain 				shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
167555181be8SFinn Thain 			}
16761da177e4SLinus Torvalds 			d[c - 1] = NCR5380_read(INPUT_DATA_REG);
16771da177e4SLinus Torvalds 		}
16781da177e4SLinus Torvalds 	} else {
16791da177e4SLinus Torvalds 		foo = NCR5380_pwrite(instance, d, c);
168055181be8SFinn Thain 		if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) {
16811da177e4SLinus Torvalds 			/*
16821da177e4SLinus Torvalds 			 * Wait for the last byte to be sent.  If REQ is being asserted for
16831da177e4SLinus Torvalds 			 * the byte we're interested, we'll ACK it and it will go false.
16841da177e4SLinus Torvalds 			 */
168555181be8SFinn Thain 			if (NCR5380_poll_politely2(instance,
168655181be8SFinn Thain 			     BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
168755181be8SFinn Thain 			     BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) {
168855181be8SFinn Thain 				foo = -1;
168955181be8SFinn Thain 				shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n");
16901da177e4SLinus Torvalds 			}
16911da177e4SLinus Torvalds 		}
16921da177e4SLinus Torvalds 	}
16931da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
16941da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
16951da177e4SLinus Torvalds 	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
16961da177e4SLinus Torvalds 	*data = d + c;
16971da177e4SLinus Torvalds 	*count = 0;
16981da177e4SLinus Torvalds 	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
16991da177e4SLinus Torvalds 	return foo;
17001da177e4SLinus Torvalds #endif				/* def REAL_DMA */
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds #endif				/* defined(REAL_DMA) | defined(PSEUDO_DMA) */
17031da177e4SLinus Torvalds 
17041da177e4SLinus Torvalds /*
17051da177e4SLinus Torvalds  * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
17061da177e4SLinus Torvalds  *
17071da177e4SLinus Torvalds  * Purpose : run through the various SCSI phases and do as the target
17081da177e4SLinus Torvalds  *      directs us to.  Operates on the currently connected command,
17091da177e4SLinus Torvalds  *      instance->connected.
17101da177e4SLinus Torvalds  *
17111da177e4SLinus Torvalds  * Inputs : instance, instance for which we are doing commands
17121da177e4SLinus Torvalds  *
17131da177e4SLinus Torvalds  * Side effects : SCSI things happen, the disconnected queue will be
17141da177e4SLinus Torvalds  *      modified if a command disconnects, *instance->connected will
17151da177e4SLinus Torvalds  *      change.
17161da177e4SLinus Torvalds  *
17171da177e4SLinus Torvalds  * XXX Note : we need to watch for bus free or a reset condition here
17181da177e4SLinus Torvalds  *      to recover from an unexpected bus free condition.
17191da177e4SLinus Torvalds  *
17201da177e4SLinus Torvalds  * Locks: io_request_lock held by caller in IRQ mode
17211da177e4SLinus Torvalds  */
17221da177e4SLinus Torvalds 
17231da177e4SLinus Torvalds static void NCR5380_information_transfer(struct Scsi_Host *instance) {
1724e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
17251da177e4SLinus Torvalds 	unsigned char msgout = NOP;
17261da177e4SLinus Torvalds 	int sink = 0;
17271da177e4SLinus Torvalds 	int len;
17281da177e4SLinus Torvalds #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
17291da177e4SLinus Torvalds 	int transfersize;
17301da177e4SLinus Torvalds #endif
17311da177e4SLinus Torvalds 	unsigned char *data;
17321da177e4SLinus Torvalds 	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
173311d2f63bSFinn Thain 	struct scsi_cmnd *cmd;
17341da177e4SLinus Torvalds 
173511d2f63bSFinn Thain 	while ((cmd = hostdata->connected)) {
1736*32b26a10SFinn Thain 		struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
1737*32b26a10SFinn Thain 
17381da177e4SLinus Torvalds 		tmp = NCR5380_read(STATUS_REG);
17391da177e4SLinus Torvalds 		/* We only have a valid SCSI phase when REQ is asserted */
17401da177e4SLinus Torvalds 		if (tmp & SR_REQ) {
17411da177e4SLinus Torvalds 			phase = (tmp & PHASE_MASK);
17421da177e4SLinus Torvalds 			if (phase != old_phase) {
17431da177e4SLinus Torvalds 				old_phase = phase;
17441da177e4SLinus Torvalds 				NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
17451da177e4SLinus Torvalds 			}
17461da177e4SLinus Torvalds 			if (sink && (phase != PHASE_MSGOUT)) {
17471da177e4SLinus Torvalds 				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
17501da177e4SLinus Torvalds 				while (NCR5380_read(STATUS_REG) & SR_REQ);
17511da177e4SLinus Torvalds 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
17521da177e4SLinus Torvalds 				sink = 0;
17531da177e4SLinus Torvalds 				continue;
17541da177e4SLinus Torvalds 			}
17551da177e4SLinus Torvalds 			switch (phase) {
17561da177e4SLinus Torvalds 			case PHASE_DATAOUT:
17571da177e4SLinus Torvalds #if (NDEBUG & NDEBUG_NO_DATAOUT)
17581da177e4SLinus Torvalds 				printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", instance->host_no);
17591da177e4SLinus Torvalds 				sink = 1;
17601da177e4SLinus Torvalds 				do_abort(instance);
17611da177e4SLinus Torvalds 				cmd->result = DID_ERROR << 16;
1762cce99c69SMatthew Wilcox 				cmd->scsi_done(cmd);
17631da177e4SLinus Torvalds 				return;
17641da177e4SLinus Torvalds #endif
1765bf1a0c6fSFinn Thain 			case PHASE_DATAIN:
17661da177e4SLinus Torvalds 				/*
17671da177e4SLinus Torvalds 				 * If there is no room left in the current buffer in the
17681da177e4SLinus Torvalds 				 * scatter-gather list, move onto the next one.
17691da177e4SLinus Torvalds 				 */
17701da177e4SLinus Torvalds 
17711da177e4SLinus Torvalds 				if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
17721da177e4SLinus Torvalds 					++cmd->SCp.buffer;
17731da177e4SLinus Torvalds 					--cmd->SCp.buffers_residual;
17741da177e4SLinus Torvalds 					cmd->SCp.this_residual = cmd->SCp.buffer->length;
177545711f1aSJens Axboe 					cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
177652a6a1cbSFinn Thain 					dprintk(NDEBUG_INFORMATION, "scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual);
17771da177e4SLinus Torvalds 				}
17781da177e4SLinus Torvalds 				/*
17791da177e4SLinus Torvalds 				 * The preferred transfer method is going to be
17801da177e4SLinus Torvalds 				 * PSEUDO-DMA for systems that are strictly PIO,
17811da177e4SLinus Torvalds 				 * since we can let the hardware do the handshaking.
17821da177e4SLinus Torvalds 				 *
17831da177e4SLinus Torvalds 				 * For this to work, we need to know the transfersize
17841da177e4SLinus Torvalds 				 * ahead of time, since the pseudo-DMA code will sit
17851da177e4SLinus Torvalds 				 * in an unconditional loop.
17861da177e4SLinus Torvalds 				 */
17871da177e4SLinus Torvalds 
17881da177e4SLinus Torvalds #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
1789ff3d4578SFinn Thain 				transfersize = 0;
1790ff3d4578SFinn Thain 				if (!cmd->device->borken &&
1791ff3d4578SFinn Thain 				    !(hostdata->flags & FLAG_NO_PSEUDO_DMA))
1792ff3d4578SFinn Thain 					transfersize = NCR5380_dma_xfer_len(instance, cmd, phase);
17931da177e4SLinus Torvalds 
1794ff3d4578SFinn Thain 				if (transfersize) {
17951da177e4SLinus Torvalds 					len = transfersize;
17961da177e4SLinus Torvalds 					if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **) &cmd->SCp.ptr)) {
17971da177e4SLinus Torvalds 						/*
17981da177e4SLinus Torvalds 						 * If the watchdog timer fires, all future accesses to this
17991da177e4SLinus Torvalds 						 * device will use the polled-IO.
18001da177e4SLinus Torvalds 						 */
1801017560fcSJeff Garzik 						scmd_printk(KERN_INFO, cmd,
1802017560fcSJeff Garzik 							    "switching to slow handshake\n");
18031da177e4SLinus Torvalds 						cmd->device->borken = 1;
18041da177e4SLinus Torvalds 						sink = 1;
18051da177e4SLinus Torvalds 						do_abort(instance);
18061da177e4SLinus Torvalds 						cmd->result = DID_ERROR << 16;
1807cce99c69SMatthew Wilcox 						cmd->scsi_done(cmd);
18081da177e4SLinus Torvalds 						/* XXX - need to source or sink data here, as appropriate */
18091da177e4SLinus Torvalds 					} else
18101da177e4SLinus Torvalds 						cmd->SCp.this_residual -= transfersize - len;
18111da177e4SLinus Torvalds 				} else
18121da177e4SLinus Torvalds #endif				/* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
181311d2f63bSFinn Thain 				{
181411d2f63bSFinn Thain 					spin_unlock_irq(&hostdata->lock);
18151da177e4SLinus Torvalds 					NCR5380_transfer_pio(instance, &phase, (int *) &cmd->SCp.this_residual, (unsigned char **)
18161da177e4SLinus Torvalds 							     &cmd->SCp.ptr);
181711d2f63bSFinn Thain 					spin_lock_irq(&hostdata->lock);
181811d2f63bSFinn Thain 				}
18191da177e4SLinus Torvalds 				break;
18201da177e4SLinus Torvalds 			case PHASE_MSGIN:
18211da177e4SLinus Torvalds 				len = 1;
18221da177e4SLinus Torvalds 				data = &tmp;
18231da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
18241da177e4SLinus Torvalds 				cmd->SCp.Message = tmp;
18251da177e4SLinus Torvalds 
18261da177e4SLinus Torvalds 				switch (tmp) {
18271da177e4SLinus Torvalds 				case ABORT:
18281da177e4SLinus Torvalds 				case COMMAND_COMPLETE:
18291da177e4SLinus Torvalds 					/* Accept message by clearing ACK */
18301da177e4SLinus Torvalds 					sink = 1;
18311da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
18320d3d9a42SFinn Thain 					dsprintk(NDEBUG_QUEUES, instance,
18330d3d9a42SFinn Thain 					         "COMMAND COMPLETE %p target %d lun %llu\n",
18340d3d9a42SFinn Thain 					         cmd, scmd_id(cmd), cmd->device->lun);
18350d3d9a42SFinn Thain 
18361da177e4SLinus Torvalds 					hostdata->connected = NULL;
18379cb78c16SHannes Reinecke 					hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
18381da177e4SLinus Torvalds 
18391da177e4SLinus Torvalds 					/*
18401da177e4SLinus Torvalds 					 * I'm not sure what the correct thing to do here is :
18411da177e4SLinus Torvalds 					 *
18421da177e4SLinus Torvalds 					 * If the command that just executed is NOT a request
18431da177e4SLinus Torvalds 					 * sense, the obvious thing to do is to set the result
18441da177e4SLinus Torvalds 					 * code to the values of the stored parameters.
18451da177e4SLinus Torvalds 					 *
18461da177e4SLinus Torvalds 					 * If it was a REQUEST SENSE command, we need some way
18471da177e4SLinus Torvalds 					 * to differentiate between the failure code of the original
18481da177e4SLinus Torvalds 					 * and the failure code of the REQUEST sense - the obvious
18491da177e4SLinus Torvalds 					 * case is success, where we fall through and leave the result
18501da177e4SLinus Torvalds 					 * code unchanged.
18511da177e4SLinus Torvalds 					 *
18521da177e4SLinus Torvalds 					 * The non-obvious place is where the REQUEST SENSE failed
18531da177e4SLinus Torvalds 					 */
18541da177e4SLinus Torvalds 
18551da177e4SLinus Torvalds 					if (cmd->cmnd[0] != REQUEST_SENSE)
18561da177e4SLinus Torvalds 						cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
18571da177e4SLinus Torvalds 					else if (status_byte(cmd->SCp.Status) != GOOD)
18581da177e4SLinus Torvalds 						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
18591da177e4SLinus Torvalds 
186028424d3aSBoaz Harrosh 					if ((cmd->cmnd[0] == REQUEST_SENSE) &&
186128424d3aSBoaz Harrosh 						hostdata->ses.cmd_len) {
186228424d3aSBoaz Harrosh 						scsi_eh_restore_cmnd(cmd, &hostdata->ses);
186328424d3aSBoaz Harrosh 						hostdata->ses.cmd_len = 0 ;
186428424d3aSBoaz Harrosh 					}
18651da177e4SLinus Torvalds 
186628424d3aSBoaz Harrosh 					if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
186728424d3aSBoaz Harrosh 						scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
186828424d3aSBoaz Harrosh 
1869*32b26a10SFinn Thain 						list_add(&ncmd->list, &hostdata->unissued);
18700d3d9a42SFinn Thain 						dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES,
18710d3d9a42SFinn Thain 						         instance, "REQUEST SENSE cmd %p added to head of issue queue\n",
1872dbb6b350SFinn Thain 						         cmd);
1873997acab7SFinn Thain 					} else {
18741da177e4SLinus Torvalds 						cmd->scsi_done(cmd);
18751da177e4SLinus Torvalds 					}
18761da177e4SLinus Torvalds 
18771da177e4SLinus Torvalds 					/*
18781da177e4SLinus Torvalds 					 * Restore phase bits to 0 so an interrupted selection,
18791da177e4SLinus Torvalds 					 * arbitration can resume.
18801da177e4SLinus Torvalds 					 */
18811da177e4SLinus Torvalds 					NCR5380_write(TARGET_COMMAND_REG, 0);
188272064a78SFinn Thain 
188372064a78SFinn Thain 					/* Enable reselect interrupts */
188472064a78SFinn Thain 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
18851da177e4SLinus Torvalds 					return;
18861da177e4SLinus Torvalds 				case MESSAGE_REJECT:
18871da177e4SLinus Torvalds 					/* Accept message by clearing ACK */
18881da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
18891da177e4SLinus Torvalds 					switch (hostdata->last_message) {
18901da177e4SLinus Torvalds 					case HEAD_OF_QUEUE_TAG:
18911da177e4SLinus Torvalds 					case ORDERED_QUEUE_TAG:
18921da177e4SLinus Torvalds 					case SIMPLE_QUEUE_TAG:
18931da177e4SLinus Torvalds 						cmd->device->simple_tags = 0;
18949cb78c16SHannes Reinecke 						hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
18951da177e4SLinus Torvalds 						break;
18961da177e4SLinus Torvalds 					default:
18971da177e4SLinus Torvalds 						break;
18981da177e4SLinus Torvalds 					}
1899340b9612SFinn Thain 					break;
19001da177e4SLinus Torvalds 				case DISCONNECT:{
19011da177e4SLinus Torvalds 						/* Accept message by clearing ACK */
19021da177e4SLinus Torvalds 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
19031da177e4SLinus Torvalds 						hostdata->connected = NULL;
1904*32b26a10SFinn Thain 						list_add(&ncmd->list, &hostdata->disconnected);
19050d3d9a42SFinn Thain 						dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES,
19060d3d9a42SFinn Thain 						         instance, "connected command %p for target %d lun %llu moved to disconnected queue\n",
19070d3d9a42SFinn Thain 						         cmd, scmd_id(cmd), cmd->device->lun);
19080d3d9a42SFinn Thain 
19091da177e4SLinus Torvalds 						/*
19101da177e4SLinus Torvalds 						 * Restore phase bits to 0 so an interrupted selection,
19111da177e4SLinus Torvalds 						 * arbitration can resume.
19121da177e4SLinus Torvalds 						 */
19131da177e4SLinus Torvalds 						NCR5380_write(TARGET_COMMAND_REG, 0);
19141da177e4SLinus Torvalds 
19151da177e4SLinus Torvalds 						/* Enable reselect interrupts */
19161da177e4SLinus Torvalds 						NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
19171da177e4SLinus Torvalds 						return;
19181da177e4SLinus Torvalds 					}
19191da177e4SLinus Torvalds 					/*
19201da177e4SLinus Torvalds 					 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
19211da177e4SLinus Torvalds 					 * operation, in violation of the SCSI spec so we can safely
19221da177e4SLinus Torvalds 					 * ignore SAVE/RESTORE pointers calls.
19231da177e4SLinus Torvalds 					 *
19241da177e4SLinus Torvalds 					 * Unfortunately, some disks violate the SCSI spec and
19251da177e4SLinus Torvalds 					 * don't issue the required SAVE_POINTERS message before
19261da177e4SLinus Torvalds 					 * disconnecting, and we have to break spec to remain
19271da177e4SLinus Torvalds 					 * compatible.
19281da177e4SLinus Torvalds 					 */
19291da177e4SLinus Torvalds 				case SAVE_POINTERS:
19301da177e4SLinus Torvalds 				case RESTORE_POINTERS:
19311da177e4SLinus Torvalds 					/* Accept message by clearing ACK */
19321da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
19331da177e4SLinus Torvalds 					break;
19341da177e4SLinus Torvalds 				case EXTENDED_MESSAGE:
19351da177e4SLinus Torvalds /*
19361da177e4SLinus Torvalds  * Extended messages are sent in the following format :
19371da177e4SLinus Torvalds  * Byte
19381da177e4SLinus Torvalds  * 0            EXTENDED_MESSAGE == 1
19391da177e4SLinus Torvalds  * 1            length (includes one byte for code, doesn't
19401da177e4SLinus Torvalds  *              include first two bytes)
19411da177e4SLinus Torvalds  * 2            code
19421da177e4SLinus Torvalds  * 3..length+1  arguments
19431da177e4SLinus Torvalds  *
19441da177e4SLinus Torvalds  * Start the extended message buffer with the EXTENDED_MESSAGE
19451abfd370SMatthew Wilcox  * byte, since spi_print_msg() wants the whole thing.
19461da177e4SLinus Torvalds  */
19471da177e4SLinus Torvalds 					extended_msg[0] = EXTENDED_MESSAGE;
19481da177e4SLinus Torvalds 					/* Accept first byte by clearing ACK */
19491da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
195011d2f63bSFinn Thain 
195111d2f63bSFinn Thain 					spin_unlock_irq(&hostdata->lock);
195211d2f63bSFinn Thain 
195352a6a1cbSFinn Thain 					dprintk(NDEBUG_EXTENDED, "scsi%d : receiving extended message\n", instance->host_no);
19541da177e4SLinus Torvalds 
19551da177e4SLinus Torvalds 					len = 2;
19561da177e4SLinus Torvalds 					data = extended_msg + 1;
19571da177e4SLinus Torvalds 					phase = PHASE_MSGIN;
19581da177e4SLinus Torvalds 					NCR5380_transfer_pio(instance, &phase, &len, &data);
19591da177e4SLinus Torvalds 
196052a6a1cbSFinn Thain 					dprintk(NDEBUG_EXTENDED, "scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]);
19611da177e4SLinus Torvalds 
1962e0783ed3SFinn Thain 					if (!len && extended_msg[1] > 0 &&
1963e0783ed3SFinn Thain 					    extended_msg[1] <= sizeof(extended_msg) - 2) {
19641da177e4SLinus Torvalds 						/* Accept third byte by clearing ACK */
19651da177e4SLinus Torvalds 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
19661da177e4SLinus Torvalds 						len = extended_msg[1] - 1;
19671da177e4SLinus Torvalds 						data = extended_msg + 3;
19681da177e4SLinus Torvalds 						phase = PHASE_MSGIN;
19691da177e4SLinus Torvalds 
19701da177e4SLinus Torvalds 						NCR5380_transfer_pio(instance, &phase, &len, &data);
197152a6a1cbSFinn Thain 						dprintk(NDEBUG_EXTENDED, "scsi%d : message received, residual %d\n", instance->host_no, len);
19721da177e4SLinus Torvalds 
19731da177e4SLinus Torvalds 						switch (extended_msg[2]) {
19741da177e4SLinus Torvalds 						case EXTENDED_SDTR:
19751da177e4SLinus Torvalds 						case EXTENDED_WDTR:
19761da177e4SLinus Torvalds 						case EXTENDED_MODIFY_DATA_POINTER:
19771da177e4SLinus Torvalds 						case EXTENDED_EXTENDED_IDENTIFY:
19781da177e4SLinus Torvalds 							tmp = 0;
19791da177e4SLinus Torvalds 						}
19801da177e4SLinus Torvalds 					} else if (len) {
19811da177e4SLinus Torvalds 						printk("scsi%d: error receiving extended message\n", instance->host_no);
19821da177e4SLinus Torvalds 						tmp = 0;
19831da177e4SLinus Torvalds 					} else {
19841da177e4SLinus Torvalds 						printk("scsi%d: extended message code %02x length %d is too long\n", instance->host_no, extended_msg[2], extended_msg[1]);
19851da177e4SLinus Torvalds 						tmp = 0;
19861da177e4SLinus Torvalds 					}
198711d2f63bSFinn Thain 
198811d2f63bSFinn Thain 					spin_lock_irq(&hostdata->lock);
198911d2f63bSFinn Thain 					if (!hostdata->connected)
199011d2f63bSFinn Thain 						return;
199111d2f63bSFinn Thain 
19921da177e4SLinus Torvalds 					/* Fall through to reject message */
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 					/*
19951da177e4SLinus Torvalds 					 * If we get something weird that we aren't expecting,
19961da177e4SLinus Torvalds 					 * reject it.
19971da177e4SLinus Torvalds 					 */
19981da177e4SLinus Torvalds 				default:
19991da177e4SLinus Torvalds 					if (!tmp) {
20001da177e4SLinus Torvalds 						printk("scsi%d: rejecting message ", instance->host_no);
20011abfd370SMatthew Wilcox 						spi_print_msg(extended_msg);
20021da177e4SLinus Torvalds 						printk("\n");
20031da177e4SLinus Torvalds 					} else if (tmp != EXTENDED_MESSAGE)
2004017560fcSJeff Garzik 						scmd_printk(KERN_INFO, cmd,
2005017560fcSJeff Garzik 							"rejecting unknown message %02x\n",tmp);
20061da177e4SLinus Torvalds 					else
2007017560fcSJeff Garzik 						scmd_printk(KERN_INFO, cmd,
2008017560fcSJeff Garzik 							"rejecting unknown extended message code %02x, length %d\n", extended_msg[1], extended_msg[0]);
20091da177e4SLinus Torvalds 
20101da177e4SLinus Torvalds 					msgout = MESSAGE_REJECT;
20111da177e4SLinus Torvalds 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
20121da177e4SLinus Torvalds 					break;
20131da177e4SLinus Torvalds 				}	/* switch (tmp) */
20141da177e4SLinus Torvalds 				break;
20151da177e4SLinus Torvalds 			case PHASE_MSGOUT:
20161da177e4SLinus Torvalds 				len = 1;
20171da177e4SLinus Torvalds 				data = &msgout;
20181da177e4SLinus Torvalds 				hostdata->last_message = msgout;
20191da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
20201da177e4SLinus Torvalds 				if (msgout == ABORT) {
20219cb78c16SHannes Reinecke 					hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
20221da177e4SLinus Torvalds 					hostdata->connected = NULL;
20231da177e4SLinus Torvalds 					cmd->result = DID_ERROR << 16;
20241da177e4SLinus Torvalds 					cmd->scsi_done(cmd);
20251da177e4SLinus Torvalds 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
20261da177e4SLinus Torvalds 					return;
20271da177e4SLinus Torvalds 				}
20281da177e4SLinus Torvalds 				msgout = NOP;
20291da177e4SLinus Torvalds 				break;
20301da177e4SLinus Torvalds 			case PHASE_CMDOUT:
20311da177e4SLinus Torvalds 				len = cmd->cmd_len;
20321da177e4SLinus Torvalds 				data = cmd->cmnd;
20331da177e4SLinus Torvalds 				/*
20341da177e4SLinus Torvalds 				 * XXX for performance reasons, on machines with a
20351da177e4SLinus Torvalds 				 * PSEUDO-DMA architecture we should probably
20361da177e4SLinus Torvalds 				 * use the dma transfer function.
20371da177e4SLinus Torvalds 				 */
20381da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
20391da177e4SLinus Torvalds 				break;
20401da177e4SLinus Torvalds 			case PHASE_STATIN:
20411da177e4SLinus Torvalds 				len = 1;
20421da177e4SLinus Torvalds 				data = &tmp;
20431da177e4SLinus Torvalds 				NCR5380_transfer_pio(instance, &phase, &len, &data);
20441da177e4SLinus Torvalds 				cmd->SCp.Status = tmp;
20451da177e4SLinus Torvalds 				break;
20461da177e4SLinus Torvalds 			default:
20471da177e4SLinus Torvalds 				printk("scsi%d : unknown phase\n", instance->host_no);
20484dde8f7dSFinn Thain 				NCR5380_dprint(NDEBUG_ANY, instance);
20491da177e4SLinus Torvalds 			}	/* switch(phase) */
2050686f3990SFinn Thain 		} else {
205111d2f63bSFinn Thain 			spin_unlock_irq(&hostdata->lock);
2052686f3990SFinn Thain 			NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
205311d2f63bSFinn Thain 			spin_lock_irq(&hostdata->lock);
20541da177e4SLinus Torvalds 		}
205511d2f63bSFinn Thain 	}
20561da177e4SLinus Torvalds }
20571da177e4SLinus Torvalds 
20581da177e4SLinus Torvalds /*
20591da177e4SLinus Torvalds  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
20601da177e4SLinus Torvalds  *
20611da177e4SLinus Torvalds  * Purpose : does reselection, initializing the instance->connected
2062710ddd0dSFinn Thain  *      field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
20631da177e4SLinus Torvalds  *      nexus has been reestablished,
20641da177e4SLinus Torvalds  *
20651da177e4SLinus Torvalds  * Inputs : instance - this instance of the NCR5380.
20661da177e4SLinus Torvalds  *
20671da177e4SLinus Torvalds  * Locks: io_request_lock held by caller if IRQ driven
20681da177e4SLinus Torvalds  */
20691da177e4SLinus Torvalds 
20701da177e4SLinus Torvalds static void NCR5380_reselect(struct Scsi_Host *instance) {
2071e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
20721da177e4SLinus Torvalds 	unsigned char target_mask;
20731da177e4SLinus Torvalds 	unsigned char lun, phase;
20741da177e4SLinus Torvalds 	int len;
20751da177e4SLinus Torvalds 	unsigned char msg[3];
20761da177e4SLinus Torvalds 	unsigned char *data;
2077*32b26a10SFinn Thain 	struct NCR5380_cmd *ncmd;
2078*32b26a10SFinn Thain 	struct scsi_cmnd *tmp;
20791da177e4SLinus Torvalds 
20801da177e4SLinus Torvalds 	/*
20811da177e4SLinus Torvalds 	 * Disable arbitration, etc. since the host adapter obviously
20821da177e4SLinus Torvalds 	 * lost, and tell an interrupted NCR5380_select() to restart.
20831da177e4SLinus Torvalds 	 */
20841da177e4SLinus Torvalds 
20851da177e4SLinus Torvalds 	NCR5380_write(MODE_REG, MR_BASE);
20861da177e4SLinus Torvalds 
20871da177e4SLinus Torvalds 	target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
208872064a78SFinn Thain 	dprintk(NDEBUG_RESELECTION, "scsi%d : reselect\n", instance->host_no);
20891da177e4SLinus Torvalds 
20901da177e4SLinus Torvalds 	/*
20911da177e4SLinus Torvalds 	 * At this point, we have detected that our SCSI ID is on the bus,
20921da177e4SLinus Torvalds 	 * SEL is true and BSY was false for at least one bus settle delay
20931da177e4SLinus Torvalds 	 * (400 ns).
20941da177e4SLinus Torvalds 	 *
20951da177e4SLinus Torvalds 	 * We must assert BSY ourselves, until the target drops the SEL
20961da177e4SLinus Torvalds 	 * signal.
20971da177e4SLinus Torvalds 	 */
20981da177e4SLinus Torvalds 
20991da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
210072064a78SFinn Thain 	if (NCR5380_poll_politely(instance,
210172064a78SFinn Thain 	                          STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) {
210272064a78SFinn Thain 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
210372064a78SFinn Thain 		return;
210472064a78SFinn Thain 	}
21051da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
21061da177e4SLinus Torvalds 
21071da177e4SLinus Torvalds 	/*
21081da177e4SLinus Torvalds 	 * Wait for target to go into MSGIN.
21091da177e4SLinus Torvalds 	 */
21101da177e4SLinus Torvalds 
21111cc160e1SFinn Thain 	if (NCR5380_poll_politely(instance,
211272064a78SFinn Thain 	                          STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) {
211372064a78SFinn Thain 		do_abort(instance);
211472064a78SFinn Thain 		return;
211572064a78SFinn Thain 	}
21161da177e4SLinus Torvalds 
21171da177e4SLinus Torvalds 	len = 1;
21181da177e4SLinus Torvalds 	data = msg;
21191da177e4SLinus Torvalds 	phase = PHASE_MSGIN;
21201da177e4SLinus Torvalds 	NCR5380_transfer_pio(instance, &phase, &len, &data);
21211da177e4SLinus Torvalds 
212272064a78SFinn Thain 	if (len) {
212372064a78SFinn Thain 		do_abort(instance);
212472064a78SFinn Thain 		return;
212572064a78SFinn Thain 	}
212672064a78SFinn Thain 
21271da177e4SLinus Torvalds 	if (!(msg[0] & 0x80)) {
212872064a78SFinn Thain 		shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got ");
21291abfd370SMatthew Wilcox 		spi_print_msg(msg);
213072064a78SFinn Thain 		printk("\n");
213172064a78SFinn Thain 		do_abort(instance);
213272064a78SFinn Thain 		return;
213372064a78SFinn Thain 	}
213472064a78SFinn Thain 	lun = msg[0] & 0x07;
21351da177e4SLinus Torvalds 
21361da177e4SLinus Torvalds 	/*
21371da177e4SLinus Torvalds 	 * We need to add code for SCSI-II to track which devices have
21381da177e4SLinus Torvalds 	 * I_T_L_Q nexuses established, and which have simple I_T_L
21391da177e4SLinus Torvalds 	 * nexuses so we can chose to do additional data transfer.
21401da177e4SLinus Torvalds 	 */
21411da177e4SLinus Torvalds 
21421da177e4SLinus Torvalds 	/*
21431da177e4SLinus Torvalds 	 * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we
21441da177e4SLinus Torvalds 	 * just reestablished, and remove it from the disconnected queue.
21451da177e4SLinus Torvalds 	 */
21461da177e4SLinus Torvalds 
2147*32b26a10SFinn Thain 	tmp = NULL;
2148*32b26a10SFinn Thain 	list_for_each_entry(ncmd, &hostdata->disconnected, list) {
2149*32b26a10SFinn Thain 		struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
2150*32b26a10SFinn Thain 
2151*32b26a10SFinn Thain 		if (target_mask == (1 << scmd_id(cmd)) &&
2152*32b26a10SFinn Thain 		    lun == (u8)cmd->device->lun) {
2153*32b26a10SFinn Thain 			list_del(&ncmd->list);
2154*32b26a10SFinn Thain 			tmp = cmd;
21551da177e4SLinus Torvalds 			break;
21561da177e4SLinus Torvalds 		}
215772064a78SFinn Thain 	}
21580d3d9a42SFinn Thain 
21590d3d9a42SFinn Thain 	if (tmp) {
21600d3d9a42SFinn Thain 		dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance,
21610d3d9a42SFinn Thain 		         "reselect: removed %p from disconnected queue\n", tmp);
21620d3d9a42SFinn Thain 	} else {
216372064a78SFinn Thain 		shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n",
216472064a78SFinn Thain 		             target_mask, lun);
21651da177e4SLinus Torvalds 		/*
21661da177e4SLinus Torvalds 		 * Since we have an established nexus that we can't do anything with,
21671da177e4SLinus Torvalds 		 * we must abort it.
21681da177e4SLinus Torvalds 		 */
216972064a78SFinn Thain 		do_abort(instance);
217072064a78SFinn Thain 		return;
21711da177e4SLinus Torvalds 	}
21721da177e4SLinus Torvalds 
217372064a78SFinn Thain 	/* Accept message by clearing ACK */
217472064a78SFinn Thain 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
217572064a78SFinn Thain 
21761da177e4SLinus Torvalds 	hostdata->connected = tmp;
217772064a78SFinn Thain 	dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n",
217872064a78SFinn Thain 	        instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag);
21791da177e4SLinus Torvalds }
21801da177e4SLinus Torvalds 
21811da177e4SLinus Torvalds /*
21821da177e4SLinus Torvalds  * Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
21831da177e4SLinus Torvalds  *
21841da177e4SLinus Torvalds  * Purpose : called by interrupt handler when DMA finishes or a phase
21851da177e4SLinus Torvalds  *      mismatch occurs (which would finish the DMA transfer).
21861da177e4SLinus Torvalds  *
21871da177e4SLinus Torvalds  * Inputs : instance - this instance of the NCR5380.
21881da177e4SLinus Torvalds  *
2189710ddd0dSFinn Thain  * Returns : pointer to the scsi_cmnd structure for which the I_T_L
21901da177e4SLinus Torvalds  *      nexus has been reestablished, on failure NULL is returned.
21911da177e4SLinus Torvalds  */
21921da177e4SLinus Torvalds 
21931da177e4SLinus Torvalds #ifdef REAL_DMA
21941da177e4SLinus Torvalds static void NCR5380_dma_complete(NCR5380_instance * instance) {
2195e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
21961da177e4SLinus Torvalds 	int transferred;
21971da177e4SLinus Torvalds 
21981da177e4SLinus Torvalds 	/*
21991da177e4SLinus Torvalds 	 * XXX this might not be right.
22001da177e4SLinus Torvalds 	 *
22011da177e4SLinus Torvalds 	 * Wait for final byte to transfer, ie wait for ACK to go false.
22021da177e4SLinus Torvalds 	 *
22031da177e4SLinus Torvalds 	 * We should use the Last Byte Sent bit, unfortunately this is
22041da177e4SLinus Torvalds 	 * not available on the 5380/5381 (only the various CMOS chips)
22051da177e4SLinus Torvalds 	 *
22061da177e4SLinus Torvalds 	 * FIXME: timeout, and need to handle long timeout/irq case
22071da177e4SLinus Torvalds 	 */
22081da177e4SLinus Torvalds 
22091da177e4SLinus Torvalds 	NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ);
22101da177e4SLinus Torvalds 
22111da177e4SLinus Torvalds 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
22121da177e4SLinus Torvalds 
22131da177e4SLinus Torvalds 	/*
22141da177e4SLinus Torvalds 	 * The only places we should see a phase mismatch and have to send
22151da177e4SLinus Torvalds 	 * data from the same set of pointers will be the data transfer
22161da177e4SLinus Torvalds 	 * phases.  So, residual, requested length are only important here.
22171da177e4SLinus Torvalds 	 */
22181da177e4SLinus Torvalds 
22191da177e4SLinus Torvalds 	if (!(hostdata->connected->SCp.phase & SR_CD)) {
22201da177e4SLinus Torvalds 		transferred = instance->dmalen - NCR5380_dma_residual();
22211da177e4SLinus Torvalds 		hostdata->connected->SCp.this_residual -= transferred;
22221da177e4SLinus Torvalds 		hostdata->connected->SCp.ptr += transferred;
22231da177e4SLinus Torvalds 	}
22241da177e4SLinus Torvalds }
22251da177e4SLinus Torvalds #endif				/* def REAL_DMA */
22261da177e4SLinus Torvalds 
22271da177e4SLinus Torvalds /*
2228710ddd0dSFinn Thain  * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
22291da177e4SLinus Torvalds  *
22301da177e4SLinus Torvalds  * Purpose : abort a command
22311da177e4SLinus Torvalds  *
2232710ddd0dSFinn Thain  * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
22331da177e4SLinus Torvalds  *      host byte of the result field to, if zero DID_ABORTED is
22341da177e4SLinus Torvalds  *      used.
22351da177e4SLinus Torvalds  *
2236b6c92b7eSHannes Reinecke  * Returns : SUCCESS - success, FAILED on failure.
22371da177e4SLinus Torvalds  *
22381da177e4SLinus Torvalds  *	XXX - there is no way to abort the command that is currently
22391da177e4SLinus Torvalds  *	connected, you have to wait for it to complete.  If this is
22401da177e4SLinus Torvalds  *	a problem, we could implement longjmp() / setjmp(), setjmp()
22411da177e4SLinus Torvalds  *	called where the loop started in NCR5380_main().
22421da177e4SLinus Torvalds  *
22431da177e4SLinus Torvalds  * Locks: host lock taken by caller
22441da177e4SLinus Torvalds  */
22451da177e4SLinus Torvalds 
2246710ddd0dSFinn Thain static int NCR5380_abort(struct scsi_cmnd *cmd)
2247710ddd0dSFinn Thain {
22481da177e4SLinus Torvalds 	struct Scsi_Host *instance = cmd->device->host;
2249e8a60144SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
225011d2f63bSFinn Thain 	unsigned long flags;
22511da177e4SLinus Torvalds 
225211d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
225311d2f63bSFinn Thain 
2254*32b26a10SFinn Thain #if (NDEBUG & NDEBUG_ANY)
2255*32b26a10SFinn Thain 	scmd_printk(KERN_INFO, cmd, "aborting command\n");
2256*32b26a10SFinn Thain #endif
2257e5c3fddfSFinn Thain 	NCR5380_dprint(NDEBUG_ANY, instance);
2258e5c3fddfSFinn Thain 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
22591da177e4SLinus Torvalds 
226011d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
22611da177e4SLinus Torvalds 
22621da177e4SLinus Torvalds 	return FAILED;
22631da177e4SLinus Torvalds }
22641da177e4SLinus Torvalds 
22651da177e4SLinus Torvalds 
22663be1b3eaSFinn Thain /**
22673be1b3eaSFinn Thain  * NCR5380_bus_reset - reset the SCSI bus
22683be1b3eaSFinn Thain  * @cmd: SCSI command undergoing EH
22691da177e4SLinus Torvalds  *
22703be1b3eaSFinn Thain  * Returns SUCCESS
22711da177e4SLinus Torvalds  */
22721da177e4SLinus Torvalds 
2273710ddd0dSFinn Thain static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
227468b3aa7cSJeff Garzik  {
227568b3aa7cSJeff Garzik  	struct Scsi_Host *instance = cmd->device->host;
227611d2f63bSFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(instance);
227711d2f63bSFinn Thain 	unsigned long flags;
22781da177e4SLinus Torvalds 
227911d2f63bSFinn Thain 	spin_lock_irqsave(&hostdata->lock, flags);
22803be1b3eaSFinn Thain 
22813be1b3eaSFinn Thain #if (NDEBUG & NDEBUG_ANY)
22823be1b3eaSFinn Thain 	scmd_printk(KERN_INFO, cmd, "performing bus reset\n");
22833be1b3eaSFinn Thain #endif
2284e5c3fddfSFinn Thain 	NCR5380_dprint(NDEBUG_ANY, instance);
2285e5c3fddfSFinn Thain 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
22863be1b3eaSFinn Thain 
228768b3aa7cSJeff Garzik  	do_reset(instance);
22883be1b3eaSFinn Thain 
228911d2f63bSFinn Thain 	spin_unlock_irqrestore(&hostdata->lock, flags);
229068b3aa7cSJeff Garzik  
22911da177e4SLinus Torvalds 	return SUCCESS;
22921da177e4SLinus Torvalds }
2293