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