Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *  linux/drivers/acorn/scsi/fas216.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *  Copyright (C) 1997-2003 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * other sources, including:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *   the AMD Am53CF94 data sheet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *   the AMD Am53C94 data sheet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * This is a generic driver.  To use it, have a look at cumana_2.c.  You
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * should define your own structure that overlays FAS216_Info, eg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * struct my_host_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *    FAS216_Info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *    ... my host specific data ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  * };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * Changelog:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *  30-08-1997	RMK	Created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  *  14-09-1997	RMK	Started disconnect support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  *  08-02-1998	RMK	Corrected real DMA support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  *  15-02-1998	RMK	Started sync xfer support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  *  06-04-1998	RMK	Tightened conditions for printing incomplete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  *			transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  *  02-05-1998	RMK	Added extra checks in fas216_reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  *  24-05-1998	RMK	Fixed synchronous transfers with period >= 200ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  *  27-06-1998	RMK	Changed asm/delay.h to linux/delay.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  *  26-08-1998	RMK	Improved message support wrt MESSAGE_REJECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  *  02-04-2000	RMK	Converted to use the new error handling, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  *			automatically request sense data upon check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  *			condition status from targets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include <asm/ecard.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include "../scsi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #include <scsi/scsi_dbg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #include "fas216.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include "scsi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) /* NOTE: SCSI2 Synchronous transfers *require* DMA according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  *  the data sheet.  This restriction is crazy, especially when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  *  you only want to send 16 bytes!  What were the guys who
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59)  *  designed this chip on at that time?  Did they read the SCSI2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60)  *  spec at all?  The following sections are taken from the SCSI2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  *  standard (s2r10) concerning this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63)  * > IMPLEMENTORS NOTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64)  * >   (1)  Re-negotiation at every selection is not recommended, since a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65)  * >   significant performance impact is likely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67)  * >  The implied synchronous agreement shall remain in effect until a BUS DEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68)  * >  RESET message is received, until a hard reset condition occurs, or until one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69)  * >  of the two SCSI devices elects to modify the agreement.  The default data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70)  * >  transfer mode is asynchronous data transfer mode.  The default data transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71)  * >  mode is entered at power on, after a BUS DEVICE RESET message, or after a hard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72)  * >  reset condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74)  *  In total, this means that once you have elected to use synchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75)  *  transfers, you must always use DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77)  *  I was thinking that this was a good chip until I found this restriction ;(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define SCSI2_SYNC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #undef  SCSI2_TAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #undef DEBUG_CONNECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #undef DEBUG_MESSAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #undef CHECK_STRUCTURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define LOG_CONNECT		(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #define LOG_BUSSERVICE		(1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define LOG_FUNCTIONDONE	(1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define LOG_MESSAGES		(1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define LOG_BUFFER		(1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #define LOG_ERROR		(1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static int level_mask = LOG_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) module_param(level_mask, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static int __init fas216_log_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	level_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	while ((s = strsep(&str, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 		switch (s[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 		case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 			if (strcmp(s, "all") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 				level_mask |= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 		case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 			if (strncmp(s, "bus", 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 				level_mask |= LOG_BUSSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 			if (strncmp(s, "buf", 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 				level_mask |= LOG_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 			level_mask |= LOG_CONNECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 		case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 			level_mask |= LOG_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 			level_mask |= LOG_MESSAGES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 			if (strcmp(s, "none") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 				level_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 		case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 			level_mask |= LOG_FUNCTIONDONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) __setup("fas216_logging=", fas216_log_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	unsigned int off = reg << info->scsi.io_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	return readb(info->scsi.io_base + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	unsigned int off = reg << info->scsi.io_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	writeb(val, info->scsi.io_base + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) static void fas216_dumpstate(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	unsigned char is, stat, inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	is   = fas216_readb(info, REG_IS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	stat = fas216_readb(info, REG_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	inst = fas216_readb(info, REG_INST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	       " INST=%02X IS=%02X CFIS=%02X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 		fas216_readb(info, REG_CTCL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 		fas216_readb(info, REG_CTCM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		fas216_readb(info, REG_CMD),  stat, inst, is,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		fas216_readb(info, REG_CFIS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		fas216_readb(info, REG_CNTL1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 		fas216_readb(info, REG_CNTL2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		fas216_readb(info, REG_CNTL3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 		fas216_readb(info, REG_CTCH));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) static void print_SCp(struct scsi_pointer *SCp, const char *prefix, const char *suffix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 		prefix, SCp->ptr, SCp->this_residual, SCp->buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		SCp->buffers_residual, suffix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) #ifdef CHECK_STRUCTURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) static void fas216_dumpinfo(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	static int used = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	if (used++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	printk("FAS216_Info=\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	printk("  { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		info->magic_start, info->host, info->SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		info->origSCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	printk("    scsi={ io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 		info->scsi.io_shift, info->scsi.irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 		info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 		info->scsi.cfg[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	printk("           type=%p phase=%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 		info->scsi.type, info->scsi.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	print_SCp(&info->scsi.SCp, "           SCp={ ", " }\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	printk("      msgs async_stp=%X disconnectable=%d aborting=%d }\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		info->scsi.async_stp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 		info->scsi.disconnectable, info->scsi.aborting);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	printk("    stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	       "            disconnects=%X aborts=%X bus_resets=%X host_resets=%X}\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 		info->stats.queues, info->stats.removes, info->stats.fins,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 		info->stats.reads, info->stats.writes, info->stats.miscs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		info->stats.disconnects, info->stats.aborts, info->stats.bus_resets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		info->stats.host_resets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	printk("    ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		info->ifcfg.clockrate, info->ifcfg.select_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 		info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 		printk("    busyluns[%d]=%08lx dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 			i, info->busyluns[i], i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 			info->device[i].disconnect_ok, info->device[i].stp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 			info->device[i].sof, info->device[i].sync_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	printk("    dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 		info->dma.transfer_type, info->dma.setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 		info->dma.pseudo, info->dma.stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	printk("    internal_done=%X magic_end=%lX }\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 		info->internal_done, info->magic_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) static void __fas216_checkmagic(FAS216_Info *info, const char *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	int corruption = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	if (info->magic_start != MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 		corruption++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	if (info->magic_end != MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		corruption++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	if (corruption) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 		fas216_dumpinfo(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 		panic("scsi memory space corrupted in %s", func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) #define fas216_checkmagic(info) __fas216_checkmagic((info), __func__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) #define fas216_checkmagic(info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) static const char *fas216_bus_phase(int stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	static const char *phases[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 		"DATA OUT", "DATA IN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 		"COMMAND", "STATUS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 		"MISC OUT", "MISC IN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 		"MESG OUT", "MESG IN"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	return phases[stat & STAT_BUSMASK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) static const char *fas216_drv_phase(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	static const char *phases[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 		[PHASE_IDLE]		= "idle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 		[PHASE_SELECTION]	= "selection",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 		[PHASE_COMMAND]		= "command",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 		[PHASE_DATAOUT]		= "data out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		[PHASE_DATAIN]		= "data in",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 		[PHASE_MSGIN]		= "message in",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		[PHASE_MSGIN_DISCONNECT]= "disconnect",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		[PHASE_MSGOUT_EXPECT]	= "expect message out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 		[PHASE_MSGOUT]		= "message out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		[PHASE_STATUS]		= "status",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 		[PHASE_DONE]		= "done",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	if (info->scsi.phase < ARRAY_SIZE(phases) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	    phases[info->scsi.phase])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 		return phases[info->scsi.phase];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	return "???";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) static char fas216_target(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	if (info->SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		return '0' + info->SCpnt->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 		return 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) fas216_do_log(FAS216_Info *info, char target, char *fmt, va_list ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	static char buf[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	vsnprintf(buf, sizeof(buf), fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	printk("scsi%d.%c: %s", info->host->host_no, target, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) static void fas216_log_command(FAS216_Info *info, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 			       struct scsi_cmnd *SCpnt, char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	if (level != 0 && !(level & level_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	fas216_do_log(info, '0' + SCpnt->device->id, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	scsi_print_command(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) fas216_log_target(FAS216_Info *info, int level, int target, char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	if (level != 0 && !(level & level_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	if (target < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 		target = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		target += '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	fas216_do_log(info, target, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) static void fas216_log(FAS216_Info *info, int level, char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	if (level != 0 && !(level & level_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	fas216_do_log(info, fas216_target(info), fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) #define PH_SIZE	32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) static int ph_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) static void add_debug_list(int stat, int ssr, int isr, int ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	ph_list[ph_ptr].stat = stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	ph_list[ph_ptr].ssr = ssr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	ph_list[ph_ptr].isr = isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	ph_list[ph_ptr].ph = ph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	ph_ptr = (ph_ptr + 1) & (PH_SIZE-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) static struct { int command; void *from; } cmd_list[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) static int cmd_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) static void fas216_cmd(FAS216_Info *info, unsigned int command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	cmd_list[cmd_ptr].command = command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	cmd_list[cmd_ptr].from = __builtin_return_address(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	cmd_ptr = (cmd_ptr + 1) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	fas216_writeb(info, REG_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) static void print_debug_list(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	i = ph_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	printk(KERN_ERR "SCSI IRQ trail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		printk(" %02x:%02x:%02x:%1x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 			ph_list[i].stat, ph_list[i].ssr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 			ph_list[i].isr, ph_list[i].ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		i = (i + 1) & (PH_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		if (((i ^ ph_ptr) & 7) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 			printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	} while (i != ph_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	if ((i ^ ph_ptr) & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	i = cmd_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	printk(KERN_ERR "FAS216 commands: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		i = (i + 1) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	} while (i != cmd_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) static void fas216_done(FAS216_Info *info, unsigned int result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405)  * fas216_get_last_msg - retrive last message from the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406)  * @info: interface to search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407)  * @pos: current fifo position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409)  * Retrieve a last message from the list, using position in fifo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) static inline unsigned short
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) fas216_get_last_msg(FAS216_Info *info, int pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	unsigned short packed_msg = NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	struct message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	int msgnr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		if (pos >= msg->fifo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	if (msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		if (msg->msg[0] == EXTENDED_MESSAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 			packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 			packed_msg = msg->msg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	fas216_log(info, LOG_MESSAGES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		"Message: %04x found at position %02x\n", packed_msg, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	return packed_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437)  * fas216_syncperiod - calculate STP register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438)  * @info: state structure for interface connected to device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439)  * @ns: period in ns (between subsequent bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441)  * Calculate value to be loaded into the STP register for a given period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442)  * in ns. Returns a value suitable for REG_STP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) static int fas216_syncperiod(FAS216_Info *info, int ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	int value = (info->ifcfg.clockrate * ns) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	if (value < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		value = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	else if (value > 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		value = 35;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	return value & 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459)  * fas216_set_sync - setup FAS216 chip for specified transfer period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460)  * @info: state structure for interface connected to device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461)  * @target: target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463)  * Correctly setup FAS216 chip for specified transfer period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464)  * Notes   : we need to switch the chip out of FASTSCSI mode if we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465)  *           a transfer period >= 200ns - otherwise the chip will violate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466)  *           the SCSI timings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) static void fas216_set_sync(FAS216_Info *info, int target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	unsigned int cntl3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	fas216_writeb(info, REG_SOF, info->device[target].sof);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	fas216_writeb(info, REG_STP, info->device[target].stp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	cntl3 = info->scsi.cfg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	if (info->device[target].period >= (200 / 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		cntl3 = cntl3 & ~CNTL3_FASTSCSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	fas216_writeb(info, REG_CNTL3, cntl3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) /* Synchronous transfer support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484)  * Note: The SCSI II r10 spec says (5.6.12):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486)  *  (2)  Due to historical problems with early host adapters that could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487)  *  not accept an SDTR message, some targets may not initiate synchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488)  *  negotiation after a power cycle as required by this standard.  Host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489)  *  adapters that support synchronous mode may avoid the ensuing failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490)  *  modes when the target is independently power cycled by initiating a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)  *  synchronous negotiation on each REQUEST SENSE and INQUIRY command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492)  *  This approach increases the SCSI bus overhead and is not recommended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493)  *  for new implementations.  The correct method is to respond to an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494)  *  SDTR message with a MESSAGE REJECT message if the either the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)  *  initiator or target devices does not support synchronous transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)  *  or does not want to negotiate for synchronous transfers at the time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)  *  Using the correct method assures compatibility with wide data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  *  transfers and future enhancements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  * We will always initiate a synchronous transfer negotiation request on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  * every INQUIRY or REQUEST SENSE message, unless the target itself has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  * at some point performed a synchronous transfer negotiation request, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)  * we have synchronous transfers disabled for this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507)  * fas216_handlesync - Handle a synchronous transfer message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508)  * @info: state structure for interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509)  * @msg: message from target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511)  * Handle a synchronous transfer message from the target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) static void fas216_handlesync(FAS216_Info *info, char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	struct fas216_device *dev = &info->device[info->SCpnt->device->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	enum { sync, async, none, reject } res = none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) #ifdef SCSI2_SYNC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	switch (msg[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	case MESSAGE_REJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		/* Synchronous transfer request failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		 * Note: SCSI II r10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		 *  SCSI devices that are capable of synchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 		 *  data transfers shall not respond to an SDTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		 *  message with a MESSAGE REJECT message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		 * Hence, if we get this condition, we disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		 * negotiation for this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		if (dev->sync_state == neg_inprogress) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 			dev->sync_state = neg_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 			res = async;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	case EXTENDED_MESSAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		switch (dev->sync_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		/* We don't accept synchronous transfer requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		 * Respond with a MESSAGE_REJECT to prevent a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		 * synchronous transfer agreement from being reached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		case neg_invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 			res = reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		/* We were not negotiating a synchronous transfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		 * but the device sent us a negotiation request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		 * Honour the request by sending back a SDTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 		 * message containing our capability, limited by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		 * the targets capability.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 			fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 			if (msg[4] > info->ifcfg.sync_max_depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 				msg[4] = info->ifcfg.sync_max_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 			if (msg[3] < 1000 / info->ifcfg.clockrate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 				msg[3] = 1000 / info->ifcfg.clockrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 			msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 			msgqueue_addmsg(&info->scsi.msgs, 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 					EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 					msg[3], msg[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 			info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 			/* This is wrong.  The agreement is not in effect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 			 * until this message is accepted by the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 			dev->sync_state = neg_targcomplete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 			res = sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		/* We initiated the synchronous transfer negotiation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		 * and have successfully received a response from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 		 * target.  The synchronous transfer agreement has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		 * reached.  Note: if the values returned are out of our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		 * bounds, we must reject the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		case neg_inprogress:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			res = reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			if (msg[4] <= info->ifcfg.sync_max_depth &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			    msg[3] >= 1000 / info->ifcfg.clockrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 				dev->sync_state = neg_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 				res = sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	res = reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	switch (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	case sync:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		dev->period = msg[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		dev->sof    = msg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		dev->stp    = fas216_syncperiod(info, msg[3] * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		fas216_set_sync(info, info->SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	case reject:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	case async:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		dev->period = info->ifcfg.asyncperiod / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		dev->sof    = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		dev->stp    = info->scsi.async_stp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		fas216_set_sync(info, info->SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	case none:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621)  * fas216_updateptrs - update data pointers after transfer suspended/paused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622)  * @info: interface's local pointer to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623)  * @bytes_transferred: number of bytes transferred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625)  * Update data pointers after transfer suspended/paused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	struct scsi_pointer *SCp = &info->scsi.SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	BUG_ON(bytes_transferred < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	SCp->phase -= bytes_transferred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	while (bytes_transferred != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 		if (SCp->this_residual > bytes_transferred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		 * We have used up this buffer.  Move on to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		 * next buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		bytes_transferred -= SCp->this_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 		if (!next_SCp(SCp) && bytes_transferred) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 			printk(KERN_WARNING "scsi%d.%c: out of buffers\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 				info->host->host_no, '0' + info->SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	SCp->this_residual -= bytes_transferred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	if (SCp->this_residual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		SCp->ptr += bytes_transferred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		SCp->ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660)  * fas216_pio - transfer data off of/on to card using programmed IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661)  * @info: interface to transfer data to/from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662)  * @direction: direction to transfer data (DMA_OUT/DMA_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664)  * Transfer data off of/on to card using programmed IO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665)  * Notes: this is incredibly slow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) static void fas216_pio(FAS216_Info *info, fasdmadir_t direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	struct scsi_pointer *SCp = &info->scsi.SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	if (direction == DMA_OUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		fas216_writeb(info, REG_FF, get_next_SCp_byte(SCp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		put_next_SCp_byte(SCp, fas216_readb(info, REG_FF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	if (SCp->this_residual == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		next_SCp(SCp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) static void fas216_set_stc(FAS216_Info *info, unsigned int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	fas216_writeb(info, REG_STCL, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	fas216_writeb(info, REG_STCM, length >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	fas216_writeb(info, REG_STCH, length >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) static unsigned int fas216_get_ctc(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	return fas216_readb(info, REG_CTCL) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	       (fas216_readb(info, REG_CTCM) << 8) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	       (fas216_readb(info, REG_CTCH) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697)  * fas216_cleanuptransfer - clean up after a transfer has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698)  * @info: interface to clean up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700)  * Update the data pointers according to the number of bytes transferred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701)  * on the SCSI bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) static void fas216_cleanuptransfer(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	unsigned long total, residual, fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	fasdmatype_t dmatype = info->dma.transfer_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	info->dma.transfer_type = fasdma_none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	 * PIO transfers do not need to be cleaned up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	if (dmatype == fasdma_pio || dmatype == fasdma_none)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	if (dmatype == fasdma_real_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		total = info->scsi.SCp.phase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		total = info->scsi.SCp.this_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	residual = fas216_get_ctc(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	fas216_log(info, LOG_BUFFER, "cleaning up from previous "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		   "transfer: length 0x%06x, residual 0x%x, fifo %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		   total, residual, fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	 * If we were performing Data-Out, the transfer counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	 * counts down each time a byte is transferred by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	 * host to the FIFO.  This means we must include the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	 * bytes left in the FIFO from the transfer counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	if (info->scsi.phase == PHASE_DATAOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		residual += fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	fas216_updateptrs(info, total - residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742)  * fas216_transfer - Perform a DMA/PIO transfer off of/on to card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743)  * @info: interface from which device disconnected from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745)  * Start a DMA/PIO transfer off of/on to card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) static void fas216_transfer(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	fasdmadir_t direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	fasdmatype_t dmatype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	fas216_log(info, LOG_BUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		   "starttransfer: buffer %p length 0x%06x reqlen 0x%06x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		   info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 		   info->scsi.SCp.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	if (!info->scsi.SCp.ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		fas216_log(info, LOG_ERROR, "null buffer passed to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 			   "fas216_starttransfer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		print_SCp(&info->scsi.SCp, "SCp: ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		print_SCp(&info->SCpnt->SCp, "Cmnd SCp: ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	 * If we have a synchronous transfer agreement in effect, we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	 * use DMA mode.  If we are using asynchronous transfers, we may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	 * use DMA mode or PIO mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	if (info->device[info->SCpnt->device->id].sof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		dmatype = fasdma_real_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 		dmatype = fasdma_pio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	if (info->scsi.phase == PHASE_DATAOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		direction = DMA_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 		direction = DMA_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	if (info->dma.setup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		dmatype = info->dma.setup(info->host, &info->scsi.SCp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 					  direction, dmatype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	info->dma.transfer_type = dmatype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	if (dmatype == fasdma_real_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		fas216_set_stc(info, info->scsi.SCp.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		fas216_set_stc(info, info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	switch (dmatype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	case fasdma_pio:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		fas216_log(info, LOG_BUFFER, "PIO transfer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		fas216_writeb(info, REG_SOF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		fas216_writeb(info, REG_STP, info->scsi.async_stp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		fas216_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 		fas216_pio(info, direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	case fasdma_pseudo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		fas216_log(info, LOG_BUFFER, "pseudo transfer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 		fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		info->dma.pseudo(info->host, &info->scsi.SCp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 				 direction, info->SCpnt->transfersize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	case fasdma_real_block:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		fas216_log(info, LOG_BUFFER, "block dma transfer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	case fasdma_real_all:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 		fas216_log(info, LOG_BUFFER, "total dma transfer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 		fas216_log(info, LOG_BUFFER | LOG_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 			   "invalid FAS216 DMA type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824)  * fas216_stoptransfer - Stop a DMA transfer onto / off of the card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825)  * @info: interface from which device disconnected from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827)  * Called when we switch away from DATA IN or DATA OUT phases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) static void fas216_stoptransfer(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	if (info->dma.transfer_type == fasdma_real_all ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	    info->dma.transfer_type == fasdma_real_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		info->dma.stop(info->host, &info->scsi.SCp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	fas216_cleanuptransfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	if (info->scsi.phase == PHASE_DATAIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		unsigned int fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		 * If we were performing Data-In, then the FIFO counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		 * contains the number of bytes not transferred via DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		 * from the on-board FIFO.  Read them manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		while (fifo && info->scsi.SCp.ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 			*info->scsi.SCp.ptr = fas216_readb(info, REG_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 			fas216_updateptrs(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			fifo--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		 * After a Data-Out phase, there may be unsent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 		 * bytes left in the FIFO.  Flush them out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) static void fas216_aborttransfer(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	if (info->dma.transfer_type == fasdma_real_all ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	    info->dma.transfer_type == fasdma_real_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 		info->dma.stop(info->host, &info->scsi.SCp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	info->dma.transfer_type = fasdma_none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) static void fas216_kick(FAS216_Info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877)  * fas216_disconnected_intr - handle device disconnection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878)  * @info: interface from which device disconnected from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880)  * Handle device disconnection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) static void fas216_disconnect_intr(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	fas216_log(info, LOG_CONNECT, "disconnect phase=%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		   info->scsi.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	switch (info->scsi.phase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	case PHASE_SELECTION:			/* while selecting - no target		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	case PHASE_SELSTEPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 		fas216_done(info, DID_NO_CONNECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	case PHASE_MSGIN_DISCONNECT:		/* message in - disconnecting		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		info->scsi.disconnectable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		info->scsi.phase = PHASE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		info->stats.disconnects += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		spin_lock_irqsave(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		if (info->scsi.phase == PHASE_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 			fas216_kick(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		spin_unlock_irqrestore(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	case PHASE_DONE:			/* at end of command - complete		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		fas216_done(info, DID_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	case PHASE_MSGOUT:			/* message out - possible ABORT message	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 			info->scsi.aborting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 			fas216_done(info, DID_ABORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	default:				/* huh?					*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 			info->host->host_no, fas216_target(info), fas216_drv_phase(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		print_debug_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		fas216_stoptransfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		fas216_done(info, DID_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932)  * fas216_reselected_intr - start reconnection of a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933)  * @info: interface which was reselected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935)  * Start reconnection of a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) fas216_reselected_intr(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	unsigned int cfis, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	unsigned char msg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	unsigned char target, lun, tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	WARN_ON(info->scsi.phase == PHASE_SELECTION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		info->scsi.phase == PHASE_SELSTEPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	cfis = fas216_readb(info, REG_CFIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	fas216_log(info, LOG_CONNECT, "reconnect phase=%02x cfis=%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		   info->scsi.phase, cfis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	cfis &= CFIS_CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	if (cfis < 2 || cfis > 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 			info->host->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		goto bad_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	for (i = 0; i < cfis; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		msg[i] = fas216_readb(info, REG_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	if (!(msg[0] & (1 << info->host->this_id)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	    !(msg[1] & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		goto initiator_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	target = msg[0] & ~(1 << info->host->this_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	target = ffs(target) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	lun = msg[1] & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	tag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	if (cfis >= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		if (msg[2] != SIMPLE_QUEUE_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			goto initiator_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		tag = msg[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	/* set up for synchronous transfers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	fas216_writeb(info, REG_SDID, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	fas216_set_sync(info, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	fas216_log(info, LOG_CONNECT, "Reconnected: target %1x lun %1x tag %02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		   target, lun, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	if (info->scsi.disconnectable && info->SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		info->scsi.disconnectable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		if (info->SCpnt->device->id  == target &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		    info->SCpnt->device->lun == lun &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		    info->SCpnt->tag         == tag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 			fas216_log(info, LOG_CONNECT, "reconnected previously executing command");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 			queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 			fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 			info->SCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	if (!info->SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 					target, lun, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		fas216_log(info, LOG_CONNECT, "had to get command");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	if (info->SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		 * Restore data pointer from SAVED data pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		info->scsi.SCp = info->SCpnt->SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 		fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		info->scsi.phase = PHASE_MSGIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		 * Our command structure not found - abort the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		 * command on the target.  Since we have no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		 * record of this command, we can't send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		 * an INITIATOR DETECTED ERROR message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		if (tag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 			msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 			msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		info->scsi.aborting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	fas216_cmd(info, CMD_MSGACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)  initiator_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	printk(KERN_ERR "scsi%d.H: error during reselection: bytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		info->host->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	for (i = 0; i < cfis; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 		printk(" %02x", msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)  bad_message:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	fas216_cmd(info, CMD_MSGACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	switch (message[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	case COMMAND_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		if (msglen != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		printk(KERN_ERR "scsi%d.%c: command complete with no "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 			"status in MESSAGE_IN?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 			info->host->host_no, fas216_target(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	case SAVE_POINTERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		if (msglen != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		 * Save current data pointer to SAVED data pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 		 * SCSI II standard says that we must not acknowledge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		 * this until we have really saved pointers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		 * NOTE: we DO NOT save the command nor status pointers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		 * as required by the SCSI II standard.  These always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		 * point to the start of their respective areas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		info->SCpnt->SCp = info->scsi.SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		info->SCpnt->SCp.sent_command = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 		fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 			"save data pointers: [%p, %X]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	case RESTORE_POINTERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		if (msglen != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 		 * Restore current data pointer from SAVED data pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		info->scsi.SCp = info->SCpnt->SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			"restore data pointers: [%p, 0x%x]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	case DISCONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 		if (msglen != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		info->scsi.phase = PHASE_MSGIN_DISCONNECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	case MESSAGE_REJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		if (msglen != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			fas216_handlesync(info, message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 			fas216_log(info, 0, "reject, last message 0x%04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 				fas216_get_last_msg(info, info->scsi.msgin_fifo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	case NOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	case EXTENDED_MESSAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		if (msglen < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		switch (message[2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 		case EXTENDED_SDTR:	/* Sync transfer negotiation request/reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 			fas216_handlesync(info, message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 			goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 		goto unrecognised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) unrecognised:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	fas216_log(info, 0, "unrecognised message, rejecting");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	for (i = 0; i < msglen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 		printk("%s%02X", i & 31 ? " " : "\n  ", message[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	 * Something strange seems to be happening here -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	 * I can't use SETATN since the chip gives me an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	 * invalid command interrupt when I do.  Weird.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) fas216_cmd(info, CMD_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) fas216_dumpstate(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) fas216_dumpstate(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static int fas216_wait_cmd(FAS216_Info *info, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	int tout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	fas216_cmd(info, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	for (tout = 1000; tout; tout -= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		stat = fas216_readb(info, REG_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		if (stat & (STAT_INT|STAT_PARITYERROR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	return stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) static int fas216_get_msg_byte(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	if ((stat & STAT_INT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 		goto timedout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	if ((stat & STAT_BUSMASK) != STAT_MESGIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		goto unexpected_phase_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	fas216_readb(info, REG_INST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	if ((stat & STAT_INT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		goto timedout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	if (stat & STAT_PARITYERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		goto parity_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	if ((stat & STAT_BUSMASK) != STAT_MESGIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		goto unexpected_phase_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	fas216_readb(info, REG_INST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	return fas216_readb(info, REG_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) timedout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	fas216_log(info, LOG_ERROR, "timed out waiting for message byte");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) unexpected_phase_change:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	return -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) parity_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	fas216_log(info, LOG_ERROR, "parity error during message in phase");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	return -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)  * fas216_message - handle a function done interrupt from FAS216 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)  * @info: interface which caused function done interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)  * Handle a function done interrupt from FAS216 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) static void fas216_message(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	unsigned char *message = info->scsi.message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	unsigned int msglen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	int msgbyte = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	message[0] = fas216_readb(info, REG_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	if (message[0] == EXTENDED_MESSAGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		msgbyte = fas216_get_msg_byte(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		if (msgbyte >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 			message[1] = msgbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 			for (msglen = 2; msglen < message[1] + 2; msglen++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 				msgbyte = fas216_get_msg_byte(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 				if (msgbyte >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 					message[msglen] = msgbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	if (msgbyte == -3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		goto parity_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) #ifdef DEBUG_MESSAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		printk("scsi%d.%c: message in: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 			info->host->host_no, fas216_target(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 		for (i = 0; i < msglen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 			printk("%02X ", message[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 		printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	fas216_parse_message(info, message, msglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	fas216_cmd(info, CMD_MSGACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) parity_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	fas216_cmd(info, CMD_MSGACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)  * fas216_send_command - send command after all message bytes have been sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)  * @info: interface which caused bus service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)  * Send a command to a target after all message bytes have been sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static void fas216_send_command(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	fas216_cmd(info, CMD_NOP|CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	/* load command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		fas216_writeb(info, REG_FF, info->SCpnt->cmnd[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	fas216_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	info->scsi.phase = PHASE_COMMAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)  * fas216_send_messageout - handle bus service to send a message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)  * @info: interface which caused bus service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)  * Handle bus service to send a message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)  * Note: We do not allow the device to change the data direction!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) static void fas216_send_messageout(FAS216_Info *info, int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	if (tot_msglen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		struct message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 		int msgnr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 			int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 			for (i = start; i < msg->length; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 				fas216_writeb(info, REG_FF, msg->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 			msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 			start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		fas216_writeb(info, REG_FF, NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	fas216_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 	info->scsi.phase = PHASE_MSGOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)  * fas216_busservice_intr - handle bus service interrupt from FAS216 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)  * @info: interface which caused bus service interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)  * @stat: Status register contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)  * @is: SCSI Status register contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)  * Handle a bus service interrupt from FAS216 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int is)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	fas216_log(info, LOG_BUSSERVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 		   "bus service: stat=%02x is=%02x phase=%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 		   stat, is, info->scsi.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 	switch (info->scsi.phase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	case PHASE_SELECTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 		if ((is & IS_BITS) != IS_MSGBYTESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			goto bad_is;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	case PHASE_SELSTEPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 		switch (is & IS_BITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 		case IS_SELARB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 		case IS_MSGBYTESENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 			goto bad_is;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		case IS_NOTCOMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 		case IS_EARLYPHASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 			if ((stat & STAT_BUSMASK) == STAT_MESGIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 			goto bad_is;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 		case IS_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	fas216_cmd(info, CMD_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) #define STATE(st,ph) ((ph) << 3 | (st))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	/* This table describes the legal SCSI state transitions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	 * as described by the SCSI II spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 	case STATE(STAT_DATAIN, PHASE_MSGOUT):  /* Message Out  -> Data In      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command      -> Data In      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	case STATE(STAT_DATAIN, PHASE_MSGIN):   /* Message In   -> Data In      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		info->scsi.phase = PHASE_DATAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		fas216_transfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	case STATE(STAT_DATAIN, PHASE_DATAIN):  /* Data In      -> Data In      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 	case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out     -> Data Out     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		fas216_cleanuptransfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		fas216_transfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 	case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out  -> Data Out     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command      -> Data Out     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 	case STATE(STAT_DATAOUT, PHASE_MSGIN):  /* Message In   -> Data Out     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 		fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		info->scsi.phase = PHASE_DATAOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 		fas216_transfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out     -> Status       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 	case STATE(STAT_STATUS, PHASE_DATAIN):  /* Data In      -> Status       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 		fas216_stoptransfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	case STATE(STAT_STATUS, PHASE_MSGOUT):  /* Message Out  -> Status       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	case STATE(STAT_STATUS, PHASE_COMMAND): /* Command      -> Status       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 	case STATE(STAT_STATUS, PHASE_MSGIN):   /* Message In   -> Status       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		fas216_cmd(info, CMD_INITCMDCOMPLETE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 		info->scsi.phase = PHASE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out     -> Message In   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 	case STATE(STAT_MESGIN, PHASE_DATAIN):  /* Data In      -> Message In   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		fas216_stoptransfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 	case STATE(STAT_MESGIN, PHASE_COMMAND):	/* Command	-> Message In	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 	case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 		info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 		fas216_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 		info->scsi.phase = PHASE_MSGIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 	case STATE(STAT_MESGIN, PHASE_MSGIN):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 		info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		fas216_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 	case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out  -> Command      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	case STATE(STAT_COMMAND, PHASE_MSGIN):  /* Message In   -> Command      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		fas216_send_command(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		info->scsi.phase = PHASE_COMMAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	 * Selection    -> Message Out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 	case STATE(STAT_MESGOUT, PHASE_SELECTION):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 		fas216_send_messageout(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 	 * Message Out  -> Message Out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 	case STATE(STAT_MESGOUT, PHASE_MSGOUT):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 		 * If we get another message out phase, this usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 		 * means some parity error occurred.  Resend complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		 * set of messages.  If we have more than one byte to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 		 * send, we need to assert ATN again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 		if (info->device[info->SCpnt->device->id].parity_check) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 			 * We were testing... good, the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 			 * supports parity checking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 			info->device[info->SCpnt->device->id].parity_check = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 			info->device[info->SCpnt->device->id].parity_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 			fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 		if (msgqueue_msglength(&info->scsi.msgs) > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 			fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 		/*FALLTHROUGH*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	 * Any          -> Message Out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 		fas216_send_messageout(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	/* Error recovery rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 	 *   These either attempt to abort or retry the operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 	 * TODO: we need more of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 	case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command      -> Command      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 		/* error - we've sent out all the command bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 		 * we have.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 		 * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 		 * to include the command bytes sent for this to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 		 * correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 		printk(KERN_ERR "scsi%d.%c: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 			"target trying to receive more command bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 			info->host->host_no, fas216_target(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 		fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 		fas216_set_stc(info, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 		fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 		msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 		printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 			info->host->host_no, fas216_target(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 			fas216_bus_phase(stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 		msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 		fas216_cmd(info, CMD_SETATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 		info->scsi.phase = PHASE_MSGOUT_EXPECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 		info->scsi.aborting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 		fas216_cmd(info, CMD_TRANSFERINFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		info->host->host_no, fas216_target(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 		fas216_bus_phase(stat),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 		fas216_drv_phase(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 	print_debug_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) bad_is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 	fas216_log(info, 0, "bus service at step %d?", is & IS_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	fas216_dumpstate(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 	print_debug_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 	fas216_done(info, DID_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)  * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)  * @info: interface which caused function done interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)  * @stat: Status register contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)  * @is: SCSI Status register contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)  * Handle a function done interrupt from FAS216 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int is)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	unsigned int fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 	fas216_log(info, LOG_FUNCTIONDONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 		   "function done: stat=%02x is=%02x phase=%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 		   stat, is, info->scsi.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 	switch (info->scsi.phase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 	case PHASE_STATUS:			/* status phase - read status and msg	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 		if (fifo_len != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 			fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 		 * Read status then message byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 		info->scsi.SCp.Status = fas216_readb(info, REG_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 		info->scsi.SCp.Message = fas216_readb(info, REG_FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 		info->scsi.phase = PHASE_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 		fas216_cmd(info, CMD_MSGACCEPTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 	case PHASE_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 	case PHASE_SELECTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 	case PHASE_SELSTEPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 	case PHASE_MSGIN:			/* message in phase			*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 		if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 			info->scsi.msgin_fifo = fifo_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 			fas216_message(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 		fas216_log(info, 0, "internal phase %s for function done?"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 			"  What do I do with this?",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 			fas216_target(info), fas216_drv_phase(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) static void fas216_bus_reset(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 	neg_t sync_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	sync_state = neg_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) #ifdef SCSI2_SYNC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 		sync_state = neg_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	info->scsi.phase = PHASE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	info->SCpnt = NULL; /* bug! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	memset(&info->scsi.SCp, 0, sizeof(info->scsi.SCp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 		info->device[i].disconnect_ok	= info->ifcfg.disconnect_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 		info->device[i].sync_state	= sync_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 		info->device[i].period		= info->ifcfg.asyncperiod / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 		info->device[i].stp		= info->scsi.async_stp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 		info->device[i].sof		= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 		info->device[i].wide_xfer	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	info->rst_bus_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 	wake_up(&info->eh_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)  * fas216_intr - handle interrupts to progress a command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)  * @info: interface to service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)  * Handle interrupts from the interface to progress a command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) irqreturn_t fas216_intr(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 	unsigned char inst, is, stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 	int handled = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	stat = fas216_readb(info, REG_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	is = fas216_readb(info, REG_IS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 	inst = fas216_readb(info, REG_INST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	add_debug_list(stat, is, inst, info->scsi.phase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 	if (stat & STAT_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 		if (inst & INST_BUSRESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 			fas216_log(info, 0, "bus reset detected");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 			fas216_bus_reset(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 			scsi_report_bus_reset(info->host, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 		} else if (inst & INST_ILLEGALCMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 			fas216_log(info, LOG_ERROR, "illegal command given\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 			fas216_dumpstate(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 			print_debug_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 		} else if (inst & INST_DISCONNECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 			fas216_disconnect_intr(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 		else if (inst & INST_RESELECTED)	/* reselected			*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 			fas216_reselected_intr(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 		else if (inst & INST_BUSSERVICE)	/* bus service request		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 			fas216_busservice_intr(info, stat, is);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 		else if (inst & INST_FUNCDONE)		/* function done		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 			fas216_funcdone_intr(info, stat, is);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 		    	fas216_log(info, 0, "unknown interrupt received:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 				" phase %s inst %02X is %02X stat %02X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 				fas216_drv_phase(info), inst, is, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 		handled = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	return handled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) static void __fas216_start_command(FAS216_Info *info, struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 	int tot_msglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 	/* following what the ESP driver says */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	fas216_set_stc(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 	fas216_cmd(info, CMD_NOP | CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 	/* flush FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 	fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 	/* load bus-id and timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 	fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 	fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 	/* synchronous transfers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 	fas216_set_sync(info, SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 	tot_msglen = msgqueue_msglength(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) #ifdef DEBUG_MESSAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 		struct message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 		int msgnr = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 		printk("scsi%d.%c: message out: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 			info->host->host_no, '0' + SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 			printk("{ ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 			for (i = 0; i < msg->length; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 				printk("%02x ", msg->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 			printk("} ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 		printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 	if (tot_msglen == 1 || tot_msglen == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 		 * We have an easy message length to send...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 		struct message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 		int msgnr = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 		info->scsi.phase = PHASE_SELSTEPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 		/* load message bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 			for (i = 0; i < msg->length; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 				fas216_writeb(info, REG_FF, msg->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 			msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 		/* load command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 		for (i = 0; i < SCpnt->cmd_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 			fas216_writeb(info, REG_FF, SCpnt->cmnd[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 		if (tot_msglen == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 			fas216_cmd(info, CMD_SELECTATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 			fas216_cmd(info, CMD_SELECTATN3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 		 * We have an unusual number of message bytes to send.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 		 *  Load first byte into fifo, and issue SELECT with ATN and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 		 *  stop steps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 		struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 		fas216_writeb(info, REG_FF, msg->msg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 		msg->fifo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 		fas216_cmd(info, CMD_SELECTATNSTOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)  * Decide whether we need to perform a parity test on this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)  * Can also be used to force parity error conditions during initial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)  * information transfer phase (message out) for test purposes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) static int parity_test(FAS216_Info *info, int target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 	if (target == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 		info->device[target].parity_check = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 	return info->device[target].parity_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) static void fas216_start_command(FAS216_Info *info, struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 	int disconnect_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	 * claim host busy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	info->scsi.phase = PHASE_SELECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 	info->scsi.SCp = SCpnt->SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	info->SCpnt = SCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	info->dma.transfer_type = fasdma_none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	if (parity_test(info, SCpnt->device->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 		fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 		fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	 * Don't allow request sense commands to disconnect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 	disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 			info->device[SCpnt->device->id].disconnect_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 	 * build outgoing message bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 	msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->device->lun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	 * add tag message if required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 	if (SCpnt->tag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 		msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) #ifdef SCSI2_SYNC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 		if ((info->device[SCpnt->device->id].sync_state == neg_wait ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 		     info->device[SCpnt->device->id].sync_state == neg_complete) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 		    (SCpnt->cmnd[0] == REQUEST_SENSE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 		     SCpnt->cmnd[0] == INQUIRY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 			info->device[SCpnt->device->id].sync_state = neg_inprogress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 			msgqueue_addmsg(&info->scsi.msgs, 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 					EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 					1000 / info->ifcfg.clockrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 					info->ifcfg.sync_max_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 	} while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 	__fas216_start_command(info, SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) static void fas216_allocate_tag(FAS216_Info *info, struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) #ifdef SCSI2_TAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 	 * tagged queuing - allocate a new tag to this command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 	if (SCpnt->device->simple_tags && SCpnt->cmnd[0] != REQUEST_SENSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 	    SCpnt->cmnd[0] != INQUIRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 	    SCpnt->device->current_tag += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 		if (SCpnt->device->current_tag == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 		    SCpnt->device->current_tag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 			SCpnt->tag = SCpnt->device->current_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 		set_bit(SCpnt->device->id * 8 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 			(u8)(SCpnt->device->lun & 0x7), info->busyluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 	info->stats.removes += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 	switch (SCpnt->cmnd[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 	case WRITE_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 	case WRITE_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 	case WRITE_12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 		info->stats.writes += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 	case READ_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 	case READ_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 	case READ_12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 		info->stats.reads += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 		info->stats.miscs += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) static void fas216_do_bus_device_reset(FAS216_Info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 				       struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 	struct message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 	 * claim host busy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 	info->scsi.phase = PHASE_SELECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 	info->scsi.SCp = SCpnt->SCp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 	info->SCpnt = SCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 	info->dma.transfer_type = fasdma_none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 	fas216_log(info, LOG_ERROR, "sending bus device reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 	msgqueue_flush(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 	msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 	/* following what the ESP driver says */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 	fas216_set_stc(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 	fas216_cmd(info, CMD_NOP | CMD_WITHDMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 	/* flush FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 	fas216_cmd(info, CMD_FLUSHFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 	/* load bus-id and timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 	fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 	fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 	/* synchronous transfers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 	fas216_set_sync(info, SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 	msg = msgqueue_getmsg(&info->scsi.msgs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 	fas216_writeb(info, REG_FF, BUS_DEVICE_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 	msg->fifo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 	fas216_cmd(info, CMD_SELECTATNSTOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)  * fas216_kick - kick a command to the interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)  * @info: our host interface to kick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)  * Kick a command to the interface, interface should be idle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)  * Notes: Interrupts are always disabled!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) static void fas216_kick(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) 	struct scsi_cmnd *SCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) #define TYPE_OTHER	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) #define TYPE_RESET	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) #define TYPE_QUEUE	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) 	int where_from = TYPE_OTHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 	 * Obtain the next command to process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) 		if (info->rstSCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 			SCpnt = info->rstSCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 			/* don't remove it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) 			where_from = TYPE_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) 		if (info->reqSCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) 			SCpnt = info->reqSCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 			info->reqSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) 		if (info->origSCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 			SCpnt = info->origSCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) 			info->origSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) 		/* retrieve next command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) 		if (!SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 			SCpnt = queue_remove_exclude(&info->queues.issue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) 						     info->busyluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) 			where_from = TYPE_QUEUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) 	} while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	if (!SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) 		 * no command pending, so enable reselection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) 		fas216_cmd(info, CMD_ENABLESEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) 	 * We're going to start a command, so disable reselection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) 	fas216_cmd(info, CMD_DISABLESEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) 	if (info->scsi.disconnectable && info->SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) 		fas216_log(info, LOG_CONNECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) 			"moved command for %d to disconnected queue",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) 			info->SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) 		queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) 		info->scsi.disconnectable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) 		info->SCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) 	fas216_log_command(info, LOG_CONNECT | LOG_MESSAGES, SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) 			   "starting");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) 	switch (where_from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) 	case TYPE_QUEUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) 		fas216_allocate_tag(info, SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) 	case TYPE_OTHER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) 		fas216_start_command(info, SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) 	case TYPE_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) 		fas216_do_bus_device_reset(info, SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) 	fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) 		info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) 	 * should now get either DISCONNECT or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) 	 * (FUNCTION DONE with BUS SERVICE) interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)  * Clean up from issuing a BUS DEVICE RESET message to a device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) static void fas216_devicereset_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) 				    unsigned int result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) 	fas216_log(info, LOG_ERROR, "fas216 device reset complete");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) 	info->rstSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) 	info->rst_dev_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) 	wake_up(&info->eh_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)  * fas216_rq_sns_done - Finish processing automatic request sense command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)  * @info: interface that completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)  * @SCpnt: command that completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)  * @result: driver byte of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)  * Finish processing automatic request sense command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) static void fas216_rq_sns_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) 			       unsigned int result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) 	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 		   "request sense complete, result=0x%04x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) 		   result, SCpnt->SCp.Message, SCpnt->SCp.Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 	if (result != DID_OK || SCpnt->SCp.Status != GOOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 		 * Something went wrong.  Make sure that we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 		 * have valid data in the sense buffer that could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 		 * confuse the higher levels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 		memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) //printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) //{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) 	 * Note that we don't set SCpnt->result, since that should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) 	 * reflect the status of the command that we were asked by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 	 * the upper layers to process.  This would have been set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) 	 * correctly by fas216_std_done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 	scsi_eh_restore_cmnd(SCpnt, &info->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 	SCpnt->scsi_done(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)  * fas216_std_done - finish processing of standard command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)  * @info: interface that completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)  * @SCpnt: command that completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036)  * @result: driver byte of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)  * Finish processing of standard command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) fas216_std_done(FAS216_Info *info, struct scsi_cmnd *SCpnt, unsigned int result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) 	info->stats.fins += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) 	SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) 			info->scsi.SCp.Status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) 	fas216_log_command(info, LOG_CONNECT, SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) 		"command complete, result=0x%08x", SCpnt->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 	 * If the driver detected an error, we're all done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) 	if (host_byte(SCpnt->result) != DID_OK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) 	    msg_byte(SCpnt->result) != COMMAND_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) 	 * If the command returned CHECK_CONDITION or COMMAND_TERMINATED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) 	 * status, request the sense information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) 	if (status_byte(SCpnt->result) == CHECK_CONDITION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 	    status_byte(SCpnt->result) == COMMAND_TERMINATED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) 		goto request_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) 	 * If the command did not complete with GOOD status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) 	 * we are all done here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) 	if (status_byte(SCpnt->result) != GOOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) 	 * We have successfully completed a command.  Make sure that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 	 * we do not have any buffers left to transfer.  The world
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) 	 * is not perfect, and we seem to occasionally hit this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 	 * It can be indicative of a buggy driver, target or the upper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) 	 * levels of the SCSI code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) 	if (info->scsi.SCp.ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 		switch (SCpnt->cmnd[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 		case INQUIRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 		case START_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) 		case MODE_SENSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 			scmd_printk(KERN_ERR, SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 				    "incomplete data transfer detected: res=%08X ptr=%p len=%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 				    SCpnt->result, info->scsi.SCp.ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 				    info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 			scsi_print_command(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 			set_host_byte(SCpnt, DID_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) 			goto request_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 	if (SCpnt->scsi_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 		SCpnt->scsi_done(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) 	panic("scsi%d.H: null scsi_done function in fas216_done",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 		info->host->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) request_sense:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) 	if (SCpnt->cmnd[0] == REQUEST_SENSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) 	scsi_eh_prep_cmnd(SCpnt, &info->ses, NULL, 0, ~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) 	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) 			  "requesting sense");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) 	init_SCp(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) 	SCpnt->SCp.Message = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) 	SCpnt->SCp.Status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) 	SCpnt->tag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 	SCpnt->host_scribble = (void *)fas216_rq_sns_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) 	 * Place this command into the high priority "request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) 	 * sense" slot.  This will be the very next command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) 	 * executed, unless a target connects to us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) 	if (info->reqSCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) 		printk(KERN_WARNING "scsi%d.%c: losing request command\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) 			info->host->host_no, '0' + SCpnt->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) 	info->reqSCpnt = SCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)  * fas216_done - complete processing for current command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)  * @info: interface that completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135)  * @result: driver byte of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)  * Complete processing for current command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) static void fas216_done(FAS216_Info *info, unsigned int result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 	void (*fn)(FAS216_Info *, struct scsi_cmnd *, unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) 	struct scsi_cmnd *SCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 	if (!info->SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 		goto no_command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 	SCpnt = info->SCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 	info->SCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)     	info->scsi.phase = PHASE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) 	if (info->scsi.aborting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 		fas216_log(info, 0, "uncaught abort - returning DID_ABORT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 		result = DID_ABORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) 		info->scsi.aborting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) 	 * Sanity check the completion - if we have zero bytes left
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) 	 * to transfer, we should not have a valid pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) 	if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) 		scmd_printk(KERN_INFO, SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) 			    "zero bytes left to transfer, but buffer pointer still valid: ptr=%p len=%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) 			    info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) 		info->scsi.SCp.ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) 		scsi_print_command(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) 	 * Clear down this command as completed.  If we need to request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 	 * the sense information, fas216_kick will re-assert the busy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) 	 * status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) 	info->device[SCpnt->device->id].parity_check = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 	clear_bit(SCpnt->device->id * 8 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 		  (u8)(SCpnt->device->lun & 0x7), info->busyluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) 	fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 	fn(info, SCpnt, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) 	if (info->scsi.irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 		spin_lock_irqsave(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) 		if (info->scsi.phase == PHASE_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 			fas216_kick(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 		spin_unlock_irqrestore(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) no_command:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) 	panic("scsi%d.H: null command in fas216_done",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 		info->host->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)  * fas216_queue_command - queue a command for adapter to process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)  * @SCpnt: Command to queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)  * @done: done function to call once command is complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)  * Queue a command for adapter to process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203)  * Returns: 0 on success, else error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204)  * Notes: io_request_lock is held, interrupts are disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) static int fas216_queue_command_lck(struct scsi_cmnd *SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) 			 void (*done)(struct scsi_cmnd *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) 	fas216_log_command(info, LOG_CONNECT, SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) 			   "received command (%p)", SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) 	SCpnt->scsi_done = done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) 	SCpnt->host_scribble = (void *)fas216_std_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) 	SCpnt->result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 	init_SCp(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) 	info->stats.queues += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) 	SCpnt->tag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) 	spin_lock(&info->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 	 * Add command into execute queue and let it complete under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) 	 * whatever scheme we're using.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) 	result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) 	 * If we successfully added the command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) 	 * kick the interface to get it moving.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) 	if (result == 0 && info->scsi.phase == PHASE_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) 		fas216_kick(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) 	spin_unlock(&info->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) 	fas216_log_target(info, LOG_CONNECT, -1, "queue %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) 		result ? "failure" : "success");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) DEF_SCSI_QCMD(fas216_queue_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)  * fas216_internal_done - trigger restart of a waiting thread in fas216_noqueue_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)  * @SCpnt: Command to wake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)  * Trigger restart of a waiting thread in fas216_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) static void fas216_internal_done(struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) 	info->internal_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)  * fas216_noqueue_command - process a command for the adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)  * @SCpnt: Command to queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269)  * Queue a command for adapter to process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270)  * Returns: scsi result code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)  * Notes: io_request_lock is held, interrupts are disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) static int fas216_noqueue_command_lck(struct scsi_cmnd *SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) 			   void (*done)(struct scsi_cmnd *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) 	 * We should only be using this if we don't have an interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) 	 * Provide some "incentive" to use the queueing code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) 	BUG_ON(info->scsi.irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) 	info->internal_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) 	fas216_queue_command_lck(SCpnt, fas216_internal_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) 	 * This wastes time, since we can't return until the command is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) 	 * complete. We can't sleep either since we may get re-entered!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) 	 * However, we must re-enable interrupts, or else we'll be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) 	 * waiting forever.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) 	spin_unlock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) 	while (!info->internal_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) 		 * If we don't have an IRQ, then we must poll the card for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) 		 * it's interrupt, and use that to call this driver's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) 		 * interrupt routine.  That way, we keep the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) 		 * progressing.  Maybe we can add some intelligence here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) 		 * and go to sleep if we know that the device is going
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) 		 * to be some time (eg, disconnected).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) 		if (fas216_readb(info, REG_STAT) & STAT_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) 			spin_lock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) 			fas216_intr(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) 			spin_unlock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) 	spin_lock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) 	done(SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) DEF_SCSI_QCMD(fas216_noqueue_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)  * Error handler timeout function.  Indicate that we timed out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324)  * and wake up any error handler process so it can continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) static void fas216_eh_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) 	FAS216_Info *info = from_timer(info, t, eh_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) 	fas216_log(info, LOG_ERROR, "error handling timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) 	del_timer(&info->eh_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) 	if (info->rst_bus_status == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) 		info->rst_bus_status = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) 	if (info->rst_dev_status == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) 		info->rst_dev_status = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) 	wake_up(&info->eh_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) enum res_find {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) 	res_failed,		/* not found			*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) 	res_success,		/* command on issue queue	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) 	res_hw_abort		/* command on disconnected dev	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349)  * fas216_do_abort - decide how to abort a command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350)  * @SCpnt: command to abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352)  * Decide how to abort a command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)  * Returns: abort status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) static enum res_find fas216_find_command(FAS216_Info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) 					 struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) 	enum res_find res = res_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) 	if (queue_remove_cmd(&info->queues.issue, SCpnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) 		 * The command was on the issue queue, and has not been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) 		 * issued yet.  We can remove the command from the queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) 		 * and acknowledge the abort.  Neither the device nor the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) 		 * interface know about the command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) 		printk("on issue queue ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) 		res = res_success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) 	} else if (queue_remove_cmd(&info->queues.disconnected, SCpnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) 		 * The command was on the disconnected queue.  We must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) 		 * reconnect with the device if possible, and send it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) 		 * an abort message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) 		printk("on disconnected queue ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) 		res = res_hw_abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) 	} else if (info->SCpnt == SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) 		printk("executing ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) 		switch (info->scsi.phase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) 		 * If the interface is idle, and the command is 'disconnectable',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) 		 * then it is the same as on the disconnected queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) 		case PHASE_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) 			if (info->scsi.disconnectable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) 				info->scsi.disconnectable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) 				info->SCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) 				res = res_hw_abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) 	} else if (info->origSCpnt == SCpnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) 		 * The command will be executed next, but a command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) 		 * is currently using the interface.  This is similar to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) 		 * being on the issue queue, except the busylun bit has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) 		 * been set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) 		info->origSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) 		clear_bit(SCpnt->device->id * 8 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) 			  (u8)(SCpnt->device->lun & 0x7), info->busyluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) 		printk("waiting for execution ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) 		res = res_success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) 		printk("unknown ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417)  * fas216_eh_abort - abort this command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)  * @SCpnt: command to abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420)  * Abort this command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421)  * Returns: FAILED if unable to abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)  * Notes: io_request_lock is taken, and irqs are disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) int fas216_eh_abort(struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) 	int result = FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) 	info->stats.aborts += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) 	scmd_printk(KERN_WARNING, SCpnt, "abort command\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) 	print_debug_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) 	fas216_dumpstate(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) 	switch (fas216_find_command(info, SCpnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) 	 * We found the command, and cleared it out.  Either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) 	 * the command is still known to be executing on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) 	 * target, or the busylun bit is not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) 	case res_success:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) 		scmd_printk(KERN_WARNING, SCpnt, "abort %p success\n", SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) 		result = SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) 	 * We need to reconnect to the target and send it an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) 	 * ABORT or ABORT_TAG message.  We can only do this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) 	 * if the bus is free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) 	case res_hw_abort:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) 	 * We are unable to abort the command for some reason.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) 	case res_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) 		scmd_printk(KERN_WARNING, SCpnt, "abort %p failed\n", SCpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469)  * fas216_eh_device_reset - Reset the device associated with this command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470)  * @SCpnt: command specifing device to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472)  * Reset the device associated with this command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473)  * Returns: FAILED if unable to reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)  * Notes: We won't be re-entered, so we'll only have one device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475)  * reset on the go at one time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) int fas216_eh_device_reset(struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) 	int i, res = FAILED, target = SCpnt->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) 	fas216_log(info, LOG_ERROR, "device reset for target %d", target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) 	spin_lock_irqsave(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) 		 * If we are currently connected to a device, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) 		 * it is the device we want to reset, there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) 		 * nothing we can do here.  Chances are it is stuck,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) 		 * and we need a bus reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) 		if (info->SCpnt && !info->scsi.disconnectable &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) 		    info->SCpnt->device->id == SCpnt->device->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) 		 * We're going to be resetting this device.  Remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) 		 * all pending commands from the driver.  By doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) 		 * so, we guarantee that we won't touch the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) 		 * structures except to process the reset request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) 		queue_remove_all_target(&info->queues.issue, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) 		queue_remove_all_target(&info->queues.disconnected, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) 		if (info->origSCpnt && info->origSCpnt->device->id == target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) 			info->origSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) 		if (info->reqSCpnt && info->reqSCpnt->device->id == target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) 			info->reqSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) 		for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) 			clear_bit(target * 8 + i, info->busyluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) 		 * Hijack this SCSI command structure to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) 		 * a bus device reset message to this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) 		SCpnt->host_scribble = (void *)fas216_devicereset_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) 		info->rst_dev_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) 		info->rstSCpnt = SCpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) 		if (info->scsi.phase == PHASE_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) 			fas216_kick(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) 		mod_timer(&info->eh_timer, jiffies + 30 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) 		spin_unlock_irqrestore(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) 		 * Wait up to 30 seconds for the reset to complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) 		wait_event(info->eh_wait, info->rst_dev_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) 		del_timer_sync(&info->eh_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) 		spin_lock_irqsave(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) 		info->rstSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) 		if (info->rst_dev_status == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) 			res = SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) 	} while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) 	SCpnt->host_scribble = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) 	spin_unlock_irqrestore(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) 	fas216_log(info, LOG_ERROR, "device reset complete: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) 		   res == SUCCESS ? "success" : "failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551)  * fas216_eh_bus_reset - Reset the bus associated with the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552)  * @SCpnt: command specifing bus to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554)  * Reset the bus associated with the command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555)  * Returns: FAILED if unable to reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556)  * Notes: Further commands are blocked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) 	struct scsi_device *SDpnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) 	fas216_log(info, LOG_ERROR, "resetting bus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) 	info->stats.bus_resets += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) 	spin_lock_irqsave(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) 	 * Stop all activity on this interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) 	fas216_aborttransfer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) 	fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 	 * Clear any pending interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) 	while (fas216_readb(info, REG_STAT) & STAT_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) 		fas216_readb(info, REG_INST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) 	info->rst_bus_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) 	 * For each attached hard-reset device, clear out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) 	 * all command structures.  Leave the running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) 	 * command in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) 	shost_for_each_device(SDpnt, info->host) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) 		if (SDpnt->soft_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) 		queue_remove_all_target(&info->queues.issue, SDpnt->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) 		queue_remove_all_target(&info->queues.disconnected, SDpnt->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) 		if (info->origSCpnt && info->origSCpnt->device->id == SDpnt->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) 			info->origSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) 		if (info->reqSCpnt && info->reqSCpnt->device->id == SDpnt->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) 			info->reqSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) 		info->SCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) 		for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) 			clear_bit(SDpnt->id * 8 + i, info->busyluns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) 	info->scsi.phase = PHASE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) 	 * Reset the SCSI bus.  Device cleanup happens in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) 	 * the interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) 	fas216_cmd(info, CMD_RESETSCSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) 	mod_timer(&info->eh_timer, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) 	spin_unlock_irqrestore(&info->host_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) 	 * Wait one second for the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) 	wait_event(info->eh_wait, info->rst_bus_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) 	del_timer_sync(&info->eh_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) 	fas216_log(info, LOG_ERROR, "bus reset complete: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) 		   info->rst_bus_status == 1 ? "success" : "failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) 	return info->rst_bus_status == 1 ? SUCCESS : FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632)  * fas216_init_chip - Initialise FAS216 state after reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633)  * @info: state structure for interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)  * Initialise FAS216 state after reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) static void fas216_init_chip(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) 	unsigned int clock = ((info->ifcfg.clockrate - 1) / 5 + 1) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) 	fas216_writeb(info, REG_CLKF, clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) 	fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) 	fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) 	fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) 	fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) 	fas216_writeb(info, REG_SOF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) 	fas216_writeb(info, REG_STP, info->scsi.async_stp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) 	fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651)  * fas216_eh_host_reset - Reset the host associated with this command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652)  * @SCpnt: command specifing host to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)  * Reset the host associated with this command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655)  * Returns: FAILED if unable to reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656)  * Notes: io_request_lock is taken, and irqs are disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) 	spin_lock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) 	fas216_log(info, LOG_ERROR, "resetting host");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) 	 * Reset the SCSI chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) 	fas216_cmd(info, CMD_RESETCHIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) 	 * Ugly ugly ugly!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) 	 * We need to release the host_lock and enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) 	 * IRQs if we sleep, but we must relock and disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) 	 * IRQs after the sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) 	spin_unlock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) 	msleep(50 * 1000/100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) 	spin_lock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) 	 * Release the SCSI reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) 	fas216_cmd(info, CMD_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) 	fas216_init_chip(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) 	spin_unlock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) 	return SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) #define TYPE_UNKNOWN	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) #define TYPE_NCR53C90	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) #define TYPE_NCR53C90A	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) #define TYPE_NCR53C9x	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) #define TYPE_Am53CF94	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) #define TYPE_EmFAS216	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) #define TYPE_QLFAS216	6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) static char *chip_types[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) 	"unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) 	"NS NCR53C90",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) 	"NS NCR53C90A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) 	"NS NCR53C9x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) 	"AMD Am53CF94",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) 	"Emulex FAS216",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) 	"QLogic FAS216"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) static int fas216_detect_type(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) 	int family, rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) 	 * Reset the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) 	fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) 	udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) 	fas216_writeb(info, REG_CMD, CMD_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) 	 * Check to see if control reg 2 is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) 	fas216_writeb(info, REG_CNTL3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) 	fas216_writeb(info, REG_CNTL2, CNTL2_S2FE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) 	 * If we are unable to read back control reg 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) 	 * correctly, it is not present, and we have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) 	 * NCR53C90.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) 	if ((fas216_readb(info, REG_CNTL2) & (~0xe0)) != CNTL2_S2FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) 		return TYPE_NCR53C90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) 	 * Now, check control register 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) 	fas216_writeb(info, REG_CNTL2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) 	fas216_writeb(info, REG_CNTL3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) 	fas216_writeb(info, REG_CNTL3, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) 	 * If we are unable to read the register back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) 	 * correctly, we have a NCR53C90A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) 	if (fas216_readb(info, REG_CNTL3) != 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) 		return TYPE_NCR53C90A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) 	 * Now read the ID from the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) 	fas216_writeb(info, REG_CNTL3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) 	fas216_writeb(info, REG_CNTL3, CNTL3_ADIDCHK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) 	fas216_writeb(info, REG_CNTL3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) 	fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) 	udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) 	fas216_writeb(info, REG_CMD, CMD_WITHDMA | CMD_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) 	fas216_writeb(info, REG_CNTL2, CNTL2_ENF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) 	fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) 	udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) 	fas216_writeb(info, REG_CMD, CMD_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) 	rev     = fas216_readb(info, REG_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) 	family  = rev >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) 	rev    &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) 	switch (family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) 	case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) 		if (rev == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) 			return TYPE_Am53CF94;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) 	case 0x02:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) 		switch (rev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) 			return TYPE_EmFAS216;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) 		case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) 			return TYPE_QLFAS216;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) 	printk("family %x rev %x\n", family, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) 	return TYPE_NCR53C9x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795)  * fas216_reset_state - Initialise driver internal state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796)  * @info: state to initialise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798)  * Initialise driver internal state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) static void fas216_reset_state(FAS216_Info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) 	fas216_bus_reset(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) 	 * Clear out all stale info in our state structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) 	memset(info->busyluns, 0, sizeof(info->busyluns));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) 	info->scsi.disconnectable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) 	info->scsi.aborting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) 	for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) 		info->device[i].parity_enabled	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) 		info->device[i].parity_check	= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) 	 * Drain all commands on disconnected queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) 	while (queue_remove(&info->queues.disconnected) != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) 	 * Remove executing commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) 	info->SCpnt     = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) 	info->reqSCpnt  = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) 	info->rstSCpnt  = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) 	info->origSCpnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835)  * fas216_init - initialise FAS/NCR/AMD SCSI structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836)  * @host: a driver-specific filled-out structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838)  * Initialise FAS/NCR/AMD SCSI structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839)  * Returns: 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) int fas216_init(struct Scsi_Host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) 	FAS216_Info *info = (FAS216_Info *)host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) 	info->magic_start    = MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) 	info->magic_end      = MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) 	info->host           = host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) 	info->scsi.cfg[0]    = host->this_id | CNTL1_PERE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) 	info->scsi.cfg[1]    = CNTL2_ENF | CNTL2_S2FE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) 	info->scsi.cfg[2]    = info->ifcfg.cntl3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) 			       CNTL3_ADIDCHK | CNTL3_QTAG | CNTL3_G2CB | CNTL3_LBTM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) 	info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) 	info->rst_dev_status = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) 	info->rst_bus_status = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) 	init_waitqueue_head(&info->eh_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) 	timer_setup(&info->eh_timer, fas216_eh_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) 	spin_lock_init(&info->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) 	memset(&info->stats, 0, sizeof(info->stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) 	msgqueue_initialise(&info->scsi.msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) 	if (!queue_initialise(&info->queues.issue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) 	if (!queue_initialise(&info->queues.disconnected)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) 		queue_free(&info->queues.issue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877)  * fas216_add - initialise FAS/NCR/AMD SCSI ic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878)  * @host: a driver-specific filled-out structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879)  * @dev: parent device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881)  * Initialise FAS/NCR/AMD SCSI ic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882)  * Returns: 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) int fas216_add(struct Scsi_Host *host, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) 	FAS216_Info *info = (FAS216_Info *)host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) 	int type, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) 	if (info->ifcfg.clockrate <= 10 || info->ifcfg.clockrate > 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) 		printk(KERN_CRIT "fas216: invalid clock rate %u MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) 			info->ifcfg.clockrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) 	fas216_reset_state(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) 	type = fas216_detect_type(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) 	info->scsi.type = chip_types[type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) 	udelay(300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) 	 * Initialise the chip correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) 	fas216_init_chip(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) 	 * Reset the SCSI bus.  We don't want to see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) 	 * the resulting reset interrupt, so mask it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) 	 * out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) 	fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_DISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) 	fas216_writeb(info, REG_CMD, CMD_RESETSCSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) 	 * scsi standard says wait 250ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) 	spin_unlock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) 	msleep(100*1000/100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) 	spin_lock_irq(info->host->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) 	fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) 	fas216_readb(info, REG_INST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) 	ret = scsi_add_host(host, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) 		fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) 		scsi_scan_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) void fas216_remove(struct Scsi_Host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) 	FAS216_Info *info = (FAS216_Info *)host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) 	fas216_checkmagic(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) 	scsi_remove_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) 	fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) 	scsi_host_put(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947)  * fas216_release - release all resources for FAS/NCR/AMD SCSI ic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948)  * @host: a driver-specific filled-out structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950)  * release all resources and put everything to bed for FAS/NCR/AMD SCSI ic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) void fas216_release(struct Scsi_Host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) 	FAS216_Info *info = (FAS216_Info *)host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) 	queue_free(&info->queues.disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) 	queue_free(&info->queues.issue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) void fas216_print_host(FAS216_Info *info, struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) 	seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) 			"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) 			"Chip    : %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) 			" Address: 0x%p\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) 			" IRQ    : %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) 			" DMA    : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) 			info->scsi.type, info->scsi.io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) 			info->scsi.irq, info->scsi.dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) void fas216_print_stats(FAS216_Info *info, struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) 	seq_printf(m, "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) 			"Command Statistics:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) 			" Queued     : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) 			" Issued     : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) 			" Completed  : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) 			" Reads      : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) 			" Writes     : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) 			" Others     : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) 			" Disconnects: %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) 			" Aborts     : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) 			" Bus resets : %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) 			" Host resets: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) 			info->stats.queues,	 info->stats.removes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) 			info->stats.fins,	 info->stats.reads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) 			info->stats.writes,	 info->stats.miscs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) 			info->stats.disconnects, info->stats.aborts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) 			info->stats.bus_resets,	 info->stats.host_resets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) void fas216_print_devices(FAS216_Info *info, struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) 	struct fas216_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) 	struct scsi_device *scd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) 	seq_puts(m, "Device/Lun TaggedQ       Parity   Sync\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) 	shost_for_each_device(scd, info->host) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) 		dev = &info->device[scd->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) 		seq_printf(m, "     %d/%llu   ", scd->id, scd->lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) 		if (scd->tagged_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) 			seq_printf(m, "%3sabled(%3d) ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) 				     scd->simple_tags ? "en" : "dis",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) 				     scd->current_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) 			seq_puts(m, "unsupported   ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) 		seq_printf(m, "%3sabled ", dev->parity_enabled ? "en" : "dis");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) 		if (dev->sof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) 			seq_printf(m, "offset %d, %d ns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) 				     dev->sof, dev->period * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) 			seq_puts(m, "async\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) EXPORT_SYMBOL(fas216_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) EXPORT_SYMBOL(fas216_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) EXPORT_SYMBOL(fas216_queue_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) EXPORT_SYMBOL(fas216_noqueue_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) EXPORT_SYMBOL(fas216_intr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) EXPORT_SYMBOL(fas216_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) EXPORT_SYMBOL(fas216_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) EXPORT_SYMBOL(fas216_eh_abort);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) EXPORT_SYMBOL(fas216_eh_device_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) EXPORT_SYMBOL(fas216_eh_bus_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) EXPORT_SYMBOL(fas216_eh_host_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) EXPORT_SYMBOL(fas216_print_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) EXPORT_SYMBOL(fas216_print_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) EXPORT_SYMBOL(fas216_print_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) MODULE_AUTHOR("Russell King");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) MODULE_LICENSE("GPL");