* add p cc
[mascara-docs.git] / i386 / linux / linux-0.99 / drivers / scsi / fdomain.c
blob8043f70cf1db766bbd035309fcab19e1d93907ff
1 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
2 * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
3 * Revised: Sun Jan 23 08:59:04 1994 by faith@cs.unc.edu
4 * Author: Rickard E. Faith, faith@cs.unc.edu
5 * Copyright 1992, 1993, 1994 Rickard E. Faith
7 * $Id: fdomain.c,v 5.9 1994/01/23 13:59:14 root Exp $
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 **************************************************************************
21 DESCRIPTION:
23 This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680
24 and TMC-1650/1670 SCSI host adapters. The 1650 and 1670 have a 25-pin
25 external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin
26 high-density external connector. The 1670 and 1680 have floppy disk
27 controllers built in.
29 Future Domain's older boards are based on the TMC-1800 chip, and the
30 driver was originally written for a TMC-1680 board with the TMC-1800
31 chip. More recently, boards are being produced with the TMC-18C50 chip.
32 The latest and greatest board may not work with this driver. If you have
33 to patch this driver so that it will recognize your board's BIOS
34 signature, then the driver may fail to function after the board is
35 detected.
37 If you have a TMC-8xx or TMC-9xx board, then this is not the driver for
38 your board. Please refer to the Seagate driver for more information and
39 possible support.
43 REFERENCES USED:
45 "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation,
46 1990.
48 "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain
49 Corporation, January 1992.
51 "LXT SCSI Products: Specifications and OEM Technical Manual (Revision
52 B/September 1991)", Maxtor Corporation, 1991.
54 "7213S product Manual (Revision P3)", Maxtor Corporation, 1992.
56 "Draft Proposed American National Standard: Small Computer System
57 Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109,
58 revision 10h, October 17, 1991)
60 Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric
61 Youngdale (eric@tantalus.nrl.navy.mil), 1992.
65 NOTES ON REFERENCES:
67 The Maxtor manuals were free. Maxtor telephone technical support is
68 great!
70 The Future Domain manuals were $25 and $35. They document the chip, not
71 the TMC-16x0 boards, so some information I had to guess at. In 1992,
72 Future Domain sold DOS BIOS source for $250 and the UN*X driver source was
73 $750, but these required a non-disclosure agreement, so even if I could
74 have afforded them, they would *not* have been useful for writing this
75 publically distributable driver. Future Domain technical support has
76 provided some information on the phone and have sent a few useful FAXs.
77 They have been much more helpful since they started to recognize that the
78 word "Linux" refers to an operating system :-).
82 ALPHA TESTERS:
84 There are many other alpha testers that come and go as the driver
85 develops. The people listed here were most helpful in times of greatest
86 need (mostly early on -- I've probably left out a few worthy people in
87 more recent times):
89 Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken
90 Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari
91 Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad
92 Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com).
94 Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me
95 his 18C50-based card for debugging. He is the sole reason that this
96 driver works with the 18C50 chip.
98 All of the alpha testers deserve much thanks.
102 NOTES ON USER DEFINABLE OPTIONS:
104 DEBUG: This turns on the printing of various debug informaiton.
106 ENABLE_PARITY: This turns on SCSI parity checking. With the current
107 driver, all attached devices must support SCSI parity. If none of your
108 devices support parity, then you can probably get the driver to work by
109 turning this option off. I have no way of testing this, however.
111 FIFO_COUNT: The host adapter has an 8K cache. When this many 512 byte
112 blocks are filled by the SCSI device, an interrupt will be raised.
113 Therefore, this could be as low as 0, or as high as 16. Note, however,
114 that values which are too high or too low seem to prevent any interrupts
115 from occuring, and thereby lock up the machine. I have found that 2 is a
116 good number, but throughput may be increased by changing this value to
117 values which are close to 2. Please let me know if you try any different
118 values.
120 DO_DETECT: This activates some old scan code which was needed before the
121 high level drivers got fixed. If you are having toruble with the driver,
122 turning this on should not hurt, and might help. Please let me know if
123 this is the case, since this code will be removed from future drivers.
125 RESELECTION: This is no longer an option, since I gave up trying to
126 implement it in version 4.x of this driver. It did not improve
127 performance at all and made the driver unstable (because I never found one
128 of the two race conditions which were introduced by multiple outstanding
129 commands). The instability seems a very high price to pay just so that
130 you don't have to wait for the tape to rewind. When I have time, I will
131 work on this again. In the interim, if anyone want to work on the code, I
132 can give them my latest version.
134 **************************************************************************/
136 #include <linux/sched.h>
137 #include <asm/io.h>
138 #include "../block/blk.h"
139 #include "scsi.h"
140 #include "hosts.h"
141 #include "fdomain.h"
142 #include <asm/system.h>
143 #include <linux/errno.h>
144 #include <linux/string.h>
145 #include <linux/ioport.h>
147 #define VERSION "$Revision: 5.9 $"
149 /* START OF USER DEFINABLE OPTIONS */
151 #define DEBUG 1 /* Enable debugging output */
152 #define ENABLE_PARITY 1 /* Enable SCSI Parity */
153 #define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */
154 #define DO_DETECT 0 /* Do device detection here (see scsi.c) */
156 /* END OF USER DEFINABLE OPTIONS */
158 #if DEBUG
159 #define EVERY_ACCESS 0 /* Write a line on every scsi access */
160 #define ERRORS_ONLY 1 /* Only write a line if there is an error */
161 #define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */
162 #define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
163 #define DEBUG_ABORT 1 /* Debug abort() routine */
164 #define DEBUG_RESET 1 /* Debug reset() routine */
165 #define DEBUG_RACE 1 /* Debug interrupt-driven race condition */
166 #else
167 #define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
168 #define ERRORS_ONLY 0
169 #define DEBUG_DETECT 0
170 #define DEBUG_MESSAGES 0
171 #define DEBUG_ABORT 0
172 #define DEBUG_RESET 0
173 #define DEBUG_RACE 0
174 #endif
176 /* Errors are reported on the line, so we don't need to report them again */
177 #if EVERY_ACCESS
178 #undef ERRORS_ONLY
179 #define ERRORS_ONLY 0
180 #endif
182 #if ENABLE_PARITY
183 #define PARITY_MASK 0x08
184 #else
185 #define PARITY_MASK 0x00
186 #endif
188 enum chip_type {
189 unknown = 0x00,
190 tmc1800 = 0x01,
191 tmc18c50 = 0x02,
194 enum {
195 in_arbitration = 0x02,
196 in_selection = 0x04,
197 in_other = 0x08,
198 disconnect = 0x10,
199 aborted = 0x20,
200 sent_ident = 0x40,
203 enum in_port_type {
204 Read_SCSI_Data = 0,
205 SCSI_Status = 1,
206 TMC_Status = 2,
207 FIFO_Status = 3, /* tmc18c50 only */
208 Interrupt_Cond = 4, /* tmc18c50 only */
209 LSB_ID_Code = 5,
210 MSB_ID_Code = 6,
211 Read_Loopback = 7,
212 SCSI_Data_NoACK = 8,
213 Interrupt_Status = 9,
214 Configuration1 = 10,
215 Configuration2 = 11, /* tmc18c50 only */
216 Read_FIFO = 12,
217 FIFO_Data_Count = 14
220 enum out_port_type {
221 Write_SCSI_Data = 0,
222 SCSI_Cntl = 1,
223 Interrupt_Cntl = 2,
224 SCSI_Mode_Cntl = 3,
225 TMC_Cntl = 4,
226 Memory_Cntl = 5, /* tmc18c50 only */
227 Write_Loopback = 7,
228 Write_FIFO = 12
231 static int port_base = 0;
232 static void *bios_base = NULL;
233 static int bios_major = 0;
234 static int bios_minor = 0;
235 static int interrupt_level = 0;
236 static int this_host = 0;
237 static volatile int in_command = 0;
238 static Scsi_Cmnd *current_SC = NULL;
239 static enum chip_type chip = unknown;
240 static int adapter_mask = 0x40;
241 #if DEBUG_RACE
242 static volatile int in_interrupt_flag = 0;
243 #endif
245 static int SCSI_Mode_Cntl_port;
246 static int FIFO_Data_Count_port;
247 static int Interrupt_Cntl_port;
248 static int Interrupt_Status_port;
249 static int Read_FIFO_port;
250 static int Read_SCSI_Data_port;
251 static int SCSI_Cntl_port;
252 static int SCSI_Data_NoACK_port;
253 static int SCSI_Status_port;
254 static int TMC_Cntl_port;
255 static int TMC_Status_port;
256 static int Write_FIFO_port;
257 static int Write_SCSI_Data_port;
259 extern void fdomain_16x0_intr( int unused );
261 static void *addresses[] = {
262 (void *)0xc8000,
263 (void *)0xca000,
264 (void *)0xce000,
265 (void *)0xde000 };
266 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
268 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
269 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
271 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
275 READ THIS BEFORE YOU ADD A SIGNATURE!
277 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME!
279 READ EVERY WORD, ESPECIALLY THE WORD *NOT*
281 This driver works *ONLY* for Future Domain cards using the TMC-1800 or
282 the TMC-18C50 chip. This includes models TMC-1650, 1660, 1670, and 1680.
284 The following BIOS signature signatures are for boards which do *NOT*
285 work with this driver (these TMC-8xx and TMC-9xx boards may work with the
286 Seagate driver):
288 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88
289 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89
290 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89
291 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90
292 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
293 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
294 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92
298 struct signature {
299 char *signature;
300 int sig_offset;
301 int sig_length;
302 int major_bios_version;
303 int minor_bios_version;
304 } signatures[] = {
305 /* 1 2 3 4 5 6 */
306 /* 123456789012345678901234567890123456789012345678901234567890 */
307 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0 },
308 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0 },
309 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0 },
310 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2 },
311 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1 },
313 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE
314 Also, fix the disk geometry code for your signature and send your
315 changes for faith@cs.unc.edu. Above all, do *NOT* change any old
316 signatures!
318 Note that the last line will match a "generic" 18XX bios. Because
319 Future Domain has changed the host SCSI ID and/or the location of the
320 geometry information in the on-board RAM area for each of the first
321 three BIOS's, it is still important to enter a fully qualified
322 signature in the table for any new BIOS's (after the host SCSI ID and
323 geometry location are verified.) */
326 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
328 static void print_banner( void )
330 printk( "%s", fdomain_16x0_info() );
331 printk( "Future Domain: BIOS version %d.%d, %s\n",
332 bios_major, bios_minor,
333 chip == tmc1800 ? "TMC-1800"
334 : (chip == tmc18c50 ? "TMC-18C50" : "Unknown") );
336 if (interrupt_level) {
337 printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
338 (unsigned)bios_base, port_base, interrupt_level );
339 } else {
340 printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
341 (unsigned)bios_base, port_base );
345 static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
347 unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
349 while (jiffies < the_time);
352 inline static void fdomain_make_bus_idle( void )
354 outb( 0, SCSI_Cntl_port );
355 outb( 0, SCSI_Mode_Cntl_port );
356 if (chip == tmc18c50)
357 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
358 else
359 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
362 static int fdomain_is_valid_port( int port )
364 int options;
366 #if DEBUG_DETECT
367 printk( " (%x%x),",
368 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
369 #endif
371 /* The MCA ID is a unique id for each MCA compatible board. We
372 are using ISA boards, but Future Domain provides the MCA ID
373 anyway. We can use this ID to ensure that this is a Future
374 Domain TMC-1660/TMC-1680.
377 if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
378 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
379 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
380 chip = tmc1800;
381 } else { /* test for 0xe960 id */
382 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
383 chip = tmc18c50;
386 /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
387 Now, check to be sure the bios_base matches these ports. If someone
388 was unlucky enough to have purchased more than one Future Domain
389 board, then they will have to modify this code, as we only detect one
390 board here. [The one with the lowest bios_base.] */
392 options = inb( port + Configuration1 );
394 #if DEBUG_DETECT
395 printk( " Options = %x\n", options );
396 #endif
398 /* Check for board with lowest bios_base. */
399 if (addresses[ (options & 0xc0) >> 6 ] != bios_base)
400 return 0;
401 interrupt_level = ints[ (options & 0x0e) >> 1 ];
403 return 1;
406 static int fdomain_test_loopback( void )
408 int i;
409 int result;
411 for (i = 0; i < 255; i++) {
412 outb( i, port_base + Write_Loopback );
413 result = inb( port_base + Read_Loopback );
414 if (i != result)
415 return 1;
417 return 0;
420 int fdomain_16x0_detect( int hostnum )
422 int i, j;
423 int flag = 0;
424 struct sigaction sa;
425 int retcode;
426 #if DO_DETECT
427 const int buflen = 255;
428 Scsi_Cmnd SCinit;
429 unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
430 unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
431 unsigned char do_read_capacity[] = { READ_CAPACITY,
432 0, 0, 0, 0, 0, 0, 0, 0, 0 };
433 unsigned char buf[buflen];
434 #endif
436 #if DEBUG_DETECT
437 printk( "fdomain_16x0_detect()," );
438 #endif
440 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
441 #if DEBUG_DETECT
442 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
443 #endif
444 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
445 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
446 signatures[j].signature, signatures[j].sig_length )) {
447 bios_major = signatures[j].major_bios_version;
448 bios_minor = signatures[j].minor_bios_version;
449 bios_base = addresses[i];
454 if (!bios_base) {
455 #if DEBUG_DETECT
456 printk( " FAILED: NO BIOS\n" );
457 #endif
458 return 0;
461 if (bios_major == 2) {
462 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
463 Assuming the ROM is enabled (otherwise we wouldn't have been
464 able to read the ROM signature :-), then the ROM sets up the
465 RAM area with some magic numbers, such as a list of port
466 base addresses and a list of the disk "geometry" reported to
467 DOS (this geometry has nothing to do with physical geometry).
470 port_base = *((char *)bios_base + 0x1fcc)
471 + (*((char *)bios_base + 0x1fcd) << 8);
473 #if DEBUG_DETECT
474 printk( " %x,", port_base );
475 #endif
477 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
478 if (port_base == ports[i])
479 ++flag;
482 if (flag)
483 flag = fdomain_is_valid_port( port_base );
486 if (!flag) { /* Cannot get port base from BIOS RAM */
488 /* This is a bad sign. It usually means that someone patched the
489 BIOS signature list (the signatures variable) to contain a BIOS
490 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. It
491 also means that we don't have a Version 2.0 BIOS :-)
494 #if DEBUG_DETECT
495 if (bios_major != 2) printk( " RAM FAILED, " );
496 #endif
498 /* Anyway, the alternative to finding the address in the RAM is
499 to just search through every possible port address for one
500 that is attached to the Future Domain card. Don't panic,
501 though, about reading all these random port addresses--there
502 are rumors that the Future Domain BIOS does something very
503 similar.
505 Do not, however, check ports which the kernel knows are being used
506 by another driver.
509 for (i = 0; !flag && i < PORT_COUNT; i++) {
510 port_base = ports[i];
511 if (check_region( port_base, 0x10 )) {
512 #if DEBUG_DETECT
513 printf( " (%x inuse),", port_base );
514 #endif
515 continue;
517 #if DEBUG_DETECT
518 printk( " %x,", port_base );
519 #endif
520 flag = fdomain_is_valid_port( port_base );
524 if (!flag) {
525 #if DEBUG_DETECT
526 printk( " FAILED: NO PORT\n" );
527 #endif
528 return 0; /* Cannot find valid set of ports */
531 print_banner();
533 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
534 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
535 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
536 Interrupt_Status_port = port_base + Interrupt_Status;
537 Read_FIFO_port = port_base + Read_FIFO;
538 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
539 SCSI_Cntl_port = port_base + SCSI_Cntl;
540 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
541 SCSI_Status_port = port_base + SCSI_Status;
542 TMC_Cntl_port = port_base + TMC_Cntl;
543 TMC_Status_port = port_base + TMC_Status;
544 Write_FIFO_port = port_base + Write_FIFO;
545 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
547 fdomain_16x0_reset( NULL );
549 if (fdomain_test_loopback()) {
550 #if DEBUG_DETECT
551 printk( "Future Domain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
552 #endif
553 return 0;
556 this_host = hostnum;
558 /* Log IRQ with kernel */
560 if (!interrupt_level) {
561 panic( "Future Domain: *NO* interrupt level selected!\n" );
562 } else {
563 /* Register the IRQ with the kernel */
565 sa.sa_handler = fdomain_16x0_intr;
566 sa.sa_flags = SA_INTERRUPT;
567 sa.sa_mask = 0;
568 sa.sa_restorer = NULL;
570 retcode = irqaction( interrupt_level, &sa );
572 if (retcode < 0) {
573 if (retcode == -EINVAL) {
574 printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
575 printk( " This shouldn't happen!\n" );
576 printk( " Send mail to faith@cs.unc.edu\n" );
577 } else if (retcode == -EBUSY) {
578 printk( "Future Domain: IRQ %d is already in use!\n",
579 interrupt_level );
580 printk( " Please use another IRQ!\n" );
581 } else {
582 printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
583 printk( " This shouldn't happen!\n" );
584 printk( " Send mail to faith@cs.unc.edu\n" );
586 panic( "Future Domain: Driver requires interruptions\n" );
587 } else {
588 printk( "Future Domain: IRQ %d requested from kernel\n",
589 interrupt_level );
593 /* Log I/O ports with kernel */
595 snarf_region( port_base, 0x10 );
597 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
598 adapter_mask = 0x80;
599 scsi_hosts[this_host].this_id = 7;
602 #if DO_DETECT
604 /* These routines are here because of the way the SCSI bus behaves after
605 a reset. This appropriate behavior was not handled correctly by the
606 higher level SCSI routines when I first wrote this driver. Now,
607 however, correct scan routines are part of scsi.c and these routines
608 are no longer needed. However, this code is still good for
609 debugging. */
611 SCinit.request_buffer = SCinit.buffer = buf;
612 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
613 SCinit.use_sg = 0;
614 SCinit.lun = 0;
616 printk( "Future Domain detection routine scanning for devices:\n" );
617 for (i = 0; i < 8; i++) {
618 SCinit.target = i;
619 if (i == scsi_hosts[this_host].this_id) /* Skip host adapter */
620 continue;
621 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
622 retcode = fdomain_16x0_command(&SCinit);
623 if (!retcode) {
624 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
625 retcode = fdomain_16x0_command(&SCinit);
626 if (!retcode) {
627 printk( " SCSI ID %d: ", i );
628 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
629 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
630 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
631 retcode = fdomain_16x0_command(&SCinit);
632 if (!retcode) {
633 unsigned long blocks, size, capacity;
635 blocks = (buf[0] << 24) | (buf[1] << 16)
636 | (buf[2] << 8) | buf[3];
637 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
638 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
640 printk( "%lu MB (%lu byte blocks)",
641 ((capacity + 5L) / 10L), size );
642 } else {
643 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
644 retcode = fdomain_16x0_command(&SCinit);
646 printk ("\n" );
647 } else {
648 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
649 retcode = fdomain_16x0_command(&SCinit);
653 #endif
655 return 1;
658 const char *fdomain_16x0_info(void)
660 static char buffer[80];
661 char *pt;
663 strcpy( buffer, "Future Domain: TMC-16x0 SCSI driver, version" );
664 if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */
665 strcat( buffer, strchr( VERSION, ':' ) + 1 );
666 pt = strrchr( buffer, '$') - 1;
667 if (!pt) /* Stripped RCS Revision string? */
668 pt = buffer + strlen( buffer ) - 1;
669 if (*pt != ' ')
670 ++pt;
671 *pt++ = '\n';
672 *pt = '\0';
673 } else { /* Assume VERSION is a number */
674 strcat( buffer, " " VERSION "\n" );
677 return buffer;
680 #if 0
681 static int fdomain_arbitrate( void )
683 int status = 0;
684 unsigned long timeout;
686 #if EVERY_ACCESS
687 printk( "fdomain_arbitrate()\n" );
688 #endif
690 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
691 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */
692 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
694 timeout = jiffies + 50; /* 500 mS */
695 while (jiffies < timeout) {
696 status = inb( TMC_Status_port ); /* Read adapter status */
697 if (status & 0x02) /* Arbitration complete */
698 return 0;
701 /* Make bus idle */
702 fdomain_make_bus_idle();
704 #if EVERY_ACCESS
705 printk( "Arbitration failed, status = %x\n", status );
706 #endif
707 #if ERRORS_ONLY
708 printk( "Future Domain: Arbitration failed, status = %x", status );
709 #endif
710 return 1;
712 #endif
714 static int fdomain_select( int target )
716 int status;
717 unsigned long timeout;
720 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
721 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
723 /* Stop arbitration and enable parity */
724 outb( PARITY_MASK, TMC_Cntl_port );
726 timeout = jiffies + 25; /* 250mS */
727 while (jiffies < timeout) {
728 status = inb( SCSI_Status_port ); /* Read adapter status */
729 if (status & 1) { /* Busy asserted */
730 /* Enable SCSI Bus (on error, should make bus idle with 0) */
731 outb( 0x80, SCSI_Cntl_port );
732 return 0;
735 /* Make bus idle */
736 fdomain_make_bus_idle();
737 #if EVERY_ACCESS
738 if (!target) printk( "Selection failed\n" );
739 #endif
740 #if ERRORS_ONLY
741 if (!target) printk( "Future Domain: Selection failed" );
742 #endif
743 return 1;
746 void my_done( int error )
748 if (in_command) {
749 in_command = 0;
750 outb( 0x00, Interrupt_Cntl_port );
751 fdomain_make_bus_idle();
752 current_SC->result = error;
753 if (current_SC->scsi_done)
754 current_SC->scsi_done( current_SC );
755 else panic( "Future Domain: current_SC->scsi_done() == NULL" );
756 } else {
757 panic( "Future Domain: my_done() called outside of command\n" );
759 #if DEBUG_RACE
760 in_interrupt_flag = 0;
761 #endif
764 void fdomain_16x0_intr( int unused )
766 int status;
767 int done = 0;
768 unsigned data_count;
770 sti();
772 outb( 0x00, Interrupt_Cntl_port );
774 /* We usually have one spurious interrupt after each command. Ignore it. */
775 if (!in_command || !current_SC) { /* Spurious interrupt */
776 #if EVERY_ACCESS
777 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
778 in_command, current_SC );
779 #endif
780 return;
783 /* Abort calls my_done, so we do nothing here. */
784 if (current_SC->SCp.phase & aborted) {
785 #if DEBUG_ABORT
786 printk( "Interrupt after abort, ignoring\n" );
787 #endif
789 return; */
792 #if DEBUG_RACE
793 ++in_interrupt_flag;
794 #endif
796 if (current_SC->SCp.phase & in_arbitration) {
797 status = inb( TMC_Status_port ); /* Read adapter status */
798 if (!(status & 0x02)) {
799 #if EVERY_ACCESS
800 printk( " AFAIL " );
801 #endif
802 my_done( DID_BUS_BUSY << 16 );
803 return;
805 current_SC->SCp.phase = in_selection;
807 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
809 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
810 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
812 /* Stop arbitration and enable parity */
813 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
814 #if DEBUG_RACE
815 in_interrupt_flag = 0;
816 #endif
817 return;
818 } else if (current_SC->SCp.phase & in_selection) {
819 status = inb( SCSI_Status_port );
820 if (!(status & 0x01)) {
821 /* Try again, for slow devices */
822 if (fdomain_select( current_SC->target )) {
823 #if EVERY_ACCESS
824 printk( " SFAIL " );
825 #endif
826 my_done( DID_NO_CONNECT << 16 );
827 return;
828 } else {
829 #if EVERY_ACCESS
830 printk( " AltSel " );
831 #endif
832 /* Stop arbitration and enable parity */
833 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
836 current_SC->SCp.phase = in_other;
837 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
838 outb( 0x80, SCSI_Cntl_port );
839 #if DEBUG_RACE
840 in_interrupt_flag = 0;
841 #endif
842 return;
845 /* current_SC->SCp.phase == in_other: this is the body of the routine */
847 status = inb( SCSI_Status_port );
849 if (status & 0x10) { /* REQ */
851 switch (status & 0x0e) {
853 case 0x08: /* COMMAND OUT */
854 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
855 Write_SCSI_Data_port );
856 #if EVERY_ACCESS
857 printk( "CMD = %x,",
858 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
859 #endif
860 break;
861 case 0x00: /* DATA OUT -- tmc18c50 only */
862 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
863 current_SC->SCp.have_data_in = -1;
864 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
866 break;
867 case 0x04: /* DATA IN -- tmc18c50 only */
868 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
869 current_SC->SCp.have_data_in = 1;
870 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
872 break;
873 case 0x0c: /* STATUS IN */
874 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
875 #if EVERY_ACCESS
876 printk( "Status = %x, ", current_SC->SCp.Status );
877 #endif
878 #if ERRORS_ONLY
879 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
880 printk( "Future Domain: target = %d, command = %x, "
881 "Status = %x\n",
882 current_SC->target, current_SC->cmnd[0],
883 current_SC->SCp.Status );
885 #endif
886 break;
887 case 0x0a: /* MESSAGE OUT */
888 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
889 break;
890 case 0x0e: /* MESSAGE IN */
891 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
892 #if EVERY_ACCESS
893 printk( "Message = %x, ", current_SC->SCp.Message );
894 #endif
895 if (!current_SC->SCp.Message) ++done;
896 #if DEBUG_MESSAGES || EVERY_ACCESS
897 if (current_SC->SCp.Message) {
898 printk( "Future Domain: Message = %x\n",
899 current_SC->SCp.Message );
901 #endif
902 break;
906 if (chip == tmc1800
907 && !current_SC->SCp.have_data_in
908 && (current_SC->SCp.sent_command
909 >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) {
910 /* We have to get the FIFO direction
911 correct, so I've made a table based
912 on the SCSI Standard of which commands
913 appear to require a DATA OUT phase.
916 p. 94: Command for all device types
917 CHANGE DEFINITION 40 DATA OUT
918 COMPARE 39 DATA OUT
919 COPY 18 DATA OUT
920 COPY AND VERIFY 3a DATA OUT
921 INQUIRY 12
922 LOG SELECT 4c DATA OUT
923 LOG SENSE 4d
924 MODE SELECT (6) 15 DATA OUT
925 MODE SELECT (10) 55 DATA OUT
926 MODE SENSE (6) 1a
927 MODE SENSE (10) 5a
928 READ BUFFER 3c
929 RECEIVE DIAGNOSTIC RESULTS 1c
930 REQUEST SENSE 03
931 SEND DIAGNOSTIC 1d DATA OUT
932 TEST UNIT READY 00
933 WRITE BUFFER 3b DATA OUT
935 p.178: Commands for direct-access devices (not listed on p. 94)
936 FORMAT UNIT 04 DATA OUT
937 LOCK-UNLOCK CACHE 36
938 PRE-FETCH 34
939 PREVENT-ALLOW MEDIUM REMOVAL 1e
940 READ (6)/RECEIVE 08
941 READ (10) 3c
942 READ CAPACITY 25
943 READ DEFECT DATA (10) 37
944 READ LONG 3e
945 REASSIGN BLOCKS 07 DATA OUT
946 RELEASE 17
947 RESERVE 16 DATA OUT
948 REZERO UNIT/REWIND 01
949 SEARCH DATA EQUAL (10) 31 DATA OUT
950 SEARCH DATA HIGH (10) 30 DATA OUT
951 SEARCH DATA LOW (10) 32 DATA OUT
952 SEEK (6) 0b
953 SEEK (10) 2b
954 SET LIMITS (10) 33
955 START STOP UNIT 1b
956 SYNCHRONIZE CACHE 35
957 VERIFY (10) 2f
958 WRITE (6)/PRINT/SEND 0a DATA OUT
959 WRITE (10)/SEND 2a DATA OUT
960 WRITE AND VERIFY (10) 2e DATA OUT
961 WRITE LONG 3f DATA OUT
962 WRITE SAME 41 DATA OUT ?
964 p. 261: Commands for sequential-access devices (not previously listed)
965 ERASE 19
966 LOAD UNLOAD 1b
967 LOCATE 2b
968 READ BLOCK LIMITS 05
969 READ POSITION 34
970 READ REVERSE 0f
971 RECOVER BUFFERED DATA 14
972 SPACE 11
973 WRITE FILEMARKS 10 ?
975 p. 298: Commands for printer devices (not previously listed)
976 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
977 SLEW AND PRINT 0b DATA OUT -- same as seek
978 STOP PRINT 1b
979 SYNCHRONIZE BUFFER 10
981 p. 315: Commands for processor devices (not previously listed)
983 p. 321: Commands for write-once devices (not previously listed)
984 MEDIUM SCAN 38
985 READ (12) a8
986 SEARCH DATA EQUAL (12) b1 DATA OUT
987 SEARCH DATA HIGH (12) b0 DATA OUT
988 SEARCH DATA LOW (12) b2 DATA OUT
989 SET LIMITS (12) b3
990 VERIFY (12) af
991 WRITE (12) aa DATA OUT
992 WRITE AND VERIFY (12) ae DATA OUT
994 p. 332: Commands for CD-ROM devices (not previously listed)
995 PAUSE/RESUME 4b
996 PLAY AUDIO (10) 45
997 PLAY AUDIO (12) a5
998 PLAY AUDIO MSF 47
999 PLAY TRACK RELATIVE (10) 49
1000 PLAY TRACK RELATIVE (12) a9
1001 READ HEADER 44
1002 READ SUB-CHANNEL 42
1003 READ TOC 43
1005 p. 370: Commands for scanner devices (not previously listed)
1006 GET DATA BUFFER STATUS 34
1007 GET WINDOW 25
1008 OBJECT POSITION 31
1009 SCAN 1b
1010 SET WINDOW 24 DATA OUT
1012 p. 391: Commands for optical memory devices (not listed)
1013 ERASE (10) 2c
1014 ERASE (12) ac
1015 MEDIUM SCAN 38 DATA OUT
1016 READ DEFECT DATA (12) b7
1017 READ GENERATION 29
1018 READ UPDATED BLOCK 2d
1019 UPDATE BLOCK 3d DATA OUT
1021 p. 419: Commands for medium changer devices (not listed)
1022 EXCHANGE MEDIUM 46
1023 INITIALIZE ELEMENT STATUS 07
1024 MOVE MEDIUM a5
1025 POSITION TO ELEMENT 2b
1026 READ ELEMENT STATUS b8
1027 REQUEST VOL. ELEMENT ADDRESS b5
1028 SEND VOLUME TAG b6 DATA OUT
1030 p. 454: Commands for communications devices (not listed previously)
1031 GET MESSAGE (6) 08
1032 GET MESSAGE (10) 28
1033 GET MESSAGE (12) a8
1036 switch (current_SC->cmnd[0]) {
1037 case CHANGE_DEFINITION: case COMPARE: case COPY:
1038 case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
1039 case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
1041 case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
1042 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
1043 case WRITE_6: case WRITE_10: case WRITE_VERIFY:
1044 case 0x3f: case 0x41:
1046 case 0xb1: case 0xb0: case 0xb2:
1047 case 0xaa: case 0xae:
1049 case 0x24:
1051 case 0x38: case 0x3d:
1053 case 0xb6:
1055 case 0xea: /* alternate number for WRITE LONG */
1057 current_SC->SCp.have_data_in = -1;
1058 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1059 break;
1061 case 0x00:
1062 default:
1064 current_SC->SCp.have_data_in = 1;
1065 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1066 break;
1070 if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
1071 while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
1072 #if EVERY_ACCESS
1073 printk( "DC=%d, ", data_count ) ;
1074 #endif
1075 if (data_count > current_SC->SCp.this_residual)
1076 data_count = current_SC->SCp.this_residual;
1077 if (data_count > 0) {
1078 #if EVERY_ACCESS
1079 printk( "%d OUT, ", data_count );
1080 #endif
1081 if (data_count == 1) {
1082 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1083 --current_SC->SCp.this_residual;
1084 } else {
1085 data_count >>= 1;
1086 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1087 current_SC->SCp.ptr += 2 * data_count;
1088 current_SC->SCp.this_residual -= 2 * data_count;
1091 if (!current_SC->SCp.this_residual) {
1092 if (current_SC->SCp.buffers_residual) {
1093 --current_SC->SCp.buffers_residual;
1094 ++current_SC->SCp.buffer;
1095 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1096 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1097 } else
1098 break;
1103 if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
1104 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
1105 #if EVERY_ACCESS
1106 printk( "DC=%d, ", data_count );
1107 #endif
1108 if (data_count > current_SC->SCp.this_residual)
1109 data_count = current_SC->SCp.this_residual;
1110 if (data_count) {
1111 #if EVERY_ACCESS
1112 printk( "%d IN, ", data_count );
1113 #endif
1114 if (data_count == 1) {
1115 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1116 --current_SC->SCp.this_residual;
1117 } else {
1118 data_count >>= 1; /* Number of words */
1119 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1120 current_SC->SCp.ptr += 2 * data_count;
1121 current_SC->SCp.this_residual -= 2 * data_count;
1124 if (!current_SC->SCp.this_residual
1125 && current_SC->SCp.buffers_residual) {
1126 --current_SC->SCp.buffers_residual;
1127 ++current_SC->SCp.buffer;
1128 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1129 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1134 if (done) {
1135 #if EVERY_ACCESS
1136 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1137 #endif
1139 #if ERRORS_ONLY
1140 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1141 if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
1142 unsigned char key;
1143 unsigned char code;
1144 unsigned char qualifier;
1146 key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
1147 & 0x0f;
1148 code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
1149 qualifier = (unsigned char)(*((char *)current_SC->request_buffer
1150 + 13));
1152 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1153 && !(key == NOT_READY
1154 && code == 0x04
1155 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1156 && !(key == ILLEGAL_REQUEST && (code == 0x25
1157 || code == 0x24
1158 || !code)))
1160 printk( "Future Domain: REQUEST SENSE "
1161 "Key = %x, Code = %x, Qualifier = %x\n",
1162 key, code, qualifier );
1165 #endif
1166 #if EVERY_ACCESS
1167 printk( "BEFORE MY_DONE. . ." );
1168 #endif
1169 my_done( (current_SC->SCp.Status & 0xff)
1170 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1171 #if EVERY_ACCESS
1172 printk( "RETURNING.\n" );
1173 #endif
1175 } else {
1176 if (current_SC->SCp.phase & disconnect) {
1177 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1178 outb( 0x00, SCSI_Cntl_port );
1179 } else {
1180 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1183 #if DEBUG_RACE
1184 in_interrupt_flag = 0;
1185 #endif
1186 return;
1189 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
1191 if (in_command) {
1192 panic( "Future Domain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1194 #if EVERY_ACCESS
1195 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1196 SCpnt->target,
1197 *(unsigned char *)SCpnt->cmnd,
1198 SCpnt->use_sg,
1199 SCpnt->request_bufflen );
1200 #endif
1202 fdomain_make_bus_idle();
1204 current_SC = SCpnt; /* Save this for the done function */
1205 current_SC->scsi_done = done;
1207 /* Initialize static data */
1209 if (current_SC->use_sg) {
1210 current_SC->SCp.buffer =
1211 (struct scatterlist *)current_SC->request_buffer;
1212 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1213 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1214 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1215 } else {
1216 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1217 current_SC->SCp.this_residual = current_SC->request_bufflen;
1218 current_SC->SCp.buffer = NULL;
1219 current_SC->SCp.buffers_residual = 0;
1223 current_SC->SCp.Status = 0;
1224 current_SC->SCp.Message = 0;
1225 current_SC->SCp.have_data_in = 0;
1226 current_SC->SCp.sent_command = 0;
1227 current_SC->SCp.phase = in_arbitration;
1229 /* Start arbitration */
1230 outb( 0x00, Interrupt_Cntl_port );
1231 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
1232 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
1233 ++in_command;
1234 outb( 0x20, Interrupt_Cntl_port );
1235 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
1237 return 0;
1240 /* The following code, which simulates the old-style command function, was
1241 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)
1242 1992 Tommy Thorn. */
1244 static volatile int internal_done_flag = 0;
1245 static volatile int internal_done_errcode = 0;
1247 static void internal_done( Scsi_Cmnd *SCpnt )
1249 internal_done_errcode = SCpnt->result;
1250 ++internal_done_flag;
1253 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
1255 fdomain_16x0_queue( SCpnt, internal_done );
1257 while (!internal_done_flag)
1259 internal_done_flag = 0;
1260 return internal_done_errcode;
1263 /* End of code derived from Tommy Thorn's work. */
1265 void print_info( Scsi_Cmnd *SCpnt )
1267 unsigned int imr;
1268 unsigned int irr;
1269 unsigned int isr;
1271 print_banner();
1272 switch (SCpnt->SCp.phase) {
1273 case in_arbitration: printk( "arbitration " ); break;
1274 case in_selection: printk( "selection " ); break;
1275 case in_other: printk( "other " ); break;
1276 default: printk( "unknown " ); break;
1279 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1280 SCpnt->SCp.phase,
1281 SCpnt->target,
1282 *(unsigned char *)SCpnt->cmnd,
1283 SCpnt->use_sg,
1284 SCpnt->request_bufflen );
1285 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1286 SCpnt->SCp.sent_command,
1287 SCpnt->SCp.have_data_in,
1288 SCpnt->timeout );
1289 #if DEBUG_RACE
1290 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1291 #endif
1293 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1294 outb( 0x0a, 0xa0 );
1295 irr = inb( 0xa0 ) << 8;
1296 outb( 0x0a, 0x20 );
1297 irr += inb( 0x20 );
1298 outb( 0x0b, 0xa0 );
1299 isr = inb( 0xa0 ) << 8;
1300 outb( 0x0b, 0x20 );
1301 isr += inb( 0x20 );
1303 /* Print out interesting information */
1304 printk( "IMR = 0x%04x", imr );
1305 if (imr & (1 << interrupt_level))
1306 printk( " (masked)" );
1307 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1309 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1310 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1311 if (inb( TMC_Status_port & 1))
1312 printk( " (interrupt)" );
1313 printk( "\n" );
1314 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1315 if (inb( Interrupt_Status_port ) & 0x08)
1316 printk( " (enabled)" );
1317 printk( "\n" );
1318 if (chip == tmc18c50) {
1319 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1320 printk( "Int. Condition = 0x%02x\n",
1321 inb( port_base + Interrupt_Cond ) );
1323 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1324 if (chip == tmc18c50)
1325 printk( "Configuration 2 = 0x%02x\n",
1326 inb( port_base + Configuration2 ) );
1329 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code )
1332 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1333 printk( "Future Domain: Abort " );
1334 #endif
1336 cli();
1337 if (!in_command) {
1338 #if EVERY_ACCESS || ERRORS_ONLY
1339 printk( " (not in command)\n" );
1340 #endif
1341 sti();
1342 return 0;
1343 } else {
1344 #if EVERY_ACCESS || ERRORS_ONLY
1345 printk( " code = %d\n", code );
1346 #endif
1349 #if DEBUG_ABORT
1350 print_info( SCpnt );
1351 #endif
1353 fdomain_make_bus_idle();
1355 current_SC->SCp.phase |= aborted;
1357 current_SC->result = code ? code : DID_ABORT;
1359 sti();
1361 /* Aborts are not done well. . . */
1362 my_done( code << 16 );
1364 return 0;
1367 int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
1369 #if DEBUG_RESET
1370 static int called_once = 0;
1371 #endif
1373 #if ERRORS_ONLY
1374 printk( "Future Domain: SCSI Bus Reset\n" );
1375 #endif
1377 #if DEBUG_RESET
1378 if (called_once) print_info( current_SC );
1379 called_once = 1;
1380 #endif
1382 outb( 1, SCSI_Cntl_port );
1383 do_pause( 2 );
1384 outb( 0, SCSI_Cntl_port );
1385 do_pause( 115 );
1386 outb( 0, SCSI_Mode_Cntl_port );
1387 outb( PARITY_MASK, TMC_Cntl_port );
1389 /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1390 is probably hosed at this point. We will, however, try to keep
1391 things going by informing the high-level code that we need help. */
1393 if (SCpnt)
1394 SCpnt->flags |= NEEDS_JUMPSTART;
1396 return 0;
1399 int fdomain_16x0_biosparam( int size, int dev, int *info_array )
1401 int drive;
1402 struct drive_info {
1403 unsigned short cylinders;
1404 unsigned char heads;
1405 unsigned char sectors;
1406 } *i;
1408 /* NOTES:
1409 The RAM area starts at 0x1f00 from the bios_base address.
1411 For BIOS Version 2.0:
1413 The drive parameter table seems to start at 0x1f30.
1414 The first byte's purpose is not known.
1415 Next is the cylinder, head, and sector information.
1416 The last 4 bytes appear to be the drive's size in sectors.
1417 The other bytes in the drive parameter table are unknown.
1418 If anyone figures them out, please send me mail, and I will
1419 update these notes.
1421 Tape drives do not get placed in this table.
1423 There is another table at 0x1fea:
1424 If the byte is 0x01, then the SCSI ID is not in use.
1425 If the byte is 0x18 or 0x48, then the SCSI ID is in use,
1426 although tapes don't seem to be in this table. I haven't
1427 seen any other numbers (in a limited sample).
1429 0x1f2d is a drive count (i.e., not including tapes)
1431 The table at 0x1fcc are I/O ports addresses for the various
1432 operations. I calculate these by hand in this driver code.
1434 For BIOS Version 3.2:
1436 The drive parameter table starts at 0x1f70. Each entry is
1437 0x0a bytes long. Heads are one less than we need to report.
1440 drive = MINOR(dev) / 16;
1442 if (bios_major == 2) {
1443 i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1444 info_array[0] = i->heads;
1445 info_array[1] = i->sectors;
1446 info_array[2] = i->cylinders;
1447 } else if (bios_major == 3) { /* Appears to be the same for 3.0 and 3.2 */
1448 i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1449 info_array[0] = i->heads + 1;
1450 info_array[1] = i->sectors;
1451 info_array[2] = i->cylinders;
1452 } else {
1453 /* How the data is stored in the RAM area is very BIOS-dependent.
1454 Therefore, assume a version 3 layout, and check for validity. */
1456 i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1457 info_array[0] = i->heads + 1;
1458 info_array[1] = i->sectors;
1459 info_array[2] = i->cylinders;
1461 if (!info_array[0]
1462 || !info_array[1]
1463 || !info_array[2]
1464 || info_array[2] > 1024 /* DOS uses only 10 bits.
1465 Should this be changed
1466 to support larger drives?
1467 I.e., will the controller
1468 "do the right thing"?
1472 info_array[0]
1473 = info_array[1]
1474 = info_array[2]
1475 = 0;
1479 return 0;