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