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