This source file includes following definitions.
- do_pause
- fdomain_make_bus_idle
- fdomain_is_valid_port
- fdomain_test_loopback
- fdomain_16x0_detect
- fdomain_16x0_info
- fdomain_arbitrate
- fdomain_select
- my_done
- fdomain_16x0_intr
- fdomain_16x0_queue
- internal_done
- fdomain_16x0_command
- print_info
- fdomain_16x0_abort
- fdomain_16x0_reset
- fdomain_16x0_biosparam
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 #include <linux/sched.h>
137 #include <asm/io.h>
138 #include "../block/blk.h"
139 #include "scsi.h"
140 #include "hosts.h"
141 #include "fdomain.h"
142 #include <asm/system.h>
143 #include <linux/errno.h>
144 #include <linux/string.h>
145 #include <linux/ioport.h>
146
147 #define VERSION "$Revision: 5.9 $"
148
149
150
151 #define DEBUG 1
152 #define ENABLE_PARITY 1
153 #define FIFO_COUNT 2
154 #define DO_DETECT 0
155
156
157
158 #if DEBUG
159 #define EVERY_ACCESS 0
160 #define ERRORS_ONLY 1
161 #define DEBUG_DETECT 0
162 #define DEBUG_MESSAGES 1
163 #define DEBUG_ABORT 1
164 #define DEBUG_RESET 1
165 #define DEBUG_RACE 1
166 #else
167 #define EVERY_ACCESS 0
168 #define ERRORS_ONLY 0
169 #define DEBUG_DETECT 0
170 #define DEBUG_MESSAGES 0
171 #define DEBUG_ABORT 0
172 #define DEBUG_RESET 0
173 #define DEBUG_RACE 0
174 #endif
175
176
177 #if EVERY_ACCESS
178 #undef ERRORS_ONLY
179 #define ERRORS_ONLY 0
180 #endif
181
182 #if ENABLE_PARITY
183 #define PARITY_MASK 0x08
184 #else
185 #define PARITY_MASK 0x00
186 #endif
187
188 enum chip_type {
189 unknown = 0x00,
190 tmc1800 = 0x01,
191 tmc18c50 = 0x02,
192 };
193
194 enum {
195 in_arbitration = 0x02,
196 in_selection = 0x04,
197 in_other = 0x08,
198 disconnect = 0x10,
199 aborted = 0x20,
200 sent_ident = 0x40,
201 };
202
203 enum in_port_type {
204 Read_SCSI_Data = 0,
205 SCSI_Status = 1,
206 TMC_Status = 2,
207 FIFO_Status = 3,
208 Interrupt_Cond = 4,
209 LSB_ID_Code = 5,
210 MSB_ID_Code = 6,
211 Read_Loopback = 7,
212 SCSI_Data_NoACK = 8,
213 Interrupt_Status = 9,
214 Configuration1 = 10,
215 Configuration2 = 11,
216 Read_FIFO = 12,
217 FIFO_Data_Count = 14
218 };
219
220 enum out_port_type {
221 Write_SCSI_Data = 0,
222 SCSI_Cntl = 1,
223 Interrupt_Cntl = 2,
224 SCSI_Mode_Cntl = 3,
225 TMC_Cntl = 4,
226 Memory_Cntl = 5,
227 Write_Loopback = 7,
228 Write_FIFO = 12
229 };
230
231 static int port_base = 0;
232 static void *bios_base = NULL;
233 static int bios_major = 0;
234 static int bios_minor = 0;
235 static int interrupt_level = 0;
236 static int this_host = 0;
237 static volatile int in_command = 0;
238 static Scsi_Cmnd *current_SC = NULL;
239 static enum chip_type chip = unknown;
240 static int adapter_mask = 0x40;
241 #if DEBUG_RACE
242 static volatile int in_interrupt_flag = 0;
243 #endif
244
245 static int SCSI_Mode_Cntl_port;
246 static int FIFO_Data_Count_port;
247 static int Interrupt_Cntl_port;
248 static int Interrupt_Status_port;
249 static int Read_FIFO_port;
250 static int Read_SCSI_Data_port;
251 static int SCSI_Cntl_port;
252 static int SCSI_Data_NoACK_port;
253 static int SCSI_Status_port;
254 static int TMC_Cntl_port;
255 static int TMC_Status_port;
256 static int Write_FIFO_port;
257 static int Write_SCSI_Data_port;
258
259 extern void fdomain_16x0_intr( int unused );
260
261 static void *addresses[] = {
262 (void *)0xc8000,
263 (void *)0xca000,
264 (void *)0xce000,
265 (void *)0xde000 };
266 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
267
268 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
269 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
270
271 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 struct signature {
299 char *signature;
300 int sig_offset;
301 int sig_length;
302 int major_bios_version;
303 int minor_bios_version;
304 } signatures[] = {
305
306
307 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0 },
308 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0 },
309 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0 },
310 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2 },
311 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1 },
312
313
314
315
316
317
318
319
320
321
322
323
324 };
325
326 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
327
328 static void print_banner( void )
329 {
330 printk( "%s", fdomain_16x0_info() );
331 printk( "Future Domain: BIOS version %d.%d, %s\n",
332 bios_major, bios_minor,
333 chip == tmc1800 ? "TMC-1800"
334 : (chip == tmc18c50 ? "TMC-18C50" : "Unknown") );
335
336 if (interrupt_level) {
337 printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
338 (unsigned)bios_base, port_base, interrupt_level );
339 } else {
340 printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
341 (unsigned)bios_base, port_base );
342 }
343 }
344
345 static void do_pause( unsigned amount )
346 {
347 unsigned long the_time = jiffies + amount;
348
349 while (jiffies < the_time);
350 }
351
352 inline static void fdomain_make_bus_idle( void )
353 {
354 outb( 0, SCSI_Cntl_port );
355 outb( 0, SCSI_Mode_Cntl_port );
356 if (chip == tmc18c50)
357 outb( 0x21 | PARITY_MASK, TMC_Cntl_port );
358 else
359 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
360 }
361
362 static int fdomain_is_valid_port( int port )
363 {
364 int options;
365
366 #if DEBUG_DETECT
367 printk( " (%x%x),",
368 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
369 #endif
370
371
372
373
374
375
376
377 if (inb( port + LSB_ID_Code ) != 0xe9) {
378 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
379 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
380 chip = tmc1800;
381 } else {
382 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
383 chip = tmc18c50;
384 }
385
386
387
388
389
390
391
392 options = inb( port + Configuration1 );
393
394 #if DEBUG_DETECT
395 printk( " Options = %x\n", options );
396 #endif
397
398
399 if (addresses[ (options & 0xc0) >> 6 ] != bios_base)
400 return 0;
401 interrupt_level = ints[ (options & 0x0e) >> 1 ];
402
403 return 1;
404 }
405
406 static int fdomain_test_loopback( void )
407 {
408 int i;
409 int result;
410
411 for (i = 0; i < 255; i++) {
412 outb( i, port_base + Write_Loopback );
413 result = inb( port_base + Read_Loopback );
414 if (i != result)
415 return 1;
416 }
417 return 0;
418 }
419
420 int fdomain_16x0_detect( int hostnum )
421 {
422 int i, j;
423 int flag = 0;
424 struct sigaction sa;
425 int retcode;
426 #if DO_DETECT
427 const int buflen = 255;
428 Scsi_Cmnd SCinit;
429 unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
430 unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
431 unsigned char do_read_capacity[] = { READ_CAPACITY,
432 0, 0, 0, 0, 0, 0, 0, 0, 0 };
433 unsigned char buf[buflen];
434 #endif
435
436 #if DEBUG_DETECT
437 printk( "fdomain_16x0_detect()," );
438 #endif
439
440 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
441 #if DEBUG_DETECT
442 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
443 #endif
444 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
445 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
446 signatures[j].signature, signatures[j].sig_length )) {
447 bios_major = signatures[j].major_bios_version;
448 bios_minor = signatures[j].minor_bios_version;
449 bios_base = addresses[i];
450 }
451 }
452 }
453
454 if (!bios_base) {
455 #if DEBUG_DETECT
456 printk( " FAILED: NO BIOS\n" );
457 #endif
458 return 0;
459 }
460
461 if (bios_major == 2) {
462
463
464
465
466
467
468
469
470 port_base = *((char *)bios_base + 0x1fcc)
471 + (*((char *)bios_base + 0x1fcd) << 8);
472
473 #if DEBUG_DETECT
474 printk( " %x,", port_base );
475 #endif
476
477 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
478 if (port_base == ports[i])
479 ++flag;
480 }
481
482 if (flag)
483 flag = fdomain_is_valid_port( port_base );
484 }
485
486 if (!flag) {
487
488
489
490
491
492
493
494 #if DEBUG_DETECT
495 if (bios_major != 2) printk( " RAM FAILED, " );
496 #endif
497
498
499
500
501
502
503
504
505
506
507
508
509 for (i = 0; !flag && i < PORT_COUNT; i++) {
510 port_base = ports[i];
511 if (check_region( port_base, 0x10 )) {
512 #if DEBUG_DETECT
513 printf( " (%x inuse),", port_base );
514 #endif
515 continue;
516 }
517 #if DEBUG_DETECT
518 printk( " %x,", port_base );
519 #endif
520 flag = fdomain_is_valid_port( port_base );
521 }
522 }
523
524 if (!flag) {
525 #if DEBUG_DETECT
526 printk( " FAILED: NO PORT\n" );
527 #endif
528 return 0;
529 }
530
531 print_banner();
532
533 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
534 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
535 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
536 Interrupt_Status_port = port_base + Interrupt_Status;
537 Read_FIFO_port = port_base + Read_FIFO;
538 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
539 SCSI_Cntl_port = port_base + SCSI_Cntl;
540 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
541 SCSI_Status_port = port_base + SCSI_Status;
542 TMC_Cntl_port = port_base + TMC_Cntl;
543 TMC_Status_port = port_base + TMC_Status;
544 Write_FIFO_port = port_base + Write_FIFO;
545 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
546
547 fdomain_16x0_reset( NULL );
548
549 if (fdomain_test_loopback()) {
550 #if DEBUG_DETECT
551 printk( "Future Domain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
552 #endif
553 return 0;
554 }
555
556 this_host = hostnum;
557
558
559
560 if (!interrupt_level) {
561 panic( "Future Domain: *NO* interrupt level selected!\n" );
562 } else {
563
564
565 sa.sa_handler = fdomain_16x0_intr;
566 sa.sa_flags = SA_INTERRUPT;
567 sa.sa_mask = 0;
568 sa.sa_restorer = NULL;
569
570 retcode = irqaction( interrupt_level, &sa );
571
572 if (retcode < 0) {
573 if (retcode == -EINVAL) {
574 printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
575 printk( " This shouldn't happen!\n" );
576 printk( " Send mail to faith@cs.unc.edu\n" );
577 } else if (retcode == -EBUSY) {
578 printk( "Future Domain: IRQ %d is already in use!\n",
579 interrupt_level );
580 printk( " Please use another IRQ!\n" );
581 } else {
582 printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
583 printk( " This shouldn't happen!\n" );
584 printk( " Send mail to faith@cs.unc.edu\n" );
585 }
586 panic( "Future Domain: Driver requires interruptions\n" );
587 } else {
588 printk( "Future Domain: IRQ %d requested from kernel\n",
589 interrupt_level );
590 }
591 }
592
593
594
595 snarf_region( port_base, 0x10 );
596
597 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
598 adapter_mask = 0x80;
599 scsi_hosts[this_host].this_id = 7;
600 }
601
602 #if DO_DETECT
603
604
605
606
607
608
609
610
611 SCinit.request_buffer = SCinit.buffer = buf;
612 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
613 SCinit.use_sg = 0;
614 SCinit.lun = 0;
615
616 printk( "Future Domain detection routine scanning for devices:\n" );
617 for (i = 0; i < 8; i++) {
618 SCinit.target = i;
619 if (i == scsi_hosts[this_host].this_id)
620 continue;
621 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
622 retcode = fdomain_16x0_command(&SCinit);
623 if (!retcode) {
624 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
625 retcode = fdomain_16x0_command(&SCinit);
626 if (!retcode) {
627 printk( " SCSI ID %d: ", i );
628 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
629 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
630 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
631 retcode = fdomain_16x0_command(&SCinit);
632 if (!retcode) {
633 unsigned long blocks, size, capacity;
634
635 blocks = (buf[0] << 24) | (buf[1] << 16)
636 | (buf[2] << 8) | buf[3];
637 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
638 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
639
640 printk( "%lu MB (%lu byte blocks)",
641 ((capacity + 5L) / 10L), size );
642 } else {
643 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
644 retcode = fdomain_16x0_command(&SCinit);
645 }
646 printk ("\n" );
647 } else {
648 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
649 retcode = fdomain_16x0_command(&SCinit);
650 }
651 }
652 }
653 #endif
654
655 return 1;
656 }
657
658 const char *fdomain_16x0_info(void)
659 {
660 static char buffer[80];
661 char *pt;
662
663 strcpy( buffer, "Future Domain: TMC-16x0 SCSI driver, version" );
664 if (strchr( VERSION, ':')) {
665 strcat( buffer, strchr( VERSION, ':' ) + 1 );
666 pt = strrchr( buffer, '$') - 1;
667 if (!pt)
668 pt = buffer + strlen( buffer ) - 1;
669 if (*pt != ' ')
670 ++pt;
671 *pt++ = '\n';
672 *pt = '\0';
673 } else {
674 strcat( buffer, " " VERSION "\n" );
675 }
676
677 return buffer;
678 }
679
680 #if 0
681 static int fdomain_arbitrate( void )
682 {
683 int status = 0;
684 unsigned long timeout;
685
686 #if EVERY_ACCESS
687 printk( "fdomain_arbitrate()\n" );
688 #endif
689
690 outb( 0x00, SCSI_Cntl_port );
691 outb( adapter_mask, port_base + SCSI_Data_NoACK );
692 outb( 0x04 | PARITY_MASK, TMC_Cntl_port );
693
694 timeout = jiffies + 50;
695 while (jiffies < timeout) {
696 status = inb( TMC_Status_port );
697 if (status & 0x02)
698 return 0;
699 }
700
701
702 fdomain_make_bus_idle();
703
704 #if EVERY_ACCESS
705 printk( "Arbitration failed, status = %x\n", status );
706 #endif
707 #if ERRORS_ONLY
708 printk( "Future Domain: Arbitration failed, status = %x", status );
709 #endif
710 return 1;
711 }
712 #endif
713
714 static int fdomain_select( int target )
715 {
716 int status;
717 unsigned long timeout;
718
719
720 outb( 0x82, SCSI_Cntl_port );
721 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
722
723
724 outb( PARITY_MASK, TMC_Cntl_port );
725
726 timeout = jiffies + 25;
727 while (jiffies < timeout) {
728 status = inb( SCSI_Status_port );
729 if (status & 1) {
730
731 outb( 0x80, SCSI_Cntl_port );
732 return 0;
733 }
734 }
735
736 fdomain_make_bus_idle();
737 #if EVERY_ACCESS
738 if (!target) printk( "Selection failed\n" );
739 #endif
740 #if ERRORS_ONLY
741 if (!target) printk( "Future Domain: Selection failed" );
742 #endif
743 return 1;
744 }
745
746 void my_done( int error )
747 {
748 if (in_command) {
749 in_command = 0;
750 outb( 0x00, Interrupt_Cntl_port );
751 fdomain_make_bus_idle();
752 current_SC->result = error;
753 if (current_SC->scsi_done)
754 current_SC->scsi_done( current_SC );
755 else panic( "Future Domain: current_SC->scsi_done() == NULL" );
756 } else {
757 panic( "Future Domain: my_done() called outside of command\n" );
758 }
759 #if DEBUG_RACE
760 in_interrupt_flag = 0;
761 #endif
762 }
763
764 void fdomain_16x0_intr( int unused )
765 {
766 int status;
767 int done = 0;
768 unsigned data_count;
769
770 sti();
771
772 outb( 0x00, Interrupt_Cntl_port );
773
774
775 if (!in_command || !current_SC) {
776 #if EVERY_ACCESS
777 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
778 in_command, current_SC );
779 #endif
780 return;
781 }
782
783
784 if (current_SC->SCp.phase & aborted) {
785 #if DEBUG_ABORT
786 printk( "Interrupt after abort, ignoring\n" );
787 #endif
788
789
790 }
791
792 #if DEBUG_RACE
793 ++in_interrupt_flag;
794 #endif
795
796 if (current_SC->SCp.phase & in_arbitration) {
797 status = inb( TMC_Status_port );
798 if (!(status & 0x02)) {
799 #if EVERY_ACCESS
800 printk( " AFAIL " );
801 #endif
802 my_done( DID_BUS_BUSY << 16 );
803 return;
804 }
805 current_SC->SCp.phase = in_selection;
806
807 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
808
809 outb( 0x82, SCSI_Cntl_port );
810 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
811
812
813 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
814 #if DEBUG_RACE
815 in_interrupt_flag = 0;
816 #endif
817 return;
818 } else if (current_SC->SCp.phase & in_selection) {
819 status = inb( SCSI_Status_port );
820 if (!(status & 0x01)) {
821
822 if (fdomain_select( current_SC->target )) {
823 #if EVERY_ACCESS
824 printk( " SFAIL " );
825 #endif
826 my_done( DID_NO_CONNECT << 16 );
827 return;
828 } else {
829 #if EVERY_ACCESS
830 printk( " AltSel " );
831 #endif
832
833 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
834 }
835 }
836 current_SC->SCp.phase = in_other;
837 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
838 outb( 0x80, SCSI_Cntl_port );
839 #if DEBUG_RACE
840 in_interrupt_flag = 0;
841 #endif
842 return;
843 }
844
845
846
847 status = inb( SCSI_Status_port );
848
849 if (status & 0x10) {
850
851 switch (status & 0x0e) {
852
853 case 0x08:
854 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
855 Write_SCSI_Data_port );
856 #if EVERY_ACCESS
857 printk( "CMD = %x,",
858 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
859 #endif
860 break;
861 case 0x00:
862 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
863 current_SC->SCp.have_data_in = -1;
864 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
865 }
866 break;
867 case 0x04:
868 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
869 current_SC->SCp.have_data_in = 1;
870 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
871 }
872 break;
873 case 0x0c:
874 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
875 #if EVERY_ACCESS
876 printk( "Status = %x, ", current_SC->SCp.Status );
877 #endif
878 #if ERRORS_ONLY
879 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
880 printk( "Future Domain: target = %d, command = %x, "
881 "Status = %x\n",
882 current_SC->target, current_SC->cmnd[0],
883 current_SC->SCp.Status );
884 }
885 #endif
886 break;
887 case 0x0a:
888 outb( MESSAGE_REJECT, Write_SCSI_Data_port );
889 break;
890 case 0x0e:
891 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
892 #if EVERY_ACCESS
893 printk( "Message = %x, ", current_SC->SCp.Message );
894 #endif
895 if (!current_SC->SCp.Message) ++done;
896 #if DEBUG_MESSAGES || EVERY_ACCESS
897 if (current_SC->SCp.Message) {
898 printk( "Future Domain: Message = %x\n",
899 current_SC->SCp.Message );
900 }
901 #endif
902 break;
903 }
904 }
905
906 if (chip == tmc1800
907 && !current_SC->SCp.have_data_in
908 && (current_SC->SCp.sent_command
909 >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) {
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 switch (current_SC->cmnd[0]) {
1037 case CHANGE_DEFINITION: case COMPARE: case COPY:
1038 case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
1039 case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
1040
1041 case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
1042 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
1043 case WRITE_6: case WRITE_10: case WRITE_VERIFY:
1044 case 0x3f: case 0x41:
1045
1046 case 0xb1: case 0xb0: case 0xb2:
1047 case 0xaa: case 0xae:
1048
1049 case 0x24:
1050
1051 case 0x38: case 0x3d:
1052
1053 case 0xb6:
1054
1055 case 0xea:
1056
1057 current_SC->SCp.have_data_in = -1;
1058 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1059 break;
1060
1061 case 0x00:
1062 default:
1063
1064 current_SC->SCp.have_data_in = 1;
1065 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1066 break;
1067 }
1068 }
1069
1070 if (current_SC->SCp.have_data_in == -1) {
1071 while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
1072 #if EVERY_ACCESS
1073 printk( "DC=%d, ", data_count ) ;
1074 #endif
1075 if (data_count > current_SC->SCp.this_residual)
1076 data_count = current_SC->SCp.this_residual;
1077 if (data_count > 0) {
1078 #if EVERY_ACCESS
1079 printk( "%d OUT, ", data_count );
1080 #endif
1081 if (data_count == 1) {
1082 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1083 --current_SC->SCp.this_residual;
1084 } else {
1085 data_count >>= 1;
1086 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1087 current_SC->SCp.ptr += 2 * data_count;
1088 current_SC->SCp.this_residual -= 2 * data_count;
1089 }
1090 }
1091 if (!current_SC->SCp.this_residual) {
1092 if (current_SC->SCp.buffers_residual) {
1093 --current_SC->SCp.buffers_residual;
1094 ++current_SC->SCp.buffer;
1095 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1096 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1097 } else
1098 break;
1099 }
1100 }
1101 }
1102
1103 if (current_SC->SCp.have_data_in == 1) {
1104 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
1105 #if EVERY_ACCESS
1106 printk( "DC=%d, ", data_count );
1107 #endif
1108 if (data_count > current_SC->SCp.this_residual)
1109 data_count = current_SC->SCp.this_residual;
1110 if (data_count) {
1111 #if EVERY_ACCESS
1112 printk( "%d IN, ", data_count );
1113 #endif
1114 if (data_count == 1) {
1115 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1116 --current_SC->SCp.this_residual;
1117 } else {
1118 data_count >>= 1;
1119 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1120 current_SC->SCp.ptr += 2 * data_count;
1121 current_SC->SCp.this_residual -= 2 * data_count;
1122 }
1123 }
1124 if (!current_SC->SCp.this_residual
1125 && current_SC->SCp.buffers_residual) {
1126 --current_SC->SCp.buffers_residual;
1127 ++current_SC->SCp.buffer;
1128 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1129 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1130 }
1131 }
1132 }
1133
1134 if (done) {
1135 #if EVERY_ACCESS
1136 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1137 #endif
1138
1139 #if ERRORS_ONLY
1140 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1141 if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
1142 unsigned char key;
1143 unsigned char code;
1144 unsigned char qualifier;
1145
1146 key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
1147 & 0x0f;
1148 code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
1149 qualifier = (unsigned char)(*((char *)current_SC->request_buffer
1150 + 13));
1151
1152 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1153 && !(key == NOT_READY
1154 && code == 0x04
1155 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1156 && !(key == ILLEGAL_REQUEST && (code == 0x25
1157 || code == 0x24
1158 || !code)))
1159
1160 printk( "Future Domain: REQUEST SENSE "
1161 "Key = %x, Code = %x, Qualifier = %x\n",
1162 key, code, qualifier );
1163 }
1164 }
1165 #endif
1166 #if EVERY_ACCESS
1167 printk( "BEFORE MY_DONE. . ." );
1168 #endif
1169 my_done( (current_SC->SCp.Status & 0xff)
1170 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1171 #if EVERY_ACCESS
1172 printk( "RETURNING.\n" );
1173 #endif
1174
1175 } else {
1176 if (current_SC->SCp.phase & disconnect) {
1177 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1178 outb( 0x00, SCSI_Cntl_port );
1179 } else {
1180 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1181 }
1182 }
1183 #if DEBUG_RACE
1184 in_interrupt_flag = 0;
1185 #endif
1186 return;
1187 }
1188
1189 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
1190 {
1191 if (in_command) {
1192 panic( "Future Domain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1193 }
1194 #if EVERY_ACCESS
1195 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1196 SCpnt->target,
1197 *(unsigned char *)SCpnt->cmnd,
1198 SCpnt->use_sg,
1199 SCpnt->request_bufflen );
1200 #endif
1201
1202 fdomain_make_bus_idle();
1203
1204 current_SC = SCpnt;
1205 current_SC->scsi_done = done;
1206
1207
1208
1209 if (current_SC->use_sg) {
1210 current_SC->SCp.buffer =
1211 (struct scatterlist *)current_SC->request_buffer;
1212 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1213 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1214 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1215 } else {
1216 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1217 current_SC->SCp.this_residual = current_SC->request_bufflen;
1218 current_SC->SCp.buffer = NULL;
1219 current_SC->SCp.buffers_residual = 0;
1220 }
1221
1222
1223 current_SC->SCp.Status = 0;
1224 current_SC->SCp.Message = 0;
1225 current_SC->SCp.have_data_in = 0;
1226 current_SC->SCp.sent_command = 0;
1227 current_SC->SCp.phase = in_arbitration;
1228
1229
1230 outb( 0x00, Interrupt_Cntl_port );
1231 outb( 0x00, SCSI_Cntl_port );
1232 outb( adapter_mask, SCSI_Data_NoACK_port );
1233 ++in_command;
1234 outb( 0x20, Interrupt_Cntl_port );
1235 outb( 0x14 | PARITY_MASK, TMC_Cntl_port );
1236
1237 return 0;
1238 }
1239
1240
1241
1242
1243
1244 static volatile int internal_done_flag = 0;
1245 static volatile int internal_done_errcode = 0;
1246
1247 static void internal_done( Scsi_Cmnd *SCpnt )
1248 {
1249 internal_done_errcode = SCpnt->result;
1250 ++internal_done_flag;
1251 }
1252
1253 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
1254 {
1255 fdomain_16x0_queue( SCpnt, internal_done );
1256
1257 while (!internal_done_flag)
1258 ;
1259 internal_done_flag = 0;
1260 return internal_done_errcode;
1261 }
1262
1263
1264
1265 void print_info( Scsi_Cmnd *SCpnt )
1266 {
1267 unsigned int imr;
1268 unsigned int irr;
1269 unsigned int isr;
1270
1271 print_banner();
1272 switch (SCpnt->SCp.phase) {
1273 case in_arbitration: printk( "arbitration " ); break;
1274 case in_selection: printk( "selection " ); break;
1275 case in_other: printk( "other " ); break;
1276 default: printk( "unknown " ); break;
1277 }
1278
1279 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1280 SCpnt->SCp.phase,
1281 SCpnt->target,
1282 *(unsigned char *)SCpnt->cmnd,
1283 SCpnt->use_sg,
1284 SCpnt->request_bufflen );
1285 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1286 SCpnt->SCp.sent_command,
1287 SCpnt->SCp.have_data_in,
1288 SCpnt->timeout );
1289 #if DEBUG_RACE
1290 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1291 #endif
1292
1293 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1294 outb( 0x0a, 0xa0 );
1295 irr = inb( 0xa0 ) << 8;
1296 outb( 0x0a, 0x20 );
1297 irr += inb( 0x20 );
1298 outb( 0x0b, 0xa0 );
1299 isr = inb( 0xa0 ) << 8;
1300 outb( 0x0b, 0x20 );
1301 isr += inb( 0x20 );
1302
1303
1304 printk( "IMR = 0x%04x", imr );
1305 if (imr & (1 << interrupt_level))
1306 printk( " (masked)" );
1307 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1308
1309 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1310 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1311 if (inb( TMC_Status_port & 1))
1312 printk( " (interrupt)" );
1313 printk( "\n" );
1314 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1315 if (inb( Interrupt_Status_port ) & 0x08)
1316 printk( " (enabled)" );
1317 printk( "\n" );
1318 if (chip == tmc18c50) {
1319 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1320 printk( "Int. Condition = 0x%02x\n",
1321 inb( port_base + Interrupt_Cond ) );
1322 }
1323 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1324 if (chip == tmc18c50)
1325 printk( "Configuration 2 = 0x%02x\n",
1326 inb( port_base + Configuration2 ) );
1327 }
1328
1329 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
1330 {
1331
1332 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1333 printk( "Future Domain: Abort " );
1334 #endif
1335
1336 cli();
1337 if (!in_command) {
1338 #if EVERY_ACCESS || ERRORS_ONLY
1339 printk( " (not in command)\n" );
1340 #endif
1341 sti();
1342 return 0;
1343 } else {
1344 #if EVERY_ACCESS || ERRORS_ONLY
1345 printk( " code = %d\n", code );
1346 #endif
1347 }
1348
1349 #if DEBUG_ABORT
1350 print_info( SCpnt );
1351 #endif
1352
1353 fdomain_make_bus_idle();
1354
1355 current_SC->SCp.phase |= aborted;
1356
1357 current_SC->result = code ? code : DID_ABORT;
1358
1359 sti();
1360
1361
1362 my_done( code << 16 );
1363
1364 return 0;
1365 }
1366
1367 int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
1368 {
1369 #if DEBUG_RESET
1370 static int called_once = 0;
1371 #endif
1372
1373 #if ERRORS_ONLY
1374 printk( "Future Domain: SCSI Bus Reset\n" );
1375 #endif
1376
1377 #if DEBUG_RESET
1378 if (called_once) print_info( current_SC );
1379 called_once = 1;
1380 #endif
1381
1382 outb( 1, SCSI_Cntl_port );
1383 do_pause( 2 );
1384 outb( 0, SCSI_Cntl_port );
1385 do_pause( 115 );
1386 outb( 0, SCSI_Mode_Cntl_port );
1387 outb( PARITY_MASK, TMC_Cntl_port );
1388
1389
1390
1391
1392
1393 if (SCpnt)
1394 SCpnt->flags |= NEEDS_JUMPSTART;
1395
1396 return 0;
1397 }
1398
1399 int fdomain_16x0_biosparam( int size, int dev, int *info_array )
1400 {
1401 int drive;
1402 struct drive_info {
1403 unsigned short cylinders;
1404 unsigned char heads;
1405 unsigned char sectors;
1406 } *i;
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 drive = MINOR(dev) / 16;
1441
1442 if (bios_major == 2) {
1443 i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1444 info_array[0] = i->heads;
1445 info_array[1] = i->sectors;
1446 info_array[2] = i->cylinders;
1447 } else if (bios_major == 3) {
1448 i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1449 info_array[0] = i->heads + 1;
1450 info_array[1] = i->sectors;
1451 info_array[2] = i->cylinders;
1452 } else {
1453
1454
1455
1456 i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1457 info_array[0] = i->heads + 1;
1458 info_array[1] = i->sectors;
1459 info_array[2] = i->cylinders;
1460
1461 if (!info_array[0]
1462 || !info_array[1]
1463 || !info_array[2]
1464 || info_array[2] > 1024
1465
1466
1467
1468
1469
1470 ) {
1471
1472 info_array[0]
1473 = info_array[1]
1474 = info_array[2]
1475 = 0;
1476 }
1477 }
1478
1479 return 0;
1480 }