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