^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");