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: Tue Jul 4 13:58:47 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.33 1995/07/04 18:59:49 faith 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, 141 and to Martin Andrews (andrewm@ccfadm.eeg.ccf.org) for the signature to 142 some random TMC-1680 repackaged by IBM. 143
144 Thanks for Mark Singer (elf@netcom.com) and Richard Simpson 145 (rsimpson@ewrcsdra.demon.co.uk) for more Quantum signatures and detective 146 work on the Quantum RAM layout. 147
148 Special thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for 149 providing patches for proper PCI BIOS32-mediated detection of the TMC-3260 150 card (a PCI bus card with the 36C70 chip). Please send James PCI-related 151 bug reports. 152 153 All of the alpha testers deserve much thanks. 154
155
156
157 NOTES ON USER DEFINABLE OPTIONS: 158
159 DEBUG: This turns on the printing of various debug information. 160
161 ENABLE_PARITY: This turns on SCSI parity checking. With the current 162 driver, all attached devices must support SCSI parity. If none of your 163 devices support parity, then you can probably get the driver to work by 164 turning this option off. I have no way of testing this, however. 165
166 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the 167 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by 168 the SCSI device, an interrupt will be raised. Therefore, this could be as 169 low as 0, or as high as 16. Note, however, that values which are too high 170 or too low seem to prevent any interrupts from occurring, and thereby lock 171 up the machine. I have found that 2 is a good number, but throughput may 172 be increased by changing this value to values which are close to 2. 173 Please let me know if you try any different values. 174
175 DO_DETECT: This activates some old scan code which was needed before the 176 high level drivers got fixed. If you are having trouble with the driver, 177 turning this on should not hurt, and might help. Please let me know if 178 this is the case, since this code will be removed from future drivers. 179
180 RESELECTION: This is no longer an option, since I gave up trying to 181 implement it in version 4.x of this driver. It did not improve 182 performance at all and made the driver unstable (because I never found one 183 of the two race conditions which were introduced by the multiple 184 outstanding command code). The instability seems a very high price to pay 185 just so that you don't have to wait for the tape to rewind. If you want 186 this feature implemented, send me patches. I'll be happy to send a copy 187 of my (broken) driver to anyone who would like to see a copy. 188
189 **************************************************************************/ 190
191 #ifdefMODULE 192 #include <linux/module.h>
193 #endif 194
195 #include <linux/sched.h>
196 #include <asm/io.h>
197 #include "../block/blk.h"
198 #include "scsi.h"
199 #include "hosts.h"
200 #include "fdomain.h"
201 #include <asm/system.h>
202 #include <linux/errno.h>
203 #include <linux/string.h>
204 #include <linux/ioport.h>
205 #include <linux/proc_fs.h>
206 #include <linux/bios32.h>
207 #include <linux/pci.h>
208
209 #defineVERSION "$Revision: 5.33 $"
210
211 /* START OF USER DEFINABLE OPTIONS */ 212
213 #defineDEBUG 1 /* Enable debugging output */ 214 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 215 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 216 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 217
218 /* END OF USER DEFINABLE OPTIONS */ 219
220 #ifDEBUG 221 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 222 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 223 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 224 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 225 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 226 #defineDEBUG_RESET 1 /* Debug reset() routine */ 227 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 228 #else 229 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 230 #defineERRORS_ONLY 0
231 #defineDEBUG_DETECT 0
232 #defineDEBUG_MESSAGES 0
233 #defineDEBUG_ABORT 0
234 #defineDEBUG_RESET 0
235 #defineDEBUG_RACE 0
236 #endif 237
238 /* Errors are reported on the line, so we don't need to report them again */ 239 #ifEVERY_ACCESS 240 #undefERRORS_ONLY 241 #defineERRORS_ONLY 0
242 #endif 243
244 #ifENABLE_PARITY 245 #definePARITY_MASK 0x08
246 #else 247 #definePARITY_MASK 0x00
248 #endif 249
250 enumchip_type{ 251 unknown = 0x00,
252 tmc1800 = 0x01,
253 tmc18c50 = 0x02,
254 tmc18c30 = 0x03,
255 };
256
257 enum{ 258 in_arbitration = 0x02,
259 in_selection = 0x04,
260 in_other = 0x08,
261 disconnect = 0x10,
262 aborted = 0x20,
263 sent_ident = 0x40,
264 };
265
266 enum in_port_type { 267 Read_SCSI_Data = 0,
268 SCSI_Status = 1,
269 TMC_Status = 2,
270 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 271 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 272 LSB_ID_Code = 5,
273 MSB_ID_Code = 6,
274 Read_Loopback = 7,
275 SCSI_Data_NoACK = 8,
276 Interrupt_Status = 9,
277 Configuration1 = 10,
278 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 279 Read_FIFO = 12,
280 FIFO_Data_Count = 14
281 };
282
283 enum out_port_type { 284 Write_SCSI_Data = 0,
285 SCSI_Cntl = 1,
286 Interrupt_Cntl = 2,
287 SCSI_Mode_Cntl = 3,
288 TMC_Cntl = 4,
289 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 290 Write_Loopback = 7,
291 IO_Control = 11, /* tmc18c30 only */ 292 Write_FIFO = 12
293 };
294
295 staticintport_base = 0;
296 staticvoid *bios_base = NULL;
297 staticintbios_major = 0;
298 staticintbios_minor = 0;
299 staticintPCI_bus = 0;
300 staticintQuantum = 0; /* Quantum board variant */ 301 staticintinterrupt_level = 0;
302 staticvolatileintin_command = 0;
303 staticScsi_Cmnd *current_SC = NULL;
304 staticenumchip_typechip = unknown;
305 staticintadapter_mask = 0x40;
306 #ifDEBUG_RACE 307 staticvolatileintin_interrupt_flag = 0;
308 #endif 309
310 staticintSCSI_Mode_Cntl_port;
311 staticintFIFO_Data_Count_port;
312 staticintInterrupt_Cntl_port;
313 staticintInterrupt_Status_port;
314 staticintRead_FIFO_port;
315 staticintRead_SCSI_Data_port;
316 staticintSCSI_Cntl_port;
317 staticintSCSI_Data_NoACK_port;
318 staticintSCSI_Status_port;
319 staticintTMC_Cntl_port;
320 staticintTMC_Status_port;
321 staticintWrite_FIFO_port;
322 staticintWrite_SCSI_Data_port;
323
324 staticintFIFO_Size = 0x2000; /* 8k FIFO for 325 pre-tmc18c30 chips */ 326
327 externvoidfdomain_16x0_intr( intirq, structpt_regs * regs );
328
329 staticvoid *addresses[] = { 330 (void *)0xc8000,
331 (void *)0xca000,
332 (void *)0xce000,
333 (void *)0xde000,
334 (void *)0xd0000, /* Extra addresses for PCI boards */ 335 (void *)0xe0000,
336 };
337 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
338
339 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
340 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
341
342 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
343
344 /* 345
346 READ THIS BEFORE YOU ADD A SIGNATURE! 347
348 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 349
350 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 351
352 This driver works *ONLY* for Future Domain cards using the TMC-1800, 353 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 354 and 1680. 355
356 The following BIOS signature signatures are for boards which do *NOT* 357 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 358 Seagate driver): 359
360 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 361 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 362 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 363 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 364 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 365 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 366 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 367
368 */ 369
370 structsignature{ 371 char *signature;
372 intsig_offset;
373 intsig_length;
374 intmajor_bios_version;
375 intminor_bios_version;
376 intflag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ 377 }signatures[] = { 378 /* 1 2 3 4 5 6 */ 379 /* 123456789012345678901234567890123456789012345678901234567890 */ 380 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
381 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
382 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
383 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
384 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
385 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
386 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
387 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
388 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
389 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
390 /* This next signature may not be a 3.5 bios */ 391 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
392 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
393 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
394 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
395
396 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE 397 Also, fix the disk geometry code for your signature and send your 398 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 399 signatures! 400
401 Note that the last line will match a "generic" 18XX bios. Because 402 Future Domain has changed the host SCSI ID and/or the location of the 403 geometry information in the on-board RAM area for each of the first 404 three BIOS's, it is still important to enter a fully qualified 405 signature in the table for any new BIOS's (after the host SCSI ID and 406 geometry location are verified). */ 407 };
408
409 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
410
411 staticvoidprint_banner( structScsi_Host *shpnt )
412 { 413 if (!shpnt) return; /* This won't ever happen */ 414
415 printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
416
417 if (bios_major >= 0) printk( "%d.", bios_major );
418 elseprintk( "?." );
419
420 if (bios_minor >= 0) printk( "%d", bios_minor );
421 elseprintk( "?." );
422
423 printk( " at 0x%x using scsi id %d\n",
424 (unsigned)bios_base, shpnt->this_id );
425
426 /* If this driver works for later FD PCI 427 boards, we will have to modify banner 428 for additional PCI cards, but for now if 429 it's PCI it's a TMC-3260 - JTM */ 430 printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
431 shpnt->host_no,
432 chip == tmc1800 ? "TMC-1800"
433 : (chip == tmc18c50 ? "TMC-18C50"
434 : (chip == tmc18c30 ?
435 (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30")
436 : "Unknown")),
437 port_base );
438
439 if (interrupt_level) printk( "%d", interrupt_level );
440 elseprintk( "<none>" );
441
442 printk( "\n" );
443 } 444
445 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 446 { 447 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 448
449 while (jiffies < the_time);
450 } 451
452 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 453 { 454 outb( 0, SCSI_Cntl_port );
455 outb( 0, SCSI_Mode_Cntl_port );
456 if (chip == tmc18c50 || chip == tmc18c30)
457 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 458 else 459 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
460 } 461
462 staticintfdomain_is_valid_port( intport )
/* */ 463 { 464 #ifDEBUG_DETECT 465 printk( " (%x%x),",
466 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
467 #endif 468
469 /* The MCA ID is a unique id for each MCA compatible board. We 470 are using ISA boards, but Future Domain provides the MCA ID 471 anyway. We can use this ID to ensure that this is a Future 472 Domain TMC-1660/TMC-1680. 473 */ 474
475 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 476 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
477 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
478 chip = tmc1800;
479 }else{/* test for 0xe960 id */ 480 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
481 chip = tmc18c50;
482
483 #if 0
484
485 /* Try to toggle 32-bit mode. This only 486 works on an 18c30 chip. (User reports 487 say that this doesn't work at all, so 488 we'll use the other method.) */ 489
490 outb( 0x80, port + IO_Control );
491 if ((inb( port + Configuration2 ) & 0x80) == 0x80) { 492 outb( 0x00, port + IO_Control );
493 if ((inb( port + Configuration2 ) & 0x80) == 0x00) { 494 chip = tmc18c30;
495 FIFO_Size = 0x800; /* 2k FIFO */ 496 } 497 } 498 #else 499
500 /* That should have worked, but appears to 501 have problems. Lets assume it is an 502 18c30 if the RAM is disabled. */ 503
504 if (inb( port + Configuration2 ) & 0x02) { 505 chip = tmc18c30;
506 FIFO_Size = 0x800; /* 2k FIFO */ 507 } 508 #endif 509 /* If that failed, we are an 18c50. */ 510 } 511
512 return 1;
513 } 514
515 staticintfdomain_test_loopback( void )
/* */ 516 { 517 inti;
518 intresult;
519
520 for (i = 0; i < 255; i++) { 521 outb( i, port_base + Write_Loopback );
522 result = inb( port_base + Read_Loopback );
523 if (i != result)
524 return 1;
525 } 526 return 0;
527 } 528
529 /* fdomain_get_irq assumes that we have a valid MCA ID for a 530 TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the 531 bios_base matches these ports. If someone was unlucky enough to have 532 purchased more than one Future Domain board, then they will have to 533 modify this code, as we only detect one board here. [The one with the 534 lowest bios_base.] 535
536 Note that this routine is only used for systems without a PCI BIOS32 537 (e.g., ISA bus). For PCI bus systems, this routine will likely fail 538 unless one of the IRQs listed in the ints array is used by the board. 539 Sometimes it is possible to use the computer's BIOS setup screen to 540 configure a PCI system so that one of these IRQs will be used by the 541 Future Domain card. */ 542
543 staticintfdomain_get_irq( intbase )
/* */ 544 { 545 intoptions = inb( base + Configuration1 );
546
547 #ifDEBUG_DETECT 548 printk( " Options = %x\n", options );
549 #endif 550
551 /* Check for board with lowest bios_base -- 552 this isn't valid for the 18c30 or for 553 boards on the PCI bus, so just assume we 554 have the right board. */ 555
556 if (chip != tmc18c30 557 && !PCI_bus 558 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
559
560 returnints[ (options & 0x0e) >> 1 ];
561 } 562
563 staticintfdomain_isa_detect( int *irq, int *iobase )
/* */ 564 { 565 inti;
566 intbase;
567 intflag = 0;
568
569 if (bios_major == 2) { 570 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 571 Assuming the ROM is enabled (otherwise we wouldn't have been 572 able to read the ROM signature :-), then the ROM sets up the 573 RAM area with some magic numbers, such as a list of port 574 base addresses and a list of the disk "geometry" reported to 575 DOS (this geometry has nothing to do with physical geometry). 576 */ 577
578 switch (Quantum) { 579 case 2: /* ISA_200S */ 580 case 3: /* ISA_250MG */ 581 base = *((char *)bios_base + 0x1fa2)
582 + (*((char *)bios_base + 0x1fa3) << 8);
583 break;
584 case 4: /* ISA_200S (another one) */ 585 base = *((char *)bios_base + 0x1fa3)
586 + (*((char *)bios_base + 0x1fa4) << 8);
587 break;
588 default:
589 base = *((char *)bios_base + 0x1fcc)
590 + (*((char *)bios_base + 0x1fcd) << 8);
591 break;
592 } 593
594 #ifDEBUG_DETECT 595 printk( " %x,", base );
596 #endif 597
598 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 599 if (base == ports[i])
600 ++flag;
601 } 602
603 if (flag && fdomain_is_valid_port( base )) { 604 *irq = fdomain_get_irq( base );
605 *iobase = base;
606 return 1;
607 } 608
609 /* This is a bad sign. It usually means that someone patched the 610 BIOS signature list (the signatures variable) to contain a BIOS 611 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ 612
613 #ifDEBUG_DETECT 614 printk( " RAM FAILED, " );
615 #endif 616 } 617
618 /* Anyway, the alternative to finding the address in the RAM is to just 619 search through every possible port address for one that is attached 620 to the Future Domain card. Don't panic, though, about reading all 621 these random port addresses -- there are rumors that the Future 622 Domain BIOS does something very similar. 623
624 Do not, however, check ports which the kernel knows are being used by 625 another driver. */ 626
627 for (i = 0; i < PORT_COUNT; i++) { 628 base = ports[i];
629 if (check_region( base, 0x10 )) { 630 #ifDEBUG_DETECT 631 printk( " (%x inuse),", base );
632 #endif 633 continue;
634 } 635 #ifDEBUG_DETECT 636 printk( " %x,", base );
637 #endif 638 if ((flag = fdomain_is_valid_port( base ))) break;
639 } 640
641 if (!flag) return 0; /* iobase not found */ 642
643 *irq = fdomain_get_irq( base );
644 *iobase = base;
645
646 return 1; /* success */ 647 } 648
649 staticintfdomain_pci_nobios_detect( int *irq, int *iobase )
/* */ 650 { 651 inti;
652 intflag = 0;
653
654 /* The proper way of doing this is to use ask the PCI bus for the device 655 IRQ and interrupt level. But we can't do that if PCI BIOS32 support 656 isn't compiled into the kernel, or if a PCI BIOS32 isn't present. 657
658 Instead, we scan down a bunch of addresses (Future Domain tech 659 support says we will probably find the address before we get to 660 0xf800). This works fine on some systems -- other systems may have 661 to scan more addresses. If you have to modify this section for your 662 installation, please send mail to faith@cs.unc.edu. */ 663
664 for (i = 0xfff8; i > 0xe000; i -= 8) { 665 if (check_region( i, 0x10 )) { 666 #ifDEBUG_DETECT 667 printk( " (%x inuse)," , i );
668 #endif 669 continue;
670 } 671 if ((flag = fdomain_is_valid_port( i ))) break;
672 } 673
674 if (!flag) return 0; /* iobase not found */ 675
676 *irq = fdomain_get_irq( i );
677 *iobase = i;
678
679 return 1; /* success */ 680 } 681
682 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* 683 iobase) This function gets the Interrupt Level and I/O base address from 684 the PCI configuration registers. The I/O base address is masked with 685 0xfff8 since on my card the address read from the PCI config registers 686 is off by one from the actual I/O base address necessary for accessing 687 the status and control registers on the card (PCI config register gives 688 0xf801, actual address is 0xf800). This is likely a bug in the FD 689 config code that writes to the PCI registers, however using a mask 690 should be safe since I think the scan done by the card to determine the 691 I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at 692 least the old scan code we used to use to get the I/O base did... Also, 693 the device ID from the PCI config registers is 0x0 and should be 0x60e9 694 as it is in the status registers (offset 5 from I/O base). If this is 695 changed in future hardware/BIOS changes it will need to be fixed in this 696 detection function. Comments, bug reports, etc... on this function 697 should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ 698
699 #ifdefCONFIG_PCI 700 staticintfdomain_pci_bios_detect( int *irq, int *iobase )
/* */ 701 { 702 interror;
703 unsignedcharpci_bus, pci_dev_fn; /* PCI bus & device function */ 704 unsignedcharpci_irq; /* PCI interrupt line */ 705 unsignedintpci_base; /* PCI I/O base address */ 706 unsignedshortpci_vendor, pci_device; /* PCI vendor & device IDs */ 707
708 /* If the PCI BIOS doesn't exist, use the old-style detection routines. 709 Otherwise, get the I/O base address and interrupt from the PCI config 710 registers. */ 711
712 if (!pcibios_present()) returnfdomain_pci_nobios_detect( irq, iobase );
713
714 #ifDEBUG_DETECT 715 /* Tell how to print a list of the known PCI devices from bios32 and 716 list vendor and device IDs being used if in debug mode. */ 717
718 printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
719 printk( "\nTMC-3260 detect:"
720 " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
721 PCI_VENDOR_ID_FD,
722 PCI_DEVICE_ID_FD_36C70 );
723 #endif 724
725 /* We will have to change this if more than 1 PCI bus is present and the 726 FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, 727 which is not supported by bios32 right now anyway). This should 728 probably be done by a call to pcibios_find_device but I can't get it 729 to work... Also the device ID reported from the PCI config registers 730 does not match the device ID quoted in the tech manual or available 731 from offset 5 from the I/O base address. It should be 0x60E9, but it 732 is 0x0 if read from the PCI config registers. I guess the FD folks 733 neglected to write it to the PCI registers... This loop is necessary 734 to get the device function (at least until someone can get 735 pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ 736
737 pci_bus = 0;
738
739 for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { 740 pcibios_read_config_word( pci_bus,
741 pci_dev_fn,
742 PCI_VENDOR_ID,
743 &pci_vendor );
744
745 if (pci_vendor == PCI_VENDOR_ID_FD) { 746 pcibios_read_config_word( pci_bus,
747 pci_dev_fn,
748 PCI_DEVICE_ID,
749 &pci_device );
750
751 if (pci_device == PCI_DEVICE_ID_FD_36C70) { 752 /* Break out once we have the correct device. If other FD 753 PCI devices are added to this driver we will need to add 754 an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ 755 break;
756 }else{ 757 /* If we can't find an FD scsi card we give up. */ 758 return 0;
759 } 760 } 761 } 762
763 #ifDEBUG_DETECT 764 printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
765 pci_bus,
766 (pci_dev_fn & 0xf8) >> 3,
767 pci_dev_fn & 7 );
768 #endif 769
770 /* We now have the appropriate device function for the FD board so we 771 just read the PCI config info from the registers. */ 772
773 if ((error = pcibios_read_config_dword( pci_bus,
774 pci_dev_fn,
775 PCI_BASE_ADDRESS_0,
776 &pci_base ))
777 || (error = pcibios_read_config_byte( pci_bus,
778 pci_dev_fn,
779 PCI_INTERRUPT_LINE,
780 &pci_irq ))) { 781 printk ( "PCI ERROR: Future Domain 36C70 not initializing"
782 " due to error reading configuration space\n" );
783 return 0;
784 }else{ 785 #ifDEBUG_DETECT 786 printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
787 pci_irq, pci_base );
788 #endif 789
790 /* Now we have the I/O base address and interrupt from the PCI 791 configuration registers. Unfortunately it seems that the I/O base 792 address is off by one on my card so I mask it with 0xfff8. This 793 must be some kind of goof in the FD code that does the autoconfig 794 and writes to the PCI registers (or maybe I just don't understand 795 something). If they fix it in later versions of the card or BIOS 796 we may have to adjust the address based on the signature or 797 something... */ 798
799 *irq = pci_irq;
800 *iobase = (pci_base & 0xfff8);
801
802 #ifDEBUG_DETECT 803 printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
804 printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
805 #endif 806
807 if (!fdomain_is_valid_port( *iobase )) return 0;
808 return 1;
809 } 810 return 0;
811 } 812 #endif 813
814 intfdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* */ 815 { 816 inti, j;
817 intflag = 0;
818 intretcode;
819 structScsi_Host *shpnt;
820 #ifDO_DETECT 821 constintbuflen = 255;
822 Scsi_CmndSCinit;
823 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
824 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
825 unsignedchardo_read_capacity[] = {READ_CAPACITY,
826 0, 0, 0, 0, 0, 0, 0, 0, 0 };
827 unsignedcharbuf[buflen];
828 #endif 829
830 #ifDEBUG_DETECT 831 printk( "fdomain_16x0_detect()," );
832 #endif 833
834 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 835 #ifDEBUG_DETECT 836 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
837 #endif 838 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 839 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
840 signatures[j].signature, signatures[j].sig_length )) { 841 bios_major = signatures[j].major_bios_version;
842 bios_minor = signatures[j].minor_bios_version;
843 PCI_bus = (signatures[j].flag == 1);
844 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
845 bios_base = addresses[i];
846 } 847 } 848 } 849
850 if (!bios_base) { 851 #ifDEBUG_DETECT 852 printk( " FAILED: NO BIOS\n" );
853 #endif 854 return 0;
855 } 856
857 if (!PCI_bus) { 858 flag = fdomain_isa_detect( &interrupt_level, &port_base );
859 }else{ 860 #ifdefCONFIG_PCI 861 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
862 #else 863 flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
864 #endif 865 } 866
867 if (!flag) { 868 #ifDEBUG_DETECT 869 printk( " FAILED: NO PORT\n" );
870 #endif 871 #ifdefCONFIG_PCI 872 printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
873 printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" );
874 #endif 875 return 0; /* Cannot find valid set of ports */ 876 } 877
878 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
879 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
880 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
881 Interrupt_Status_port = port_base + Interrupt_Status;
882 Read_FIFO_port = port_base + Read_FIFO;
883 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
884 SCSI_Cntl_port = port_base + SCSI_Cntl;
885 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
886 SCSI_Status_port = port_base + SCSI_Status;
887 TMC_Cntl_port = port_base + TMC_Cntl;
888 TMC_Status_port = port_base + TMC_Status;
889 Write_FIFO_port = port_base + Write_FIFO;
890 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
891
892 fdomain_16x0_reset( NULL );
893
894 if (fdomain_test_loopback()) { 895 #ifDEBUG_DETECT 896 printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
897 #endif 898 return 0;
899 } 900
901 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 902 adapter_mask = 0x80;
903 tpnt->this_id = 7;
904 } 905
906 /* Print out a banner here in case we can't 907 get resources. */ 908
909 shpnt = scsi_register( tpnt, 0 );
910 print_banner( shpnt );
911
912 /* Log IRQ with kernel */ 913 if (!interrupt_level) { 914 panic( "fdomain: *NO* interrupt level selected!\n" );
915 }else{ 916 /* Register the IRQ with the kernel */ 917
918 retcode = request_irq( interrupt_level,
919 fdomain_16x0_intr, SA_INTERRUPT, "fdomain" );
920
921 if (retcode < 0) { 922 if (retcode == -EINVAL) { 923 printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
924 printk( " This shouldn't happen!\n" );
925 printk( " Send mail to faith@cs.unc.edu\n" );
926 }elseif (retcode == -EBUSY) { 927 printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
928 printk( " Please use another IRQ!\n" );
929 }else{ 930 printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
931 printk( " This shouldn't happen!\n" );
932 printk( " Send mail to faith@cs.unc.edu\n" );
933 } 934 panic( "fdomain: Driver requires interruptions\n" );
935 } 936 } 937
938 /* Log I/O ports with kernel */ 939 request_region( port_base, 0x10, "fdomain" );
940
941 #ifDO_DETECT 942
943 /* These routines are here because of the way the SCSI bus behaves after 944 a reset. This appropriate behavior was not handled correctly by the 945 higher level SCSI routines when I first wrote this driver. Now, 946 however, correct scan routines are part of scsi.c and these routines 947 are no longer needed. However, this code is still good for 948 debugging. */ 949
950 SCinit.request_buffer = SCinit.buffer = buf;
951 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
952 SCinit.use_sg = 0;
953 SCinit.lun = 0;
954
955 printk( "fdomain: detection routine scanning for devices:\n" );
956 for (i = 0; i < 8; i++) { 957 SCinit.target = i;
958 if (i == tpnt->this_id) /* Skip host adapter */ 959 continue;
960 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
961 retcode = fdomain_16x0_command(&SCinit);
962 if (!retcode) { 963 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
964 retcode = fdomain_16x0_command(&SCinit);
965 if (!retcode) { 966 printk( " SCSI ID %d: ", i );
967 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
968 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
969 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
970 retcode = fdomain_16x0_command(&SCinit);
971 if (!retcode) { 972 unsignedlongblocks, size, capacity;
973
974 blocks = (buf[0] << 24) | (buf[1] << 16)
975 | (buf[2] << 8) | buf[3];
976 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
977 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
978
979 printk( "%lu MB (%lu byte blocks)",
980 ((capacity + 5L) / 10L), size );
981 }else{ 982 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
983 retcode = fdomain_16x0_command(&SCinit);
984 } 985 printk ("\n" );
986 }else{ 987 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
988 retcode = fdomain_16x0_command(&SCinit);
989 } 990 } 991 } 992 #endif 993
994 return 1; /* Maximum of one adapter will be detected. */ 995 } 996
997 constchar *fdomain_16x0_info( structScsi_Host *ignore )
/* */ 998 { 999 staticcharbuffer[80];
1000 char *pt;
1001
1002 strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
1003 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */1004 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1005 pt = strrchr( buffer, '$') - 1;
1006 if (!pt) /* Stripped RCS Revision string? */1007 pt = buffer + strlen( buffer ) - 1;
1008 if (*pt != ' ')
1009 ++pt;
1010 *pt = '\0';
1011 }else{/* Assume VERSION is a number */1012 strcat( buffer, " " VERSION );
1013 }1014
1015 returnbuffer;
1016 }1017
1018 #if 0
1019 staticint fdomain_arbitrate( void )
/* */1020 {1021 intstatus = 0;
1022 unsignedlongtimeout;
1023
1024 #ifEVERY_ACCESS1025 printk( "fdomain_arbitrate()\n" );
1026 #endif1027
1028 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1029 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */1030 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1031
1032 timeout = jiffies + 50; /* 500 mS */1033 while (jiffies < timeout) {1034 status = inb( TMC_Status_port ); /* Read adapter status */1035 if (status & 0x02) /* Arbitration complete */1036 return 0;
1037 }1038
1039 /* Make bus idle */1040 fdomain_make_bus_idle();
1041
1042 #ifEVERY_ACCESS1043 printk( "Arbitration failed, status = %x\n", status );
1044 #endif1045 #ifERRORS_ONLY1046 printk( "fdomain: Arbitration failed, status = %x\n", status );
1047 #endif1048 return 1;
1049 }1050 #endif1051
1052 staticintfdomain_select( inttarget )
/* */1053 {1054 intstatus;
1055 unsignedlongtimeout;
1056 staticintflag = 0;
1057
1058
1059 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1060 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
1061
1062 /* Stop arbitration and enable parity */1063 outb( PARITY_MASK, TMC_Cntl_port );
1064
1065 timeout = jiffies + 35; /* 350mS -- because of timeouts1066 (was 250mS) */1067
1068 while (jiffies < timeout) {1069 status = inb( SCSI_Status_port ); /* Read adapter status */1070 if (status & 1) {/* Busy asserted */1071 /* Enable SCSI Bus (on error, should make bus idle with 0) */1072 outb( 0x80, SCSI_Cntl_port );
1073 return 0;
1074 }1075 }1076 /* Make bus idle */1077 fdomain_make_bus_idle();
1078 #ifEVERY_ACCESS1079 if (!target) printk( "Selection failed\n" );
1080 #endif1081 #ifERRORS_ONLY1082 if (!target) {1083 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */1084 ++flag;
1085 else1086 printk( "fdomain: Selection failed\n" );
1087 }1088 #endif1089 return 1;
1090 }1091
1092 voidmy_done( interror )
/* */1093 {1094 if (in_command) {1095 in_command = 0;
1096 outb( 0x00, Interrupt_Cntl_port );
1097 fdomain_make_bus_idle();
1098 current_SC->result = error;
1099 if (current_SC->scsi_done)
1100 current_SC->scsi_done( current_SC );
1101 elsepanic( "fdomain: current_SC->scsi_done() == NULL" );
1102 }else{1103 panic( "fdomain: my_done() called outside of command\n" );
1104 }1105 #ifDEBUG_RACE1106 in_interrupt_flag = 0;
1107 #endif1108 }1109
1110 voidfdomain_16x0_intr( intirq, structpt_regs * regs )
/* */1111 {1112 intstatus;
1113 intdone = 0;
1114 unsigneddata_count;
1115
1116 /* The fdomain_16x0_intr is only called via1117 the interrupt handler. The goal of the1118 sti() here is to allow other1119 interruptions while this routine is1120 running. */1121
1122 sti(); /* Yes, we really want sti() here */1123
1124 outb( 0x00, Interrupt_Cntl_port );
1125
1126 /* We usually have one spurious interrupt after each command. Ignore it. */1127 if (!in_command || !current_SC) {/* Spurious interrupt */1128 #ifEVERY_ACCESS1129 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1130 in_command, current_SC );
1131 #endif1132 return;
1133 }1134
1135 /* Abort calls my_done, so we do nothing here. */1136 if (current_SC->SCp.phase & aborted) {1137 #ifDEBUG_ABORT1138 printk( "Interrupt after abort, ignoring\n" );
1139 #endif1140 /*1141 return; */1142 }1143
1144 #ifDEBUG_RACE1145 ++in_interrupt_flag;
1146 #endif1147
1148 if (current_SC->SCp.phase & in_arbitration) {1149 status = inb( TMC_Status_port ); /* Read adapter status */1150 if (!(status & 0x02)) {1151 #ifEVERY_ACCESS1152 printk( " AFAIL " );
1153 #endif1154 my_done( DID_BUS_BUSY << 16 );
1155 return;
1156 }1157 current_SC->SCp.phase = in_selection;
1158
1159 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
1160
1161 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1162 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
1163
1164 /* Stop arbitration and enable parity */1165 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1166 #ifDEBUG_RACE1167 in_interrupt_flag = 0;
1168 #endif1169 return;
1170 }elseif (current_SC->SCp.phase & in_selection) {1171 status = inb( SCSI_Status_port );
1172 if (!(status & 0x01)) {1173 /* Try again, for slow devices */1174 if (fdomain_select( current_SC->target )) {1175 #ifEVERY_ACCESS1176 printk( " SFAIL " );
1177 #endif1178 my_done( DID_NO_CONNECT << 16 );
1179 return;
1180 }else{1181 #ifEVERY_ACCESS1182 printk( " AltSel " );
1183 #endif1184 /* Stop arbitration and enable parity */1185 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1186 }1187 }1188 current_SC->SCp.phase = in_other;
1189 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1190 outb( 0x80, SCSI_Cntl_port );
1191 #ifDEBUG_RACE1192 in_interrupt_flag = 0;
1193 #endif1194 return;
1195 }1196
1197 /* current_SC->SCp.phase == in_other: this is the body of the routine */1198
1199 status = inb( SCSI_Status_port );
1200
1201 if (status & 0x10) {/* REQ */1202
1203 switch (status & 0x0e) {1204
1205 case 0x08: /* COMMAND OUT */1206 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
1207 Write_SCSI_Data_port );
1208 #ifEVERY_ACCESS1209 printk( "CMD = %x,",
1210 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1211 #endif1212 break;
1213 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */1214 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1215 current_SC->SCp.have_data_in = -1;
1216 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1217 }1218 break;
1219 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */1220 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1221 current_SC->SCp.have_data_in = 1;
1222 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1223 }1224 break;
1225 case 0x0c: /* STATUS IN */1226 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
1227 #ifEVERY_ACCESS1228 printk( "Status = %x, ", current_SC->SCp.Status );
1229 #endif1230 #ifERRORS_ONLY1231 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {1232 printk( "fdomain: target = %d, command = %x, status = %x\n",
1233 current_SC->target,
1234 current_SC->cmnd[0],
1235 current_SC->SCp.Status );
1236 }1237 #endif1238 break;
1239 case 0x0a: /* MESSAGE OUT */1240 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */1241 break;
1242 case 0x0e: /* MESSAGE IN */1243 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1244 #ifEVERY_ACCESS1245 printk( "Message = %x, ", current_SC->SCp.Message );
1246 #endif1247 if (!current_SC->SCp.Message) ++done;
1248 #ifDEBUG_MESSAGES || EVERY_ACCESS1249 if (current_SC->SCp.Message) {1250 printk( "fdomain: message = %x\n", current_SC->SCp.Message );
1251 }1252 #endif1253 break;
1254 }1255 }1256
1257 if (chip == tmc18001258 && !current_SC->SCp.have_data_in1259 && (current_SC->SCp.sent_command1260 >= current_SC->cmd_len)) {1261 /* We have to get the FIFO direction1262 correct, so I've made a table based1263 on the SCSI Standard of which commands1264 appear to require a DATA OUT phase.1265 */1266 /*1267 p. 94: Command for all device types1268 CHANGE DEFINITION 40 DATA OUT1269 COMPARE 39 DATA OUT1270 COPY 18 DATA OUT1271 COPY AND VERIFY 3a DATA OUT1272 INQUIRY 12 1273 LOG SELECT 4c DATA OUT1274 LOG SENSE 4d1275 MODE SELECT (6) 15 DATA OUT1276 MODE SELECT (10) 55 DATA OUT1277 MODE SENSE (6) 1a1278 MODE SENSE (10) 5a1279 READ BUFFER 3c1280 RECEIVE DIAGNOSTIC RESULTS 1c1281 REQUEST SENSE 031282 SEND DIAGNOSTIC 1d DATA OUT1283 TEST UNIT READY 001284 WRITE BUFFER 3b DATA OUT1285
1286 p.178: Commands for direct-access devices (not listed on p. 94)1287 FORMAT UNIT 04 DATA OUT1288 LOCK-UNLOCK CACHE 361289 PRE-FETCH 341290 PREVENT-ALLOW MEDIUM REMOVAL 1e1291 READ (6)/RECEIVE 081292 READ (10) 3c1293 READ CAPACITY 251294 READ DEFECT DATA (10) 371295 READ LONG 3e1296 REASSIGN BLOCKS 07 DATA OUT1297 RELEASE 171298 RESERVE 16 DATA OUT1299 REZERO UNIT/REWIND 011300 SEARCH DATA EQUAL (10) 31 DATA OUT1301 SEARCH DATA HIGH (10) 30 DATA OUT1302 SEARCH DATA LOW (10) 32 DATA OUT1303 SEEK (6) 0b1304 SEEK (10) 2b1305 SET LIMITS (10) 331306 START STOP UNIT 1b1307 SYNCHRONIZE CACHE 351308 VERIFY (10) 2f1309 WRITE (6)/PRINT/SEND 0a DATA OUT1310 WRITE (10)/SEND 2a DATA OUT1311 WRITE AND VERIFY (10) 2e DATA OUT1312 WRITE LONG 3f DATA OUT1313 WRITE SAME 41 DATA OUT ?1314
1315 p. 261: Commands for sequential-access devices (not previously listed)1316 ERASE 191317 LOAD UNLOAD 1b1318 LOCATE 2b1319 READ BLOCK LIMITS 051320 READ POSITION 341321 READ REVERSE 0f1322 RECOVER BUFFERED DATA 141323 SPACE 111324 WRITE FILEMARKS 10 ?1325
1326 p. 298: Commands for printer devices (not previously listed)1327 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1328 SLEW AND PRINT 0b DATA OUT -- same as seek1329 STOP PRINT 1b1330 SYNCHRONIZE BUFFER 101331
1332 p. 315: Commands for processor devices (not previously listed)1333 1334 p. 321: Commands for write-once devices (not previously listed)1335 MEDIUM SCAN 381336 READ (12) a81337 SEARCH DATA EQUAL (12) b1 DATA OUT1338 SEARCH DATA HIGH (12) b0 DATA OUT1339 SEARCH DATA LOW (12) b2 DATA OUT1340 SET LIMITS (12) b31341 VERIFY (12) af1342 WRITE (12) aa DATA OUT1343 WRITE AND VERIFY (12) ae DATA OUT1344
1345 p. 332: Commands for CD-ROM devices (not previously listed)1346 PAUSE/RESUME 4b1347 PLAY AUDIO (10) 451348 PLAY AUDIO (12) a51349 PLAY AUDIO MSF 471350 PLAY TRACK RELATIVE (10) 491351 PLAY TRACK RELATIVE (12) a91352 READ HEADER 441353 READ SUB-CHANNEL 421354 READ TOC 431355
1356 p. 370: Commands for scanner devices (not previously listed)1357 GET DATA BUFFER STATUS 341358 GET WINDOW 251359 OBJECT POSITION 311360 SCAN 1b1361 SET WINDOW 24 DATA OUT1362
1363 p. 391: Commands for optical memory devices (not listed)1364 ERASE (10) 2c1365 ERASE (12) ac1366 MEDIUM SCAN 38 DATA OUT1367 READ DEFECT DATA (12) b71368 READ GENERATION 291369 READ UPDATED BLOCK 2d1370 UPDATE BLOCK 3d DATA OUT1371
1372 p. 419: Commands for medium changer devices (not listed)1373 EXCHANGE MEDIUM 461374 INITIALIZE ELEMENT STATUS 071375 MOVE MEDIUM a51376 POSITION TO ELEMENT 2b1377 READ ELEMENT STATUS b81378 REQUEST VOL. ELEMENT ADDRESS b51379 SEND VOLUME TAG b6 DATA OUT1380
1381 p. 454: Commands for communications devices (not listed previously)1382 GET MESSAGE (6) 081383 GET MESSAGE (10) 281384 GET MESSAGE (12) a81385 */1386
1387 switch (current_SC->cmnd[0]) {1388 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1389 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1390 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1391
1392 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1393 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1394 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1395 case 0x3f: case 0x41:
1396
1397 case 0xb1: case 0xb0: case 0xb2:
1398 case 0xaa: case 0xae:
1399
1400 case 0x24:
1401
1402 case 0x38: case 0x3d:
1403
1404 case 0xb6:
1405
1406 case 0xea: /* alternate number for WRITE LONG */1407
1408 current_SC->SCp.have_data_in = -1;
1409 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1410 break;
1411
1412 case 0x00:
1413 default:
1414
1415 current_SC->SCp.have_data_in = 1;
1416 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1417 break;
1418 }1419 }1420
1421 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1422 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1423 #ifEVERY_ACCESS1424 printk( "DC=%d, ", data_count ) ;
1425 #endif1426 if (data_count > current_SC->SCp.this_residual)
1427 data_count = current_SC->SCp.this_residual;
1428 if (data_count > 0) {1429 #ifEVERY_ACCESS1430 printk( "%d OUT, ", data_count );
1431 #endif1432 if (data_count == 1) {1433 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1434 --current_SC->SCp.this_residual;
1435 }else{1436 data_count >>= 1;
1437 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1438 current_SC->SCp.ptr += 2 * data_count;
1439 current_SC->SCp.this_residual -= 2 * data_count;
1440 }1441 }1442 if (!current_SC->SCp.this_residual) {1443 if (current_SC->SCp.buffers_residual) {1444 --current_SC->SCp.buffers_residual;
1445 ++current_SC->SCp.buffer;
1446 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1447 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1448 }else1449 break;
1450 }1451 }1452 }1453
1454 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1455 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1456 #ifEVERY_ACCESS1457 printk( "DC=%d, ", data_count );
1458 #endif1459 if (data_count > current_SC->SCp.this_residual)
1460 data_count = current_SC->SCp.this_residual;
1461 if (data_count) {1462 #ifEVERY_ACCESS1463 printk( "%d IN, ", data_count );
1464 #endif1465 if (data_count == 1) {1466 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1467 --current_SC->SCp.this_residual;
1468 }else{1469 data_count >>= 1; /* Number of words */1470 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1471 current_SC->SCp.ptr += 2 * data_count;
1472 current_SC->SCp.this_residual -= 2 * data_count;
1473 }1474 }1475 if (!current_SC->SCp.this_residual1476 && current_SC->SCp.buffers_residual) {1477 --current_SC->SCp.buffers_residual;
1478 ++current_SC->SCp.buffer;
1479 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1480 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1481 }1482 }1483 }1484
1485 if (done) {1486 #ifEVERY_ACCESS1487 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1488 #endif1489
1490 #ifERRORS_ONLY1491 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1492 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1493 unsignedcharkey;
1494 unsignedcharcode;
1495 unsignedcharqualifier;
1496
1497 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1498 & 0x0f;
1499 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1500 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1501 + 13));
1502
1503 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1504 && !(key == NOT_READY1505 && code == 0x04
1506 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1507 && !(key == ILLEGAL_REQUEST && (code == 0x25
1508 || code == 0x24
1509 || !code)))
1510
1511 printk( "fdomain: REQUEST SENSE "
1512 "Key = %x, Code = %x, Qualifier = %x\n",
1513 key, code, qualifier );
1514 }1515 }1516 #endif1517 #ifEVERY_ACCESS1518 printk( "BEFORE MY_DONE. . ." );
1519 #endif1520 my_done( (current_SC->SCp.Status & 0xff)
1521 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1522 #ifEVERY_ACCESS1523 printk( "RETURNING.\n" );
1524 #endif1525
1526 }else{1527 if (current_SC->SCp.phase & disconnect) {1528 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1529 outb( 0x00, SCSI_Cntl_port );
1530 }else{1531 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1532 }1533 }1534 #ifDEBUG_RACE1535 in_interrupt_flag = 0;
1536 #endif1537 return;
1538 }1539
1540 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1541 {1542 if (in_command) {1543 panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1544 }1545 #ifEVERY_ACCESS1546 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1547 SCpnt->target,
1548 *(unsignedchar *)SCpnt->cmnd,
1549 SCpnt->use_sg,
1550 SCpnt->request_bufflen );
1551 #endif1552
1553 fdomain_make_bus_idle();
1554
1555 current_SC = SCpnt; /* Save this for the done function */1556 current_SC->scsi_done = done;
1557
1558 /* Initialize static data */1559
1560 if (current_SC->use_sg) {1561 current_SC->SCp.buffer =
1562 (structscatterlist *)current_SC->request_buffer;
1563 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1564 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1565 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1566 }else{1567 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1568 current_SC->SCp.this_residual = current_SC->request_bufflen;
1569 current_SC->SCp.buffer = NULL;
1570 current_SC->SCp.buffers_residual = 0;
1571 }1572
1573
1574 current_SC->SCp.Status = 0;
1575 current_SC->SCp.Message = 0;
1576 current_SC->SCp.have_data_in = 0;
1577 current_SC->SCp.sent_command = 0;
1578 current_SC->SCp.phase = in_arbitration;
1579
1580 /* Start arbitration */1581 outb( 0x00, Interrupt_Cntl_port );
1582 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1583 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1584 ++in_command;
1585 outb( 0x20, Interrupt_Cntl_port );
1586 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1587
1588 return 0;
1589 }1590
1591 /* The following code, which simulates the old-style command function, was1592 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1593 1992 Tommy Thorn. */1594
1595 staticvolatileintinternal_done_flag = 0;
1596 staticvolatileintinternal_done_errcode = 0;
1597
1598 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1599 {1600 internal_done_errcode = SCpnt->result;
1601 ++internal_done_flag;
1602 }1603
1604 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1605 {1606 fdomain_16x0_queue( SCpnt, internal_done );
1607
1608 while (!internal_done_flag)
1609 ;
1610 internal_done_flag = 0;
1611 returninternal_done_errcode;
1612 }1613
1614 /* End of code derived from Tommy Thorn's work. */1615
1616 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1617 {1618 unsignedintimr;
1619 unsignedintirr;
1620 unsignedintisr;
1621
1622 if (!SCpnt || !SCpnt->host) {1623 printk( "fdomain: cannot provide detailed information\n" );
1624 }1625
1626 printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
1627 print_banner( SCpnt->host );
1628 switch (SCpnt->SCp.phase) {1629 casein_arbitration: printk( "arbitration " ); break;
1630 casein_selection: printk( "selection " ); break;
1631 casein_other: printk( "other " ); break;
1632 default: printk( "unknown " ); break;
1633 }1634
1635 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1636 SCpnt->SCp.phase,
1637 SCpnt->target,
1638 *(unsignedchar *)SCpnt->cmnd,
1639 SCpnt->use_sg,
1640 SCpnt->request_bufflen );
1641 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1642 SCpnt->SCp.sent_command,
1643 SCpnt->SCp.have_data_in,
1644 SCpnt->timeout );
1645 #ifDEBUG_RACE1646 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1647 #endif1648
1649 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1650 outb( 0x0a, 0xa0 );
1651 irr = inb( 0xa0 ) << 8;
1652 outb( 0x0a, 0x20 );
1653 irr += inb( 0x20 );
1654 outb( 0x0b, 0xa0 );
1655 isr = inb( 0xa0 ) << 8;
1656 outb( 0x0b, 0x20 );
1657 isr += inb( 0x20 );
1658
1659 /* Print out interesting information */1660 printk( "IMR = 0x%04x", imr );
1661 if (imr & (1 << interrupt_level))
1662 printk( " (masked)" );
1663 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1664
1665 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1666 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1667 if (inb( TMC_Status_port & 1))
1668 printk( " (interrupt)" );
1669 printk( "\n" );
1670 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1671 if (inb( Interrupt_Status_port ) & 0x08)
1672 printk( " (enabled)" );
1673 printk( "\n" );
1674 if (chip == tmc18c50 || chip == tmc18c30) {1675 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1676 printk( "Int. Condition = 0x%02x\n",
1677 inb( port_base + Interrupt_Cond ) );
1678 }1679 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1680 if (chip == tmc18c50 || chip == tmc18c30)
1681 printk( "Configuration 2 = 0x%02x\n",
1682 inb( port_base + Configuration2 ) );
1683 }1684
1685 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1686 {1687 unsignedlongflags;
1688 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1689 printk( "fdomain: abort " );
1690 #endif1691
1692 save_flags( flags );
1693 cli();
1694 if (!in_command) {1695 #ifEVERY_ACCESS || ERRORS_ONLY1696 printk( " (not in command)\n" );
1697 #endif1698 restore_flags( flags );
1699 returnSCSI_ABORT_NOT_RUNNING;
1700 }1701
1702 #ifDEBUG_ABORT1703 print_info( SCpnt );
1704 #endif1705
1706 fdomain_make_bus_idle();
1707
1708 current_SC->SCp.phase |= aborted;
1709
1710 current_SC->result = DID_ABORT << 16;
1711
1712 restore_flags( flags );
1713
1714 /* Aborts are not done well. . . */1715 my_done( DID_ABORT << 16 );
1716
1717 returnSCSI_ABORT_SUCCESS;
1718 }1719
1720 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1721 {1722 #ifDEBUG_RESET1723 staticintcalled_once = 0;
1724 #endif1725
1726 #ifERRORS_ONLY1727 if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
1728 #endif1729
1730 #ifDEBUG_RESET1731 if (called_once) print_info( current_SC );
1732 called_once = 1;
1733 #endif1734
1735 outb( 1, SCSI_Cntl_port );
1736 do_pause( 2 );
1737 outb( 0, SCSI_Cntl_port );
1738 do_pause( 115 );
1739 outb( 0, SCSI_Mode_Cntl_port );
1740 outb( PARITY_MASK, TMC_Cntl_port );
1741
1742 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1743 is probably hosed at this point. We will, however, try to keep1744 things going by informing the high-level code that we need help. */1745
1746 returnSCSI_RESET_WAKEUP;
1747 }1748
1749 #include "sd.h"
1750 #include "scsi_ioctl.h"
1751
1752 intfdomain_16x0_biosparam( Scsi_Disk *disk, intdev, int *info_array )
/* */1753 {1754 intdrive;
1755 unsignedcharbuf[512 + sizeof( int ) * 2];
1756 intsize = disk->capacity;
1757 int *sizes = (int *)buf;
1758 unsignedchar *data = (unsignedchar *)(sizes + 2);
1759 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1760 intretcode;
1761 structdrive_info{1762 unsignedshortcylinders;
1763 unsignedcharheads;
1764 unsignedcharsectors;
1765 } *i;
1766
1767 /* NOTES:1768 The RAM area starts at 0x1f00 from the bios_base address.1769
1770 For BIOS Version 2.0:1771 1772 The drive parameter table seems to start at 0x1f30.1773 The first byte's purpose is not known.1774 Next is the cylinder, head, and sector information.1775 The last 4 bytes appear to be the drive's size in sectors.1776 The other bytes in the drive parameter table are unknown.1777 If anyone figures them out, please send me mail, and I will1778 update these notes.1779
1780 Tape drives do not get placed in this table.1781
1782 There is another table at 0x1fea:1783 If the byte is 0x01, then the SCSI ID is not in use.1784 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1785 although tapes don't seem to be in this table. I haven't1786 seen any other numbers (in a limited sample).1787
1788 0x1f2d is a drive count (i.e., not including tapes)1789
1790 The table at 0x1fcc are I/O ports addresses for the various1791 operations. I calculate these by hand in this driver code.1792
1793 1794 1795 For the ISA-200S version of BIOS Version 2.0:1796
1797 The drive parameter table starts at 0x1f33.1798
1799 WARNING: Assume that the table entry is 25 bytes long. Someone needs1800 to check this for the Quantum ISA-200S card.1801
1802 1803 1804 For BIOS Version 3.2:1805
1806 The drive parameter table starts at 0x1f70. Each entry is1807 0x0a bytes long. Heads are one less than we need to report.1808 */1809
1810 drive = MINOR(dev) / 16;
1811
1812 if (bios_major == 2) {1813 switch (Quantum) {1814 case 2: /* ISA_200S */1815 /* The value of 25 has never been verified.1816 It should probably be 15. */1817 i = (structdrive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1818 break;
1819 case 3: /* ISA_250MG */1820 i = (structdrive_info *)( (char *)bios_base + 0x1f36 + drive * 15 );
1821 break;
1822 case 4: /* ISA_200S (another one) */1823 i = (structdrive_info *)( (char *)bios_base + 0x1f34 + drive * 15 );
1824 break;
1825 default:
1826 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1827 break;
1828 }1829 info_array[0] = i->heads;
1830 info_array[1] = i->sectors;
1831 info_array[2] = i->cylinders;
1832 }elseif (bios_major == 3
1833 && bios_minor >= 0
1834 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1835 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1836 info_array[0] = i->heads + 1;
1837 info_array[1] = i->sectors;
1838 info_array[2] = i->cylinders;
1839 }else{/* 3.4 BIOS (and up?) */1840 /* This algorithm was provided by Future Domain (much thanks!). */1841
1842 sizes[0] = 0; /* zero bytes out */1843 sizes[1] = 512; /* one sector in */1844 memcpy( data, do_read, sizeof( do_read ) );
1845 retcode = kernel_scsi_ioctl( disk->device,
1846 SCSI_IOCTL_SEND_COMMAND,
1847 (void *)buf );
1848 if (!retcode/* SCSI command ok */1849 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1850 && data[0x1c2]) {/* Partition type */1851
1852 /* The partition table layout is as follows:1853
1854 Start: 0x1b3h1855 Offset: 0 = partition status1856 1 = starting head1857 2 = starting sector and cylinder (word, encoded)1858 4 = partition type1859 5 = ending head1860 6 = ending sector and cylinder (word, encoded)1861 8 = starting absolute sector (double word)1862 c = number of sectors (double word)1863 Signature: 0x1fe = 0x55aa1864
1865 So, this algorithm assumes:1866 1) the first partition table is in use,1867 2) the data in the first entry is correct, and1868 3) partitions never divide cylinders1869
1870 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1871 as well as for Linux. Note also, that Linux doesn't pay any1872 attention to the fields that are used by this algorithm -- it1873 only uses the absolute sector data. Recent versions of Linux's1874 fdisk(1) will fill this data in correctly, and forthcoming1875 versions will check for consistency.1876
1877 Checking for a non-zero partition type is not part of the1878 Future Domain algorithm, but it seemed to be a reasonable thing1879 to do, especially in the Linux and BSD worlds. */1880
1881 info_array[0] = data[0x1c3] + 1; /* heads */1882 info_array[1] = data[0x1c4] & 0x3f; /* sectors */1883 }else{1884
1885 /* Note that this new method guarantees that there will always be1886 less than 1024 cylinders on a platter. This is good for drives1887 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */1888
1889 if ((unsignedint)size >= 0x7e0000U) {1890 info_array[0] = 0xff; /* heads = 255 */1891 info_array[1] = 0x3f; /* sectors = 63 */1892 }elseif ((unsignedint)size >= 0x200000U) {1893 info_array[0] = 0x80; /* heads = 128 */1894 info_array[1] = 0x3f; /* sectors = 63 */1895 }else{1896 info_array[0] = 0x40; /* heads = 64 */1897 info_array[1] = 0x20; /* sectors = 32 */1898 }1899 }1900 /* For both methods, compute the cylinders */1901 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
1902 }1903
1904 return 0;
1905 }1906
1907 #ifdefMODULE1908 /* Eventually this will go into an include file, but this will be later */1909 Scsi_Host_Templatedriver_template = FDOMAIN_16X0;
1910
1911 #include "scsi_module.c"
1912 #endif