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