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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269#include <linux/module.h>
270#include <linux/init.h>
271#include <linux/interrupt.h>
272#include <linux/blkdev.h>
273#include <linux/spinlock.h>
274#include <linux/errno.h>
275#include <linux/string.h>
276#include <linux/ioport.h>
277#include <linux/proc_fs.h>
278#include <linux/pci.h>
279#include <linux/stat.h>
280#include <linux/delay.h>
281#include <linux/io.h>
282#include <scsi/scsicam.h>
283
284#include <asm/system.h>
285
286#include <scsi/scsi.h>
287#include <scsi/scsi_cmnd.h>
288#include <scsi/scsi_device.h>
289#include <scsi/scsi_host.h>
290#include <scsi/scsi_ioctl.h>
291#include "fdomain.h"
292
293MODULE_AUTHOR("Rickard E. Faith");
294MODULE_DESCRIPTION("Future domain SCSI driver");
295MODULE_LICENSE("GPL");
296
297
298#define VERSION "$Revision: 5.51 $"
299
300
301
302#define DEBUG 0
303#define ENABLE_PARITY 1
304#define FIFO_COUNT 2
305
306
307
308#if DEBUG
309#define EVERY_ACCESS 0
310#define ERRORS_ONLY 1
311#define DEBUG_DETECT 0
312#define DEBUG_MESSAGES 1
313#define DEBUG_ABORT 1
314#define DEBUG_RESET 1
315#define DEBUG_RACE 1
316#else
317#define EVERY_ACCESS 0
318#define ERRORS_ONLY 0
319#define DEBUG_DETECT 0
320#define DEBUG_MESSAGES 0
321#define DEBUG_ABORT 0
322#define DEBUG_RESET 0
323#define DEBUG_RACE 0
324#endif
325
326
327#if EVERY_ACCESS
328#undef ERRORS_ONLY
329#define ERRORS_ONLY 0
330#endif
331
332#if ENABLE_PARITY
333#define PARITY_MASK 0x08
334#else
335#define PARITY_MASK 0x00
336#endif
337
338enum chip_type {
339 unknown = 0x00,
340 tmc1800 = 0x01,
341 tmc18c50 = 0x02,
342 tmc18c30 = 0x03,
343};
344
345enum {
346 in_arbitration = 0x02,
347 in_selection = 0x04,
348 in_other = 0x08,
349 disconnect = 0x10,
350 aborted = 0x20,
351 sent_ident = 0x40,
352};
353
354enum in_port_type {
355 Read_SCSI_Data = 0,
356 SCSI_Status = 1,
357 TMC_Status = 2,
358 FIFO_Status = 3,
359 Interrupt_Cond = 4,
360 LSB_ID_Code = 5,
361 MSB_ID_Code = 6,
362 Read_Loopback = 7,
363 SCSI_Data_NoACK = 8,
364 Interrupt_Status = 9,
365 Configuration1 = 10,
366 Configuration2 = 11,
367 Read_FIFO = 12,
368 FIFO_Data_Count = 14
369};
370
371enum out_port_type {
372 Write_SCSI_Data = 0,
373 SCSI_Cntl = 1,
374 Interrupt_Cntl = 2,
375 SCSI_Mode_Cntl = 3,
376 TMC_Cntl = 4,
377 Memory_Cntl = 5,
378 Write_Loopback = 7,
379 IO_Control = 11,
380 Write_FIFO = 12
381};
382
383
384static int port_base;
385static unsigned long bios_base;
386static void __iomem * bios_mem;
387static int bios_major;
388static int bios_minor;
389static int PCI_bus;
390#ifdef CONFIG_PCI
391static struct pci_dev *PCI_dev;
392#endif
393static int Quantum;
394static int interrupt_level;
395static volatile int in_command;
396static struct scsi_cmnd *current_SC;
397static enum chip_type chip = unknown;
398static int adapter_mask;
399static int this_id;
400static int setup_called;
401
402#if DEBUG_RACE
403static volatile int in_interrupt_flag;
404#endif
405
406static int FIFO_Size = 0x2000;
407
408
409static irqreturn_t do_fdomain_16x0_intr( int irq, void *dev_id );
410
411
412static char * fdomain = NULL;
413module_param(fdomain, charp, 0);
414
415#ifndef PCMCIA
416
417static unsigned long addresses[] = {
418 0xc8000,
419 0xca000,
420 0xce000,
421 0xde000,
422 0xcc000,
423 0xd0000,
424 0xe0000,
425};
426#define ADDRESS_COUNT ARRAY_SIZE(addresses)
427
428static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
429#define PORT_COUNT ARRAY_SIZE(ports)
430
431static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
432
433#endif
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467#ifndef PCMCIA
468
469static struct signature {
470 const char *signature;
471 int sig_offset;
472 int sig_length;
473 int major_bios_version;
474 int minor_bios_version;
475 int flag;
476} signatures[] = {
477
478
479 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
480 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
481 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
482 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
483 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
484 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
485 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
486 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
487 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
488 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
489 { "Adaptec AHA-2920 PCI-SCSI Card", 42, 31, 3, -1, 1 },
490 { "IBM F1 P264/32", 5, 14, 3, -1, 1 },
491
492 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
493 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
494 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
495 { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 },
496 { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 },
497 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
498
499
500
501
502
503
504
505
506
507
508
509
510};
511
512#define SIGNATURE_COUNT ARRAY_SIZE(signatures)
513
514#endif
515
516static void print_banner( struct Scsi_Host *shpnt )
517{
518 if (!shpnt) return;
519
520 if (bios_major < 0 && bios_minor < 0) {
521 printk(KERN_INFO "scsi%d: <fdomain> No BIOS; using scsi id %d\n",
522 shpnt->host_no, shpnt->this_id);
523 } else {
524 printk(KERN_INFO "scsi%d: <fdomain> BIOS version ", shpnt->host_no);
525
526 if (bios_major >= 0) printk("%d.", bios_major);
527 else printk("?.");
528
529 if (bios_minor >= 0) printk("%d", bios_minor);
530 else printk("?.");
531
532 printk( " at 0x%lx using scsi id %d\n",
533 bios_base, shpnt->this_id );
534 }
535
536
537
538
539
540 printk(KERN_INFO "scsi%d: <fdomain> %s chip at 0x%x irq ",
541 shpnt->host_no,
542 chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")),
543 port_base);
544
545 if (interrupt_level)
546 printk("%d", interrupt_level);
547 else
548 printk("<none>");
549
550 printk( "\n" );
551}
552
553int fdomain_setup(char *str)
554{
555 int ints[4];
556
557 (void)get_options(str, ARRAY_SIZE(ints), ints);
558
559 if (setup_called++ || ints[0] < 2 || ints[0] > 3) {
560 printk(KERN_INFO "scsi: <fdomain> Usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n");
561 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
562 return 0;
563 }
564
565 port_base = ints[0] >= 1 ? ints[1] : 0;
566 interrupt_level = ints[0] >= 2 ? ints[2] : 0;
567 this_id = ints[0] >= 3 ? ints[3] : 0;
568
569 bios_major = bios_minor = -1;
570 ++setup_called;
571 return 1;
572}
573
574__setup("fdomain=", fdomain_setup);
575
576
577static void do_pause(unsigned amount)
578{
579 mdelay(10*amount);
580}
581
582static inline void fdomain_make_bus_idle( void )
583{
584 outb(0, port_base + SCSI_Cntl);
585 outb(0, port_base + SCSI_Mode_Cntl);
586 if (chip == tmc18c50 || chip == tmc18c30)
587 outb(0x21 | PARITY_MASK, port_base + TMC_Cntl);
588 else
589 outb(0x01 | PARITY_MASK, port_base + TMC_Cntl);
590}
591
592static int fdomain_is_valid_port( int port )
593{
594#if DEBUG_DETECT
595 printk( " (%x%x),",
596 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
597#endif
598
599
600
601
602
603
604
605 if (inb( port + LSB_ID_Code ) != 0xe9) {
606 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
607 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
608 chip = tmc1800;
609 } else {
610 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
611 chip = tmc18c50;
612
613
614
615
616
617
618 outb( 0x80, port + IO_Control );
619 if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
620 outb( 0x00, port + IO_Control );
621 if ((inb( port + Configuration2 ) & 0x80) == 0x00) {
622 chip = tmc18c30;
623 FIFO_Size = 0x800;
624 }
625 }
626
627 }
628
629 return 1;
630}
631
632static int fdomain_test_loopback( void )
633{
634 int i;
635 int result;
636
637 for (i = 0; i < 255; i++) {
638 outb( i, port_base + Write_Loopback );
639 result = inb( port_base + Read_Loopback );
640 if (i != result)
641 return 1;
642 }
643 return 0;
644}
645
646#ifndef PCMCIA
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662static int fdomain_get_irq( int base )
663{
664 int options = inb(base + Configuration1);
665
666#if DEBUG_DETECT
667 printk("scsi: <fdomain> Options = %x\n", options);
668#endif
669
670
671
672
673
674
675 if (chip != tmc18c30 && !PCI_bus && addresses[(options & 0xc0) >> 6 ] != bios_base)
676 return 0;
677 return ints[(options & 0x0e) >> 1];
678}
679
680static int fdomain_isa_detect( int *irq, int *iobase )
681{
682 int i, j;
683 int base = 0xdeadbeef;
684 int flag = 0;
685
686#if DEBUG_DETECT
687 printk( "scsi: <fdomain> fdomain_isa_detect:" );
688#endif
689
690 for (i = 0; i < ADDRESS_COUNT; i++) {
691 void __iomem *p = ioremap(addresses[i], 0x2000);
692 if (!p)
693 continue;
694#if DEBUG_DETECT
695 printk( " %lx(%lx),", addresses[i], bios_base );
696#endif
697 for (j = 0; j < SIGNATURE_COUNT; j++) {
698 if (check_signature(p + signatures[j].sig_offset,
699 signatures[j].signature,
700 signatures[j].sig_length )) {
701 bios_major = signatures[j].major_bios_version;
702 bios_minor = signatures[j].minor_bios_version;
703 PCI_bus = (signatures[j].flag == 1);
704 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
705 bios_base = addresses[i];
706 bios_mem = p;
707 goto found;
708 }
709 }
710 iounmap(p);
711 }
712
713found:
714 if (bios_major == 2) {
715
716
717
718
719
720
721
722
723 switch (Quantum) {
724 case 2:
725 case 3:
726 base = readb(bios_mem + 0x1fa2) + (readb(bios_mem + 0x1fa3) << 8);
727 break;
728 case 4:
729 base = readb(bios_mem + 0x1fa3) + (readb(bios_mem + 0x1fa4) << 8);
730 break;
731 default:
732 base = readb(bios_mem + 0x1fcc) + (readb(bios_mem + 0x1fcd) << 8);
733 break;
734 }
735
736#if DEBUG_DETECT
737 printk( " %x,", base );
738#endif
739
740 for (i = 0; i < PORT_COUNT; i++) {
741 if (base == ports[i]) {
742 if (!request_region(base, 0x10, "fdomain"))
743 break;
744 if (!fdomain_is_valid_port(base)) {
745 release_region(base, 0x10);
746 break;
747 }
748 *irq = fdomain_get_irq( base );
749 *iobase = base;
750 return 1;
751 }
752 }
753
754
755
756
757
758#if DEBUG_DETECT
759 printk( " RAM FAILED, " );
760#endif
761 }
762
763
764
765
766
767
768
769
770
771
772 for (i = 0; i < PORT_COUNT; i++) {
773 base = ports[i];
774 if (!request_region(base, 0x10, "fdomain")) {
775#if DEBUG_DETECT
776 printk( " (%x inuse),", base );
777#endif
778 continue;
779 }
780#if DEBUG_DETECT
781 printk( " %x,", base );
782#endif
783 flag = fdomain_is_valid_port(base);
784 if (flag)
785 break;
786 release_region(base, 0x10);
787 }
788
789#if DEBUG_DETECT
790 if (flag) printk( " SUCCESS\n" );
791 else printk( " FAILURE\n" );
792#endif
793
794 if (!flag) return 0;
795
796 *irq = fdomain_get_irq( base );
797 *iobase = base;
798
799 return 1;
800}
801
802#else
803
804static int fdomain_isa_detect( int *irq, int *iobase )
805{
806 if (irq)
807 *irq = 0;
808 if (iobase)
809 *iobase = 0;
810 return 0;
811}
812
813#endif
814
815
816
817
818
819
820#ifdef CONFIG_PCI
821static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_pdev )
822{
823 unsigned int pci_irq;
824 unsigned long pci_base;
825 struct pci_dev *pdev = NULL;
826
827#if DEBUG_DETECT
828
829
830
831 printk( "scsi: <fdomain> INFO: use lspci -v to see list of PCI devices\n" );
832 printk( "scsi: <fdomain> TMC-3260 detect:"
833 " Using Vendor ID: 0x%x and Device ID: 0x%x\n",
834 PCI_VENDOR_ID_FD,
835 PCI_DEVICE_ID_FD_36C70 );
836#endif
837
838 if ((pdev = pci_get_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL)
839 return 0;
840 if (pci_enable_device(pdev))
841 goto fail;
842
843#if DEBUG_DETECT
844 printk( "scsi: <fdomain> TMC-3260 detect:"
845 " PCI bus %u, device %u, function %u\n",
846 pdev->bus->number,
847 PCI_SLOT(pdev->devfn),
848 PCI_FUNC(pdev->devfn));
849#endif
850
851
852
853
854 pci_base = pci_resource_start(pdev, 0);
855 pci_irq = pdev->irq;
856
857 if (!request_region( pci_base, 0x10, "fdomain" ))
858 goto fail;
859
860
861
862
863 *irq = pci_irq;
864 *iobase = pci_base;
865 *ret_pdev = pdev;
866
867#if DEBUG_DETECT
868 printk( "scsi: <fdomain> TMC-3260 detect:"
869 " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
870#endif
871
872 if (!fdomain_is_valid_port(pci_base)) {
873 printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
874 release_region(pci_base, 0x10);
875 goto fail;
876 }
877
878
879 bios_major = bios_minor = -1;
880 PCI_bus = 1;
881 PCI_dev = pdev;
882 Quantum = 0;
883 bios_base = 0;
884
885 return 1;
886fail:
887 pci_dev_put(pdev);
888 return 0;
889}
890
891#endif
892
893struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
894{
895 int retcode;
896 struct Scsi_Host *shpnt;
897 struct pci_dev *pdev = NULL;
898
899 if (setup_called) {
900#if DEBUG_DETECT
901 printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
902 port_base, interrupt_level );
903#endif
904 if (!request_region(port_base, 0x10, "fdomain")) {
905 printk( "scsi: <fdomain> port 0x%x is busy\n", port_base );
906 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
907 return NULL;
908 }
909 if (!fdomain_is_valid_port( port_base )) {
910 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
911 port_base );
912 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
913 release_region(port_base, 0x10);
914 return NULL;
915 }
916 } else {
917 int flag = 0;
918
919#ifdef CONFIG_PCI
920
921 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base, &pdev );
922#endif
923 if (!flag) {
924
925 flag = fdomain_isa_detect( &interrupt_level, &port_base );
926
927 if (!flag) {
928 printk( "scsi: <fdomain> Detection failed (no card)\n" );
929 return NULL;
930 }
931 }
932 }
933
934 fdomain_16x0_bus_reset(NULL);
935
936 if (fdomain_test_loopback()) {
937 printk(KERN_ERR "scsi: <fdomain> Detection failed (loopback test failed at port base 0x%x)\n", port_base);
938 if (setup_called) {
939 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
940 }
941 goto fail;
942 }
943
944 if (this_id) {
945 tpnt->this_id = (this_id & 0x07);
946 adapter_mask = (1 << tpnt->this_id);
947 } else {
948 if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
949 tpnt->this_id = 7;
950 adapter_mask = 0x80;
951 } else {
952 tpnt->this_id = 6;
953 adapter_mask = 0x40;
954 }
955 }
956
957
958
959
960 shpnt = scsi_register( tpnt, 0 );
961 if(shpnt == NULL) {
962 release_region(port_base, 0x10);
963 return NULL;
964 }
965 shpnt->irq = interrupt_level;
966 shpnt->io_port = port_base;
967 shpnt->n_io_port = 0x10;
968 print_banner( shpnt );
969
970
971 if (!interrupt_level) {
972 printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
973 goto fail;
974 } else {
975
976
977 retcode = request_irq( interrupt_level,
978 do_fdomain_16x0_intr, pdev?IRQF_SHARED:0, "fdomain", shpnt);
979
980 if (retcode < 0) {
981 if (retcode == -EINVAL) {
982 printk(KERN_ERR "scsi: <fdomain> IRQ %d is bad!\n", interrupt_level );
983 printk(KERN_ERR " This shouldn't happen!\n" );
984 printk(KERN_ERR " Send mail to faith@acm.org\n" );
985 } else if (retcode == -EBUSY) {
986 printk(KERN_ERR "scsi: <fdomain> IRQ %d is already in use!\n", interrupt_level );
987 printk(KERN_ERR " Please use another IRQ!\n" );
988 } else {
989 printk(KERN_ERR "scsi: <fdomain> Error getting IRQ %d\n", interrupt_level );
990 printk(KERN_ERR " This shouldn't happen!\n" );
991 printk(KERN_ERR " Send mail to faith@acm.org\n" );
992 }
993 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
994 goto fail;
995 }
996 }
997 return shpnt;
998fail:
999 pci_dev_put(pdev);
1000 release_region(port_base, 0x10);
1001 return NULL;
1002}
1003
1004static int fdomain_16x0_detect(struct scsi_host_template *tpnt)
1005{
1006 if (fdomain)
1007 fdomain_setup(fdomain);
1008 return (__fdomain_16x0_detect(tpnt) != NULL);
1009}
1010
1011static const char *fdomain_16x0_info( struct Scsi_Host *ignore )
1012{
1013 static char buffer[128];
1014 char *pt;
1015
1016 strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" );
1017 if (strchr( VERSION, ':')) {
1018 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1019 pt = strrchr( buffer, '$') - 1;
1020 if (!pt)
1021 pt = buffer + strlen( buffer ) - 1;
1022 if (*pt != ' ')
1023 ++pt;
1024 *pt = '\0';
1025 } else {
1026 strcat( buffer, " " VERSION );
1027 }
1028
1029 return buffer;
1030}
1031
1032#if 0
1033static int fdomain_arbitrate( void )
1034{
1035 int status = 0;
1036 unsigned long timeout;
1037
1038#if EVERY_ACCESS
1039 printk( "fdomain_arbitrate()\n" );
1040#endif
1041
1042 outb(0x00, port_base + SCSI_Cntl);
1043 outb(adapter_mask, port_base + SCSI_Data_NoACK);
1044 outb(0x04 | PARITY_MASK, port_base + TMC_Cntl);
1045
1046 timeout = 500;
1047 do {
1048 status = inb(port_base + TMC_Status);
1049 if (status & 0x02)
1050 return 0;
1051 mdelay(1);
1052 } while (--timeout);
1053
1054
1055 fdomain_make_bus_idle();
1056
1057#if EVERY_ACCESS
1058 printk( "Arbitration failed, status = %x\n", status );
1059#endif
1060#if ERRORS_ONLY
1061 printk( "scsi: <fdomain> Arbitration failed, status = %x\n", status );
1062#endif
1063 return 1;
1064}
1065#endif
1066
1067static int fdomain_select( int target )
1068{
1069 int status;
1070 unsigned long timeout;
1071#if ERRORS_ONLY
1072 static int flag = 0;
1073#endif
1074
1075 outb(0x82, port_base + SCSI_Cntl);
1076 outb(adapter_mask | (1 << target), port_base + SCSI_Data_NoACK);
1077
1078
1079 outb(PARITY_MASK, port_base + TMC_Cntl);
1080
1081 timeout = 350;
1082
1083 do {
1084 status = inb(port_base + SCSI_Status);
1085 if (status & 1) {
1086
1087 outb(0x80, port_base + SCSI_Cntl);
1088 return 0;
1089 }
1090 mdelay(1);
1091 } while (--timeout);
1092
1093 fdomain_make_bus_idle();
1094#if EVERY_ACCESS
1095 if (!target) printk( "Selection failed\n" );
1096#endif
1097#if ERRORS_ONLY
1098 if (!target) {
1099 if (!flag)
1100 ++flag;
1101 else
1102 printk( "scsi: <fdomain> Selection failed\n" );
1103 }
1104#endif
1105 return 1;
1106}
1107
1108static void my_done(int error)
1109{
1110 if (in_command) {
1111 in_command = 0;
1112 outb(0x00, port_base + Interrupt_Cntl);
1113 fdomain_make_bus_idle();
1114 current_SC->result = error;
1115 if (current_SC->scsi_done)
1116 current_SC->scsi_done( current_SC );
1117 else panic( "scsi: <fdomain> current_SC->scsi_done() == NULL" );
1118 } else {
1119 panic( "scsi: <fdomain> my_done() called outside of command\n" );
1120 }
1121#if DEBUG_RACE
1122 in_interrupt_flag = 0;
1123#endif
1124}
1125
1126static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
1127{
1128 unsigned long flags;
1129 int status;
1130 int done = 0;
1131 unsigned data_count;
1132
1133
1134
1135
1136
1137
1138
1139
1140 if ((inb(port_base + TMC_Status) & 0x01) == 0)
1141 return IRQ_NONE;
1142
1143
1144 outb(0x00, port_base + Interrupt_Cntl);
1145
1146
1147 if (!in_command || !current_SC) {
1148#if EVERY_ACCESS
1149 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1150 in_command, current_SC );
1151#endif
1152 return IRQ_NONE;
1153 }
1154
1155
1156 if (current_SC->SCp.phase & aborted) {
1157#if DEBUG_ABORT
1158 printk( "scsi: <fdomain> Interrupt after abort, ignoring\n" );
1159#endif
1160
1161
1162 }
1163
1164#if DEBUG_RACE
1165 ++in_interrupt_flag;
1166#endif
1167
1168 if (current_SC->SCp.phase & in_arbitration) {
1169 status = inb(port_base + TMC_Status);
1170 if (!(status & 0x02)) {
1171#if EVERY_ACCESS
1172 printk( " AFAIL " );
1173#endif
1174 spin_lock_irqsave(current_SC->device->host->host_lock, flags);
1175 my_done( DID_BUS_BUSY << 16 );
1176 spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
1177 return IRQ_HANDLED;
1178 }
1179 current_SC->SCp.phase = in_selection;
1180
1181 outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl);
1182
1183 outb(0x82, port_base + SCSI_Cntl);
1184 outb(adapter_mask | (1 << scmd_id(current_SC)), port_base + SCSI_Data_NoACK);
1185
1186
1187 outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
1188#if DEBUG_RACE
1189 in_interrupt_flag = 0;
1190#endif
1191 return IRQ_HANDLED;
1192 } else if (current_SC->SCp.phase & in_selection) {
1193 status = inb(port_base + SCSI_Status);
1194 if (!(status & 0x01)) {
1195
1196 if (fdomain_select( scmd_id(current_SC) )) {
1197#if EVERY_ACCESS
1198 printk( " SFAIL " );
1199#endif
1200 spin_lock_irqsave(current_SC->device->host->host_lock, flags);
1201 my_done( DID_NO_CONNECT << 16 );
1202 spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
1203 return IRQ_HANDLED;
1204 } else {
1205#if EVERY_ACCESS
1206 printk( " AltSel " );
1207#endif
1208
1209 outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
1210 }
1211 }
1212 current_SC->SCp.phase = in_other;
1213 outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
1214 outb(0x80, port_base + SCSI_Cntl);
1215#if DEBUG_RACE
1216 in_interrupt_flag = 0;
1217#endif
1218 return IRQ_HANDLED;
1219 }
1220
1221
1222
1223 status = inb(port_base + SCSI_Status);
1224
1225 if (status & 0x10) {
1226
1227 switch (status & 0x0e) {
1228
1229 case 0x08:
1230 outb(current_SC->cmnd[current_SC->SCp.sent_command++],
1231 port_base + Write_SCSI_Data);
1232#if EVERY_ACCESS
1233 printk( "CMD = %x,",
1234 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1235#endif
1236 break;
1237 case 0x00:
1238 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
1239 current_SC->SCp.have_data_in = -1;
1240 outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
1241 }
1242 break;
1243 case 0x04:
1244 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
1245 current_SC->SCp.have_data_in = 1;
1246 outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
1247 }
1248 break;
1249 case 0x0c:
1250 current_SC->SCp.Status = inb(port_base + Read_SCSI_Data);
1251#if EVERY_ACCESS
1252 printk( "Status = %x, ", current_SC->SCp.Status );
1253#endif
1254#if ERRORS_ONLY
1255 if (current_SC->SCp.Status
1256 && current_SC->SCp.Status != 2
1257 && current_SC->SCp.Status != 8) {
1258 printk( "scsi: <fdomain> target = %d, command = %x, status = %x\n",
1259 current_SC->device->id,
1260 current_SC->cmnd[0],
1261 current_SC->SCp.Status );
1262 }
1263#endif
1264 break;
1265 case 0x0a:
1266 outb(MESSAGE_REJECT, port_base + Write_SCSI_Data);
1267 break;
1268 case 0x0e:
1269 current_SC->SCp.Message = inb(port_base + Read_SCSI_Data);
1270#if EVERY_ACCESS
1271 printk( "Message = %x, ", current_SC->SCp.Message );
1272#endif
1273 if (!current_SC->SCp.Message) ++done;
1274#if DEBUG_MESSAGES || EVERY_ACCESS
1275 if (current_SC->SCp.Message) {
1276 printk( "scsi: <fdomain> message = %x\n",
1277 current_SC->SCp.Message );
1278 }
1279#endif
1280 break;
1281 }
1282 }
1283
1284 if (chip == tmc1800 && !current_SC->SCp.have_data_in
1285 && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
1286
1287 if(current_SC->sc_data_direction == DMA_TO_DEVICE)
1288 {
1289 current_SC->SCp.have_data_in = -1;
1290 outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
1291 }
1292 else
1293 {
1294 current_SC->SCp.have_data_in = 1;
1295 outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
1296 }
1297 }
1298
1299 if (current_SC->SCp.have_data_in == -1) {
1300 while ((data_count = FIFO_Size - inw(port_base + FIFO_Data_Count)) > 512) {
1301#if EVERY_ACCESS
1302 printk( "DC=%d, ", data_count ) ;
1303#endif
1304 if (data_count > current_SC->SCp.this_residual)
1305 data_count = current_SC->SCp.this_residual;
1306 if (data_count > 0) {
1307#if EVERY_ACCESS
1308 printk( "%d OUT, ", data_count );
1309#endif
1310 if (data_count == 1) {
1311 outb(*current_SC->SCp.ptr++, port_base + Write_FIFO);
1312 --current_SC->SCp.this_residual;
1313 } else {
1314 data_count >>= 1;
1315 outsw(port_base + Write_FIFO, current_SC->SCp.ptr, data_count);
1316 current_SC->SCp.ptr += 2 * data_count;
1317 current_SC->SCp.this_residual -= 2 * data_count;
1318 }
1319 }
1320 if (!current_SC->SCp.this_residual) {
1321 if (current_SC->SCp.buffers_residual) {
1322 --current_SC->SCp.buffers_residual;
1323 ++current_SC->SCp.buffer;
1324 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1325 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1326 } else
1327 break;
1328 }
1329 }
1330 }
1331
1332 if (current_SC->SCp.have_data_in == 1) {
1333 while ((data_count = inw(port_base + FIFO_Data_Count)) > 0) {
1334#if EVERY_ACCESS
1335 printk( "DC=%d, ", data_count );
1336#endif
1337 if (data_count > current_SC->SCp.this_residual)
1338 data_count = current_SC->SCp.this_residual;
1339 if (data_count) {
1340#if EVERY_ACCESS
1341 printk( "%d IN, ", data_count );
1342#endif
1343 if (data_count == 1) {
1344 *current_SC->SCp.ptr++ = inb(port_base + Read_FIFO);
1345 --current_SC->SCp.this_residual;
1346 } else {
1347 data_count >>= 1;
1348 insw(port_base + Read_FIFO, current_SC->SCp.ptr, data_count);
1349 current_SC->SCp.ptr += 2 * data_count;
1350 current_SC->SCp.this_residual -= 2 * data_count;
1351 }
1352 }
1353 if (!current_SC->SCp.this_residual
1354 && current_SC->SCp.buffers_residual) {
1355 --current_SC->SCp.buffers_residual;
1356 ++current_SC->SCp.buffer;
1357 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1358 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1359 }
1360 }
1361 }
1362
1363 if (done) {
1364#if EVERY_ACCESS
1365 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1366#endif
1367
1368#if ERRORS_ONLY
1369 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1370 char *buf = scsi_sglist(current_SC);
1371 if ((unsigned char)(*(buf + 2)) & 0x0f) {
1372 unsigned char key;
1373 unsigned char code;
1374 unsigned char qualifier;
1375
1376 key = (unsigned char)(*(buf + 2)) & 0x0f;
1377 code = (unsigned char)(*(buf + 12));
1378 qualifier = (unsigned char)(*(buf + 13));
1379
1380 if (key != UNIT_ATTENTION
1381 && !(key == NOT_READY
1382 && code == 0x04
1383 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1384 && !(key == ILLEGAL_REQUEST && (code == 0x25
1385 || code == 0x24
1386 || !code)))
1387
1388 printk( "scsi: <fdomain> REQUEST SENSE"
1389 " Key = %x, Code = %x, Qualifier = %x\n",
1390 key, code, qualifier );
1391 }
1392 }
1393#endif
1394#if EVERY_ACCESS
1395 printk( "BEFORE MY_DONE. . ." );
1396#endif
1397 spin_lock_irqsave(current_SC->device->host->host_lock, flags);
1398 my_done( (current_SC->SCp.Status & 0xff)
1399 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1400 spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
1401#if EVERY_ACCESS
1402 printk( "RETURNING.\n" );
1403#endif
1404
1405 } else {
1406 if (current_SC->SCp.phase & disconnect) {
1407 outb(0xd0 | FIFO_COUNT, port_base + Interrupt_Cntl);
1408 outb(0x00, port_base + SCSI_Cntl);
1409 } else {
1410 outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
1411 }
1412 }
1413#if DEBUG_RACE
1414 in_interrupt_flag = 0;
1415#endif
1416 return IRQ_HANDLED;
1417}
1418
1419static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
1420 void (*done)(struct scsi_cmnd *))
1421{
1422 if (in_command) {
1423 panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
1424 }
1425#if EVERY_ACCESS
1426 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1427 SCpnt->target,
1428 *(unsigned char *)SCpnt->cmnd,
1429 scsi_sg_count(SCpnt),
1430 scsi_bufflen(SCpnt));
1431#endif
1432
1433 fdomain_make_bus_idle();
1434
1435 current_SC = SCpnt;
1436 current_SC->scsi_done = done;
1437
1438
1439
1440 if (scsi_sg_count(current_SC)) {
1441 current_SC->SCp.buffer = scsi_sglist(current_SC);
1442 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1443 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1444 current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
1445 } else {
1446 current_SC->SCp.ptr = 0;
1447 current_SC->SCp.this_residual = 0;
1448 current_SC->SCp.buffer = NULL;
1449 current_SC->SCp.buffers_residual = 0;
1450 }
1451
1452 current_SC->SCp.Status = 0;
1453 current_SC->SCp.Message = 0;
1454 current_SC->SCp.have_data_in = 0;
1455 current_SC->SCp.sent_command = 0;
1456 current_SC->SCp.phase = in_arbitration;
1457
1458
1459 outb(0x00, port_base + Interrupt_Cntl);
1460 outb(0x00, port_base + SCSI_Cntl);
1461 outb(adapter_mask, port_base + SCSI_Data_NoACK);
1462 ++in_command;
1463 outb(0x20, port_base + Interrupt_Cntl);
1464 outb(0x14 | PARITY_MASK, port_base + TMC_Cntl);
1465
1466 return 0;
1467}
1468
1469#if DEBUG_ABORT
1470static void print_info(struct scsi_cmnd *SCpnt)
1471{
1472 unsigned int imr;
1473 unsigned int irr;
1474 unsigned int isr;
1475
1476 if (!SCpnt || !SCpnt->device || !SCpnt->device->host) {
1477 printk(KERN_WARNING "scsi: <fdomain> Cannot provide detailed information\n");
1478 return;
1479 }
1480
1481 printk(KERN_INFO "%s\n", fdomain_16x0_info( SCpnt->device->host ) );
1482 print_banner(SCpnt->device->host);
1483 switch (SCpnt->SCp.phase) {
1484 case in_arbitration: printk("arbitration"); break;
1485 case in_selection: printk("selection"); break;
1486 case in_other: printk("other"); break;
1487 default: printk("unknown"); break;
1488 }
1489
1490 printk( " (%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1491 SCpnt->SCp.phase,
1492 SCpnt->device->id,
1493 *(unsigned char *)SCpnt->cmnd,
1494 scsi_sg_count(SCpnt),
1495 scsi_bufflen(SCpnt));
1496 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1497 SCpnt->SCp.sent_command,
1498 SCpnt->SCp.have_data_in,
1499 SCpnt->timeout );
1500#if DEBUG_RACE
1501 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1502#endif
1503
1504 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1505 outb( 0x0a, 0xa0 );
1506 irr = inb( 0xa0 ) << 8;
1507 outb( 0x0a, 0x20 );
1508 irr += inb( 0x20 );
1509 outb( 0x0b, 0xa0 );
1510 isr = inb( 0xa0 ) << 8;
1511 outb( 0x0b, 0x20 );
1512 isr += inb( 0x20 );
1513
1514
1515 printk( "IMR = 0x%04x", imr );
1516 if (imr & (1 << interrupt_level))
1517 printk( " (masked)" );
1518 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1519
1520 printk( "SCSI Status = 0x%02x\n", inb(port_base + SCSI_Status));
1521 printk( "TMC Status = 0x%02x", inb(port_base + TMC_Status));
1522 if (inb((port_base + TMC_Status) & 1))
1523 printk( " (interrupt)" );
1524 printk( "\n" );
1525 printk("Interrupt Status = 0x%02x", inb(port_base + Interrupt_Status));
1526 if (inb(port_base + Interrupt_Status) & 0x08)
1527 printk( " (enabled)" );
1528 printk( "\n" );
1529 if (chip == tmc18c50 || chip == tmc18c30) {
1530 printk("FIFO Status = 0x%02x\n", inb(port_base + FIFO_Status));
1531 printk( "Int. Condition = 0x%02x\n",
1532 inb( port_base + Interrupt_Cond ) );
1533 }
1534 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1535 if (chip == tmc18c50 || chip == tmc18c30)
1536 printk( "Configuration 2 = 0x%02x\n",
1537 inb( port_base + Configuration2 ) );
1538}
1539#endif
1540
1541static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
1542{
1543#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1544 printk( "scsi: <fdomain> abort " );
1545#endif
1546
1547 if (!in_command) {
1548#if EVERY_ACCESS || ERRORS_ONLY
1549 printk( " (not in command)\n" );
1550#endif
1551 return FAILED;
1552 } else printk( "\n" );
1553
1554#if DEBUG_ABORT
1555 print_info( SCpnt );
1556#endif
1557
1558 fdomain_make_bus_idle();
1559 current_SC->SCp.phase |= aborted;
1560 current_SC->result = DID_ABORT << 16;
1561
1562
1563 my_done(DID_ABORT << 16);
1564 return SUCCESS;
1565}
1566
1567int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
1568{
1569 unsigned long flags;
1570
1571 local_irq_save(flags);
1572
1573 outb(1, port_base + SCSI_Cntl);
1574 do_pause( 2 );
1575 outb(0, port_base + SCSI_Cntl);
1576 do_pause( 115 );
1577 outb(0, port_base + SCSI_Mode_Cntl);
1578 outb(PARITY_MASK, port_base + TMC_Cntl);
1579
1580 local_irq_restore(flags);
1581 return SUCCESS;
1582}
1583
1584static int fdomain_16x0_biosparam(struct scsi_device *sdev,
1585 struct block_device *bdev,
1586 sector_t capacity, int *info_array)
1587{
1588 int drive;
1589 int size = capacity;
1590 unsigned long offset;
1591 struct drive_info {
1592 unsigned short cylinders;
1593 unsigned char heads;
1594 unsigned char sectors;
1595 } i;
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640 if (MAJOR(bdev->bd_dev) != SCSI_DISK0_MAJOR) {
1641 printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
1642 return 0;
1643 }
1644 drive = MINOR(bdev->bd_dev) >> 4;
1645
1646 if (bios_major == 2) {
1647 switch (Quantum) {
1648 case 2:
1649
1650
1651 offset = 0x1f33 + drive * 25;
1652 break;
1653 case 3:
1654 offset = 0x1f36 + drive * 15;
1655 break;
1656 case 4:
1657 offset = 0x1f34 + drive * 15;
1658 break;
1659 default:
1660 offset = 0x1f31 + drive * 25;
1661 break;
1662 }
1663 memcpy_fromio( &i, bios_mem + offset, sizeof( struct drive_info ) );
1664 info_array[0] = i.heads;
1665 info_array[1] = i.sectors;
1666 info_array[2] = i.cylinders;
1667 } else if (bios_major == 3
1668 && bios_minor >= 0
1669 && bios_minor < 4) {
1670 memcpy_fromio( &i, bios_mem + 0x1f71 + drive * 10,
1671 sizeof( struct drive_info ) );
1672 info_array[0] = i.heads + 1;
1673 info_array[1] = i.sectors;
1674 info_array[2] = i.cylinders;
1675 } else {
1676
1677 unsigned char *p = scsi_bios_ptable(bdev);
1678
1679 if (p && p[65] == 0xaa && p[64] == 0x55
1680 && p[4]) {
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711 info_array[0] = p[5] + 1;
1712 info_array[1] = p[6] & 0x3f;
1713 } else {
1714
1715
1716
1717
1718
1719 if ((unsigned int)size >= 0x7e0000U) {
1720 info_array[0] = 0xff;
1721 info_array[1] = 0x3f;
1722 } else if ((unsigned int)size >= 0x200000U) {
1723 info_array[0] = 0x80;
1724 info_array[1] = 0x3f;
1725 } else {
1726 info_array[0] = 0x40;
1727 info_array[1] = 0x20;
1728 }
1729 }
1730
1731 info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
1732 kfree(p);
1733 }
1734
1735 return 0;
1736}
1737
1738static int fdomain_16x0_release(struct Scsi_Host *shpnt)
1739{
1740 if (shpnt->irq)
1741 free_irq(shpnt->irq, shpnt);
1742 if (shpnt->io_port && shpnt->n_io_port)
1743 release_region(shpnt->io_port, shpnt->n_io_port);
1744 if (PCI_bus)
1745 pci_dev_put(PCI_dev);
1746 return 0;
1747}
1748
1749struct scsi_host_template fdomain_driver_template = {
1750 .module = THIS_MODULE,
1751 .name = "fdomain",
1752 .proc_name = "fdomain",
1753 .detect = fdomain_16x0_detect,
1754 .info = fdomain_16x0_info,
1755 .queuecommand = fdomain_16x0_queue,
1756 .eh_abort_handler = fdomain_16x0_abort,
1757 .eh_bus_reset_handler = fdomain_16x0_bus_reset,
1758 .bios_param = fdomain_16x0_biosparam,
1759 .release = fdomain_16x0_release,
1760 .can_queue = 1,
1761 .this_id = 6,
1762 .sg_tablesize = 64,
1763 .cmd_per_lun = 1,
1764 .use_clustering = DISABLE_CLUSTERING,
1765};
1766
1767#ifndef PCMCIA
1768#ifdef CONFIG_PCI
1769
1770static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
1771 { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
1772 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
1773 { }
1774};
1775MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl);
1776#endif
1777#define driver_template fdomain_driver_template
1778#include "scsi_module.c"
1779
1780#endif
1781