1 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver 2 * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu 3 * Revised: Thu Feb 8 08:21:33 1996 by r.faith@ieee.org 4 * Author: Rickard E. Faith, faith@cs.unc.edu 5 * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith 6 * 7 * $Id: fdomain.c,v 5.39 1995/10/12 20:31:47 root 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 (drew@cs.colorado.edu) and Eric 80 Youngdale (ericy@cais.com), 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 (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken 119 Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari 120 Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad 121 Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com). 122
123 Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), 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 (dnewman@crl.com) for providing initial patches for 128 the version 3.4 BIOS. 129
130 Thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) 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 (tigger@petroglyph.cl.msu.edu) for providing the 135 patch for the version 3.5 BIOS. 136
137 Thanks for Stephen Henson (shenson@nyx10.cs.du.edu) 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 (andrewm@ccfadm.eeg.ccf.org) for the signature to some 142 random TMC-1680 repackaged by IBM; and to Mintak Ng (mintak@panix.com) for 143 the version 3.61 BIOS siganture. 144
145 Thanks for Mark Singer (elf@netcom.com) and Richard Simpson 146 (rsimpson@ewrcsdra.demon.co.uk) for more Quantum signatures and detective 147 work on the Quantum RAM layout. 148
149 Special thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) 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 (tec@usa1.com) 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 #ifdefPCMCIA 196 #defineMODULE 197 #endif 198
199 #ifdefMODULE 200 #include <linux/module.h>
201 #endif 202
203 #ifdefPCMCIA 204 #undefMODULE 205 #endif 206
207 #include <linux/sched.h>
208 #include <asm/io.h>
209 #include <linux/blk.h>
210 #include "scsi.h"
211 #include "hosts.h"
212 #include "fdomain.h"
213 #include <asm/system.h>
214 #include <linux/errno.h>
215 #include <linux/string.h>
216 #include <linux/ioport.h>
217 #include <linux/proc_fs.h>
218 #include <linux/bios32.h>
219 #include <linux/pci.h>
220 #include <linux/stat.h>
221
222 #include <linux/config.h> /* for CONFIG_PCI */ 223
224 structproc_dir_entryproc_scsi_fdomain = { 225 PROC_SCSI_FDOMAIN, 7, "fdomain",
226 S_IFDIR | S_IRUGO | S_IXUGO, 2
227 };
228
229 #defineVERSION "$Revision: 5.39 $"
230
231 /* START OF USER DEFINABLE OPTIONS */ 232
233 #defineDEBUG 1 /* Enable debugging output */ 234 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 235 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 236 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 237
238 /* END OF USER DEFINABLE OPTIONS */ 239
240 #ifDEBUG 241 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 242 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 243 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 244 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 245 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 246 #defineDEBUG_RESET 1 /* Debug reset() routine */ 247 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 248 #else 249 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 250 #defineERRORS_ONLY 0
251 #defineDEBUG_DETECT 0
252 #defineDEBUG_MESSAGES 0
253 #defineDEBUG_ABORT 0
254 #defineDEBUG_RESET 0
255 #defineDEBUG_RACE 0
256 #endif 257
258 /* Errors are reported on the line, so we don't need to report them again */ 259 #ifEVERY_ACCESS 260 #undefERRORS_ONLY 261 #defineERRORS_ONLY 0
262 #endif 263
264 #ifENABLE_PARITY 265 #definePARITY_MASK 0x08
266 #else 267 #definePARITY_MASK 0x00
268 #endif 269
270 enumchip_type{ 271 unknown = 0x00,
272 tmc1800 = 0x01,
273 tmc18c50 = 0x02,
274 tmc18c30 = 0x03,
275 };
276
277 enum{ 278 in_arbitration = 0x02,
279 in_selection = 0x04,
280 in_other = 0x08,
281 disconnect = 0x10,
282 aborted = 0x20,
283 sent_ident = 0x40,
284 };
285
286 enum in_port_type { 287 Read_SCSI_Data = 0,
288 SCSI_Status = 1,
289 TMC_Status = 2,
290 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 291 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 292 LSB_ID_Code = 5,
293 MSB_ID_Code = 6,
294 Read_Loopback = 7,
295 SCSI_Data_NoACK = 8,
296 Interrupt_Status = 9,
297 Configuration1 = 10,
298 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 299 Read_FIFO = 12,
300 FIFO_Data_Count = 14
301 };
302
303 enum out_port_type { 304 Write_SCSI_Data = 0,
305 SCSI_Cntl = 1,
306 Interrupt_Cntl = 2,
307 SCSI_Mode_Cntl = 3,
308 TMC_Cntl = 4,
309 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 310 Write_Loopback = 7,
311 IO_Control = 11, /* tmc18c30 only */ 312 Write_FIFO = 12
313 };
314
315 staticintport_base = 0;
316 staticvoid *bios_base = NULL;
317 staticintbios_major = 0;
318 staticintbios_minor = 0;
319 staticintPCI_bus = 0;
320 staticintQuantum = 0; /* Quantum board variant */ 321 staticintinterrupt_level = 0;
322 staticvolatileintin_command = 0;
323 staticScsi_Cmnd *current_SC = NULL;
324 staticenumchip_typechip = unknown;
325 staticintadapter_mask = 0;
326 staticintthis_id = 0;
327 staticintsetup_called = 0;
328
329 #ifDEBUG_RACE 330 staticvolatileintin_interrupt_flag = 0;
331 #endif 332
333 staticintSCSI_Mode_Cntl_port;
334 staticintFIFO_Data_Count_port;
335 staticintInterrupt_Cntl_port;
336 staticintInterrupt_Status_port;
337 staticintRead_FIFO_port;
338 staticintRead_SCSI_Data_port;
339 staticintSCSI_Cntl_port;
340 staticintSCSI_Data_NoACK_port;
341 staticintSCSI_Status_port;
342 staticintTMC_Cntl_port;
343 staticintTMC_Status_port;
344 staticintWrite_FIFO_port;
345 staticintWrite_SCSI_Data_port;
346
347 staticintFIFO_Size = 0x2000; /* 8k FIFO for 348 pre-tmc18c30 chips */ 349
350 externvoidfdomain_16x0_intr( intirq, void *dev_id, structpt_regs * regs );
351
352 staticvoid *addresses[] = { 353 (void *)0xc8000,
354 (void *)0xca000,
355 (void *)0xce000,
356 (void *)0xde000,
357 (void *)0xcc000, /* Extra addresses for PCI boards */ 358 (void *)0xd0000,
359 (void *)0xe0000,
360 };
361 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
362
363 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
364 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
365
366 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
367
368 /* 369
370 READ THIS BEFORE YOU ADD A SIGNATURE! 371
372 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 373
374 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 375
376 This driver works *ONLY* for Future Domain cards using the TMC-1800, 377 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 378 and 1680. 379
380 The following BIOS signature signatures are for boards which do *NOT* 381 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 382 Seagate driver): 383
384 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 385 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 386 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 387 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 388 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 389 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 390 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 391
392 */ 393
394 structsignature{ 395 constchar *signature;
396 intsig_offset;
397 intsig_length;
398 intmajor_bios_version;
399 intminor_bios_version;
400 intflag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ 401 }signatures[] = { 402 /* 1 2 3 4 5 6 */ 403 /* 123456789012345678901234567890123456789012345678901234567890 */ 404 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
405 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
406 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
407 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
408 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
409 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
410 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
411 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
412 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
413 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
414 { "Adaptec AHA-2920 PCI-SCSI Card", 42, 31, 3, 0, 1 },
415 /* This next signature may not be a 3.5 bios */ 416 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
417 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
418 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
419 { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 },
420 { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 },
421 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
422
423 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE 424 Also, fix the disk geometry code for your signature and send your 425 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 426 signatures! 427
428 Note that the last line will match a "generic" 18XX bios. Because 429 Future Domain has changed the host SCSI ID and/or the location of the 430 geometry information in the on-board RAM area for each of the first 431 three BIOS's, it is still important to enter a fully qualified 432 signature in the table for any new BIOS's (after the host SCSI ID and 433 geometry location are verified). */ 434 };
435
436 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
437
438 staticvoidprint_banner( structScsi_Host *shpnt )
439 { 440 if (!shpnt) return; /* This won't ever happen */ 441
442 if (bios_major < 0 && bios_minor < 0) { 443 printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n",
444 shpnt->host_no, shpnt->this_id );
445 }else{ 446 printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
447
448 if (bios_major >= 0) printk( "%d.", bios_major );
449 elseprintk( "?." );
450
451 if (bios_minor >= 0) printk( "%d", bios_minor );
452 elseprintk( "?." );
453
454 printk( " at 0x%x using scsi id %d\n",
455 (unsigned)bios_base, shpnt->this_id );
456 } 457
458 /* If this driver works for later FD PCI 459 boards, we will have to modify banner 460 for additional PCI cards, but for now if 461 it's PCI it's a TMC-3260 - JTM */ 462 printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
463 shpnt->host_no,
464 chip == tmc1800 ? "TMC-1800"
465 : (chip == tmc18c50 ? "TMC-18C50"
466 : (chip == tmc18c30 ?
467 (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30")
468 : "Unknown")),
469 port_base );
470
471 if (interrupt_level) printk( "%d", interrupt_level );
472 elseprintk( "<none>" );
473
474 printk( "\n" );
475 } 476
477 voidfdomain_setup( char *str, int *ints )
/* */ 478 { 479 if (setup_called++ || ints[0] < 2 || ints[0] > 3) { 480 printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
481 printk( "fdomain: bad LILO parameters?\n" );
482 } 483
484 port_base = ints[0] >= 1 ? ints[1] : 0;
485 interrupt_level = ints[0] >= 2 ? ints[2] : 0;
486 this_id = ints[0] >= 3 ? ints[3] : 0;
487
488 bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ 489 } 490
491
492 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 493 { 494 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 495
496 while (jiffies < the_time);
497 } 498
499 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 500 { 501 outb( 0, SCSI_Cntl_port );
502 outb( 0, SCSI_Mode_Cntl_port );
503 if (chip == tmc18c50 || chip == tmc18c30)
504 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 505 else 506 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
507 } 508
509 staticintfdomain_is_valid_port( intport )
/* */ 510 { 511 #ifDEBUG_DETECT 512 printk( " (%x%x),",
513 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
514 #endif 515
516 /* The MCA ID is a unique id for each MCA compatible board. We 517 are using ISA boards, but Future Domain provides the MCA ID 518 anyway. We can use this ID to ensure that this is a Future 519 Domain TMC-1660/TMC-1680. 520 */ 521
522 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 523 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
524 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
525 chip = tmc1800;
526 }else{/* test for 0xe960 id */ 527 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
528 chip = tmc18c50;
529
530 #if 0
531
532 /* Try to toggle 32-bit mode. This only 533 works on an 18c30 chip. (User reports 534 say that this doesn't work at all, so 535 we'll use the other method.) */ 536
537 outb( 0x80, port + IO_Control );
538 if ((inb( port + Configuration2 ) & 0x80) == 0x80) { 539 outb( 0x00, port + IO_Control );
540 if ((inb( port + Configuration2 ) & 0x80) == 0x00) { 541 chip = tmc18c30;
542 FIFO_Size = 0x800; /* 2k FIFO */ 543 } 544 } 545 #else 546
547 /* That should have worked, but appears to 548 have problems. Lets assume it is an 549 18c30 if the RAM is disabled. */ 550
551 if (inb( port + Configuration2 ) & 0x02) { 552 chip = tmc18c30;
553 FIFO_Size = 0x800; /* 2k FIFO */ 554 } 555 #endif 556 /* If that failed, we are an 18c50. */ 557 } 558
559 return 1;
560 } 561
562 staticintfdomain_test_loopback( void )
/* */ 563 { 564 inti;
565 intresult;
566
567 for (i = 0; i < 255; i++) { 568 outb( i, port_base + Write_Loopback );
569 result = inb( port_base + Read_Loopback );
570 if (i != result)
571 return 1;
572 } 573 return 0;
574 } 575
576 /* fdomain_get_irq assumes that we have a valid MCA ID for a 577 TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the 578 bios_base matches these ports. If someone was unlucky enough to have 579 purchased more than one Future Domain board, then they will have to 580 modify this code, as we only detect one board here. [The one with the 581 lowest bios_base.] 582
583 Note that this routine is only used for systems without a PCI BIOS32 584 (e.g., ISA bus). For PCI bus systems, this routine will likely fail 585 unless one of the IRQs listed in the ints array is used by the board. 586 Sometimes it is possible to use the computer's BIOS setup screen to 587 configure a PCI system so that one of these IRQs will be used by the 588 Future Domain card. */ 589
590 staticintfdomain_get_irq( intbase )
/* */ 591 { 592 intoptions = inb( base + Configuration1 );
593
594 #ifDEBUG_DETECT 595 printk( " Options = %x\n", options );
596 #endif 597
598 /* Check for board with lowest bios_base -- 599 this isn't valid for the 18c30 or for 600 boards on the PCI bus, so just assume we 601 have the right board. */ 602
603 if (chip != tmc18c30 604 && !PCI_bus 605 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
606
607 returnints[ (options & 0x0e) >> 1 ];
608 } 609
610 staticintfdomain_isa_detect( int *irq, int *iobase )
/* */ 611 { 612 inti;
613 intbase;
614 intflag = 0;
615
616 if (bios_major == 2) { 617 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 618 Assuming the ROM is enabled (otherwise we wouldn't have been 619 able to read the ROM signature :-), then the ROM sets up the 620 RAM area with some magic numbers, such as a list of port 621 base addresses and a list of the disk "geometry" reported to 622 DOS (this geometry has nothing to do with physical geometry). 623 */ 624
625 switch (Quantum) { 626 case 2: /* ISA_200S */ 627 case 3: /* ISA_250MG */ 628 base = *((char *)bios_base + 0x1fa2)
629 + (*((char *)bios_base + 0x1fa3) << 8);
630 break;
631 case 4: /* ISA_200S (another one) */ 632 base = *((char *)bios_base + 0x1fa3)
633 + (*((char *)bios_base + 0x1fa4) << 8);
634 break;
635 default:
636 base = *((char *)bios_base + 0x1fcc)
637 + (*((char *)bios_base + 0x1fcd) << 8);
638 break;
639 } 640
641 #ifDEBUG_DETECT 642 printk( " %x,", base );
643 #endif 644
645 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 646 if (base == ports[i])
647 ++flag;
648 } 649
650 if (flag && fdomain_is_valid_port( base )) { 651 *irq = fdomain_get_irq( base );
652 *iobase = base;
653 return 1;
654 } 655
656 /* This is a bad sign. It usually means that someone patched the 657 BIOS signature list (the signatures variable) to contain a BIOS 658 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ 659
660 #ifDEBUG_DETECT 661 printk( " RAM FAILED, " );
662 #endif 663 } 664
665 /* Anyway, the alternative to finding the address in the RAM is to just 666 search through every possible port address for one that is attached 667 to the Future Domain card. Don't panic, though, about reading all 668 these random port addresses -- there are rumors that the Future 669 Domain BIOS does something very similar. 670
671 Do not, however, check ports which the kernel knows are being used by 672 another driver. */ 673
674 for (i = 0; i < PORT_COUNT; i++) { 675 base = ports[i];
676 if (check_region( base, 0x10 )) { 677 #ifDEBUG_DETECT 678 printk( " (%x inuse),", base );
679 #endif 680 continue;
681 } 682 #ifDEBUG_DETECT 683 printk( " %x,", base );
684 #endif 685 if ((flag = fdomain_is_valid_port( base ))) break;
686 } 687
688 if (!flag) return 0; /* iobase not found */ 689
690 *irq = fdomain_get_irq( base );
691 *iobase = base;
692
693 return 1; /* success */ 694 } 695
696 staticintfdomain_pci_nobios_detect( int *irq, int *iobase )
/* */ 697 { 698 inti;
699 intflag = 0;
700
701 /* The proper way of doing this is to use ask the PCI bus for the device 702 IRQ and interrupt level. But we can't do that if PCI BIOS32 support 703 isn't compiled into the kernel, or if a PCI BIOS32 isn't present. 704
705 Instead, we scan down a bunch of addresses (Future Domain tech 706 support says we will probably find the address before we get to 707 0xf800). This works fine on some systems -- other systems may have 708 to scan more addresses. If you have to modify this section for your 709 installation, please send mail to faith@cs.unc.edu. */ 710
711 for (i = 0xfff8; i > 0xe000; i -= 8) { 712 if (check_region( i, 0x10 )) { 713 #ifDEBUG_DETECT 714 printk( " (%x inuse)," , i );
715 #endif 716 continue;
717 } 718 if ((flag = fdomain_is_valid_port( i ))) break;
719 } 720
721 if (!flag) return 0; /* iobase not found */ 722
723 *irq = fdomain_get_irq( i );
724 *iobase = i;
725
726 return 1; /* success */ 727 } 728
729 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* 730 iobase) This function gets the Interrupt Level and I/O base address from 731 the PCI configuration registers. The I/O base address is masked with 732 0xfff8 since on my card the address read from the PCI config registers 733 is off by one from the actual I/O base address necessary for accessing 734 the status and control registers on the card (PCI config register gives 735 0xf801, actual address is 0xf800). This is likely a bug in the FD 736 config code that writes to the PCI registers, however using a mask 737 should be safe since I think the scan done by the card to determine the 738 I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at 739 least the old scan code we used to use to get the I/O base did... Also, 740 the device ID from the PCI config registers is 0x0 and should be 0x60e9 741 as it is in the status registers (offset 5 from I/O base). If this is 742 changed in future hardware/BIOS changes it will need to be fixed in this 743 detection function. Comments, bug reports, etc... on this function 744 should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ 745
746 #ifdefCONFIG_PCI 747 staticintfdomain_pci_bios_detect( int *irq, int *iobase )
/* */ 748 { 749 interror;
750 unsignedcharpci_bus, pci_dev_fn; /* PCI bus & device function */ 751 unsignedcharpci_irq; /* PCI interrupt line */ 752 unsignedintpci_base; /* PCI I/O base address */ 753 unsignedshortpci_vendor, pci_device; /* PCI vendor & device IDs */ 754
755 /* If the PCI BIOS doesn't exist, use the old-style detection routines. 756 Otherwise, get the I/O base address and interrupt from the PCI config 757 registers. */ 758
759 if (!pcibios_present()) returnfdomain_pci_nobios_detect( irq, iobase );
760
761 #ifDEBUG_DETECT 762 /* Tell how to print a list of the known PCI devices from bios32 and 763 list vendor and device IDs being used if in debug mode. */ 764
765 printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
766 printk( "\nTMC-3260 detect:"
767 " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
768 PCI_VENDOR_ID_FD,
769 PCI_DEVICE_ID_FD_36C70 );
770 #endif 771
772 /* We will have to change this if more than 1 PCI bus is present and the 773 FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, 774 which is not supported by bios32 right now anyway). This should 775 probably be done by a call to pcibios_find_device but I can't get it 776 to work... Also the device ID reported from the PCI config registers 777 does not match the device ID quoted in the tech manual or available 778 from offset 5 from the I/O base address. It should be 0x60E9, but it 779 is 0x0 if read from the PCI config registers. I guess the FD folks 780 neglected to write it to the PCI registers... This loop is necessary 781 to get the device function (at least until someone can get 782 pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ 783
784 pci_bus = 0;
785
786 for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { 787 pcibios_read_config_word( pci_bus,
788 pci_dev_fn,
789 PCI_VENDOR_ID,
790 &pci_vendor );
791
792 if (pci_vendor == PCI_VENDOR_ID_FD) { 793 pcibios_read_config_word( pci_bus,
794 pci_dev_fn,
795 PCI_DEVICE_ID,
796 &pci_device );
797
798 if (pci_device == PCI_DEVICE_ID_FD_36C70) { 799 /* Break out once we have the correct device. If other FD 800 PCI devices are added to this driver we will need to add 801 an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ 802 break;
803 }else{ 804 /* If we can't find an FD scsi card we give up. */ 805 return 0;
806 } 807 } 808 } 809
810 #ifDEBUG_DETECT 811 printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
812 pci_bus,
813 (pci_dev_fn & 0xf8) >> 3,
814 pci_dev_fn & 7 );
815 #endif 816
817 /* We now have the appropriate device function for the FD board so we 818 just read the PCI config info from the registers. */ 819
820 if ((error = pcibios_read_config_dword( pci_bus,
821 pci_dev_fn,
822 PCI_BASE_ADDRESS_0,
823 &pci_base ))
824 || (error = pcibios_read_config_byte( pci_bus,
825 pci_dev_fn,
826 PCI_INTERRUPT_LINE,
827 &pci_irq ))) { 828 printk ( "PCI ERROR: Future Domain 36C70 not initializing"
829 " due to error reading configuration space\n" );
830 return 0;
831 }else{ 832 #ifDEBUG_DETECT 833 printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
834 pci_irq, pci_base );
835 #endif 836
837 /* Now we have the I/O base address and interrupt from the PCI 838 configuration registers. Unfortunately it seems that the I/O base 839 address is off by one on my card so I mask it with 0xfff8. This 840 must be some kind of goof in the FD code that does the autoconfig 841 and writes to the PCI registers (or maybe I just don't understand 842 something). If they fix it in later versions of the card or BIOS 843 we may have to adjust the address based on the signature or 844 something... */ 845
846 *irq = pci_irq;
847 *iobase = (pci_base & 0xfff8);
848
849 #ifDEBUG_DETECT 850 printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
851 printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
852 #endif 853
854 if (!fdomain_is_valid_port( *iobase )) return 0;
855 return 1;
856 } 857 return 0;
858 } 859 #endif 860
861 intfdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* */ 862 { 863 inti, j;
864 intretcode;
865 structScsi_Host *shpnt;
866 #ifDO_DETECT 867 constintbuflen = 255;
868 Scsi_CmndSCinit;
869 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
870 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
871 unsignedchardo_read_capacity[] = {READ_CAPACITY,
872 0, 0, 0, 0, 0, 0, 0, 0, 0 };
873 unsignedcharbuf[buflen];
874 #endif 875
876 #ifDEBUG_DETECT 877 printk( "fdomain_16x0_detect()," );
878 #endif 879 tpnt->proc_dir = &proc_scsi_fdomain;
880
881 if (setup_called) { 882 #ifDEBUG_DETECT 883 printk( "no BIOS, using port_base = 0x%x, irq = %d\n",
884 port_base, interrupt_level );
885 #endif 886 if (!fdomain_is_valid_port( port_base )) { 887 printk( "fdomain: cannot locate chip at port base 0x%x\n",
888 port_base );
889 printk( "fdomain: bad LILO parameters?\n" );
890 return 0;
891 } 892 }else{ 893 intflag = 0;
894
895 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 896 #ifDEBUG_DETECT 897 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
898 #endif 899 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 900 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
901 signatures[j].signature, signatures[j].sig_length )) { 902 bios_major = signatures[j].major_bios_version;
903 bios_minor = signatures[j].minor_bios_version;
904 PCI_bus = (signatures[j].flag == 1);
905 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
906 bios_base = addresses[i];
907 } 908 } 909 } 910
911 if (!bios_base) { 912 #ifDEBUG_DETECT 913 printk( " FAILED: NO BIOS\n" );
914 #endif 915 return 0;
916 } 917
918 if (!PCI_bus) { 919 flag = fdomain_isa_detect( &interrupt_level, &port_base );
920 }else{ 921 #ifdefCONFIG_PCI 922 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
923 #else 924 flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
925 #endif 926 } 927
928 if (!flag) { 929 #ifDEBUG_DETECT 930 printk( " FAILED: NO PORT\n" );
931 #endif 932 #ifdefCONFIG_PCI 933 printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
934 printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" );
935 #endif 936 return 0; /* Cannot find valid set of ports */ 937 } 938 } 939
940 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
941 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
942 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
943 Interrupt_Status_port = port_base + Interrupt_Status;
944 Read_FIFO_port = port_base + Read_FIFO;
945 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
946 SCSI_Cntl_port = port_base + SCSI_Cntl;
947 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
948 SCSI_Status_port = port_base + SCSI_Status;
949 TMC_Cntl_port = port_base + TMC_Cntl;
950 TMC_Status_port = port_base + TMC_Status;
951 Write_FIFO_port = port_base + Write_FIFO;
952 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
953
954 fdomain_16x0_reset( NULL );
955
956 if (fdomain_test_loopback()) { 957 #ifDEBUG_DETECT 958 printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
959 #endif 960 if (setup_called) { 961 printk( "fdomain: loopback test failed at port base 0x%x\n",
962 port_base );
963 printk( "fdomain: bad LILO parameters?\n" );
964 } 965 return 0;
966 } 967
968 if (this_id) { 969 tpnt->this_id = (this_id & 0x07);
970 adapter_mask = (1 << tpnt->this_id);
971 }else{ 972 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 973 tpnt->this_id = 7;
974 adapter_mask = 0x80;
975 }else{ 976 tpnt->this_id = 6;
977 adapter_mask = 0x40;
978 } 979 } 980
981 /* Print out a banner here in case we can't 982 get resources. */ 983
984 shpnt = scsi_register( tpnt, 0 );
985 shpnt->irq = interrupt_level;
986 shpnt->io_port = port_base;
987 shpnt->n_io_port = 0x10;
988 print_banner( shpnt );
989
990 /* Log IRQ with kernel */ 991 if (!interrupt_level) { 992 panic( "fdomain: *NO* interrupt level selected!\n" );
993 }else{ 994 /* Register the IRQ with the kernel */ 995
996 retcode = request_irq( interrupt_level,
997 fdomain_16x0_intr, SA_INTERRUPT, "fdomain", NULL);
998
999 if (retcode < 0) {1000 if (retcode == -EINVAL) {1001 printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
1002 printk( " This shouldn't happen!\n" );
1003 printk( " Send mail to faith@cs.unc.edu\n" );
1004 }elseif (retcode == -EBUSY) {1005 printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
1006 printk( " Please use another IRQ!\n" );
1007 }else{1008 printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
1009 printk( " This shouldn't happen!\n" );
1010 printk( " Send mail to faith@cs.unc.edu\n" );
1011 }1012 panic( "fdomain: Driver requires interruptions\n" );
1013 }1014 }1015
1016 /* Log I/O ports with kernel */1017 request_region( port_base, 0x10, "fdomain" );
1018
1019 #ifDO_DETECT1020
1021 /* These routines are here because of the way the SCSI bus behaves after1022 a reset. This appropriate behavior was not handled correctly by the1023 higher level SCSI routines when I first wrote this driver. Now,1024 however, correct scan routines are part of scsi.c and these routines1025 are no longer needed. However, this code is still good for1026 debugging. */1027
1028 SCinit.request_buffer = SCinit.buffer = buf;
1029 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
1030 SCinit.use_sg = 0;
1031 SCinit.lun = 0;
1032
1033 printk( "fdomain: detection routine scanning for devices:\n" );
1034 for (i = 0; i < 8; i++) {1035 SCinit.target = i;
1036 if (i == tpnt->this_id) /* Skip host adapter */1037 continue;
1038 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1039 retcode = fdomain_16x0_command(&SCinit);
1040 if (!retcode) {1041 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
1042 retcode = fdomain_16x0_command(&SCinit);
1043 if (!retcode) {1044 printk( " SCSI ID %d: ", i );
1045 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
1046 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
1047 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
1048 retcode = fdomain_16x0_command(&SCinit);
1049 if (!retcode) {1050 unsignedlongblocks, size, capacity;
1051
1052 blocks = (buf[0] << 24) | (buf[1] << 16)
1053 | (buf[2] << 8) | buf[3];
1054 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
1055 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
1056
1057 printk( "%lu MB (%lu byte blocks)",
1058 ((capacity + 5L) / 10L), size );
1059 }else{1060 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1061 retcode = fdomain_16x0_command(&SCinit);
1062 }1063 printk ("\n" );
1064 }else{1065 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1066 retcode = fdomain_16x0_command(&SCinit);
1067 }1068 }1069 }1070 #endif1071
1072 return 1; /* Maximum of one adapter will be detected. */1073 }1074
1075 constchar *fdomain_16x0_info( structScsi_Host *ignore )
/* */1076 {1077 staticcharbuffer[80];
1078 char *pt;
1079
1080 strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
1081 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */1082 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1083 pt = strrchr( buffer, '$') - 1;
1084 if (!pt) /* Stripped RCS Revision string? */1085 pt = buffer + strlen( buffer ) - 1;
1086 if (*pt != ' ')
1087 ++pt;
1088 *pt = '\0';
1089 }else{/* Assume VERSION is a number */1090 strcat( buffer, " " VERSION );
1091 }1092
1093 returnbuffer;
1094 }1095
1096 /* First pass at /proc information routine. */1097 /*1098 * inout : decides on the direction of the dataflow and the meaning of the 1099 * variables1100 * buffer: If inout==FALSE data is beeing written to it else read from it1101 * *start: If inout==FALSE start of the valid data in the buffer1102 * offset: If inout==FALSE offset from the beginning of the imaginary file 1103 * from which we start writing into the buffer1104 * length: If inout==FALSE max number of bytes to be written into the buffer 1105 * else number of bytes in the buffer1106 */1107 intfdomain_16x0_proc_info( char *buffer, char **start, off_toffset,
/* */1108 intlength, inthostno, intinout )
1109 {1110 constchar *info = fdomain_16x0_info( NULL );
1111 intlen;
1112 intpos;
1113 intbegin;
1114
1115 if (inout) return(-ENOSYS);
1116
1117 begin = 0;
1118 strcpy( buffer, info );
1119 strcat( buffer, "\n" );
1120
1121 pos = len = strlen( buffer );
1122
1123 if(pos < offset) {1124 len = 0;
1125 begin = pos;
1126 }1127
1128 *start = buffer + (offset - begin); /* Start of wanted data */1129 len -= (offset - begin);
1130 if(len > length) len = length;
1131
1132 return(len);
1133 }1134
1135 #if 0
1136 staticint fdomain_arbitrate( void )
/* */1137 {1138 intstatus = 0;
1139 unsignedlongtimeout;
1140
1141 #ifEVERY_ACCESS1142 printk( "fdomain_arbitrate()\n" );
1143 #endif1144
1145 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1146 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */1147 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1148
1149 timeout = jiffies + 50; /* 500 mS */1150 while (jiffies < timeout) {1151 status = inb( TMC_Status_port ); /* Read adapter status */1152 if (status & 0x02) /* Arbitration complete */1153 return 0;
1154 }1155
1156 /* Make bus idle */1157 fdomain_make_bus_idle();
1158
1159 #ifEVERY_ACCESS1160 printk( "Arbitration failed, status = %x\n", status );
1161 #endif1162 #ifERRORS_ONLY1163 printk( "fdomain: Arbitration failed, status = %x\n", status );
1164 #endif1165 return 1;
1166 }1167 #endif1168
1169 staticintfdomain_select( inttarget )
/* */1170 {1171 intstatus;
1172 unsignedlongtimeout;
1173 staticintflag = 0;
1174
1175
1176 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1177 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
1178
1179 /* Stop arbitration and enable parity */1180 outb( PARITY_MASK, TMC_Cntl_port );
1181
1182 timeout = jiffies + 35; /* 350mS -- because of timeouts1183 (was 250mS) */1184
1185 while (jiffies < timeout) {1186 status = inb( SCSI_Status_port ); /* Read adapter status */1187 if (status & 1) {/* Busy asserted */1188 /* Enable SCSI Bus (on error, should make bus idle with 0) */1189 outb( 0x80, SCSI_Cntl_port );
1190 return 0;
1191 }1192 }1193 /* Make bus idle */1194 fdomain_make_bus_idle();
1195 #ifEVERY_ACCESS1196 if (!target) printk( "Selection failed\n" );
1197 #endif1198 #ifERRORS_ONLY1199 if (!target) {1200 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */1201 ++flag;
1202 else1203 printk( "fdomain: Selection failed\n" );
1204 }1205 #endif1206 return 1;
1207 }1208
1209 voidmy_done( interror )
/* */1210 {1211 if (in_command) {1212 in_command = 0;
1213 outb( 0x00, Interrupt_Cntl_port );
1214 fdomain_make_bus_idle();
1215 current_SC->result = error;
1216 if (current_SC->scsi_done)
1217 current_SC->scsi_done( current_SC );
1218 elsepanic( "fdomain: current_SC->scsi_done() == NULL" );
1219 }else{1220 panic( "fdomain: my_done() called outside of command\n" );
1221 }1222 #ifDEBUG_RACE1223 in_interrupt_flag = 0;
1224 #endif1225 }1226
1227 voidfdomain_16x0_intr( intirq, void *dev_id, structpt_regs * regs )
/* */1228 {1229 intstatus;
1230 intdone = 0;
1231 unsigneddata_count;
1232
1233 /* The fdomain_16x0_intr is only called via1234 the interrupt handler. The goal of the1235 sti() here is to allow other1236 interruptions while this routine is1237 running. */1238
1239 sti(); /* Yes, we really want sti() here */1240
1241 outb( 0x00, Interrupt_Cntl_port );
1242
1243 /* We usually have one spurious interrupt after each command. Ignore it. */1244 if (!in_command || !current_SC) {/* Spurious interrupt */1245 #ifEVERY_ACCESS1246 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1247 in_command, current_SC );
1248 #endif1249 return;
1250 }1251
1252 /* Abort calls my_done, so we do nothing here. */1253 if (current_SC->SCp.phase & aborted) {1254 #ifDEBUG_ABORT1255 printk( "Interrupt after abort, ignoring\n" );
1256 #endif1257 /*1258 return; */1259 }1260
1261 #ifDEBUG_RACE1262 ++in_interrupt_flag;
1263 #endif1264
1265 if (current_SC->SCp.phase & in_arbitration) {1266 status = inb( TMC_Status_port ); /* Read adapter status */1267 if (!(status & 0x02)) {1268 #ifEVERY_ACCESS1269 printk( " AFAIL " );
1270 #endif1271 my_done( DID_BUS_BUSY << 16 );
1272 return;
1273 }1274 current_SC->SCp.phase = in_selection;
1275
1276 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
1277
1278 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1279 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
1280
1281 /* Stop arbitration and enable parity */1282 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1283 #ifDEBUG_RACE1284 in_interrupt_flag = 0;
1285 #endif1286 return;
1287 }elseif (current_SC->SCp.phase & in_selection) {1288 status = inb( SCSI_Status_port );
1289 if (!(status & 0x01)) {1290 /* Try again, for slow devices */1291 if (fdomain_select( current_SC->target )) {1292 #ifEVERY_ACCESS1293 printk( " SFAIL " );
1294 #endif1295 my_done( DID_NO_CONNECT << 16 );
1296 return;
1297 }else{1298 #ifEVERY_ACCESS1299 printk( " AltSel " );
1300 #endif1301 /* Stop arbitration and enable parity */1302 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1303 }1304 }1305 current_SC->SCp.phase = in_other;
1306 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1307 outb( 0x80, SCSI_Cntl_port );
1308 #ifDEBUG_RACE1309 in_interrupt_flag = 0;
1310 #endif1311 return;
1312 }1313
1314 /* current_SC->SCp.phase == in_other: this is the body of the routine */1315
1316 status = inb( SCSI_Status_port );
1317
1318 if (status & 0x10) {/* REQ */1319
1320 switch (status & 0x0e) {1321
1322 case 0x08: /* COMMAND OUT */1323 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
1324 Write_SCSI_Data_port );
1325 #ifEVERY_ACCESS1326 printk( "CMD = %x,",
1327 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1328 #endif1329 break;
1330 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */1331 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1332 current_SC->SCp.have_data_in = -1;
1333 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1334 }1335 break;
1336 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */1337 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1338 current_SC->SCp.have_data_in = 1;
1339 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1340 }1341 break;
1342 case 0x0c: /* STATUS IN */1343 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
1344 #ifEVERY_ACCESS1345 printk( "Status = %x, ", current_SC->SCp.Status );
1346 #endif1347 #ifERRORS_ONLY1348 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {1349 printk( "fdomain: target = %d, command = %x, status = %x\n",
1350 current_SC->target,
1351 current_SC->cmnd[0],
1352 current_SC->SCp.Status );
1353 }1354 #endif1355 break;
1356 case 0x0a: /* MESSAGE OUT */1357 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */1358 break;
1359 case 0x0e: /* MESSAGE IN */1360 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1361 #ifEVERY_ACCESS1362 printk( "Message = %x, ", current_SC->SCp.Message );
1363 #endif1364 if (!current_SC->SCp.Message) ++done;
1365 #ifDEBUG_MESSAGES || EVERY_ACCESS1366 if (current_SC->SCp.Message) {1367 printk( "fdomain: message = %x\n", current_SC->SCp.Message );
1368 }1369 #endif1370 break;
1371 }1372 }1373
1374 if (chip == tmc18001375 && !current_SC->SCp.have_data_in1376 && (current_SC->SCp.sent_command1377 >= current_SC->cmd_len)) {1378 /* We have to get the FIFO direction1379 correct, so I've made a table based1380 on the SCSI Standard of which commands1381 appear to require a DATA OUT phase.1382 */1383 /*1384 p. 94: Command for all device types1385 CHANGE DEFINITION 40 DATA OUT1386 COMPARE 39 DATA OUT1387 COPY 18 DATA OUT1388 COPY AND VERIFY 3a DATA OUT1389 INQUIRY 12 1390 LOG SELECT 4c DATA OUT1391 LOG SENSE 4d1392 MODE SELECT (6) 15 DATA OUT1393 MODE SELECT (10) 55 DATA OUT1394 MODE SENSE (6) 1a1395 MODE SENSE (10) 5a1396 READ BUFFER 3c1397 RECEIVE DIAGNOSTIC RESULTS 1c1398 REQUEST SENSE 031399 SEND DIAGNOSTIC 1d DATA OUT1400 TEST UNIT READY 001401 WRITE BUFFER 3b DATA OUT1402
1403 p.178: Commands for direct-access devices (not listed on p. 94)1404 FORMAT UNIT 04 DATA OUT1405 LOCK-UNLOCK CACHE 361406 PRE-FETCH 341407 PREVENT-ALLOW MEDIUM REMOVAL 1e1408 READ (6)/RECEIVE 081409 READ (10) 3c1410 READ CAPACITY 251411 READ DEFECT DATA (10) 371412 READ LONG 3e1413 REASSIGN BLOCKS 07 DATA OUT1414 RELEASE 171415 RESERVE 16 DATA OUT1416 REZERO UNIT/REWIND 011417 SEARCH DATA EQUAL (10) 31 DATA OUT1418 SEARCH DATA HIGH (10) 30 DATA OUT1419 SEARCH DATA LOW (10) 32 DATA OUT1420 SEEK (6) 0b1421 SEEK (10) 2b1422 SET LIMITS (10) 331423 START STOP UNIT 1b1424 SYNCHRONIZE CACHE 351425 VERIFY (10) 2f1426 WRITE (6)/PRINT/SEND 0a DATA OUT1427 WRITE (10)/SEND 2a DATA OUT1428 WRITE AND VERIFY (10) 2e DATA OUT1429 WRITE LONG 3f DATA OUT1430 WRITE SAME 41 DATA OUT ?1431
1432 p. 261: Commands for sequential-access devices (not previously listed)1433 ERASE 191434 LOAD UNLOAD 1b1435 LOCATE 2b1436 READ BLOCK LIMITS 051437 READ POSITION 341438 READ REVERSE 0f1439 RECOVER BUFFERED DATA 141440 SPACE 111441 WRITE FILEMARKS 10 ?1442
1443 p. 298: Commands for printer devices (not previously listed)1444 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1445 SLEW AND PRINT 0b DATA OUT -- same as seek1446 STOP PRINT 1b1447 SYNCHRONIZE BUFFER 101448
1449 p. 315: Commands for processor devices (not previously listed)1450 1451 p. 321: Commands for write-once devices (not previously listed)1452 MEDIUM SCAN 381453 READ (12) a81454 SEARCH DATA EQUAL (12) b1 DATA OUT1455 SEARCH DATA HIGH (12) b0 DATA OUT1456 SEARCH DATA LOW (12) b2 DATA OUT1457 SET LIMITS (12) b31458 VERIFY (12) af1459 WRITE (12) aa DATA OUT1460 WRITE AND VERIFY (12) ae DATA OUT1461
1462 p. 332: Commands for CD-ROM devices (not previously listed)1463 PAUSE/RESUME 4b1464 PLAY AUDIO (10) 451465 PLAY AUDIO (12) a51466 PLAY AUDIO MSF 471467 PLAY TRACK RELATIVE (10) 491468 PLAY TRACK RELATIVE (12) a91469 READ HEADER 441470 READ SUB-CHANNEL 421471 READ TOC 431472
1473 p. 370: Commands for scanner devices (not previously listed)1474 GET DATA BUFFER STATUS 341475 GET WINDOW 251476 OBJECT POSITION 311477 SCAN 1b1478 SET WINDOW 24 DATA OUT1479
1480 p. 391: Commands for optical memory devices (not listed)1481 ERASE (10) 2c1482 ERASE (12) ac1483 MEDIUM SCAN 38 DATA OUT1484 READ DEFECT DATA (12) b71485 READ GENERATION 291486 READ UPDATED BLOCK 2d1487 UPDATE BLOCK 3d DATA OUT1488
1489 p. 419: Commands for medium changer devices (not listed)1490 EXCHANGE MEDIUM 461491 INITIALIZE ELEMENT STATUS 071492 MOVE MEDIUM a51493 POSITION TO ELEMENT 2b1494 READ ELEMENT STATUS b81495 REQUEST VOL. ELEMENT ADDRESS b51496 SEND VOLUME TAG b6 DATA OUT1497
1498 p. 454: Commands for communications devices (not listed previously)1499 GET MESSAGE (6) 081500 GET MESSAGE (10) 281501 GET MESSAGE (12) a81502 */1503
1504 switch (current_SC->cmnd[0]) {1505 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1506 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1507 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1508
1509 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1510 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1511 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1512 case 0x3f: case 0x41:
1513
1514 case 0xb1: case 0xb0: case 0xb2:
1515 case 0xaa: case 0xae:
1516
1517 case 0x24:
1518
1519 case 0x38: case 0x3d:
1520
1521 case 0xb6:
1522
1523 case 0xea: /* alternate number for WRITE LONG */1524
1525 current_SC->SCp.have_data_in = -1;
1526 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1527 break;
1528
1529 case 0x00:
1530 default:
1531
1532 current_SC->SCp.have_data_in = 1;
1533 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1534 break;
1535 }1536 }1537
1538 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1539 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1540 #ifEVERY_ACCESS1541 printk( "DC=%d, ", data_count ) ;
1542 #endif1543 if (data_count > current_SC->SCp.this_residual)
1544 data_count = current_SC->SCp.this_residual;
1545 if (data_count > 0) {1546 #ifEVERY_ACCESS1547 printk( "%d OUT, ", data_count );
1548 #endif1549 if (data_count == 1) {1550 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1551 --current_SC->SCp.this_residual;
1552 }else{1553 data_count >>= 1;
1554 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1555 current_SC->SCp.ptr += 2 * data_count;
1556 current_SC->SCp.this_residual -= 2 * data_count;
1557 }1558 }1559 if (!current_SC->SCp.this_residual) {1560 if (current_SC->SCp.buffers_residual) {1561 --current_SC->SCp.buffers_residual;
1562 ++current_SC->SCp.buffer;
1563 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1564 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1565 }else1566 break;
1567 }1568 }1569 }1570
1571 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1572 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1573 #ifEVERY_ACCESS1574 printk( "DC=%d, ", data_count );
1575 #endif1576 if (data_count > current_SC->SCp.this_residual)
1577 data_count = current_SC->SCp.this_residual;
1578 if (data_count) {1579 #ifEVERY_ACCESS1580 printk( "%d IN, ", data_count );
1581 #endif1582 if (data_count == 1) {1583 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1584 --current_SC->SCp.this_residual;
1585 }else{1586 data_count >>= 1; /* Number of words */1587 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1588 current_SC->SCp.ptr += 2 * data_count;
1589 current_SC->SCp.this_residual -= 2 * data_count;
1590 }1591 }1592 if (!current_SC->SCp.this_residual1593 && current_SC->SCp.buffers_residual) {1594 --current_SC->SCp.buffers_residual;
1595 ++current_SC->SCp.buffer;
1596 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1597 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1598 }1599 }1600 }1601
1602 if (done) {1603 #ifEVERY_ACCESS1604 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1605 #endif1606
1607 #ifERRORS_ONLY1608 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1609 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1610 unsignedcharkey;
1611 unsignedcharcode;
1612 unsignedcharqualifier;
1613
1614 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1615 & 0x0f;
1616 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1617 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1618 + 13));
1619
1620 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1621 && !(key == NOT_READY1622 && code == 0x04
1623 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1624 && !(key == ILLEGAL_REQUEST && (code == 0x25
1625 || code == 0x24
1626 || !code)))
1627
1628 printk( "fdomain: REQUEST SENSE "
1629 "Key = %x, Code = %x, Qualifier = %x\n",
1630 key, code, qualifier );
1631 }1632 }1633 #endif1634 #ifEVERY_ACCESS1635 printk( "BEFORE MY_DONE. . ." );
1636 #endif1637 my_done( (current_SC->SCp.Status & 0xff)
1638 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1639 #ifEVERY_ACCESS1640 printk( "RETURNING.\n" );
1641 #endif1642
1643 }else{1644 if (current_SC->SCp.phase & disconnect) {1645 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1646 outb( 0x00, SCSI_Cntl_port );
1647 }else{1648 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1649 }1650 }1651 #ifDEBUG_RACE1652 in_interrupt_flag = 0;
1653 #endif1654 return;
1655 }1656
1657 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1658 {1659 if (in_command) {1660 panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1661 }1662 #ifEVERY_ACCESS1663 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1664 SCpnt->target,
1665 *(unsignedchar *)SCpnt->cmnd,
1666 SCpnt->use_sg,
1667 SCpnt->request_bufflen );
1668 #endif1669
1670 fdomain_make_bus_idle();
1671
1672 current_SC = SCpnt; /* Save this for the done function */1673 current_SC->scsi_done = done;
1674
1675 /* Initialize static data */1676
1677 if (current_SC->use_sg) {1678 current_SC->SCp.buffer =
1679 (structscatterlist *)current_SC->request_buffer;
1680 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1681 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1682 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1683 }else{1684 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1685 current_SC->SCp.this_residual = current_SC->request_bufflen;
1686 current_SC->SCp.buffer = NULL;
1687 current_SC->SCp.buffers_residual = 0;
1688 }1689
1690
1691 current_SC->SCp.Status = 0;
1692 current_SC->SCp.Message = 0;
1693 current_SC->SCp.have_data_in = 0;
1694 current_SC->SCp.sent_command = 0;
1695 current_SC->SCp.phase = in_arbitration;
1696
1697 /* Start arbitration */1698 outb( 0x00, Interrupt_Cntl_port );
1699 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1700 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1701 ++in_command;
1702 outb( 0x20, Interrupt_Cntl_port );
1703 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1704
1705 return 0;
1706 }1707
1708 /* The following code, which simulates the old-style command function, was1709 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1710 1992 Tommy Thorn. */1711
1712 staticvolatileintinternal_done_flag = 0;
1713 staticvolatileintinternal_done_errcode = 0;
1714
1715 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1716 {1717 internal_done_errcode = SCpnt->result;
1718 ++internal_done_flag;
1719 }1720
1721 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1722 {1723 fdomain_16x0_queue( SCpnt, internal_done );
1724
1725 while (!internal_done_flag)
1726 ;
1727 internal_done_flag = 0;
1728 returninternal_done_errcode;
1729 }1730
1731 /* End of code derived from Tommy Thorn's work. */1732
1733 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1734 {1735 unsignedintimr;
1736 unsignedintirr;
1737 unsignedintisr;
1738
1739 if (!SCpnt || !SCpnt->host) {1740 printk( "fdomain: cannot provide detailed information\n" );
1741 }1742
1743 printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
1744 print_banner( SCpnt->host );
1745 switch (SCpnt->SCp.phase) {1746 casein_arbitration: printk( "arbitration " ); break;
1747 casein_selection: printk( "selection " ); break;
1748 casein_other: printk( "other " ); break;
1749 default: printk( "unknown " ); break;
1750 }1751
1752 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1753 SCpnt->SCp.phase,
1754 SCpnt->target,
1755 *(unsignedchar *)SCpnt->cmnd,
1756 SCpnt->use_sg,
1757 SCpnt->request_bufflen );
1758 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1759 SCpnt->SCp.sent_command,
1760 SCpnt->SCp.have_data_in,
1761 SCpnt->timeout );
1762 #ifDEBUG_RACE1763 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1764 #endif1765
1766 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1767 outb( 0x0a, 0xa0 );
1768 irr = inb( 0xa0 ) << 8;
1769 outb( 0x0a, 0x20 );
1770 irr += inb( 0x20 );
1771 outb( 0x0b, 0xa0 );
1772 isr = inb( 0xa0 ) << 8;
1773 outb( 0x0b, 0x20 );
1774 isr += inb( 0x20 );
1775
1776 /* Print out interesting information */1777 printk( "IMR = 0x%04x", imr );
1778 if (imr & (1 << interrupt_level))
1779 printk( " (masked)" );
1780 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1781
1782 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1783 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1784 if (inb( TMC_Status_port & 1))
1785 printk( " (interrupt)" );
1786 printk( "\n" );
1787 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1788 if (inb( Interrupt_Status_port ) & 0x08)
1789 printk( " (enabled)" );
1790 printk( "\n" );
1791 if (chip == tmc18c50 || chip == tmc18c30) {1792 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1793 printk( "Int. Condition = 0x%02x\n",
1794 inb( port_base + Interrupt_Cond ) );
1795 }1796 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1797 if (chip == tmc18c50 || chip == tmc18c30)
1798 printk( "Configuration 2 = 0x%02x\n",
1799 inb( port_base + Configuration2 ) );
1800 }1801
1802 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1803 {1804 unsignedlongflags;
1805 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1806 printk( "fdomain: abort " );
1807 #endif1808
1809 save_flags( flags );
1810 cli();
1811 if (!in_command) {1812 #ifEVERY_ACCESS || ERRORS_ONLY1813 printk( " (not in command)\n" );
1814 #endif1815 restore_flags( flags );
1816 returnSCSI_ABORT_NOT_RUNNING;
1817 }elseprintk( "\n" );
1818
1819 #ifDEBUG_ABORT1820 print_info( SCpnt );
1821 #endif1822
1823 fdomain_make_bus_idle();
1824
1825 current_SC->SCp.phase |= aborted;
1826
1827 current_SC->result = DID_ABORT << 16;
1828
1829 restore_flags( flags );
1830
1831 /* Aborts are not done well. . . */1832 my_done( DID_ABORT << 16 );
1833
1834 returnSCSI_ABORT_SUCCESS;
1835 }1836
1837 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1838 {1839 #ifDEBUG_RESET1840 staticintcalled_once = 0;
1841 #endif1842
1843 #ifERRORS_ONLY1844 if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
1845 #endif1846
1847 #ifDEBUG_RESET1848 if (called_once) print_info( current_SC );
1849 called_once = 1;
1850 #endif1851
1852 outb( 1, SCSI_Cntl_port );
1853 do_pause( 2 );
1854 outb( 0, SCSI_Cntl_port );
1855 do_pause( 115 );
1856 outb( 0, SCSI_Mode_Cntl_port );
1857 outb( PARITY_MASK, TMC_Cntl_port );
1858
1859 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1860 is probably hosed at this point. We will, however, try to keep1861 things going by informing the high-level code that we need help. */1862
1863 returnSCSI_RESET_WAKEUP;
1864 }1865
1866 #include "sd.h"
1867 #include "scsi_ioctl.h"
1868
1869 intfdomain_16x0_biosparam( Scsi_Disk *disk, kdev_tdev, int *info_array )
/* */1870 {1871 intdrive;
1872 unsignedcharbuf[512 + sizeof( int ) * 2];
1873 intsize = disk->capacity;
1874 int *sizes = (int *)buf;
1875 unsignedchar *data = (unsignedchar *)(sizes + 2);
1876 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1877 intretcode;
1878 structdrive_info{1879 unsignedshortcylinders;
1880 unsignedcharheads;
1881 unsignedcharsectors;
1882 } *i;
1883
1884 /* NOTES:1885 The RAM area starts at 0x1f00 from the bios_base address.1886
1887 For BIOS Version 2.0:1888 1889 The drive parameter table seems to start at 0x1f30.1890 The first byte's purpose is not known.1891 Next is the cylinder, head, and sector information.1892 The last 4 bytes appear to be the drive's size in sectors.1893 The other bytes in the drive parameter table are unknown.1894 If anyone figures them out, please send me mail, and I will1895 update these notes.1896
1897 Tape drives do not get placed in this table.1898
1899 There is another table at 0x1fea:1900 If the byte is 0x01, then the SCSI ID is not in use.1901 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1902 although tapes don't seem to be in this table. I haven't1903 seen any other numbers (in a limited sample).1904
1905 0x1f2d is a drive count (i.e., not including tapes)1906
1907 The table at 0x1fcc are I/O ports addresses for the various1908 operations. I calculate these by hand in this driver code.1909
1910 1911 1912 For the ISA-200S version of BIOS Version 2.0:1913
1914 The drive parameter table starts at 0x1f33.1915
1916 WARNING: Assume that the table entry is 25 bytes long. Someone needs1917 to check this for the Quantum ISA-200S card.1918
1919 1920 1921 For BIOS Version 3.2:1922
1923 The drive parameter table starts at 0x1f70. Each entry is1924 0x0a bytes long. Heads are one less than we need to report.1925 */1926
1927 drive = MINOR(dev) / 16;
1928
1929 if (bios_major == 2) {1930 switch (Quantum) {1931 case 2: /* ISA_200S */1932 /* The value of 25 has never been verified.1933 It should probably be 15. */1934 i = (structdrive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1935 break;
1936 case 3: /* ISA_250MG */1937 i = (structdrive_info *)( (char *)bios_base + 0x1f36 + drive * 15 );
1938 break;
1939 case 4: /* ISA_200S (another one) */1940 i = (structdrive_info *)( (char *)bios_base + 0x1f34 + drive * 15 );
1941 break;
1942 default:
1943 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1944 break;
1945 }1946 info_array[0] = i->heads;
1947 info_array[1] = i->sectors;
1948 info_array[2] = i->cylinders;
1949 }elseif (bios_major == 3
1950 && bios_minor >= 0
1951 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1952 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1953 info_array[0] = i->heads + 1;
1954 info_array[1] = i->sectors;
1955 info_array[2] = i->cylinders;
1956 }else{/* 3.4 BIOS (and up?) */1957 /* This algorithm was provided by Future Domain (much thanks!). */1958
1959 sizes[0] = 0; /* zero bytes out */1960 sizes[1] = 512; /* one sector in */1961 memcpy( data, do_read, sizeof( do_read ) );
1962 retcode = kernel_scsi_ioctl( disk->device,
1963 SCSI_IOCTL_SEND_COMMAND,
1964 (void *)buf );
1965 if (!retcode/* SCSI command ok */1966 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1967 && data[0x1c2]) {/* Partition type */1968
1969 /* The partition table layout is as follows:1970
1971 Start: 0x1b3h1972 Offset: 0 = partition status1973 1 = starting head1974 2 = starting sector and cylinder (word, encoded)1975 4 = partition type1976 5 = ending head1977 6 = ending sector and cylinder (word, encoded)1978 8 = starting absolute sector (double word)1979 c = number of sectors (double word)1980 Signature: 0x1fe = 0x55aa1981
1982 So, this algorithm assumes:1983 1) the first partition table is in use,1984 2) the data in the first entry is correct, and1985 3) partitions never divide cylinders1986
1987 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1988 as well as for Linux. Note also, that Linux doesn't pay any1989 attention to the fields that are used by this algorithm -- it1990 only uses the absolute sector data. Recent versions of Linux's1991 fdisk(1) will fill this data in correctly, and forthcoming1992 versions will check for consistency.1993
1994 Checking for a non-zero partition type is not part of the1995 Future Domain algorithm, but it seemed to be a reasonable thing1996 to do, especially in the Linux and BSD worlds. */1997
1998 info_array[0] = data[0x1c3] + 1; /* heads */1999 info_array[1] = data[0x1c4] & 0x3f; /* sectors */2000 }else{2001
2002 /* Note that this new method guarantees that there will always be2003 less than 1024 cylinders on a platter. This is good for drives2004 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */2005
2006 if ((unsignedint)size >= 0x7e0000U) {2007 info_array[0] = 0xff; /* heads = 255 */2008 info_array[1] = 0x3f; /* sectors = 63 */2009 }elseif ((unsignedint)size >= 0x200000U) {2010 info_array[0] = 0x80; /* heads = 128 */2011 info_array[1] = 0x3f; /* sectors = 63 */2012 }else{2013 info_array[0] = 0x40; /* heads = 64 */2014 info_array[1] = 0x20; /* sectors = 32 */2015 }2016 }2017 /* For both methods, compute the cylinders */2018 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
2019 }2020
2021 return 0;
2022 }2023
2024 #ifdefMODULE2025 /* Eventually this will go into an include file, but this will be later */2026 Scsi_Host_Templatedriver_template = FDOMAIN_16X0;
2027
2028 #include "scsi_module.c"
2029 #endif