|
|
1.1 ! root 1: #include <linux/config.h> ! 2: #include <linux/delay.h> ! 3: #include <linux/signal.h> ! 4: #include <linux/sched.h> ! 5: #include <linux/errno.h> ! 6: #include <linux/bios32.h> ! 7: #include <linux/pci.h> ! 8: #include <linux/string.h> ! 9: #include <linux/blk.h> ! 10: ! 11: #include <asm/io.h> ! 12: #include <asm/system.h> ! 13: ! 14: #include "scsi.h" ! 15: #include "hosts.h" ! 16: #include "AM53C974.h" ! 17: #include "constants.h" ! 18: #include "sd.h" ! 19: ! 20: /* AM53/79C974 (PCscsi) driver release 0.5 ! 21: * ! 22: * The architecture and much of the code of this device ! 23: * driver was originally developed by Drew Eckhardt for ! 24: * the NCR5380. The following copyrights apply: ! 25: * For the architecture and all pieces of code which can also be found ! 26: * in the NCR5380 device driver: ! 27: * Copyright 1993, Drew Eckhardt ! 28: * Visionary Computing ! 29: * (Unix and Linux consulting and custom programming) ! 30: * [email protected] ! 31: * +1 (303) 666-5836 ! 32: * ! 33: * The AM53C974_nobios_detect code was origininally developed by ! 34: * Robin Cutshaw ([email protected]) and is used here in a ! 35: * slightly modified form. ! 36: * ! 37: * For the remaining code: ! 38: * Copyright 1994, D. Frieauff ! 39: * EMail: [email protected] ! 40: * Phone: x49-7545-8-2256 , x49-7541-42305 ! 41: */ ! 42: ! 43: /* ! 44: * $Log: AM53C974.c,v $ ! 45: * Revision 1.1.1.1 1997/02/25 21:27:44 thomas ! 46: * Initial source ! 47: * ! 48: * Revision 1.1.1.1 1996/10/30 01:39:58 thomas ! 49: * Imported from UK22 ! 50: * ! 51: * Revision 1.1 1996/03/25 20:25:05 goel ! 52: * Linux driver merge. ! 53: * ! 54: */ ! 55: ! 56: #ifdef AM53C974_DEBUG ! 57: #define DEB(x) x ! 58: #ifdef AM53C974_DEBUG_KEYWAIT ! 59: #define KEYWAIT() AM53C974_keywait() ! 60: #else ! 61: #define KEYWAIT() ! 62: #endif ! 63: #ifdef AM53C974_DEBUG_INIT ! 64: #define DEB_INIT(x) x ! 65: #else ! 66: #define DEB_INIT(x) ! 67: #endif ! 68: #ifdef AM53C974_DEBUG_MSG ! 69: #define DEB_MSG(x) x ! 70: #else ! 71: #define DEB_MSG(x) ! 72: #endif ! 73: #ifdef AM53C974_DEB_RESEL ! 74: #define DEB_RESEL(x) x ! 75: #else ! 76: #define DEB_RESEL(x) ! 77: #endif ! 78: #ifdef AM53C974_DEBUG_QUEUE ! 79: #define DEB_QUEUE(x) x ! 80: #define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } ! 81: #define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); } ! 82: #else ! 83: #define DEB_QUEUE(x) ! 84: #define LIST(x,y) ! 85: #define REMOVE(w,x,y,z) ! 86: #endif ! 87: #ifdef AM53C974_DEBUG_INFO ! 88: #define DEB_INFO(x) x ! 89: #else ! 90: #define DEB_INFO(x) ! 91: #endif ! 92: #ifdef AM53C974_DEBUG_LINKED ! 93: #define DEB_LINKED(x) x ! 94: #else ! 95: #define DEB_LINKED(x) ! 96: #endif ! 97: #ifdef AM53C974_DEBUG_INTR ! 98: #define DEB_INTR(x) x ! 99: #else ! 100: #define DEB_INTR(x) ! 101: #endif ! 102: #else ! 103: #define DEB_INIT(x) ! 104: #define DEB(x) ! 105: #define DEB_QUEUE(x) ! 106: #define LIST(x,y) ! 107: #define REMOVE(w,x,y,z) ! 108: #define DEB_INFO(x) ! 109: #define DEB_LINKED(x) ! 110: #define DEB_INTR(x) ! 111: #define DEB_MSG(x) ! 112: #define DEB_RESEL(x) ! 113: #define KEYWAIT() ! 114: #endif ! 115: #ifdef AM53C974_DEBUG_ABORT ! 116: #define DEB_ABORT(x) x ! 117: #else ! 118: #define DEB_ABORT(x) ! 119: #endif ! 120: ! 121: #ifdef VERBOSE_AM53C974_DEBUG ! 122: #define VDEB(x) x ! 123: #else ! 124: #define VDEB(x) ! 125: #endif ! 126: ! 127: #define INSIDE(x,l,h) ( ((x) >= (l)) && ((x) <= (h)) ) ! 128: ! 129: #ifdef AM53C974_DEBUG ! 130: static void AM53C974_print_pci(struct Scsi_Host *instance); ! 131: static void AM53C974_print_phase(struct Scsi_Host *instance); ! 132: static void AM53C974_print_queues(struct Scsi_Host *instance); ! 133: #endif /* AM53C974_DEBUG */ ! 134: static void AM53C974_print(struct Scsi_Host *instance); ! 135: static void AM53C974_keywait(void); ! 136: static int AM53C974_bios_detect(Scsi_Host_Template *tpnt); ! 137: static int AM53C974_nobios_detect(Scsi_Host_Template *tpnt); ! 138: static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config); ! 139: static void AM53C974_config_after_reset(struct Scsi_Host *instance); ! 140: static __inline__ void initialize_SCp(Scsi_Cmnd *cmd); ! 141: static __inline__ void run_main(void); ! 142: static void AM53C974_main (void); ! 143: static void AM53C974_intr(int irq, struct pt_regs *regs); ! 144: static void AM53C974_intr_disconnect(struct Scsi_Host *instance); ! 145: static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg); ! 146: static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target); ! 147: static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target); ! 148: static void AM53C974_information_transfer(struct Scsi_Host *instance, ! 149: unsigned char statreg, unsigned char isreg, ! 150: unsigned char instreg, unsigned char cfifo, ! 151: unsigned char dmastatus); ! 152: static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd, unsigned char msg); ! 153: static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag); ! 154: static void AM53C974_intr_reselect(struct Scsi_Host *instance, unsigned char statreg); ! 155: static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, ! 156: unsigned long length, char *data); ! 157: static void AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, ! 158: unsigned char statreg); ! 159: static void AM53C974_intr_bus_reset(struct Scsi_Host *instance); ! 160: ! 161: static struct Scsi_Host *first_instance = NULL; ! 162: static Scsi_Host_Template *the_template = NULL; ! 163: static struct Scsi_Host *first_host = NULL; /* Head of list of AMD boards */ ! 164: static volatile int main_running = 0; ! 165: static int commandline_current = 0; ! 166: override_t overrides[7] = { {-1, 0, 0, 0}, }; /* LILO overrides */ ! 167: ! 168: #ifdef AM53C974_DEBUG ! 169: static int deb_stop = 1; ! 170: ! 171: /************************************************************************** ! 172: * Function : void AM53C974_print_pci(struct Scsi_Host *instance) ! 173: * ! 174: * Purpose : dump the PCI registers for debugging purposes ! 175: * ! 176: * Input : instance - which AM53C974 ! 177: **************************************************************************/ ! 178: static void AM53C974_print_pci(struct Scsi_Host *instance) ! 179: { ! 180: int i; ! 181: unsigned short vendor_id, device_id, command, status, scratch[8]; ! 182: unsigned long class_revision, base; ! 183: unsigned char irq, cache_line_size, latency_timer, header_type; ! 184: ! 185: AM53C974_PCIREG_OPEN(); ! 186: ! 187: for (i = 0; i < 8; i++) *(scratch + i) = AM53C974_PCIREG_READ_WORD(instance, PCI_SCRATCH_REG_0 + 2*i); ! 188: vendor_id = AM53C974_PCIREG_READ_WORD(instance, PCI_VENDOR_ID); ! 189: device_id = AM53C974_PCIREG_READ_WORD(instance, PCI_DEVICE_ID); ! 190: command = AM53C974_PCIREG_READ_WORD(instance, PCI_COMMAND); ! 191: status = AM53C974_PCIREG_READ_WORD(instance, PCI_STATUS); ! 192: class_revision = AM53C974_PCIREG_READ_DWORD(instance, PCI_CLASS_REVISION); ! 193: cache_line_size = AM53C974_PCIREG_READ_BYTE(instance, PCI_CACHE_LINE_SIZE); ! 194: latency_timer = AM53C974_PCIREG_READ_BYTE(instance, PCI_LATENCY_TIMER); ! 195: header_type = AM53C974_PCIREG_READ_BYTE(instance, PCI_HEADER_TYPE); ! 196: base = AM53C974_PCIREG_READ_DWORD(instance, PCI_BASE_ADDRESS_0); ! 197: irq = AM53C974_PCIREG_READ_BYTE(instance, PCI_INTERRUPT_LINE); ! 198: ! 199: AM53C974_PCIREG_CLOSE(); ! 200: ! 201: ! 202: printk("------------- start of PCI register dump -------------\n"); ! 203: printk("PCI_VENDOR_ID: 0x%x\n", vendor_id); ! 204: printk("PCI_DEVICE_ID: 0x%x\n", device_id); ! 205: printk("PCI_COMMAND: 0x%x\n", command); ! 206: printk("PCI_STATUS: 0x%x\n", status); ! 207: printk("PCI_CLASS_REVISION: 0x%lx\n", class_revision); ! 208: printk("PCI_CACHE_LINE_SIZE: 0x%x\n", cache_line_size); ! 209: printk("PCI_LATENCY_TIMER: 0x%x\n", latency_timer); ! 210: printk("PCI_HEADER_TYPE: 0x%x\n", header_type); ! 211: printk("PCI_BASE_ADDRESS_0: 0x%lx\n", base); ! 212: printk("PCI_INTERRUPT_LINE: %d\n", irq); ! 213: for (i = 0; i < 8; i++) printk("PCI_SCRATCH_%d: 0x%x\n", i, scratch[i]); ! 214: printk("------------- end of PCI register dump -------------\n\n"); ! 215: } ! 216: ! 217: static struct { ! 218: unsigned char value; ! 219: char *name; ! 220: } phases[] = { ! 221: {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, ! 222: {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, ! 223: {PHASE_RES_0, "RESERVED 0"}, {PHASE_RES_1, "RESERVED 1"}}; ! 224: ! 225: /************************************************************************** ! 226: * Function : void AM53C974_print_phase(struct Scsi_Host *instance) ! 227: * ! 228: * Purpose : print the current SCSI phase for debugging purposes ! 229: * ! 230: * Input : instance - which AM53C974 ! 231: **************************************************************************/ ! 232: static void AM53C974_print_phase(struct Scsi_Host *instance) ! 233: { ! 234: AM53C974_local_declare(); ! 235: unsigned char statreg, latched; ! 236: int i; ! 237: AM53C974_setio(instance); ! 238: ! 239: latched = (AM53C974_read_8(CNTLREG2)) & CNTLREG2_ENF; ! 240: statreg = AM53C974_read_8(STATREG); ! 241: for (i = 0; (phases[i].value != PHASE_RES_1) && ! 242: (phases[i].value != (statreg & STATREG_PHASE)); ++i); ! 243: if (latched) ! 244: printk("scsi%d : phase %s, latched at end of last command\n", instance->host_no, phases[i].name); ! 245: else ! 246: printk("scsi%d : phase %s, real time\n", instance->host_no, phases[i].name); ! 247: } ! 248: ! 249: /************************************************************************** ! 250: * Function : void AM53C974_print_queues(struct Scsi_Host *instance) ! 251: * ! 252: * Purpose : print commands in the various queues ! 253: * ! 254: * Inputs : instance - which AM53C974 ! 255: **************************************************************************/ ! 256: static void AM53C974_print_queues(struct Scsi_Host *instance) ! 257: { ! 258: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 259: Scsi_Cmnd *ptr; ! 260: ! 261: printk("AM53C974: coroutine is%s running.\n", main_running ? "" : "n't"); ! 262: ! 263: cli(); ! 264: ! 265: if (!hostdata->connected) { ! 266: printk ("scsi%d: no currently connected command\n", instance->host_no); } ! 267: else { ! 268: print_Scsi_Cmnd ((Scsi_Cmnd *)hostdata->connected); } ! 269: if (!hostdata->sel_cmd) { ! 270: printk ("scsi%d: no currently arbitrating command\n", instance->host_no); } ! 271: else { ! 272: print_Scsi_Cmnd ((Scsi_Cmnd *)hostdata->sel_cmd); } ! 273: ! 274: printk ("scsi%d: issue_queue ", instance->host_no); ! 275: if (!hostdata->issue_queue) ! 276: printk("empty\n"); ! 277: else { ! 278: printk(":\n"); ! 279: for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *)ptr->host_scribble) ! 280: print_Scsi_Cmnd (ptr); } ! 281: ! 282: printk ("scsi%d: disconnected_queue ", instance->host_no); ! 283: if (!hostdata->disconnected_queue) ! 284: printk("empty\n"); ! 285: else { ! 286: printk(":\n"); ! 287: for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *)ptr->host_scribble) ! 288: print_Scsi_Cmnd (ptr); } ! 289: ! 290: sti(); ! 291: } ! 292: ! 293: #endif /* AM53C974_DEBUG */ ! 294: ! 295: /************************************************************************** ! 296: * Function : void AM53C974_print(struct Scsi_Host *instance) ! 297: * ! 298: * Purpose : dump the chip registers for debugging purposes ! 299: * ! 300: * Input : instance - which AM53C974 ! 301: **************************************************************************/ ! 302: static void AM53C974_print(struct Scsi_Host *instance) ! 303: { ! 304: AM53C974_local_declare(); ! 305: unsigned long ctcreg, dmastc, dmaspa, dmawbc, dmawac; ! 306: unsigned char cmdreg, statreg, isreg, cfireg, cntlreg[4], dmacmd, dmastatus; ! 307: AM53C974_setio(instance); ! 308: ! 309: cli(); ! 310: ctcreg = AM53C974_read_8(CTCHREG) << 16; ! 311: ctcreg |= AM53C974_read_8(CTCMREG) << 8; ! 312: ctcreg |= AM53C974_read_8(CTCLREG); ! 313: cmdreg = AM53C974_read_8(CMDREG); ! 314: statreg = AM53C974_read_8(STATREG); ! 315: isreg = AM53C974_read_8(ISREG); ! 316: cfireg = AM53C974_read_8(CFIREG); ! 317: cntlreg[0] = AM53C974_read_8(CNTLREG1); ! 318: cntlreg[1] = AM53C974_read_8(CNTLREG2); ! 319: cntlreg[2] = AM53C974_read_8(CNTLREG3); ! 320: cntlreg[3] = AM53C974_read_8(CNTLREG4); ! 321: dmacmd = AM53C974_read_8(DMACMD); ! 322: dmastc = AM53C974_read_32(DMASTC); ! 323: dmaspa = AM53C974_read_32(DMASPA); ! 324: dmawbc = AM53C974_read_32(DMAWBC); ! 325: dmawac = AM53C974_read_32(DMAWAC); ! 326: dmastatus = AM53C974_read_8(DMASTATUS); ! 327: sti(); ! 328: ! 329: printk("AM53C974 register dump:\n"); ! 330: printk("IO base: 0x%04lx; CTCREG: 0x%04lx; CMDREG: 0x%02x; STATREG: 0x%02x; ISREG: 0x%02x\n", ! 331: io_port, ctcreg, cmdreg, statreg, isreg); ! 332: printk("CFIREG: 0x%02x; CNTLREG1-4: 0x%02x; 0x%02x; 0x%02x; 0x%02x\n", ! 333: cfireg, cntlreg[0], cntlreg[1], cntlreg[2], cntlreg[3]); ! 334: printk("DMACMD: 0x%02x; DMASTC: 0x%04lx; DMASPA: 0x%04lx\n", dmacmd, dmastc, dmaspa); ! 335: printk("DMAWBC: 0x%04lx; DMAWAC: 0x%04lx; DMASTATUS: 0x%02x\n", dmawbc, dmawac, dmastatus); ! 336: printk("---------------------------------------------------------\n"); ! 337: } ! 338: ! 339: /************************************************************************** ! 340: * Function : void AM53C974_keywait(void) ! 341: * ! 342: * Purpose : wait until a key is pressed, if it was the 'r' key leave singlestep mode; ! 343: * this function is used for debugging only ! 344: * ! 345: * Input : none ! 346: **************************************************************************/ ! 347: static void AM53C974_keywait(void) ! 348: { ! 349: #ifdef AM53C974_DEBUG ! 350: int key; ! 351: ! 352: if (!deb_stop) return; ! 353: #endif ! 354: ! 355: cli(); ! 356: while ((inb_p(0x64) & 0x01) != 0x01) ; ! 357: #ifdef AM53C974_DEBUG ! 358: key = inb(0x60); ! 359: if (key == 0x93) deb_stop = 0; /* don't stop if 'r' was pressed */ ! 360: #endif ! 361: sti(); ! 362: } ! 363: ! 364: /************************************************************************** ! 365: * Function : AM53C974_setup(char *str, int *ints) ! 366: * ! 367: * Purpose : LILO command line initialization of the overrides array, ! 368: * ! 369: * Inputs : str - unused, ints - array of integer parameters with ints[0] ! 370: * equal to the number of ints. ! 371: * ! 372: * NOTE : this function needs to be declared as an external function ! 373: * in init/main.c and included there in the bootsetups list ! 374: ***************************************************************************/ ! 375: void AM53C974_setup(char *str, int *ints) ! 376: { ! 377: if (ints[0] < 4) ! 378: printk("AM53C974_setup: wrong number of parameters;\n correct syntax is: AM53C974=host-scsi-id, target-scsi-id, max-rate, max-offset\n"); ! 379: else { ! 380: if (commandline_current < (sizeof(overrides) / sizeof(override_t))) { ! 381: if ((ints[1] < 0) || (ints[1] > 7) || ! 382: (ints[2] < 0) || (ints[2] > 7) || ! 383: (ints[1] == ints[2]) || ! 384: (ints[3] < (DEF_CLK / MAX_PERIOD)) || (ints[3] > (DEF_CLK / MIN_PERIOD)) || ! 385: (ints[4] < 0) || (ints[4] > MAX_OFFSET)) ! 386: printk("AM53C974_setup: illegal parameter\n"); ! 387: else { ! 388: overrides[commandline_current].host_scsi_id = ints[1]; ! 389: overrides[commandline_current].target_scsi_id = ints[2]; ! 390: overrides[commandline_current].max_rate = ints[3]; ! 391: overrides[commandline_current].max_offset = ints[4]; ! 392: commandline_current++; } ! 393: } ! 394: else ! 395: printk("AM53C974_setup: too many overrides\n"); ! 396: } ! 397: } ! 398: ! 399: #if defined (CONFIG_PCI) ! 400: /************************************************************************** ! 401: * Function : int AM53C974_bios_detect(Scsi_Host_Template *tpnt) ! 402: * ! 403: * Purpose : detects and initializes AM53C974 SCSI chips with PCI Bios ! 404: * ! 405: * Inputs : tpnt - host template ! 406: * ! 407: * Returns : number of host adapters detected ! 408: **************************************************************************/ ! 409: int AM53C974_bios_detect(Scsi_Host_Template *tpnt) ! 410: { ! 411: int count = 0; /* number of boards detected */ ! 412: int pci_index; ! 413: pci_config_t pci_config; ! 414: ! 415: for (pci_index = 0; pci_index <= 16; ++pci_index) { ! 416: unsigned char pci_bus, pci_device_fn; ! 417: if (pcibios_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pci_index, &pci_bus, &pci_device_fn) != 0) ! 418: break; ! 419: ! 420: pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &pci_config._vendor); ! 421: pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &pci_config._device); ! 422: pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_config._command); ! 423: pcibios_read_config_word(pci_bus, pci_device_fn, PCI_STATUS, &pci_config._status); ! 424: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_CLASS_REVISION, &pci_config._class_revision); ! 425: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_CACHE_LINE_SIZE, &pci_config._cache_line_size); ! 426: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_config._latency_timer); ! 427: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_HEADER_TYPE, &pci_config._header_type); ! 428: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_BIST, &pci_config._bist); ! 429: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_config._base0); ! 430: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_config._base1); ! 431: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_config._base2); ! 432: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_config._base3); ! 433: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_config._base4); ! 434: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_config._base5); ! 435: pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_ROM_ADDRESS, &pci_config._baserom); ! 436: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_config._int_line); ! 437: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_PIN, &pci_config._int_pin); ! 438: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MIN_GNT, &pci_config._min_gnt); ! 439: pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MAX_LAT, &pci_config._max_lat); ! 440: pci_config._pcibus = 0xFFFFFFFF; ! 441: pci_config._cardnum = 0xFFFFFFFF; ! 442: ! 443: /* check whether device is I/O mapped -- should be */ ! 444: if (!(pci_config._command & PCI_COMMAND_IO)) continue; ! 445: ! 446: /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility ! 447: to set the PCI Master Enable Bit if needed. ! 448: (from Mark Stockton <[email protected]>) */ ! 449: if (!(pci_config._command & PCI_COMMAND_MASTER)) { ! 450: pci_config._command |= PCI_COMMAND_MASTER; ! 451: printk("PCI Master Bit has not been set. Setting...\n"); ! 452: pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, pci_config._command); } ! 453: ! 454: /* everything seems OK now, so initialize */ ! 455: if (AM53C974_init(tpnt, pci_config)) count++ ; ! 456: } ! 457: return (count); ! 458: } ! 459: #endif ! 460: ! 461: /************************************************************************** ! 462: * Function : int AM53C974_nobios_detect(Scsi_Host_Template *tpnt) ! 463: * ! 464: * Purpose : detects and initializes AM53C974 SCSI chips using PCI config 2 ! 465: * ! 466: * Inputs : tpnt - host template ! 467: * ! 468: * Returns : number of host adapters detected ! 469: * ! 470: * NOTE : This code assumes the controller on PCI bus 0. ! 471: * ! 472: * Origin: Robin Cutshaw ([email protected]) ! 473: **************************************************************************/ ! 474: int AM53C974_nobios_detect(Scsi_Host_Template *tpnt) ! 475: { ! 476: int count = 0; /* number of boards detected */ ! 477: pci_config_t pci_config; ! 478: ! 479: /* first try PCI config method 1 */ ! 480: for (pci_config._pcibus = 0; pci_config._pcibus < 0x10; pci_config._pcibus++) { ! 481: for (pci_config._cardnum = 0; pci_config._cardnum < 0x20; pci_config._cardnum++) { ! 482: unsigned long config_cmd; ! 483: config_cmd = 0x80000000 | (pci_config._pcibus<<16) | (pci_config._cardnum<<11); ! 484: ! 485: outl(config_cmd, 0xCF8); /* ioreg 0 */ ! 486: pci_config._device_vendor = inl(0xCFC); ! 487: ! 488: if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) { ! 489: outl(config_cmd | PCI_COMMAND, 0xCF8); pci_config._status_command = inl(0xCFC); ! 490: outl(config_cmd | PCI_CLASS_REVISION, 0xCF8); pci_config._class_revision = inl(0xCFC); ! 491: outl(config_cmd | PCI_CACHE_LINE_SIZE, 0xCF8); pci_config._bist_header_latency_cache = inl(0xCFC); ! 492: outl(config_cmd | PCI_BASE_ADDRESS_0, 0xCF8); pci_config._base0 = inl(0xCFC); ! 493: outl(config_cmd | PCI_BASE_ADDRESS_1, 0xCF8); pci_config._base1 = inl(0xCFC); ! 494: outl(config_cmd | PCI_BASE_ADDRESS_2, 0xCF8); pci_config._base2 = inl(0xCFC); ! 495: outl(config_cmd | PCI_BASE_ADDRESS_3, 0xCF8); pci_config._base3 = inl(0xCFC); ! 496: outl(config_cmd | PCI_BASE_ADDRESS_4, 0xCF8); pci_config._base4 = inl(0xCFC); ! 497: outl(config_cmd | PCI_BASE_ADDRESS_5, 0xCF8); pci_config._base5 = inl(0xCFC); ! 498: outl(config_cmd | PCI_ROM_ADDRESS, 0xCF8); pci_config._baserom = inl(0xCFC); ! 499: outl(config_cmd | PCI_INTERRUPT_LINE, 0xCF8); pci_config._max_min_ipin_iline = inl(0xCFC); ! 500: ! 501: /* check whether device is I/O mapped -- should be */ ! 502: if (!(pci_config._command & PCI_COMMAND_IO)) continue; ! 503: ! 504: /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility ! 505: to set the PCI Master Enable Bit if needed. ! 506: From Mark Stockton <[email protected]> */ ! 507: if (!(pci_config._command & PCI_COMMAND_MASTER)) { ! 508: pci_config._command |= PCI_COMMAND_MASTER; ! 509: printk("Config 1; PCI Master Bit has not been set. Setting...\n"); ! 510: outl(config_cmd | PCI_COMMAND, 0xCF8); outw(pci_config._command, 0xCFC); } ! 511: ! 512: /* everything seems OK now, so initialize */ ! 513: if (AM53C974_init(tpnt, pci_config)) count++ ; ! 514: } ! 515: } ! 516: } ! 517: outb(0, 0xCF8); /* is this really necessary? */ ! 518: ! 519: /* try PCI config method 2, if no device was detected by method 1 */ ! 520: if (!count) { ! 521: AM53C974_PCIREG_OPEN(); ! 522: ! 523: pci_config._pcibus = 0xFFFFFFFF; ! 524: pci_config._cardnum = 0xFFFFFFFF; ! 525: ! 526: for (pci_config._ioaddr = 0xC000; pci_config._ioaddr < 0xD000; pci_config._ioaddr += 0x0100) { ! 527: pci_config._device_vendor = inl(pci_config._ioaddr); ! 528: ! 529: if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) { ! 530: pci_config._status_command = inl(pci_config._ioaddr + PCI_COMMAND); ! 531: pci_config._class_revision = inl(pci_config._ioaddr + PCI_CLASS_REVISION); ! 532: pci_config._bist_header_latency_cache = inl(pci_config._ioaddr + PCI_CACHE_LINE_SIZE); ! 533: pci_config._base0 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_0); ! 534: pci_config._base1 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_1); ! 535: pci_config._base2 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_2); ! 536: pci_config._base3 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_3); ! 537: pci_config._base4 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_4); ! 538: pci_config._base5 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_5); ! 539: pci_config._baserom = inl(pci_config._ioaddr + PCI_ROM_ADDRESS); ! 540: pci_config._max_min_ipin_iline = inl(pci_config._ioaddr + PCI_INTERRUPT_LINE); ! 541: ! 542: /* check whether device is I/O mapped -- should be */ ! 543: if (!(pci_config._command & PCI_COMMAND_IO)) continue; ! 544: ! 545: /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility ! 546: to set the PCI Master Enable Bit if needed. ! 547: From Mark Stockton <[email protected]> */ ! 548: if (!(pci_config._command & PCI_COMMAND_MASTER)) { ! 549: pci_config._command |= PCI_COMMAND_MASTER; ! 550: printk("Config 2; PCI Master Bit has not been set. Setting...\n"); ! 551: outw(pci_config._command, pci_config._ioaddr + PCI_COMMAND); } ! 552: ! 553: /* everything seems OK now, so initialize */ ! 554: if (AM53C974_init(tpnt, pci_config)) count++ ; ! 555: } ! 556: } ! 557: AM53C974_PCIREG_CLOSE(); ! 558: } ! 559: ! 560: return(count); ! 561: } ! 562: ! 563: /************************************************************************** ! 564: * Function : int AM53C974_detect(Scsi_Host_Template *tpnt) ! 565: * ! 566: * Purpose : detects and initializes AM53C974 SCSI chips ! 567: * ! 568: * Inputs : tpnt - host template ! 569: * ! 570: * Returns : number of host adapters detected ! 571: **************************************************************************/ ! 572: int AM53C974_detect(Scsi_Host_Template *tpnt) ! 573: { ! 574: int count; /* number of boards detected */ ! 575: ! 576: #if defined (CONFIG_PCI) ! 577: if (pcibios_present()) ! 578: count = AM53C974_bios_detect(tpnt); ! 579: else ! 580: #endif ! 581: count = AM53C974_nobios_detect(tpnt); ! 582: return (count); ! 583: } ! 584: ! 585: /************************************************************************** ! 586: * Function : int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config) ! 587: * ! 588: * Purpose : initializes instance and corresponding AM53/79C974 chip, ! 589: * ! 590: * Inputs : tpnt - template, pci_config - PCI configuration, ! 591: * ! 592: * Returns : 1 on success, 0 on failure. ! 593: * ! 594: * NOTE: If no override for the controller's SCSI id is given and AM53C974_SCSI_ID ! 595: * is not defined we assume that the SCSI address of this controller is correctly ! 596: * set up by the BIOS (as reflected by contents of register CNTLREG1). ! 597: * This is the only BIOS assistance we need. ! 598: **************************************************************************/ ! 599: static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config) ! 600: { ! 601: AM53C974_local_declare(); ! 602: int i, j; ! 603: struct Scsi_Host *instance, *search; ! 604: struct AM53C974_hostdata *hostdata; ! 605: ! 606: #ifdef AM53C974_OPTION_DEBUG_PROBE_ONLY ! 607: printk ("AM53C974: probe only enabled, aborting initialization\n"); ! 608: return -1; ! 609: #endif ! 610: ! 611: instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata)); ! 612: hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 613: instance->base = NULL; ! 614: instance->io_port = pci_config._base0 & (pci_config._base0 & 0x1 ? ! 615: 0xFFFFFFFC : 0xFFFFFFF0); ! 616: instance->irq = pci_config._int_line; ! 617: instance->dma_channel = -1; ! 618: AM53C974_setio(instance); ! 619: ! 620: #ifdef AM53C974_SCSI_ID ! 621: instance->this_id = AM53C974_SCSI_ID; ! 622: AM53C974_write_8(CNTLREG1, instance->this_id & CNTLREG1_SID); ! 623: #else ! 624: instance->this_id = AM53C974_read_8(CNTLREG1) & CNTLREG1_SID; ! 625: if (instance->this_id != 7) ! 626: printk("scsi%d: WARNING: unusual hostadapter SCSI id %d; please verify!\n", ! 627: instance->host_no, instance->this_id); ! 628: #endif ! 629: ! 630: for (i = 0; i < sizeof(hostdata->msgout); i++) { ! 631: hostdata->msgout[i] = NOP; ! 632: hostdata->last_message[i] = NOP; } ! 633: for (i = 0; i < 8; i++) { ! 634: hostdata->busy[i] = 0; ! 635: hostdata->sync_per[i] = DEF_STP; ! 636: hostdata->sync_off[i] = 0; ! 637: hostdata->sync_neg[i] = 0; ! 638: hostdata->sync_en[i] = DEFAULT_SYNC_NEGOTIATION_ENABLED; ! 639: hostdata->max_rate[i] = DEFAULT_RATE; ! 640: hostdata->max_offset[i] = DEFAULT_SYNC_OFFSET; } ! 641: ! 642: /* overwrite defaults by LILO overrides */ ! 643: for (i = 0; i < commandline_current; i++) { ! 644: if (overrides[i].host_scsi_id == instance->this_id) { ! 645: j = overrides[i].target_scsi_id; ! 646: hostdata->sync_en[j] = 1; ! 647: hostdata->max_rate[j] = overrides[i].max_rate; ! 648: hostdata->max_offset[j] = overrides[i].max_offset; ! 649: } ! 650: } ! 651: ! 652: hostdata->sel_cmd = NULL; ! 653: hostdata->connected = NULL; ! 654: hostdata->issue_queue = NULL; ! 655: hostdata->disconnected_queue = NULL; ! 656: hostdata->in_reset = 0; ! 657: hostdata->aborted = 0; ! 658: hostdata->selecting = 0; ! 659: hostdata->disconnecting = 0; ! 660: hostdata->dma_busy = 0; ! 661: ! 662: /* Set up an interrupt handler if we aren't already sharing an IRQ with another board */ ! 663: for (search = first_host; ! 664: search && ( ((the_template != NULL) && (search->hostt != the_template)) || ! 665: (search->irq != instance->irq) || (search == instance) ); ! 666: search = search->next); ! 667: if (!search) { ! 668: if (request_irq(instance->irq, AM53C974_intr, SA_INTERRUPT, "AM53C974")) { ! 669: printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq); ! 670: scsi_unregister(instance); ! 671: return -1; } ! 672: } ! 673: else { ! 674: printk("scsi%d: using interrupt handler previously installed for scsi%d\n", ! 675: instance->host_no, search->host_no); } ! 676: ! 677: if (!the_template) { ! 678: the_template = instance->hostt; ! 679: first_instance = instance; } ! 680: ! 681: /* do hard reset */ ! 682: AM53C974_write_8(CMDREG, CMDREG_RDEV); /* reset device */ ! 683: udelay(5); ! 684: AM53C974_write_8(CMDREG, CMDREG_NOP); ! 685: AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id); ! 686: AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */ ! 687: udelay(10); ! 688: AM53C974_config_after_reset(instance); ! 689: ! 690: return(0); ! 691: } ! 692: ! 693: /********************************************************************* ! 694: * Function : AM53C974_config_after_reset(struct Scsi_Host *instance) * ! 695: * * ! 696: * Purpose : initializes chip registers after reset * ! 697: * * ! 698: * Inputs : instance - which AM53C974 * ! 699: * * ! 700: * Returns : nothing * ! 701: **********************************************************************/ ! 702: static void AM53C974_config_after_reset(struct Scsi_Host *instance) ! 703: { ! 704: AM53C974_local_declare(); ! 705: AM53C974_setio(instance); ! 706: ! 707: /* clear SCSI FIFO */ ! 708: AM53C974_write_8(CMDREG, CMDREG_CFIFO); ! 709: ! 710: /* configure device */ ! 711: AM53C974_write_8(STIMREG, DEF_SCSI_TIMEOUT); ! 712: AM53C974_write_8(STPREG, DEF_STP & STPREG_STP); ! 713: AM53C974_write_8(SOFREG, (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4)); ! 714: AM53C974_write_8(CLKFREG, DEF_CLKF & CLKFREG_MASK); ! 715: AM53C974_write_8(CNTLREG1, (DEF_ETM<<7) | CNTLREG1_DISR | (DEF_PERE<<4) | instance->this_id); ! 716: AM53C974_write_8(CNTLREG2, (DEF_ENF<<6)); ! 717: AM53C974_write_8(CNTLREG3, (DEF_ADIDCHK<<7) | (DEF_FASTSCSI<<4) | (DEF_FASTCLK<<3)); ! 718: AM53C974_write_8(CNTLREG4, (DEF_GLITCH<<6) | (DEF_PWD<<5) | (DEF_RAE<<3) | (DEF_RADE<<2) | CNTLREG4_RES); ! 719: } ! 720: ! 721: /*********************************************************************** ! 722: * Function : const char *AM53C974_info(struct Scsi_Host *instance) * ! 723: * * ! 724: * Purpose : return device driver information * ! 725: * * ! 726: * Inputs : instance - which AM53C974 * ! 727: * * ! 728: * Returns : info string * ! 729: ************************************************************************/ ! 730: const char *AM53C974_info(struct Scsi_Host *instance) ! 731: { ! 732: static char info[100]; ! 733: ! 734: sprintf(info, "AM53/79C974 PCscsi driver rev. %d.%d; host I/O address: 0x%x; irq: %d\n", ! 735: AM53C974_DRIVER_REVISION_MAJOR, AM53C974_DRIVER_REVISION_MINOR, ! 736: instance->io_port, instance->irq); ! 737: return (info); ! 738: } ! 739: ! 740: /************************************************************************** ! 741: * Function : int AM53C974_command (Scsi_Cmnd *SCpnt) * ! 742: * * ! 743: * Purpose : the unqueued SCSI command function, replaced by the * ! 744: * AM53C974_queue_command function * ! 745: * * ! 746: * Inputs : SCpnt - pointer to command structure * ! 747: * * ! 748: * Returns :status, see hosts.h for details * ! 749: ***************************************************************************/ ! 750: int AM53C974_command(Scsi_Cmnd *SCpnt) ! 751: { ! 752: DEB(printk("AM53C974_command called\n")); ! 753: return 0; ! 754: } ! 755: ! 756: /************************************************************************** ! 757: * Function : void initialize_SCp(Scsi_Cmnd *cmd) * ! 758: * * ! 759: * Purpose : initialize the saved data pointers for cmd to point to the * ! 760: * start of the buffer. * ! 761: * * ! 762: * Inputs : cmd - Scsi_Cmnd structure to have pointers reset. * ! 763: * * ! 764: * Returns : nothing * ! 765: **************************************************************************/ ! 766: static __inline__ void initialize_SCp(Scsi_Cmnd *cmd) ! 767: { ! 768: if (cmd->use_sg) { ! 769: cmd->SCp.buffer = (struct scatterlist *)cmd->buffer; ! 770: cmd->SCp.buffers_residual = cmd->use_sg - 1; ! 771: cmd->SCp.ptr = (char *)cmd->SCp.buffer->address; ! 772: cmd->SCp.this_residual = cmd->SCp.buffer->length; } ! 773: else { ! 774: cmd->SCp.buffer = NULL; ! 775: cmd->SCp.buffers_residual = 0; ! 776: cmd->SCp.ptr = (char *)cmd->request_buffer; ! 777: cmd->SCp.this_residual = cmd->request_bufflen; } ! 778: } ! 779: ! 780: /************************************************************************** ! 781: * Function : run_main(void) * ! 782: * * ! 783: * Purpose : insure that the coroutine is running and will process our * ! 784: * request. main_running is checked/set here (in an inline * ! 785: * function rather than in AM53C974_main itself to reduce the * ! 786: * chances of stack overflow. * ! 787: * * ! 788: * * ! 789: * Inputs : none * ! 790: * * ! 791: * Returns : nothing * ! 792: **************************************************************************/ ! 793: static __inline__ void run_main(void) ! 794: { ! 795: cli(); ! 796: if (!main_running) { ! 797: /* main_running is cleared in AM53C974_main once it can't do ! 798: more work, and AM53C974_main exits with interrupts disabled. */ ! 799: main_running = 1; ! 800: AM53C974_main(); ! 801: sti(); } ! 802: else ! 803: sti(); ! 804: } ! 805: ! 806: /************************************************************************** ! 807: * Function : int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ! 808: * ! 809: * Purpose : writes SCSI command into AM53C974 FIFO ! 810: * ! 811: * Inputs : cmd - SCSI command, done - function called on completion, with ! 812: * a pointer to the command descriptor. ! 813: * ! 814: * Returns : status, see hosts.h for details ! 815: * ! 816: * Side effects : ! 817: * cmd is added to the per instance issue_queue, with minor ! 818: * twiddling done to the host specific fields of cmd. If the ! 819: * main coroutine is not running, it is restarted. ! 820: **************************************************************************/ ! 821: int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ! 822: { ! 823: struct Scsi_Host *instance = cmd->host; ! 824: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 825: Scsi_Cmnd *tmp; ! 826: ! 827: cli(); ! 828: DEB_QUEUE(printk(SEPARATOR_LINE)); ! 829: DEB_QUEUE(printk("scsi%d: AM53C974_queue_command called\n", instance->host_no)); ! 830: DEB_QUEUE(printk("cmd=%02x target=%02x lun=%02x bufflen=%d use_sg = %02x\n", ! 831: cmd->cmnd[0], cmd->target, cmd->lun, cmd->request_bufflen, cmd->use_sg)); ! 832: ! 833: /* We use the host_scribble field as a pointer to the next command in a queue */ ! 834: cmd->host_scribble = NULL; ! 835: cmd->scsi_done = done; ! 836: cmd->result = 0; ! 837: cmd->device->disconnect = 0; ! 838: ! 839: /* Insert the cmd into the issue queue. Note that REQUEST SENSE ! 840: * commands are added to the head of the queue since any command will ! 841: * clear the contingent allegiance condition that exists and the ! 842: * sense data is only guaranteed to be valid while the condition exists. */ ! 843: if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { ! 844: LIST(cmd, hostdata->issue_queue); ! 845: cmd->host_scribble = (unsigned char *)hostdata->issue_queue; ! 846: hostdata->issue_queue = cmd; } ! 847: else { ! 848: for (tmp = (Scsi_Cmnd *)hostdata->issue_queue; tmp->host_scribble; ! 849: tmp = (Scsi_Cmnd *)tmp->host_scribble); ! 850: LIST(cmd, tmp); ! 851: tmp->host_scribble = (unsigned char *)cmd; } ! 852: ! 853: DEB_QUEUE(printk("scsi%d : command added to %s of queue\n", instance->host_no, ! 854: (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail")); ! 855: ! 856: /* Run the coroutine if it isn't already running. */ ! 857: run_main(); ! 858: return 0; ! 859: } ! 860: ! 861: /************************************************************************** ! 862: * Function : AM53C974_main (void) ! 863: * ! 864: * Purpose : AM53C974_main is a coroutine that runs as long as more work can ! 865: * be done on the AM53C974 host adapters in a system. Both ! 866: * AM53C974_queue_command() and AM53C974_intr() will try to start it ! 867: * in case it is not running. ! 868: * ! 869: * NOTE : AM53C974_main exits with interrupts *disabled*, the caller should ! 870: * reenable them. This prevents reentrancy and kernel stack overflow. ! 871: **************************************************************************/ ! 872: static void AM53C974_main(void) ! 873: { ! 874: AM53C974_local_declare(); ! 875: Scsi_Cmnd *tmp, *prev; ! 876: struct Scsi_Host *instance; ! 877: struct AM53C974_hostdata *hostdata; ! 878: int done; ! 879: ! 880: /* We run (with interrupts disabled) until we're sure that none of ! 881: * the host adapters have anything that can be done, at which point ! 882: * we set main_running to 0 and exit. */ ! 883: ! 884: do { ! 885: cli(); /* Freeze request queues */ ! 886: done = 1; ! 887: for (instance = first_instance; instance && instance->hostt == the_template; ! 888: instance = instance->next) { ! 889: hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 890: AM53C974_setio(instance); ! 891: /* start to select target if we are not connected and not in the ! 892: selection process */ ! 893: if (!hostdata->connected && !hostdata->sel_cmd) { ! 894: /* Search through the issue_queue for a command destined for a target ! 895: that is not busy. */ ! 896: for (tmp = (Scsi_Cmnd *)hostdata->issue_queue, prev = NULL; tmp; ! 897: prev = tmp, tmp = (Scsi_Cmnd *)tmp->host_scribble) { ! 898: /* When we find one, remove it from the issue queue. */ ! 899: if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) { ! 900: if (prev) { ! 901: REMOVE(prev, (Scsi_Cmnd *)(prev->host_scribble), tmp, ! 902: (Scsi_Cmnd *)(tmp->host_scribble)); ! 903: prev->host_scribble = tmp->host_scribble; } ! 904: else { ! 905: REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble); ! 906: hostdata->issue_queue = (Scsi_Cmnd *)tmp->host_scribble; } ! 907: tmp->host_scribble = NULL; ! 908: ! 909: /* go into selection mode, disable reselection and wait for ! 910: SO interrupt which will continue with the selection process */ ! 911: hostdata->selecting = 1; ! 912: hostdata->sel_cmd = tmp; ! 913: AM53C974_write_8(CMDREG, CMDREG_DSR); ! 914: break; ! 915: } /* if target/lun is not busy */ ! 916: ! 917: } /* for */ ! 918: } /* if (!hostdata->connected) */ ! 919: else { ! 920: DEB(printk("main: connected; cmd = 0x%lx, sel_cmd = 0x%lx\n", ! 921: (long)hostdata->connected, (long)hostdata->sel_cmd)); ! 922: } ! 923: } /* for instance */ ! 924: } while (!done); ! 925: main_running = 0; ! 926: } ! 927: ! 928: /********************************************************************* ! 929: * Function : AM53C974_intr(int irq, struct pt_regs *regs) * ! 930: * * ! 931: * Purpose : interrupt handler * ! 932: * * ! 933: * Inputs : irq - interrupt line, regs - ? * ! 934: * * ! 935: * Returns : nothing * ! 936: **********************************************************************/ ! 937: static void AM53C974_intr(int irq, struct pt_regs *regs) ! 938: { ! 939: AM53C974_local_declare(); ! 940: struct Scsi_Host *instance; ! 941: struct AM53C974_hostdata *hostdata; ! 942: unsigned char cmdreg, dmastatus, statreg, isreg, instreg, cfifo; ! 943: ! 944: /* find AM53C974 hostadapter responsible for this interrupt */ ! 945: for (instance = first_instance; instance; instance = instance->next) ! 946: if ((instance->irq == irq) && (instance->hostt == the_template)) goto FOUND; ! 947: sti(); ! 948: return; ! 949: ! 950: /* found; now decode and process */ ! 951: FOUND: ! 952: hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 953: AM53C974_setio(instance); ! 954: dmastatus = AM53C974_read_8(DMASTATUS); ! 955: ! 956: DEB_INTR(printk(SEPARATOR_LINE)); ! 957: DEB_INTR(printk("AM53C974 interrupt; dmastatus=0x%02x\n", dmastatus)); ! 958: KEYWAIT(); ! 959: ! 960: /*** DMA related interrupts ***/ ! 961: if (hostdata->connected && (dmastatus & (DMASTATUS_ERROR | DMASTATUS_PWDN | ! 962: DMASTATUS_ABORT))) { ! 963: /* DMA error or POWERDOWN */ ! 964: printk("scsi%d: DMA error or powerdown; dmastatus: 0x%02x\n", ! 965: instance->host_no, dmastatus); ! 966: #ifdef AM53C974_DEBUG ! 967: deb_stop = 1; ! 968: #endif ! 969: panic("scsi%d: cannot recover\n", instance->host_no); } ! 970: ! 971: if (hostdata->connected && (dmastatus & DMASTATUS_DONE)) { ! 972: /* DMA transfer done */ ! 973: unsigned long residual; ! 974: cli(); ! 975: if (!(AM53C974_read_8(DMACMD) & DMACMD_DIR)) { ! 976: do { ! 977: dmastatus = AM53C974_read_8(DMASTATUS); ! 978: residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | ! 979: (AM53C974_read_8(CTCHREG) << 16); ! 980: residual += AM53C974_read_8(CFIREG) & CFIREG_CF; ! 981: } while (!(dmastatus & DMASTATUS_SCSIINT) && residual); ! 982: residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | ! 983: (AM53C974_read_8(CTCHREG) << 16); ! 984: residual += AM53C974_read_8(CFIREG) & CFIREG_CF; ! 985: } ! 986: else ! 987: residual = 0; ! 988: hostdata->connected->SCp.ptr += hostdata->connected->SCp.this_residual - residual; ! 989: hostdata->connected->SCp.this_residual = residual; ! 990: ! 991: AM53C974_write_8(DMACMD, DMACMD_IDLE); ! 992: ! 993: /* if service request missed before, process it now (ugly) */ ! 994: if (hostdata->dma_busy) { ! 995: hostdata->dma_busy = 0; ! 996: cmdreg = AM53C974_read_8(CMDREG); ! 997: statreg = AM53C974_read_8(STATREG); ! 998: isreg = AM53C974_read_8(ISREG); ! 999: instreg = AM53C974_read_8(INSTREG); ! 1000: cfifo = AM53C974_cfifo(); ! 1001: AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, ! 1002: dmastatus); } ! 1003: sti(); ! 1004: } ! 1005: ! 1006: if (!(dmastatus & DMASTATUS_SCSIINT)) { ! 1007: sti(); ! 1008: return; } ! 1009: ! 1010: /*** SCSI related interrupts ***/ ! 1011: cmdreg = AM53C974_read_8(CMDREG); ! 1012: statreg = AM53C974_read_8(STATREG); ! 1013: isreg = AM53C974_read_8(ISREG); ! 1014: instreg = AM53C974_read_8(INSTREG); ! 1015: cfifo = AM53C974_cfifo(); ! 1016: ! 1017: DEB_INTR(printk("scsi%d: statreg: 0x%02x; isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n", ! 1018: instance->host_no, statreg, isreg, instreg, cfifo)); ! 1019: ! 1020: if (statreg & STATREG_PE) { ! 1021: /* parity error */ ! 1022: #ifdef AM53C974_DEBUG ! 1023: deb_stop = 1; ! 1024: #endif ! 1025: printk("scsi%d : PARITY error\n", instance->host_no); ! 1026: if (hostdata->connected) hostdata->sync_off[hostdata->connected->target] = 0; /* setup asynchronous transfer */ ! 1027: hostdata->aborted = 1; } ! 1028: ! 1029: if (statreg & STATREG_IOE) { ! 1030: /* illegal operation error */ ! 1031: #ifdef AM53C974_DEBUG ! 1032: deb_stop = 1; ! 1033: #endif ! 1034: printk("scsi%d : ILLEGAL OPERATION error\n", instance->host_no); ! 1035: printk("cmdreg: 0x%02x; dmacmd: 0x%02x; statreg: 0x%02x; \n" ! 1036: "isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n", ! 1037: cmdreg, AM53C974_read_8(DMACMD), statreg, isreg, instreg, cfifo); } ! 1038: if (hostdata->in_reset && (instreg & INSTREG_SRST)) { ! 1039: /* RESET INTERRUPT */ ! 1040: #ifdef AM53C974_DEBUG ! 1041: deb_stop = 1; ! 1042: #endif ! 1043: DEB(printk("Bus reset interrupt received\n")); ! 1044: AM53C974_intr_bus_reset(instance); ! 1045: cli(); ! 1046: if (hostdata->connected) { ! 1047: hostdata->connected->result = DID_RESET << 16; ! 1048: hostdata->connected->scsi_done((Scsi_Cmnd *)hostdata->connected); ! 1049: hostdata->connected = NULL; } ! 1050: else { ! 1051: if (hostdata->sel_cmd) { ! 1052: hostdata->sel_cmd->result = DID_RESET << 16; ! 1053: hostdata->sel_cmd->scsi_done((Scsi_Cmnd *)hostdata->sel_cmd); ! 1054: hostdata->sel_cmd = NULL; } ! 1055: } ! 1056: sti(); ! 1057: if (hostdata->in_reset == 1) goto EXIT; ! 1058: else return; ! 1059: } ! 1060: ! 1061: if (instreg & INSTREG_ICMD) { ! 1062: /* INVALID COMMAND INTERRUPT */ ! 1063: #ifdef AM53C974_DEBUG ! 1064: deb_stop = 1; ! 1065: #endif ! 1066: printk("scsi%d: Invalid command interrupt\n", instance->host_no); ! 1067: printk("cmdreg: 0x%02x; dmacmd: 0x%02x; statreg: 0x%02x; dmastatus: 0x%02x; \n" ! 1068: "isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n", ! 1069: cmdreg, AM53C974_read_8(DMACMD), statreg, dmastatus, isreg, instreg, cfifo); ! 1070: panic("scsi%d: cannot recover\n", instance->host_no); } ! 1071: ! 1072: if (instreg & INSTREG_DIS) { ! 1073: /* DISCONNECT INTERRUPT */ ! 1074: DEB_INTR(printk("Disconnect interrupt received; ")); ! 1075: cli(); ! 1076: AM53C974_intr_disconnect(instance); ! 1077: sti(); ! 1078: goto EXIT; } ! 1079: ! 1080: if (instreg & INSTREG_RESEL) { ! 1081: /* RESELECTION INTERRUPT */ ! 1082: DEB_INTR(printk("Reselection interrupt received\n")); ! 1083: cli(); ! 1084: AM53C974_intr_reselect(instance, statreg); ! 1085: sti(); ! 1086: goto EXIT; } ! 1087: ! 1088: if (instreg & INSTREG_SO) { ! 1089: DEB_INTR(printk("Successful operation interrupt received\n")); ! 1090: if (hostdata->selecting) { ! 1091: DEB_INTR(printk("DSR completed, starting select\n")); ! 1092: cli(); ! 1093: AM53C974_select(instance, (Scsi_Cmnd *)hostdata->sel_cmd, ! 1094: (hostdata->sel_cmd->cmnd[0] == REQUEST_SENSE) ? ! 1095: TAG_NONE : TAG_NEXT); ! 1096: hostdata->selecting = 0; ! 1097: AM53C974_set_sync(instance, hostdata->sel_cmd->target); ! 1098: sti(); ! 1099: return; } ! 1100: ! 1101: if (hostdata->sel_cmd != NULL) { ! 1102: if ( ((isreg & ISREG_IS) != ISREG_OK_NO_STOP) && ! 1103: ((isreg & ISREG_IS) != ISREG_OK_STOP) ) { ! 1104: /* UNSUCCESSFUL SELECTION */ ! 1105: DEB_INTR(printk("unsuccessful selection\n")); ! 1106: cli(); ! 1107: hostdata->dma_busy = 0; ! 1108: LIST(hostdata->sel_cmd, hostdata->issue_queue); ! 1109: hostdata->sel_cmd->host_scribble = (unsigned char *)hostdata->issue_queue; ! 1110: hostdata->issue_queue = hostdata->sel_cmd; ! 1111: hostdata->sel_cmd = NULL; ! 1112: hostdata->selecting = 0; ! 1113: sti(); ! 1114: goto EXIT; } ! 1115: else { ! 1116: /* SUCCESSFUL SELECTION */ ! 1117: DEB(printk("successful selection; cmd=0x%02lx\n", (long)hostdata->sel_cmd)); ! 1118: cli(); ! 1119: hostdata->dma_busy = 0; ! 1120: hostdata->disconnecting = 0; ! 1121: hostdata->connected = hostdata->sel_cmd; ! 1122: hostdata->sel_cmd = NULL; ! 1123: hostdata->selecting = 0; ! 1124: #ifdef SCSI2 ! 1125: if (!hostdata->connected->device->tagged_queue) ! 1126: #endif ! 1127: hostdata->busy[hostdata->connected->target] |= (1 << hostdata->connected->lun); ! 1128: /* very strange -- use_sg is sometimes nonzero for request sense commands !! */ ! 1129: if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) { ! 1130: DEB(printk("scsi%d: REQUEST_SENSE command with nonzero use_sg\n", instance->host_no)); ! 1131: KEYWAIT(); ! 1132: hostdata->connected->use_sg = 0; } ! 1133: initialize_SCp((Scsi_Cmnd *)hostdata->connected); ! 1134: hostdata->connected->SCp.phase = PHASE_CMDOUT; ! 1135: AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus); ! 1136: sti(); ! 1137: return; } ! 1138: } ! 1139: else { ! 1140: cli(); ! 1141: AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus); ! 1142: sti(); ! 1143: return; } ! 1144: } ! 1145: ! 1146: if (instreg & INSTREG_SR) { ! 1147: DEB_INTR(printk("Service request interrupt received, ")); ! 1148: if (hostdata->connected) { ! 1149: DEB_INTR(printk("calling information_transfer\n")); ! 1150: cli(); ! 1151: AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus); ! 1152: sti(); } ! 1153: else { ! 1154: printk("scsi%d: weird: service request when no command connected\n", instance->host_no); ! 1155: AM53C974_write_8(CMDREG, CMDREG_CFIFO); } /* clear FIFO */ ! 1156: return; ! 1157: } ! 1158: ! 1159: EXIT: ! 1160: DEB_INTR(printk("intr: starting main\n")); ! 1161: run_main(); ! 1162: DEB_INTR(printk("end of intr\n")); ! 1163: } ! 1164: ! 1165: /************************************************************************** ! 1166: * Function : AM53C974_intr_disconnect(struct Scsi_Host *instance) ! 1167: * ! 1168: * Purpose : manage target disconnection ! 1169: * ! 1170: * Inputs : instance -- which AM53C974 ! 1171: * ! 1172: * Returns : nothing ! 1173: **************************************************************************/ ! 1174: static void AM53C974_intr_disconnect(struct Scsi_Host *instance) ! 1175: { ! 1176: AM53C974_local_declare(); ! 1177: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1178: Scsi_Cmnd *cmd; ! 1179: AM53C974_setio(instance); ! 1180: ! 1181: if (hostdata->sel_cmd != NULL) { ! 1182: /* normal selection timeout, typical for nonexisting targets */ ! 1183: cmd = (Scsi_Cmnd *)hostdata->sel_cmd; ! 1184: DEB_INTR(printk("bad target\n")); ! 1185: cmd->result = DID_BAD_TARGET << 16; ! 1186: goto EXIT_FINISHED; } ! 1187: ! 1188: if (!hostdata->connected) { ! 1189: /* can happen if controller was reset, a device tried to reconnect, ! 1190: failed and disconnects now */ ! 1191: AM53C974_write_8(CMDREG, CMDREG_CFIFO); ! 1192: return; } ! 1193: ! 1194: if (hostdata->disconnecting) { ! 1195: /* target sent disconnect message, so we are prepared */ ! 1196: cmd = (Scsi_Cmnd *)hostdata->connected; ! 1197: AM53C974_set_async(instance, cmd->target); ! 1198: DEB_INTR(printk("scsi%d : disc. from cmnd %d for ta %d, lun %d\n", ! 1199: instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); ! 1200: if (cmd->device->disconnect) { ! 1201: /* target wants to reselect later */ ! 1202: DEB_INTR(printk("ok, re-enabling selection\n")); ! 1203: LIST(cmd,hostdata->disconnected_queue); ! 1204: cmd->host_scribble = (unsigned char *)hostdata->disconnected_queue; ! 1205: hostdata->disconnected_queue = cmd; ! 1206: DEB_QUEUE(printk("scsi%d : command for target %d lun %d this %d was moved from connected to" ! 1207: " the disconnected_queue\n", instance->host_no, cmd->target, ! 1208: cmd->lun, hostdata->disconnected_queue->SCp.this_residual)); ! 1209: DEB_QUEUE(AM53C974_print_queues(instance)); ! 1210: goto EXIT_UNFINISHED; } ! 1211: else { ! 1212: /* target does not want to reselect later, we are really finished */ ! 1213: #ifdef AM53C974_DEBUG ! 1214: if (cmd->cmnd[0] == REQUEST_SENSE) { ! 1215: int i; ! 1216: printk("Request sense data dump:\n"); ! 1217: for (i = 0; i < cmd->request_bufflen; i++) { ! 1218: printk("%02x ", *((char *)(cmd->request_buffer) + i)); ! 1219: if (i && !(i % 16)) printk("\n"); } ! 1220: printk("\n"); } ! 1221: #endif ! 1222: goto EXIT_FINISHED; } /* !cmd->device->disconnect */ ! 1223: } /* if (hostdata->disconnecting) */ ! 1224: ! 1225: /* no disconnect message received; unexpected disconnection */ ! 1226: cmd = (Scsi_Cmnd *)hostdata->connected; ! 1227: if (cmd) { ! 1228: #ifdef AM53C974_DEBUG ! 1229: deb_stop = 1; ! 1230: #endif ! 1231: AM53C974_set_async(instance, cmd->target); ! 1232: printk("scsi%d: Unexpected disconnect; phase: %d; target: %d; this_residual: %d; buffers_residual: %d; message: %d\n", ! 1233: instance->host_no, cmd->SCp.phase, cmd->target, cmd->SCp.this_residual, cmd->SCp.buffers_residual, ! 1234: cmd->SCp.Message); ! 1235: printk("cmdreg: 0x%02x; statreg: 0x%02x; isreg: 0x%02x; cfifo: 0x%02x\n", ! 1236: AM53C974_read_8(CMDREG), AM53C974_read_8(STATREG), AM53C974_read_8(ISREG), ! 1237: AM53C974_read_8(CFIREG) & CFIREG_CF); ! 1238: ! 1239: if ((hostdata->last_message[0] == EXTENDED_MESSAGE) && ! 1240: (hostdata->last_message[2] == EXTENDED_SDTR)) { ! 1241: /* sync. negotiation was aborted, setup asynchronous transfer with target */ ! 1242: hostdata->sync_off[cmd->target] = 0; } ! 1243: if (hostdata->aborted || hostdata->msgout[0] == ABORT) ! 1244: cmd->result = DID_ABORT << 16; ! 1245: else ! 1246: cmd->result = DID_ERROR << 16; ! 1247: goto EXIT_FINISHED; } ! 1248: ! 1249: EXIT_FINISHED: ! 1250: hostdata->aborted = 0; ! 1251: hostdata->msgout[0] = NOP; ! 1252: hostdata->sel_cmd = NULL; ! 1253: hostdata->connected = NULL; ! 1254: hostdata->selecting = 0; ! 1255: hostdata->disconnecting = 0; ! 1256: hostdata->dma_busy = 0; ! 1257: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1258: AM53C974_write_8(CMDREG, CMDREG_CFIFO); ! 1259: DEB(printk("disconnect; issue_queue: 0x%lx, disconnected_queue: 0x%lx\n", ! 1260: (long)hostdata->issue_queue, (long)hostdata->disconnected_queue)); ! 1261: cmd->scsi_done(cmd); ! 1262: ! 1263: if (!hostdata->selecting) { ! 1264: AM53C974_set_async(instance, cmd->target); ! 1265: AM53C974_write_8(CMDREG, CMDREG_ESR); } /* allow reselect */ ! 1266: return; ! 1267: ! 1268: EXIT_UNFINISHED: ! 1269: hostdata->msgout[0] = NOP; ! 1270: hostdata->sel_cmd = NULL; ! 1271: hostdata->connected = NULL; ! 1272: hostdata->aborted = 0; ! 1273: hostdata->selecting = 0; ! 1274: hostdata->disconnecting = 0; ! 1275: hostdata->dma_busy = 0; ! 1276: DEB(printk("disconnect; issue_queue: 0x%lx, disconnected_queue: 0x%lx\n", ! 1277: (long)hostdata->issue_queue, (long)hostdata->disconnected_queue)); ! 1278: if (!hostdata->selecting) { ! 1279: AM53C974_set_async(instance, cmd->target); ! 1280: AM53C974_write_8(CMDREG, CMDREG_ESR); } /* allow reselect */ ! 1281: return; ! 1282: } ! 1283: ! 1284: /************************************************************************** ! 1285: * Function : int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg) ! 1286: * ! 1287: * Purpose : setup message string for sync. negotiation ! 1288: * ! 1289: * Inputs : instance -- which AM53C974 ! 1290: * target -- which SCSI target to deal with ! 1291: * msg -- input message string ! 1292: * ! 1293: * Returns : 0 if parameters accepted or 1 if not accepted ! 1294: * ! 1295: * Side effects: hostdata is changed ! 1296: * ! 1297: * Note: we assume here that fastclk is enabled ! 1298: **************************************************************************/ ! 1299: static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg) ! 1300: { ! 1301: AM53C974_local_declare(); ! 1302: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1303: int period, offset, i, rate, rate_rem; ! 1304: AM53C974_setio(instance); ! 1305: ! 1306: period = (DEF_CLK * msg[3] * 8 + 1000) / 2000; ! 1307: if (period < MIN_PERIOD) { ! 1308: period = MIN_PERIOD; ! 1309: hostdata->msgout[3] = period / 4; } ! 1310: else ! 1311: if (period > MAX_PERIOD) { ! 1312: period = MAX_PERIOD; ! 1313: hostdata->msgout[3] = period / 4; } ! 1314: else ! 1315: hostdata->msgout[3] = msg[3]; ! 1316: offset = msg[4]; ! 1317: if (offset > MAX_OFFSET) offset = MAX_OFFSET; ! 1318: hostdata->msgout[4] = offset; ! 1319: hostdata->sync_per[target] = period; ! 1320: hostdata->sync_off[target] = offset; ! 1321: for (i = 0; i < 3; i++) hostdata->msgout[i] = msg[i]; ! 1322: if ((hostdata->msgout[3] != msg[3]) || (msg[4] != offset)) return(1); ! 1323: ! 1324: rate = DEF_CLK / period; ! 1325: rate_rem = 10 * (DEF_CLK - period * rate) / period; ! 1326: ! 1327: if (offset) ! 1328: printk("\ntarget %d: rate=%d.%d Mhz, synchronous, sync offset=%d bytes\n", ! 1329: target, rate, rate_rem, offset); ! 1330: else ! 1331: printk("\ntarget %d: rate=%d.%d Mhz, asynchronous\n", target, rate, rate_rem); ! 1332: ! 1333: return(0); ! 1334: } ! 1335: ! 1336: /************************************************************************** ! 1337: * Function : AM53C974_set_async(struct Scsi_Host *instance, int target) ! 1338: * ! 1339: * Purpose : put controller into async. mode ! 1340: * ! 1341: * Inputs : instance -- which AM53C974 ! 1342: * target -- which SCSI target to deal with ! 1343: * ! 1344: * Returns : nothing ! 1345: **************************************************************************/ ! 1346: static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target) ! 1347: { ! 1348: AM53C974_local_declare(); ! 1349: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1350: AM53C974_setio(instance); ! 1351: ! 1352: AM53C974_write_8(STPREG, hostdata->sync_per[target]); ! 1353: AM53C974_write_8(SOFREG, (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4)); ! 1354: } ! 1355: ! 1356: /************************************************************************** ! 1357: * Function : AM53C974_set_sync(struct Scsi_Host *instance, int target) ! 1358: * ! 1359: * Purpose : put controller into sync. mode ! 1360: * ! 1361: * Inputs : instance -- which AM53C974 ! 1362: * target -- which SCSI target to deal with ! 1363: * ! 1364: * Returns : nothing ! 1365: **************************************************************************/ ! 1366: static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target) ! 1367: { ! 1368: AM53C974_local_declare(); ! 1369: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1370: AM53C974_setio(instance); ! 1371: ! 1372: AM53C974_write_8(STPREG, hostdata->sync_per[target]); ! 1373: AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) | ! 1374: (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4)); ! 1375: } ! 1376: ! 1377: /*********************************************************************** ! 1378: * Function : AM53C974_information_transfer(struct Scsi_Host *instance, * ! 1379: * unsigned char statreg, unsigned char isreg, * ! 1380: * unsigned char instreg, unsigned char cfifo, * ! 1381: * unsigned char dmastatus) * ! 1382: * * ! 1383: * Purpose : handle phase changes * ! 1384: * * ! 1385: * Inputs : instance - which AM53C974 * ! 1386: * statreg - stus register * ! 1387: * isreg - internal state register * ! 1388: * instreg - interrupt status register * ! 1389: * cfifo - number of bytes in FIFO * ! 1390: * dmastatus - dma status register * ! 1391: * * ! 1392: * Returns : nothing * ! 1393: ************************************************************************/ ! 1394: static void AM53C974_information_transfer(struct Scsi_Host *instance, ! 1395: unsigned char statreg, unsigned char isreg, ! 1396: unsigned char instreg, unsigned char cfifo, ! 1397: unsigned char dmastatus) ! 1398: { ! 1399: AM53C974_local_declare(); ! 1400: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1401: Scsi_Cmnd *cmd = (Scsi_Cmnd *)hostdata->connected; ! 1402: int ret, i, len, residual=-1; ! 1403: AM53C974_setio(instance); ! 1404: ! 1405: DEB_INFO(printk(SEPARATOR_LINE)); ! 1406: switch (statreg & STATREG_PHASE) { /* scsi phase */ ! 1407: case PHASE_DATAOUT: ! 1408: DEB_INFO(printk("Dataout phase; cmd=0x%lx, sel_cmd=0x%lx, this_residual=%d, buffers_residual=%d\n", ! 1409: (long)hostdata->connected, (long)hostdata->sel_cmd, cmd->SCp.this_residual, cmd->SCp.buffers_residual)); ! 1410: cmd->SCp.phase = PHASE_DATAOUT; ! 1411: goto PHASE_DATA_IO; ! 1412: ! 1413: case PHASE_DATAIN: ! 1414: DEB_INFO(printk("Datain phase; cmd=0x%lx, sel_cmd=0x%lx, this_residual=%d, buffers_residual=%d\n", ! 1415: (long)hostdata->connected, (long)hostdata->sel_cmd, cmd->SCp.this_residual, cmd->SCp.buffers_residual)); ! 1416: cmd->SCp.phase = PHASE_DATAIN; ! 1417: PHASE_DATA_IO: ! 1418: if (hostdata->aborted) { ! 1419: AM53C974_write_8(DMACMD, DMACMD_IDLE); ! 1420: AM53C974_write_8(CMDREG, CMDREG_CFIFO); ! 1421: AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1422: return; } ! 1423: if ((!cmd->SCp.this_residual) && cmd->SCp.buffers_residual) { ! 1424: cmd->SCp.buffer++; ! 1425: cmd->SCp.buffers_residual--; ! 1426: cmd->SCp.ptr = (unsigned char *)cmd->SCp.buffer->address; ! 1427: cmd->SCp.this_residual = cmd->SCp.buffer->length; } ! 1428: if (cmd->SCp.this_residual) { ! 1429: if (!(AM53C974_read_8(DMACMD) & DMACMD_START)) { ! 1430: hostdata->dma_busy = 0; ! 1431: AM53C974_transfer_dma(instance, statreg & STATREG_IO, ! 1432: (unsigned long)cmd->SCp.this_residual, ! 1433: cmd->SCp.ptr); } ! 1434: else ! 1435: hostdata->dma_busy = 1; ! 1436: } ! 1437: return; ! 1438: ! 1439: case PHASE_MSGIN: ! 1440: DEB_INFO(printk("Message-In phase; cmd=0x%lx, sel_cmd=0x%lx\n", ! 1441: (long)hostdata->connected, (long)hostdata->sel_cmd)); ! 1442: AM53C974_set_async(instance, cmd->target); ! 1443: if (cmd->SCp.phase == PHASE_DATAIN) ! 1444: AM53C974_dma_blast(instance, dmastatus, statreg); ! 1445: if ((cmd->SCp.phase == PHASE_DATAOUT) && (AM53C974_read_8(DMACMD) & DMACMD_START)) { ! 1446: AM53C974_write_8(DMACMD, DMACMD_IDLE); ! 1447: residual = cfifo + (AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | ! 1448: (AM53C974_read_8(CTCHREG) << 16)); ! 1449: cmd->SCp.ptr += cmd->SCp.this_residual - residual; ! 1450: cmd->SCp.this_residual = residual; ! 1451: if (cfifo) { AM53C974_write_8(CMDREG, CMDREG_CFIFO); cfifo = 0; } ! 1452: } ! 1453: if (cmd->SCp.phase == PHASE_STATIN) { ! 1454: while ((AM53C974_read_8(CFIREG) & CFIREG_CF) < 2) ; ! 1455: cmd->SCp.Status = AM53C974_read_8(FFREG); ! 1456: cmd->SCp.Message = AM53C974_read_8(FFREG); ! 1457: DEB_INFO(printk("Message-In phase; status=0x%02x, message=0x%02x\n", ! 1458: cmd->SCp.Status, cmd->SCp.Message)); ! 1459: ret = AM53C974_message(instance, cmd, cmd->SCp.Message); } ! 1460: else { ! 1461: if (!cfifo) { ! 1462: AM53C974_write_8(CMDREG, CMDREG_IT); ! 1463: AM53C974_poll_int(); ! 1464: cmd->SCp.Message = AM53C974_read_8(FFREG); ! 1465: } ! 1466: ret = AM53C974_message(instance, cmd, cmd->SCp.Message); ! 1467: } ! 1468: cmd->SCp.phase = PHASE_MSGIN; ! 1469: AM53C974_set_sync(instance, cmd->target); ! 1470: break; ! 1471: case PHASE_MSGOUT: ! 1472: DEB_INFO(printk("Message-Out phase; cfifo=%d; msgout[0]=0x%02x\n", ! 1473: AM53C974_read_8(CFIREG) & CFIREG_CF, hostdata->msgout[0])); ! 1474: AM53C974_write_8(DMACMD, DMACMD_IDLE); ! 1475: AM53C974_set_async(instance, cmd->target); ! 1476: for (i = 0; i < sizeof(hostdata->last_message); i++) ! 1477: hostdata->last_message[i] = hostdata->msgout[i]; ! 1478: if ((hostdata->msgout[0] == 0) || INSIDE(hostdata->msgout[0], 0x02, 0x1F) || ! 1479: INSIDE(hostdata->msgout[0], 0x80, 0xFF)) ! 1480: len = 1; ! 1481: else { ! 1482: if (hostdata->msgout[0] == EXTENDED_MESSAGE) { ! 1483: #ifdef AM53C974_DEBUG_INFO ! 1484: printk("Extended message dump:\n"); ! 1485: for (i = 0; i < hostdata->msgout[1] + 2; i++) { ! 1486: printk("%02x ", hostdata->msgout[i]); ! 1487: if (i && !(i % 16)) printk("\n"); } ! 1488: printk("\n"); ! 1489: #endif ! 1490: len = hostdata->msgout[1] + 2; } ! 1491: else ! 1492: len = 2; ! 1493: } ! 1494: for (i = 0; i < len; i++) AM53C974_write_8(FFREG, hostdata->msgout[i]); ! 1495: AM53C974_write_8(CMDREG, CMDREG_IT); ! 1496: cmd->SCp.phase = PHASE_MSGOUT; ! 1497: hostdata->msgout[0] = NOP; ! 1498: AM53C974_set_sync(instance, cmd->target); ! 1499: break; ! 1500: ! 1501: case PHASE_CMDOUT: ! 1502: DEB_INFO(printk("Command-Out phase\n")); ! 1503: AM53C974_set_async(instance, cmd->target); ! 1504: for (i = 0; i < cmd->cmd_len; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]); ! 1505: AM53C974_write_8(CMDREG, CMDREG_IT); ! 1506: cmd->SCp.phase = PHASE_CMDOUT; ! 1507: AM53C974_set_sync(instance, cmd->target); ! 1508: break; ! 1509: ! 1510: case PHASE_STATIN: ! 1511: DEB_INFO(printk("Status phase\n")); ! 1512: if (cmd->SCp.phase == PHASE_DATAIN) ! 1513: AM53C974_dma_blast(instance, dmastatus, statreg); ! 1514: AM53C974_set_async(instance, cmd->target); ! 1515: if (cmd->SCp.phase == PHASE_DATAOUT) { ! 1516: unsigned long residual; ! 1517: ! 1518: if (AM53C974_read_8(DMACMD) & DMACMD_START) { ! 1519: AM53C974_write_8(DMACMD, DMACMD_IDLE); ! 1520: residual = cfifo + (AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | ! 1521: (AM53C974_read_8(CTCHREG) << 16)); ! 1522: cmd->SCp.ptr += cmd->SCp.this_residual - residual; ! 1523: cmd->SCp.this_residual = residual; } ! 1524: if (cfifo) { AM53C974_write_8(CMDREG, CMDREG_CFIFO); cfifo = 0; } ! 1525: } ! 1526: cmd->SCp.phase = PHASE_STATIN; ! 1527: AM53C974_write_8(CMDREG, CMDREG_ICCS); /* command complete */ ! 1528: break; ! 1529: ! 1530: case PHASE_RES_0: ! 1531: case PHASE_RES_1: ! 1532: #ifdef AM53C974_DEBUG ! 1533: deb_stop = 1; ! 1534: #endif ! 1535: DEB_INFO(printk("Reserved phase\n")); ! 1536: break; ! 1537: } ! 1538: KEYWAIT(); ! 1539: } ! 1540: ! 1541: /****************************************************************************** ! 1542: * Function : int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd, ! 1543: * unsigned char msg) ! 1544: * ! 1545: * Purpose : handle SCSI messages ! 1546: * ! 1547: * Inputs : instance -- which AM53C974 ! 1548: * cmd -- SCSI command the message belongs to ! 1549: * msg -- message id byte ! 1550: * ! 1551: * Returns : 1 on success, 0 on failure. ! 1552: **************************************************************************/ ! 1553: static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd, ! 1554: unsigned char msg) ! 1555: { ! 1556: AM53C974_local_declare(); ! 1557: static unsigned char extended_msg[10]; ! 1558: unsigned char statreg; ! 1559: int len, ret = 0; ! 1560: unsigned char *p; ! 1561: #ifdef AM53C974_DEBUG_MSG ! 1562: int j; ! 1563: #endif ! 1564: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1565: AM53C974_setio(instance); ! 1566: ! 1567: DEB_MSG(printk(SEPARATOR_LINE)); ! 1568: ! 1569: /* Linking lets us reduce the time required to get the ! 1570: * next command out to the device, hopefully this will ! 1571: * mean we don't waste another revolution due to the delays ! 1572: * required by ARBITRATION and another SELECTION. ! 1573: * In the current implementation proposal, low level drivers ! 1574: * merely have to start the next command, pointed to by ! 1575: * next_link, done() is called as with unlinked commands. */ ! 1576: switch (msg) { ! 1577: #ifdef LINKED ! 1578: case LINKED_CMD_COMPLETE: ! 1579: case LINKED_FLG_CMD_COMPLETE: ! 1580: /* Accept message by releasing ACK */ ! 1581: DEB_LINKED(printk("scsi%d : target %d lun %d linked command complete.\n", ! 1582: instance->host_no, cmd->target, cmd->lun)); ! 1583: /* Sanity check : A linked command should only terminate with ! 1584: * one of these messages if there are more linked commands available. */ ! 1585: if (!cmd->next_link) { ! 1586: printk("scsi%d : target %d lun %d linked command complete, no next_link\n" ! 1587: instance->host_no, cmd->target, cmd->lun); ! 1588: hostdata->aborted = 1; ! 1589: AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1590: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1591: break; } ! 1592: if (hostdata->aborted) { ! 1593: DEB_ABORT(printk("ATN set for cmnd %d upon reception of LINKED_CMD_COMPLETE or" ! 1594: "LINKED_FLG_CMD_COMPLETE message\n", cmd->cmnd[0])); ! 1595: AM53C974_write_8(CMDREG, CMDREG_SATN); } ! 1596: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1597: ! 1598: initialize_SCp(cmd->next_link); ! 1599: /* The next command is still part of this process */ ! 1600: cmd->next_link->tag = cmd->tag; ! 1601: cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); ! 1602: DEB_LINKED(printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", ! 1603: instance->host_no, cmd->target, cmd->lun)); ! 1604: cmd->scsi_done(cmd); ! 1605: cmd = hostdata->connected; ! 1606: break; ! 1607: ! 1608: #endif /* def LINKED */ ! 1609: ! 1610: case ABORT: ! 1611: case COMMAND_COMPLETE: ! 1612: DEB_MSG(printk("scsi%d: command complete message received; cmd %d for target %d, lun %d\n", ! 1613: instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); ! 1614: hostdata->disconnecting = 1; ! 1615: cmd->device->disconnect = 0; ! 1616: ! 1617: /* I'm not sure what the correct thing to do here is : ! 1618: * ! 1619: * If the command that just executed is NOT a request ! 1620: * sense, the obvious thing to do is to set the result ! 1621: * code to the values of the stored parameters. ! 1622: * If it was a REQUEST SENSE command, we need some way ! 1623: * to differentiate between the failure code of the original ! 1624: * and the failure code of the REQUEST sense - the obvious ! 1625: * case is success, where we fall through and leave the result ! 1626: * code unchanged. ! 1627: * ! 1628: * The non-obvious place is where the REQUEST SENSE failed */ ! 1629: if (cmd->cmnd[0] != REQUEST_SENSE) ! 1630: cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); ! 1631: else if (cmd->SCp.Status != GOOD) ! 1632: cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); ! 1633: if (hostdata->aborted) { ! 1634: AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1635: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1636: DEB_ABORT(printk("ATN set for cmnd %d upon reception of ABORT or" ! 1637: "COMMAND_COMPLETE message\n", cmd->cmnd[0])); ! 1638: break; } ! 1639: if ((cmd->cmnd[0] != REQUEST_SENSE) && (cmd->SCp.Status == CHECK_CONDITION)) { ! 1640: DEB_MSG(printk("scsi%d : performing request sense\n", instance->host_no)); ! 1641: cmd->cmnd[0] = REQUEST_SENSE; ! 1642: cmd->cmnd[1] &= 0xe0; ! 1643: cmd->cmnd[2] = 0; ! 1644: cmd->cmnd[3] = 0; ! 1645: cmd->cmnd[4] = sizeof(cmd->sense_buffer); ! 1646: cmd->cmnd[5] = 0; ! 1647: cmd->SCp.buffer = NULL; ! 1648: cmd->SCp.buffers_residual = 0; ! 1649: cmd->SCp.ptr = (char *)cmd->sense_buffer; ! 1650: cmd->SCp.this_residual = sizeof(cmd->sense_buffer); ! 1651: LIST(cmd,hostdata->issue_queue); ! 1652: cmd->host_scribble = (unsigned char *)hostdata->issue_queue; ! 1653: hostdata->issue_queue = (Scsi_Cmnd *)cmd; ! 1654: DEB_MSG(printk("scsi%d : REQUEST SENSE added to head of issue queue\n",instance->host_no)); ! 1655: } ! 1656: ! 1657: /* Accept message by clearing ACK */ ! 1658: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1659: break; ! 1660: ! 1661: case MESSAGE_REJECT: ! 1662: DEB_MSG(printk("scsi%d: reject message received; cmd %d for target %d, lun %d\n", ! 1663: instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); ! 1664: switch (hostdata->last_message[0]) { ! 1665: case EXTENDED_MESSAGE: ! 1666: if (hostdata->last_message[2] == EXTENDED_SDTR) { ! 1667: /* sync. negotiation was rejected, setup asynchronous transfer with target */ ! 1668: printk("\ntarget %d: rate=%d Mhz, asynchronous (sync. negotiation rejected)\n", ! 1669: cmd->target, DEF_CLK / DEF_STP); ! 1670: hostdata->sync_off[cmd->target] = 0; ! 1671: hostdata->sync_per[cmd->target] = DEF_STP; } ! 1672: break; ! 1673: case HEAD_OF_QUEUE_TAG: ! 1674: case ORDERED_QUEUE_TAG: ! 1675: case SIMPLE_QUEUE_TAG: ! 1676: cmd->device->tagged_queue = 0; ! 1677: hostdata->busy[cmd->target] |= (1 << cmd->lun); ! 1678: break; ! 1679: default: ! 1680: break; ! 1681: } ! 1682: if (hostdata->aborted) AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1683: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1684: break; ! 1685: ! 1686: case DISCONNECT: ! 1687: DEB_MSG(printk("scsi%d: disconnect message received; cmd %d for target %d, lun %d\n", ! 1688: instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); ! 1689: cmd->device->disconnect = 1; ! 1690: hostdata->disconnecting = 1; ! 1691: AM53C974_write_8(CMDREG, CMDREG_MA); /* Accept message by clearing ACK */ ! 1692: break; ! 1693: ! 1694: case SAVE_POINTERS: ! 1695: case RESTORE_POINTERS: ! 1696: DEB_MSG(printk("scsi%d: save/restore pointers message received; cmd %d for target %d, lun %d\n", ! 1697: instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); ! 1698: /* The SCSI data pointer is *IMPLICITLY* saved on a disconnect ! 1699: * operation, in violation of the SCSI spec so we can safely ! 1700: * ignore SAVE/RESTORE pointers calls. ! 1701: * ! 1702: * Unfortunately, some disks violate the SCSI spec and ! 1703: * don't issue the required SAVE_POINTERS message before ! 1704: * disconnecting, and we have to break spec to remain ! 1705: * compatible. */ ! 1706: if (hostdata->aborted) { ! 1707: DEB_ABORT(printk("ATN set for cmnd %d upon reception of SAVE/REST. POINTERS message\n", ! 1708: cmd->cmnd[0])); ! 1709: AM53C974_write_8(CMDREG, CMDREG_SATN); } ! 1710: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1711: break; ! 1712: ! 1713: case EXTENDED_MESSAGE: ! 1714: DEB_MSG(printk("scsi%d: extended message received; cmd %d for target %d, lun %d\n", ! 1715: instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); ! 1716: /* Extended messages are sent in the following format : ! 1717: * Byte ! 1718: * 0 EXTENDED_MESSAGE == 1 ! 1719: * 1 length (includes one byte for code, doesn't include first two bytes) ! 1720: * 2 code ! 1721: * 3..length+1 arguments ! 1722: */ ! 1723: /* BEWARE!! THIS CODE IS EXTREMELY UGLY */ ! 1724: extended_msg[0] = EXTENDED_MESSAGE; ! 1725: AM53C974_read_8(INSTREG) ; /* clear int */ ! 1726: AM53C974_write_8(CMDREG, CMDREG_MA); /* ack. msg byte, then wait for SO */ ! 1727: AM53C974_poll_int(); ! 1728: /* get length */ ! 1729: AM53C974_write_8(CMDREG, CMDREG_IT); ! 1730: AM53C974_poll_int(); ! 1731: AM53C974_write_8(CMDREG, CMDREG_MA); /* ack. msg byte, then wait for SO */ ! 1732: AM53C974_poll_int(); ! 1733: extended_msg[1] = len = AM53C974_read_8(FFREG); /* get length */ ! 1734: p = extended_msg+2; ! 1735: /* read the remaining (len) bytes */ ! 1736: while (len) { ! 1737: AM53C974_write_8(CMDREG, CMDREG_IT); ! 1738: AM53C974_poll_int(); ! 1739: if (len > 1) { ! 1740: AM53C974_write_8(CMDREG, CMDREG_MA); /* ack. msg byte, then wait for SO */ ! 1741: AM53C974_poll_int(); } ! 1742: *p = AM53C974_read_8(FFREG); ! 1743: p++; len--; } ! 1744: ! 1745: #ifdef AM53C974_DEBUG_MSG ! 1746: printk("scsi%d: received extended message: ", instance->host_no); ! 1747: for (j = 0; j < extended_msg[1] + 2; j++) { ! 1748: printk("0x%02x ", extended_msg[j]); ! 1749: if (j && !(j % 16)) printk("\n"); } ! 1750: printk("\n"); ! 1751: #endif ! 1752: ! 1753: /* check message */ ! 1754: if (extended_msg[2] == EXTENDED_SDTR) ! 1755: ret = AM53C974_sync_neg(instance, cmd->target, extended_msg); ! 1756: if (ret || hostdata->aborted) AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1757: ! 1758: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1759: break; ! 1760: ! 1761: default: ! 1762: printk("scsi%d: unknown message 0x%02x received\n",instance->host_no, msg); ! 1763: #ifdef AM53C974_DEBUG ! 1764: deb_stop = 1; ! 1765: #endif ! 1766: /* reject message */ ! 1767: hostdata->msgout[0] = MESSAGE_REJECT; ! 1768: AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1769: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1770: return(0); ! 1771: break; ! 1772: ! 1773: } /* switch (msg) */ ! 1774: KEYWAIT(); ! 1775: return(1); ! 1776: } ! 1777: ! 1778: /************************************************************************** ! 1779: * Function : AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) ! 1780: * ! 1781: * Purpose : try to establish nexus for the command; ! 1782: * start sync negotiation via start stop and transfer the command in ! 1783: * cmdout phase in case of an inquiry or req. sense command with no ! 1784: * sync. neg. performed yet ! 1785: * ! 1786: * Inputs : instance -- which AM53C974 ! 1787: * cmd -- command which requires the selection ! 1788: * tag -- tagged queueing ! 1789: * ! 1790: * Returns : nothing ! 1791: * ! 1792: * Note: this function initializes the selection process, which is continued ! 1793: * in the interrupt handler ! 1794: **************************************************************************/ ! 1795: static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) ! 1796: { ! 1797: AM53C974_local_declare(); ! 1798: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1799: unsigned char cfifo, tmp[3]; ! 1800: unsigned int i, len, cmd_size = COMMAND_SIZE(cmd->cmnd[0]); ! 1801: AM53C974_setio(instance); ! 1802: ! 1803: cfifo = AM53C974_cfifo(); ! 1804: if (cfifo) { ! 1805: printk("scsi%d: select error; %d residual bytes in FIFO\n", instance->host_no, cfifo); ! 1806: AM53C974_write_8(CMDREG, CMDREG_CFIFO); /* clear FIFO */ ! 1807: } ! 1808: ! 1809: tmp[0] = IDENTIFY(1, cmd->lun); ! 1810: ! 1811: #ifdef SCSI2 ! 1812: if (cmd->device->tagged_queue && (tag != TAG_NONE)) { ! 1813: tmp[1] = SIMPLE_QUEUE_TAG; ! 1814: if (tag == TAG_NEXT) { ! 1815: /* 0 is TAG_NONE, used to imply no tag for this command */ ! 1816: if (cmd->device->current_tag == 0) cmd->device->current_tag = 1; ! 1817: cmd->tag = cmd->device->current_tag; ! 1818: cmd->device->current_tag++; } ! 1819: else ! 1820: cmd->tag = (unsigned char)tag; ! 1821: tmp[2] = cmd->tag; ! 1822: hostdata->last_message[0] = SIMPLE_QUEUE_TAG; ! 1823: len = 3; ! 1824: AM53C974_write_8(FFREG, tmp[0]); ! 1825: AM53C974_write_8(FFREG, tmp[1]); ! 1826: AM53C974_write_8(FFREG, tmp[2]); ! 1827: } ! 1828: else ! 1829: #endif /* def SCSI2 */ ! 1830: { ! 1831: len = 1; ! 1832: AM53C974_write_8(FFREG, tmp[0]); ! 1833: cmd->tag = 0; } ! 1834: ! 1835: /* in case of an inquiry or req. sense command with no sync. neg performed yet, we start ! 1836: sync negotiation via start stops and transfer the command in cmdout phase */ ! 1837: if (((cmd->cmnd[0] == INQUIRY) || (cmd->cmnd[0] == REQUEST_SENSE)) && ! 1838: !(hostdata->sync_neg[cmd->target]) && hostdata->sync_en[cmd->target]) { ! 1839: hostdata->sync_neg[cmd->target] = 1; ! 1840: hostdata->msgout[0] = EXTENDED_MESSAGE; ! 1841: hostdata->msgout[1] = 3; ! 1842: hostdata->msgout[2] = EXTENDED_SDTR; ! 1843: hostdata->msgout[3] = 250 / (int)hostdata->max_rate[cmd->target]; ! 1844: hostdata->msgout[4] = hostdata->max_offset[cmd->target]; ! 1845: len += 5; } ! 1846: ! 1847: AM53C974_write_8(SDIDREG, SDIREG_MASK & cmd->target); /* setup dest. id */ ! 1848: AM53C974_write_8(STIMREG, DEF_SCSI_TIMEOUT); /* setup timeout reg */ ! 1849: switch (len) { ! 1850: case 1: ! 1851: for (i = 0; i < cmd_size; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]); ! 1852: AM53C974_write_8(CMDREG, CMDREG_SAS); /* select with ATN, 1 msg byte */ ! 1853: hostdata->msgout[0] = NOP; ! 1854: break; ! 1855: case 3: ! 1856: for (i = 0; i < cmd_size; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]); ! 1857: AM53C974_write_8(CMDREG, CMDREG_SA3S); /* select with ATN, 3 msg bytes */ ! 1858: hostdata->msgout[0] = NOP; ! 1859: break; ! 1860: default: ! 1861: AM53C974_write_8(CMDREG, CMDREG_SASS); /* select with ATN, stop steps; continue in message out phase */ ! 1862: break; ! 1863: } ! 1864: } ! 1865: ! 1866: /************************************************************************** ! 1867: * Function : AM53C974_intr_select(struct Scsi_Host *instance, unsigned char statreg) ! 1868: * ! 1869: * Purpose : handle reselection ! 1870: * ! 1871: * Inputs : instance -- which AM53C974 ! 1872: * statreg -- status register ! 1873: * ! 1874: * Returns : nothing ! 1875: * ! 1876: * side effects: manipulates hostdata ! 1877: **************************************************************************/ ! 1878: static void AM53C974_intr_reselect(struct Scsi_Host *instance, unsigned char statreg) ! 1879: { ! 1880: AM53C974_local_declare(); ! 1881: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 1882: unsigned char cfifo, msg[3], lun, t, target = 0; ! 1883: #ifdef SCSI2 ! 1884: unsigned char tag; ! 1885: #endif ! 1886: Scsi_Cmnd *tmp = NULL, *prev; ! 1887: AM53C974_setio(instance); ! 1888: ! 1889: cfifo = AM53C974_cfifo(); ! 1890: ! 1891: if (hostdata->selecting) { ! 1892: /* caught reselect interrupt in selection process; ! 1893: put selecting command back into the issue queue and continue with the ! 1894: reselecting command */ ! 1895: DEB_RESEL(printk("AM53C974_intr_reselect: in selection process\n")); ! 1896: LIST(hostdata->sel_cmd, hostdata->issue_queue); ! 1897: hostdata->sel_cmd->host_scribble = (unsigned char *)hostdata->issue_queue; ! 1898: hostdata->issue_queue = hostdata->sel_cmd; ! 1899: hostdata->sel_cmd = NULL; ! 1900: hostdata->selecting = 0; } ! 1901: ! 1902: /* 2 bytes must be in the FIFO now */ ! 1903: if (cfifo != 2) { ! 1904: printk("scsi %d: error: %d bytes in fifo, 2 expected\n", instance->host_no, cfifo); ! 1905: hostdata->aborted = 1; ! 1906: goto EXIT_ABORT; } ! 1907: ! 1908: /* determine target which reselected */ ! 1909: t = AM53C974_read_8(FFREG); ! 1910: if (!(t & (1 << instance->this_id))) { ! 1911: printk("scsi %d: error: invalid host id\n", instance->host_no); ! 1912: hostdata->aborted = 1; ! 1913: goto EXIT_ABORT; } ! 1914: t ^= (1 << instance->this_id); ! 1915: target = 0; while (t != 1) { t >>= 1; target++; } ! 1916: DEB_RESEL(printk("scsi %d: reselect; target: %d\n", instance->host_no, target)); ! 1917: ! 1918: if (hostdata->aborted) goto EXIT_ABORT; ! 1919: ! 1920: if ((statreg & STATREG_PHASE) != PHASE_MSGIN) { ! 1921: printk("scsi %d: error: upon reselection interrupt not in MSGIN\n", instance->host_no); ! 1922: hostdata->aborted = 1; ! 1923: goto EXIT_ABORT; } ! 1924: ! 1925: msg[0] = AM53C974_read_8(FFREG); ! 1926: if (!msg[0] & 0x80) { ! 1927: printk("scsi%d: error: expecting IDENTIFY message, got ", instance->host_no); ! 1928: print_msg(msg); ! 1929: hostdata->aborted = 1; ! 1930: goto EXIT_ABORT; } ! 1931: ! 1932: lun = (msg[0] & 0x07); ! 1933: ! 1934: /* We need to add code for SCSI-II to track which devices have ! 1935: * I_T_L_Q nexuses established, and which have simple I_T_L ! 1936: * nexuses so we can chose to do additional data transfer. */ ! 1937: #ifdef SCSI2 ! 1938: #error "SCSI-II tagged queueing is not supported yet" ! 1939: #endif ! 1940: ! 1941: /* Find the command corresponding to the I_T_L or I_T_L_Q nexus we ! 1942: * just reestablished, and remove it from the disconnected queue. */ ! 1943: for (tmp = (Scsi_Cmnd *)hostdata->disconnected_queue, prev = NULL; ! 1944: tmp; prev = tmp, tmp = (Scsi_Cmnd *)tmp->host_scribble) ! 1945: if ((target == tmp->target) && (lun == tmp->lun) ! 1946: #ifdef SCSI2 ! 1947: && (tag == tmp->tag) ! 1948: #endif ! 1949: ) { ! 1950: if (prev) { ! 1951: REMOVE(prev, (Scsi_Cmnd *)(prev->host_scribble), tmp, ! 1952: (Scsi_Cmnd *)(tmp->host_scribble)); ! 1953: prev->host_scribble = tmp->host_scribble; } ! 1954: else { ! 1955: REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble); ! 1956: hostdata->disconnected_queue = (Scsi_Cmnd *)tmp->host_scribble; } ! 1957: tmp->host_scribble = NULL; ! 1958: hostdata->connected = tmp; ! 1959: break; } ! 1960: ! 1961: if (!tmp) { ! 1962: #ifdef SCSI2 ! 1963: printk("scsi%d: warning : target %d lun %d tag %d not in disconnect_queue.\n", ! 1964: instance->host_no, target, lun, tag); ! 1965: #else ! 1966: printk("scsi%d: warning : target %d lun %d not in disconnect_queue.\n", ! 1967: instance->host_no, target, lun); ! 1968: #endif ! 1969: /* Since we have an established nexus that we can't do anything with, we must abort it. */ ! 1970: hostdata->aborted = 1; ! 1971: DEB(AM53C974_keywait()); ! 1972: goto EXIT_ABORT; } ! 1973: else ! 1974: goto EXIT_OK; ! 1975: ! 1976: EXIT_ABORT: ! 1977: AM53C974_write_8(CMDREG, CMDREG_SATN); ! 1978: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1979: return; ! 1980: ! 1981: EXIT_OK: ! 1982: DEB_RESEL(printk("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", ! 1983: instance->host_no, target, tmp->lun, tmp->tag)); ! 1984: AM53C974_set_sync(instance, target); ! 1985: AM53C974_write_8(SDIDREG, SDIREG_MASK & target); /* setup dest. id */ ! 1986: AM53C974_write_8(CMDREG, CMDREG_MA); ! 1987: hostdata->dma_busy = 0; ! 1988: hostdata->connected->SCp.phase = PHASE_CMDOUT; ! 1989: } ! 1990: ! 1991: /************************************************************************** ! 1992: * Function : AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, ! 1993: * unsigned long length, char *data) ! 1994: * ! 1995: * Purpose : setup DMA transfer ! 1996: * ! 1997: * Inputs : instance -- which AM53C974 ! 1998: * dir -- direction flag, 0: write to device, read from memory; ! 1999: * 1: read from device, write to memory ! 2000: * length -- number of bytes to transfer to from buffer ! 2001: * data -- pointer to data buffer ! 2002: * ! 2003: * Returns : nothing ! 2004: **************************************************************************/ ! 2005: static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, ! 2006: unsigned long length, char *data) ! 2007: { ! 2008: AM53C974_local_declare(); ! 2009: AM53C974_setio(instance); ! 2010: ! 2011: AM53C974_write_8(CMDREG, CMDREG_NOP); ! 2012: AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D); /* idle command */ ! 2013: AM53C974_write_8(STCLREG, (unsigned char)(length & 0xff)); ! 2014: AM53C974_write_8(STCMREG, (unsigned char)((length & 0xff00) >> 8)); ! 2015: AM53C974_write_8(STCHREG, (unsigned char)((length & 0xff0000) >> 16)); ! 2016: AM53C974_write_32(DMASTC, length & 0xffffff); ! 2017: AM53C974_write_32(DMASPA, (unsigned long)data); ! 2018: AM53C974_write_8(CMDREG, CMDREG_IT | CMDREG_DMA); ! 2019: AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D | DMACMD_START); ! 2020: } ! 2021: ! 2022: /************************************************************************** ! 2023: * Function : AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, ! 2024: * unsigned char statreg) ! 2025: * ! 2026: * Purpose : cleanup DMA transfer ! 2027: * ! 2028: * Inputs : instance -- which AM53C974 ! 2029: * dmastatus -- dma status register ! 2030: * statreg -- status register ! 2031: * ! 2032: * Returns : nothing ! 2033: **************************************************************************/ ! 2034: static void AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, ! 2035: unsigned char statreg) ! 2036: { ! 2037: AM53C974_local_declare(); ! 2038: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 2039: unsigned long ctcreg; ! 2040: int dir = statreg & STATREG_IO; ! 2041: int cfifo, pio, i = 0; ! 2042: AM53C974_setio(instance); ! 2043: ! 2044: do { ! 2045: cfifo = AM53C974_cfifo(); ! 2046: i++; ! 2047: } while (cfifo && (i < 50000)); ! 2048: pio = (i == 50000) ? 1: 0; ! 2049: ! 2050: if (statreg & STATREG_CTZ) { AM53C974_write_8(DMACMD, DMACMD_IDLE); return; } ! 2051: ! 2052: if (dmastatus & DMASTATUS_DONE) { AM53C974_write_8(DMACMD, DMACMD_IDLE); return; } ! 2053: ! 2054: AM53C974_write_8(DMACMD, ((dir << 7) & DMACMD_DIR) | DMACMD_BLAST); ! 2055: while(!(AM53C974_read_8(DMASTATUS) & DMASTATUS_BCMPLT)) ; ! 2056: AM53C974_write_8(DMACMD, DMACMD_IDLE); ! 2057: ! 2058: if (pio) { ! 2059: /* transfer residual bytes via PIO */ ! 2060: unsigned char *wac = (unsigned char *)AM53C974_read_32(DMAWAC); ! 2061: printk("pio mode, residual=%d\n", AM53C974_read_8(CFIREG) & CFIREG_CF); ! 2062: while (AM53C974_read_8(CFIREG) & CFIREG_CF) *(wac++) = AM53C974_read_8(FFREG); ! 2063: } ! 2064: ! 2065: ctcreg = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | ! 2066: (AM53C974_read_8(CTCHREG) << 16); ! 2067: ! 2068: hostdata->connected->SCp.ptr += hostdata->connected->SCp.this_residual - ctcreg; ! 2069: hostdata->connected->SCp.this_residual = ctcreg; ! 2070: } ! 2071: ! 2072: /************************************************************************** ! 2073: * Function : AM53C974_intr_bus_reset(struct Scsi_Host *instance) ! 2074: * ! 2075: * Purpose : handle bus reset interrupt ! 2076: * ! 2077: * Inputs : instance -- which AM53C974 ! 2078: * ! 2079: * Returns : nothing ! 2080: **************************************************************************/ ! 2081: static void AM53C974_intr_bus_reset(struct Scsi_Host *instance) ! 2082: { ! 2083: AM53C974_local_declare(); ! 2084: unsigned char cntlreg1; ! 2085: AM53C974_setio(instance); ! 2086: ! 2087: AM53C974_write_8(CMDREG, CMDREG_CFIFO); ! 2088: AM53C974_write_8(CMDREG, CMDREG_NOP); ! 2089: ! 2090: cntlreg1 = AM53C974_read_8(CNTLREG1); ! 2091: AM53C974_write_8(CNTLREG1, cntlreg1 | CNTLREG1_DISR); ! 2092: } ! 2093: ! 2094: /************************************************************************** ! 2095: * Function : int AM53C974_abort(Scsi_Cmnd *cmd) ! 2096: * ! 2097: * Purpose : abort a command ! 2098: * ! 2099: * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the ! 2100: * host byte of the result field to, if zero DID_ABORTED is ! 2101: * used. ! 2102: * ! 2103: * Returns : 0 - success, -1 on failure. ! 2104: **************************************************************************/ ! 2105: int AM53C974_abort(Scsi_Cmnd *cmd) ! 2106: { ! 2107: AM53C974_local_declare(); ! 2108: struct Scsi_Host *instance = cmd->host; ! 2109: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 2110: Scsi_Cmnd *tmp, **prev; ! 2111: ! 2112: #ifdef AM53C974_DEBUG ! 2113: deb_stop = 1; ! 2114: #endif ! 2115: cli(); ! 2116: AM53C974_setio(instance); ! 2117: ! 2118: DEB_ABORT(printk(SEPARATOR_LINE)); ! 2119: DEB_ABORT(printk("scsi%d : AM53C974_abort called -- trouble starts!!\n", instance->host_no)); ! 2120: DEB_ABORT(AM53C974_print(instance)); ! 2121: DEB_ABORT(AM53C974_keywait()); ! 2122: ! 2123: /* Case 1 : If the command is the currently executing command, ! 2124: we'll set the aborted flag and return control so that the ! 2125: information transfer routine can exit cleanly. */ ! 2126: if ((hostdata->connected == cmd) || (hostdata->sel_cmd == cmd)) { ! 2127: DEB_ABORT(printk("scsi%d: aborting connected command\n", instance->host_no)); ! 2128: hostdata->aborted = 1; ! 2129: hostdata->msgout[0] = ABORT; ! 2130: sti(); ! 2131: return(SCSI_ABORT_PENDING); } ! 2132: ! 2133: /* Case 2 : If the command hasn't been issued yet, ! 2134: we simply remove it from the issue queue. */ ! 2135: for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue), ! 2136: tmp = (Scsi_Cmnd *)hostdata->issue_queue; tmp; ! 2137: prev = (Scsi_Cmnd **)&(tmp->host_scribble), ! 2138: tmp = (Scsi_Cmnd *)tmp->host_scribble) { ! 2139: if (cmd == tmp) { ! 2140: DEB_ABORT(printk("scsi%d : abort removed command from issue queue.\n", instance->host_no)); ! 2141: REMOVE(5, *prev, tmp, tmp->host_scribble); ! 2142: (*prev) = (Scsi_Cmnd *)tmp->host_scribble; ! 2143: tmp->host_scribble = NULL; ! 2144: tmp->result = DID_ABORT << 16; ! 2145: sti(); ! 2146: tmp->done(tmp); ! 2147: return(SCSI_ABORT_SUCCESS); } ! 2148: #ifdef AM53C974_DEBUG_ABORT ! 2149: else { ! 2150: if (prev == (Scsi_Cmnd **)tmp) ! 2151: printk("scsi%d : LOOP\n", instance->host_no); ! 2152: } ! 2153: #endif ! 2154: } ! 2155: ! 2156: /* Case 3 : If any commands are connected, we're going to fail the abort ! 2157: * and let the high level SCSI driver retry at a later time or ! 2158: * issue a reset. ! 2159: * ! 2160: * Timeouts, and therefore aborted commands, will be highly unlikely ! 2161: * and handling them cleanly in this situation would make the common ! 2162: * case of noresets less efficient, and would pollute our code. So, ! 2163: * we fail. */ ! 2164: if (hostdata->connected || hostdata->sel_cmd) { ! 2165: DEB_ABORT(printk("scsi%d : abort failed, other command connected.\n", instance->host_no)); ! 2166: sti(); ! 2167: return(SCSI_ABORT_NOT_RUNNING); } ! 2168: ! 2169: /* Case 4: If the command is currently disconnected from the bus, and ! 2170: * there are no connected commands, we reconnect the I_T_L or ! 2171: * I_T_L_Q nexus associated with it, go into message out, and send ! 2172: * an abort message. */ ! 2173: for (tmp = (Scsi_Cmnd *)hostdata->disconnected_queue; tmp; ! 2174: tmp = (Scsi_Cmnd *)tmp->host_scribble) { ! 2175: if (cmd == tmp) { ! 2176: DEB_ABORT(printk("scsi%d: aborting disconnected command\n", instance->host_no)); ! 2177: hostdata->aborted = 1; ! 2178: hostdata->msgout[0] = ABORT; ! 2179: hostdata->selecting = 1; ! 2180: hostdata->sel_cmd = tmp; ! 2181: AM53C974_write_8(CMDREG, CMDREG_DSR); ! 2182: sti(); ! 2183: return(SCSI_ABORT_PENDING); } ! 2184: } ! 2185: ! 2186: /* Case 5 : If we reached this point, the command was not found in any of ! 2187: * the queues. ! 2188: * ! 2189: * We probably reached this point because of an unlikely race condition ! 2190: * between the command completing successfully and the abortion code, ! 2191: * so we won't panic, but we will notify the user in case something really ! 2192: * broke. */ ! 2193: DEB_ABORT(printk("scsi%d : abort failed, command not found.\n", instance->host_no)); ! 2194: sti(); ! 2195: return(SCSI_ABORT_NOT_RUNNING); ! 2196: } ! 2197: ! 2198: /************************************************************************** ! 2199: * Function : int AM53C974_reset(Scsi_Cmnd *cmd) ! 2200: * ! 2201: * Purpose : reset the SCSI controller and bus ! 2202: * ! 2203: * Inputs : cmd -- which command within the command block was responsible for the reset ! 2204: * ! 2205: * Returns : status (SCSI_ABORT_SUCCESS) ! 2206: **************************************************************************/ ! 2207: int AM53C974_reset(Scsi_Cmnd *cmd) ! 2208: { ! 2209: AM53C974_local_declare(); ! 2210: int i; ! 2211: struct Scsi_Host *instance = cmd->host; ! 2212: struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; ! 2213: AM53C974_setio(instance); ! 2214: ! 2215: cli(); ! 2216: DEB(printk("AM53C974_reset called; ")); ! 2217: ! 2218: printk("AM53C974_reset called\n"); ! 2219: AM53C974_print(instance); ! 2220: AM53C974_keywait(); ! 2221: ! 2222: /* do hard reset */ ! 2223: AM53C974_write_8(CMDREG, CMDREG_RDEV); ! 2224: AM53C974_write_8(CMDREG, CMDREG_NOP); ! 2225: hostdata->msgout[0] = NOP; ! 2226: for (i = 0; i < 8; i++) { ! 2227: hostdata->busy[i] = 0; ! 2228: hostdata->sync_per[i] = DEF_STP; ! 2229: hostdata->sync_off[i] = 0; ! 2230: hostdata->sync_neg[i] = 0; } ! 2231: hostdata->last_message[0] = NOP; ! 2232: hostdata->sel_cmd = NULL; ! 2233: hostdata->connected = NULL; ! 2234: hostdata->issue_queue = NULL; ! 2235: hostdata->disconnected_queue = NULL; ! 2236: hostdata->in_reset = 0; ! 2237: hostdata->aborted = 0; ! 2238: hostdata->selecting = 0; ! 2239: hostdata->disconnecting = 0; ! 2240: hostdata->dma_busy = 0; ! 2241: ! 2242: /* reset bus */ ! 2243: AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id); /* disable interrupt upon SCSI RESET */ ! 2244: AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */ ! 2245: udelay(40); ! 2246: AM53C974_config_after_reset(instance); ! 2247: ! 2248: sti(); ! 2249: cmd->result = DID_RESET << 16; ! 2250: cmd->scsi_done(cmd); ! 2251: return SCSI_ABORT_SUCCESS; ! 2252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.