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