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