1 /* $Id: $ 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 <boyd@cis.ohio-state.edu> 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 #ifdefMODULE 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 #defineANY2SCSI_INLINE/* undef this to use old macros */ 125 #undefDEBUG 126
127 #include "wd7000.h"
128
129 #include<linux/stat.h>
130
131 structproc_dir_entryproc_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 #defineOGMB_CNT 16
144 #defineICMB_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 #defineMAX_SCBS 32
154
155 /* 156 * WD7000-specific mailbox structure 157 * 158 */ 159 typedefvolatilestructmailbox{ 160 uncharstatus;
161 uncharscbptr[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 typedefstructadapter{ 170 structScsi_Host *sh; /* Pointer to Scsi_Host structure */ 171 intiobase; /* This adapter's I/O base address */ 172 intirq; /* This adapter's IRQ level */ 173 intdma; /* This adapter's DMA channel */ 174 struct{/* This adapter's mailboxes */ 175 Mailboxogmb[OGMB_CNT]; /* Outgoing mailboxes */ 176 Mailboxicmb[ICMB_CNT]; /* Incoming mailboxes */ 177 }mb;
178 intnext_ogmb; /* to reduce contention at mailboxes */ 179 uncharcontrol; /* shadows CONTROL port value */ 180 uncharrev1, 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 typedefstruct{ 195 constvoid *bios; /* (linear) base address for ROM BIOS */ 196 intiobase; /* I/O ports base address */ 197 intirq; /* IRQ level */ 198 intdma; /* DMA channel */ 199 }Config;
200
201 staticconstConfigconfigs[] = { 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 #defineNUM_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 typedefstructsignature{ 214 constvoid *sig; /* String to look for */ 215 unsignedofs; /* offset from BIOS base address */ 216 unsignedlen; /* length of string */ 217 }Signature;
218
219 staticconstSignaturesignatures[] = { 220 {"SSTBIOS",0x0000d,7}/* "SSTBIOS" @ offset 0x0000d */ 221 };
222 #defineNUM_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 #defineASC_STAT 0 /* Status, Read */ 230 #defineASC_COMMAND 0 /* Command, Write */ 231 #defineASC_INTR_STAT 1 /* Interrupt Status, Read */ 232 #defineASC_INTR_ACK 1 /* Acknowledge, Write */ 233 #defineASC_CONTROL 2 /* Control, Write */ 234
235 /* ASC Status Port 236 */ 237 #defineINT_IM 0x80 /* Interrupt Image Flag */ 238 #defineCMD_RDY 0x40 /* Command Port Ready */ 239 #defineCMD_REJ 0x20 /* Command Port Byte Rejected */ 240 #defineASC_INIT 0x10 /* ASC Initialized Flag */ 241 #defineASC_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 #defineINITIALIZATION 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 #defineSTART_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 typedefstruct initCmd { 264 uncharop; /* command opcode (= 1) */ 265 uncharID; /* Adapter's SCSI ID */ 266 unchar bus_on; /* Bus on time, x 125ns (see below) */ 267 unchar bus_off; /* Bus off time, "" "" */ 268 uncharrsvd; /* Reserved */ 269 uncharmailboxes[3]; /* Address of Mailboxes, MSB first */ 270 uncharogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ 271 uncharicmbs; /* Number of incoming MBs, "" "" */ 272 }InitCmd;
273
274 #defineBUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ 275 #defineBUS_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 #defineMB_INTR 0xC0 /* Mailbox Service possible/required */ 293 #defineIMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */ 294 #defineMB_MASK 0x3f /* mask for mailbox number */ 295
296 /* CONTROL port bits 297 */ 298 #defineINT_EN 0x08 /* Interrupt Enable */ 299 #defineDMA_EN 0x04 /* DMA Enable */ 300 #define SCSI_RES 0x02 /* SCSI Reset */ 301 #defineASC_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 typedefstructsgb{ 332 uncharlen[3];
333 uncharptr[3]; /* Also SCSI-style - MSB first */ 334 }Sgb;
335
336 typedefstructscb{/* Command Control Block 5.4.1 */ 337 uncharop; /* Command Control Block Operation Code */ 338 uncharidlun; /* 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 uncharcdb[12]; /* SCSI Command Block */ 343 volatileuncharstatus; /* SCSI Return Status */ 344 volatileuncharvue; /* Vendor Unique Error Code */ 345 uncharmaxlen[3]; /* Maximum Data Transfer Length */ 346 unchardataptr[3]; /* SCSI Data Block Pointer */ 347 uncharlinkptr[3]; /* Next Command Link Pointer */ 348 unchardirec; /* Transfer Direction */ 349 uncharreserved2[6]; /* SCSI Command Descriptor Block */ 350 /* end of hardware SCB */ 351 Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */ 352 Sgbsgb[WD7000_SG]; /* Scatter/gather list for this SCB */ 353 Adapter *host; /* host adapter */ 354 structscb *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 #defineICB_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 #defineICB_OP_GET_REVISION 0x8C /* read firmware revision level */ 381 #defineICB_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 typedefstruct icbRecvCmd { 386 uncharop;
387 uncharIDlun; /* Initiator SCSI ID/lun */ 388 uncharlen[3]; /* command buffer length */ 389 uncharptr[3]; /* command buffer address */ 390 uncharrsvd[7]; /* reserved */ 391 volatileuncharvue; /* vendor-unique error code */ 392 volatileuncharstatus; /* returned (icmb) status */ 393 volatileuncharphase; /* used by interrupt handler */ 394 }IcbRecvCmd;
395
396 typedefstruct icbSendStat { 397 uncharop;
398 uncharIDlun; /* Target SCSI ID/lun */ 399 uncharstat; /* (outgoing) completion status byte 1 */ 400 uncharrsvd[12]; /* reserved */ 401 volatileuncharvue; /* vendor-unique error code */ 402 volatileuncharstatus; /* returned (icmb) status */ 403 volatileuncharphase; /* used by interrupt handler */ 404 }IcbSendStat;
405
406 typedefstruct icbRevLvl { 407 uncharop;
408 volatileuncharprimary; /* primary revision level (returned) */ 409 volatileuncharsecondary; /* secondary revision level (returned) */ 410 uncharrsvd[12]; /* reserved */ 411 volatileuncharvue; /* vendor-unique error code */ 412 volatileuncharstatus; /* returned (icmb) status */ 413 volatileuncharphase; /* used by interrupt handler */ 414 }IcbRevLvl;
415
416 typedefstruct icbUnsMask {/* I'm totally guessing here */ 417 uncharop;
418 volatileuncharmask[14]; /* mask bits */ 419 #ifdef 0
420 uncharrsvd[12]; /* reserved */ 421 #endif 422 volatileuncharvue; /* vendor-unique error code */ 423 volatileuncharstatus; /* returned (icmb) status */ 424 volatileuncharphase; /* used by interrupt handler */ 425 } IcbUnsMask;
426
427 typedefstruct icbDiag { 428 uncharop;
429 unchartype; /* diagnostics type code (0-3) */ 430 uncharlen[3]; /* buffer length */ 431 uncharptr[3]; /* buffer address */ 432 uncharrsvd[7]; /* reserved */ 433 volatileuncharvue; /* vendor-unique error code */ 434 volatileuncharstatus; /* returned (icmb) status */ 435 volatileuncharphase; /* 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 #defineICB_DIAG_FULL 3 /* do both 1 & 2 */ 442
443 typedefstruct icbParms { 444 uncharop;
445 unchar rsvd1; /* reserved */ 446 uncharlen[3]; /* parms buffer length */ 447 uncharptr[3]; /* parms buffer address */ 448 uncharidx[2]; /* index (MSB-LSB) */ 449 unchar rsvd2[5]; /* reserved */ 450 volatileuncharvue; /* vendor-unique error code */ 451 volatileuncharstatus; /* returned (icmb) status */ 452 volatileuncharphase; /* used by interrupt handler */ 453 }IcbParms;
454
455 typedefstruct icbAny { 456 uncharop;
457 unchardata[14]; /* format-specific data */ 458 volatileuncharvue; /* vendor-unique error code */ 459 volatileuncharstatus; /* returned (icmb) status */ 460 volatileuncharphase; /* used by interrupt handler */ 461 }IcbAny;
462
463 typedefunionicb{ 464 uncharop; /* 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 IcbDiagdiag; /* format for execute diagnostics */ 469 IcbParms eparms; /* format for get/set exec parms */ 470 IcbAnyicb; /* generic format */ 471 unchardata[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 staticScbscbs[MAX_SCBS];
482 staticScb *scbfree = NULL; /* free list */ 483 staticintfreescbs = MAX_SCBS; /* free list counter */ 484
485 /* 486 * END of data/declarations - code follows. 487 */ 488
489
490 #ifdefANY2SCSI_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 typedefunion{/* let's cheat... */ 501 inti;
502 uncharu[sizeof(int)]; /* the sizeof(int) makes it more portable */ 503 }i_u;
504
505
506 staticinlinevoidany2scsi( unchar *scsi, intany )
/* */ 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 staticinlineintscsi2int( unchar *scsi )
/* */ 515 { 516 i_uresult;
517
518 result.i = 0; /* clears unused bytes */ 519 *(result.u+2) = *scsi++;
520 *(result.u+1) = *scsi++;
521 *(result.u) = *scsi++;
522 returnresult.i;
523 } 524 #else 525 /* 526 These are the old ones - I've just moved them here... 527 */ 528 #undefany2scsi 529 #defineany2scsi(up, p) \
530 (up)[0] = (((unsignedlong)(p)) >> 16); \
531 (up)[1] = ((unsignedlong)(p)) >> 8; \
532 (up)[2] = ((unsignedlong)(p));
533
534 #undefscsi2int 535 #definescsi2int(up) ( (((unsignedlong)*(up)) << 16) + \
536 (((unsignedlong)(up)[1]) << 8) + ((unsignedlong)(up)[2]) )
537 #endif 538
539
540 staticinlinevoidwd7000_enable_intr(Adapter *host)
/* */ 541 { 542 host->control |= INT_EN;
543 outb(host->control, host->iobase+ASC_CONTROL);
544 } 545
546
547 staticinlinevoidwd7000_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 #defineWAITnexttimeout 200 /* 2 seconds */ 557
558 #defineWAIT(port, mask, allof, noneof) \
559 {registervolatileunsignedWAITbits; \
560 registerunsignedlongWAITtimeout = jiffies + WAITnexttimeout; \
561 while (1) { \
562 WAITbits = inb(port) & (mask); \
563 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
564 break; \
565 if (jiffies > WAITtimeout) gotofail; \
566 } \
567 } 568
569
570 staticinlinevoiddelay( unsignedhow_long )
/* */ 571 { 572 registerunsignedlongtime = jiffies + how_long;
573
574 while (jiffies < time);
575 } 576
577
578 staticinlineintcommand_out(Adapter *host, unchar *cmd, intlen)
/* */ 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 staticinlineScb *alloc_scbs(intneeded)
/* */ 607 { 608 registerScb *scb, *p;
609 registerunsignedlongflags;
610 registerunsignedlongtimeout = jiffies + WAITnexttimeout;
611 registerunsignedlongnow;
612 staticintbusy = 0;
613 inti;
614
615 if (needed <= 0) returnNULL; /* 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 returnNULL;
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 returnscb;
653 } 654
655
656 staticinlinevoidfree_scb( Scb *scb )
/* */ 657 { 658 registerunsignedlongflags;
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 staticinlinevoidinit_scbs(void)
/* */ 672 { 673 inti;
674 unsignedlongflags;
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 staticintmail_out( Adapter *host, Scb *scbptr )
/* */ 692 /* 693 * Note: this can also be used for ICBs; just cast to the parm type. 694 */ 695 { 696 registerinti, ogmb;
697 registerunsignedlongflags;
698 uncharstart_ogmb;
699 Mailbox *ogmbs = host->mb.ogmb;
700 int *next_ogmb = &(host->next_ogmb);
701 #ifdefDEBUG 702 printk("wd7000 mail_out: %06x",(unsignedint) 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 #ifdefDEBUG 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 #ifdefDEBUG 723 printk(", scb is %x",(unsignedint) 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 #ifdefDEBUG 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 #ifdefDEBUG 745 printk(", awaiting interrupt.\n");
746 #endif 747 return 1;
748 } 749
750
751 intmake_code(unsignedhosterr, unsignedscsierr)
/* */ 752 { 753 #ifdefDEBUG 754 intin_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 #ifdefDEBUG 792 if (scsierr||hosterr)
793 printk("\nSCSI command error: SCSI %02x host %04x return %d",
794 scsierr,in_error,hosterr);
795 #endif 796 returnscsierr | (hosterr << 16);
797 } 798
799
800 staticvoidwd7000_scsi_done(Scsi_Cmnd * SCpnt)
/* */ 801 { 802 #ifdefDEBUG 803 printk("wd7000_scsi_done: %06x\n",(unsignedint) SCpnt);
804 #endif 805 SCpnt->SCp.phase = 0;
806 } 807
808
809 #definewd7000_intr_ack(host) outb(0,host->iobase+ASC_INTR_ACK)
810
811 voidwd7000_intr_handle(intirq, structpt_regs * regs)
/* */ 812 { 813 registerintflag, icmb, errstatus, icmb_status;
814 registerinthost_error, scsi_error;
815 registerScb *scb; /* for SCSI commands */ 816 registerIcbAny *icb; /* for host commands */ 817 registerScsi_Cmnd *SCpnt;
818 Adapter *host = irq2host[irq]; /* This MUST be set!!! */ 819 Mailbox *icmbs = host->mb.icmb;
820
821 #ifdefDEBUG 822 printk("wd7000_intr_handle: irq = %d, host = %06x\n", irq, host);
823 #endif 824
825 flag = inb(host->iobase+ASC_INTR_STAT);
826 #ifdefDEBUG 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 #ifdefDEBUG 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 #ifdefDEBUG 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 #ifdefDEBUG 865 printk("wd7000_intr_handle: unsolicited interrupt %02xh\n",
866 icmb_status);
867 #endif 868 wd7000_intr_ack(host);
869 return;
870 } 871 scb = (structscb *) 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 intwd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */ 899 { 900 registerScb *scb;
901 registerSgb *sgb;
902 registerunchar *cdb = (unchar *) SCpnt->cmnd;
903 registeruncharidlun;
904 registershortcdblen;
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 structscatterlist *sg = (structscatterlist *) SCpnt->request_buffer;
922 unsignedi;
923
924 if (SCpnt->host->sg_tablesize == SG_NONE) { 925 panic("wd7000_queuecommand: scatter/gather not supported.\n");
926 } 927 #ifdefDEBUG 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 intwd7000_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 returnSCpnt->result;
958 } 959
960
961 intwd7000_diagnostics( Adapter *host, intcode )
/* */ 962 { 963 staticIcbDiagicb = {ICB_OP_DIAGNOSTICS};
964 staticuncharbuf[256];
965 unsignedlongtimeout;
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, (structscb *) &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 intwd7000_init( Adapter *host )
/* */ 996 { 997 InitCmdinit_cmd = { 998 INITIALIZATION, 7, BUS_ON, BUS_OFF, 0, {0,0,0}, OGMB_CNT, ICMB_CNT 999 };
1000 intdiag;
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 voidwd7000_revision(Adapter *host)
/* */1078 {1079 staticIcbRevLvlicb = {ICB_OP_GET_REVISION};
1080
1081 icb.phase = 1;
1082 /*1083 * Like diagnostics, this is only done at init time, in fact, from1084 * 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, (structscb *) &icb);
1089 while (icb.phase)
1090 barrier(); /* wait for completion */1091 host->rev1 = icb.primary;
1092 host->rev2 = icb.secondary;
1093 }1094
1095
1096 intwd7000_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; we1102 * need the storage set up by scsi_register before wd7000_init, and1103 * changing the location of an Adapter structure is more trouble than1104 * calling scsi_unregister.1105 *1106 */1107 {1108 inti,j, present = 0;
1109 constConfig *cfg;
1110 constSignature *sig;
1111 Adapter *host = NULL;
1112 structScsi_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 #ifdefDEBUG1126 printk("WD-7000 SST BIOS detected at %04X: checking...\n",
1127 (int) cfg->bios);
1128 #endif1129 /*1130 * We won't explicitly test the configuration (in this1131 * version); instead, we'll just see if it works to1132 * 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) for1141 * this adapter. It is located just after the registered1142 * Scsi_Host structure (sh), and is located by the empty1143 * array hostdata.1144 */1145 sh = scsi_register(tpnt, sizeof(Adapter) );
1146 host = (Adapter *) sh->hostdata;
1147 #ifdefDEBUG1148 printk("wd7000_detect: adapter allocated at %06x\n",
1149 (int)host);
1150 #endif1151 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 returnpresent;
1188 }1189
1190
1191 /*1192 * I have absolutely NO idea how to do an abort with the WD7000...1193 */1194 intwd7000_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 returnSCSI_ABORT_SUCCESS;
1202 }1203
1204 returnSCSI_ABORT_SNOOZE;
1205 }1206
1207
1208 /*1209 * I also have no idea how to do a reset...1210 */1211 intwd7000_reset(Scsi_Cmnd * SCpnt)
/* */1212 {1213 returnSCSI_RESET_PUNT;
1214 }1215
1216
1217 /*1218 * This was borrowed directly from aha1542.c, but my disks are organized1219 * this way, so I think it will work OK. Someone who is ambitious can1220 * borrow a newer or more complete version from another driver.1221 */1222 intwd7000_biosparam(Disk * disk, kdev_tdev, int* ip)
/* */1223 {1224 intsize = 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 #ifdefMODULE1233 /* Eventually this will go into an include file, but this will be later */1234 Scsi_Host_Templatedriver_template = WD7000;
1235
1236 #include "scsi_module.c"
1237 #endif