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