1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168#include <linux/delay.h>
169#include <linux/module.h>
170#include <linux/interrupt.h>
171#include <linux/kernel.h>
172#include <linux/types.h>
173#include <linux/string.h>
174#include <linux/spinlock.h>
175#include <linux/ioport.h>
176#include <linux/proc_fs.h>
177#include <linux/blkdev.h>
178#include <linux/init.h>
179#include <linux/stat.h>
180#include <linux/io.h>
181
182#include <asm/dma.h>
183
184#include <scsi/scsi.h>
185#include <scsi/scsi_cmnd.h>
186#include <scsi/scsi_device.h>
187#include <scsi/scsi_host.h>
188#include <scsi/scsicam.h>
189
190
191#undef WD7000_DEBUG
192#ifdef WD7000_DEBUG
193#define dprintk printk
194#else
195#define dprintk no_printk
196#endif
197
198
199
200
201
202
203
204#define OGMB_CNT 16
205#define ICMB_CNT 32
206
207
208
209
210
211
212
213
214#define MAX_SCBS 32
215
216
217
218
219
220
221
222
223
224
225
226
227#define WD7000_Q 16
228#define WD7000_SG 16
229
230
231
232
233
234
235typedef volatile struct mailbox {
236 unchar status;
237 unchar scbptr[3];
238} Mailbox;
239
240
241
242
243
244typedef struct adapter {
245 struct Scsi_Host *sh;
246 int iobase;
247 int irq;
248 int dma;
249 int int_counter;
250 int bus_on;
251 int bus_off;
252 struct {
253 Mailbox ogmb[OGMB_CNT];
254 Mailbox icmb[ICMB_CNT];
255 } mb;
256 int next_ogmb;
257 unchar control;
258 unchar rev1, rev2;
259} Adapter;
260
261
262
263
264static const long wd7000_biosaddr[] = {
265 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000,
266 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
267};
268#define NUM_ADDRS ARRAY_SIZE(wd7000_biosaddr)
269
270static 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
275};
276#define NUM_IOPORTS ARRAY_SIZE(wd7000_iobase)
277
278static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 };
279#define NUM_IRQS ARRAY_SIZE(wd7000_irq)
280
281static const short wd7000_dma[] = { 5, 6, 7 };
282#define NUM_DMAS ARRAY_SIZE(wd7000_dma)
283
284
285
286
287
288
289#define UNITS 8
290static struct Scsi_Host *wd7000_host[UNITS];
291
292#define BUS_ON 64
293#define BUS_OFF 15
294
295
296
297
298typedef struct {
299 short irq;
300 short dma;
301 unsigned iobase;
302 short bus_on;
303
304 short bus_off;
305
306
307} Config;
308
309
310
311
312static Config configs[] = {
313 {15, 6, 0x350, BUS_ON, BUS_OFF},
314 {11, 5, 0x320, BUS_ON, BUS_OFF},
315 {7, 6, 0x350, BUS_ON, BUS_OFF},
316 {-1, -1, 0x0, BUS_ON, BUS_OFF}
317};
318#define NUM_CONFIGS ARRAY_SIZE(configs)
319
320
321
322
323
324
325typedef struct signature {
326 const char *sig;
327 unsigned long ofs;
328 unsigned len;
329} Signature;
330
331static const Signature signatures[] = {
332 {"SSTBIOS", 0x0000d, 7}
333};
334#define NUM_SIGNATURES ARRAY_SIZE(signatures)
335
336
337
338
339
340
341#define ASC_STAT 0
342#define ASC_COMMAND 0
343#define ASC_INTR_STAT 1
344#define ASC_INTR_ACK 1
345#define ASC_CONTROL 2
346
347
348
349
350#define INT_IM 0x80
351#define CMD_RDY 0x40
352#define CMD_REJ 0x20
353#define ASC_INIT 0x10
354#define ASC_STATMASK 0xf0
355
356
357
358
359
360
361
362
363
364
365#define NO_OP 0
366#define INITIALIZATION 1
367#define DISABLE_UNS_INTR 2
368#define ENABLE_UNS_INTR 3
369#define INTR_ON_FREE_OGMB 4
370#define SOFT_RESET 5
371#define HARD_RESET_ACK 6
372#define START_OGMB 0x80
373#define SCAN_OGMBS 0xc0
374
375
376
377
378typedef struct initCmd {
379 unchar op;
380 unchar ID;
381 unchar bus_on;
382 unchar bus_off;
383 unchar rsvd;
384 unchar mailboxes[3];
385 unchar ogmbs;
386 unchar icmbs;
387} InitCmd;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405#define MB_INTR 0xC0
406#define IMB_INTR 0x40
407#define MB_MASK 0x3f
408
409
410
411
412#define INT_EN 0x08
413#define DMA_EN 0x04
414#define SCSI_RES 0x02
415#define ASC_RES 0x01
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445typedef struct sgb {
446 unchar len[3];
447 unchar ptr[3];
448} Sgb;
449
450typedef struct scb {
451 unchar op;
452 unchar idlun;
453
454
455
456 unchar cdb[12];
457 volatile unchar status;
458 volatile unchar vue;
459 unchar maxlen[3];
460 unchar dataptr[3];
461 unchar linkptr[3];
462 unchar direc;
463 unchar reserved2[6];
464
465 struct scsi_cmnd *SCpnt;
466 Sgb sgb[WD7000_SG];
467 Adapter *host;
468 struct scb *next;
469} Scb;
470
471
472
473
474
475
476
477
478
479
480
481
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
489
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
498
499typedef struct icbRecvCmd {
500 unchar op;
501 unchar IDlun;
502 unchar len[3];
503 unchar ptr[3];
504 unchar rsvd[7];
505 volatile unchar vue;
506 volatile unchar status;
507 volatile unchar phase;
508} IcbRecvCmd;
509
510typedef struct icbSendStat {
511 unchar op;
512 unchar IDlun;
513 unchar stat;
514 unchar rsvd[12];
515 volatile unchar vue;
516 volatile unchar status;
517 volatile unchar phase;
518} IcbSendStat;
519
520typedef struct icbRevLvl {
521 unchar op;
522 volatile unchar primary;
523 volatile unchar secondary;
524 unchar rsvd[12];
525 volatile unchar vue;
526 volatile unchar status;
527 volatile unchar phase;
528} IcbRevLvl;
529
530typedef struct icbUnsMask {
531 unchar op;
532 volatile unchar mask[14];
533#if 0
534 unchar rsvd[12];
535#endif
536 volatile unchar vue;
537 volatile unchar status;
538 volatile unchar phase;
539} IcbUnsMask;
540
541typedef struct icbDiag {
542 unchar op;
543 unchar type;
544 unchar len[3];
545 unchar ptr[3];
546 unchar rsvd[7];
547 volatile unchar vue;
548 volatile unchar status;
549 volatile unchar phase;
550} IcbDiag;
551
552#define ICB_DIAG_POWERUP 0
553#define ICB_DIAG_WALKING 1
554#define ICB_DIAG_DMA 2
555#define ICB_DIAG_FULL 3
556
557typedef struct icbParms {
558 unchar op;
559 unchar rsvd1;
560 unchar len[3];
561 unchar ptr[3];
562 unchar idx[2];
563 unchar rsvd2[5];
564 volatile unchar vue;
565 volatile unchar status;
566 volatile unchar phase;
567} IcbParms;
568
569typedef struct icbAny {
570 unchar op;
571 unchar data[14];
572 volatile unchar vue;
573 volatile unchar status;
574 volatile unchar phase;
575} IcbAny;
576
577typedef union icb {
578 unchar op;
579 IcbRecvCmd recv_cmd;
580 IcbSendStat send_stat;
581 IcbRevLvl rev_lvl;
582 IcbDiag diag;
583 IcbParms eparms;
584 IcbAny icb;
585 unchar data[18];
586} Icb;
587
588#ifdef MODULE
589static char *wd7000;
590module_param(wd7000, charp, 0);
591#endif
592
593
594
595
596
597
598
599static Scb scbs[MAX_SCBS];
600static Scb *scbfree;
601static int freescbs = MAX_SCBS;
602static spinlock_t scbpool_lock;
603
604
605
606
607static void __init setup_error(char *mesg, int *ints)
608{
609 if (ints[0] == 3)
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);
613 else
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);
615}
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632static int __init wd7000_setup(char *str)
633{
634 static short wd7000_card_num;
635 short i;
636 int ints[6];
637
638 (void) get_options(str, ARRAY_SIZE(ints), ints);
639
640 if (wd7000_card_num >= NUM_CONFIGS) {
641 printk(KERN_ERR "%s: Too many \"wd7000=\" configurations in " "command line!\n", __func__);
642 return 0;
643 }
644
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__);
647 } else {
648 for (i = 0; i < NUM_IRQS; i++)
649 if (ints[1] == wd7000_irq[i])
650 break;
651
652 if (i == NUM_IRQS) {
653 setup_error("invalid IRQ.", ints);
654 return 0;
655 } else
656 configs[wd7000_card_num].irq = ints[1];
657
658 for (i = 0; i < NUM_DMAS; i++)
659 if (ints[2] == wd7000_dma[i])
660 break;
661
662 if (i == NUM_DMAS) {
663 setup_error("invalid DMA channel.", ints);
664 return 0;
665 } else
666 configs[wd7000_card_num].dma = ints[2];
667
668 for (i = 0; i < NUM_IOPORTS; i++)
669 if (ints[3] == wd7000_iobase[i])
670 break;
671
672 if (i == NUM_IOPORTS) {
673 setup_error("invalid I/O base address.", ints);
674 return 0;
675 } else
676 configs[wd7000_card_num].iobase = ints[3];
677
678 if (ints[0] > 3) {
679 if ((ints[4] < 500) || (ints[4] > 31875)) {
680 setup_error("BUS_ON value is out of range (500" " to 31875 nanoseconds)!", ints);
681 configs[wd7000_card_num].bus_on = BUS_ON;
682 } else
683 configs[wd7000_card_num].bus_on = ints[4] / 125;
684 } else
685 configs[wd7000_card_num].bus_on = BUS_ON;
686
687 if (ints[0] > 4) {
688 if ((ints[5] < 500) || (ints[5] > 31875)) {
689 setup_error("BUS_OFF value is out of range (500" " to 31875 nanoseconds)!", ints);
690 configs[wd7000_card_num].bus_off = BUS_OFF;
691 } else
692 configs[wd7000_card_num].bus_off = ints[5] / 125;
693 } else
694 configs[wd7000_card_num].bus_off = BUS_OFF;
695
696 if (wd7000_card_num) {
697 for (i = 0; i < (wd7000_card_num - 1); i++) {
698 int j = i + 1;
699
700 for (; j < wd7000_card_num; j++)
701 if (configs[i].irq == configs[j].irq) {
702 setup_error("duplicated IRQ!", ints);
703 return 0;
704 }
705 if (configs[i].dma == configs[j].dma) {
706 setup_error("duplicated DMA " "channel!", ints);
707 return 0;
708 }
709 if (configs[i].iobase == configs[j].iobase) {
710 setup_error("duplicated I/O " "base address!", ints);
711 return 0;
712 }
713 }
714 }
715
716 dprintk(KERN_DEBUG "wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, "
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);
718
719 wd7000_card_num++;
720 }
721 return 1;
722}
723
724__setup("wd7000=", wd7000_setup);
725
726static inline void any2scsi(unchar * scsi, int any)
727{
728 *scsi++ = (unsigned)any >> 16;
729 *scsi++ = (unsigned)any >> 8;
730 *scsi++ = any;
731}
732
733static inline int scsi2int(unchar * scsi)
734{
735 return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2];
736}
737
738static inline void wd7000_enable_intr(Adapter * host)
739{
740 host->control |= INT_EN;
741 outb(host->control, host->iobase + ASC_CONTROL);
742}
743
744
745static inline void wd7000_enable_dma(Adapter * host)
746{
747 unsigned long flags;
748 host->control |= DMA_EN;
749 outb(host->control, host->iobase + ASC_CONTROL);
750
751 flags = claim_dma_lock();
752 set_dma_mode(host->dma, DMA_MODE_CASCADE);
753 enable_dma(host->dma);
754 release_dma_lock(flags);
755
756}
757
758
759#define WAITnexttimeout 200
760
761static inline short WAIT(unsigned port, unsigned mask, unsigned allof, unsigned noneof)
762{
763 unsigned WAITbits;
764 unsigned long WAITtimeout = jiffies + WAITnexttimeout;
765
766 while (time_before_eq(jiffies, WAITtimeout)) {
767 WAITbits = inb(port) & mask;
768
769 if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0))
770 return (0);
771 }
772
773 return (1);
774}
775
776
777static inline int command_out(Adapter * host, unchar * cmd, int len)
778{
779 if (!WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
780 while (len--) {
781 do {
782 outb(*cmd, host->iobase + ASC_COMMAND);
783 WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0);
784 } while (inb(host->iobase + ASC_STAT) & CMD_REJ);
785
786 cmd++;
787 }
788
789 return (1);
790 }
791
792 printk(KERN_WARNING "wd7000 command_out: WAIT failed(%d)\n", len + 1);
793
794 return (0);
795}
796
797
798
799
800
801
802
803
804
805
806
807
808static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed)
809{
810 Scb *scb, *p = NULL;
811 unsigned long flags;
812 unsigned long timeout = jiffies + WAITnexttimeout;
813 unsigned long now;
814 int i;
815
816 if (needed <= 0)
817 return (NULL);
818
819 spin_unlock_irq(host->host_lock);
820
821 retry:
822 while (freescbs < needed) {
823 timeout = jiffies + WAITnexttimeout;
824 do {
825
826 for (now = jiffies; now == jiffies;)
827 cpu_relax();
828 } while (freescbs < needed && time_before_eq(jiffies, timeout));
829
830
831
832
833 if (freescbs < needed) {
834 printk(KERN_ERR "wd7000: can't get enough free SCBs.\n");
835 return (NULL);
836 }
837 }
838
839
840 spin_lock_irqsave(&scbpool_lock, flags);
841 if (freescbs < needed) {
842 spin_unlock_irqrestore(&scbpool_lock, flags);
843 goto retry;
844 }
845
846 scb = scbfree;
847 freescbs -= needed;
848 for (i = 0; i < needed; i++) {
849 p = scbfree;
850 scbfree = p->next;
851 }
852 p->next = NULL;
853
854 spin_unlock_irqrestore(&scbpool_lock, flags);
855
856 spin_lock_irq(host->host_lock);
857 return (scb);
858}
859
860
861static inline void free_scb(Scb * scb)
862{
863 unsigned long flags;
864
865 spin_lock_irqsave(&scbpool_lock, flags);
866
867 memset(scb, 0, sizeof(Scb));
868 scb->next = scbfree;
869 scbfree = scb;
870 freescbs++;
871
872 spin_unlock_irqrestore(&scbpool_lock, flags);
873}
874
875
876static inline void init_scbs(void)
877{
878 int i;
879
880 spin_lock_init(&scbpool_lock);
881
882
883
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]);
888 scbs[i].SCpnt = NULL;
889 }
890 scbs[MAX_SCBS - 1].next = NULL;
891 scbs[MAX_SCBS - 1].SCpnt = NULL;
892}
893
894
895static int mail_out(Adapter * host, Scb * scbptr)
896
897
898
899{
900 int i, ogmb;
901 unsigned long flags;
902 unchar start_ogmb;
903 Mailbox *ogmbs = host->mb.ogmb;
904 int *next_ogmb = &(host->next_ogmb);
905
906 dprintk("wd7000_mail_out: 0x%06lx", (long) scbptr);
907
908
909 spin_lock_irqsave(host->sh->host_lock, flags);
910 ogmb = *next_ogmb;
911 for (i = 0; i < OGMB_CNT; i++) {
912 if (ogmbs[ogmb].status == 0) {
913 dprintk(" using OGMB 0x%x", ogmb);
914 ogmbs[ogmb].status = 1;
915 any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr);
916
917 *next_ogmb = (ogmb + 1) % OGMB_CNT;
918 break;
919 } else
920 ogmb = (ogmb + 1) % OGMB_CNT;
921 }
922 spin_unlock_irqrestore(host->sh->host_lock, flags);
923
924 dprintk(", scb is 0x%06lx", (long) scbptr);
925
926 if (i >= OGMB_CNT) {
927
928
929
930
931
932
933
934
935 dprintk(", no free OGMBs.\n");
936 return (0);
937 }
938
939 wd7000_enable_intr(host);
940
941 start_ogmb = START_OGMB | ogmb;
942 command_out(host, &start_ogmb, 1);
943
944 dprintk(", awaiting interrupt.\n");
945
946 return (1);
947}
948
949
950static int make_code(unsigned hosterr, unsigned scsierr)
951{
952#ifdef WD7000_DEBUG
953 int in_error = hosterr;
954#endif
955
956 switch ((hosterr >> 8) & 0xff) {
957 case 0:
958 hosterr = DID_ERROR;
959 break;
960 case 1:
961 hosterr = DID_OK;
962 break;
963 case 2:
964 hosterr = DID_OK;
965 break;
966 case 4:
967 hosterr = DID_TIME_OUT;
968 break;
969 case 5:
970 hosterr = DID_RESET;
971 break;
972 case 6:
973 hosterr = DID_BAD_TARGET;
974 break;
975 case 80:
976 case 81:
977 hosterr = DID_BAD_INTR;
978 break;
979 case 82:
980 hosterr = DID_ABORT;
981 break;
982 case 83:
983 case 84:
984 hosterr = DID_RESET;
985 break;
986 default:
987 hosterr = DID_ERROR;
988 }
989#ifdef WD7000_DEBUG
990 if (scsierr || hosterr)
991 dprintk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", scsierr, in_error, hosterr);
992#endif
993 return (scsierr | (hosterr << 16));
994}
995
996#define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK)
997
998
999static irqreturn_t wd7000_intr(int irq, void *dev_id)
1000{
1001 Adapter *host = (Adapter *) dev_id;
1002 int flag, icmb, errstatus, icmb_status;
1003 int host_error, scsi_error;
1004 Scb *scb;
1005 IcbAny *icb;
1006 struct scsi_cmnd *SCpnt;
1007 Mailbox *icmbs = host->mb.icmb;
1008 unsigned long flags;
1009
1010 spin_lock_irqsave(host->sh->host_lock, flags);
1011 host->int_counter++;
1012
1013 dprintk("wd7000_intr: irq = %d, host = 0x%06lx\n", irq, (long) host);
1014
1015 flag = inb(host->iobase + ASC_INTR_STAT);
1016
1017 dprintk("wd7000_intr: intr stat = 0x%02x\n", flag);
1018
1019 if (!(inb(host->iobase + ASC_STAT) & INT_IM)) {
1020
1021
1022
1023
1024
1025
1026
1027
1028 dprintk("wd7000_intr: phantom interrupt...\n");
1029 goto ack;
1030 }
1031
1032 if (!(flag & MB_INTR))
1033 goto ack;
1034
1035
1036 if (!(flag & IMB_INTR)) {
1037 dprintk("wd7000_intr: free outgoing mailbox\n");
1038
1039
1040
1041
1042
1043 goto ack;
1044 }
1045
1046
1047 icmb = flag & MB_MASK;
1048 icmb_status = icmbs[icmb].status;
1049 if (icmb_status & 0x80) {
1050 dprintk("wd7000_intr: unsolicited interrupt 0x%02x\n", icmb_status);
1051 goto ack;
1052 }
1053
1054
1055 scb = isa_bus_to_virt(scsi2int((unchar *) icmbs[icmb].scbptr));
1056 icmbs[icmb].status = 0;
1057 if (scb->op & ICB_OP_MASK) {
1058 icb = (IcbAny *) scb;
1059 icb->status = icmb_status;
1060 icb->phase = 0;
1061 goto ack;
1062 }
1063
1064 SCpnt = scb->SCpnt;
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;
1070
1071 free_scb(scb);
1072
1073 SCpnt->scsi_done(SCpnt);
1074 }
1075
1076 ack:
1077 dprintk("wd7000_intr: return from interrupt handler\n");
1078 wd7000_intr_ack(host);
1079
1080 spin_unlock_irqrestore(host->sh->host_lock, flags);
1081 return IRQ_HANDLED;
1082}
1083
1084static int wd7000_queuecommand_lck(struct scsi_cmnd *SCpnt,
1085 void (*done)(struct scsi_cmnd *))
1086{
1087 Scb *scb;
1088 Sgb *sgb;
1089 unchar *cdb = (unchar *) SCpnt->cmnd;
1090 unchar idlun;
1091 short cdblen;
1092 int nseg;
1093 Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
1094
1095 cdblen = SCpnt->cmd_len;
1096 idlun = ((SCpnt->device->id << 5) & 0xe0) | (SCpnt->device->lun & 7);
1097 SCpnt->scsi_done = done;
1098 SCpnt->SCp.phase = 1;
1099 scb = alloc_scbs(SCpnt->device->host, 1);
1100 scb->idlun = idlun;
1101 memcpy(scb->cdb, cdb, cdblen);
1102 scb->direc = 0x40;
1103
1104 scb->SCpnt = SCpnt;
1105 SCpnt->host_scribble = (unchar *) scb;
1106 scb->host = host;
1107
1108 nseg = scsi_sg_count(SCpnt);
1109 if (nseg > 1) {
1110 struct scatterlist *sg;
1111 unsigned i;
1112
1113 dprintk("Using scatter/gather with %d elements.\n", nseg);
1114
1115 sgb = scb->sgb;
1116 scb->op = 1;
1117 any2scsi(scb->dataptr, (int) sgb);
1118 any2scsi(scb->maxlen, nseg * sizeof(Sgb));
1119
1120 scsi_for_each_sg(SCpnt, sg, nseg, i) {
1121 any2scsi(sgb[i].ptr, isa_page_to_bus(sg_page(sg)) + sg->offset);
1122 any2scsi(sgb[i].len, sg->length);
1123 }
1124 } else {
1125 scb->op = 0;
1126 if (nseg) {
1127 struct scatterlist *sg = scsi_sglist(SCpnt);
1128 any2scsi(scb->dataptr, isa_page_to_bus(sg_page(sg)) + sg->offset);
1129 }
1130 any2scsi(scb->maxlen, scsi_bufflen(SCpnt));
1131 }
1132
1133
1134
1135 while (!mail_out(host, scb))
1136 cpu_relax();
1137
1138 return 0;
1139}
1140
1141static DEF_SCSI_QCMD(wd7000_queuecommand)
1142
1143static int wd7000_diagnostics(Adapter * host, int code)
1144{
1145 static IcbDiag icb = { ICB_OP_DIAGNOSTICS };
1146 static unchar buf[256];
1147 unsigned long timeout;
1148
1149 icb.type = code;
1150 any2scsi(icb.len, sizeof(buf));
1151 any2scsi(icb.ptr, (int) &buf);
1152 icb.phase = 1;
1153
1154
1155
1156
1157
1158 mail_out(host, (struct scb *) &icb);
1159 timeout = jiffies + WAITnexttimeout;
1160 while (icb.phase && time_before(jiffies, timeout)) {
1161 cpu_relax();
1162 barrier();
1163 }
1164
1165 if (icb.phase) {
1166 printk("wd7000_diagnostics: timed out.\n");
1167 return (0);
1168 }
1169 if (make_code(icb.vue | (icb.status << 8), 0)) {
1170 printk("wd7000_diagnostics: failed (0x%02x,0x%02x)\n", icb.vue, icb.status);
1171 return (0);
1172 }
1173
1174 return (1);
1175}
1176
1177
1178static int wd7000_adapter_reset(Adapter * host)
1179{
1180 InitCmd init_cmd = {
1181 INITIALIZATION,
1182 7,
1183 host->bus_on,
1184 host->bus_off,
1185 0,
1186 {0, 0, 0},
1187 OGMB_CNT,
1188 ICMB_CNT
1189 };
1190 int diag;
1191
1192
1193
1194
1195 outb(ASC_RES, host->iobase + ASC_CONTROL);
1196 udelay(40);
1197 outb(0, host->iobase + ASC_CONTROL);
1198 host->control = 0;
1199
1200 if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
1201 printk(KERN_ERR "wd7000_init: WAIT timed out.\n");
1202 return -1;
1203 }
1204
1205 if ((diag = inb(host->iobase + ASC_INTR_STAT)) != 1) {
1206 printk("wd7000_init: ");
1207
1208 switch (diag) {
1209 case 2:
1210 printk(KERN_ERR "RAM failure.\n");
1211 break;
1212 case 3:
1213 printk(KERN_ERR "FIFO R/W failed\n");
1214 break;
1215 case 4:
1216 printk(KERN_ERR "SBIC register R/W failed\n");
1217 break;
1218 case 5:
1219 printk(KERN_ERR "Initialization D-FF failed.\n");
1220 break;
1221 case 6:
1222 printk(KERN_ERR "Host IRQ D-FF failed.\n");
1223 break;
1224 case 7:
1225 printk(KERN_ERR "ROM checksum error.\n");
1226 break;
1227 default:
1228 printk(KERN_ERR "diagnostic code 0x%02Xh received.\n", diag);
1229 }
1230 return -1;
1231 }
1232
1233 memset(&(host->mb), 0, sizeof(host->mb));
1234
1235
1236 any2scsi((unchar *) & (init_cmd.mailboxes), (int) &(host->mb));
1237 if (!command_out(host, (unchar *) & init_cmd, sizeof(init_cmd))) {
1238 printk(KERN_ERR "wd7000_adapter_reset: adapter initialization failed.\n");
1239 return -1;
1240 }
1241
1242 if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) {
1243 printk("wd7000_adapter_reset: WAIT timed out.\n");
1244 return -1;
1245 }
1246 return 0;
1247}
1248
1249static int wd7000_init(Adapter * host)
1250{
1251 if (wd7000_adapter_reset(host) == -1)
1252 return 0;
1253
1254
1255 if (request_irq(host->irq, wd7000_intr, 0, "wd7000", host)) {
1256 printk("wd7000_init: can't get IRQ %d.\n", host->irq);
1257 return (0);
1258 }
1259 if (request_dma(host->dma, "wd7000")) {
1260 printk("wd7000_init: can't get DMA channel %d.\n", host->dma);
1261 free_irq(host->irq, host);
1262 return (0);
1263 }
1264 wd7000_enable_dma(host);
1265 wd7000_enable_intr(host);
1266
1267 if (!wd7000_diagnostics(host, ICB_DIAG_FULL)) {
1268 free_dma(host->dma);
1269 free_irq(host->irq, NULL);
1270 return (0);
1271 }
1272
1273 return (1);
1274}
1275
1276
1277static void wd7000_revision(Adapter * host)
1278{
1279 static IcbRevLvl icb = { ICB_OP_GET_REVISION };
1280
1281 icb.phase = 1;
1282
1283
1284
1285
1286
1287
1288 mail_out(host, (struct scb *) &icb);
1289 while (icb.phase) {
1290 cpu_relax();
1291 barrier();
1292 }
1293 host->rev1 = icb.primary;
1294 host->rev2 = icb.secondary;
1295}
1296
1297
1298static int wd7000_set_info(struct Scsi_Host *host, char *buffer, int length)
1299{
1300 dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length);
1301
1302
1303
1304
1305 dprintk("Sorry, this function is currently out of order...\n");
1306 return (length);
1307}
1308
1309
1310static int wd7000_show_info(struct seq_file *m, struct Scsi_Host *host)
1311{
1312 Adapter *adapter = (Adapter *)host->hostdata;
1313 unsigned long flags;
1314#ifdef WD7000_DEBUG
1315 Mailbox *ogmbs, *icmbs;
1316 short count;
1317#endif
1318
1319 spin_lock_irqsave(host->host_lock, flags);
1320 seq_printf(m, "Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", host->host_no, adapter->rev1, adapter->rev2);
1321 seq_printf(m, " IO base: 0x%x\n", adapter->iobase);
1322 seq_printf(m, " IRQ: %d\n", adapter->irq);
1323 seq_printf(m, " DMA channel: %d\n", adapter->dma);
1324 seq_printf(m, " Interrupts: %d\n", adapter->int_counter);
1325 seq_printf(m, " BUS_ON time: %d nanoseconds\n", adapter->bus_on * 125);
1326 seq_printf(m, " BUS_OFF time: %d nanoseconds\n", adapter->bus_off * 125);
1327
1328#ifdef WD7000_DEBUG
1329 ogmbs = adapter->mb.ogmb;
1330 icmbs = adapter->mb.icmb;
1331
1332 seq_printf(m, "\nControl port value: 0x%x\n", adapter->control);
1333 seq_puts(m, "Incoming mailbox:\n");
1334 seq_printf(m, " size: %d\n", ICMB_CNT);
1335 seq_puts(m, " queued messages: ");
1336
1337 for (i = count = 0; i < ICMB_CNT; i++)
1338 if (icmbs[i].status) {
1339 count++;
1340 seq_printf(m, "0x%x ", i);
1341 }
1342
1343 seq_puts(m, count ? "\n" : "none\n");
1344
1345 seq_puts(m, "Outgoing mailbox:\n");
1346 seq_printf(m, " size: %d\n", OGMB_CNT);
1347 seq_printf(m, " next message: 0x%x\n", adapter->next_ogmb);
1348 seq_puts(m, " queued messages: ");
1349
1350 for (i = count = 0; i < OGMB_CNT; i++)
1351 if (ogmbs[i].status) {
1352 count++;
1353 seq_printf(m, "0x%x ", i);
1354 }
1355
1356 seq_puts(m, count ? "\n" : "none\n");
1357#endif
1358
1359 spin_unlock_irqrestore(host->host_lock, flags);
1360
1361 return 0;
1362}
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376static __init int wd7000_detect(struct scsi_host_template *tpnt)
1377{
1378 short present = 0, biosaddr_ptr, sig_ptr, i, pass;
1379 short biosptr[NUM_CONFIGS];
1380 unsigned iobase;
1381 Adapter *host = NULL;
1382 struct Scsi_Host *sh;
1383 int unit = 0;
1384
1385 dprintk("wd7000_detect: started\n");
1386
1387#ifdef MODULE
1388 if (wd7000)
1389 wd7000_setup(wd7000);
1390#endif
1391
1392 for (i = 0; i < UNITS; wd7000_host[i++] = NULL);
1393 for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
1394
1395 tpnt->proc_name = "wd7000";
1396 tpnt->show_info = &wd7000_show_info;
1397 tpnt->write_info = wd7000_set_info;
1398
1399
1400
1401
1402 init_scbs();
1403
1404 for (pass = 0; pass < NUM_CONFIGS; pass++) {
1405
1406
1407
1408 for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++)
1409 for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) {
1410 for (i = 0; i < pass; i++)
1411 if (biosptr[i] == biosaddr_ptr)
1412 break;
1413
1414 if (i == pass) {
1415 void __iomem *biosaddr = ioremap(wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs,
1416 signatures[sig_ptr].len);
1417 short bios_match = 1;
1418
1419 if (biosaddr)
1420 bios_match = check_signature(biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len);
1421
1422 iounmap(biosaddr);
1423
1424 if (bios_match)
1425 goto bios_matched;
1426 }
1427 }
1428
1429 bios_matched:
1430
1431
1432
1433#ifdef WD7000_DEBUG
1434 dprintk("wd7000_detect: pass %d\n", pass + 1);
1435
1436 if (biosaddr_ptr == NUM_ADDRS)
1437 dprintk("WD-7000 SST BIOS not detected...\n");
1438 else
1439 dprintk("WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]);
1440#endif
1441
1442 if (configs[pass].irq < 0)
1443 continue;
1444
1445 if (unit == UNITS)
1446 continue;
1447
1448 iobase = configs[pass].iobase;
1449
1450 dprintk("wd7000_detect: check IO 0x%x region...\n", iobase);
1451
1452 if (request_region(iobase, 4, "wd7000")) {
1453
1454 dprintk("wd7000_detect: ASC reset (IO 0x%x) ...", iobase);
1455
1456
1457
1458 outb(ASC_RES, iobase + ASC_CONTROL);
1459 msleep(10);
1460 outb(0, iobase + ASC_CONTROL);
1461
1462 if (WAIT(iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
1463 dprintk("failed!\n");
1464 goto err_release;
1465 } else
1466 dprintk("ok!\n");
1467
1468 if (inb(iobase + ASC_INTR_STAT) == 1) {
1469
1470
1471
1472
1473
1474
1475
1476 sh = scsi_register(tpnt, sizeof(Adapter));
1477 if (sh == NULL)
1478 goto err_release;
1479
1480 host = (Adapter *) sh->hostdata;
1481
1482 dprintk("wd7000_detect: adapter allocated at 0x%x\n", (int) host);
1483 memset(host, 0, sizeof(Adapter));
1484
1485 host->irq = configs[pass].irq;
1486 host->dma = configs[pass].dma;
1487 host->iobase = iobase;
1488 host->int_counter = 0;
1489 host->bus_on = configs[pass].bus_on;
1490 host->bus_off = configs[pass].bus_off;
1491 host->sh = wd7000_host[unit] = sh;
1492 unit++;
1493
1494 dprintk("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma);
1495
1496 if (!wd7000_init(host))
1497 goto err_unregister;
1498
1499
1500
1501
1502 wd7000_revision(host);
1503
1504
1505
1506
1507 if (host->rev1 < 6)
1508 sh->sg_tablesize = 1;
1509
1510 present++;
1511
1512 if (biosaddr_ptr != NUM_ADDRS)
1513 biosptr[pass] = biosaddr_ptr;
1514
1515 printk(KERN_INFO "Western Digital WD-7000 (rev %d.%d) ", host->rev1, host->rev2);
1516 printk("using IO 0x%x, IRQ %d, DMA %d.\n", host->iobase, host->irq, host->dma);
1517 printk(" BUS_ON time: %dns, BUS_OFF time: %dns\n", host->bus_on * 125, host->bus_off * 125);
1518 }
1519 } else
1520 dprintk("wd7000_detect: IO 0x%x region already allocated!\n", iobase);
1521
1522 continue;
1523
1524 err_unregister:
1525 scsi_unregister(sh);
1526 err_release:
1527 release_region(iobase, 4);
1528
1529 }
1530
1531 if (!present)
1532 printk("Failed initialization of WD-7000 SCSI card!\n");
1533
1534 return (present);
1535}
1536
1537static int wd7000_release(struct Scsi_Host *shost)
1538{
1539 if (shost->irq)
1540 free_irq(shost->irq, NULL);
1541 if (shost->io_port && shost->n_io_port)
1542 release_region(shost->io_port, shost->n_io_port);
1543 scsi_unregister(shost);
1544 return 0;
1545}
1546
1547#if 0
1548
1549
1550
1551static int wd7000_abort(Scsi_Cmnd * SCpnt)
1552{
1553 Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
1554
1555 if (inb(host->iobase + ASC_STAT) & INT_IM) {
1556 printk("wd7000_abort: lost interrupt\n");
1557 wd7000_intr_handle(host->irq, NULL, NULL);
1558 return FAILED;
1559 }
1560 return FAILED;
1561}
1562#endif
1563
1564
1565
1566
1567
1568static int wd7000_host_reset(struct scsi_cmnd *SCpnt)
1569{
1570 Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
1571
1572 spin_lock_irq(SCpnt->device->host->host_lock);
1573
1574 if (wd7000_adapter_reset(host) < 0) {
1575 spin_unlock_irq(SCpnt->device->host->host_lock);
1576 return FAILED;
1577 }
1578
1579 wd7000_enable_intr(host);
1580
1581 spin_unlock_irq(SCpnt->device->host->host_lock);
1582 return SUCCESS;
1583}
1584
1585
1586
1587
1588
1589static int wd7000_biosparam(struct scsi_device *sdev,
1590 struct block_device *bdev, sector_t capacity, int *ip)
1591{
1592 char b[BDEVNAME_SIZE];
1593
1594 dprintk("wd7000_biosparam: dev=%s, size=%llu, ",
1595 bdevname(bdev, b), (u64)capacity);
1596 (void)b;
1597
1598
1599
1600
1601 ip[0] = 64;
1602 ip[1] = 32;
1603 ip[2] = capacity >> 11;
1604
1605
1606
1607
1608 if (ip[2] >= 1024) {
1609 int info[3];
1610
1611
1612
1613
1614 if ((scsicam_bios_param(bdev, capacity, info) < 0) || !(((info[0] == 64) && (info[1] == 32)) || ((info[0] == 255) && (info[1] == 63)))) {
1615 printk("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" " using extended translation.\n");
1616
1617 ip[0] = 255;
1618 ip[1] = 63;
1619 ip[2] = (unsigned long) capacity / (255 * 63);
1620 } else {
1621 ip[0] = info[0];
1622 ip[1] = info[1];
1623 ip[2] = info[2];
1624
1625 if (info[0] == 255)
1626 printk(KERN_INFO "%s: current partition table is " "using extended translation.\n", __func__);
1627 }
1628 }
1629
1630 dprintk("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]);
1631 dprintk("WARNING: check, if the bios geometry is correct.\n");
1632
1633 return (0);
1634}
1635
1636MODULE_AUTHOR("Thomas Wuensche, John Boyd, Miroslav Zagorac");
1637MODULE_DESCRIPTION("Driver for the WD7000 series ISA controllers");
1638MODULE_LICENSE("GPL");
1639
1640static struct scsi_host_template driver_template = {
1641 .proc_name = "wd7000",
1642 .show_info = wd7000_show_info,
1643 .write_info = wd7000_set_info,
1644 .name = "Western Digital WD-7000",
1645 .detect = wd7000_detect,
1646 .release = wd7000_release,
1647 .queuecommand = wd7000_queuecommand,
1648 .eh_host_reset_handler = wd7000_host_reset,
1649 .bios_param = wd7000_biosparam,
1650 .can_queue = WD7000_Q,
1651 .this_id = 7,
1652 .sg_tablesize = WD7000_SG,
1653 .unchecked_isa_dma = 1,
1654 .use_clustering = ENABLE_CLUSTERING,
1655};
1656
1657#include "scsi_module.c"
1658