|
|
1.1 ! root 1: /* $Id: wd7000.c,v 1.1.1.1 1997/02/25 21:27:53 thomas Exp $ ! 2: * linux/drivers/scsi/wd7000.c ! 3: * ! 4: * Copyright (C) 1992 Thomas Wuensche ! 5: * closely related to the aha1542 driver from Tommy Thorn ! 6: * ( as close as different hardware allows on a lowlevel-driver :-) ) ! 7: * ! 8: * Revised (and renamed) by John Boyd <[email protected]> to ! 9: * accommodate Eric Youngdale's modifications to scsi.c. Nov 1992. ! 10: * ! 11: * Additional changes to support scatter/gather. Dec. 1992. tw/jb ! 12: * ! 13: * No longer tries to reset SCSI bus at boot (it wasn't working anyway). ! 14: * Rewritten to support multiple host adapters. ! 15: * Miscellaneous cleanup. ! 16: * So far, still doesn't do reset or abort correctly, since I have no idea ! 17: * how to do them with this board (8^(. Jan 1994 jb ! 18: * ! 19: * This driver now supports both of the two standard configurations (per ! 20: * the 3.36 Owner's Manual, my latest reference) by the same method as ! 21: * before; namely, by looking for a BIOS signature. Thus, the location of ! 22: * the BIOS signature determines the board configuration. Until I have ! 23: * time to do something more flexible, users should stick to one of the ! 24: * following: ! 25: * ! 26: * Standard configuration for single-adapter systems: ! 27: * - BIOS at CE00h ! 28: * - I/O base address 350h ! 29: * - IRQ level 15 ! 30: * - DMA channel 6 ! 31: * Standard configuration for a second adapter in a system: ! 32: * - BIOS at C800h ! 33: * - I/O base address 330h ! 34: * - IRQ level 11 ! 35: * - DMA channel 5 ! 36: * ! 37: * Anyone who can recompile the kernel is welcome to add others as need ! 38: * arises, but unpredictable results may occur if there are conflicts. ! 39: * In any event, if there are multiple adapters in a system, they MUST ! 40: * use different I/O bases, IRQ levels, and DMA channels, since they will be ! 41: * indistinguishable (and in direct conflict) otherwise. ! 42: * ! 43: * As a point of information, the NO_OP command toggles the CMD_RDY bit ! 44: * of the status port, and this fact could be used as a test for the I/O ! 45: * base address (or more generally, board detection). There is an interrupt ! 46: * status port, so IRQ probing could also be done. I suppose the full ! 47: * DMA diagnostic could be used to detect the DMA channel being used. I ! 48: * haven't done any of this, though, because I think there's too much of ! 49: * a chance that such explorations could be destructive, if some other ! 50: * board's resources are used inadvertently. So, call me a wimp, but I ! 51: * don't want to try it. The only kind of exploration I trust is memory ! 52: * exploration, since it's more certain that reading memory won't be ! 53: * destructive. ! 54: * ! 55: * More to my liking would be a LILO boot command line specification, such ! 56: * as is used by the aha152x driver (and possibly others). I'll look into ! 57: * it, as I have time... ! 58: * ! 59: * I get mail occasionally from people who either are using or are ! 60: * considering using a WD7000 with Linux. There is a variety of ! 61: * nomenclature describing WD7000's. To the best of my knowledge, the ! 62: * following is a brief summary (from an old WD doc - I don't work for ! 63: * them or anything like that): ! 64: * ! 65: * WD7000-FASST2: This is a WD7000 board with the real-mode SST ROM BIOS ! 66: * installed. Last I heard, the BIOS was actually done by Columbia ! 67: * Data Products. The BIOS is only used by this driver (and thus ! 68: * by Linux) to identify the board; none of it can be executed under ! 69: * Linux. ! 70: * ! 71: * WD7000-ASC: This is the original adapter board, with or without BIOS. ! 72: * The board uses a WD33C93 or WD33C93A SBIC, which in turn is ! 73: * controlled by an onboard Z80 processor. The board interface ! 74: * visible to the host CPU is defined effectively by the Z80's ! 75: * firmware, and it is this firmware's revision level that is ! 76: * determined and reported by this driver. (The version of the ! 77: * on-board BIOS is of no interest whatsoever.) The host CPU has ! 78: * no access to the SBIC; hence the fact that it is a WD33C93 is ! 79: * also of no interest to this driver. ! 80: * ! 81: * WD7000-AX: ! 82: * WD7000-MX: ! 83: * WD7000-EX: These are newer versions of the WD7000-ASC. The -ASC is ! 84: * largely built from discrete components; these boards use more ! 85: * integration. The -AX is an ISA bus board (like the -ASC), ! 86: * the -MX is an MCA (i.e., PS/2) bus board), and the -EX is an ! 87: * EISA bus board. ! 88: * ! 89: * At the time of my documentation, the -?X boards were "future" products, ! 90: * and were not yet available. However, I vaguely recall that Thomas ! 91: * Wuensche had an -AX, so I believe at least it is supported by this ! 92: * driver. I have no personal knowledge of either -MX or -EX boards. ! 93: * ! 94: * P.S. Just recently, I've discovered (directly from WD and Future ! 95: * Domain) that all but the WD7000-EX have been out of production for ! 96: * two years now. FD has production rights to the 7000-EX, and are ! 97: * producing it under a new name, and with a new BIOS. If anyone has ! 98: * one of the FD boards, it would be nice to come up with a signature ! 99: * for it. ! 100: * J.B. Jan 1994. ! 101: */ ! 102: ! 103: #ifdef MODULE ! 104: #include <linux/module.h> ! 105: #endif ! 106: ! 107: #include <stdarg.h> ! 108: #include <linux/kernel.h> ! 109: #include <linux/head.h> ! 110: #include <linux/types.h> ! 111: #include <linux/string.h> ! 112: #include <linux/sched.h> ! 113: #include <linux/malloc.h> ! 114: #include <asm/system.h> ! 115: #include <asm/dma.h> ! 116: #include <asm/io.h> ! 117: #include <linux/ioport.h> ! 118: #include <linux/proc_fs.h> ! 119: #include <linux/blk.h> ! 120: #include "scsi.h" ! 121: #include "hosts.h" ! 122: #include "sd.h" ! 123: ! 124: #define ANY2SCSI_INLINE /* undef this to use old macros */ ! 125: #undef DEBUG ! 126: ! 127: #include "wd7000.h" ! 128: ! 129: #include<linux/stat.h> ! 130: ! 131: struct proc_dir_entry proc_scsi_wd7000 = { ! 132: PROC_SCSI_7000FASST, 6, "wd7000", ! 133: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 134: }; ! 135: ! 136: ! 137: /* ! 138: * Mailbox structure sizes. ! 139: * I prefer to keep the number of ICMBs much larger than the number of ! 140: * OGMBs. OGMBs are used very quickly by the driver to start one or ! 141: * more commands, while ICMBs are used by the host adapter per command. ! 142: */ ! 143: #define OGMB_CNT 16 ! 144: #define ICMB_CNT 32 ! 145: ! 146: /* ! 147: * Scb's are shared by all active adapters. So, if they all become busy, ! 148: * callers may be made to wait in alloc_scbs for them to free. That can ! 149: * be avoided by setting MAX_SCBS to NUM_CONFIG * WD7000_Q. If you'd ! 150: * rather conserve memory, use a smaller number (> 0, of course) - things ! 151: * will should still work OK. ! 152: */ ! 153: #define MAX_SCBS 32 ! 154: ! 155: /* ! 156: * WD7000-specific mailbox structure ! 157: * ! 158: */ ! 159: typedef volatile struct mailbox{ ! 160: unchar status; ! 161: unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */ ! 162: } Mailbox; ! 163: ! 164: /* ! 165: * This structure should contain all per-adapter global data. I.e., any ! 166: * new global per-adapter data should put in here. ! 167: * ! 168: */ ! 169: typedef struct adapter { ! 170: struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */ ! 171: int iobase; /* This adapter's I/O base address */ ! 172: int irq; /* This adapter's IRQ level */ ! 173: int dma; /* This adapter's DMA channel */ ! 174: struct { /* This adapter's mailboxes */ ! 175: Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */ ! 176: Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */ ! 177: } mb; ! 178: int next_ogmb; /* to reduce contention at mailboxes */ ! 179: unchar control; /* shadows CONTROL port value */ ! 180: unchar rev1, rev2; /* filled in by wd7000_revision */ ! 181: } Adapter; ! 182: ! 183: /* ! 184: * The following is set up by wd7000_detect, and used thereafter by ! 185: * wd7000_intr_handle to map the irq level to the corresponding Adapter. ! 186: * Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be ! 187: * changed to pick up the IRQ level correctly. ! 188: */ ! 189: Adapter *irq2host[16] = {NULL}; /* Possible IRQs are 0-15 */ ! 190: ! 191: /* ! 192: * Standard Adapter Configurations - used by wd7000_detect ! 193: */ ! 194: typedef struct { ! 195: const void *bios; /* (linear) base address for ROM BIOS */ ! 196: int iobase; /* I/O ports base address */ ! 197: int irq; /* IRQ level */ ! 198: int dma; /* DMA channel */ ! 199: } Config; ! 200: ! 201: static const Config configs[] = { ! 202: {(void *) 0xce000, 0x350, 15, 6}, /* defaults for single adapter */ ! 203: {(void *) 0xc8000, 0x330, 11, 5}, /* defaults for second adapter */ ! 204: {(void *) 0xd8000, 0x350, 15, 6}, /* Arghhh.... who added this ? */ ! 205: }; ! 206: #define NUM_CONFIGS (sizeof(configs)/sizeof(Config)) ! 207: ! 208: /* ! 209: * The following list defines strings to look for in the BIOS that identify ! 210: * it as the WD7000-FASST2 SST BIOS. I suspect that something should be ! 211: * added for the Future Domain version. ! 212: */ ! 213: typedef struct signature { ! 214: const void *sig; /* String to look for */ ! 215: unsigned ofs; /* offset from BIOS base address */ ! 216: unsigned len; /* length of string */ ! 217: } Signature; ! 218: ! 219: static const Signature signatures[] = { ! 220: {"SSTBIOS",0x0000d,7} /* "SSTBIOS" @ offset 0x0000d */ ! 221: }; ! 222: #define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) ! 223: ! 224: ! 225: /* ! 226: * I/O Port Offsets and Bit Definitions ! 227: * 4 addresses are used. Those not defined here are reserved. ! 228: */ ! 229: #define ASC_STAT 0 /* Status, Read */ ! 230: #define ASC_COMMAND 0 /* Command, Write */ ! 231: #define ASC_INTR_STAT 1 /* Interrupt Status, Read */ ! 232: #define ASC_INTR_ACK 1 /* Acknowledge, Write */ ! 233: #define ASC_CONTROL 2 /* Control, Write */ ! 234: ! 235: /* ASC Status Port ! 236: */ ! 237: #define INT_IM 0x80 /* Interrupt Image Flag */ ! 238: #define CMD_RDY 0x40 /* Command Port Ready */ ! 239: #define CMD_REJ 0x20 /* Command Port Byte Rejected */ ! 240: #define ASC_INIT 0x10 /* ASC Initialized Flag */ ! 241: #define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */ ! 242: ! 243: /* COMMAND opcodes ! 244: * ! 245: * Unfortunately, I have no idea how to properly use some of these commands, ! 246: * as the OEM manual does not make it clear. I have not been able to use ! 247: * enable/disable unsolicited interrupts or the reset commands with any ! 248: * discernible effect whatsoever. I think they may be related to certain ! 249: * ICB commands, but again, the OEM manual doesn't make that clear. ! 250: */ ! 251: #define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */ ! 252: #define INITIALIZATION 1 /* initialization (10 bytes) */ ! 253: #define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */ ! 254: #define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */ ! 255: #define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */ ! 256: #define SOFT_RESET 5 /* SCSI bus soft reset */ ! 257: #define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */ ! 258: #define START_OGMB 0x80 /* start command in OGMB (n) */ ! 259: #define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */ ! 260: /* where (n) = lower 6 bits */ ! 261: /* For INITIALIZATION: ! 262: */ ! 263: typedef struct initCmd { ! 264: unchar op; /* command opcode (= 1) */ ! 265: unchar ID; /* Adapter's SCSI ID */ ! 266: unchar bus_on; /* Bus on time, x 125ns (see below) */ ! 267: unchar bus_off; /* Bus off time, "" "" */ ! 268: unchar rsvd; /* Reserved */ ! 269: unchar mailboxes[3]; /* Address of Mailboxes, MSB first */ ! 270: unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ ! 271: unchar icmbs; /* Number of incoming MBs, "" "" */ ! 272: } InitCmd; ! 273: ! 274: #define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ ! 275: #define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */ ! 276: ! 277: /* Interrupt Status Port - also returns diagnostic codes at ASC reset ! 278: * ! 279: * if msb is zero, the lower bits are diagnostic status ! 280: * Diagnostics: ! 281: * 01 No diagnostic error occurred ! 282: * 02 RAM failure ! 283: * 03 FIFO R/W failed ! 284: * 04 SBIC register read/write failed ! 285: * 05 Initialization D-FF failed ! 286: * 06 Host IRQ D-FF failed ! 287: * 07 ROM checksum error ! 288: * Interrupt status (bitwise): ! 289: * 10NNNNNN outgoing mailbox NNNNNN is free ! 290: * 11NNNNNN incoming mailbox NNNNNN needs service ! 291: */ ! 292: #define MB_INTR 0xC0 /* Mailbox Service possible/required */ ! 293: #define IMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */ ! 294: #define MB_MASK 0x3f /* mask for mailbox number */ ! 295: ! 296: /* CONTROL port bits ! 297: */ ! 298: #define INT_EN 0x08 /* Interrupt Enable */ ! 299: #define DMA_EN 0x04 /* DMA Enable */ ! 300: #define SCSI_RES 0x02 /* SCSI Reset */ ! 301: #define ASC_RES 0x01 /* ASC Reset */ ! 302: ! 303: /* ! 304: Driver data structures: ! 305: - mb and scbs are required for interfacing with the host adapter. ! 306: An SCB has extra fields not visible to the adapter; mb's ! 307: _cannot_ do this, since the adapter assumes they are contiguous in ! 308: memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact ! 309: to access them. ! 310: - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each; ! 311: the additional bytes are used only by the driver. ! 312: - For now, a pool of SCBs are kept in global storage by this driver, ! 313: and are allocated and freed as needed. ! 314: ! 315: The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command, ! 316: not when it has finished. Since the SCB must be around for completion, ! 317: problems arise when SCBs correspond to OGMBs, which may be reallocated ! 318: earlier (or delayed unnecessarily until a command completes). ! 319: Mailboxes are used as transient data structures, simply for ! 320: carrying SCB addresses to/from the 7000-FASST2. ! 321: ! 322: Note also since SCBs are not "permanently" associated with mailboxes, ! 323: there is no need to keep a global list of Scsi_Cmnd pointers indexed ! 324: by OGMB. Again, SCBs reference their Scsi_Cmnds directly, so mailbox ! 325: indices need not be involved. ! 326: */ ! 327: ! 328: /* ! 329: * WD7000-specific scatter/gather element structure ! 330: */ ! 331: typedef struct sgb { ! 332: unchar len[3]; ! 333: unchar ptr[3]; /* Also SCSI-style - MSB first */ ! 334: } Sgb; ! 335: ! 336: typedef struct scb { /* Command Control Block 5.4.1 */ ! 337: unchar op; /* Command Control Block Operation Code */ ! 338: unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ ! 339: /* Outbound data transfer, length is checked*/ ! 340: /* Inbound data transfer, length is checked */ ! 341: /* Logical Unit Number */ ! 342: unchar cdb[12]; /* SCSI Command Block */ ! 343: volatile unchar status; /* SCSI Return Status */ ! 344: volatile unchar vue; /* Vendor Unique Error Code */ ! 345: unchar maxlen[3]; /* Maximum Data Transfer Length */ ! 346: unchar dataptr[3]; /* SCSI Data Block Pointer */ ! 347: unchar linkptr[3]; /* Next Command Link Pointer */ ! 348: unchar direc; /* Transfer Direction */ ! 349: unchar reserved2[6]; /* SCSI Command Descriptor Block */ ! 350: /* end of hardware SCB */ ! 351: Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */ ! 352: Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */ ! 353: Adapter *host; /* host adapter */ ! 354: struct scb *next; /* for lists of scbs */ ! 355: } Scb; ! 356: ! 357: /* ! 358: * This driver is written to allow host-only commands to be executed. ! 359: * These use a 16-byte block called an ICB. The format is extended by the ! 360: * driver to 18 bytes, to support the status returned in the ICMB and ! 361: * an execution phase code. ! 362: * ! 363: * There are other formats besides these; these are the ones I've tried ! 364: * to use. Formats for some of the defined ICB opcodes are not defined ! 365: * (notably, get/set unsolicited interrupt status) in my copy of the OEM ! 366: * manual, and others are ambiguous/hard to follow. ! 367: */ ! 368: #define ICB_OP_MASK 0x80 /* distinguishes scbs from icbs */ ! 369: #define ICB_OP_OPEN_RBUF 0x80 /* open receive buffer */ ! 370: #define ICB_OP_RECV_CMD 0x81 /* receive command from initiator */ ! 371: #define ICB_OP_RECV_DATA 0x82 /* receive data from initiator */ ! 372: #define ICB_OP_RECV_SDATA 0x83 /* receive data with status from init. */ ! 373: #define ICB_OP_SEND_DATA 0x84 /* send data with status to initiator */ ! 374: #define ICB_OP_SEND_STAT 0x86 /* send command status to initiator */ ! 375: /* 0x87 is reserved */ ! 376: #define ICB_OP_READ_INIT 0x88 /* read initialization bytes */ ! 377: #define ICB_OP_READ_ID 0x89 /* read adapter's SCSI ID */ ! 378: #define ICB_OP_SET_UMASK 0x8A /* set unsolicited interrupt mask */ ! 379: #define ICB_OP_GET_UMASK 0x8B /* read unsolicited interrupt mask */ ! 380: #define ICB_OP_GET_REVISION 0x8C /* read firmware revision level */ ! 381: #define ICB_OP_DIAGNOSTICS 0x8D /* execute diagnostics */ ! 382: #define ICB_OP_SET_EPARMS 0x8E /* set execution parameters */ ! 383: #define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */ ! 384: ! 385: typedef struct icbRecvCmd { ! 386: unchar op; ! 387: unchar IDlun; /* Initiator SCSI ID/lun */ ! 388: unchar len[3]; /* command buffer length */ ! 389: unchar ptr[3]; /* command buffer address */ ! 390: unchar rsvd[7]; /* reserved */ ! 391: volatile unchar vue; /* vendor-unique error code */ ! 392: volatile unchar status; /* returned (icmb) status */ ! 393: volatile unchar phase; /* used by interrupt handler */ ! 394: } IcbRecvCmd; ! 395: ! 396: typedef struct icbSendStat { ! 397: unchar op; ! 398: unchar IDlun; /* Target SCSI ID/lun */ ! 399: unchar stat; /* (outgoing) completion status byte 1 */ ! 400: unchar rsvd[12]; /* reserved */ ! 401: volatile unchar vue; /* vendor-unique error code */ ! 402: volatile unchar status; /* returned (icmb) status */ ! 403: volatile unchar phase; /* used by interrupt handler */ ! 404: } IcbSendStat; ! 405: ! 406: typedef struct icbRevLvl { ! 407: unchar op; ! 408: volatile unchar primary; /* primary revision level (returned) */ ! 409: volatile unchar secondary; /* secondary revision level (returned) */ ! 410: unchar rsvd[12]; /* reserved */ ! 411: volatile unchar vue; /* vendor-unique error code */ ! 412: volatile unchar status; /* returned (icmb) status */ ! 413: volatile unchar phase; /* used by interrupt handler */ ! 414: } IcbRevLvl; ! 415: ! 416: typedef struct icbUnsMask { /* I'm totally guessing here */ ! 417: unchar op; ! 418: volatile unchar mask[14]; /* mask bits */ ! 419: #ifdef 0 ! 420: unchar rsvd[12]; /* reserved */ ! 421: #endif ! 422: volatile unchar vue; /* vendor-unique error code */ ! 423: volatile unchar status; /* returned (icmb) status */ ! 424: volatile unchar phase; /* used by interrupt handler */ ! 425: } IcbUnsMask; ! 426: ! 427: typedef struct icbDiag { ! 428: unchar op; ! 429: unchar type; /* diagnostics type code (0-3) */ ! 430: unchar len[3]; /* buffer length */ ! 431: unchar ptr[3]; /* buffer address */ ! 432: unchar rsvd[7]; /* reserved */ ! 433: volatile unchar vue; /* vendor-unique error code */ ! 434: volatile unchar status; /* returned (icmb) status */ ! 435: volatile unchar phase; /* used by interrupt handler */ ! 436: } IcbDiag; ! 437: ! 438: #define ICB_DIAG_POWERUP 0 /* Power-up diags only */ ! 439: #define ICB_DIAG_WALKING 1 /* walking 1's pattern */ ! 440: #define ICB_DIAG_DMA 2 /* DMA - system memory diags */ ! 441: #define ICB_DIAG_FULL 3 /* do both 1 & 2 */ ! 442: ! 443: typedef struct icbParms { ! 444: unchar op; ! 445: unchar rsvd1; /* reserved */ ! 446: unchar len[3]; /* parms buffer length */ ! 447: unchar ptr[3]; /* parms buffer address */ ! 448: unchar idx[2]; /* index (MSB-LSB) */ ! 449: unchar rsvd2[5]; /* reserved */ ! 450: volatile unchar vue; /* vendor-unique error code */ ! 451: volatile unchar status; /* returned (icmb) status */ ! 452: volatile unchar phase; /* used by interrupt handler */ ! 453: } IcbParms; ! 454: ! 455: typedef struct icbAny { ! 456: unchar op; ! 457: unchar data[14]; /* format-specific data */ ! 458: volatile unchar vue; /* vendor-unique error code */ ! 459: volatile unchar status; /* returned (icmb) status */ ! 460: volatile unchar phase; /* used by interrupt handler */ ! 461: } IcbAny; ! 462: ! 463: typedef union icb { ! 464: unchar op; /* ICB opcode */ ! 465: IcbRecvCmd recv_cmd; /* format for receive command */ ! 466: IcbSendStat send_stat; /* format for send status */ ! 467: IcbRevLvl rev_lvl; /* format for get revision level */ ! 468: IcbDiag diag; /* format for execute diagnostics */ ! 469: IcbParms eparms; /* format for get/set exec parms */ ! 470: IcbAny icb; /* generic format */ ! 471: unchar data[18]; ! 472: } Icb; ! 473: ! 474: ! 475: /* ! 476: * Driver SCB structure pool. ! 477: * ! 478: * The SCBs declared here are shared by all host adapters; hence, this ! 479: * structure is not part of the Adapter structure. ! 480: */ ! 481: static Scb scbs[MAX_SCBS]; ! 482: static Scb *scbfree = NULL; /* free list */ ! 483: static int freescbs = MAX_SCBS; /* free list counter */ ! 484: ! 485: /* ! 486: * END of data/declarations - code follows. ! 487: */ ! 488: ! 489: ! 490: #ifdef ANY2SCSI_INLINE ! 491: /* ! 492: Since they're used a lot, I've redone the following from the macros ! 493: formerly in wd7000.h, hopefully to speed them up by getting rid of ! 494: all the shifting (it may not matter; GCC might have done as well anyway). ! 495: ! 496: xany2scsi and xscsi2int were not being used, and are no longer defined. ! 497: (They were simply 4-byte versions of these routines). ! 498: */ ! 499: ! 500: typedef union { /* let's cheat... */ ! 501: int i; ! 502: unchar u[sizeof(int)]; /* the sizeof(int) makes it more portable */ ! 503: } i_u; ! 504: ! 505: ! 506: static inline void any2scsi( unchar *scsi, int any ) ! 507: { ! 508: *scsi++ = ((i_u) any).u[2]; ! 509: *scsi++ = ((i_u) any).u[1]; ! 510: *scsi++ = ((i_u) any).u[0]; ! 511: } ! 512: ! 513: ! 514: static inline int scsi2int( unchar *scsi ) ! 515: { ! 516: i_u result; ! 517: ! 518: result.i = 0; /* clears unused bytes */ ! 519: *(result.u+2) = *scsi++; ! 520: *(result.u+1) = *scsi++; ! 521: *(result.u) = *scsi++; ! 522: return result.i; ! 523: } ! 524: #else ! 525: /* ! 526: These are the old ones - I've just moved them here... ! 527: */ ! 528: #undef any2scsi ! 529: #define any2scsi(up, p) \ ! 530: (up)[0] = (((unsigned long)(p)) >> 16); \ ! 531: (up)[1] = ((unsigned long)(p)) >> 8; \ ! 532: (up)[2] = ((unsigned long)(p)); ! 533: ! 534: #undef scsi2int ! 535: #define scsi2int(up) ( (((unsigned long)*(up)) << 16) + \ ! 536: (((unsigned long)(up)[1]) << 8) + ((unsigned long)(up)[2]) ) ! 537: #endif ! 538: ! 539: ! 540: static inline void wd7000_enable_intr(Adapter *host) ! 541: { ! 542: host->control |= INT_EN; ! 543: outb(host->control, host->iobase+ASC_CONTROL); ! 544: } ! 545: ! 546: ! 547: static inline void wd7000_enable_dma(Adapter *host) ! 548: { ! 549: host->control |= DMA_EN; ! 550: outb(host->control,host->iobase+ASC_CONTROL); ! 551: set_dma_mode(host->dma, DMA_MODE_CASCADE); ! 552: enable_dma(host->dma); ! 553: } ! 554: ! 555: ! 556: #define WAITnexttimeout 200 /* 2 seconds */ ! 557: ! 558: #define WAIT(port, mask, allof, noneof) \ ! 559: { register volatile unsigned WAITbits; \ ! 560: register unsigned long WAITtimeout = jiffies + WAITnexttimeout; \ ! 561: while (1) { \ ! 562: WAITbits = inb(port) & (mask); \ ! 563: if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ ! 564: break; \ ! 565: if (jiffies > WAITtimeout) goto fail; \ ! 566: } \ ! 567: } ! 568: ! 569: ! 570: static inline void delay( unsigned how_long ) ! 571: { ! 572: register unsigned long time = jiffies + how_long; ! 573: ! 574: while (jiffies < time); ! 575: } ! 576: ! 577: ! 578: static inline int command_out(Adapter *host, unchar *cmd, int len) ! 579: { ! 580: WAIT(host->iobase+ASC_STAT,ASC_STATMASK,CMD_RDY,0); ! 581: while (len--) { ! 582: do { ! 583: outb(*cmd, host->iobase+ASC_COMMAND); ! 584: WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0); ! 585: } while (inb(host->iobase+ASC_STAT) & CMD_REJ); ! 586: cmd++; ! 587: } ! 588: return 1; ! 589: ! 590: fail: ! 591: printk("wd7000 command_out: WAIT failed(%d)\n", len+1); ! 592: return 0; ! 593: } ! 594: ! 595: ! 596: /* ! 597: * This version of alloc_scbs is in preparation for supporting multiple ! 598: * commands per lun and command chaining, by queueing pending commands. ! 599: * We will need to allocate Scbs in blocks since they will wait to be ! 600: * executed so there is the possibility of deadlock otherwise. ! 601: * Also, to keep larger requests from being starved by smaller requests, ! 602: * we limit access to this routine with an internal busy flag, so that ! 603: * the satisfiability of a request is not dependent on the size of the ! 604: * request. ! 605: */ ! 606: static inline Scb *alloc_scbs(int needed) ! 607: { ! 608: register Scb *scb, *p; ! 609: register unsigned long flags; ! 610: register unsigned long timeout = jiffies + WAITnexttimeout; ! 611: register unsigned long now; ! 612: static int busy = 0; ! 613: int i; ! 614: ! 615: if (needed <= 0) return NULL; /* sanity check */ ! 616: ! 617: save_flags(flags); ! 618: cli(); ! 619: while (busy) { /* someone else is allocating */ ! 620: sti(); /* Yes this is really needed here */ ! 621: now = jiffies; while (jiffies == now) /* wait a jiffy */; ! 622: cli(); ! 623: } ! 624: busy = 1; /* not busy now; it's our turn */ ! 625: ! 626: while (freescbs < needed) { ! 627: timeout = jiffies + WAITnexttimeout; ! 628: do { ! 629: sti(); /* Yes this is really needed here */ ! 630: now = jiffies; while (jiffies == now) /* wait a jiffy */; ! 631: cli(); ! 632: } while (freescbs < needed && jiffies <= timeout); ! 633: /* ! 634: * If we get here with enough free Scbs, we can take them. ! 635: * Otherwise, we timed out and didn't get enough. ! 636: */ ! 637: if (freescbs < needed) { ! 638: busy = 0; ! 639: panic("wd7000: can't get enough free SCBs.\n"); ! 640: restore_flags(flags); ! 641: return NULL; ! 642: } ! 643: } ! 644: scb = scbfree; freescbs -= needed; ! 645: for (i = 0; i < needed; i++) { p = scbfree; scbfree = p->next; } ! 646: p->next = NULL; ! 647: ! 648: busy = 0; /* we're done */ ! 649: ! 650: restore_flags(flags); ! 651: ! 652: return scb; ! 653: } ! 654: ! 655: ! 656: static inline void free_scb( Scb *scb ) ! 657: { ! 658: register unsigned long flags; ! 659: ! 660: save_flags(flags); ! 661: cli(); ! 662: ! 663: memset(scb, 0, sizeof(Scb)); ! 664: scb->next = scbfree; scbfree = scb; ! 665: freescbs++; ! 666: ! 667: restore_flags(flags); ! 668: } ! 669: ! 670: ! 671: static inline void init_scbs(void) ! 672: { ! 673: int i; ! 674: unsigned long flags; ! 675: ! 676: save_flags(flags); ! 677: cli(); ! 678: ! 679: scbfree = &(scbs[0]); ! 680: memset(scbs, 0, sizeof(scbs)); ! 681: for (i = 0; i < MAX_SCBS-1; i++) { ! 682: scbs[i].next = &(scbs[i+1]); scbs[i].SCpnt = NULL; ! 683: } ! 684: scbs[MAX_SCBS-1].next = NULL; ! 685: scbs[MAX_SCBS-1].SCpnt = NULL; ! 686: ! 687: restore_flags(flags); ! 688: } ! 689: ! 690: ! 691: static int mail_out( Adapter *host, Scb *scbptr ) ! 692: /* ! 693: * Note: this can also be used for ICBs; just cast to the parm type. ! 694: */ ! 695: { ! 696: register int i, ogmb; ! 697: register unsigned long flags; ! 698: unchar start_ogmb; ! 699: Mailbox *ogmbs = host->mb.ogmb; ! 700: int *next_ogmb = &(host->next_ogmb); ! 701: #ifdef DEBUG ! 702: printk("wd7000 mail_out: %06x",(unsigned int) scbptr); ! 703: #endif ! 704: /* We first look for a free outgoing mailbox */ ! 705: save_flags(flags); ! 706: cli(); ! 707: ogmb = *next_ogmb; ! 708: for (i = 0; i < OGMB_CNT; i++) { ! 709: if (ogmbs[ogmb].status == 0) { ! 710: #ifdef DEBUG ! 711: printk(" using OGMB %x",ogmb); ! 712: #endif ! 713: ogmbs[ogmb].status = 1; ! 714: any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); ! 715: ! 716: *next_ogmb = (ogmb+1) % OGMB_CNT; ! 717: break; ! 718: } else ! 719: ogmb = (++ogmb) % OGMB_CNT; ! 720: } ! 721: restore_flags(flags); ! 722: #ifdef DEBUG ! 723: printk(", scb is %x",(unsigned int) scbptr); ! 724: #endif ! 725: if (i >= OGMB_CNT) { ! 726: /* ! 727: * Alternatively, we might issue the "interrupt on free OGMB", ! 728: * and sleep, but it must be ensured that it isn't the init ! 729: * task running. Instead, this version assumes that the caller ! 730: * will be persistent, and try again. Since it's the adapter ! 731: * that marks OGMB's free, waiting even with interrupts off ! 732: * should work, since they are freed very quickly in most cases. ! 733: */ ! 734: #ifdef DEBUG ! 735: printk(", no free OGMBs.\n"); ! 736: #endif ! 737: return 0; ! 738: } ! 739: ! 740: wd7000_enable_intr(host); ! 741: ! 742: start_ogmb = START_OGMB | ogmb; ! 743: command_out( host, &start_ogmb, 1 ); ! 744: #ifdef DEBUG ! 745: printk(", awaiting interrupt.\n"); ! 746: #endif ! 747: return 1; ! 748: } ! 749: ! 750: ! 751: int make_code(unsigned hosterr, unsigned scsierr) ! 752: { ! 753: #ifdef DEBUG ! 754: int in_error = hosterr; ! 755: #endif ! 756: ! 757: switch ((hosterr>>8)&0xff){ ! 758: case 0: /* Reserved */ ! 759: hosterr = DID_ERROR; ! 760: break; ! 761: case 1: /* Command Complete, no errors */ ! 762: hosterr = DID_OK; ! 763: break; ! 764: case 2: /* Command complete, error logged in scb status (scsierr) */ ! 765: hosterr = DID_OK; ! 766: break; ! 767: case 4: /* Command failed to complete - timeout */ ! 768: hosterr = DID_TIME_OUT; ! 769: break; ! 770: case 5: /* Command terminated; Bus reset by external device */ ! 771: hosterr = DID_RESET; ! 772: break; ! 773: case 6: /* Unexpected Command Received w/ host as target */ ! 774: hosterr = DID_BAD_TARGET; ! 775: break; ! 776: case 80: /* Unexpected Reselection */ ! 777: case 81: /* Unexpected Selection */ ! 778: hosterr = DID_BAD_INTR; ! 779: break; ! 780: case 82: /* Abort Command Message */ ! 781: hosterr = DID_ABORT; ! 782: break; ! 783: case 83: /* SCSI Bus Software Reset */ ! 784: case 84: /* SCSI Bus Hardware Reset */ ! 785: hosterr = DID_RESET; ! 786: break; ! 787: default: /* Reserved */ ! 788: hosterr = DID_ERROR; ! 789: break; ! 790: } ! 791: #ifdef DEBUG ! 792: if (scsierr||hosterr) ! 793: printk("\nSCSI command error: SCSI %02x host %04x return %d", ! 794: scsierr,in_error,hosterr); ! 795: #endif ! 796: return scsierr | (hosterr << 16); ! 797: } ! 798: ! 799: ! 800: static void wd7000_scsi_done(Scsi_Cmnd * SCpnt) ! 801: { ! 802: #ifdef DEBUG ! 803: printk("wd7000_scsi_done: %06x\n",(unsigned int) SCpnt); ! 804: #endif ! 805: SCpnt->SCp.phase = 0; ! 806: } ! 807: ! 808: ! 809: #define wd7000_intr_ack(host) outb(0,host->iobase+ASC_INTR_ACK) ! 810: ! 811: void wd7000_intr_handle(int irq, struct pt_regs * regs) ! 812: { ! 813: register int flag, icmb, errstatus, icmb_status; ! 814: register int host_error, scsi_error; ! 815: register Scb *scb; /* for SCSI commands */ ! 816: register IcbAny *icb; /* for host commands */ ! 817: register Scsi_Cmnd *SCpnt; ! 818: Adapter *host = irq2host[irq]; /* This MUST be set!!! */ ! 819: Mailbox *icmbs = host->mb.icmb; ! 820: ! 821: #ifdef DEBUG ! 822: printk("wd7000_intr_handle: irq = %d, host = %06x\n", irq, host); ! 823: #endif ! 824: ! 825: flag = inb(host->iobase+ASC_INTR_STAT); ! 826: #ifdef DEBUG ! 827: printk("wd7000_intr_handle: intr stat = %02x\n",flag); ! 828: #endif ! 829: ! 830: if (!(inb(host->iobase+ASC_STAT) & INT_IM)) { ! 831: /* NB: these are _very_ possible if IRQ 15 is being used, since ! 832: it's the "garbage collector" on the 2nd 8259 PIC. Specifically, ! 833: any interrupt signal into the 8259 which can't be identified ! 834: comes out as 7 from the 8259, which is 15 to the host. Thus, it ! 835: is a good thing the WD7000 has an interrupt status port, so we ! 836: can sort these out. Otherwise, electrical noise and other such ! 837: problems would be indistinguishable from valid interrupts... ! 838: */ ! 839: #ifdef DEBUG ! 840: printk("wd7000_intr_handle: phantom interrupt...\n"); ! 841: #endif ! 842: wd7000_intr_ack(host); ! 843: return; ! 844: } ! 845: ! 846: if (flag & MB_INTR) { ! 847: /* The interrupt is for a mailbox */ ! 848: if (!(flag & IMB_INTR)) { ! 849: #ifdef DEBUG ! 850: printk("wd7000_intr_handle: free outgoing mailbox"); ! 851: #endif ! 852: /* ! 853: * If sleep_on() and the "interrupt on free OGMB" command are ! 854: * used in mail_out(), wake_up() should correspondingly be called ! 855: * here. For now, we don't need to do anything special. ! 856: */ ! 857: wd7000_intr_ack(host); ! 858: return; ! 859: } else { ! 860: /* The interrupt is for an incoming mailbox */ ! 861: icmb = flag & MB_MASK; ! 862: icmb_status = icmbs[icmb].status; ! 863: if (icmb_status & 0x80) { /* unsolicited - result in ICMB */ ! 864: #ifdef DEBUG ! 865: printk("wd7000_intr_handle: unsolicited interrupt %02xh\n", ! 866: icmb_status); ! 867: #endif ! 868: wd7000_intr_ack(host); ! 869: return; ! 870: } ! 871: scb = (struct scb *) scsi2int((unchar *)icmbs[icmb].scbptr); ! 872: icmbs[icmb].status = 0; ! 873: if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */ ! 874: SCpnt = scb->SCpnt; ! 875: if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */ ! 876: host_error = scb->vue | (icmb_status << 8); ! 877: scsi_error = scb->status; ! 878: errstatus = make_code(host_error,scsi_error); ! 879: SCpnt->result = errstatus; ! 880: ! 881: free_scb(scb); ! 882: ! 883: SCpnt->scsi_done(SCpnt); ! 884: } ! 885: } else { /* an ICB is done */ ! 886: icb = (IcbAny *) scb; ! 887: icb->status = icmb_status; ! 888: icb->phase = 0; ! 889: } ! 890: } /* incoming mailbox */ ! 891: } ! 892: ! 893: wd7000_intr_ack(host); ! 894: return; ! 895: } ! 896: ! 897: ! 898: int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) ! 899: { ! 900: register Scb *scb; ! 901: register Sgb *sgb; ! 902: register unchar *cdb = (unchar *) SCpnt->cmnd; ! 903: register unchar idlun; ! 904: register short cdblen; ! 905: Adapter *host = (Adapter *) SCpnt->host->hostdata; ! 906: ! 907: cdblen = SCpnt->cmd_len; ! 908: idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7); ! 909: SCpnt->scsi_done = done; ! 910: SCpnt->SCp.phase = 1; ! 911: scb = alloc_scbs(1); ! 912: scb->idlun = idlun; ! 913: memcpy(scb->cdb, cdb, cdblen); ! 914: scb->direc = 0x40; /* Disable direction check */ ! 915: ! 916: scb->SCpnt = SCpnt; /* so we can find stuff later */ ! 917: SCpnt->host_scribble = (unchar *) scb; ! 918: scb->host = host; ! 919: ! 920: if (SCpnt->use_sg) { ! 921: struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; ! 922: unsigned i; ! 923: ! 924: if (SCpnt->host->sg_tablesize == SG_NONE) { ! 925: panic("wd7000_queuecommand: scatter/gather not supported.\n"); ! 926: } ! 927: #ifdef DEBUG ! 928: printk("Using scatter/gather with %d elements.\n",SCpnt->use_sg); ! 929: #endif ! 930: ! 931: sgb = scb->sgb; ! 932: scb->op = 1; ! 933: any2scsi(scb->dataptr, (int) sgb); ! 934: any2scsi(scb->maxlen, SCpnt->use_sg * sizeof (Sgb) ); ! 935: ! 936: for (i = 0; i < SCpnt->use_sg; i++) { ! 937: any2scsi(sgb[i].ptr, (int) sg[i].address); ! 938: any2scsi(sgb[i].len, sg[i].length); ! 939: } ! 940: } else { ! 941: scb->op = 0; ! 942: any2scsi(scb->dataptr, (int) SCpnt->request_buffer); ! 943: any2scsi(scb->maxlen, SCpnt->request_bufflen); ! 944: } ! 945: while (!mail_out(host, scb)) /* keep trying */; ! 946: ! 947: return 1; ! 948: } ! 949: ! 950: ! 951: int wd7000_command(Scsi_Cmnd *SCpnt) ! 952: { ! 953: wd7000_queuecommand(SCpnt, wd7000_scsi_done); ! 954: ! 955: while (SCpnt->SCp.phase > 0) barrier(); /* phase counts scbs down to 0 */ ! 956: ! 957: return SCpnt->result; ! 958: } ! 959: ! 960: ! 961: int wd7000_diagnostics( Adapter *host, int code ) ! 962: { ! 963: static IcbDiag icb = {ICB_OP_DIAGNOSTICS}; ! 964: static unchar buf[256]; ! 965: unsigned long timeout; ! 966: ! 967: icb.type = code; ! 968: any2scsi(icb.len, sizeof(buf)); ! 969: any2scsi(icb.ptr, (int) &buf); ! 970: icb.phase = 1; ! 971: /* ! 972: * This routine is only called at init, so there should be OGMBs ! 973: * available. I'm assuming so here. If this is going to ! 974: * fail, I can just let the timeout catch the failure. ! 975: */ ! 976: mail_out(host, (struct scb *) &icb); ! 977: timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ ! 978: while (icb.phase && jiffies < timeout) ! 979: barrier(); /* wait for completion */ ! 980: ! 981: if (icb.phase) { ! 982: printk("wd7000_diagnostics: timed out.\n"); ! 983: return 0; ! 984: } ! 985: if (make_code(icb.vue|(icb.status << 8),0)) { ! 986: printk("wd7000_diagnostics: failed (%02x,%02x)\n", ! 987: icb.vue, icb.status); ! 988: return 0; ! 989: } ! 990: ! 991: return 1; ! 992: } ! 993: ! 994: ! 995: int wd7000_init( Adapter *host ) ! 996: { ! 997: InitCmd init_cmd = { ! 998: INITIALIZATION, 7, BUS_ON, BUS_OFF, 0, {0,0,0}, OGMB_CNT, ICMB_CNT ! 999: }; ! 1000: int diag; ! 1001: ! 1002: /* ! 1003: Reset the adapter - only. The SCSI bus was initialized at power-up, ! 1004: and we need to do this just so we control the mailboxes, etc. ! 1005: */ ! 1006: outb(ASC_RES, host->iobase+ASC_CONTROL); ! 1007: delay(1); /* reset pulse: this is 10ms, only need 25us */ ! 1008: outb(0,host->iobase+ASC_CONTROL); ! 1009: host->control = 0; /* this must always shadow ASC_CONTROL */ ! 1010: WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0); ! 1011: ! 1012: if ((diag = inb(host->iobase+ASC_INTR_STAT)) != 1) { ! 1013: printk("wd7000_init: "); ! 1014: switch (diag) { ! 1015: case 2: ! 1016: printk("RAM failure.\n"); ! 1017: break; ! 1018: case 3: ! 1019: printk("FIFO R/W failed\n"); ! 1020: break; ! 1021: case 4: ! 1022: printk("SBIC register R/W failed\n"); ! 1023: break; ! 1024: case 5: ! 1025: printk("Initialization D-FF failed.\n"); ! 1026: break; ! 1027: case 6: ! 1028: printk("Host IRQ D-FF failed.\n"); ! 1029: break; ! 1030: case 7: ! 1031: printk("ROM checksum error.\n"); ! 1032: break; ! 1033: default: ! 1034: printk("diagnostic code %02Xh received.\n", diag); ! 1035: break; ! 1036: } ! 1037: return 0; ! 1038: } ! 1039: ! 1040: /* Clear mailboxes */ ! 1041: memset(&(host->mb), 0, sizeof(host->mb)); ! 1042: ! 1043: /* Execute init command */ ! 1044: any2scsi((unchar *) &(init_cmd.mailboxes), (int) &(host->mb)); ! 1045: if (!command_out(host, (unchar *) &init_cmd, sizeof(init_cmd))) { ! 1046: printk("wd7000_init: adapter initialization failed.\n"); ! 1047: return 0; ! 1048: } ! 1049: WAIT(host->iobase+ASC_STAT, ASC_STATMASK, ASC_INIT, 0); ! 1050: ! 1051: if (request_irq(host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000")) { ! 1052: printk("wd7000_init: can't get IRQ %d.\n", host->irq); ! 1053: return 0; ! 1054: } ! 1055: if (request_dma(host->dma,"wd7000")) { ! 1056: printk("wd7000_init: can't get DMA channel %d.\n", host->dma); ! 1057: free_irq(host->irq); ! 1058: return 0; ! 1059: } ! 1060: wd7000_enable_dma(host); ! 1061: wd7000_enable_intr(host); ! 1062: ! 1063: if (!wd7000_diagnostics(host,ICB_DIAG_FULL)) { ! 1064: free_dma(host->dma); ! 1065: free_irq(host->irq); ! 1066: return 0; ! 1067: } ! 1068: ! 1069: return 1; ! 1070: ! 1071: fail: ! 1072: printk("wd7000_init: WAIT timed out.\n"); ! 1073: return 0; /* 0 = not ok */ ! 1074: } ! 1075: ! 1076: ! 1077: void wd7000_revision(Adapter *host) ! 1078: { ! 1079: static IcbRevLvl icb = {ICB_OP_GET_REVISION}; ! 1080: ! 1081: icb.phase = 1; ! 1082: /* ! 1083: * Like diagnostics, this is only done at init time, in fact, from ! 1084: * wd7000_detect, so there should be OGMBs available. If it fails, ! 1085: * the only damage will be that the revision will show up as 0.0, ! 1086: * which in turn means that scatter/gather will be disabled. ! 1087: */ ! 1088: mail_out(host, (struct scb *) &icb); ! 1089: while (icb.phase) ! 1090: barrier(); /* wait for completion */ ! 1091: host->rev1 = icb.primary; ! 1092: host->rev2 = icb.secondary; ! 1093: } ! 1094: ! 1095: ! 1096: int wd7000_detect(Scsi_Host_Template * tpnt) ! 1097: /* ! 1098: * Returns the number of adapters this driver is supporting. ! 1099: * ! 1100: * The source for hosts.c says to wait to call scsi_register until 100% ! 1101: * sure about an adapter. We need to do it a little sooner here; we ! 1102: * need the storage set up by scsi_register before wd7000_init, and ! 1103: * changing the location of an Adapter structure is more trouble than ! 1104: * calling scsi_unregister. ! 1105: * ! 1106: */ ! 1107: { ! 1108: int i,j, present = 0; ! 1109: const Config *cfg; ! 1110: const Signature *sig; ! 1111: Adapter *host = NULL; ! 1112: struct Scsi_Host *sh; ! 1113: ! 1114: tpnt->proc_dir = &proc_scsi_wd7000; ! 1115: ! 1116: /* Set up SCB free list, which is shared by all adapters */ ! 1117: init_scbs(); ! 1118: ! 1119: cfg = configs; ! 1120: for (i = 0; i < NUM_CONFIGS; i++) { ! 1121: sig = signatures; ! 1122: for (j = 0; j < NUM_SIGNATURES; j++) { ! 1123: if (!memcmp(cfg->bios+sig->ofs, sig->sig, sig->len)) { ! 1124: /* matched this one */ ! 1125: #ifdef DEBUG ! 1126: printk("WD-7000 SST BIOS detected at %04X: checking...\n", ! 1127: (int) cfg->bios); ! 1128: #endif ! 1129: /* ! 1130: * We won't explicitly test the configuration (in this ! 1131: * version); instead, we'll just see if it works to ! 1132: * setup the adapter; if it does, we'll use it. ! 1133: */ ! 1134: if (check_region(cfg->iobase, 4)) { /* ports in use */ ! 1135: printk("IO %xh already in use.\n", host->iobase); ! 1136: continue; ! 1137: } ! 1138: /* ! 1139: * We register here, to get a pointer to the extra space, ! 1140: * which we'll use as the Adapter structure (host) for ! 1141: * this adapter. It is located just after the registered ! 1142: * Scsi_Host structure (sh), and is located by the empty ! 1143: * array hostdata. ! 1144: */ ! 1145: sh = scsi_register(tpnt, sizeof(Adapter) ); ! 1146: host = (Adapter *) sh->hostdata; ! 1147: #ifdef DEBUG ! 1148: printk("wd7000_detect: adapter allocated at %06x\n", ! 1149: (int)host); ! 1150: #endif ! 1151: memset( host, 0, sizeof(Adapter) ); ! 1152: host->sh = sh; ! 1153: host->irq = cfg->irq; ! 1154: host->iobase = cfg->iobase; ! 1155: host->dma = cfg->dma; ! 1156: irq2host[host->irq] = host; ! 1157: ! 1158: if (!wd7000_init(host)) { /* Initialization failed */ ! 1159: scsi_unregister (sh); ! 1160: continue; ! 1161: } ! 1162: ! 1163: /* ! 1164: * OK from here - we'll use this adapter/configuration. ! 1165: */ ! 1166: wd7000_revision(host); /* important for scatter/gather */ ! 1167: ! 1168: printk("Western Digital WD-7000 (%d.%d) ", ! 1169: host->rev1, host->rev2); ! 1170: printk("using IO %xh IRQ %d DMA %d.\n", ! 1171: host->iobase, host->irq, host->dma); ! 1172: ! 1173: request_region(host->iobase, 4,"wd7000"); /* Register our ports */ ! 1174: /* ! 1175: * For boards before rev 6.0, scatter/gather isn't supported. ! 1176: */ ! 1177: if (host->rev1 < 6) sh->sg_tablesize = SG_NONE; ! 1178: ! 1179: present++; /* count it */ ! 1180: break; /* don't try any more sigs */ ! 1181: } ! 1182: sig++; /* try next signature with this configuration */ ! 1183: } ! 1184: cfg++; /* try next configuration */ ! 1185: } ! 1186: ! 1187: return present; ! 1188: } ! 1189: ! 1190: ! 1191: /* ! 1192: * I have absolutely NO idea how to do an abort with the WD7000... ! 1193: */ ! 1194: int wd7000_abort(Scsi_Cmnd * SCpnt) ! 1195: { ! 1196: Adapter *host = (Adapter *) SCpnt->host->hostdata; ! 1197: ! 1198: if (inb(host->iobase+ASC_STAT) & INT_IM) { ! 1199: printk("wd7000_abort: lost interrupt\n"); ! 1200: wd7000_intr_handle(host->irq, NULL); ! 1201: return SCSI_ABORT_SUCCESS; ! 1202: } ! 1203: ! 1204: return SCSI_ABORT_SNOOZE; ! 1205: } ! 1206: ! 1207: ! 1208: /* ! 1209: * I also have no idea how to do a reset... ! 1210: */ ! 1211: int wd7000_reset(Scsi_Cmnd * SCpnt) ! 1212: { ! 1213: return SCSI_RESET_PUNT; ! 1214: } ! 1215: ! 1216: ! 1217: /* ! 1218: * This was borrowed directly from aha1542.c, but my disks are organized ! 1219: * this way, so I think it will work OK. Someone who is ambitious can ! 1220: * borrow a newer or more complete version from another driver. ! 1221: */ ! 1222: int wd7000_biosparam(Disk * disk, kdev_t dev, int* ip) ! 1223: { ! 1224: int size = disk->capacity; ! 1225: ip[0] = 64; ! 1226: ip[1] = 32; ! 1227: ip[2] = size >> 11; ! 1228: /* if (ip[2] >= 1024) ip[2] = 1024; */ ! 1229: return 0; ! 1230: } ! 1231: ! 1232: #ifdef MODULE ! 1233: /* Eventually this will go into an include file, but this will be later */ ! 1234: Scsi_Host_Template driver_template = WD7000; ! 1235: ! 1236: #include "scsi_module.c" ! 1237: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.