patch-2.0.16 linux/drivers/scsi/wd7000.c
Next file: linux/drivers/sound/dmabuf.c
Previous file: linux/drivers/scsi/sg.c
Back to the patch index
Back to the overall index
- Lines: 698
- Date:
Sat Aug 31 20:52:44 1996
- Orig file:
v2.0.15/linux/drivers/scsi/wd7000.c
- Orig date:
Fri Mar 1 07:50:54 1996
diff -u --recursive --new-file v2.0.15/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
@@ -98,6 +98,23 @@
* one of the FD boards, it would be nice to come up with a signature
* for it.
* J.B. Jan 1994.
+ *
+ *
+ * Revision: 08/24/1996. by Miroslav Zagorac <zaga@fly.cc.fer.hr>
+ *
+ * Enhancement for wd7000_detect function has been made, so you don't have
+ * to enter BIOS ROM adress and IO port in initialisation data (see struct
+ * Config). We cannot detect IRQ and DMA for now, so we have to enter them
+ * as arguments while wd_7000 is detected. If someone has IRQ and DMA set
+ * to some other value, he can enter them in configuration without any
+ * problem. Also I wrote a function wd7000_setup, so now you can enter
+ * WD-7000 definition as kernel arguments, as in lilo.conf:
+ *
+ * append="wd7000=IRQ,DMA"
+ *
+ * PS: If card BIOS ROM is disabled, function wd7000_detect now will recognize
+ * adapter, unlike the old one. Anyway, BIOS ROM from WD7000 adapter is
+ * worthless for Linux. :)
*/
#ifdef MODULE
@@ -121,7 +138,7 @@
#include "hosts.h"
#include "sd.h"
-#define ANY2SCSI_INLINE /* undef this to use old macros */
+#define ANY2SCSI_INLINE /* undef this to use old macros */
#undef DEBUG
#include "wd7000.h"
@@ -158,7 +175,7 @@
*/
typedef volatile struct mailbox{
unchar status;
- unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */
+ unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */
} Mailbox;
/*
@@ -167,17 +184,17 @@
*
*/
typedef struct adapter {
- struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */
- int iobase; /* This adapter's I/O base address */
- int irq; /* This adapter's IRQ level */
- int dma; /* This adapter's DMA channel */
- struct { /* This adapter's mailboxes */
- Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */
- Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */
+ struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */
+ int iobase; /* This adapter's I/O base address */
+ int irq; /* This adapter's IRQ level */
+ int dma; /* This adapter's DMA channel */
+ struct { /* This adapter's mailboxes */
+ Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */
+ Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */
} mb;
- int next_ogmb; /* to reduce contention at mailboxes */
- unchar control; /* shadows CONTROL port value */
- unchar rev1, rev2; /* filled in by wd7000_revision */
+ int next_ogmb; /* to reduce contention at mailboxes */
+ unchar control; /* shadows CONTROL port value */
+ unchar rev1, rev2; /* filled in by wd7000_revision */
} Adapter;
/*
@@ -186,22 +203,47 @@
* Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be
* changed to pick up the IRQ level correctly.
*/
-Adapter *irq2host[16] = {NULL}; /* Possible IRQs are 0-15 */
+Adapter *irq2host[16] = {NULL}; /* Possible IRQs are 0-15 */
+
+/*
+ * (linear) base address for ROM BIOS
+ */
+static const long wd7000_biosaddr[] = {
+ 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000,
+ 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
+};
+#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long))
+
+static const unsigned short wd7000_iobase[] = {
+ 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338,
+ 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378,
+ 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8,
+ 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8
+};
+#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short))
+
+static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 };
+#define NUM_IRQS (sizeof(wd7000_irq)/sizeof(short))
+static const short wd7000_dma[] = { 5, 6, 7 };
+#define NUM_DMAS (sizeof(wd7000_dma)/sizeof(short))
+
/*
* Standard Adapter Configurations - used by wd7000_detect
*/
typedef struct {
- const void *bios; /* (linear) base address for ROM BIOS */
- int iobase; /* I/O ports base address */
- int irq; /* IRQ level */
- int dma; /* DMA channel */
+ int irq; /* IRQ level */
+ int dma; /* DMA channel */
} Config;
+/*
+ * Add here your configuration...
+ */
static const Config configs[] = {
- {(void *) 0xce000, 0x350, 15, 6}, /* defaults for single adapter */
- {(void *) 0xc8000, 0x330, 11, 5}, /* defaults for second adapter */
- {(void *) 0xd8000, 0x350, 15, 6}, /* Arghhh.... who added this ? */
+ { 15, 6 }, /* defaults for single adapter */
+ { 11, 5 }, /* defaults for second adapter */
+ { 9, 6 }, /* My configuretion (Zaga) */
+ { -1, -1 } /* Empty slot */
};
#define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
@@ -211,13 +253,13 @@
* added for the Future Domain version.
*/
typedef struct signature {
- const void *sig; /* String to look for */
- unsigned ofs; /* offset from BIOS base address */
- unsigned len; /* length of string */
+ const void *sig; /* String to look for */
+ unsigned ofs; /* offset from BIOS base address */
+ unsigned len; /* length of string */
} Signature;
static const Signature signatures[] = {
- {"SSTBIOS",0x0000d,7} /* "SSTBIOS" @ offset 0x0000d */
+ { "SSTBIOS", 0x0000d, 7 } /* "SSTBIOS" @ offset 0x0000d */
};
#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
@@ -226,19 +268,20 @@
* I/O Port Offsets and Bit Definitions
* 4 addresses are used. Those not defined here are reserved.
*/
-#define ASC_STAT 0 /* Status, Read */
-#define ASC_COMMAND 0 /* Command, Write */
-#define ASC_INTR_STAT 1 /* Interrupt Status, Read */
-#define ASC_INTR_ACK 1 /* Acknowledge, Write */
-#define ASC_CONTROL 2 /* Control, Write */
-
-/* ASC Status Port
- */
-#define INT_IM 0x80 /* Interrupt Image Flag */
-#define CMD_RDY 0x40 /* Command Port Ready */
-#define CMD_REJ 0x20 /* Command Port Byte Rejected */
-#define ASC_INIT 0x10 /* ASC Initialized Flag */
-#define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */
+#define ASC_STAT 0 /* Status, Read */
+#define ASC_COMMAND 0 /* Command, Write */
+#define ASC_INTR_STAT 1 /* Interrupt Status, Read */
+#define ASC_INTR_ACK 1 /* Acknowledge, Write */
+#define ASC_CONTROL 2 /* Control, Write */
+
+/*
+ * ASC Status Port
+ */
+#define INT_IM 0x80 /* Interrupt Image Flag */
+#define CMD_RDY 0x40 /* Command Port Ready */
+#define CMD_REJ 0x20 /* Command Port Byte Rejected */
+#define ASC_INIT 0x10 /* ASC Initialized Flag */
+#define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */
/* COMMAND opcodes
*
@@ -248,31 +291,31 @@
* discernible effect whatsoever. I think they may be related to certain
* ICB commands, but again, the OEM manual doesn't make that clear.
*/
-#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */
-#define INITIALIZATION 1 /* initialization (10 bytes) */
-#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */
-#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */
-#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */
-#define SOFT_RESET 5 /* SCSI bus soft reset */
-#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */
-#define START_OGMB 0x80 /* start command in OGMB (n) */
-#define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */
+#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */
+#define INITIALIZATION 1 /* initialization (10 bytes) */
+#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */
+#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */
+#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */
+#define SOFT_RESET 5 /* SCSI bus soft reset */
+#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */
+#define START_OGMB 0x80 /* start command in OGMB (n) */
+#define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */
/* where (n) = lower 6 bits */
/* For INITIALIZATION:
*/
typedef struct initCmd {
- unchar op; /* command opcode (= 1) */
- unchar ID; /* Adapter's SCSI ID */
- unchar bus_on; /* Bus on time, x 125ns (see below) */
- unchar bus_off; /* Bus off time, "" "" */
- unchar rsvd; /* Reserved */
- unchar mailboxes[3]; /* Address of Mailboxes, MSB first */
- unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */
- unchar icmbs; /* Number of incoming MBs, "" "" */
+ unchar op; /* command opcode (= 1) */
+ unchar ID; /* Adapter's SCSI ID */
+ unchar bus_on; /* Bus on time, x 125ns (see below) */
+ unchar bus_off; /* Bus off time, "" "" */
+ unchar rsvd; /* Reserved */
+ unchar mailboxes[3]; /* Address of Mailboxes, MSB first */
+ unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */
+ unchar icmbs; /* Number of incoming MBs, "" "" */
} InitCmd;
-#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */
-#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */
+#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */
+#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */
/* Interrupt Status Port - also returns diagnostic codes at ASC reset
*
@@ -301,29 +344,29 @@
#define ASC_RES 0x01 /* ASC Reset */
/*
- Driver data structures:
- - mb and scbs are required for interfacing with the host adapter.
- An SCB has extra fields not visible to the adapter; mb's
- _cannot_ do this, since the adapter assumes they are contiguous in
- memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
- to access them.
- - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each;
- the additional bytes are used only by the driver.
- - For now, a pool of SCBs are kept in global storage by this driver,
- and are allocated and freed as needed.
-
- The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
- not when it has finished. Since the SCB must be around for completion,
- problems arise when SCBs correspond to OGMBs, which may be reallocated
- earlier (or delayed unnecessarily until a command completes).
- Mailboxes are used as transient data structures, simply for
- carrying SCB addresses to/from the 7000-FASST2.
-
- Note also since SCBs are not "permanently" associated with mailboxes,
- there is no need to keep a global list of Scsi_Cmnd pointers indexed
- by OGMB. Again, SCBs reference their Scsi_Cmnds directly, so mailbox
- indices need not be involved.
-*/
+ * Driver data structures:
+ * - mb and scbs are required for interfacing with the host adapter.
+ * An SCB has extra fields not visible to the adapter; mb's
+ * _cannot_ do this, since the adapter assumes they are contiguous in
+ * memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
+ * to access them.
+ * - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each;
+ * the additional bytes are used only by the driver.
+ * - For now, a pool of SCBs are kept in global storage by this driver,
+ * and are allocated and freed as needed.
+ *
+ * The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
+ * not when it has finished. Since the SCB must be around for completion,
+ * problems arise when SCBs correspond to OGMBs, which may be reallocated
+ * earlier (or delayed unnecessarily until a command completes).
+ * Mailboxes are used as transient data structures, simply for
+ * carrying SCB addresses to/from the 7000-FASST2.
+ *
+ * Note also since SCBs are not "permanently" associated with mailboxes,
+ * there is no need to keep a global list of Scsi_Cmnd pointers indexed
+ * by OGMB. Again, SCBs reference their Scsi_Cmnds directly, so mailbox
+ * indices need not be involved.
+ */
/*
* WD7000-specific scatter/gather element structure
@@ -483,10 +526,87 @@
static int freescbs = MAX_SCBS; /* free list counter */
/*
+ *
+ */
+static short wd7000_setupIRQ[NUM_CONFIGS];
+static short wd7000_setupDMA[NUM_CONFIGS];
+static short wd7000_card_num = 0;
+
+/*
* END of data/declarations - code follows.
*/
+/*
+ * Note: You can now set these options from the kernel's "command line".
+ * The syntax is:
+ *
+ * wd7000=IRQ,DMA
+ * eg:
+ * wd7000=15,6
+ *
+ * will configure the driver for a WD-7000 controller
+ * using IRQ 15 with a DMA channel 6.
+ */
+void wd7000_setup (char *str, int *ints) {
+ short i, j;
+
+ if (wd7000_card_num >= NUM_CONFIGS) {
+ printk ("wd7000_setup: Too many \"wd7000=\" configurations in "
+ "command line!\n");
+
+ return;
+ }
+
+ if (ints[0] != 2)
+ printk ("wd7000_setup: Error in command line! "
+ "Usage: wd7000=IRQ,DMA\n");
+ else {
+ for (i = 0; i < NUM_IRQS; i++)
+ if (ints[1] == wd7000_irq[i])
+ break;
+
+ if (i == NUM_IRQS) {
+ printk ("wd7000_setup: invalid IRQ.\n");
+ return;
+ }
+ else
+ wd7000_setupIRQ[wd7000_card_num] = ints[1];
+
+ for (i = 0; i < NUM_DMAS; i++)
+ if (ints[2] == wd7000_dma[i])
+ break;
+
+ if (i == NUM_IRQS) {
+ printk ("wd7000_setup: invalid DMA channel.\n");
+ return;
+ }
+ else
+ wd7000_setupDMA[wd7000_card_num] = ints[2];
+
+ if (wd7000_card_num)
+ for (i = 0; i < (wd7000_card_num - 1); i++)
+ for (j = i + 1; j < wd7000_card_num; j++)
+ if (wd7000_setupIRQ[i] == wd7000_setupIRQ[j]) {
+ printk ("wd7000_setup: duplicated IRQ!\n");
+ return;
+ }
+ else if (wd7000_setupDMA[i] == wd7000_setupDMA[j]) {
+ printk ("wd7000_setup: duplicated DMA channel!\n");
+ return;
+ }
+
+#ifdef DEBUG
+ printk ("wd7000_setup: IRQ=%d, DMA=%d\n",
+ wd7000_setupIRQ[wd7000_card_num],
+ wd7000_setupDMA[wd7000_card_num]);
+#endif
+
+ wd7000_card_num++;
+ }
+}
+
+
#ifdef ANY2SCSI_INLINE
/*
Since they're used a lot, I've redone the following from the macros
@@ -627,7 +747,8 @@
timeout = jiffies + WAITnexttimeout;
do {
sti(); /* Yes this is really needed here */
- now = jiffies; while (jiffies == now) /* wait a jiffy */;
+ now = jiffies;
+ while (jiffies == now); /* wait a jiffy */
cli();
} while (freescbs < needed && jiffies <= timeout);
/*
@@ -699,7 +820,7 @@
Mailbox *ogmbs = host->mb.ogmb;
int *next_ogmb = &(host->next_ogmb);
#ifdef DEBUG
- printk("wd7000 mail_out: %06x",(unsigned int) scbptr);
+ printk("wd7000 mail_out: 0x%06lx",(long) scbptr);
#endif
/* We first look for a free outgoing mailbox */
save_flags(flags);
@@ -708,7 +829,7 @@
for (i = 0; i < OGMB_CNT; i++) {
if (ogmbs[ogmb].status == 0) {
#ifdef DEBUG
- printk(" using OGMB %x",ogmb);
+ printk(" using OGMB 0x%x",ogmb);
#endif
ogmbs[ogmb].status = 1;
any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr);
@@ -720,7 +841,7 @@
}
restore_flags(flags);
#ifdef DEBUG
- printk(", scb is %x",(unsigned int) scbptr);
+ printk(", scb is 0x%06lx",(long) scbptr);
#endif
if (i >= OGMB_CNT) {
/*
@@ -790,7 +911,7 @@
}
#ifdef DEBUG
if (scsierr||hosterr)
- printk("\nSCSI command error: SCSI %02x host %04x return %d",
+ printk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n",
scsierr,in_error,hosterr);
#endif
return scsierr | (hosterr << 16);
@@ -800,7 +921,7 @@
static void wd7000_scsi_done(Scsi_Cmnd * SCpnt)
{
#ifdef DEBUG
- printk("wd7000_scsi_done: %06x\n",(unsigned int) SCpnt);
+ printk("wd7000_scsi_done: 0x%06x\n",(long) SCpnt);
#endif
SCpnt->SCp.phase = 0;
}
@@ -819,12 +940,12 @@
Mailbox *icmbs = host->mb.icmb;
#ifdef DEBUG
- printk("wd7000_intr_handle: irq = %d, host = %06x\n", irq, host);
+ printk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host);
#endif
flag = inb(host->iobase+ASC_INTR_STAT);
#ifdef DEBUG
- printk("wd7000_intr_handle: intr stat = %02x\n",flag);
+ printk("wd7000_intr_handle: intr stat = 0x%02x\n",flag);
#endif
if (!(inb(host->iobase+ASC_STAT) & INT_IM)) {
@@ -847,7 +968,7 @@
/* The interrupt is for a mailbox */
if (!(flag & IMB_INTR)) {
#ifdef DEBUG
- printk("wd7000_intr_handle: free outgoing mailbox");
+ printk("wd7000_intr_handle: free outgoing mailbox\n");
#endif
/*
* If sleep_on() and the "interrupt on free OGMB" command are
@@ -862,7 +983,7 @@
icmb_status = icmbs[icmb].status;
if (icmb_status & 0x80) { /* unsolicited - result in ICMB */
#ifdef DEBUG
- printk("wd7000_intr_handle: unsolicited interrupt %02xh\n",
+ printk("wd7000_intr_handle: unsolicited interrupt 0x%02xh\n",
icmb_status);
#endif
wd7000_intr_ack(host);
@@ -983,7 +1104,7 @@
return 0;
}
if (make_code(icb.vue|(icb.status << 8),0)) {
- printk("wd7000_diagnostics: failed (%02x,%02x)\n",
+ printk("wd7000_diagnostics: failed (0x%02x,0x%02x)\n",
icb.vue, icb.status);
return 0;
}
@@ -1011,6 +1132,7 @@
if ((diag = inb(host->iobase+ASC_INTR_STAT)) != 1) {
printk("wd7000_init: ");
+
switch (diag) {
case 2:
printk("RAM failure.\n");
@@ -1031,8 +1153,7 @@
printk("ROM checksum error.\n");
break;
default:
- printk("diagnostic code %02Xh received.\n", diag);
- break;
+ printk("diagnostic code 0x%02Xh received.\n", diag);
}
return 0;
}
@@ -1093,8 +1214,7 @@
}
-int wd7000_detect(Scsi_Host_Template * tpnt)
-/*
+/*
* Returns the number of adapters this driver is supporting.
*
* The source for hosts.c says to wait to call scsi_register until 100%
@@ -1104,87 +1224,139 @@
* calling scsi_unregister.
*
*/
+int wd7000_detect (Scsi_Host_Template *tpnt)
{
- int i,j, present = 0;
- const Config *cfg;
- const Signature *sig;
+ short present = 0, biosaddr_ptr, iobase_ptr, cfg_ptr, sig_ptr, i;
+ short biosptr[NUM_CONFIGS];
Adapter *host = NULL;
struct Scsi_Host *sh;
+ for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
+
tpnt->proc_dir = &proc_scsi_wd7000;
- /* Set up SCB free list, which is shared by all adapters */
- init_scbs();
+ /*
+ * Set up SCB free list, which is shared by all adapters
+ */
+ init_scbs ();
+
+ for (cfg_ptr = 0; cfg_ptr < NUM_CONFIGS; cfg_ptr++) {
+ for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++)
+ for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) {
+ for (i = 0; i < cfg_ptr; i++)
+ if (biosptr[i] == biosaddr_ptr)
+ break;
+
+ if ((i == cfg_ptr) &&
+ !memcmp ((void *) (wd7000_biosaddr[biosaddr_ptr] +
+ signatures[sig_ptr].ofs), signatures[sig_ptr].sig,
+ signatures[sig_ptr].len))
+ goto bios_matched;
+ }
+
+bios_matched:
- cfg = configs;
- for (i = 0; i < NUM_CONFIGS; i++) {
- sig = signatures;
- for (j = 0; j < NUM_SIGNATURES; j++) {
- if (!memcmp(cfg->bios+sig->ofs, sig->sig, sig->len)) {
- /* matched this one */
#ifdef DEBUG
- printk("WD-7000 SST BIOS detected at %04X: checking...\n",
- (int) cfg->bios);
+ printk ("wd7000_detect: pass %d\n", cfg_ptr + 1);
+
+ if (biosaddr_ptr == NUM_ADDRS)
+ printk ("WD-7000 SST BIOS not detected...\n");
+ else
+ printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n",
+ wd7000_biosaddr[biosaddr_ptr]);
#endif
- /*
- * We won't explicitly test the configuration (in this
- * version); instead, we'll just see if it works to
- * setup the adapter; if it does, we'll use it.
- */
- if (check_region(cfg->iobase, 4)) { /* ports in use */
- printk("IO %xh already in use.\n", host->iobase);
- continue;
- }
- /*
- * We register here, to get a pointer to the extra space,
- * which we'll use as the Adapter structure (host) for
- * this adapter. It is located just after the registered
- * Scsi_Host structure (sh), and is located by the empty
- * array hostdata.
+
+ for (iobase_ptr = 0; iobase_ptr < NUM_IOPORTS; iobase_ptr++)
+ if (! check_region (wd7000_iobase[iobase_ptr], 4)) {
+ /*
+ * ASC reset...
*/
- sh = scsi_register(tpnt, sizeof(Adapter) );
- host = (Adapter *) sh->hostdata;
+ outb (ASC_RES, wd7000_iobase[iobase_ptr] + ASC_CONTROL);
+ delay (1);
+ outb (0, wd7000_iobase[iobase_ptr] + ASC_CONTROL);
+ WAIT (wd7000_iobase[iobase_ptr] + ASC_STAT, ASC_STATMASK,
+ CMD_RDY, 0);
+
+ if (inb (wd7000_iobase[iobase_ptr] + ASC_INTR_STAT) == 1) {
+ /*
+ * We register here, to get a pointer to the extra space,
+ * which we'll use as the Adapter structure (host) for
+ * this adapter. It is located just after the registered
+ * Scsi_Host structure (sh), and is located by the empty
+ * array hostdata.
+ */
+ sh = scsi_register (tpnt, sizeof (Adapter));
+ host = (Adapter *) sh->hostdata;
+
#ifdef DEBUG
- printk("wd7000_detect: adapter allocated at %06x\n",
- (int)host);
+ printk ("wd7000_detect: adapter allocated at 0x%x\n",
+ (int) host);
#endif
- memset( host, 0, sizeof(Adapter) );
- host->sh = sh;
- host->irq = cfg->irq;
- host->iobase = cfg->iobase;
- host->dma = cfg->dma;
- irq2host[host->irq] = host;
-
- if (!wd7000_init(host)) { /* Initialization failed */
- scsi_unregister (sh);
- continue;
- }
- /*
- * OK from here - we'll use this adapter/configuration.
- */
- wd7000_revision(host); /* important for scatter/gather */
+ memset (host, 0, sizeof (Adapter));
- printk("Western Digital WD-7000 (%d.%d) ",
- host->rev1, host->rev2);
- printk("using IO %xh IRQ %d DMA %d.\n",
- host->iobase, host->irq, host->dma);
-
- request_region(host->iobase, 4,"wd7000"); /* Register our ports */
- /*
- * For boards before rev 6.0, scatter/gather isn't supported.
- */
- if (host->rev1 < 6) sh->sg_tablesize = SG_NONE;
+ if (wd7000_card_num) {
+ host->irq = wd7000_setupIRQ[--wd7000_card_num];
+ host->dma = wd7000_setupDMA[wd7000_card_num];
+ }
+ else {
+ host->irq = configs[cfg_ptr].irq;
+ host->dma = configs[cfg_ptr].dma;
+ }
+
+ host->sh = sh;
+ host->iobase = wd7000_iobase[iobase_ptr];
+ irq2host[host->irq] = host;
- present++; /* count it */
- break; /* don't try any more sigs */
+#ifdef DEBUG
+ printk ("wd7000_detect: Trying init WD-7000 card at IO "
+ "0x%x, IRQ %d, DMA %d...\n",
+ host->iobase, host->irq, host->dma);
+#endif
+
+ if (! wd7000_init (host)) { /* Initialization failed */
+ scsi_unregister (sh);
+
+ continue;
+ }
+
+ /*
+ * OK from here - we'll use this adapter/configuration.
+ */
+ wd7000_revision (host); /* important for scatter/gather */
+
+ /*
+ * Register our ports.
+ */
+ request_region (host->iobase, 4, "wd7000");
+
+ /*
+ * For boards before rev 6.0, scatter/gather
+ * isn't supported.
+ */
+ if (host->rev1 < 6)
+ sh->sg_tablesize = SG_NONE;
+
+ present++; /* count it */
+
+ if (biosaddr_ptr != NUM_ADDRS)
+ biosptr[cfg_ptr] = biosaddr_ptr;
+
+ printk ("Western Digital WD-7000 (rev %d.%d) ",
+ host->rev1, host->rev2);
+ printk ("using IO 0x%xh, IRQ %d, DMA %d.\n",
+ host->iobase, host->irq, host->dma);
+
+ break;
+ }
+fail:
}
- sig++; /* try next signature with this configuration */
- }
- cfg++; /* try next configuration */
}
- return present;
+ if (! present)
+ printk ("Failed initialization of WD-7000 SCSI card!\n");
+
+ return (present);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov