|
|
1.1 ! root 1: /* fdomain.c -- Future Domain TMC-16x0 SCSI driver ! 2: * Created: Sun May 3 18:53:19 1992 by [email protected] ! 3: * Revised: Thu Oct 12 15:59:37 1995 by [email protected] ! 4: * Author: Rickard E. Faith, [email protected] ! 5: * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith ! 6: * ! 7: * $Id: fdomain.c,v 1.1.1.1 1997/02/25 21:27:49 thomas Exp $ ! 8: ! 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. ! 13: ! 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. ! 18: ! 19: * You should have received a copy of the GNU General Public License along ! 20: * with this program; if not, write to the Free Software Foundation, Inc., ! 21: * 675 Mass Ave, Cambridge, MA 02139, USA. ! 22: ! 23: ************************************************************************** ! 24: ! 25: DESCRIPTION: ! 26: ! 27: This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 ! 28: TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a ! 29: 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin ! 30: high-density external connector. The 1670 and 1680 have floppy disk ! 31: controllers built in. The TMC-3260 is a PCI bus card. ! 32: ! 33: Future Domain's older boards are based on the TMC-1800 chip, and this ! 34: driver was originally written for a TMC-1680 board with the TMC-1800 chip. ! 35: More recently, boards are being produced with the TMC-18C50 and TMC-18C30 ! 36: chips. The latest and greatest board may not work with this driver. If ! 37: you have to patch this driver so that it will recognize your board's BIOS ! 38: signature, then the driver may fail to function after the board is ! 39: detected. ! 40: ! 41: The following BIOS versions are supported: 2.0, 3.0, 3.2, 3.4, and 3.5. ! 42: The following chips are supported: TMC-1800, TMC-18C50, TMC-18C30. ! 43: Reports suggest that the driver will also work with the 36C70 chip and ! 44: with the Quantum ISA-200S and ISA-250MG SCSI adapters. ! 45: ! 46: Please note that the drive ordering that Future Domain implemented in BIOS ! 47: versions 3.4 and 3.5 is the opposite of the order (currently) used by the ! 48: rest of the SCSI industry. If you have BIOS version 3.4 or 3.5, and have ! 49: more then one drive, then the drive ordering will be the reverse of that ! 50: which you see under DOS. For example, under DOS SCSI ID 0 will be D: and ! 51: SCSI ID 1 will be C: (the boot device). Under Linux, SCSI ID 0 will be ! 52: /dev/sda and SCSI ID 1 will be /dev/sdb. The Linux ordering is consistent ! 53: with that provided by all the other SCSI drivers for Linux. If you want ! 54: this changed, send me patches that are protected by #ifdefs. ! 55: ! 56: If you have a TMC-8xx or TMC-9xx board, then this is not the driver for ! 57: your board. Please refer to the Seagate driver for more information and ! 58: possible support. ! 59: ! 60: ! 61: ! 62: REFERENCES USED: ! 63: ! 64: "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, ! 65: 1990. ! 66: ! 67: "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain ! 68: Corporation, January 1992. ! 69: ! 70: "LXT SCSI Products: Specifications and OEM Technical Manual (Revision ! 71: B/September 1991)", Maxtor Corporation, 1991. ! 72: ! 73: "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. ! 74: ! 75: "Draft Proposed American National Standard: Small Computer System ! 76: Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, ! 77: revision 10h, October 17, 1991) ! 78: ! 79: Private communications, Drew Eckhardt ([email protected]) and Eric ! 80: Youngdale ([email protected]), 1992. ! 81: ! 82: Private communication, Tuong Le (Future Domain Engineering department), ! 83: 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and ! 84: TMC-18C30 detection.) ! 85: ! 86: Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page ! 87: 60 (2.39: Disk Partition Table Layout). ! 88: ! 89: "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page ! 90: 6-1. ! 91: ! 92: ! 93: ! 94: NOTES ON REFERENCES: ! 95: ! 96: The Maxtor manuals were free. Maxtor telephone technical support is ! 97: great! ! 98: ! 99: The Future Domain manuals were $25 and $35. They document the chip, not ! 100: the TMC-16x0 boards, so some information I had to guess at. In 1992, ! 101: Future Domain sold DOS BIOS source for $250 and the UN*X driver source was ! 102: $750, but these required a non-disclosure agreement, so even if I could ! 103: have afforded them, they would *not* have been useful for writing this ! 104: publically distributable driver. Future Domain technical support has ! 105: provided some information on the phone and have sent a few useful FAXs. ! 106: They have been much more helpful since they started to recognize that the ! 107: word "Linux" refers to an operating system :-). ! 108: ! 109: ! 110: ! 111: ALPHA TESTERS: ! 112: ! 113: There are many other alpha testers that come and go as the driver ! 114: develops. The people listed here were most helpful in times of greatest ! 115: need (mostly early on -- I've probably left out a few worthy people in ! 116: more recent times): ! 117: ! 118: Todd Carrico ([email protected]), Dan Poirier ([email protected] ), Ken ! 119: Corey ([email protected]), C. de Bruin (bruin@[email protected]), Sakari ! 120: Aaltonen ([email protected]), John Rice ([email protected]), Brad ! 121: Yearwood ([email protected]), and Ray Toy ([email protected]). ! 122: ! 123: Special thanks to Tien-Wan Yang ([email protected]), who graciously lent me ! 124: his 18C50-based card for debugging. He is the sole reason that this ! 125: driver works with the 18C50 chip. ! 126: ! 127: Thanks to Dave Newman ([email protected]) for providing initial patches for ! 128: the version 3.4 BIOS. ! 129: ! 130: Thanks to James T. McKinley ([email protected]) for providing ! 131: patches that support the TMC-3260, a PCI bus card with the 36C70 chip. ! 132: The 36C70 chip appears to be "completely compatible" with the 18C30 chip. ! 133: ! 134: Thanks to Eric Kasten ([email protected]) for providing the ! 135: patch for the version 3.5 BIOS. ! 136: ! 137: Thanks for Stephen Henson ([email protected]) for providing the ! 138: patch for the Quantum ISA-200S SCSI adapter. ! 139: ! 140: Thanks to Adam Bowen for the signature to the 1610M/MER/MEX scsi cards, to ! 141: Martin Andrews ([email protected]) for the signature to some ! 142: random TMC-1680 repackaged by IBM; and to Mintak Ng ([email protected]) for ! 143: the version 3.61 BIOS siganture. ! 144: ! 145: Thanks for Mark Singer ([email protected]) and Richard Simpson ! 146: ([email protected]) for more Quantum signatures and detective ! 147: work on the Quantum RAM layout. ! 148: ! 149: Special thanks to James T. McKinley ([email protected]) for ! 150: providing patches for proper PCI BIOS32-mediated detection of the TMC-3260 ! 151: card (a PCI bus card with the 36C70 chip). Please send James PCI-related ! 152: bug reports. ! 153: ! 154: Thanks to Tom Cavin ([email protected]) for preliminary command-line option ! 155: patches. ! 156: ! 157: All of the alpha testers deserve much thanks. ! 158: ! 159: ! 160: ! 161: NOTES ON USER DEFINABLE OPTIONS: ! 162: ! 163: DEBUG: This turns on the printing of various debug information. ! 164: ! 165: ENABLE_PARITY: This turns on SCSI parity checking. With the current ! 166: driver, all attached devices must support SCSI parity. If none of your ! 167: devices support parity, then you can probably get the driver to work by ! 168: turning this option off. I have no way of testing this, however. ! 169: ! 170: FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the ! 171: 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by ! 172: the SCSI device, an interrupt will be raised. Therefore, this could be as ! 173: low as 0, or as high as 16. Note, however, that values which are too high ! 174: or too low seem to prevent any interrupts from occurring, and thereby lock ! 175: up the machine. I have found that 2 is a good number, but throughput may ! 176: be increased by changing this value to values which are close to 2. ! 177: Please let me know if you try any different values. ! 178: ! 179: DO_DETECT: This activates some old scan code which was needed before the ! 180: high level drivers got fixed. If you are having trouble with the driver, ! 181: turning this on should not hurt, and might help. Please let me know if ! 182: this is the case, since this code will be removed from future drivers. ! 183: ! 184: RESELECTION: This is no longer an option, since I gave up trying to ! 185: implement it in version 4.x of this driver. It did not improve ! 186: performance at all and made the driver unstable (because I never found one ! 187: of the two race conditions which were introduced by the multiple ! 188: outstanding command code). The instability seems a very high price to pay ! 189: just so that you don't have to wait for the tape to rewind. If you want ! 190: this feature implemented, send me patches. I'll be happy to send a copy ! 191: of my (broken) driver to anyone who would like to see a copy. ! 192: ! 193: **************************************************************************/ ! 194: ! 195: #ifdef MODULE ! 196: #include <linux/module.h> ! 197: #endif ! 198: ! 199: #include <linux/sched.h> ! 200: #include <asm/io.h> ! 201: #include <linux/blk.h> ! 202: #include "scsi.h" ! 203: #include "hosts.h" ! 204: #include "fdomain.h" ! 205: #include <asm/system.h> ! 206: #include <linux/errno.h> ! 207: #include <linux/string.h> ! 208: #include <linux/ioport.h> ! 209: #include <linux/proc_fs.h> ! 210: #include <linux/bios32.h> ! 211: #include <linux/pci.h> ! 212: #include <linux/stat.h> ! 213: ! 214: #include <linux/config.h> /* for CONFIG_PCI */ ! 215: ! 216: struct proc_dir_entry proc_scsi_fdomain = { ! 217: PROC_SCSI_FDOMAIN, 7, "fdomain", ! 218: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 219: }; ! 220: ! 221: #define VERSION "$Revision: 1.1.1.1 $" ! 222: ! 223: /* START OF USER DEFINABLE OPTIONS */ ! 224: ! 225: #define DEBUG 1 /* Enable debugging output */ ! 226: #define ENABLE_PARITY 1 /* Enable SCSI Parity */ ! 227: #define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ ! 228: #define DO_DETECT 0 /* Do device detection here (see scsi.c) */ ! 229: ! 230: /* END OF USER DEFINABLE OPTIONS */ ! 231: ! 232: #if DEBUG ! 233: #define EVERY_ACCESS 0 /* Write a line on every scsi access */ ! 234: #define ERRORS_ONLY 1 /* Only write a line if there is an error */ ! 235: #define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ ! 236: #define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ ! 237: #define DEBUG_ABORT 1 /* Debug abort() routine */ ! 238: #define DEBUG_RESET 1 /* Debug reset() routine */ ! 239: #define DEBUG_RACE 1 /* Debug interrupt-driven race condition */ ! 240: #else ! 241: #define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ ! 242: #define ERRORS_ONLY 0 ! 243: #define DEBUG_DETECT 0 ! 244: #define DEBUG_MESSAGES 0 ! 245: #define DEBUG_ABORT 0 ! 246: #define DEBUG_RESET 0 ! 247: #define DEBUG_RACE 0 ! 248: #endif ! 249: ! 250: /* Errors are reported on the line, so we don't need to report them again */ ! 251: #if EVERY_ACCESS ! 252: #undef ERRORS_ONLY ! 253: #define ERRORS_ONLY 0 ! 254: #endif ! 255: ! 256: #if ENABLE_PARITY ! 257: #define PARITY_MASK 0x08 ! 258: #else ! 259: #define PARITY_MASK 0x00 ! 260: #endif ! 261: ! 262: enum chip_type { ! 263: unknown = 0x00, ! 264: tmc1800 = 0x01, ! 265: tmc18c50 = 0x02, ! 266: tmc18c30 = 0x03, ! 267: }; ! 268: ! 269: enum { ! 270: in_arbitration = 0x02, ! 271: in_selection = 0x04, ! 272: in_other = 0x08, ! 273: disconnect = 0x10, ! 274: aborted = 0x20, ! 275: sent_ident = 0x40, ! 276: }; ! 277: ! 278: enum in_port_type { ! 279: Read_SCSI_Data = 0, ! 280: SCSI_Status = 1, ! 281: TMC_Status = 2, ! 282: FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ ! 283: Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ ! 284: LSB_ID_Code = 5, ! 285: MSB_ID_Code = 6, ! 286: Read_Loopback = 7, ! 287: SCSI_Data_NoACK = 8, ! 288: Interrupt_Status = 9, ! 289: Configuration1 = 10, ! 290: Configuration2 = 11, /* tmc18c50/tmc18c30 only */ ! 291: Read_FIFO = 12, ! 292: FIFO_Data_Count = 14 ! 293: }; ! 294: ! 295: enum out_port_type { ! 296: Write_SCSI_Data = 0, ! 297: SCSI_Cntl = 1, ! 298: Interrupt_Cntl = 2, ! 299: SCSI_Mode_Cntl = 3, ! 300: TMC_Cntl = 4, ! 301: Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ ! 302: Write_Loopback = 7, ! 303: IO_Control = 11, /* tmc18c30 only */ ! 304: Write_FIFO = 12 ! 305: }; ! 306: ! 307: static int port_base = 0; ! 308: static void *bios_base = NULL; ! 309: static int bios_major = 0; ! 310: static int bios_minor = 0; ! 311: static int PCI_bus = 0; ! 312: static int Quantum = 0; /* Quantum board variant */ ! 313: static int interrupt_level = 0; ! 314: static volatile int in_command = 0; ! 315: static Scsi_Cmnd *current_SC = NULL; ! 316: static enum chip_type chip = unknown; ! 317: static int adapter_mask = 0; ! 318: static int this_id = 0; ! 319: static int setup_called = 0; ! 320: ! 321: #if DEBUG_RACE ! 322: static volatile int in_interrupt_flag = 0; ! 323: #endif ! 324: ! 325: static int SCSI_Mode_Cntl_port; ! 326: static int FIFO_Data_Count_port; ! 327: static int Interrupt_Cntl_port; ! 328: static int Interrupt_Status_port; ! 329: static int Read_FIFO_port; ! 330: static int Read_SCSI_Data_port; ! 331: static int SCSI_Cntl_port; ! 332: static int SCSI_Data_NoACK_port; ! 333: static int SCSI_Status_port; ! 334: static int TMC_Cntl_port; ! 335: static int TMC_Status_port; ! 336: static int Write_FIFO_port; ! 337: static int Write_SCSI_Data_port; ! 338: ! 339: static int FIFO_Size = 0x2000; /* 8k FIFO for ! 340: pre-tmc18c30 chips */ ! 341: ! 342: extern void fdomain_16x0_intr( int irq, struct pt_regs * regs ); ! 343: ! 344: static void *addresses[] = { ! 345: (void *)0xc8000, ! 346: (void *)0xca000, ! 347: (void *)0xce000, ! 348: (void *)0xde000, ! 349: (void *)0xd0000, /* Extra addresses for PCI boards */ ! 350: (void *)0xe0000, ! 351: }; ! 352: #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) ! 353: ! 354: static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; ! 355: #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) ! 356: ! 357: static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; ! 358: ! 359: /* ! 360: ! 361: READ THIS BEFORE YOU ADD A SIGNATURE! ! 362: ! 363: READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! ! 364: ! 365: READ EVERY WORD, ESPECIALLY THE WORD *NOT* ! 366: ! 367: This driver works *ONLY* for Future Domain cards using the TMC-1800, ! 368: TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, ! 369: and 1680. ! 370: ! 371: The following BIOS signature signatures are for boards which do *NOT* ! 372: work with this driver (these TMC-8xx and TMC-9xx boards may work with the ! 373: Seagate driver): ! 374: ! 375: FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 ! 376: FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 ! 377: FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 ! 378: FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 ! 379: FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 ! 380: FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 ! 381: FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 ! 382: ! 383: */ ! 384: ! 385: struct signature { ! 386: const char *signature; ! 387: int sig_offset; ! 388: int sig_length; ! 389: int major_bios_version; ! 390: int minor_bios_version; ! 391: int flag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ ! 392: } signatures[] = { ! 393: /* 1 2 3 4 5 6 */ ! 394: /* 123456789012345678901234567890123456789012345678901234567890 */ ! 395: { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 }, ! 396: { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 }, ! 397: { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 }, ! 398: { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 }, ! 399: { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 }, ! 400: { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 }, ! 401: { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 }, ! 402: { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 }, ! 403: { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 }, ! 404: { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 }, ! 405: /* This next signature may not be a 3.5 bios */ ! 406: { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 }, ! 407: { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 }, ! 408: { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 }, ! 409: { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 }, ! 410: { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 }, ! 411: { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 }, ! 412: ! 413: /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE ! 414: Also, fix the disk geometry code for your signature and send your ! 415: changes for [email protected]. Above all, do *NOT* change any old ! 416: signatures! ! 417: ! 418: Note that the last line will match a "generic" 18XX bios. Because ! 419: Future Domain has changed the host SCSI ID and/or the location of the ! 420: geometry information in the on-board RAM area for each of the first ! 421: three BIOS's, it is still important to enter a fully qualified ! 422: signature in the table for any new BIOS's (after the host SCSI ID and ! 423: geometry location are verified). */ ! 424: }; ! 425: ! 426: #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) ! 427: ! 428: static void print_banner( struct Scsi_Host *shpnt ) ! 429: { ! 430: if (!shpnt) return; /* This won't ever happen */ ! 431: ! 432: if (bios_major < 0 && bios_minor < 0) { ! 433: printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n", ! 434: shpnt->host_no, shpnt->this_id ); ! 435: } else { ! 436: printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no ); ! 437: ! 438: if (bios_major >= 0) printk( "%d.", bios_major ); ! 439: else printk( "?." ); ! 440: ! 441: if (bios_minor >= 0) printk( "%d", bios_minor ); ! 442: else printk( "?." ); ! 443: ! 444: printk( " at 0x%x using scsi id %d\n", ! 445: (unsigned)bios_base, shpnt->this_id ); ! 446: } ! 447: ! 448: /* If this driver works for later FD PCI ! 449: boards, we will have to modify banner ! 450: for additional PCI cards, but for now if ! 451: it's PCI it's a TMC-3260 - JTM */ ! 452: printk( "scsi%d <fdomain>: %s chip at 0x%x irq ", ! 453: shpnt->host_no, ! 454: chip == tmc1800 ? "TMC-1800" ! 455: : (chip == tmc18c50 ? "TMC-18C50" ! 456: : (chip == tmc18c30 ? ! 457: (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") ! 458: : "Unknown")), ! 459: port_base ); ! 460: ! 461: if (interrupt_level) printk( "%d", interrupt_level ); ! 462: else printk( "<none>" ); ! 463: ! 464: printk( "\n" ); ! 465: } ! 466: ! 467: void fdomain_setup( char *str, int *ints ) ! 468: { ! 469: if (setup_called++ || ints[0] < 2 || ints[0] > 3) { ! 470: printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" ); ! 471: printk( "fdomain: bad LILO parameters?\n" ); ! 472: } ! 473: ! 474: port_base = ints[0] >= 1 ? ints[1] : 0; ! 475: interrupt_level = ints[0] >= 2 ? ints[2] : 0; ! 476: this_id = ints[0] >= 3 ? ints[3] : 0; ! 477: ! 478: bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ ! 479: } ! 480: ! 481: ! 482: static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */ ! 483: { ! 484: unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ ! 485: ! 486: while (jiffies < the_time); ! 487: } ! 488: ! 489: inline static void fdomain_make_bus_idle( void ) ! 490: { ! 491: outb( 0, SCSI_Cntl_port ); ! 492: outb( 0, SCSI_Mode_Cntl_port ); ! 493: if (chip == tmc18c50 || chip == tmc18c30) ! 494: outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ ! 495: else ! 496: outb( 0x01 | PARITY_MASK, TMC_Cntl_port ); ! 497: } ! 498: ! 499: static int fdomain_is_valid_port( int port ) ! 500: { ! 501: #if DEBUG_DETECT ! 502: printk( " (%x%x),", ! 503: inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) ); ! 504: #endif ! 505: ! 506: /* The MCA ID is a unique id for each MCA compatible board. We ! 507: are using ISA boards, but Future Domain provides the MCA ID ! 508: anyway. We can use this ID to ensure that this is a Future ! 509: Domain TMC-1660/TMC-1680. ! 510: */ ! 511: ! 512: if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */ ! 513: if (inb( port + LSB_ID_Code ) != 0x27) return 0; ! 514: if (inb( port + MSB_ID_Code ) != 0x61) return 0; ! 515: chip = tmc1800; ! 516: } else { /* test for 0xe960 id */ ! 517: if (inb( port + MSB_ID_Code ) != 0x60) return 0; ! 518: chip = tmc18c50; ! 519: ! 520: #if 0 ! 521: ! 522: /* Try to toggle 32-bit mode. This only ! 523: works on an 18c30 chip. (User reports ! 524: say that this doesn't work at all, so ! 525: we'll use the other method.) */ ! 526: ! 527: outb( 0x80, port + IO_Control ); ! 528: if ((inb( port + Configuration2 ) & 0x80) == 0x80) { ! 529: outb( 0x00, port + IO_Control ); ! 530: if ((inb( port + Configuration2 ) & 0x80) == 0x00) { ! 531: chip = tmc18c30; ! 532: FIFO_Size = 0x800; /* 2k FIFO */ ! 533: } ! 534: } ! 535: #else ! 536: ! 537: /* That should have worked, but appears to ! 538: have problems. Lets assume it is an ! 539: 18c30 if the RAM is disabled. */ ! 540: ! 541: if (inb( port + Configuration2 ) & 0x02) { ! 542: chip = tmc18c30; ! 543: FIFO_Size = 0x800; /* 2k FIFO */ ! 544: } ! 545: #endif ! 546: /* If that failed, we are an 18c50. */ ! 547: } ! 548: ! 549: return 1; ! 550: } ! 551: ! 552: static int fdomain_test_loopback( void ) ! 553: { ! 554: int i; ! 555: int result; ! 556: ! 557: for (i = 0; i < 255; i++) { ! 558: outb( i, port_base + Write_Loopback ); ! 559: result = inb( port_base + Read_Loopback ); ! 560: if (i != result) ! 561: return 1; ! 562: } ! 563: return 0; ! 564: } ! 565: ! 566: /* fdomain_get_irq assumes that we have a valid MCA ID for a ! 567: TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the ! 568: bios_base matches these ports. If someone was unlucky enough to have ! 569: purchased more than one Future Domain board, then they will have to ! 570: modify this code, as we only detect one board here. [The one with the ! 571: lowest bios_base.] ! 572: ! 573: Note that this routine is only used for systems without a PCI BIOS32 ! 574: (e.g., ISA bus). For PCI bus systems, this routine will likely fail ! 575: unless one of the IRQs listed in the ints array is used by the board. ! 576: Sometimes it is possible to use the computer's BIOS setup screen to ! 577: configure a PCI system so that one of these IRQs will be used by the ! 578: Future Domain card. */ ! 579: ! 580: static int fdomain_get_irq( int base ) ! 581: { ! 582: int options = inb( base + Configuration1 ); ! 583: ! 584: #if DEBUG_DETECT ! 585: printk( " Options = %x\n", options ); ! 586: #endif ! 587: ! 588: /* Check for board with lowest bios_base -- ! 589: this isn't valid for the 18c30 or for ! 590: boards on the PCI bus, so just assume we ! 591: have the right board. */ ! 592: ! 593: if (chip != tmc18c30 ! 594: && !PCI_bus ! 595: && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0; ! 596: ! 597: return ints[ (options & 0x0e) >> 1 ]; ! 598: } ! 599: ! 600: static int fdomain_isa_detect( int *irq, int *iobase ) ! 601: { ! 602: int i; ! 603: int base; ! 604: int flag = 0; ! 605: ! 606: if (bios_major == 2) { ! 607: /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. ! 608: Assuming the ROM is enabled (otherwise we wouldn't have been ! 609: able to read the ROM signature :-), then the ROM sets up the ! 610: RAM area with some magic numbers, such as a list of port ! 611: base addresses and a list of the disk "geometry" reported to ! 612: DOS (this geometry has nothing to do with physical geometry). ! 613: */ ! 614: ! 615: switch (Quantum) { ! 616: case 2: /* ISA_200S */ ! 617: case 3: /* ISA_250MG */ ! 618: base = *((char *)bios_base + 0x1fa2) ! 619: + (*((char *)bios_base + 0x1fa3) << 8); ! 620: break; ! 621: case 4: /* ISA_200S (another one) */ ! 622: base = *((char *)bios_base + 0x1fa3) ! 623: + (*((char *)bios_base + 0x1fa4) << 8); ! 624: break; ! 625: default: ! 626: base = *((char *)bios_base + 0x1fcc) ! 627: + (*((char *)bios_base + 0x1fcd) << 8); ! 628: break; ! 629: } ! 630: ! 631: #if DEBUG_DETECT ! 632: printk( " %x,", base ); ! 633: #endif ! 634: ! 635: for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { ! 636: if (base == ports[i]) ! 637: ++flag; ! 638: } ! 639: ! 640: if (flag && fdomain_is_valid_port( base )) { ! 641: *irq = fdomain_get_irq( base ); ! 642: *iobase = base; ! 643: return 1; ! 644: } ! 645: ! 646: /* This is a bad sign. It usually means that someone patched the ! 647: BIOS signature list (the signatures variable) to contain a BIOS ! 648: signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ ! 649: ! 650: #if DEBUG_DETECT ! 651: printk( " RAM FAILED, " ); ! 652: #endif ! 653: } ! 654: ! 655: /* Anyway, the alternative to finding the address in the RAM is to just ! 656: search through every possible port address for one that is attached ! 657: to the Future Domain card. Don't panic, though, about reading all ! 658: these random port addresses -- there are rumors that the Future ! 659: Domain BIOS does something very similar. ! 660: ! 661: Do not, however, check ports which the kernel knows are being used by ! 662: another driver. */ ! 663: ! 664: for (i = 0; i < PORT_COUNT; i++) { ! 665: base = ports[i]; ! 666: if (check_region( base, 0x10 )) { ! 667: #if DEBUG_DETECT ! 668: printk( " (%x inuse),", base ); ! 669: #endif ! 670: continue; ! 671: } ! 672: #if DEBUG_DETECT ! 673: printk( " %x,", base ); ! 674: #endif ! 675: if ((flag = fdomain_is_valid_port( base ))) break; ! 676: } ! 677: ! 678: if (!flag) return 0; /* iobase not found */ ! 679: ! 680: *irq = fdomain_get_irq( base ); ! 681: *iobase = base; ! 682: ! 683: return 1; /* success */ ! 684: } ! 685: ! 686: static int fdomain_pci_nobios_detect( int *irq, int *iobase ) ! 687: { ! 688: int i; ! 689: int flag = 0; ! 690: ! 691: /* The proper way of doing this is to use ask the PCI bus for the device ! 692: IRQ and interrupt level. But we can't do that if PCI BIOS32 support ! 693: isn't compiled into the kernel, or if a PCI BIOS32 isn't present. ! 694: ! 695: Instead, we scan down a bunch of addresses (Future Domain tech ! 696: support says we will probably find the address before we get to ! 697: 0xf800). This works fine on some systems -- other systems may have ! 698: to scan more addresses. If you have to modify this section for your ! 699: installation, please send mail to [email protected]. */ ! 700: ! 701: for (i = 0xfff8; i > 0xe000; i -= 8) { ! 702: if (check_region( i, 0x10 )) { ! 703: #if DEBUG_DETECT ! 704: printk( " (%x inuse)," , i ); ! 705: #endif ! 706: continue; ! 707: } ! 708: if ((flag = fdomain_is_valid_port( i ))) break; ! 709: } ! 710: ! 711: if (!flag) return 0; /* iobase not found */ ! 712: ! 713: *irq = fdomain_get_irq( i ); ! 714: *iobase = i; ! 715: ! 716: return 1; /* success */ ! 717: } ! 718: ! 719: /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* ! 720: iobase) This function gets the Interrupt Level and I/O base address from ! 721: the PCI configuration registers. The I/O base address is masked with ! 722: 0xfff8 since on my card the address read from the PCI config registers ! 723: is off by one from the actual I/O base address necessary for accessing ! 724: the status and control registers on the card (PCI config register gives ! 725: 0xf801, actual address is 0xf800). This is likely a bug in the FD ! 726: config code that writes to the PCI registers, however using a mask ! 727: should be safe since I think the scan done by the card to determine the ! 728: I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at ! 729: least the old scan code we used to use to get the I/O base did... Also, ! 730: the device ID from the PCI config registers is 0x0 and should be 0x60e9 ! 731: as it is in the status registers (offset 5 from I/O base). If this is ! 732: changed in future hardware/BIOS changes it will need to be fixed in this ! 733: detection function. Comments, bug reports, etc... on this function ! 734: should be sent to [email protected] - James T. McKinley. */ ! 735: ! 736: #ifdef CONFIG_PCI ! 737: static int fdomain_pci_bios_detect( int *irq, int *iobase ) ! 738: { ! 739: int error; ! 740: unsigned char pci_bus, pci_dev_fn; /* PCI bus & device function */ ! 741: unsigned char pci_irq; /* PCI interrupt line */ ! 742: unsigned int pci_base; /* PCI I/O base address */ ! 743: unsigned short pci_vendor, pci_device; /* PCI vendor & device IDs */ ! 744: ! 745: /* If the PCI BIOS doesn't exist, use the old-style detection routines. ! 746: Otherwise, get the I/O base address and interrupt from the PCI config ! 747: registers. */ ! 748: ! 749: if (!pcibios_present()) return fdomain_pci_nobios_detect( irq, iobase ); ! 750: ! 751: #if DEBUG_DETECT ! 752: /* Tell how to print a list of the known PCI devices from bios32 and ! 753: list vendor and device IDs being used if in debug mode. */ ! 754: ! 755: printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" ); ! 756: printk( "\nTMC-3260 detect:" ! 757: " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n", ! 758: PCI_VENDOR_ID_FD, ! 759: PCI_DEVICE_ID_FD_36C70 ); ! 760: #endif ! 761: ! 762: /* We will have to change this if more than 1 PCI bus is present and the ! 763: FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, ! 764: which is not supported by bios32 right now anyway). This should ! 765: probably be done by a call to pcibios_find_device but I can't get it ! 766: to work... Also the device ID reported from the PCI config registers ! 767: does not match the device ID quoted in the tech manual or available ! 768: from offset 5 from the I/O base address. It should be 0x60E9, but it ! 769: is 0x0 if read from the PCI config registers. I guess the FD folks ! 770: neglected to write it to the PCI registers... This loop is necessary ! 771: to get the device function (at least until someone can get ! 772: pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ ! 773: ! 774: pci_bus = 0; ! 775: ! 776: for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { ! 777: pcibios_read_config_word( pci_bus, ! 778: pci_dev_fn, ! 779: PCI_VENDOR_ID, ! 780: &pci_vendor ); ! 781: ! 782: if (pci_vendor == PCI_VENDOR_ID_FD) { ! 783: pcibios_read_config_word( pci_bus, ! 784: pci_dev_fn, ! 785: PCI_DEVICE_ID, ! 786: &pci_device ); ! 787: ! 788: if (pci_device == PCI_DEVICE_ID_FD_36C70) { ! 789: /* Break out once we have the correct device. If other FD ! 790: PCI devices are added to this driver we will need to add ! 791: an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ ! 792: break; ! 793: } else { ! 794: /* If we can't find an FD scsi card we give up. */ ! 795: return 0; ! 796: } ! 797: } ! 798: } ! 799: ! 800: #if DEBUG_DETECT ! 801: printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n", ! 802: pci_bus, ! 803: (pci_dev_fn & 0xf8) >> 3, ! 804: pci_dev_fn & 7 ); ! 805: #endif ! 806: ! 807: /* We now have the appropriate device function for the FD board so we ! 808: just read the PCI config info from the registers. */ ! 809: ! 810: if ((error = pcibios_read_config_dword( pci_bus, ! 811: pci_dev_fn, ! 812: PCI_BASE_ADDRESS_0, ! 813: &pci_base )) ! 814: || (error = pcibios_read_config_byte( pci_bus, ! 815: pci_dev_fn, ! 816: PCI_INTERRUPT_LINE, ! 817: &pci_irq ))) { ! 818: printk ( "PCI ERROR: Future Domain 36C70 not initializing" ! 819: " due to error reading configuration space\n" ); ! 820: return 0; ! 821: } else { ! 822: #if DEBUG_DETECT ! 823: printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", ! 824: pci_irq, pci_base ); ! 825: #endif ! 826: ! 827: /* Now we have the I/O base address and interrupt from the PCI ! 828: configuration registers. Unfortunately it seems that the I/O base ! 829: address is off by one on my card so I mask it with 0xfff8. This ! 830: must be some kind of goof in the FD code that does the autoconfig ! 831: and writes to the PCI registers (or maybe I just don't understand ! 832: something). If they fix it in later versions of the card or BIOS ! 833: we may have to adjust the address based on the signature or ! 834: something... */ ! 835: ! 836: *irq = pci_irq; ! 837: *iobase = (pci_base & 0xfff8); ! 838: ! 839: #if DEBUG_DETECT ! 840: printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); ! 841: printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase ); ! 842: #endif ! 843: ! 844: if (!fdomain_is_valid_port( *iobase )) return 0; ! 845: return 1; ! 846: } ! 847: return 0; ! 848: } ! 849: #endif ! 850: ! 851: int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) ! 852: { ! 853: int i, j; ! 854: int retcode; ! 855: struct Scsi_Host *shpnt; ! 856: #if DO_DETECT ! 857: const int buflen = 255; ! 858: Scsi_Cmnd SCinit; ! 859: unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 }; ! 860: unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 }; ! 861: unsigned char do_read_capacity[] = { READ_CAPACITY, ! 862: 0, 0, 0, 0, 0, 0, 0, 0, 0 }; ! 863: unsigned char buf[buflen]; ! 864: #endif ! 865: ! 866: #if DEBUG_DETECT ! 867: printk( "fdomain_16x0_detect()," ); ! 868: #endif ! 869: tpnt->proc_dir = &proc_scsi_fdomain; ! 870: ! 871: if (setup_called) { ! 872: #if DEBUG_DETECT ! 873: printk( "no BIOS, using port_base = 0x%x, irq = %d\n", ! 874: port_base, interrupt_level ); ! 875: #endif ! 876: if (!fdomain_is_valid_port( port_base )) { ! 877: printk( "fdomain: cannot locate chip at port base 0x%x\n", ! 878: port_base ); ! 879: printk( "fdomain: bad LILO parameters?\n" ); ! 880: return 0; ! 881: } ! 882: } else { ! 883: int flag = 0; ! 884: ! 885: for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { ! 886: #if DEBUG_DETECT ! 887: printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base ); ! 888: #endif ! 889: for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { ! 890: if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset), ! 891: signatures[j].signature, signatures[j].sig_length )) { ! 892: bios_major = signatures[j].major_bios_version; ! 893: bios_minor = signatures[j].minor_bios_version; ! 894: PCI_bus = (signatures[j].flag == 1); ! 895: Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; ! 896: bios_base = addresses[i]; ! 897: } ! 898: } ! 899: } ! 900: ! 901: if (!bios_base) { ! 902: #if DEBUG_DETECT ! 903: printk( " FAILED: NO BIOS\n" ); ! 904: #endif ! 905: return 0; ! 906: } ! 907: ! 908: if (!PCI_bus) { ! 909: flag = fdomain_isa_detect( &interrupt_level, &port_base ); ! 910: } else { ! 911: #ifdef CONFIG_PCI ! 912: flag = fdomain_pci_bios_detect( &interrupt_level, &port_base ); ! 913: #else ! 914: flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base ); ! 915: #endif ! 916: } ! 917: ! 918: if (!flag) { ! 919: #if DEBUG_DETECT ! 920: printk( " FAILED: NO PORT\n" ); ! 921: #endif ! 922: #ifdef CONFIG_PCI ! 923: printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" ); ! 924: printk( "Send mail to [email protected].\n" ); ! 925: #endif ! 926: return 0; /* Cannot find valid set of ports */ ! 927: } ! 928: } ! 929: ! 930: SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl; ! 931: FIFO_Data_Count_port = port_base + FIFO_Data_Count; ! 932: Interrupt_Cntl_port = port_base + Interrupt_Cntl; ! 933: Interrupt_Status_port = port_base + Interrupt_Status; ! 934: Read_FIFO_port = port_base + Read_FIFO; ! 935: Read_SCSI_Data_port = port_base + Read_SCSI_Data; ! 936: SCSI_Cntl_port = port_base + SCSI_Cntl; ! 937: SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK; ! 938: SCSI_Status_port = port_base + SCSI_Status; ! 939: TMC_Cntl_port = port_base + TMC_Cntl; ! 940: TMC_Status_port = port_base + TMC_Status; ! 941: Write_FIFO_port = port_base + Write_FIFO; ! 942: Write_SCSI_Data_port = port_base + Write_SCSI_Data; ! 943: ! 944: fdomain_16x0_reset( NULL ); ! 945: ! 946: if (fdomain_test_loopback()) { ! 947: #if DEBUG_DETECT ! 948: printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" ); ! 949: #endif ! 950: if (setup_called) { ! 951: printk( "fdomain: loopback test failed at port base 0x%x\n", ! 952: port_base ); ! 953: printk( "fdomain: bad LILO parameters?\n" ); ! 954: } ! 955: return 0; ! 956: } ! 957: ! 958: if (this_id) { ! 959: tpnt->this_id = (this_id & 0x07); ! 960: adapter_mask = (1 << tpnt->this_id); ! 961: } else { ! 962: if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { ! 963: tpnt->this_id = 7; ! 964: adapter_mask = 0x80; ! 965: } else { ! 966: tpnt->this_id = 6; ! 967: adapter_mask = 0x40; ! 968: } ! 969: } ! 970: ! 971: /* Print out a banner here in case we can't ! 972: get resources. */ ! 973: ! 974: shpnt = scsi_register( tpnt, 0 ); ! 975: print_banner( shpnt ); ! 976: ! 977: /* Log IRQ with kernel */ ! 978: if (!interrupt_level) { ! 979: panic( "fdomain: *NO* interrupt level selected!\n" ); ! 980: } else { ! 981: /* Register the IRQ with the kernel */ ! 982: ! 983: retcode = request_irq( interrupt_level, ! 984: fdomain_16x0_intr, SA_INTERRUPT, "fdomain" ); ! 985: ! 986: if (retcode < 0) { ! 987: if (retcode == -EINVAL) { ! 988: printk( "fdomain: IRQ %d is bad!\n", interrupt_level ); ! 989: printk( " This shouldn't happen!\n" ); ! 990: printk( " Send mail to [email protected]\n" ); ! 991: } else if (retcode == -EBUSY) { ! 992: printk( "fdomain: IRQ %d is already in use!\n", interrupt_level ); ! 993: printk( " Please use another IRQ!\n" ); ! 994: } else { ! 995: printk( "fdomain: Error getting IRQ %d\n", interrupt_level ); ! 996: printk( " This shouldn't happen!\n" ); ! 997: printk( " Send mail to [email protected]\n" ); ! 998: } ! 999: panic( "fdomain: Driver requires interruptions\n" ); ! 1000: } ! 1001: } ! 1002: ! 1003: /* Log I/O ports with kernel */ ! 1004: request_region( port_base, 0x10, "fdomain" ); ! 1005: ! 1006: #if DO_DETECT ! 1007: ! 1008: /* These routines are here because of the way the SCSI bus behaves after ! 1009: a reset. This appropriate behavior was not handled correctly by the ! 1010: higher level SCSI routines when I first wrote this driver. Now, ! 1011: however, correct scan routines are part of scsi.c and these routines ! 1012: are no longer needed. However, this code is still good for ! 1013: debugging. */ ! 1014: ! 1015: SCinit.request_buffer = SCinit.buffer = buf; ! 1016: SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1; ! 1017: SCinit.use_sg = 0; ! 1018: SCinit.lun = 0; ! 1019: ! 1020: printk( "fdomain: detection routine scanning for devices:\n" ); ! 1021: for (i = 0; i < 8; i++) { ! 1022: SCinit.target = i; ! 1023: if (i == tpnt->this_id) /* Skip host adapter */ ! 1024: continue; ! 1025: memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); ! 1026: retcode = fdomain_16x0_command(&SCinit); ! 1027: if (!retcode) { ! 1028: memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry)); ! 1029: retcode = fdomain_16x0_command(&SCinit); ! 1030: if (!retcode) { ! 1031: printk( " SCSI ID %d: ", i ); ! 1032: for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++) ! 1033: printk( "%c", buf[j] >= 20 ? buf[j] : ' ' ); ! 1034: memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity)); ! 1035: retcode = fdomain_16x0_command(&SCinit); ! 1036: if (!retcode) { ! 1037: unsigned long blocks, size, capacity; ! 1038: ! 1039: blocks = (buf[0] << 24) | (buf[1] << 16) ! 1040: | (buf[2] << 8) | buf[3]; ! 1041: size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; ! 1042: capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L; ! 1043: ! 1044: printk( "%lu MB (%lu byte blocks)", ! 1045: ((capacity + 5L) / 10L), size ); ! 1046: } else { ! 1047: memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); ! 1048: retcode = fdomain_16x0_command(&SCinit); ! 1049: } ! 1050: printk ("\n" ); ! 1051: } else { ! 1052: memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); ! 1053: retcode = fdomain_16x0_command(&SCinit); ! 1054: } ! 1055: } ! 1056: } ! 1057: #endif ! 1058: ! 1059: return 1; /* Maximum of one adapter will be detected. */ ! 1060: } ! 1061: ! 1062: const char *fdomain_16x0_info( struct Scsi_Host *ignore ) ! 1063: { ! 1064: static char buffer[80]; ! 1065: char *pt; ! 1066: ! 1067: strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" ); ! 1068: if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */ ! 1069: strcat( buffer, strchr( VERSION, ':' ) + 1 ); ! 1070: pt = strrchr( buffer, '$') - 1; ! 1071: if (!pt) /* Stripped RCS Revision string? */ ! 1072: pt = buffer + strlen( buffer ) - 1; ! 1073: if (*pt != ' ') ! 1074: ++pt; ! 1075: *pt = '\0'; ! 1076: } else { /* Assume VERSION is a number */ ! 1077: strcat( buffer, " " VERSION ); ! 1078: } ! 1079: ! 1080: return buffer; ! 1081: } ! 1082: ! 1083: /* First pass at /proc information routine. */ ! 1084: /* ! 1085: * inout : decides on the direction of the dataflow and the meaning of the ! 1086: * variables ! 1087: * buffer: If inout==FALSE data is beeing written to it else read from it ! 1088: * *start: If inout==FALSE start of the valid data in the buffer ! 1089: * offset: If inout==FALSE offset from the beginning of the imaginary file ! 1090: * from which we start writing into the buffer ! 1091: * length: If inout==FALSE max number of bytes to be written into the buffer ! 1092: * else number of bytes in the buffer ! 1093: */ ! 1094: int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, ! 1095: int length, int hostno, int inout ) ! 1096: { ! 1097: const char *info = fdomain_16x0_info( NULL ); ! 1098: int len; ! 1099: int pos; ! 1100: int begin; ! 1101: ! 1102: if (inout) return(-ENOSYS); ! 1103: ! 1104: begin = 0; ! 1105: strcpy( buffer, info ); ! 1106: strcat( buffer, "\n" ); ! 1107: ! 1108: pos = len = strlen( buffer ); ! 1109: ! 1110: if(pos < offset) { ! 1111: len = 0; ! 1112: begin = pos; ! 1113: } ! 1114: ! 1115: *start = buffer + (offset - begin); /* Start of wanted data */ ! 1116: len -= (offset - begin); ! 1117: if(len > length) len = length; ! 1118: ! 1119: return(len); ! 1120: } ! 1121: ! 1122: #if 0 ! 1123: static int fdomain_arbitrate( void ) ! 1124: { ! 1125: int status = 0; ! 1126: unsigned long timeout; ! 1127: ! 1128: #if EVERY_ACCESS ! 1129: printk( "fdomain_arbitrate()\n" ); ! 1130: #endif ! 1131: ! 1132: outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ ! 1133: outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ ! 1134: outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ ! 1135: ! 1136: timeout = jiffies + 50; /* 500 mS */ ! 1137: while (jiffies < timeout) { ! 1138: status = inb( TMC_Status_port ); /* Read adapter status */ ! 1139: if (status & 0x02) /* Arbitration complete */ ! 1140: return 0; ! 1141: } ! 1142: ! 1143: /* Make bus idle */ ! 1144: fdomain_make_bus_idle(); ! 1145: ! 1146: #if EVERY_ACCESS ! 1147: printk( "Arbitration failed, status = %x\n", status ); ! 1148: #endif ! 1149: #if ERRORS_ONLY ! 1150: printk( "fdomain: Arbitration failed, status = %x\n", status ); ! 1151: #endif ! 1152: return 1; ! 1153: } ! 1154: #endif ! 1155: ! 1156: static int fdomain_select( int target ) ! 1157: { ! 1158: int status; ! 1159: unsigned long timeout; ! 1160: static int flag = 0; ! 1161: ! 1162: ! 1163: outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ ! 1164: outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); ! 1165: ! 1166: /* Stop arbitration and enable parity */ ! 1167: outb( PARITY_MASK, TMC_Cntl_port ); ! 1168: ! 1169: timeout = jiffies + 35; /* 350mS -- because of timeouts ! 1170: (was 250mS) */ ! 1171: ! 1172: while (jiffies < timeout) { ! 1173: status = inb( SCSI_Status_port ); /* Read adapter status */ ! 1174: if (status & 1) { /* Busy asserted */ ! 1175: /* Enable SCSI Bus (on error, should make bus idle with 0) */ ! 1176: outb( 0x80, SCSI_Cntl_port ); ! 1177: return 0; ! 1178: } ! 1179: } ! 1180: /* Make bus idle */ ! 1181: fdomain_make_bus_idle(); ! 1182: #if EVERY_ACCESS ! 1183: if (!target) printk( "Selection failed\n" ); ! 1184: #endif ! 1185: #if ERRORS_ONLY ! 1186: if (!target) { ! 1187: if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */ ! 1188: ++flag; ! 1189: else ! 1190: printk( "fdomain: Selection failed\n" ); ! 1191: } ! 1192: #endif ! 1193: return 1; ! 1194: } ! 1195: ! 1196: void my_done( int error ) ! 1197: { ! 1198: if (in_command) { ! 1199: in_command = 0; ! 1200: outb( 0x00, Interrupt_Cntl_port ); ! 1201: fdomain_make_bus_idle(); ! 1202: current_SC->result = error; ! 1203: if (current_SC->scsi_done) ! 1204: current_SC->scsi_done( current_SC ); ! 1205: else panic( "fdomain: current_SC->scsi_done() == NULL" ); ! 1206: } else { ! 1207: panic( "fdomain: my_done() called outside of command\n" ); ! 1208: } ! 1209: #if DEBUG_RACE ! 1210: in_interrupt_flag = 0; ! 1211: #endif ! 1212: } ! 1213: ! 1214: void fdomain_16x0_intr( int irq, struct pt_regs * regs ) ! 1215: { ! 1216: int status; ! 1217: int done = 0; ! 1218: unsigned data_count; ! 1219: ! 1220: /* The fdomain_16x0_intr is only called via ! 1221: the interrupt handler. The goal of the ! 1222: sti() here is to allow other ! 1223: interruptions while this routine is ! 1224: running. */ ! 1225: ! 1226: sti(); /* Yes, we really want sti() here */ ! 1227: ! 1228: outb( 0x00, Interrupt_Cntl_port ); ! 1229: ! 1230: /* We usually have one spurious interrupt after each command. Ignore it. */ ! 1231: if (!in_command || !current_SC) { /* Spurious interrupt */ ! 1232: #if EVERY_ACCESS ! 1233: printk( "Spurious interrupt, in_command = %d, current_SC = %x\n", ! 1234: in_command, current_SC ); ! 1235: #endif ! 1236: return; ! 1237: } ! 1238: ! 1239: /* Abort calls my_done, so we do nothing here. */ ! 1240: if (current_SC->SCp.phase & aborted) { ! 1241: #if DEBUG_ABORT ! 1242: printk( "Interrupt after abort, ignoring\n" ); ! 1243: #endif ! 1244: /* ! 1245: return; */ ! 1246: } ! 1247: ! 1248: #if DEBUG_RACE ! 1249: ++in_interrupt_flag; ! 1250: #endif ! 1251: ! 1252: if (current_SC->SCp.phase & in_arbitration) { ! 1253: status = inb( TMC_Status_port ); /* Read adapter status */ ! 1254: if (!(status & 0x02)) { ! 1255: #if EVERY_ACCESS ! 1256: printk( " AFAIL " ); ! 1257: #endif ! 1258: my_done( DID_BUS_BUSY << 16 ); ! 1259: return; ! 1260: } ! 1261: current_SC->SCp.phase = in_selection; ! 1262: ! 1263: outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port ); ! 1264: ! 1265: outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ ! 1266: outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port ); ! 1267: ! 1268: /* Stop arbitration and enable parity */ ! 1269: outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); ! 1270: #if DEBUG_RACE ! 1271: in_interrupt_flag = 0; ! 1272: #endif ! 1273: return; ! 1274: } else if (current_SC->SCp.phase & in_selection) { ! 1275: status = inb( SCSI_Status_port ); ! 1276: if (!(status & 0x01)) { ! 1277: /* Try again, for slow devices */ ! 1278: if (fdomain_select( current_SC->target )) { ! 1279: #if EVERY_ACCESS ! 1280: printk( " SFAIL " ); ! 1281: #endif ! 1282: my_done( DID_NO_CONNECT << 16 ); ! 1283: return; ! 1284: } else { ! 1285: #if EVERY_ACCESS ! 1286: printk( " AltSel " ); ! 1287: #endif ! 1288: /* Stop arbitration and enable parity */ ! 1289: outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); ! 1290: } ! 1291: } ! 1292: current_SC->SCp.phase = in_other; ! 1293: outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); ! 1294: outb( 0x80, SCSI_Cntl_port ); ! 1295: #if DEBUG_RACE ! 1296: in_interrupt_flag = 0; ! 1297: #endif ! 1298: return; ! 1299: } ! 1300: ! 1301: /* current_SC->SCp.phase == in_other: this is the body of the routine */ ! 1302: ! 1303: status = inb( SCSI_Status_port ); ! 1304: ! 1305: if (status & 0x10) { /* REQ */ ! 1306: ! 1307: switch (status & 0x0e) { ! 1308: ! 1309: case 0x08: /* COMMAND OUT */ ! 1310: outb( current_SC->cmnd[current_SC->SCp.sent_command++], ! 1311: Write_SCSI_Data_port ); ! 1312: #if EVERY_ACCESS ! 1313: printk( "CMD = %x,", ! 1314: current_SC->cmnd[ current_SC->SCp.sent_command - 1] ); ! 1315: #endif ! 1316: break; ! 1317: case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ ! 1318: if (chip != tmc1800 && !current_SC->SCp.have_data_in) { ! 1319: current_SC->SCp.have_data_in = -1; ! 1320: outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); ! 1321: } ! 1322: break; ! 1323: case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ ! 1324: if (chip != tmc1800 && !current_SC->SCp.have_data_in) { ! 1325: current_SC->SCp.have_data_in = 1; ! 1326: outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); ! 1327: } ! 1328: break; ! 1329: case 0x0c: /* STATUS IN */ ! 1330: current_SC->SCp.Status = inb( Read_SCSI_Data_port ); ! 1331: #if EVERY_ACCESS ! 1332: printk( "Status = %x, ", current_SC->SCp.Status ); ! 1333: #endif ! 1334: #if ERRORS_ONLY ! 1335: if (current_SC->SCp.Status && current_SC->SCp.Status != 2) { ! 1336: printk( "fdomain: target = %d, command = %x, status = %x\n", ! 1337: current_SC->target, ! 1338: current_SC->cmnd[0], ! 1339: current_SC->SCp.Status ); ! 1340: } ! 1341: #endif ! 1342: break; ! 1343: case 0x0a: /* MESSAGE OUT */ ! 1344: outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */ ! 1345: break; ! 1346: case 0x0e: /* MESSAGE IN */ ! 1347: current_SC->SCp.Message = inb( Read_SCSI_Data_port ); ! 1348: #if EVERY_ACCESS ! 1349: printk( "Message = %x, ", current_SC->SCp.Message ); ! 1350: #endif ! 1351: if (!current_SC->SCp.Message) ++done; ! 1352: #if DEBUG_MESSAGES || EVERY_ACCESS ! 1353: if (current_SC->SCp.Message) { ! 1354: printk( "fdomain: message = %x\n", current_SC->SCp.Message ); ! 1355: } ! 1356: #endif ! 1357: break; ! 1358: } ! 1359: } ! 1360: ! 1361: if (chip == tmc1800 ! 1362: && !current_SC->SCp.have_data_in ! 1363: && (current_SC->SCp.sent_command ! 1364: >= current_SC->cmd_len)) { ! 1365: /* We have to get the FIFO direction ! 1366: correct, so I've made a table based ! 1367: on the SCSI Standard of which commands ! 1368: appear to require a DATA OUT phase. ! 1369: */ ! 1370: /* ! 1371: p. 94: Command for all device types ! 1372: CHANGE DEFINITION 40 DATA OUT ! 1373: COMPARE 39 DATA OUT ! 1374: COPY 18 DATA OUT ! 1375: COPY AND VERIFY 3a DATA OUT ! 1376: INQUIRY 12 ! 1377: LOG SELECT 4c DATA OUT ! 1378: LOG SENSE 4d ! 1379: MODE SELECT (6) 15 DATA OUT ! 1380: MODE SELECT (10) 55 DATA OUT ! 1381: MODE SENSE (6) 1a ! 1382: MODE SENSE (10) 5a ! 1383: READ BUFFER 3c ! 1384: RECEIVE DIAGNOSTIC RESULTS 1c ! 1385: REQUEST SENSE 03 ! 1386: SEND DIAGNOSTIC 1d DATA OUT ! 1387: TEST UNIT READY 00 ! 1388: WRITE BUFFER 3b DATA OUT ! 1389: ! 1390: p.178: Commands for direct-access devices (not listed on p. 94) ! 1391: FORMAT UNIT 04 DATA OUT ! 1392: LOCK-UNLOCK CACHE 36 ! 1393: PRE-FETCH 34 ! 1394: PREVENT-ALLOW MEDIUM REMOVAL 1e ! 1395: READ (6)/RECEIVE 08 ! 1396: READ (10) 3c ! 1397: READ CAPACITY 25 ! 1398: READ DEFECT DATA (10) 37 ! 1399: READ LONG 3e ! 1400: REASSIGN BLOCKS 07 DATA OUT ! 1401: RELEASE 17 ! 1402: RESERVE 16 DATA OUT ! 1403: REZERO UNIT/REWIND 01 ! 1404: SEARCH DATA EQUAL (10) 31 DATA OUT ! 1405: SEARCH DATA HIGH (10) 30 DATA OUT ! 1406: SEARCH DATA LOW (10) 32 DATA OUT ! 1407: SEEK (6) 0b ! 1408: SEEK (10) 2b ! 1409: SET LIMITS (10) 33 ! 1410: START STOP UNIT 1b ! 1411: SYNCHRONIZE CACHE 35 ! 1412: VERIFY (10) 2f ! 1413: WRITE (6)/PRINT/SEND 0a DATA OUT ! 1414: WRITE (10)/SEND 2a DATA OUT ! 1415: WRITE AND VERIFY (10) 2e DATA OUT ! 1416: WRITE LONG 3f DATA OUT ! 1417: WRITE SAME 41 DATA OUT ? ! 1418: ! 1419: p. 261: Commands for sequential-access devices (not previously listed) ! 1420: ERASE 19 ! 1421: LOAD UNLOAD 1b ! 1422: LOCATE 2b ! 1423: READ BLOCK LIMITS 05 ! 1424: READ POSITION 34 ! 1425: READ REVERSE 0f ! 1426: RECOVER BUFFERED DATA 14 ! 1427: SPACE 11 ! 1428: WRITE FILEMARKS 10 ? ! 1429: ! 1430: p. 298: Commands for printer devices (not previously listed) ! 1431: ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) ***** ! 1432: SLEW AND PRINT 0b DATA OUT -- same as seek ! 1433: STOP PRINT 1b ! 1434: SYNCHRONIZE BUFFER 10 ! 1435: ! 1436: p. 315: Commands for processor devices (not previously listed) ! 1437: ! 1438: p. 321: Commands for write-once devices (not previously listed) ! 1439: MEDIUM SCAN 38 ! 1440: READ (12) a8 ! 1441: SEARCH DATA EQUAL (12) b1 DATA OUT ! 1442: SEARCH DATA HIGH (12) b0 DATA OUT ! 1443: SEARCH DATA LOW (12) b2 DATA OUT ! 1444: SET LIMITS (12) b3 ! 1445: VERIFY (12) af ! 1446: WRITE (12) aa DATA OUT ! 1447: WRITE AND VERIFY (12) ae DATA OUT ! 1448: ! 1449: p. 332: Commands for CD-ROM devices (not previously listed) ! 1450: PAUSE/RESUME 4b ! 1451: PLAY AUDIO (10) 45 ! 1452: PLAY AUDIO (12) a5 ! 1453: PLAY AUDIO MSF 47 ! 1454: PLAY TRACK RELATIVE (10) 49 ! 1455: PLAY TRACK RELATIVE (12) a9 ! 1456: READ HEADER 44 ! 1457: READ SUB-CHANNEL 42 ! 1458: READ TOC 43 ! 1459: ! 1460: p. 370: Commands for scanner devices (not previously listed) ! 1461: GET DATA BUFFER STATUS 34 ! 1462: GET WINDOW 25 ! 1463: OBJECT POSITION 31 ! 1464: SCAN 1b ! 1465: SET WINDOW 24 DATA OUT ! 1466: ! 1467: p. 391: Commands for optical memory devices (not listed) ! 1468: ERASE (10) 2c ! 1469: ERASE (12) ac ! 1470: MEDIUM SCAN 38 DATA OUT ! 1471: READ DEFECT DATA (12) b7 ! 1472: READ GENERATION 29 ! 1473: READ UPDATED BLOCK 2d ! 1474: UPDATE BLOCK 3d DATA OUT ! 1475: ! 1476: p. 419: Commands for medium changer devices (not listed) ! 1477: EXCHANGE MEDIUM 46 ! 1478: INITIALIZE ELEMENT STATUS 07 ! 1479: MOVE MEDIUM a5 ! 1480: POSITION TO ELEMENT 2b ! 1481: READ ELEMENT STATUS b8 ! 1482: REQUEST VOL. ELEMENT ADDRESS b5 ! 1483: SEND VOLUME TAG b6 DATA OUT ! 1484: ! 1485: p. 454: Commands for communications devices (not listed previously) ! 1486: GET MESSAGE (6) 08 ! 1487: GET MESSAGE (10) 28 ! 1488: GET MESSAGE (12) a8 ! 1489: */ ! 1490: ! 1491: switch (current_SC->cmnd[0]) { ! 1492: case CHANGE_DEFINITION: case COMPARE: case COPY: ! 1493: case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: ! 1494: case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: ! 1495: ! 1496: case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: ! 1497: case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: ! 1498: case WRITE_6: case WRITE_10: case WRITE_VERIFY: ! 1499: case 0x3f: case 0x41: ! 1500: ! 1501: case 0xb1: case 0xb0: case 0xb2: ! 1502: case 0xaa: case 0xae: ! 1503: ! 1504: case 0x24: ! 1505: ! 1506: case 0x38: case 0x3d: ! 1507: ! 1508: case 0xb6: ! 1509: ! 1510: case 0xea: /* alternate number for WRITE LONG */ ! 1511: ! 1512: current_SC->SCp.have_data_in = -1; ! 1513: outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); ! 1514: break; ! 1515: ! 1516: case 0x00: ! 1517: default: ! 1518: ! 1519: current_SC->SCp.have_data_in = 1; ! 1520: outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); ! 1521: break; ! 1522: } ! 1523: } ! 1524: ! 1525: if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ ! 1526: while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) { ! 1527: #if EVERY_ACCESS ! 1528: printk( "DC=%d, ", data_count ) ; ! 1529: #endif ! 1530: if (data_count > current_SC->SCp.this_residual) ! 1531: data_count = current_SC->SCp.this_residual; ! 1532: if (data_count > 0) { ! 1533: #if EVERY_ACCESS ! 1534: printk( "%d OUT, ", data_count ); ! 1535: #endif ! 1536: if (data_count == 1) { ! 1537: outb( *current_SC->SCp.ptr++, Write_FIFO_port ); ! 1538: --current_SC->SCp.this_residual; ! 1539: } else { ! 1540: data_count >>= 1; ! 1541: outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count ); ! 1542: current_SC->SCp.ptr += 2 * data_count; ! 1543: current_SC->SCp.this_residual -= 2 * data_count; ! 1544: } ! 1545: } ! 1546: if (!current_SC->SCp.this_residual) { ! 1547: if (current_SC->SCp.buffers_residual) { ! 1548: --current_SC->SCp.buffers_residual; ! 1549: ++current_SC->SCp.buffer; ! 1550: current_SC->SCp.ptr = current_SC->SCp.buffer->address; ! 1551: current_SC->SCp.this_residual = current_SC->SCp.buffer->length; ! 1552: } else ! 1553: break; ! 1554: } ! 1555: } ! 1556: } ! 1557: ! 1558: if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ ! 1559: while ((data_count = inw( FIFO_Data_Count_port )) > 0) { ! 1560: #if EVERY_ACCESS ! 1561: printk( "DC=%d, ", data_count ); ! 1562: #endif ! 1563: if (data_count > current_SC->SCp.this_residual) ! 1564: data_count = current_SC->SCp.this_residual; ! 1565: if (data_count) { ! 1566: #if EVERY_ACCESS ! 1567: printk( "%d IN, ", data_count ); ! 1568: #endif ! 1569: if (data_count == 1) { ! 1570: *current_SC->SCp.ptr++ = inb( Read_FIFO_port ); ! 1571: --current_SC->SCp.this_residual; ! 1572: } else { ! 1573: data_count >>= 1; /* Number of words */ ! 1574: insw( Read_FIFO_port, current_SC->SCp.ptr, data_count ); ! 1575: current_SC->SCp.ptr += 2 * data_count; ! 1576: current_SC->SCp.this_residual -= 2 * data_count; ! 1577: } ! 1578: } ! 1579: if (!current_SC->SCp.this_residual ! 1580: && current_SC->SCp.buffers_residual) { ! 1581: --current_SC->SCp.buffers_residual; ! 1582: ++current_SC->SCp.buffer; ! 1583: current_SC->SCp.ptr = current_SC->SCp.buffer->address; ! 1584: current_SC->SCp.this_residual = current_SC->SCp.buffer->length; ! 1585: } ! 1586: } ! 1587: } ! 1588: ! 1589: if (done) { ! 1590: #if EVERY_ACCESS ! 1591: printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in ); ! 1592: #endif ! 1593: ! 1594: #if ERRORS_ONLY ! 1595: if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { ! 1596: if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) { ! 1597: unsigned char key; ! 1598: unsigned char code; ! 1599: unsigned char qualifier; ! 1600: ! 1601: key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) ! 1602: & 0x0f; ! 1603: code = (unsigned char)(*((char *)current_SC->request_buffer + 12)); ! 1604: qualifier = (unsigned char)(*((char *)current_SC->request_buffer ! 1605: + 13)); ! 1606: ! 1607: if (!(key == UNIT_ATTENTION && (code == 0x29 || !code)) ! 1608: && !(key == NOT_READY ! 1609: && code == 0x04 ! 1610: && (!qualifier || qualifier == 0x02 || qualifier == 0x01)) ! 1611: && !(key == ILLEGAL_REQUEST && (code == 0x25 ! 1612: || code == 0x24 ! 1613: || !code))) ! 1614: ! 1615: printk( "fdomain: REQUEST SENSE " ! 1616: "Key = %x, Code = %x, Qualifier = %x\n", ! 1617: key, code, qualifier ); ! 1618: } ! 1619: } ! 1620: #endif ! 1621: #if EVERY_ACCESS ! 1622: printk( "BEFORE MY_DONE. . ." ); ! 1623: #endif ! 1624: my_done( (current_SC->SCp.Status & 0xff) ! 1625: | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) ); ! 1626: #if EVERY_ACCESS ! 1627: printk( "RETURNING.\n" ); ! 1628: #endif ! 1629: ! 1630: } else { ! 1631: if (current_SC->SCp.phase & disconnect) { ! 1632: outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port ); ! 1633: outb( 0x00, SCSI_Cntl_port ); ! 1634: } else { ! 1635: outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); ! 1636: } ! 1637: } ! 1638: #if DEBUG_RACE ! 1639: in_interrupt_flag = 0; ! 1640: #endif ! 1641: return; ! 1642: } ! 1643: ! 1644: int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) ! 1645: { ! 1646: if (in_command) { ! 1647: panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" ); ! 1648: } ! 1649: #if EVERY_ACCESS ! 1650: printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", ! 1651: SCpnt->target, ! 1652: *(unsigned char *)SCpnt->cmnd, ! 1653: SCpnt->use_sg, ! 1654: SCpnt->request_bufflen ); ! 1655: #endif ! 1656: ! 1657: fdomain_make_bus_idle(); ! 1658: ! 1659: current_SC = SCpnt; /* Save this for the done function */ ! 1660: current_SC->scsi_done = done; ! 1661: ! 1662: /* Initialize static data */ ! 1663: ! 1664: if (current_SC->use_sg) { ! 1665: current_SC->SCp.buffer = ! 1666: (struct scatterlist *)current_SC->request_buffer; ! 1667: current_SC->SCp.ptr = current_SC->SCp.buffer->address; ! 1668: current_SC->SCp.this_residual = current_SC->SCp.buffer->length; ! 1669: current_SC->SCp.buffers_residual = current_SC->use_sg - 1; ! 1670: } else { ! 1671: current_SC->SCp.ptr = (char *)current_SC->request_buffer; ! 1672: current_SC->SCp.this_residual = current_SC->request_bufflen; ! 1673: current_SC->SCp.buffer = NULL; ! 1674: current_SC->SCp.buffers_residual = 0; ! 1675: } ! 1676: ! 1677: ! 1678: current_SC->SCp.Status = 0; ! 1679: current_SC->SCp.Message = 0; ! 1680: current_SC->SCp.have_data_in = 0; ! 1681: current_SC->SCp.sent_command = 0; ! 1682: current_SC->SCp.phase = in_arbitration; ! 1683: ! 1684: /* Start arbitration */ ! 1685: outb( 0x00, Interrupt_Cntl_port ); ! 1686: outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ ! 1687: outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */ ! 1688: ++in_command; ! 1689: outb( 0x20, Interrupt_Cntl_port ); ! 1690: outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ ! 1691: ! 1692: return 0; ! 1693: } ! 1694: ! 1695: /* The following code, which simulates the old-style command function, was ! 1696: taken from Tommy Thorn's aha1542.c file. This code is Copyright (C) ! 1697: 1992 Tommy Thorn. */ ! 1698: ! 1699: static volatile int internal_done_flag = 0; ! 1700: static volatile int internal_done_errcode = 0; ! 1701: ! 1702: static void internal_done( Scsi_Cmnd *SCpnt ) ! 1703: { ! 1704: internal_done_errcode = SCpnt->result; ! 1705: ++internal_done_flag; ! 1706: } ! 1707: ! 1708: int fdomain_16x0_command( Scsi_Cmnd *SCpnt ) ! 1709: { ! 1710: fdomain_16x0_queue( SCpnt, internal_done ); ! 1711: ! 1712: while (!internal_done_flag) ! 1713: ; ! 1714: internal_done_flag = 0; ! 1715: return internal_done_errcode; ! 1716: } ! 1717: ! 1718: /* End of code derived from Tommy Thorn's work. */ ! 1719: ! 1720: void print_info( Scsi_Cmnd *SCpnt ) ! 1721: { ! 1722: unsigned int imr; ! 1723: unsigned int irr; ! 1724: unsigned int isr; ! 1725: ! 1726: if (!SCpnt || !SCpnt->host) { ! 1727: printk( "fdomain: cannot provide detailed information\n" ); ! 1728: } ! 1729: ! 1730: printk( "%s\n", fdomain_16x0_info( SCpnt->host ) ); ! 1731: print_banner( SCpnt->host ); ! 1732: switch (SCpnt->SCp.phase) { ! 1733: case in_arbitration: printk( "arbitration " ); break; ! 1734: case in_selection: printk( "selection " ); break; ! 1735: case in_other: printk( "other " ); break; ! 1736: default: printk( "unknown " ); break; ! 1737: } ! 1738: ! 1739: printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", ! 1740: SCpnt->SCp.phase, ! 1741: SCpnt->target, ! 1742: *(unsigned char *)SCpnt->cmnd, ! 1743: SCpnt->use_sg, ! 1744: SCpnt->request_bufflen ); ! 1745: printk( "sent_command = %d, have_data_in = %d, timeout = %d\n", ! 1746: SCpnt->SCp.sent_command, ! 1747: SCpnt->SCp.have_data_in, ! 1748: SCpnt->timeout ); ! 1749: #if DEBUG_RACE ! 1750: printk( "in_interrupt_flag = %d\n", in_interrupt_flag ); ! 1751: #endif ! 1752: ! 1753: imr = (inb( 0x0a1 ) << 8) + inb( 0x21 ); ! 1754: outb( 0x0a, 0xa0 ); ! 1755: irr = inb( 0xa0 ) << 8; ! 1756: outb( 0x0a, 0x20 ); ! 1757: irr += inb( 0x20 ); ! 1758: outb( 0x0b, 0xa0 ); ! 1759: isr = inb( 0xa0 ) << 8; ! 1760: outb( 0x0b, 0x20 ); ! 1761: isr += inb( 0x20 ); ! 1762: ! 1763: /* Print out interesting information */ ! 1764: printk( "IMR = 0x%04x", imr ); ! 1765: if (imr & (1 << interrupt_level)) ! 1766: printk( " (masked)" ); ! 1767: printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr ); ! 1768: ! 1769: printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) ); ! 1770: printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) ); ! 1771: if (inb( TMC_Status_port & 1)) ! 1772: printk( " (interrupt)" ); ! 1773: printk( "\n" ); ! 1774: printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) ); ! 1775: if (inb( Interrupt_Status_port ) & 0x08) ! 1776: printk( " (enabled)" ); ! 1777: printk( "\n" ); ! 1778: if (chip == tmc18c50 || chip == tmc18c30) { ! 1779: printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) ); ! 1780: printk( "Int. Condition = 0x%02x\n", ! 1781: inb( port_base + Interrupt_Cond ) ); ! 1782: } ! 1783: printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) ); ! 1784: if (chip == tmc18c50 || chip == tmc18c30) ! 1785: printk( "Configuration 2 = 0x%02x\n", ! 1786: inb( port_base + Configuration2 ) ); ! 1787: } ! 1788: ! 1789: int fdomain_16x0_abort( Scsi_Cmnd *SCpnt) ! 1790: { ! 1791: unsigned long flags; ! 1792: #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT ! 1793: printk( "fdomain: abort " ); ! 1794: #endif ! 1795: ! 1796: save_flags( flags ); ! 1797: cli(); ! 1798: if (!in_command) { ! 1799: #if EVERY_ACCESS || ERRORS_ONLY ! 1800: printk( " (not in command)\n" ); ! 1801: #endif ! 1802: restore_flags( flags ); ! 1803: return SCSI_ABORT_NOT_RUNNING; ! 1804: } else printk( "\n" ); ! 1805: ! 1806: #if DEBUG_ABORT ! 1807: print_info( SCpnt ); ! 1808: #endif ! 1809: ! 1810: fdomain_make_bus_idle(); ! 1811: ! 1812: current_SC->SCp.phase |= aborted; ! 1813: ! 1814: current_SC->result = DID_ABORT << 16; ! 1815: ! 1816: restore_flags( flags ); ! 1817: ! 1818: /* Aborts are not done well. . . */ ! 1819: my_done( DID_ABORT << 16 ); ! 1820: ! 1821: return SCSI_ABORT_SUCCESS; ! 1822: } ! 1823: ! 1824: int fdomain_16x0_reset( Scsi_Cmnd *SCpnt ) ! 1825: { ! 1826: #if DEBUG_RESET ! 1827: static int called_once = 0; ! 1828: #endif ! 1829: ! 1830: #if ERRORS_ONLY ! 1831: if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" ); ! 1832: #endif ! 1833: ! 1834: #if DEBUG_RESET ! 1835: if (called_once) print_info( current_SC ); ! 1836: called_once = 1; ! 1837: #endif ! 1838: ! 1839: outb( 1, SCSI_Cntl_port ); ! 1840: do_pause( 2 ); ! 1841: outb( 0, SCSI_Cntl_port ); ! 1842: do_pause( 115 ); ! 1843: outb( 0, SCSI_Mode_Cntl_port ); ! 1844: outb( PARITY_MASK, TMC_Cntl_port ); ! 1845: ! 1846: /* Unless this is the very first call (i.e., SCPnt == NULL), everything ! 1847: is probably hosed at this point. We will, however, try to keep ! 1848: things going by informing the high-level code that we need help. */ ! 1849: ! 1850: return SCSI_RESET_WAKEUP; ! 1851: } ! 1852: ! 1853: #include "sd.h" ! 1854: #include "scsi_ioctl.h" ! 1855: ! 1856: int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ) ! 1857: { ! 1858: int drive; ! 1859: unsigned char buf[512 + sizeof( int ) * 2]; ! 1860: int size = disk->capacity; ! 1861: int *sizes = (int *)buf; ! 1862: unsigned char *data = (unsigned char *)(sizes + 2); ! 1863: unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; ! 1864: int retcode; ! 1865: struct drive_info { ! 1866: unsigned short cylinders; ! 1867: unsigned char heads; ! 1868: unsigned char sectors; ! 1869: } *i; ! 1870: ! 1871: /* NOTES: ! 1872: The RAM area starts at 0x1f00 from the bios_base address. ! 1873: ! 1874: For BIOS Version 2.0: ! 1875: ! 1876: The drive parameter table seems to start at 0x1f30. ! 1877: The first byte's purpose is not known. ! 1878: Next is the cylinder, head, and sector information. ! 1879: The last 4 bytes appear to be the drive's size in sectors. ! 1880: The other bytes in the drive parameter table are unknown. ! 1881: If anyone figures them out, please send me mail, and I will ! 1882: update these notes. ! 1883: ! 1884: Tape drives do not get placed in this table. ! 1885: ! 1886: There is another table at 0x1fea: ! 1887: If the byte is 0x01, then the SCSI ID is not in use. ! 1888: If the byte is 0x18 or 0x48, then the SCSI ID is in use, ! 1889: although tapes don't seem to be in this table. I haven't ! 1890: seen any other numbers (in a limited sample). ! 1891: ! 1892: 0x1f2d is a drive count (i.e., not including tapes) ! 1893: ! 1894: The table at 0x1fcc are I/O ports addresses for the various ! 1895: operations. I calculate these by hand in this driver code. ! 1896: ! 1897: ! 1898: ! 1899: For the ISA-200S version of BIOS Version 2.0: ! 1900: ! 1901: The drive parameter table starts at 0x1f33. ! 1902: ! 1903: WARNING: Assume that the table entry is 25 bytes long. Someone needs ! 1904: to check this for the Quantum ISA-200S card. ! 1905: ! 1906: ! 1907: ! 1908: For BIOS Version 3.2: ! 1909: ! 1910: The drive parameter table starts at 0x1f70. Each entry is ! 1911: 0x0a bytes long. Heads are one less than we need to report. ! 1912: */ ! 1913: ! 1914: drive = MINOR(dev) / 16; ! 1915: ! 1916: if (bios_major == 2) { ! 1917: switch (Quantum) { ! 1918: case 2: /* ISA_200S */ ! 1919: /* The value of 25 has never been verified. ! 1920: It should probably be 15. */ ! 1921: i = (struct drive_info *)( (char *)bios_base + 0x1f33 + drive * 25 ); ! 1922: break; ! 1923: case 3: /* ISA_250MG */ ! 1924: i = (struct drive_info *)( (char *)bios_base + 0x1f36 + drive * 15 ); ! 1925: break; ! 1926: case 4: /* ISA_200S (another one) */ ! 1927: i = (struct drive_info *)( (char *)bios_base + 0x1f34 + drive * 15 ); ! 1928: break; ! 1929: default: ! 1930: i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 ); ! 1931: break; ! 1932: } ! 1933: info_array[0] = i->heads; ! 1934: info_array[1] = i->sectors; ! 1935: info_array[2] = i->cylinders; ! 1936: } else if (bios_major == 3 ! 1937: && bios_minor >= 0 ! 1938: && bios_minor < 4) { /* 3.0 and 3.2 BIOS */ ! 1939: i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 ); ! 1940: info_array[0] = i->heads + 1; ! 1941: info_array[1] = i->sectors; ! 1942: info_array[2] = i->cylinders; ! 1943: } else { /* 3.4 BIOS (and up?) */ ! 1944: /* This algorithm was provided by Future Domain (much thanks!). */ ! 1945: ! 1946: sizes[0] = 0; /* zero bytes out */ ! 1947: sizes[1] = 512; /* one sector in */ ! 1948: memcpy( data, do_read, sizeof( do_read ) ); ! 1949: retcode = kernel_scsi_ioctl( disk->device, ! 1950: SCSI_IOCTL_SEND_COMMAND, ! 1951: (void *)buf ); ! 1952: if (!retcode /* SCSI command ok */ ! 1953: && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ ! 1954: && data[0x1c2]) { /* Partition type */ ! 1955: ! 1956: /* The partition table layout is as follows: ! 1957: ! 1958: Start: 0x1b3h ! 1959: Offset: 0 = partition status ! 1960: 1 = starting head ! 1961: 2 = starting sector and cylinder (word, encoded) ! 1962: 4 = partition type ! 1963: 5 = ending head ! 1964: 6 = ending sector and cylinder (word, encoded) ! 1965: 8 = starting absolute sector (double word) ! 1966: c = number of sectors (double word) ! 1967: Signature: 0x1fe = 0x55aa ! 1968: ! 1969: So, this algorithm assumes: ! 1970: 1) the first partition table is in use, ! 1971: 2) the data in the first entry is correct, and ! 1972: 3) partitions never divide cylinders ! 1973: ! 1974: Note that (1) may be FALSE for NetBSD (and other BSD flavors), ! 1975: as well as for Linux. Note also, that Linux doesn't pay any ! 1976: attention to the fields that are used by this algorithm -- it ! 1977: only uses the absolute sector data. Recent versions of Linux's ! 1978: fdisk(1) will fill this data in correctly, and forthcoming ! 1979: versions will check for consistency. ! 1980: ! 1981: Checking for a non-zero partition type is not part of the ! 1982: Future Domain algorithm, but it seemed to be a reasonable thing ! 1983: to do, especially in the Linux and BSD worlds. */ ! 1984: ! 1985: info_array[0] = data[0x1c3] + 1; /* heads */ ! 1986: info_array[1] = data[0x1c4] & 0x3f; /* sectors */ ! 1987: } else { ! 1988: ! 1989: /* Note that this new method guarantees that there will always be ! 1990: less than 1024 cylinders on a platter. This is good for drives ! 1991: up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */ ! 1992: ! 1993: if ((unsigned int)size >= 0x7e0000U) { ! 1994: info_array[0] = 0xff; /* heads = 255 */ ! 1995: info_array[1] = 0x3f; /* sectors = 63 */ ! 1996: } else if ((unsigned int)size >= 0x200000U) { ! 1997: info_array[0] = 0x80; /* heads = 128 */ ! 1998: info_array[1] = 0x3f; /* sectors = 63 */ ! 1999: } else { ! 2000: info_array[0] = 0x40; /* heads = 64 */ ! 2001: info_array[1] = 0x20; /* sectors = 32 */ ! 2002: } ! 2003: } ! 2004: /* For both methods, compute the cylinders */ ! 2005: info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] ); ! 2006: } ! 2007: ! 2008: return 0; ! 2009: } ! 2010: ! 2011: #ifdef MODULE ! 2012: /* Eventually this will go into an include file, but this will be later */ ! 2013: Scsi_Host_Template driver_template = FDOMAIN_16X0; ! 2014: ! 2015: #include "scsi_module.c" ! 2016: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.