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