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 Oct 12 15:59:37 1995 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 #ifdefMODULE 196 #include <linux/module.h>
197 #endif 198
199 #include <linux/sched.h>
200 #include <asm/io.h>
201 #include "../block/blk.h"
202 #include "scsi.h"
203 #include "hosts.h"
204 #include "fdomain.h"
205 #include <asm/system.h>
206 #include <linux/errno.h>
207 #include <linux/string.h>
208 #include <linux/ioport.h>
209 #include <linux/proc_fs.h>
210 #include <linux/bios32.h>
211 #include <linux/pci.h>
212 #include <linux/stat.h>
213
214 structproc_dir_entryproc_scsi_fdomain = { 215 PROC_SCSI_FDOMAIN, 7, "fdomain",
216 S_IFDIR | S_IRUGO | S_IXUGO, 2
217 };
218
219 #defineVERSION "$Revision: 5.39 $"
220
221 /* START OF USER DEFINABLE OPTIONS */ 222
223 #defineDEBUG 1 /* Enable debugging output */ 224 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 225 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 226 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 227
228 /* END OF USER DEFINABLE OPTIONS */ 229
230 #ifDEBUG 231 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 232 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 233 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 234 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 235 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 236 #defineDEBUG_RESET 1 /* Debug reset() routine */ 237 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 238 #else 239 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 240 #defineERRORS_ONLY 0
241 #defineDEBUG_DETECT 0
242 #defineDEBUG_MESSAGES 0
243 #defineDEBUG_ABORT 0
244 #defineDEBUG_RESET 0
245 #defineDEBUG_RACE 0
246 #endif 247
248 /* Errors are reported on the line, so we don't need to report them again */ 249 #ifEVERY_ACCESS 250 #undefERRORS_ONLY 251 #defineERRORS_ONLY 0
252 #endif 253
254 #ifENABLE_PARITY 255 #definePARITY_MASK 0x08
256 #else 257 #definePARITY_MASK 0x00
258 #endif 259
260 enumchip_type{ 261 unknown = 0x00,
262 tmc1800 = 0x01,
263 tmc18c50 = 0x02,
264 tmc18c30 = 0x03,
265 };
266
267 enum{ 268 in_arbitration = 0x02,
269 in_selection = 0x04,
270 in_other = 0x08,
271 disconnect = 0x10,
272 aborted = 0x20,
273 sent_ident = 0x40,
274 };
275
276 enum in_port_type { 277 Read_SCSI_Data = 0,
278 SCSI_Status = 1,
279 TMC_Status = 2,
280 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 281 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 282 LSB_ID_Code = 5,
283 MSB_ID_Code = 6,
284 Read_Loopback = 7,
285 SCSI_Data_NoACK = 8,
286 Interrupt_Status = 9,
287 Configuration1 = 10,
288 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 289 Read_FIFO = 12,
290 FIFO_Data_Count = 14
291 };
292
293 enum out_port_type { 294 Write_SCSI_Data = 0,
295 SCSI_Cntl = 1,
296 Interrupt_Cntl = 2,
297 SCSI_Mode_Cntl = 3,
298 TMC_Cntl = 4,
299 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 300 Write_Loopback = 7,
301 IO_Control = 11, /* tmc18c30 only */ 302 Write_FIFO = 12
303 };
304
305 staticintport_base = 0;
306 staticvoid *bios_base = NULL;
307 staticintbios_major = 0;
308 staticintbios_minor = 0;
309 staticintPCI_bus = 0;
310 staticintQuantum = 0; /* Quantum board variant */ 311 staticintinterrupt_level = 0;
312 staticvolatileintin_command = 0;
313 staticScsi_Cmnd *current_SC = NULL;
314 staticenumchip_typechip = unknown;
315 staticintadapter_mask = 0;
316 staticintthis_id = 0;
317 staticintsetup_called = 0;
318
319 #ifDEBUG_RACE 320 staticvolatileintin_interrupt_flag = 0;
321 #endif 322
323 staticintSCSI_Mode_Cntl_port;
324 staticintFIFO_Data_Count_port;
325 staticintInterrupt_Cntl_port;
326 staticintInterrupt_Status_port;
327 staticintRead_FIFO_port;
328 staticintRead_SCSI_Data_port;
329 staticintSCSI_Cntl_port;
330 staticintSCSI_Data_NoACK_port;
331 staticintSCSI_Status_port;
332 staticintTMC_Cntl_port;
333 staticintTMC_Status_port;
334 staticintWrite_FIFO_port;
335 staticintWrite_SCSI_Data_port;
336
337 staticintFIFO_Size = 0x2000; /* 8k FIFO for 338 pre-tmc18c30 chips */ 339
340 externvoidfdomain_16x0_intr( intirq, structpt_regs * regs );
341
342 staticvoid *addresses[] = { 343 (void *)0xc8000,
344 (void *)0xca000,
345 (void *)0xce000,
346 (void *)0xde000,
347 (void *)0xd0000, /* Extra addresses for PCI boards */ 348 (void *)0xe0000,
349 };
350 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
351
352 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
353 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
354
355 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
356
357 /* 358
359 READ THIS BEFORE YOU ADD A SIGNATURE! 360
361 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 362
363 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 364
365 This driver works *ONLY* for Future Domain cards using the TMC-1800, 366 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 367 and 1680. 368
369 The following BIOS signature signatures are for boards which do *NOT* 370 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 371 Seagate driver): 372
373 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 374 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 375 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 376 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 377 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 378 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 379 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 380
381 */ 382
383 structsignature{ 384 constchar *signature;
385 intsig_offset;
386 intsig_length;
387 intmajor_bios_version;
388 intminor_bios_version;
389 intflag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ 390 }signatures[] = { 391 /* 1 2 3 4 5 6 */ 392 /* 123456789012345678901234567890123456789012345678901234567890 */ 393 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
394 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
395 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
396 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
397 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
398 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
399 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
400 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
401 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
402 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
403 /* This next signature may not be a 3.5 bios */ 404 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
405 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
406 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
407 { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 },
408 { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 },
409 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
410
411 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE 412 Also, fix the disk geometry code for your signature and send your 413 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 414 signatures! 415
416 Note that the last line will match a "generic" 18XX bios. Because 417 Future Domain has changed the host SCSI ID and/or the location of the 418 geometry information in the on-board RAM area for each of the first 419 three BIOS's, it is still important to enter a fully qualified 420 signature in the table for any new BIOS's (after the host SCSI ID and 421 geometry location are verified). */ 422 };
423
424 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
425
426 staticvoidprint_banner( structScsi_Host *shpnt )
427 { 428 if (!shpnt) return; /* This won't ever happen */ 429
430 if (bios_major < 0 && bios_minor < 0) { 431 printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n",
432 shpnt->host_no, shpnt->this_id );
433 }else{ 434 printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
435
436 if (bios_major >= 0) printk( "%d.", bios_major );
437 elseprintk( "?." );
438
439 if (bios_minor >= 0) printk( "%d", bios_minor );
440 elseprintk( "?." );
441
442 printk( " at 0x%x using scsi id %d\n",
443 (unsigned)bios_base, shpnt->this_id );
444 } 445
446 /* If this driver works for later FD PCI 447 boards, we will have to modify banner 448 for additional PCI cards, but for now if 449 it's PCI it's a TMC-3260 - JTM */ 450 printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
451 shpnt->host_no,
452 chip == tmc1800 ? "TMC-1800"
453 : (chip == tmc18c50 ? "TMC-18C50"
454 : (chip == tmc18c30 ?
455 (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30")
456 : "Unknown")),
457 port_base );
458
459 if (interrupt_level) printk( "%d", interrupt_level );
460 elseprintk( "<none>" );
461
462 printk( "\n" );
463 } 464
465 voidfdomain_setup( char *str, int *ints )
/* */ 466 { 467 if (setup_called++ || ints[0] < 2 || ints[0] > 3) { 468 printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
469 printk( "fdomain: bad LILO parameters?\n" );
470 } 471
472 port_base = ints[0] >= 1 ? ints[1] : 0;
473 interrupt_level = ints[0] >= 2 ? ints[2] : 0;
474 this_id = ints[0] >= 3 ? ints[3] : 0;
475
476 bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ 477 } 478
479
480 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 481 { 482 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 483
484 while (jiffies < the_time);
485 } 486
487 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 488 { 489 outb( 0, SCSI_Cntl_port );
490 outb( 0, SCSI_Mode_Cntl_port );
491 if (chip == tmc18c50 || chip == tmc18c30)
492 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 493 else 494 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
495 } 496
497 staticintfdomain_is_valid_port( intport )
/* */ 498 { 499 #ifDEBUG_DETECT 500 printk( " (%x%x),",
501 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
502 #endif 503
504 /* The MCA ID is a unique id for each MCA compatible board. We 505 are using ISA boards, but Future Domain provides the MCA ID 506 anyway. We can use this ID to ensure that this is a Future 507 Domain TMC-1660/TMC-1680. 508 */ 509
510 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 511 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
512 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
513 chip = tmc1800;
514 }else{/* test for 0xe960 id */ 515 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
516 chip = tmc18c50;
517
518 #if 0
519
520 /* Try to toggle 32-bit mode. This only 521 works on an 18c30 chip. (User reports 522 say that this doesn't work at all, so 523 we'll use the other method.) */ 524
525 outb( 0x80, port + IO_Control );
526 if ((inb( port + Configuration2 ) & 0x80) == 0x80) { 527 outb( 0x00, port + IO_Control );
528 if ((inb( port + Configuration2 ) & 0x80) == 0x00) { 529 chip = tmc18c30;
530 FIFO_Size = 0x800; /* 2k FIFO */ 531 } 532 } 533 #else 534
535 /* That should have worked, but appears to 536 have problems. Lets assume it is an 537 18c30 if the RAM is disabled. */ 538
539 if (inb( port + Configuration2 ) & 0x02) { 540 chip = tmc18c30;
541 FIFO_Size = 0x800; /* 2k FIFO */ 542 } 543 #endif 544 /* If that failed, we are an 18c50. */ 545 } 546
547 return 1;
548 } 549
550 staticintfdomain_test_loopback( void )
/* */ 551 { 552 inti;
553 intresult;
554
555 for (i = 0; i < 255; i++) { 556 outb( i, port_base + Write_Loopback );
557 result = inb( port_base + Read_Loopback );
558 if (i != result)
559 return 1;
560 } 561 return 0;
562 } 563
564 /* fdomain_get_irq assumes that we have a valid MCA ID for a 565 TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the 566 bios_base matches these ports. If someone was unlucky enough to have 567 purchased more than one Future Domain board, then they will have to 568 modify this code, as we only detect one board here. [The one with the 569 lowest bios_base.] 570
571 Note that this routine is only used for systems without a PCI BIOS32 572 (e.g., ISA bus). For PCI bus systems, this routine will likely fail 573 unless one of the IRQs listed in the ints array is used by the board. 574 Sometimes it is possible to use the computer's BIOS setup screen to 575 configure a PCI system so that one of these IRQs will be used by the 576 Future Domain card. */ 577
578 staticintfdomain_get_irq( intbase )
/* */ 579 { 580 intoptions = inb( base + Configuration1 );
581
582 #ifDEBUG_DETECT 583 printk( " Options = %x\n", options );
584 #endif 585
586 /* Check for board with lowest bios_base -- 587 this isn't valid for the 18c30 or for 588 boards on the PCI bus, so just assume we 589 have the right board. */ 590
591 if (chip != tmc18c30 592 && !PCI_bus 593 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
594
595 returnints[ (options & 0x0e) >> 1 ];
596 } 597
598 staticintfdomain_isa_detect( int *irq, int *iobase )
/* */ 599 { 600 inti;
601 intbase;
602 intflag = 0;
603
604 if (bios_major == 2) { 605 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 606 Assuming the ROM is enabled (otherwise we wouldn't have been 607 able to read the ROM signature :-), then the ROM sets up the 608 RAM area with some magic numbers, such as a list of port 609 base addresses and a list of the disk "geometry" reported to 610 DOS (this geometry has nothing to do with physical geometry). 611 */ 612
613 switch (Quantum) { 614 case 2: /* ISA_200S */ 615 case 3: /* ISA_250MG */ 616 base = *((char *)bios_base + 0x1fa2)
617 + (*((char *)bios_base + 0x1fa3) << 8);
618 break;
619 case 4: /* ISA_200S (another one) */ 620 base = *((char *)bios_base + 0x1fa3)
621 + (*((char *)bios_base + 0x1fa4) << 8);
622 break;
623 default:
624 base = *((char *)bios_base + 0x1fcc)
625 + (*((char *)bios_base + 0x1fcd) << 8);
626 break;
627 } 628
629 #ifDEBUG_DETECT 630 printk( " %x,", base );
631 #endif 632
633 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 634 if (base == ports[i])
635 ++flag;
636 } 637
638 if (flag && fdomain_is_valid_port( base )) { 639 *irq = fdomain_get_irq( base );
640 *iobase = base;
641 return 1;
642 } 643
644 /* This is a bad sign. It usually means that someone patched the 645 BIOS signature list (the signatures variable) to contain a BIOS 646 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ 647
648 #ifDEBUG_DETECT 649 printk( " RAM FAILED, " );
650 #endif 651 } 652
653 /* Anyway, the alternative to finding the address in the RAM is to just 654 search through every possible port address for one that is attached 655 to the Future Domain card. Don't panic, though, about reading all 656 these random port addresses -- there are rumors that the Future 657 Domain BIOS does something very similar. 658
659 Do not, however, check ports which the kernel knows are being used by 660 another driver. */ 661
662 for (i = 0; i < PORT_COUNT; i++) { 663 base = ports[i];
664 if (check_region( base, 0x10 )) { 665 #ifDEBUG_DETECT 666 printk( " (%x inuse),", base );
667 #endif 668 continue;
669 } 670 #ifDEBUG_DETECT 671 printk( " %x,", base );
672 #endif 673 if ((flag = fdomain_is_valid_port( base ))) break;
674 } 675
676 if (!flag) return 0; /* iobase not found */ 677
678 *irq = fdomain_get_irq( base );
679 *iobase = base;
680
681 return 1; /* success */ 682 } 683
684 staticintfdomain_pci_nobios_detect( int *irq, int *iobase )
/* */ 685 { 686 inti;
687 intflag = 0;
688
689 /* The proper way of doing this is to use ask the PCI bus for the device 690 IRQ and interrupt level. But we can't do that if PCI BIOS32 support 691 isn't compiled into the kernel, or if a PCI BIOS32 isn't present. 692
693 Instead, we scan down a bunch of addresses (Future Domain tech 694 support says we will probably find the address before we get to 695 0xf800). This works fine on some systems -- other systems may have 696 to scan more addresses. If you have to modify this section for your 697 installation, please send mail to faith@cs.unc.edu. */ 698
699 for (i = 0xfff8; i > 0xe000; i -= 8) { 700 if (check_region( i, 0x10 )) { 701 #ifDEBUG_DETECT 702 printk( " (%x inuse)," , i );
703 #endif 704 continue;
705 } 706 if ((flag = fdomain_is_valid_port( i ))) break;
707 } 708
709 if (!flag) return 0; /* iobase not found */ 710
711 *irq = fdomain_get_irq( i );
712 *iobase = i;
713
714 return 1; /* success */ 715 } 716
717 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* 718 iobase) This function gets the Interrupt Level and I/O base address from 719 the PCI configuration registers. The I/O base address is masked with 720 0xfff8 since on my card the address read from the PCI config registers 721 is off by one from the actual I/O base address necessary for accessing 722 the status and control registers on the card (PCI config register gives 723 0xf801, actual address is 0xf800). This is likely a bug in the FD 724 config code that writes to the PCI registers, however using a mask 725 should be safe since I think the scan done by the card to determine the 726 I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at 727 least the old scan code we used to use to get the I/O base did... Also, 728 the device ID from the PCI config registers is 0x0 and should be 0x60e9 729 as it is in the status registers (offset 5 from I/O base). If this is 730 changed in future hardware/BIOS changes it will need to be fixed in this 731 detection function. Comments, bug reports, etc... on this function 732 should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ 733
734 #ifdefCONFIG_PCI 735 staticintfdomain_pci_bios_detect( int *irq, int *iobase )
/* */ 736 { 737 interror;
738 unsignedcharpci_bus, pci_dev_fn; /* PCI bus & device function */ 739 unsignedcharpci_irq; /* PCI interrupt line */ 740 unsignedintpci_base; /* PCI I/O base address */ 741 unsignedshortpci_vendor, pci_device; /* PCI vendor & device IDs */ 742
743 /* If the PCI BIOS doesn't exist, use the old-style detection routines. 744 Otherwise, get the I/O base address and interrupt from the PCI config 745 registers. */ 746
747 if (!pcibios_present()) returnfdomain_pci_nobios_detect( irq, iobase );
748
749 #ifDEBUG_DETECT 750 /* Tell how to print a list of the known PCI devices from bios32 and 751 list vendor and device IDs being used if in debug mode. */ 752
753 printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
754 printk( "\nTMC-3260 detect:"
755 " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
756 PCI_VENDOR_ID_FD,
757 PCI_DEVICE_ID_FD_36C70 );
758 #endif 759
760 /* We will have to change this if more than 1 PCI bus is present and the 761 FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, 762 which is not supported by bios32 right now anyway). This should 763 probably be done by a call to pcibios_find_device but I can't get it 764 to work... Also the device ID reported from the PCI config registers 765 does not match the device ID quoted in the tech manual or available 766 from offset 5 from the I/O base address. It should be 0x60E9, but it 767 is 0x0 if read from the PCI config registers. I guess the FD folks 768 neglected to write it to the PCI registers... This loop is necessary 769 to get the device function (at least until someone can get 770 pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ 771
772 pci_bus = 0;
773
774 for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { 775 pcibios_read_config_word( pci_bus,
776 pci_dev_fn,
777 PCI_VENDOR_ID,
778 &pci_vendor );
779
780 if (pci_vendor == PCI_VENDOR_ID_FD) { 781 pcibios_read_config_word( pci_bus,
782 pci_dev_fn,
783 PCI_DEVICE_ID,
784 &pci_device );
785
786 if (pci_device == PCI_DEVICE_ID_FD_36C70) { 787 /* Break out once we have the correct device. If other FD 788 PCI devices are added to this driver we will need to add 789 an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ 790 break;
791 }else{ 792 /* If we can't find an FD scsi card we give up. */ 793 return 0;
794 } 795 } 796 } 797
798 #ifDEBUG_DETECT 799 printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
800 pci_bus,
801 (pci_dev_fn & 0xf8) >> 3,
802 pci_dev_fn & 7 );
803 #endif 804
805 /* We now have the appropriate device function for the FD board so we 806 just read the PCI config info from the registers. */ 807
808 if ((error = pcibios_read_config_dword( pci_bus,
809 pci_dev_fn,
810 PCI_BASE_ADDRESS_0,
811 &pci_base ))
812 || (error = pcibios_read_config_byte( pci_bus,
813 pci_dev_fn,
814 PCI_INTERRUPT_LINE,
815 &pci_irq ))) { 816 printk ( "PCI ERROR: Future Domain 36C70 not initializing"
817 " due to error reading configuration space\n" );
818 return 0;
819 }else{ 820 #ifDEBUG_DETECT 821 printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
822 pci_irq, pci_base );
823 #endif 824
825 /* Now we have the I/O base address and interrupt from the PCI 826 configuration registers. Unfortunately it seems that the I/O base 827 address is off by one on my card so I mask it with 0xfff8. This 828 must be some kind of goof in the FD code that does the autoconfig 829 and writes to the PCI registers (or maybe I just don't understand 830 something). If they fix it in later versions of the card or BIOS 831 we may have to adjust the address based on the signature or 832 something... */ 833
834 *irq = pci_irq;
835 *iobase = (pci_base & 0xfff8);
836
837 #ifDEBUG_DETECT 838 printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
839 printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
840 #endif 841
842 if (!fdomain_is_valid_port( *iobase )) return 0;
843 return 1;
844 } 845 return 0;
846 } 847 #endif 848
849 intfdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* */ 850 { 851 inti, j;
852 intretcode;
853 structScsi_Host *shpnt;
854 #ifDO_DETECT 855 constintbuflen = 255;
856 Scsi_CmndSCinit;
857 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
858 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
859 unsignedchardo_read_capacity[] = {READ_CAPACITY,
860 0, 0, 0, 0, 0, 0, 0, 0, 0 };
861 unsignedcharbuf[buflen];
862 #endif 863
864 #ifDEBUG_DETECT 865 printk( "fdomain_16x0_detect()," );
866 #endif 867 tpnt->proc_dir = &proc_scsi_fdomain;
868
869 if (setup_called) { 870 #ifDEBUG_DETECT 871 printk( "no BIOS, using port_base = 0x%x, irq = %d\n",
872 port_base, interrupt_level );
873 #endif 874 if (!fdomain_is_valid_port( port_base )) { 875 printk( "fdomain: cannot locate chip at port base 0x%x\n",
876 port_base );
877 printk( "fdomain: bad LILO parameters?\n" );
878 return 0;
879 } 880 }else{ 881 intflag = 0;
882
883 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 884 #ifDEBUG_DETECT 885 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
886 #endif 887 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 888 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
889 signatures[j].signature, signatures[j].sig_length )) { 890 bios_major = signatures[j].major_bios_version;
891 bios_minor = signatures[j].minor_bios_version;
892 PCI_bus = (signatures[j].flag == 1);
893 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
894 bios_base = addresses[i];
895 } 896 } 897 } 898
899 if (!bios_base) { 900 #ifDEBUG_DETECT 901 printk( " FAILED: NO BIOS\n" );
902 #endif 903 return 0;
904 } 905
906 if (!PCI_bus) { 907 flag = fdomain_isa_detect( &interrupt_level, &port_base );
908 }else{ 909 #ifdefCONFIG_PCI 910 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
911 #else 912 flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
913 #endif 914 } 915
916 if (!flag) { 917 #ifDEBUG_DETECT 918 printk( " FAILED: NO PORT\n" );
919 #endif 920 #ifdefCONFIG_PCI 921 printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
922 printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" );
923 #endif 924 return 0; /* Cannot find valid set of ports */ 925 } 926 } 927
928 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
929 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
930 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
931 Interrupt_Status_port = port_base + Interrupt_Status;
932 Read_FIFO_port = port_base + Read_FIFO;
933 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
934 SCSI_Cntl_port = port_base + SCSI_Cntl;
935 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
936 SCSI_Status_port = port_base + SCSI_Status;
937 TMC_Cntl_port = port_base + TMC_Cntl;
938 TMC_Status_port = port_base + TMC_Status;
939 Write_FIFO_port = port_base + Write_FIFO;
940 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
941
942 fdomain_16x0_reset( NULL );
943
944 if (fdomain_test_loopback()) { 945 #ifDEBUG_DETECT 946 printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
947 #endif 948 if (setup_called) { 949 printk( "fdomain: loopback test failed at port base 0x%x\n",
950 port_base );
951 printk( "fdomain: bad LILO parameters?\n" );
952 } 953 return 0;
954 } 955
956 if (this_id) { 957 tpnt->this_id = (this_id & 0x07);
958 adapter_mask = (1 << tpnt->this_id);
959 }else{ 960 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 961 tpnt->this_id = 7;
962 adapter_mask = 0x80;
963 }else{ 964 tpnt->this_id = 6;
965 adapter_mask = 0x40;
966 } 967 } 968
969 /* Print out a banner here in case we can't 970 get resources. */ 971
972 shpnt = scsi_register( tpnt, 0 );
973 print_banner( shpnt );
974
975 /* Log IRQ with kernel */ 976 if (!interrupt_level) { 977 panic( "fdomain: *NO* interrupt level selected!\n" );
978 }else{ 979 /* Register the IRQ with the kernel */ 980
981 retcode = request_irq( interrupt_level,
982 fdomain_16x0_intr, SA_INTERRUPT, "fdomain" );
983
984 if (retcode < 0) { 985 if (retcode == -EINVAL) { 986 printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
987 printk( " This shouldn't happen!\n" );
988 printk( " Send mail to faith@cs.unc.edu\n" );
989 }elseif (retcode == -EBUSY) { 990 printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
991 printk( " Please use another IRQ!\n" );
992 }else{ 993 printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
994 printk( " This shouldn't happen!\n" );
995 printk( " Send mail to faith@cs.unc.edu\n" );
996 } 997 panic( "fdomain: Driver requires interruptions\n" );
998 } 999 }1000
1001 /* Log I/O ports with kernel */1002 request_region( port_base, 0x10, "fdomain" );
1003
1004 #ifDO_DETECT1005
1006 /* These routines are here because of the way the SCSI bus behaves after1007 a reset. This appropriate behavior was not handled correctly by the1008 higher level SCSI routines when I first wrote this driver. Now,1009 however, correct scan routines are part of scsi.c and these routines1010 are no longer needed. However, this code is still good for1011 debugging. */1012
1013 SCinit.request_buffer = SCinit.buffer = buf;
1014 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
1015 SCinit.use_sg = 0;
1016 SCinit.lun = 0;
1017
1018 printk( "fdomain: detection routine scanning for devices:\n" );
1019 for (i = 0; i < 8; i++) {1020 SCinit.target = i;
1021 if (i == tpnt->this_id) /* Skip host adapter */1022 continue;
1023 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1024 retcode = fdomain_16x0_command(&SCinit);
1025 if (!retcode) {1026 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
1027 retcode = fdomain_16x0_command(&SCinit);
1028 if (!retcode) {1029 printk( " SCSI ID %d: ", i );
1030 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
1031 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
1032 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
1033 retcode = fdomain_16x0_command(&SCinit);
1034 if (!retcode) {1035 unsignedlongblocks, size, capacity;
1036
1037 blocks = (buf[0] << 24) | (buf[1] << 16)
1038 | (buf[2] << 8) | buf[3];
1039 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
1040 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
1041
1042 printk( "%lu MB (%lu byte blocks)",
1043 ((capacity + 5L) / 10L), size );
1044 }else{1045 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1046 retcode = fdomain_16x0_command(&SCinit);
1047 }1048 printk ("\n" );
1049 }else{1050 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1051 retcode = fdomain_16x0_command(&SCinit);
1052 }1053 }1054 }1055 #endif1056
1057 return 1; /* Maximum of one adapter will be detected. */1058 }1059
1060 constchar *fdomain_16x0_info( structScsi_Host *ignore )
/* */1061 {1062 staticcharbuffer[80];
1063 char *pt;
1064
1065 strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
1066 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */1067 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1068 pt = strrchr( buffer, '$') - 1;
1069 if (!pt) /* Stripped RCS Revision string? */1070 pt = buffer + strlen( buffer ) - 1;
1071 if (*pt != ' ')
1072 ++pt;
1073 *pt = '\0';
1074 }else{/* Assume VERSION is a number */1075 strcat( buffer, " " VERSION );
1076 }1077
1078 returnbuffer;
1079 }1080
1081 /* First pass at /proc information routine. */1082 /*1083 * inout : decides on the direction of the dataflow and the meaning of the 1084 * variables1085 * buffer: If inout==FALSE data is beeing written to it else read from it1086 * *start: If inout==FALSE start of the valid data in the buffer1087 * offset: If inout==FALSE offset from the beginning of the imaginary file 1088 * from which we start writing into the buffer1089 * length: If inout==FALSE max number of bytes to be written into the buffer 1090 * else number of bytes in the buffer1091 */1092 intfdomain_16x0_proc_info( char *buffer, char **start, off_toffset,
/* */1093 intlength, inthostno, intinout )
1094 {1095 constchar *info = fdomain_16x0_info( NULL );
1096 intlen;
1097 intpos;
1098 intbegin;
1099
1100 if (inout) return(-ENOSYS);
1101
1102 begin = 0;
1103 strcpy( buffer, info );
1104 strcat( buffer, "\n" );
1105
1106 pos = len = strlen( buffer );
1107
1108 if(pos < offset) {1109 len = 0;
1110 begin = pos;
1111 }1112
1113 *start = buffer + (offset - begin); /* Start of wanted data */1114 len -= (offset - begin);
1115 if(len > length) len = length;
1116
1117 return(len);
1118 }1119
1120 #if 0
1121 staticint fdomain_arbitrate( void )
/* */1122 {1123 intstatus = 0;
1124 unsignedlongtimeout;
1125
1126 #ifEVERY_ACCESS1127 printk( "fdomain_arbitrate()\n" );
1128 #endif1129
1130 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1131 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */1132 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1133
1134 timeout = jiffies + 50; /* 500 mS */1135 while (jiffies < timeout) {1136 status = inb( TMC_Status_port ); /* Read adapter status */1137 if (status & 0x02) /* Arbitration complete */1138 return 0;
1139 }1140
1141 /* Make bus idle */1142 fdomain_make_bus_idle();
1143
1144 #ifEVERY_ACCESS1145 printk( "Arbitration failed, status = %x\n", status );
1146 #endif1147 #ifERRORS_ONLY1148 printk( "fdomain: Arbitration failed, status = %x\n", status );
1149 #endif1150 return 1;
1151 }1152 #endif1153
1154 staticintfdomain_select( inttarget )
/* */1155 {1156 intstatus;
1157 unsignedlongtimeout;
1158 staticintflag = 0;
1159
1160
1161 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1162 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
1163
1164 /* Stop arbitration and enable parity */1165 outb( PARITY_MASK, TMC_Cntl_port );
1166
1167 timeout = jiffies + 35; /* 350mS -- because of timeouts1168 (was 250mS) */1169
1170 while (jiffies < timeout) {1171 status = inb( SCSI_Status_port ); /* Read adapter status */1172 if (status & 1) {/* Busy asserted */1173 /* Enable SCSI Bus (on error, should make bus idle with 0) */1174 outb( 0x80, SCSI_Cntl_port );
1175 return 0;
1176 }1177 }1178 /* Make bus idle */1179 fdomain_make_bus_idle();
1180 #ifEVERY_ACCESS1181 if (!target) printk( "Selection failed\n" );
1182 #endif1183 #ifERRORS_ONLY1184 if (!target) {1185 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */1186 ++flag;
1187 else1188 printk( "fdomain: Selection failed\n" );
1189 }1190 #endif1191 return 1;
1192 }1193
1194 voidmy_done( interror )
/* */1195 {1196 if (in_command) {1197 in_command = 0;
1198 outb( 0x00, Interrupt_Cntl_port );
1199 fdomain_make_bus_idle();
1200 current_SC->result = error;
1201 if (current_SC->scsi_done)
1202 current_SC->scsi_done( current_SC );
1203 elsepanic( "fdomain: current_SC->scsi_done() == NULL" );
1204 }else{1205 panic( "fdomain: my_done() called outside of command\n" );
1206 }1207 #ifDEBUG_RACE1208 in_interrupt_flag = 0;
1209 #endif1210 }1211
1212 voidfdomain_16x0_intr( intirq, structpt_regs * regs )
/* */1213 {1214 intstatus;
1215 intdone = 0;
1216 unsigneddata_count;
1217
1218 /* The fdomain_16x0_intr is only called via1219 the interrupt handler. The goal of the1220 sti() here is to allow other1221 interruptions while this routine is1222 running. */1223
1224 sti(); /* Yes, we really want sti() here */1225
1226 outb( 0x00, Interrupt_Cntl_port );
1227
1228 /* We usually have one spurious interrupt after each command. Ignore it. */1229 if (!in_command || !current_SC) {/* Spurious interrupt */1230 #ifEVERY_ACCESS1231 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1232 in_command, current_SC );
1233 #endif1234 return;
1235 }1236
1237 /* Abort calls my_done, so we do nothing here. */1238 if (current_SC->SCp.phase & aborted) {1239 #ifDEBUG_ABORT1240 printk( "Interrupt after abort, ignoring\n" );
1241 #endif1242 /*1243 return; */1244 }1245
1246 #ifDEBUG_RACE1247 ++in_interrupt_flag;
1248 #endif1249
1250 if (current_SC->SCp.phase & in_arbitration) {1251 status = inb( TMC_Status_port ); /* Read adapter status */1252 if (!(status & 0x02)) {1253 #ifEVERY_ACCESS1254 printk( " AFAIL " );
1255 #endif1256 my_done( DID_BUS_BUSY << 16 );
1257 return;
1258 }1259 current_SC->SCp.phase = in_selection;
1260
1261 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
1262
1263 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1264 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
1265
1266 /* Stop arbitration and enable parity */1267 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1268 #ifDEBUG_RACE1269 in_interrupt_flag = 0;
1270 #endif1271 return;
1272 }elseif (current_SC->SCp.phase & in_selection) {1273 status = inb( SCSI_Status_port );
1274 if (!(status & 0x01)) {1275 /* Try again, for slow devices */1276 if (fdomain_select( current_SC->target )) {1277 #ifEVERY_ACCESS1278 printk( " SFAIL " );
1279 #endif1280 my_done( DID_NO_CONNECT << 16 );
1281 return;
1282 }else{1283 #ifEVERY_ACCESS1284 printk( " AltSel " );
1285 #endif1286 /* Stop arbitration and enable parity */1287 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1288 }1289 }1290 current_SC->SCp.phase = in_other;
1291 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1292 outb( 0x80, SCSI_Cntl_port );
1293 #ifDEBUG_RACE1294 in_interrupt_flag = 0;
1295 #endif1296 return;
1297 }1298
1299 /* current_SC->SCp.phase == in_other: this is the body of the routine */1300
1301 status = inb( SCSI_Status_port );
1302
1303 if (status & 0x10) {/* REQ */1304
1305 switch (status & 0x0e) {1306
1307 case 0x08: /* COMMAND OUT */1308 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
1309 Write_SCSI_Data_port );
1310 #ifEVERY_ACCESS1311 printk( "CMD = %x,",
1312 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1313 #endif1314 break;
1315 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */1316 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1317 current_SC->SCp.have_data_in = -1;
1318 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1319 }1320 break;
1321 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */1322 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1323 current_SC->SCp.have_data_in = 1;
1324 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1325 }1326 break;
1327 case 0x0c: /* STATUS IN */1328 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
1329 #ifEVERY_ACCESS1330 printk( "Status = %x, ", current_SC->SCp.Status );
1331 #endif1332 #ifERRORS_ONLY1333 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {1334 printk( "fdomain: target = %d, command = %x, status = %x\n",
1335 current_SC->target,
1336 current_SC->cmnd[0],
1337 current_SC->SCp.Status );
1338 }1339 #endif1340 break;
1341 case 0x0a: /* MESSAGE OUT */1342 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */1343 break;
1344 case 0x0e: /* MESSAGE IN */1345 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1346 #ifEVERY_ACCESS1347 printk( "Message = %x, ", current_SC->SCp.Message );
1348 #endif1349 if (!current_SC->SCp.Message) ++done;
1350 #ifDEBUG_MESSAGES || EVERY_ACCESS1351 if (current_SC->SCp.Message) {1352 printk( "fdomain: message = %x\n", current_SC->SCp.Message );
1353 }1354 #endif1355 break;
1356 }1357 }1358
1359 if (chip == tmc18001360 && !current_SC->SCp.have_data_in1361 && (current_SC->SCp.sent_command1362 >= current_SC->cmd_len)) {1363 /* We have to get the FIFO direction1364 correct, so I've made a table based1365 on the SCSI Standard of which commands1366 appear to require a DATA OUT phase.1367 */1368 /*1369 p. 94: Command for all device types1370 CHANGE DEFINITION 40 DATA OUT1371 COMPARE 39 DATA OUT1372 COPY 18 DATA OUT1373 COPY AND VERIFY 3a DATA OUT1374 INQUIRY 12 1375 LOG SELECT 4c DATA OUT1376 LOG SENSE 4d1377 MODE SELECT (6) 15 DATA OUT1378 MODE SELECT (10) 55 DATA OUT1379 MODE SENSE (6) 1a1380 MODE SENSE (10) 5a1381 READ BUFFER 3c1382 RECEIVE DIAGNOSTIC RESULTS 1c1383 REQUEST SENSE 031384 SEND DIAGNOSTIC 1d DATA OUT1385 TEST UNIT READY 001386 WRITE BUFFER 3b DATA OUT1387
1388 p.178: Commands for direct-access devices (not listed on p. 94)1389 FORMAT UNIT 04 DATA OUT1390 LOCK-UNLOCK CACHE 361391 PRE-FETCH 341392 PREVENT-ALLOW MEDIUM REMOVAL 1e1393 READ (6)/RECEIVE 081394 READ (10) 3c1395 READ CAPACITY 251396 READ DEFECT DATA (10) 371397 READ LONG 3e1398 REASSIGN BLOCKS 07 DATA OUT1399 RELEASE 171400 RESERVE 16 DATA OUT1401 REZERO UNIT/REWIND 011402 SEARCH DATA EQUAL (10) 31 DATA OUT1403 SEARCH DATA HIGH (10) 30 DATA OUT1404 SEARCH DATA LOW (10) 32 DATA OUT1405 SEEK (6) 0b1406 SEEK (10) 2b1407 SET LIMITS (10) 331408 START STOP UNIT 1b1409 SYNCHRONIZE CACHE 351410 VERIFY (10) 2f1411 WRITE (6)/PRINT/SEND 0a DATA OUT1412 WRITE (10)/SEND 2a DATA OUT1413 WRITE AND VERIFY (10) 2e DATA OUT1414 WRITE LONG 3f DATA OUT1415 WRITE SAME 41 DATA OUT ?1416
1417 p. 261: Commands for sequential-access devices (not previously listed)1418 ERASE 191419 LOAD UNLOAD 1b1420 LOCATE 2b1421 READ BLOCK LIMITS 051422 READ POSITION 341423 READ REVERSE 0f1424 RECOVER BUFFERED DATA 141425 SPACE 111426 WRITE FILEMARKS 10 ?1427
1428 p. 298: Commands for printer devices (not previously listed)1429 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1430 SLEW AND PRINT 0b DATA OUT -- same as seek1431 STOP PRINT 1b1432 SYNCHRONIZE BUFFER 101433
1434 p. 315: Commands for processor devices (not previously listed)1435 1436 p. 321: Commands for write-once devices (not previously listed)1437 MEDIUM SCAN 381438 READ (12) a81439 SEARCH DATA EQUAL (12) b1 DATA OUT1440 SEARCH DATA HIGH (12) b0 DATA OUT1441 SEARCH DATA LOW (12) b2 DATA OUT1442 SET LIMITS (12) b31443 VERIFY (12) af1444 WRITE (12) aa DATA OUT1445 WRITE AND VERIFY (12) ae DATA OUT1446
1447 p. 332: Commands for CD-ROM devices (not previously listed)1448 PAUSE/RESUME 4b1449 PLAY AUDIO (10) 451450 PLAY AUDIO (12) a51451 PLAY AUDIO MSF 471452 PLAY TRACK RELATIVE (10) 491453 PLAY TRACK RELATIVE (12) a91454 READ HEADER 441455 READ SUB-CHANNEL 421456 READ TOC 431457
1458 p. 370: Commands for scanner devices (not previously listed)1459 GET DATA BUFFER STATUS 341460 GET WINDOW 251461 OBJECT POSITION 311462 SCAN 1b1463 SET WINDOW 24 DATA OUT1464
1465 p. 391: Commands for optical memory devices (not listed)1466 ERASE (10) 2c1467 ERASE (12) ac1468 MEDIUM SCAN 38 DATA OUT1469 READ DEFECT DATA (12) b71470 READ GENERATION 291471 READ UPDATED BLOCK 2d1472 UPDATE BLOCK 3d DATA OUT1473
1474 p. 419: Commands for medium changer devices (not listed)1475 EXCHANGE MEDIUM 461476 INITIALIZE ELEMENT STATUS 071477 MOVE MEDIUM a51478 POSITION TO ELEMENT 2b1479 READ ELEMENT STATUS b81480 REQUEST VOL. ELEMENT ADDRESS b51481 SEND VOLUME TAG b6 DATA OUT1482
1483 p. 454: Commands for communications devices (not listed previously)1484 GET MESSAGE (6) 081485 GET MESSAGE (10) 281486 GET MESSAGE (12) a81487 */1488
1489 switch (current_SC->cmnd[0]) {1490 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1491 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1492 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1493
1494 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1495 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1496 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1497 case 0x3f: case 0x41:
1498
1499 case 0xb1: case 0xb0: case 0xb2:
1500 case 0xaa: case 0xae:
1501
1502 case 0x24:
1503
1504 case 0x38: case 0x3d:
1505
1506 case 0xb6:
1507
1508 case 0xea: /* alternate number for WRITE LONG */1509
1510 current_SC->SCp.have_data_in = -1;
1511 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1512 break;
1513
1514 case 0x00:
1515 default:
1516
1517 current_SC->SCp.have_data_in = 1;
1518 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1519 break;
1520 }1521 }1522
1523 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1524 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1525 #ifEVERY_ACCESS1526 printk( "DC=%d, ", data_count ) ;
1527 #endif1528 if (data_count > current_SC->SCp.this_residual)
1529 data_count = current_SC->SCp.this_residual;
1530 if (data_count > 0) {1531 #ifEVERY_ACCESS1532 printk( "%d OUT, ", data_count );
1533 #endif1534 if (data_count == 1) {1535 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1536 --current_SC->SCp.this_residual;
1537 }else{1538 data_count >>= 1;
1539 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1540 current_SC->SCp.ptr += 2 * data_count;
1541 current_SC->SCp.this_residual -= 2 * data_count;
1542 }1543 }1544 if (!current_SC->SCp.this_residual) {1545 if (current_SC->SCp.buffers_residual) {1546 --current_SC->SCp.buffers_residual;
1547 ++current_SC->SCp.buffer;
1548 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1549 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1550 }else1551 break;
1552 }1553 }1554 }1555
1556 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1557 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1558 #ifEVERY_ACCESS1559 printk( "DC=%d, ", data_count );
1560 #endif1561 if (data_count > current_SC->SCp.this_residual)
1562 data_count = current_SC->SCp.this_residual;
1563 if (data_count) {1564 #ifEVERY_ACCESS1565 printk( "%d IN, ", data_count );
1566 #endif1567 if (data_count == 1) {1568 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1569 --current_SC->SCp.this_residual;
1570 }else{1571 data_count >>= 1; /* Number of words */1572 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1573 current_SC->SCp.ptr += 2 * data_count;
1574 current_SC->SCp.this_residual -= 2 * data_count;
1575 }1576 }1577 if (!current_SC->SCp.this_residual1578 && current_SC->SCp.buffers_residual) {1579 --current_SC->SCp.buffers_residual;
1580 ++current_SC->SCp.buffer;
1581 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1582 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1583 }1584 }1585 }1586
1587 if (done) {1588 #ifEVERY_ACCESS1589 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1590 #endif1591
1592 #ifERRORS_ONLY1593 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1594 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1595 unsignedcharkey;
1596 unsignedcharcode;
1597 unsignedcharqualifier;
1598
1599 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1600 & 0x0f;
1601 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1602 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1603 + 13));
1604
1605 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1606 && !(key == NOT_READY1607 && code == 0x04
1608 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1609 && !(key == ILLEGAL_REQUEST && (code == 0x25
1610 || code == 0x24
1611 || !code)))
1612
1613 printk( "fdomain: REQUEST SENSE "
1614 "Key = %x, Code = %x, Qualifier = %x\n",
1615 key, code, qualifier );
1616 }1617 }1618 #endif1619 #ifEVERY_ACCESS1620 printk( "BEFORE MY_DONE. . ." );
1621 #endif1622 my_done( (current_SC->SCp.Status & 0xff)
1623 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1624 #ifEVERY_ACCESS1625 printk( "RETURNING.\n" );
1626 #endif1627
1628 }else{1629 if (current_SC->SCp.phase & disconnect) {1630 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1631 outb( 0x00, SCSI_Cntl_port );
1632 }else{1633 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1634 }1635 }1636 #ifDEBUG_RACE1637 in_interrupt_flag = 0;
1638 #endif1639 return;
1640 }1641
1642 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1643 {1644 if (in_command) {1645 panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1646 }1647 #ifEVERY_ACCESS1648 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1649 SCpnt->target,
1650 *(unsignedchar *)SCpnt->cmnd,
1651 SCpnt->use_sg,
1652 SCpnt->request_bufflen );
1653 #endif1654
1655 fdomain_make_bus_idle();
1656
1657 current_SC = SCpnt; /* Save this for the done function */1658 current_SC->scsi_done = done;
1659
1660 /* Initialize static data */1661
1662 if (current_SC->use_sg) {1663 current_SC->SCp.buffer =
1664 (structscatterlist *)current_SC->request_buffer;
1665 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1666 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1667 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1668 }else{1669 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1670 current_SC->SCp.this_residual = current_SC->request_bufflen;
1671 current_SC->SCp.buffer = NULL;
1672 current_SC->SCp.buffers_residual = 0;
1673 }1674
1675
1676 current_SC->SCp.Status = 0;
1677 current_SC->SCp.Message = 0;
1678 current_SC->SCp.have_data_in = 0;
1679 current_SC->SCp.sent_command = 0;
1680 current_SC->SCp.phase = in_arbitration;
1681
1682 /* Start arbitration */1683 outb( 0x00, Interrupt_Cntl_port );
1684 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1685 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1686 ++in_command;
1687 outb( 0x20, Interrupt_Cntl_port );
1688 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1689
1690 return 0;
1691 }1692
1693 /* The following code, which simulates the old-style command function, was1694 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1695 1992 Tommy Thorn. */1696
1697 staticvolatileintinternal_done_flag = 0;
1698 staticvolatileintinternal_done_errcode = 0;
1699
1700 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1701 {1702 internal_done_errcode = SCpnt->result;
1703 ++internal_done_flag;
1704 }1705
1706 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1707 {1708 fdomain_16x0_queue( SCpnt, internal_done );
1709
1710 while (!internal_done_flag)
1711 ;
1712 internal_done_flag = 0;
1713 returninternal_done_errcode;
1714 }1715
1716 /* End of code derived from Tommy Thorn's work. */1717
1718 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1719 {1720 unsignedintimr;
1721 unsignedintirr;
1722 unsignedintisr;
1723
1724 if (!SCpnt || !SCpnt->host) {1725 printk( "fdomain: cannot provide detailed information\n" );
1726 }1727
1728 printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
1729 print_banner( SCpnt->host );
1730 switch (SCpnt->SCp.phase) {1731 casein_arbitration: printk( "arbitration " ); break;
1732 casein_selection: printk( "selection " ); break;
1733 casein_other: printk( "other " ); break;
1734 default: printk( "unknown " ); break;
1735 }1736
1737 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1738 SCpnt->SCp.phase,
1739 SCpnt->target,
1740 *(unsignedchar *)SCpnt->cmnd,
1741 SCpnt->use_sg,
1742 SCpnt->request_bufflen );
1743 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1744 SCpnt->SCp.sent_command,
1745 SCpnt->SCp.have_data_in,
1746 SCpnt->timeout );
1747 #ifDEBUG_RACE1748 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1749 #endif1750
1751 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1752 outb( 0x0a, 0xa0 );
1753 irr = inb( 0xa0 ) << 8;
1754 outb( 0x0a, 0x20 );
1755 irr += inb( 0x20 );
1756 outb( 0x0b, 0xa0 );
1757 isr = inb( 0xa0 ) << 8;
1758 outb( 0x0b, 0x20 );
1759 isr += inb( 0x20 );
1760
1761 /* Print out interesting information */1762 printk( "IMR = 0x%04x", imr );
1763 if (imr & (1 << interrupt_level))
1764 printk( " (masked)" );
1765 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1766
1767 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1768 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1769 if (inb( TMC_Status_port & 1))
1770 printk( " (interrupt)" );
1771 printk( "\n" );
1772 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1773 if (inb( Interrupt_Status_port ) & 0x08)
1774 printk( " (enabled)" );
1775 printk( "\n" );
1776 if (chip == tmc18c50 || chip == tmc18c30) {1777 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1778 printk( "Int. Condition = 0x%02x\n",
1779 inb( port_base + Interrupt_Cond ) );
1780 }1781 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1782 if (chip == tmc18c50 || chip == tmc18c30)
1783 printk( "Configuration 2 = 0x%02x\n",
1784 inb( port_base + Configuration2 ) );
1785 }1786
1787 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1788 {1789 unsignedlongflags;
1790 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1791 printk( "fdomain: abort " );
1792 #endif1793
1794 save_flags( flags );
1795 cli();
1796 if (!in_command) {1797 #ifEVERY_ACCESS || ERRORS_ONLY1798 printk( " (not in command)\n" );
1799 #endif1800 restore_flags( flags );
1801 returnSCSI_ABORT_NOT_RUNNING;
1802 }elseprintk( "\n" );
1803
1804 #ifDEBUG_ABORT1805 print_info( SCpnt );
1806 #endif1807
1808 fdomain_make_bus_idle();
1809
1810 current_SC->SCp.phase |= aborted;
1811
1812 current_SC->result = DID_ABORT << 16;
1813
1814 restore_flags( flags );
1815
1816 /* Aborts are not done well. . . */1817 my_done( DID_ABORT << 16 );
1818
1819 returnSCSI_ABORT_SUCCESS;
1820 }1821
1822 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1823 {1824 #ifDEBUG_RESET1825 staticintcalled_once = 0;
1826 #endif1827
1828 #ifERRORS_ONLY1829 if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
1830 #endif1831
1832 #ifDEBUG_RESET1833 if (called_once) print_info( current_SC );
1834 called_once = 1;
1835 #endif1836
1837 outb( 1, SCSI_Cntl_port );
1838 do_pause( 2 );
1839 outb( 0, SCSI_Cntl_port );
1840 do_pause( 115 );
1841 outb( 0, SCSI_Mode_Cntl_port );
1842 outb( PARITY_MASK, TMC_Cntl_port );
1843
1844 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1845 is probably hosed at this point. We will, however, try to keep1846 things going by informing the high-level code that we need help. */1847
1848 returnSCSI_RESET_WAKEUP;
1849 }1850
1851 #include "sd.h"
1852 #include "scsi_ioctl.h"
1853
1854 intfdomain_16x0_biosparam( Scsi_Disk *disk, kdev_tdev, int *info_array )
/* */1855 {1856 intdrive;
1857 unsignedcharbuf[512 + sizeof( int ) * 2];
1858 intsize = disk->capacity;
1859 int *sizes = (int *)buf;
1860 unsignedchar *data = (unsignedchar *)(sizes + 2);
1861 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1862 intretcode;
1863 structdrive_info{1864 unsignedshortcylinders;
1865 unsignedcharheads;
1866 unsignedcharsectors;
1867 } *i;
1868
1869 /* NOTES:1870 The RAM area starts at 0x1f00 from the bios_base address.1871
1872 For BIOS Version 2.0:1873 1874 The drive parameter table seems to start at 0x1f30.1875 The first byte's purpose is not known.1876 Next is the cylinder, head, and sector information.1877 The last 4 bytes appear to be the drive's size in sectors.1878 The other bytes in the drive parameter table are unknown.1879 If anyone figures them out, please send me mail, and I will1880 update these notes.1881
1882 Tape drives do not get placed in this table.1883
1884 There is another table at 0x1fea:1885 If the byte is 0x01, then the SCSI ID is not in use.1886 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1887 although tapes don't seem to be in this table. I haven't1888 seen any other numbers (in a limited sample).1889
1890 0x1f2d is a drive count (i.e., not including tapes)1891
1892 The table at 0x1fcc are I/O ports addresses for the various1893 operations. I calculate these by hand in this driver code.1894
1895 1896 1897 For the ISA-200S version of BIOS Version 2.0:1898
1899 The drive parameter table starts at 0x1f33.1900
1901 WARNING: Assume that the table entry is 25 bytes long. Someone needs1902 to check this for the Quantum ISA-200S card.1903
1904 1905 1906 For BIOS Version 3.2:1907
1908 The drive parameter table starts at 0x1f70. Each entry is1909 0x0a bytes long. Heads are one less than we need to report.1910 */1911
1912 drive = MINOR(dev) / 16;
1913
1914 if (bios_major == 2) {1915 switch (Quantum) {1916 case 2: /* ISA_200S */1917 /* The value of 25 has never been verified.1918 It should probably be 15. */1919 i = (structdrive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1920 break;
1921 case 3: /* ISA_250MG */1922 i = (structdrive_info *)( (char *)bios_base + 0x1f36 + drive * 15 );
1923 break;
1924 case 4: /* ISA_200S (another one) */1925 i = (structdrive_info *)( (char *)bios_base + 0x1f34 + drive * 15 );
1926 break;
1927 default:
1928 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1929 break;
1930 }1931 info_array[0] = i->heads;
1932 info_array[1] = i->sectors;
1933 info_array[2] = i->cylinders;
1934 }elseif (bios_major == 3
1935 && bios_minor >= 0
1936 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1937 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1938 info_array[0] = i->heads + 1;
1939 info_array[1] = i->sectors;
1940 info_array[2] = i->cylinders;
1941 }else{/* 3.4 BIOS (and up?) */1942 /* This algorithm was provided by Future Domain (much thanks!). */1943
1944 sizes[0] = 0; /* zero bytes out */1945 sizes[1] = 512; /* one sector in */1946 memcpy( data, do_read, sizeof( do_read ) );
1947 retcode = kernel_scsi_ioctl( disk->device,
1948 SCSI_IOCTL_SEND_COMMAND,
1949 (void *)buf );
1950 if (!retcode/* SCSI command ok */1951 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1952 && data[0x1c2]) {/* Partition type */1953
1954 /* The partition table layout is as follows:1955
1956 Start: 0x1b3h1957 Offset: 0 = partition status1958 1 = starting head1959 2 = starting sector and cylinder (word, encoded)1960 4 = partition type1961 5 = ending head1962 6 = ending sector and cylinder (word, encoded)1963 8 = starting absolute sector (double word)1964 c = number of sectors (double word)1965 Signature: 0x1fe = 0x55aa1966
1967 So, this algorithm assumes:1968 1) the first partition table is in use,1969 2) the data in the first entry is correct, and1970 3) partitions never divide cylinders1971
1972 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1973 as well as for Linux. Note also, that Linux doesn't pay any1974 attention to the fields that are used by this algorithm -- it1975 only uses the absolute sector data. Recent versions of Linux's1976 fdisk(1) will fill this data in correctly, and forthcoming1977 versions will check for consistency.1978
1979 Checking for a non-zero partition type is not part of the1980 Future Domain algorithm, but it seemed to be a reasonable thing1981 to do, especially in the Linux and BSD worlds. */1982
1983 info_array[0] = data[0x1c3] + 1; /* heads */1984 info_array[1] = data[0x1c4] & 0x3f; /* sectors */1985 }else{1986
1987 /* Note that this new method guarantees that there will always be1988 less than 1024 cylinders on a platter. This is good for drives1989 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */1990
1991 if ((unsignedint)size >= 0x7e0000U) {1992 info_array[0] = 0xff; /* heads = 255 */1993 info_array[1] = 0x3f; /* sectors = 63 */1994 }elseif ((unsignedint)size >= 0x200000U) {1995 info_array[0] = 0x80; /* heads = 128 */1996 info_array[1] = 0x3f; /* sectors = 63 */1997 }else{1998 info_array[0] = 0x40; /* heads = 64 */1999 info_array[1] = 0x20; /* sectors = 32 */2000 }2001 }2002 /* For both methods, compute the cylinders */2003 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
2004 }2005
2006 return 0;
2007 }2008
2009 #ifdefMODULE2010 /* Eventually this will go into an include file, but this will be later */2011 Scsi_Host_Templatedriver_template = FDOMAIN_16X0;
2012
2013 #include "scsi_module.c"
2014 #endif