169 #include <linux/module.h>
171 #include <linux/kernel.h>
172 #include <linux/types.h>
173 #include <linux/string.h>
179 #include <linux/stat.h>
184 #include <scsi/scsi.h>
193 #define dprintk printk
195 #define dprintk(format,args...)
235 typedef volatile struct mailbox {
264 static const long wd7000_biosaddr[] = {
265 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000,
266 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
268 #define NUM_ADDRS ARRAY_SIZE(wd7000_biosaddr)
270 static const unsigned short wd7000_iobase[] = {
271 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338,
272 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378,
273 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8,
274 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8
276 #define NUM_IOPORTS ARRAY_SIZE(wd7000_iobase)
278 static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 };
279 #define NUM_IRQS ARRAY_SIZE(wd7000_irq)
281 static const short wd7000_dma[] = { 5, 6, 7 };
282 #define NUM_DMAS ARRAY_SIZE(wd7000_dma)
312 static Config configs[] = {
318 #define NUM_CONFIGS ARRAY_SIZE(configs)
332 {
"SSTBIOS", 0x0000d, 7}
334 #define NUM_SIGNATURES ARRAY_SIZE(signatures)
342 #define ASC_COMMAND 0
343 #define ASC_INTR_STAT 1
344 #define ASC_INTR_ACK 1
345 #define ASC_CONTROL 2
353 #define ASC_INIT 0x10
354 #define ASC_STATMASK 0xf0
366 #define INITIALIZATION 1
367 #define DISABLE_UNS_INTR 2
368 #define ENABLE_UNS_INTR 3
369 #define INTR_ON_FREE_OGMB 4
371 #define HARD_RESET_ACK 6
372 #define START_OGMB 0x80
373 #define SCAN_OGMBS 0xc0
406 #define IMB_INTR 0x40
414 #define SCSI_RES 0x02
482 #define ICB_OP_MASK 0x80
483 #define ICB_OP_OPEN_RBUF 0x80
484 #define ICB_OP_RECV_CMD 0x81
485 #define ICB_OP_RECV_DATA 0x82
486 #define ICB_OP_RECV_SDATA 0x83
487 #define ICB_OP_SEND_DATA 0x84
488 #define ICB_OP_SEND_STAT 0x86
490 #define ICB_OP_READ_INIT 0x88
491 #define ICB_OP_READ_ID 0x89
492 #define ICB_OP_SET_UMASK 0x8A
493 #define ICB_OP_GET_UMASK 0x8B
494 #define ICB_OP_GET_REVISION 0x8C
495 #define ICB_OP_DIAGNOSTICS 0x8D
496 #define ICB_OP_SET_EPARMS 0x8E
497 #define ICB_OP_GET_EPARMS 0x8F
552 #define ICB_DIAG_POWERUP 0
553 #define ICB_DIAG_WALKING 1
554 #define ICB_DIAG_DMA 2
555 #define ICB_DIAG_FULL 3
607 static void __init setup_error(
char *mesg,
int *ints)
610 printk(
KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", ints[1], ints[2], ints[3], mesg);
611 else if (ints[0] == 4)
612 printk(
KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", ints[1], ints[2], ints[3], ints[4], mesg);
614 printk(
KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n", ints[1], ints[2], ints[3], ints[4], ints[5], mesg);
632 static int __init wd7000_setup(
char *
str)
634 static short wd7000_card_num;
641 printk(
KERN_ERR "%s: Too many \"wd7000=\" configurations in " "command line!\n", __func__);
645 if ((ints[0] < 3) || (ints[0] > 5)) {
646 printk(
KERN_ERR "%s: Error in command line! " "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>" "[,<BUS_OFF>]]\n", __func__);
649 if (ints[1] == wd7000_irq[i])
653 setup_error(
"invalid IRQ.", ints);
656 configs[wd7000_card_num].
irq = ints[1];
659 if (ints[2] == wd7000_dma[i])
663 setup_error(
"invalid DMA channel.", ints);
666 configs[wd7000_card_num].
dma = ints[2];
669 if (ints[3] == wd7000_iobase[i])
672 if (i == NUM_IOPORTS) {
673 setup_error(
"invalid I/O base address.", ints);
676 configs[wd7000_card_num].
iobase = ints[3];
679 if ((ints[4] < 500) || (ints[4] > 31875)) {
680 setup_error(
"BUS_ON value is out of range (500" " to 31875 nanoseconds)!", ints);
683 configs[wd7000_card_num].
bus_on = ints[4] / 125;
688 if ((ints[5] < 500) || (ints[5] > 31875)) {
689 setup_error(
"BUS_OFF value is out of range (500" " to 31875 nanoseconds)!", ints);
692 configs[wd7000_card_num].
bus_off = ints[5] / 125;
696 if (wd7000_card_num) {
697 for (i = 0; i < (wd7000_card_num - 1); i++) {
700 for (; j < wd7000_card_num; j++)
701 if (configs[i].irq == configs[j].irq) {
702 setup_error(
"duplicated IRQ!", ints);
705 if (configs[i].
dma == configs[j].
dma) {
706 setup_error(
"duplicated DMA " "channel!", ints);
710 setup_error(
"duplicated I/O " "base address!", ints);
717 "BUS_ON=%dns, BUS_OFF=%dns\n", configs[wd7000_card_num].irq, configs[wd7000_card_num].
dma, configs[wd7000_card_num].
iobase, configs[wd7000_card_num].bus_on * 125, configs[wd7000_card_num].bus_off * 125);
724 __setup(
"wd7000=", wd7000_setup);
728 *scsi++ = (unsigned)any >> 16;
729 *scsi++ = (unsigned)any >> 8;
735 return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2];
738 static inline void wd7000_enable_intr(
Adapter *
host)
745 static inline void wd7000_enable_dma(
Adapter *
host)
759 #define WAITnexttimeout 200
761 static inline short WAIT(
unsigned port,
unsigned mask,
unsigned allof,
unsigned noneof)
769 if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0))
808 static inline Scb *alloc_scbs(
struct Scsi_Host *host,
int needed)
822 while (freescbs < needed) {
826 for (now = jiffies; now ==
jiffies;)
833 if (freescbs < needed) {
841 if (freescbs < needed) {
842 spin_unlock_irqrestore(&scbpool_lock, flags);
848 for (i = 0; i < needed; i++) {
854 spin_unlock_irqrestore(&scbpool_lock, flags);
861 static inline void free_scb(
Scb * scb)
872 spin_unlock_irqrestore(&scbpool_lock, flags);
876 static inline void init_scbs(
void)
884 scbfree = &(scbs[0]);
885 memset(scbs, 0,
sizeof(scbs));
886 for (i = 0; i <
MAX_SCBS - 1; i++) {
887 scbs[
i].
next = &(scbs[i + 1]);
895 static int mail_out(
Adapter * host,
Scb * scbptr)
906 dprintk(
"wd7000_mail_out: 0x%06lx", (
long) scbptr);
912 if (ogmbs[ogmb].
status == 0) {
913 dprintk(
" using OGMB 0x%x", ogmb);
917 *next_ogmb = (ogmb + 1) % OGMB_CNT;
920 ogmb = (ogmb + 1) % OGMB_CNT;
922 spin_unlock_irqrestore(host->
sh->host_lock, flags);
924 dprintk(
", scb is 0x%06lx", (
long) scbptr);
939 wd7000_enable_intr(host);
942 command_out(host, &start_ogmb, 1);
944 dprintk(
", awaiting interrupt.\n");
950 static int make_code(
unsigned hosterr,
unsigned scsierr)
953 int in_error = hosterr;
956 switch ((hosterr >> 8) & 0xff) {
990 if (scsierr || hosterr)
991 dprintk(
"\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", scsierr, in_error, hosterr);
993 return (scsierr | (hosterr << 16));
996 #define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK)
1002 int flag, icmb, errstatus, icmb_status;
1003 int host_error, scsi_error;
1008 unsigned long flags;
1013 dprintk(
"wd7000_intr: irq = %d, host = 0x%06lx\n", irq, (
long) host);
1017 dprintk(
"wd7000_intr: intr stat = 0x%02x\n", flag);
1028 dprintk(
"wd7000_intr: phantom interrupt...\n");
1037 dprintk(
"wd7000_intr: free outgoing mailbox\n");
1048 icmb_status = icmbs[icmb].
status;
1049 if (icmb_status & 0x80) {
1050 dprintk(
"wd7000_intr: unsolicited interrupt 0x%02x\n", icmb_status);
1059 icb->
status = icmb_status;
1065 if (--(SCpnt->
SCp.phase) <= 0) {
1066 host_error = scb->
vue | (icmb_status << 8);
1067 scsi_error = scb->
status;
1068 errstatus = make_code(host_error, scsi_error);
1069 SCpnt->
result = errstatus;
1077 dprintk(
"wd7000_intr: return from interrupt handler\n");
1080 spin_unlock_irqrestore(host->sh->host_lock, flags);
1084 static int wd7000_queuecommand_lck(
struct scsi_cmnd *SCpnt,
1096 idlun = ((SCpnt->
device->id << 5) & 0xe0) | (SCpnt->
device->lun & 7);
1098 SCpnt->
SCp.phase = 1;
1099 scb = alloc_scbs(SCpnt->
device->host, 1);
1108 nseg = scsi_sg_count(SCpnt);
1113 dprintk(
"Using scatter/gather with %d elements.\n", nseg);
1135 while (!mail_out(host, scb))
1143 static
int wd7000_diagnostics(
Adapter * host,
int code)
1147 unsigned long timeout;
1158 mail_out(host, (
struct scb *) &icb);
1166 printk(
"wd7000_diagnostics: timed out.\n");
1169 if (make_code(icb.
vue | (icb.
status << 8), 0)) {
1170 printk(
"wd7000_diagnostics: failed (0x%02x,0x%02x)\n", icb.
vue, icb.
status);
1178 static int wd7000_adapter_reset(
Adapter * host)
1237 if (!command_out(host, (
unchar *) & init_cmd,
sizeof(init_cmd))) {
1238 printk(
KERN_ERR "wd7000_adapter_reset: adapter initialization failed.\n");
1243 printk(
"wd7000_adapter_reset: WAIT timed out.\n");
1249 static int wd7000_init(
Adapter * host)
1251 if (wd7000_adapter_reset(host) == -1)
1256 printk(
"wd7000_init: can't get IRQ %d.\n", host->
irq);
1260 printk(
"wd7000_init: can't get DMA channel %d.\n", host->
dma);
1264 wd7000_enable_dma(host);
1265 wd7000_enable_intr(host);
1277 static void wd7000_revision(
Adapter * host)
1288 mail_out(host, (
struct scb *) &icb);
1299 #define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
1303 dprintk(
"Buffer = <%.*s>, length = %d\n", length, buffer, length);
1308 dprintk(
"Sorry, this function is currently out of order...\n");
1316 unsigned long flags;
1327 return (wd7000_set_info(buffer, length, host));
1330 SPRINTF(
"Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", host->
host_no, adapter->
rev1, adapter->
rev2);
1335 SPRINTF(
" BUS_ON time: %d nanoseconds\n", adapter->
bus_on * 125);
1336 SPRINTF(
" BUS_OFF time: %d nanoseconds\n", adapter->
bus_off * 125);
1339 ogmbs = adapter->
mb.ogmb;
1340 icmbs = adapter->
mb.icmb;
1343 SPRINTF(
"Incoming mailbox:\n");
1345 SPRINTF(
" queued messages: ");
1355 SPRINTF(
"Outgoing mailbox:\n");
1356 SPRINTF(
" size: %d\n", OGMB_CNT);
1358 SPRINTF(
" queued messages: ");
1361 if (ogmbs[i].status) {
1369 spin_unlock_irqrestore(host->
host_lock, flags);
1374 *start = buffer +
offset;
1376 if ((
pos - buffer) < offset)
1378 else if ((
pos - buffer - offset) < length)
1379 return (
pos - buffer - offset);
1398 short present = 0, biosaddr_ptr, sig_ptr,
i, pass;
1405 dprintk(
"wd7000_detect: started\n");
1409 wd7000_setup(wd7000);
1412 for (i = 0; i <
UNITS; wd7000_host[i++] =
NULL);
1427 for (biosaddr_ptr = 0; biosaddr_ptr <
NUM_ADDRS; biosaddr_ptr++)
1429 for (i = 0; i < pass; i++)
1430 if (biosptr[i] == biosaddr_ptr)
1434 void __iomem *biosaddr =
ioremap(wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs,
1435 signatures[sig_ptr].len);
1436 short bios_match = 1;
1439 bios_match =
check_signature(biosaddr, signatures[sig_ptr].
sig, signatures[sig_ptr].len);
1453 dprintk(
"wd7000_detect: pass %d\n", pass + 1);
1455 if (biosaddr_ptr == NUM_ADDRS)
1456 dprintk(
"WD-7000 SST BIOS not detected...\n");
1458 dprintk(
"WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]);
1461 if (configs[pass].
irq < 0)
1467 iobase = configs[pass].
iobase;
1469 dprintk(
"wd7000_detect: check IO 0x%x region...\n", iobase);
1473 dprintk(
"wd7000_detect: ASC reset (IO 0x%x) ...", iobase);
1499 host = (
Adapter *) sh->hostdata;
1501 dprintk(
"wd7000_detect: adapter allocated at 0x%x\n", (
int) host);
1504 host->
irq = configs[pass].
irq;
1505 host->
dma = configs[pass].
dma;
1510 host->
sh = wd7000_host[
unit] = sh;
1513 dprintk(
"wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->
iobase, host->
irq, host->
dma);
1515 if (!wd7000_init(host))
1516 goto err_unregister;
1521 wd7000_revision(host);
1531 if (biosaddr_ptr != NUM_ADDRS)
1532 biosptr[pass] = biosaddr_ptr;
1536 printk(
" BUS_ON time: %dns, BUS_OFF time: %dns\n", host->
bus_on * 125, host->
bus_off * 125);
1539 dprintk(
"wd7000_detect: IO 0x%x region already allocated!\n", iobase);
1551 printk(
"Failed initialization of WD-7000 SCSI card!\n");
1570 static int wd7000_abort(
Scsi_Cmnd * SCpnt)
1575 printk(
"wd7000_abort: lost interrupt\n");
1587 static int wd7000_host_reset(
struct scsi_cmnd *SCpnt)
1591 spin_lock_irq(SCpnt->
device->host->host_lock);
1593 if (wd7000_adapter_reset(host) < 0) {
1594 spin_unlock_irq(SCpnt->
device->host->host_lock);
1598 wd7000_enable_intr(host);
1600 spin_unlock_irq(SCpnt->
device->host->host_lock);
1608 static int wd7000_biosparam(
struct scsi_device *sdev,
1613 dprintk(
"wd7000_biosparam: dev=%s, size=%d, ",
1622 ip[2] = capacity >> 11;
1627 if (ip[2] >= 1024) {
1633 if ((
scsicam_bios_param(bdev, capacity, info) < 0) || !(((info[0] == 64) && (info[1] == 32)) || ((info[0] == 255) && (info[1] == 63)))) {
1634 printk(
"wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" " using extended translation.\n");
1638 ip[2] = (
unsigned long) capacity / (255 * 63);
1645 printk(
KERN_INFO "%s: current partition table is " "using extended translation.\n", __func__);
1649 dprintk(
"bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]);
1650 dprintk(
"WARNING: check, if the bios geometry is correct.\n");
1655 MODULE_AUTHOR(
"Thomas Wuensche, John Boyd, Miroslav Zagorac");
1660 .proc_name =
"wd7000",
1661 .proc_info = wd7000_proc_info,
1662 .name =
"Western Digital WD-7000",
1663 .detect = wd7000_detect,
1664 .release = wd7000_release,
1665 .queuecommand = wd7000_queuecommand,
1666 .eh_host_reset_handler = wd7000_host_reset,
1667 .bios_param = wd7000_biosparam,
1672 .unchecked_isa_dma = 1,