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: Fri Jun 23 17:07:09 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.31 1995/06/23 21:07:16 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 #include <linux/sched.h>
192 #include <asm/io.h>
193 #include "../block/blk.h"
194 #include "scsi.h"
195 #include "hosts.h"
196 #include "fdomain.h"
197 #include <asm/system.h>
198 #include <linux/errno.h>
199 #include <linux/string.h>
200 #include <linux/ioport.h>
201 #include <linux/bios32.h>
202 #include <linux/pci.h>
203
204 #defineVERSION "$Revision: 5.31 $"
205
206 /* START OF USER DEFINABLE OPTIONS */ 207
208 #defineDEBUG 1 /* Enable debugging output */ 209 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 210 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 211 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 212
213 /* END OF USER DEFINABLE OPTIONS */ 214
215 #ifDEBUG 216 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 217 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 218 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 219 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 220 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 221 #defineDEBUG_RESET 1 /* Debug reset() routine */ 222 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 223 #else 224 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 225 #defineERRORS_ONLY 0
226 #defineDEBUG_DETECT 0
227 #defineDEBUG_MESSAGES 0
228 #defineDEBUG_ABORT 0
229 #defineDEBUG_RESET 0
230 #defineDEBUG_RACE 0
231 #endif 232
233 /* Errors are reported on the line, so we don't need to report them again */ 234 #ifEVERY_ACCESS 235 #undefERRORS_ONLY 236 #defineERRORS_ONLY 0
237 #endif 238
239 #ifENABLE_PARITY 240 #definePARITY_MASK 0x08
241 #else 242 #definePARITY_MASK 0x00
243 #endif 244
245 enumchip_type{ 246 unknown = 0x00,
247 tmc1800 = 0x01,
248 tmc18c50 = 0x02,
249 tmc18c30 = 0x03,
250 };
251
252 enum{ 253 in_arbitration = 0x02,
254 in_selection = 0x04,
255 in_other = 0x08,
256 disconnect = 0x10,
257 aborted = 0x20,
258 sent_ident = 0x40,
259 };
260
261 enum in_port_type { 262 Read_SCSI_Data = 0,
263 SCSI_Status = 1,
264 TMC_Status = 2,
265 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 266 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 267 LSB_ID_Code = 5,
268 MSB_ID_Code = 6,
269 Read_Loopback = 7,
270 SCSI_Data_NoACK = 8,
271 Interrupt_Status = 9,
272 Configuration1 = 10,
273 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 274 Read_FIFO = 12,
275 FIFO_Data_Count = 14
276 };
277
278 enum out_port_type { 279 Write_SCSI_Data = 0,
280 SCSI_Cntl = 1,
281 Interrupt_Cntl = 2,
282 SCSI_Mode_Cntl = 3,
283 TMC_Cntl = 4,
284 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 285 Write_Loopback = 7,
286 IO_Control = 11, /* tmc18c30 only */ 287 Write_FIFO = 12
288 };
289
290 staticintport_base = 0;
291 staticvoid *bios_base = NULL;
292 staticintbios_major = 0;
293 staticintbios_minor = 0;
294 staticintPCI_bus = 0;
295 staticintQuantum = 0; /* Quantum board variant */ 296 staticintinterrupt_level = 0;
297 staticvolatileintin_command = 0;
298 staticScsi_Cmnd *current_SC = NULL;
299 staticenumchip_typechip = unknown;
300 staticintadapter_mask = 0x40;
301 #ifDEBUG_RACE 302 staticvolatileintin_interrupt_flag = 0;
303 #endif 304
305 staticintSCSI_Mode_Cntl_port;
306 staticintFIFO_Data_Count_port;
307 staticintInterrupt_Cntl_port;
308 staticintInterrupt_Status_port;
309 staticintRead_FIFO_port;
310 staticintRead_SCSI_Data_port;
311 staticintSCSI_Cntl_port;
312 staticintSCSI_Data_NoACK_port;
313 staticintSCSI_Status_port;
314 staticintTMC_Cntl_port;
315 staticintTMC_Status_port;
316 staticintWrite_FIFO_port;
317 staticintWrite_SCSI_Data_port;
318
319 staticintFIFO_Size = 0x2000; /* 8k FIFO for 320 pre-tmc18c30 chips */ 321
322 externvoidfdomain_16x0_intr( intirq, structpt_regs * regs );
323
324 staticvoid *addresses[] = { 325 (void *)0xc8000,
326 (void *)0xca000,
327 (void *)0xce000,
328 (void *)0xde000,
329 (void *)0xd0000, /* Extra addresses for PCI boards */ 330 (void *)0xe0000,
331 };
332 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
333
334 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
335 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
336
337 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
338
339 /* 340
341 READ THIS BEFORE YOU ADD A SIGNATURE! 342
343 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 344
345 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 346
347 This driver works *ONLY* for Future Domain cards using the TMC-1800, 348 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 349 and 1680. 350
351 The following BIOS signature signatures are for boards which do *NOT* 352 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 353 Seagate driver): 354
355 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 356 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 357 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 358 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 359 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 360 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 361 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 362
363 */ 364
365 structsignature{ 366 char *signature;
367 intsig_offset;
368 intsig_length;
369 intmajor_bios_version;
370 intminor_bios_version;
371 intflag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ 372 }signatures[] = { 373 /* 1 2 3 4 5 6 */ 374 /* 123456789012345678901234567890123456789012345678901234567890 */ 375 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
376 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
377 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
378 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
379 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
380 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
381 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
382 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
383 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
384 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
385 /* This next signature may not be a 3.5 bios */ 386 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
387 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
388 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
389 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
390
391 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE 392 Also, fix the disk geometry code for your signature and send your 393 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 394 signatures! 395
396 Note that the last line will match a "generic" 18XX bios. Because 397 Future Domain has changed the host SCSI ID and/or the location of the 398 geometry information in the on-board RAM area for each of the first 399 three BIOS's, it is still important to enter a fully qualified 400 signature in the table for any new BIOS's (after the host SCSI ID and 401 geometry location are verified). */ 402 };
403
404 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
405
406 staticvoidprint_banner( structScsi_Host *shpnt )
407 { 408 if (!shpnt) return; /* This won't ever happen */ 409
410 printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
411
412 if (bios_major >= 0) printk( "%d.", bios_major );
413 elseprintk( "?." );
414
415 if (bios_minor >= 0) printk( "%d", bios_minor );
416 elseprintk( "?." );
417
418 printk( " at 0x%x using scsi id %d\n",
419 (unsigned)bios_base, shpnt->this_id );
420
421 /* If this driver works for later FD PCI 422 boards, we will have to modify banner 423 for additional PCI cards, but for now if 424 it's PCI it's a TMC-3260 - JTM */ 425 printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
426 shpnt->host_no,
427 chip == tmc1800 ? "TMC-1800"
428 : (chip == tmc18c50 ? "TMC-18C50"
429 : (chip == tmc18c30 ?
430 (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30")
431 : "Unknown")),
432 port_base );
433
434 if (interrupt_level) printk( "%d", interrupt_level );
435 elseprintk( "<none>" );
436
437 printk( "\n" );
438 } 439
440 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 441 { 442 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 443
444 while (jiffies < the_time);
445 } 446
447 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 448 { 449 outb( 0, SCSI_Cntl_port );
450 outb( 0, SCSI_Mode_Cntl_port );
451 if (chip == tmc18c50 || chip == tmc18c30)
452 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 453 else 454 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
455 } 456
457 staticintfdomain_is_valid_port( intport )
/* */ 458 { 459 #ifDEBUG_DETECT 460 printk( " (%x%x),",
461 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
462 #endif 463
464 /* The MCA ID is a unique id for each MCA compatible board. We 465 are using ISA boards, but Future Domain provides the MCA ID 466 anyway. We can use this ID to ensure that this is a Future 467 Domain TMC-1660/TMC-1680. 468 */ 469
470 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 471 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
472 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
473 chip = tmc1800;
474 }else{/* test for 0xe960 id */ 475 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
476 chip = tmc18c50;
477
478 #if 0
479
480 /* Try to toggle 32-bit mode. This only 481 works on an 18c30 chip. (User reports 482 say that this doesn't work at all, so 483 we'll use the other method.) */ 484
485 outb( 0x80, port + IO_Control );
486 if ((inb( port + Configuration2 ) & 0x80) == 0x80) { 487 outb( 0x00, port + IO_Control );
488 if ((inb( port + Configuration2 ) & 0x80) == 0x00) { 489 chip = tmc18c30;
490 FIFO_Size = 0x800; /* 2k FIFO */ 491 } 492 } 493 #else 494
495 /* That should have worked, but appears to 496 have problems. Lets assume it is an 497 18c30 if the RAM is disabled. */ 498
499 if (inb( port + Configuration2 ) & 0x02) { 500 chip = tmc18c30;
501 FIFO_Size = 0x800; /* 2k FIFO */ 502 } 503 #endif 504 /* If that failed, we are an 18c50. */ 505 } 506
507 return 1;
508 } 509
510 staticintfdomain_test_loopback( void )
/* */ 511 { 512 inti;
513 intresult;
514
515 for (i = 0; i < 255; i++) { 516 outb( i, port_base + Write_Loopback );
517 result = inb( port_base + Read_Loopback );
518 if (i != result)
519 return 1;
520 } 521 return 0;
522 } 523
524 /* fdomain_get_irq assumes that we have a valid MCA ID for a 525 TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the 526 bios_base matches these ports. If someone was unlucky enough to have 527 purchased more than one Future Domain board, then they will have to 528 modify this code, as we only detect one board here. [The one with the 529 lowest bios_base.] 530
531 Note that this routine is only used for systems without a PCI BIOS32 532 (e.g., ISA bus). For PCI bus systems, this routine will likely fail 533 unless one of the IRQs listed in the ints array is used by the board. 534 Sometimes it is possible to use the computer's BIOS setup screen to 535 configure a PCI system so that one of these IRQs will be used by the 536 Future Domain card. */ 537
538 staticintfdomain_get_irq( intbase )
/* */ 539 { 540 intoptions = inb( base + Configuration1 );
541
542 #ifDEBUG_DETECT 543 printk( " Options = %x\n", options );
544 #endif 545
546 /* Check for board with lowest bios_base -- 547 this isn't valid for the 18c30 or for 548 boards on the PCI bus, so just assume we 549 have the right board. */ 550
551 if (chip != tmc18c30 552 && !PCI_bus 553 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
554
555 returnints[ (options & 0x0e) >> 1 ];
556 } 557
558 staticintfdomain_isa_detect( int *irq, int *iobase )
/* */ 559 { 560 inti;
561 intbase;
562 intflag = 0;
563
564 if (bios_major == 2) { 565 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 566 Assuming the ROM is enabled (otherwise we wouldn't have been 567 able to read the ROM signature :-), then the ROM sets up the 568 RAM area with some magic numbers, such as a list of port 569 base addresses and a list of the disk "geometry" reported to 570 DOS (this geometry has nothing to do with physical geometry). 571 */ 572
573 switch (Quantum) { 574 case 2: /* ISA_200S */ 575 case 3: /* ISA_250MG */ 576 base = *((char *)bios_base + 0x1fa2)
577 + (*((char *)bios_base + 0x1fa3) << 8);
578 break;
579 case 4: /* ISA_200S (another one) */ 580 base = *((char *)bios_base + 0x1fa3)
581 + (*((char *)bios_base + 0x1fa4) << 8);
582 break;
583 default:
584 base = *((char *)bios_base + 0x1fcc)
585 + (*((char *)bios_base + 0x1fcd) << 8);
586 break;
587 } 588
589 #ifDEBUG_DETECT 590 printk( " %x,", base );
591 #endif 592
593 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 594 if (base == ports[i])
595 ++flag;
596 } 597
598 if (flag && fdomain_is_valid_port( base )) { 599 *irq = fdomain_get_irq( base );
600 *iobase = base;
601 return 1;
602 } 603
604 /* This is a bad sign. It usually means that someone patched the 605 BIOS signature list (the signatures variable) to contain a BIOS 606 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ 607
608 #ifDEBUG_DETECT 609 printk( " RAM FAILED, " );
610 #endif 611 } 612
613 /* Anyway, the alternative to finding the address in the RAM is to just 614 search through every possible port address for one that is attached 615 to the Future Domain card. Don't panic, though, about reading all 616 these random port addresses -- there are rumors that the Future 617 Domain BIOS does something very similar. 618
619 Do not, however, check ports which the kernel knows are being used by 620 another driver. */ 621
622 for (i = 0; i < PORT_COUNT; i++) { 623 base = ports[i];
624 if (check_region( base, 0x10 )) { 625 #ifDEBUG_DETECT 626 printk( " (%x inuse),", base );
627 #endif 628 continue;
629 } 630 #ifDEBUG_DETECT 631 printk( " %x,", base );
632 #endif 633 if ((flag = fdomain_is_valid_port( base ))) break;
634 } 635
636 if (!flag) return 0; /* iobase not found */ 637
638 *irq = fdomain_get_irq( base );
639 *iobase = base;
640
641 return 1; /* success */ 642 } 643
644 staticintfdomain_pci_nobios_detect( int *irq, int *iobase )
/* */ 645 { 646 inti;
647 intflag = 0;
648
649 /* The proper way of doing this is to use ask the PCI bus for the device 650 IRQ and interrupt level. But we can't do that if PCI BIOS32 support 651 isn't compiled into the kernel, or if a PCI BIOS32 isn't present. 652
653 Instead, we scan down a bunch of addresses (Future Domain tech 654 support says we will probably find the address before we get to 655 0xf800). This works fine on some systems -- other systems may have 656 to scan more addresses. If you have to modify this section for your 657 installation, please send mail to faith@cs.unc.edu. */ 658
659 for (i = 0xfff8; i > 0xe000; i -= 8) { 660 if (check_region( i, 0x10 )) { 661 #ifDEBUG_DETECT 662 printk( " (%x inuse)," , i );
663 #endif 664 continue;
665 } 666 if ((flag = fdomain_is_valid_port( i ))) break;
667 } 668
669 if (!flag) return 0; /* iobase not found */ 670
671 *irq = fdomain_get_irq( i );
672 *iobase = i;
673
674 return 1; /* success */ 675 } 676
677 /* PCI detection function: int fdomain_36c70_detect(int* irq, int* iobase) 678 This function gets the Interrupt Level and I/O base address from the PCI 679 configuration registers. The I/O base address is masked with 0xfff8 680 since on my card the address read from the PCI config registers is off 681 by one from the actual I/O base address necessary for accessing the 682 status and control registers on the card (PCI config register gives 683 0xf801, actual address is 0xf800). This is likely a bug in the FD 684 config code that writes to the PCI registers, however using a mask 685 should be safe since I think the scan done by the card to determine the 686 I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at 687 least the old scan code we used to use to get the I/O base did... Also, 688 the device ID from the PCI config registers is 0x0 and should be 0x60e9 689 as it is in the status registers (offset 5 from I/O base). If this is 690 changed in future hardware/BIOS changes it will need to be fixed in this 691 detection function. Comments, bug reports, etc... on this function 692 should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ 693
694 #ifdefPCI_CONFIG 695 staticint fdomain_36c70_detect( int *irq, int *iobase )
/* */ 696 { 697 interror;
698 unsignedcharpci_bus, pci_dev_fn; /* PCI bus & device function */ 699 unsignedcharpci_irq; /* PCI interrupt line */ 700 unsignedlongpci_base; /* PCI I/O base address */ 701 unsignedshortpci_vendor, pci_device; /* PCI vendor & device IDs */ 702
703 /* If the PCI BIOS doesn't exist, use the old-style detection routines. 704 Otherwise, get the I/O base address and interrupt from the PCI config 705 registers. */ 706
707 if (!pcibios_present()) return fdomain_pci_detect( irq, iobase );
708
709 #ifDEBUG_DETECT 710 /* Tell how to print a list of the known PCI devices from bios32 and 711 list vendor and device IDs being used if in debug mode. */ 712
713 printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
714 printk( "\nTMC-3260 detect:"
715 " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
716 PCI_VENDOR_ID_FD,
717 PCI_DEVICE_ID_FD_36C70 );
718 #endif 719
720 /* We will have to change this if more than 1 PCI bus is present and the 721 FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, 722 which is not supported by bios32 right now anyway). This should 723 probably be done by a call to pcibios_find_device but I can't get it 724 to work... Also the device ID reported from the PCI config registers 725 does not match the device ID quoted in the tech manual or available 726 from offset 5 from the I/O base address. It should be 0x60E9, but it 727 is 0x0 if read from the PCI config registers. I guess the FD folks 728 neglected to write it to the PCI registers... This loop is necessary 729 to get the device function (at least until someone can get 730 pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ 731
732 pci_bus = 0;
733
734 for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { 735 pcibios_read_config_word( pci_bus,
736 pci_dev_fn,
737 PCI_VENDOR_ID,
738 &pci_vendor );
739
740 if (pci_vendor == PCI_VENDOR_ID_FD) { 741 pcibios_read_config_word( pci_bus,
742 pci_dev_fn,
743 PCI_DEVICE_ID,
744 &pci_device );
745
746 if (pci_device == PCI_DEVICE_ID_FD_36C70) { 747 /* Break out once we have the correct device. If other FD 748 PCI devices are added to this driver we will need to add 749 an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ 750 break;
751 }else{ 752 /* If we can't find an FD scsi card we give up. */ 753 return 0;
754 } 755 } 756 } 757
758 #ifDEBUG_DETECT 759 printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
760 pci_bus,
761 (pci_dev_fn & 0xf8) >> 3,
762 pci_dev_fn & 7 );
763 #endif 764
765 /* We now have the appropriate device function for the FD board so we 766 just read the PCI config info from the registers. */ 767
768 if ((error = pcibios_read_config_dword( pci_bus,
769 pci_dev_fn,
770 PCI_BASE_ADDRESS_0,
771 &pci_base ))
772 || (error = pcibios_read_config_byte( pci_bus,
773 pci_dev_fn,
774 PCI_INTERRUPT_LINE,
775 &pci_irq ))) { 776 printk ( "PCI ERROR: Future Domain 36C70 not initializing"
777 " due to error reading configuration space\n" );
778 return 0;
779 }else{ 780 #ifDEBUG_DETECT 781 printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
782 pci_irq, pci_base );
783 #endif 784
785 /* Now we have the I/O base address and interrupt from the PCI 786 configuration registers. Unfortunately it seems that the I/O base 787 address is off by one on my card so I mask it with 0xfff8. This 788 must be some kind of goof in the FD code that does the autoconfig 789 and writes to the PCI registers (or maybe I just don't understand 790 something). If they fix it in later versions of the card or BIOS 791 we may have to adjust the address based on the signature or 792 something... */ 793
794 *irq = pci_irq;
795 *iobase = (pci_base & 0xfff8);
796
797 #ifDEBUG_DETECT 798 printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
799 printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
800 #endif 801
802 if (!fdomain_is_valid_port( *iobase )) return 0;
803 return 1;
804 } 805 return 0;
806 } 807 #endif 808
809 intfdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* */ 810 { 811 inti, j;
812 intflag = 0;
813 intretcode;
814 structScsi_Host *shpnt;
815 #ifDO_DETECT 816 constintbuflen = 255;
817 Scsi_CmndSCinit;
818 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
819 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
820 unsignedchardo_read_capacity[] = {READ_CAPACITY,
821 0, 0, 0, 0, 0, 0, 0, 0, 0 };
822 unsignedcharbuf[buflen];
823 #endif 824
825 #ifDEBUG_DETECT 826 printk( "fdomain_16x0_detect()," );
827 #endif 828
829 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 830 #ifDEBUG_DETECT 831 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
832 #endif 833 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 834 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
835 signatures[j].signature, signatures[j].sig_length )) { 836 bios_major = signatures[j].major_bios_version;
837 bios_minor = signatures[j].minor_bios_version;
838 PCI_bus = (signatures[j].flag == 1);
839 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
840 bios_base = addresses[i];
841 } 842 } 843 } 844
845 if (!bios_base) { 846 #ifDEBUG_DETECT 847 printk( " FAILED: NO BIOS\n" );
848 #endif 849 return 0;
850 } 851
852 if (!PCI_bus) { 853 flag = fdomain_isa_detect( &interrupt_level, &port_base );
854 }else{ 855 #ifdefPCI_CONFIG 856 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
857 #else 858 flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
859 #endif 860 } 861
862 if (!flag) { 863 #ifDEBUG_DETECT 864 printk( " FAILED: NO PORT\n" );
865 #endif 866 #ifdefPCI_CONFIG 867 printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
868 printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" );
869 #endif 870 return 0; /* Cannot find valid set of ports */ 871 } 872
873 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
874 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
875 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
876 Interrupt_Status_port = port_base + Interrupt_Status;
877 Read_FIFO_port = port_base + Read_FIFO;
878 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
879 SCSI_Cntl_port = port_base + SCSI_Cntl;
880 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
881 SCSI_Status_port = port_base + SCSI_Status;
882 TMC_Cntl_port = port_base + TMC_Cntl;
883 TMC_Status_port = port_base + TMC_Status;
884 Write_FIFO_port = port_base + Write_FIFO;
885 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
886
887 fdomain_16x0_reset( NULL );
888
889 if (fdomain_test_loopback()) { 890 #ifDEBUG_DETECT 891 printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
892 #endif 893 return 0;
894 } 895
896 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 897 adapter_mask = 0x80;
898 tpnt->this_id = 7;
899 } 900
901 /* Print out a banner here in case we can't 902 get resources. */ 903
904 shpnt = scsi_register( tpnt, 0 );
905 print_banner( shpnt );
906
907 /* Log IRQ with kernel */ 908 if (!interrupt_level) { 909 panic( "fdomain: *NO* interrupt level selected!\n" );
910 }else{ 911 /* Register the IRQ with the kernel */ 912
913 retcode = request_irq( interrupt_level,
914 fdomain_16x0_intr, SA_INTERRUPT, "fdomain" );
915
916 if (retcode < 0) { 917 if (retcode == -EINVAL) { 918 printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
919 printk( " This shouldn't happen!\n" );
920 printk( " Send mail to faith@cs.unc.edu\n" );
921 }elseif (retcode == -EBUSY) { 922 printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
923 printk( " Please use another IRQ!\n" );
924 }else{ 925 printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
926 printk( " This shouldn't happen!\n" );
927 printk( " Send mail to faith@cs.unc.edu\n" );
928 } 929 panic( "fdomain: Driver requires interruptions\n" );
930 } 931 } 932
933 /* Log I/O ports with kernel */ 934 request_region( port_base, 0x10, "fdomain" );
935
936 #ifDO_DETECT 937
938 /* These routines are here because of the way the SCSI bus behaves after 939 a reset. This appropriate behavior was not handled correctly by the 940 higher level SCSI routines when I first wrote this driver. Now, 941 however, correct scan routines are part of scsi.c and these routines 942 are no longer needed. However, this code is still good for 943 debugging. */ 944
945 SCinit.request_buffer = SCinit.buffer = buf;
946 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
947 SCinit.use_sg = 0;
948 SCinit.lun = 0;
949
950 printk( "fdomain: detection routine scanning for devices:\n" );
951 for (i = 0; i < 8; i++) { 952 SCinit.target = i;
953 if (i == tpnt->this_id) /* Skip host adapter */ 954 continue;
955 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
956 retcode = fdomain_16x0_command(&SCinit);
957 if (!retcode) { 958 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
959 retcode = fdomain_16x0_command(&SCinit);
960 if (!retcode) { 961 printk( " SCSI ID %d: ", i );
962 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
963 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
964 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
965 retcode = fdomain_16x0_command(&SCinit);
966 if (!retcode) { 967 unsignedlongblocks, size, capacity;
968
969 blocks = (buf[0] << 24) | (buf[1] << 16)
970 | (buf[2] << 8) | buf[3];
971 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
972 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
973
974 printk( "%lu MB (%lu byte blocks)",
975 ((capacity + 5L) / 10L), size );
976 }else{ 977 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
978 retcode = fdomain_16x0_command(&SCinit);
979 } 980 printk ("\n" );
981 }else{ 982 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
983 retcode = fdomain_16x0_command(&SCinit);
984 } 985 } 986 } 987 #endif 988
989 return 1; /* Maximum of one adapter will be detected. */ 990 } 991
992 constchar *fdomain_16x0_info( structScsi_Host *ignore )
/* */ 993 { 994 staticcharbuffer[80];
995 char *pt;
996
997 strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
998 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */ 999 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1000 pt = strrchr( buffer, '$') - 1;
1001 if (!pt) /* Stripped RCS Revision string? */1002 pt = buffer + strlen( buffer ) - 1;
1003 if (*pt != ' ')
1004 ++pt;
1005 *pt = '\0';
1006 }else{/* Assume VERSION is a number */1007 strcat( buffer, " " VERSION );
1008 }1009
1010 returnbuffer;
1011 }1012
1013 #if 0
1014 staticint fdomain_arbitrate( void )
/* */1015 {1016 intstatus = 0;
1017 unsignedlongtimeout;
1018
1019 #ifEVERY_ACCESS1020 printk( "fdomain_arbitrate()\n" );
1021 #endif1022
1023 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1024 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */1025 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1026
1027 timeout = jiffies + 50; /* 500 mS */1028 while (jiffies < timeout) {1029 status = inb( TMC_Status_port ); /* Read adapter status */1030 if (status & 0x02) /* Arbitration complete */1031 return 0;
1032 }1033
1034 /* Make bus idle */1035 fdomain_make_bus_idle();
1036
1037 #ifEVERY_ACCESS1038 printk( "Arbitration failed, status = %x\n", status );
1039 #endif1040 #ifERRORS_ONLY1041 printk( "fdomain: Arbitration failed, status = %x\n", status );
1042 #endif1043 return 1;
1044 }1045 #endif1046
1047 staticintfdomain_select( inttarget )
/* */1048 {1049 intstatus;
1050 unsignedlongtimeout;
1051 staticintflag = 0;
1052
1053
1054 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1055 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
1056
1057 /* Stop arbitration and enable parity */1058 outb( PARITY_MASK, TMC_Cntl_port );
1059
1060 timeout = jiffies + 35; /* 350mS -- because of timeouts1061 (was 250mS) */1062
1063 while (jiffies < timeout) {1064 status = inb( SCSI_Status_port ); /* Read adapter status */1065 if (status & 1) {/* Busy asserted */1066 /* Enable SCSI Bus (on error, should make bus idle with 0) */1067 outb( 0x80, SCSI_Cntl_port );
1068 return 0;
1069 }1070 }1071 /* Make bus idle */1072 fdomain_make_bus_idle();
1073 #ifEVERY_ACCESS1074 if (!target) printk( "Selection failed\n" );
1075 #endif1076 #ifERRORS_ONLY1077 if (!target) {1078 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */1079 ++flag;
1080 else1081 printk( "fdomain: Selection failed\n" );
1082 }1083 #endif1084 return 1;
1085 }1086
1087 voidmy_done( interror )
/* */1088 {1089 if (in_command) {1090 in_command = 0;
1091 outb( 0x00, Interrupt_Cntl_port );
1092 fdomain_make_bus_idle();
1093 current_SC->result = error;
1094 if (current_SC->scsi_done)
1095 current_SC->scsi_done( current_SC );
1096 elsepanic( "fdomain: current_SC->scsi_done() == NULL" );
1097 }else{1098 panic( "fdomain: my_done() called outside of command\n" );
1099 }1100 #ifDEBUG_RACE1101 in_interrupt_flag = 0;
1102 #endif1103 }1104
1105 voidfdomain_16x0_intr( intirq, structpt_regs * regs )
/* */1106 {1107 intstatus;
1108 intdone = 0;
1109 unsigneddata_count;
1110
1111 /* The fdomain_16x0_intr is only called via1112 the interrupt handler. The goal of the1113 sti() here is to allow other1114 interruptions while this routine is1115 running. */1116
1117 sti(); /* Yes, we really want sti() here */1118
1119 outb( 0x00, Interrupt_Cntl_port );
1120
1121 /* We usually have one spurious interrupt after each command. Ignore it. */1122 if (!in_command || !current_SC) {/* Spurious interrupt */1123 #ifEVERY_ACCESS1124 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1125 in_command, current_SC );
1126 #endif1127 return;
1128 }1129
1130 /* Abort calls my_done, so we do nothing here. */1131 if (current_SC->SCp.phase & aborted) {1132 #ifDEBUG_ABORT1133 printk( "Interrupt after abort, ignoring\n" );
1134 #endif1135 /*1136 return; */1137 }1138
1139 #ifDEBUG_RACE1140 ++in_interrupt_flag;
1141 #endif1142
1143 if (current_SC->SCp.phase & in_arbitration) {1144 status = inb( TMC_Status_port ); /* Read adapter status */1145 if (!(status & 0x02)) {1146 #ifEVERY_ACCESS1147 printk( " AFAIL " );
1148 #endif1149 my_done( DID_BUS_BUSY << 16 );
1150 return;
1151 }1152 current_SC->SCp.phase = in_selection;
1153
1154 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
1155
1156 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1157 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
1158
1159 /* Stop arbitration and enable parity */1160 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1161 #ifDEBUG_RACE1162 in_interrupt_flag = 0;
1163 #endif1164 return;
1165 }elseif (current_SC->SCp.phase & in_selection) {1166 status = inb( SCSI_Status_port );
1167 if (!(status & 0x01)) {1168 /* Try again, for slow devices */1169 if (fdomain_select( current_SC->target )) {1170 #ifEVERY_ACCESS1171 printk( " SFAIL " );
1172 #endif1173 my_done( DID_NO_CONNECT << 16 );
1174 return;
1175 }else{1176 #ifEVERY_ACCESS1177 printk( " AltSel " );
1178 #endif1179 /* Stop arbitration and enable parity */1180 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1181 }1182 }1183 current_SC->SCp.phase = in_other;
1184 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1185 outb( 0x80, SCSI_Cntl_port );
1186 #ifDEBUG_RACE1187 in_interrupt_flag = 0;
1188 #endif1189 return;
1190 }1191
1192 /* current_SC->SCp.phase == in_other: this is the body of the routine */1193
1194 status = inb( SCSI_Status_port );
1195
1196 if (status & 0x10) {/* REQ */1197
1198 switch (status & 0x0e) {1199
1200 case 0x08: /* COMMAND OUT */1201 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
1202 Write_SCSI_Data_port );
1203 #ifEVERY_ACCESS1204 printk( "CMD = %x,",
1205 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1206 #endif1207 break;
1208 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */1209 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1210 current_SC->SCp.have_data_in = -1;
1211 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1212 }1213 break;
1214 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */1215 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1216 current_SC->SCp.have_data_in = 1;
1217 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1218 }1219 break;
1220 case 0x0c: /* STATUS IN */1221 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
1222 #ifEVERY_ACCESS1223 printk( "Status = %x, ", current_SC->SCp.Status );
1224 #endif1225 #ifERRORS_ONLY1226 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {1227 printk( "fdomain: target = %d, command = %x, status = %x\n",
1228 current_SC->target,
1229 current_SC->cmnd[0],
1230 current_SC->SCp.Status );
1231 }1232 #endif1233 break;
1234 case 0x0a: /* MESSAGE OUT */1235 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */1236 break;
1237 case 0x0e: /* MESSAGE IN */1238 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1239 #ifEVERY_ACCESS1240 printk( "Message = %x, ", current_SC->SCp.Message );
1241 #endif1242 if (!current_SC->SCp.Message) ++done;
1243 #ifDEBUG_MESSAGES || EVERY_ACCESS1244 if (current_SC->SCp.Message) {1245 printk( "fdomain: message = %x\n", current_SC->SCp.Message );
1246 }1247 #endif1248 break;
1249 }1250 }1251
1252 if (chip == tmc18001253 && !current_SC->SCp.have_data_in1254 && (current_SC->SCp.sent_command1255 >= current_SC->cmd_len)) {1256 /* We have to get the FIFO direction1257 correct, so I've made a table based1258 on the SCSI Standard of which commands1259 appear to require a DATA OUT phase.1260 */1261 /*1262 p. 94: Command for all device types1263 CHANGE DEFINITION 40 DATA OUT1264 COMPARE 39 DATA OUT1265 COPY 18 DATA OUT1266 COPY AND VERIFY 3a DATA OUT1267 INQUIRY 12 1268 LOG SELECT 4c DATA OUT1269 LOG SENSE 4d1270 MODE SELECT (6) 15 DATA OUT1271 MODE SELECT (10) 55 DATA OUT1272 MODE SENSE (6) 1a1273 MODE SENSE (10) 5a1274 READ BUFFER 3c1275 RECEIVE DIAGNOSTIC RESULTS 1c1276 REQUEST SENSE 031277 SEND DIAGNOSTIC 1d DATA OUT1278 TEST UNIT READY 001279 WRITE BUFFER 3b DATA OUT1280
1281 p.178: Commands for direct-access devices (not listed on p. 94)1282 FORMAT UNIT 04 DATA OUT1283 LOCK-UNLOCK CACHE 361284 PRE-FETCH 341285 PREVENT-ALLOW MEDIUM REMOVAL 1e1286 READ (6)/RECEIVE 081287 READ (10) 3c1288 READ CAPACITY 251289 READ DEFECT DATA (10) 371290 READ LONG 3e1291 REASSIGN BLOCKS 07 DATA OUT1292 RELEASE 171293 RESERVE 16 DATA OUT1294 REZERO UNIT/REWIND 011295 SEARCH DATA EQUAL (10) 31 DATA OUT1296 SEARCH DATA HIGH (10) 30 DATA OUT1297 SEARCH DATA LOW (10) 32 DATA OUT1298 SEEK (6) 0b1299 SEEK (10) 2b1300 SET LIMITS (10) 331301 START STOP UNIT 1b1302 SYNCHRONIZE CACHE 351303 VERIFY (10) 2f1304 WRITE (6)/PRINT/SEND 0a DATA OUT1305 WRITE (10)/SEND 2a DATA OUT1306 WRITE AND VERIFY (10) 2e DATA OUT1307 WRITE LONG 3f DATA OUT1308 WRITE SAME 41 DATA OUT ?1309
1310 p. 261: Commands for sequential-access devices (not previously listed)1311 ERASE 191312 LOAD UNLOAD 1b1313 LOCATE 2b1314 READ BLOCK LIMITS 051315 READ POSITION 341316 READ REVERSE 0f1317 RECOVER BUFFERED DATA 141318 SPACE 111319 WRITE FILEMARKS 10 ?1320
1321 p. 298: Commands for printer devices (not previously listed)1322 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1323 SLEW AND PRINT 0b DATA OUT -- same as seek1324 STOP PRINT 1b1325 SYNCHRONIZE BUFFER 101326
1327 p. 315: Commands for processor devices (not previously listed)1328 1329 p. 321: Commands for write-once devices (not previously listed)1330 MEDIUM SCAN 381331 READ (12) a81332 SEARCH DATA EQUAL (12) b1 DATA OUT1333 SEARCH DATA HIGH (12) b0 DATA OUT1334 SEARCH DATA LOW (12) b2 DATA OUT1335 SET LIMITS (12) b31336 VERIFY (12) af1337 WRITE (12) aa DATA OUT1338 WRITE AND VERIFY (12) ae DATA OUT1339
1340 p. 332: Commands for CD-ROM devices (not previously listed)1341 PAUSE/RESUME 4b1342 PLAY AUDIO (10) 451343 PLAY AUDIO (12) a51344 PLAY AUDIO MSF 471345 PLAY TRACK RELATIVE (10) 491346 PLAY TRACK RELATIVE (12) a91347 READ HEADER 441348 READ SUB-CHANNEL 421349 READ TOC 431350
1351 p. 370: Commands for scanner devices (not previously listed)1352 GET DATA BUFFER STATUS 341353 GET WINDOW 251354 OBJECT POSITION 311355 SCAN 1b1356 SET WINDOW 24 DATA OUT1357
1358 p. 391: Commands for optical memory devices (not listed)1359 ERASE (10) 2c1360 ERASE (12) ac1361 MEDIUM SCAN 38 DATA OUT1362 READ DEFECT DATA (12) b71363 READ GENERATION 291364 READ UPDATED BLOCK 2d1365 UPDATE BLOCK 3d DATA OUT1366
1367 p. 419: Commands for medium changer devices (not listed)1368 EXCHANGE MEDIUM 461369 INITIALIZE ELEMENT STATUS 071370 MOVE MEDIUM a51371 POSITION TO ELEMENT 2b1372 READ ELEMENT STATUS b81373 REQUEST VOL. ELEMENT ADDRESS b51374 SEND VOLUME TAG b6 DATA OUT1375
1376 p. 454: Commands for communications devices (not listed previously)1377 GET MESSAGE (6) 081378 GET MESSAGE (10) 281379 GET MESSAGE (12) a81380 */1381
1382 switch (current_SC->cmnd[0]) {1383 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1384 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1385 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1386
1387 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1388 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1389 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1390 case 0x3f: case 0x41:
1391
1392 case 0xb1: case 0xb0: case 0xb2:
1393 case 0xaa: case 0xae:
1394
1395 case 0x24:
1396
1397 case 0x38: case 0x3d:
1398
1399 case 0xb6:
1400
1401 case 0xea: /* alternate number for WRITE LONG */1402
1403 current_SC->SCp.have_data_in = -1;
1404 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1405 break;
1406
1407 case 0x00:
1408 default:
1409
1410 current_SC->SCp.have_data_in = 1;
1411 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1412 break;
1413 }1414 }1415
1416 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1417 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1418 #ifEVERY_ACCESS1419 printk( "DC=%d, ", data_count ) ;
1420 #endif1421 if (data_count > current_SC->SCp.this_residual)
1422 data_count = current_SC->SCp.this_residual;
1423 if (data_count > 0) {1424 #ifEVERY_ACCESS1425 printk( "%d OUT, ", data_count );
1426 #endif1427 if (data_count == 1) {1428 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1429 --current_SC->SCp.this_residual;
1430 }else{1431 data_count >>= 1;
1432 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1433 current_SC->SCp.ptr += 2 * data_count;
1434 current_SC->SCp.this_residual -= 2 * data_count;
1435 }1436 }1437 if (!current_SC->SCp.this_residual) {1438 if (current_SC->SCp.buffers_residual) {1439 --current_SC->SCp.buffers_residual;
1440 ++current_SC->SCp.buffer;
1441 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1442 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1443 }else1444 break;
1445 }1446 }1447 }1448
1449 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1450 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1451 #ifEVERY_ACCESS1452 printk( "DC=%d, ", data_count );
1453 #endif1454 if (data_count > current_SC->SCp.this_residual)
1455 data_count = current_SC->SCp.this_residual;
1456 if (data_count) {1457 #ifEVERY_ACCESS1458 printk( "%d IN, ", data_count );
1459 #endif1460 if (data_count == 1) {1461 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1462 --current_SC->SCp.this_residual;
1463 }else{1464 data_count >>= 1; /* Number of words */1465 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1466 current_SC->SCp.ptr += 2 * data_count;
1467 current_SC->SCp.this_residual -= 2 * data_count;
1468 }1469 }1470 if (!current_SC->SCp.this_residual1471 && current_SC->SCp.buffers_residual) {1472 --current_SC->SCp.buffers_residual;
1473 ++current_SC->SCp.buffer;
1474 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1475 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1476 }1477 }1478 }1479
1480 if (done) {1481 #ifEVERY_ACCESS1482 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1483 #endif1484
1485 #ifERRORS_ONLY1486 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1487 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1488 unsignedcharkey;
1489 unsignedcharcode;
1490 unsignedcharqualifier;
1491
1492 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1493 & 0x0f;
1494 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1495 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1496 + 13));
1497
1498 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1499 && !(key == NOT_READY1500 && code == 0x04
1501 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1502 && !(key == ILLEGAL_REQUEST && (code == 0x25
1503 || code == 0x24
1504 || !code)))
1505
1506 printk( "fdomain: REQUEST SENSE "
1507 "Key = %x, Code = %x, Qualifier = %x\n",
1508 key, code, qualifier );
1509 }1510 }1511 #endif1512 #ifEVERY_ACCESS1513 printk( "BEFORE MY_DONE. . ." );
1514 #endif1515 my_done( (current_SC->SCp.Status & 0xff)
1516 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1517 #ifEVERY_ACCESS1518 printk( "RETURNING.\n" );
1519 #endif1520
1521 }else{1522 if (current_SC->SCp.phase & disconnect) {1523 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1524 outb( 0x00, SCSI_Cntl_port );
1525 }else{1526 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1527 }1528 }1529 #ifDEBUG_RACE1530 in_interrupt_flag = 0;
1531 #endif1532 return;
1533 }1534
1535 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1536 {1537 if (in_command) {1538 panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1539 }1540 #ifEVERY_ACCESS1541 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1542 SCpnt->target,
1543 *(unsignedchar *)SCpnt->cmnd,
1544 SCpnt->use_sg,
1545 SCpnt->request_bufflen );
1546 #endif1547
1548 fdomain_make_bus_idle();
1549
1550 current_SC = SCpnt; /* Save this for the done function */1551 current_SC->scsi_done = done;
1552
1553 /* Initialize static data */1554
1555 if (current_SC->use_sg) {1556 current_SC->SCp.buffer =
1557 (structscatterlist *)current_SC->request_buffer;
1558 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1559 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1560 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1561 }else{1562 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1563 current_SC->SCp.this_residual = current_SC->request_bufflen;
1564 current_SC->SCp.buffer = NULL;
1565 current_SC->SCp.buffers_residual = 0;
1566 }1567
1568
1569 current_SC->SCp.Status = 0;
1570 current_SC->SCp.Message = 0;
1571 current_SC->SCp.have_data_in = 0;
1572 current_SC->SCp.sent_command = 0;
1573 current_SC->SCp.phase = in_arbitration;
1574
1575 /* Start arbitration */1576 outb( 0x00, Interrupt_Cntl_port );
1577 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1578 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1579 ++in_command;
1580 outb( 0x20, Interrupt_Cntl_port );
1581 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1582
1583 return 0;
1584 }1585
1586 /* The following code, which simulates the old-style command function, was1587 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1588 1992 Tommy Thorn. */1589
1590 staticvolatileintinternal_done_flag = 0;
1591 staticvolatileintinternal_done_errcode = 0;
1592
1593 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1594 {1595 internal_done_errcode = SCpnt->result;
1596 ++internal_done_flag;
1597 }1598
1599 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1600 {1601 fdomain_16x0_queue( SCpnt, internal_done );
1602
1603 while (!internal_done_flag)
1604 ;
1605 internal_done_flag = 0;
1606 returninternal_done_errcode;
1607 }1608
1609 /* End of code derived from Tommy Thorn's work. */1610
1611 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1612 {1613 unsignedintimr;
1614 unsignedintirr;
1615 unsignedintisr;
1616
1617 if (!SCpnt || !SCpnt->host) {1618 printk( "fdomain: cannot provide detailed information\n" );
1619 }1620
1621 printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
1622 print_banner( SCpnt->host );
1623 switch (SCpnt->SCp.phase) {1624 casein_arbitration: printk( "arbitration " ); break;
1625 casein_selection: printk( "selection " ); break;
1626 casein_other: printk( "other " ); break;
1627 default: printk( "unknown " ); break;
1628 }1629
1630 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1631 SCpnt->SCp.phase,
1632 SCpnt->target,
1633 *(unsignedchar *)SCpnt->cmnd,
1634 SCpnt->use_sg,
1635 SCpnt->request_bufflen );
1636 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1637 SCpnt->SCp.sent_command,
1638 SCpnt->SCp.have_data_in,
1639 SCpnt->timeout );
1640 #ifDEBUG_RACE1641 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1642 #endif1643
1644 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1645 outb( 0x0a, 0xa0 );
1646 irr = inb( 0xa0 ) << 8;
1647 outb( 0x0a, 0x20 );
1648 irr += inb( 0x20 );
1649 outb( 0x0b, 0xa0 );
1650 isr = inb( 0xa0 ) << 8;
1651 outb( 0x0b, 0x20 );
1652 isr += inb( 0x20 );
1653
1654 /* Print out interesting information */1655 printk( "IMR = 0x%04x", imr );
1656 if (imr & (1 << interrupt_level))
1657 printk( " (masked)" );
1658 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1659
1660 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1661 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1662 if (inb( TMC_Status_port & 1))
1663 printk( " (interrupt)" );
1664 printk( "\n" );
1665 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1666 if (inb( Interrupt_Status_port ) & 0x08)
1667 printk( " (enabled)" );
1668 printk( "\n" );
1669 if (chip == tmc18c50 || chip == tmc18c30) {1670 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1671 printk( "Int. Condition = 0x%02x\n",
1672 inb( port_base + Interrupt_Cond ) );
1673 }1674 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1675 if (chip == tmc18c50 || chip == tmc18c30)
1676 printk( "Configuration 2 = 0x%02x\n",
1677 inb( port_base + Configuration2 ) );
1678 }1679
1680 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1681 {1682 unsignedlongflags;
1683 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1684 printk( "fdomain: abort " );
1685 #endif1686
1687 save_flags( flags );
1688 cli();
1689 if (!in_command) {1690 #ifEVERY_ACCESS || ERRORS_ONLY1691 printk( " (not in command)\n" );
1692 #endif1693 restore_flags( flags );
1694 returnSCSI_ABORT_NOT_RUNNING;
1695 }1696
1697 #ifDEBUG_ABORT1698 print_info( SCpnt );
1699 #endif1700
1701 fdomain_make_bus_idle();
1702
1703 current_SC->SCp.phase |= aborted;
1704
1705 current_SC->result = DID_ABORT << 16;
1706
1707 restore_flags( flags );
1708
1709 /* Aborts are not done well. . . */1710 my_done( DID_ABORT << 16 );
1711
1712 returnSCSI_ABORT_SUCCESS;
1713 }1714
1715 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1716 {1717 #ifDEBUG_RESET1718 staticintcalled_once = 0;
1719 #endif1720
1721 #ifERRORS_ONLY1722 if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
1723 #endif1724
1725 #ifDEBUG_RESET1726 if (called_once) print_info( current_SC );
1727 called_once = 1;
1728 #endif1729
1730 outb( 1, SCSI_Cntl_port );
1731 do_pause( 2 );
1732 outb( 0, SCSI_Cntl_port );
1733 do_pause( 115 );
1734 outb( 0, SCSI_Mode_Cntl_port );
1735 outb( PARITY_MASK, TMC_Cntl_port );
1736
1737 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1738 is probably hosed at this point. We will, however, try to keep1739 things going by informing the high-level code that we need help. */1740
1741 returnSCSI_RESET_WAKEUP;
1742 }1743
1744 #include "sd.h"
1745 #include "scsi_ioctl.h"
1746
1747 intfdomain_16x0_biosparam( Scsi_Disk *disk, intdev, int *info_array )
/* */1748 {1749 intdrive;
1750 unsignedcharbuf[512 + sizeof( int ) * 2];
1751 intsize = disk->capacity;
1752 int *sizes = (int *)buf;
1753 unsignedchar *data = (unsignedchar *)(sizes + 2);
1754 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1755 intretcode;
1756 structdrive_info{1757 unsignedshortcylinders;
1758 unsignedcharheads;
1759 unsignedcharsectors;
1760 } *i;
1761
1762 /* NOTES:1763 The RAM area starts at 0x1f00 from the bios_base address.1764
1765 For BIOS Version 2.0:1766 1767 The drive parameter table seems to start at 0x1f30.1768 The first byte's purpose is not known.1769 Next is the cylinder, head, and sector information.1770 The last 4 bytes appear to be the drive's size in sectors.1771 The other bytes in the drive parameter table are unknown.1772 If anyone figures them out, please send me mail, and I will1773 update these notes.1774
1775 Tape drives do not get placed in this table.1776
1777 There is another table at 0x1fea:1778 If the byte is 0x01, then the SCSI ID is not in use.1779 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1780 although tapes don't seem to be in this table. I haven't1781 seen any other numbers (in a limited sample).1782
1783 0x1f2d is a drive count (i.e., not including tapes)1784
1785 The table at 0x1fcc are I/O ports addresses for the various1786 operations. I calculate these by hand in this driver code.1787
1788 1789 1790 For the ISA-200S version of BIOS Version 2.0:1791
1792 The drive parameter table starts at 0x1f33.1793
1794 WARNING: Assume that the table entry is 25 bytes long. Someone needs1795 to check this for the Quantum ISA-200S card.1796
1797 1798 1799 For BIOS Version 3.2:1800
1801 The drive parameter table starts at 0x1f70. Each entry is1802 0x0a bytes long. Heads are one less than we need to report.1803 */1804
1805 drive = MINOR(dev) / 16;
1806
1807 if (bios_major == 2) {1808 switch (Quantum) {1809 case 2: /* ISA_200S */1810 /* The value of 25 has never been verified.1811 It should probably be 15. */1812 i = (structdrive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1813 break;
1814 case 3: /* ISA_250MG */1815 i = (structdrive_info *)( (char *)bios_base + 0x1f36 + drive * 15 );
1816 break;
1817 case 4: /* ISA_200S (another one) */1818 i = (structdrive_info *)( (char *)bios_base + 0x1f34 + drive * 15 );
1819 break;
1820 default:
1821 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1822 break;
1823 }1824 info_array[0] = i->heads;
1825 info_array[1] = i->sectors;
1826 info_array[2] = i->cylinders;
1827 }elseif (bios_major == 3
1828 && bios_minor >= 0
1829 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1830 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1831 info_array[0] = i->heads + 1;
1832 info_array[1] = i->sectors;
1833 info_array[2] = i->cylinders;
1834 }else{/* 3.4 BIOS (and up?) */1835 /* This algorithm was provided by Future Domain (much thanks!). */1836
1837 sizes[0] = 0; /* zero bytes out */1838 sizes[1] = 512; /* one sector in */1839 memcpy( data, do_read, sizeof( do_read ) );
1840 retcode = kernel_scsi_ioctl( disk->device,
1841 SCSI_IOCTL_SEND_COMMAND,
1842 (void *)buf );
1843 if (!retcode/* SCSI command ok */1844 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1845 && data[0x1c2]) {/* Partition type */1846
1847 /* The partition table layout is as follows:1848
1849 Start: 0x1b3h1850 Offset: 0 = partition status1851 1 = starting head1852 2 = starting sector and cylinder (word, encoded)1853 4 = partition type1854 5 = ending head1855 6 = ending sector and cylinder (word, encoded)1856 8 = starting absolute sector (double word)1857 c = number of sectors (double word)1858 Signature: 0x1fe = 0x55aa1859
1860 So, this algorithm assumes:1861 1) the first partition table is in use,1862 2) the data in the first entry is correct, and1863 3) partitions never divide cylinders1864
1865 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1866 as well as for Linux. Note also, that Linux doesn't pay any1867 attention to the fields that are used by this algorithm -- it1868 only uses the absolute sector data. Recent versions of Linux's1869 fdisk(1) will fill this data in correctly, and forthcoming1870 versions will check for consistency.1871
1872 Checking for a non-zero partition type is not part of the1873 Future Domain algorithm, but it seemed to be a reasonable thing1874 to do, especially in the Linux and BSD worlds. */1875
1876 info_array[0] = data[0x1c3] + 1; /* heads */1877 info_array[1] = data[0x1c4] & 0x3f; /* sectors */1878 }else{1879
1880 /* Note that this new method guarantees that there will always be1881 less than 1024 cylinders on a platter. This is good for drives1882 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */1883
1884 if ((unsignedint)size >= 0x7e0000U) {1885 info_array[0] = 0xff; /* heads = 255 */1886 info_array[1] = 0x3f; /* sectors = 63 */1887 }elseif ((unsignedint)size >= 0x200000U) {1888 info_array[0] = 0x80; /* heads = 128 */1889 info_array[1] = 0x3f; /* sectors = 63 */1890 }else{1891 info_array[0] = 0x40; /* heads = 64 */1892 info_array[1] = 0x20; /* sectors = 32 */1893 }1894 }1895 /* For both methods, compute the cylinders */1896 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
1897 }1898
1899 return 0;
1900 }