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 #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 )
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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, void *dev_id, struct pt_regs * regs)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 *))
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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", NULL)) {
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, NULL);
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, NULL);
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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, 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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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