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