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: Sun Sep 17 00:23:26 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.36 1995/09/17 04:23:42 root Exp $ 8
9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2, or (at your option) any 12 * later version. 13
14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18
19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 675 Mass Ave, Cambridge, MA 02139, USA. 22
23 ************************************************************************** 24 25 DESCRIPTION: 26
27 This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 28 TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a 29 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin 30 high-density external connector. The 1670 and 1680 have floppy disk 31 controllers built in. The TMC-3260 is a PCI bus card. 32
33 Future Domain's older boards are based on the TMC-1800 chip, and this 34 driver was originally written for a TMC-1680 board with the TMC-1800 chip. 35 More recently, boards are being produced with the TMC-18C50 and TMC-18C30 36 chips. The latest and greatest board may not work with this driver. If 37 you have to patch this driver so that it will recognize your board's BIOS 38 signature, then the driver may fail to function after the board is 39 detected. 40
41 The following BIOS versions are supported: 2.0, 3.0, 3.2, 3.4, and 3.5. 42 The following chips are supported: TMC-1800, TMC-18C50, TMC-18C30. 43 Reports suggest that the driver will also work with the 36C70 chip and 44 with the Quantum ISA-200S and ISA-250MG SCSI adapters. 45
46 Please note that the drive ordering that Future Domain implemented in BIOS 47 versions 3.4 and 3.5 is the opposite of the order (currently) used by the 48 rest of the SCSI industry. If you have BIOS version 3.4 or 3.5, and have 49 more then one drive, then the drive ordering will be the reverse of that 50 which you see under DOS. For example, under DOS SCSI ID 0 will be D: and 51 SCSI ID 1 will be C: (the boot device). Under Linux, SCSI ID 0 will be 52 /dev/sda and SCSI ID 1 will be /dev/sdb. The Linux ordering is consistent 53 with that provided by all the other SCSI drivers for Linux. If you want 54 this changed, send me patches that are protected by #ifdefs. 55
56 If you have a TMC-8xx or TMC-9xx board, then this is not the driver for 57 your board. Please refer to the Seagate driver for more information and 58 possible support. 59
60 61
62 REFERENCES USED: 63
64 "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, 65 1990. 66
67 "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain 68 Corporation, January 1992. 69
70 "LXT SCSI Products: Specifications and OEM Technical Manual (Revision 71 B/September 1991)", Maxtor Corporation, 1991. 72
73 "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. 74
75 "Draft Proposed American National Standard: Small Computer System 76 Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, 77 revision 10h, October 17, 1991) 78
79 Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric 80 Youngdale (ericy@cais.com), 1992. 81
82 Private communication, Tuong Le (Future Domain Engineering department), 83 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and 84 TMC-18C30 detection.) 85
86 Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page 87 60 (2.39: Disk Partition Table Layout). 88
89 "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page 90 6-1. 91
92
93 94 NOTES ON REFERENCES: 95
96 The Maxtor manuals were free. Maxtor telephone technical support is 97 great! 98
99 The Future Domain manuals were $25 and $35. They document the chip, not 100 the TMC-16x0 boards, so some information I had to guess at. In 1992, 101 Future Domain sold DOS BIOS source for $250 and the UN*X driver source was 102 $750, but these required a non-disclosure agreement, so even if I could 103 have afforded them, they would *not* have been useful for writing this 104 publically distributable driver. Future Domain technical support has 105 provided some information on the phone and have sent a few useful FAXs. 106 They have been much more helpful since they started to recognize that the 107 word "Linux" refers to an operating system :-). 108
109 110
111 ALPHA TESTERS: 112
113 There are many other alpha testers that come and go as the driver 114 develops. The people listed here were most helpful in times of greatest 115 need (mostly early on -- I've probably left out a few worthy people in 116 more recent times): 117
118 Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken 119 Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari 120 Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad 121 Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com). 122
123 Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me 124 his 18C50-based card for debugging. He is the sole reason that this 125 driver works with the 18C50 chip. 126
127 Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for 128 the version 3.4 BIOS. 129
130 Thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for providing 131 patches that support the TMC-3260, a PCI bus card with the 36C70 chip. 132 The 36C70 chip appears to be "completely compatible" with the 18C30 chip. 133
134 Thanks to Eric Kasten (tigger@petroglyph.cl.msu.edu) for providing the 135 patch for the version 3.5 BIOS. 136
137 Thanks for Stephen Henson (shenson@nyx10.cs.du.edu) for providing the 138 patch for the Quantum ISA-200S SCSI adapter. 139 140 Thanks to Adam Bowen for the signature to the 1610M/MER/MEX scsi cards, to 141 Martin Andrews (andrewm@ccfadm.eeg.ccf.org) for the signature to some 142 random TMC-1680 repackaged by IBM; and to Mintak Ng (mintak@panix.com) for 143 the version 3.61 BIOS siganture. 144
145 Thanks for Mark Singer (elf@netcom.com) and Richard Simpson 146 (rsimpson@ewrcsdra.demon.co.uk) for more Quantum signatures and detective 147 work on the Quantum RAM layout. 148
149 Special thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for 150 providing patches for proper PCI BIOS32-mediated detection of the TMC-3260 151 card (a PCI bus card with the 36C70 chip). Please send James PCI-related 152 bug reports. 153
154 Thanks to Tom Cavin (tec@usa1.com) for preliminary command-line option 155 patches. 156 157 All of the alpha testers deserve much thanks. 158
159
160
161 NOTES ON USER DEFINABLE OPTIONS: 162
163 DEBUG: This turns on the printing of various debug information. 164
165 ENABLE_PARITY: This turns on SCSI parity checking. With the current 166 driver, all attached devices must support SCSI parity. If none of your 167 devices support parity, then you can probably get the driver to work by 168 turning this option off. I have no way of testing this, however. 169
170 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the 171 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by 172 the SCSI device, an interrupt will be raised. Therefore, this could be as 173 low as 0, or as high as 16. Note, however, that values which are too high 174 or too low seem to prevent any interrupts from occurring, and thereby lock 175 up the machine. I have found that 2 is a good number, but throughput may 176 be increased by changing this value to values which are close to 2. 177 Please let me know if you try any different values. 178
179 DO_DETECT: This activates some old scan code which was needed before the 180 high level drivers got fixed. If you are having trouble with the driver, 181 turning this on should not hurt, and might help. Please let me know if 182 this is the case, since this code will be removed from future drivers. 183
184 RESELECTION: This is no longer an option, since I gave up trying to 185 implement it in version 4.x of this driver. It did not improve 186 performance at all and made the driver unstable (because I never found one 187 of the two race conditions which were introduced by the multiple 188 outstanding command code). The instability seems a very high price to pay 189 just so that you don't have to wait for the tape to rewind. If you want 190 this feature implemented, send me patches. I'll be happy to send a copy 191 of my (broken) driver to anyone who would like to see a copy. 192
193 **************************************************************************/ 194
195 #ifdefMODULE 196 #include <linux/module.h>
197 #endif 198
199 #include <linux/sched.h>
200 #include <asm/io.h>
201 #include "../block/blk.h"
202 #include "scsi.h"
203 #include "hosts.h"
204 #include "fdomain.h"
205 #include <asm/system.h>
206 #include <linux/errno.h>
207 #include <linux/string.h>
208 #include <linux/ioport.h>
209 #include <linux/proc_fs.h>
210 #include <linux/bios32.h>
211 #include <linux/pci.h>
212 #include<linux/stat.h>
213
214 structproc_dir_entryproc_scsi_fdomain = { 215 PROC_SCSI_FDOMAIN, 7, "fdomain",
216 S_IFDIR | S_IRUGO | S_IXUGO, 2
217 };
218
219 #defineVERSION "$Revision: 5.36 $"
220
221 /* START OF USER DEFINABLE OPTIONS */ 222
223 #defineDEBUG 1 /* Enable debugging output */ 224 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 225 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 226 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 227
228 /* END OF USER DEFINABLE OPTIONS */ 229
230 #ifDEBUG 231 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 232 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 233 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 234 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 235 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 236 #defineDEBUG_RESET 1 /* Debug reset() routine */ 237 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 238 #else 239 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 240 #defineERRORS_ONLY 0
241 #defineDEBUG_DETECT 0
242 #defineDEBUG_MESSAGES 0
243 #defineDEBUG_ABORT 0
244 #defineDEBUG_RESET 0
245 #defineDEBUG_RACE 0
246 #endif 247
248 /* Errors are reported on the line, so we don't need to report them again */ 249 #ifEVERY_ACCESS 250 #undefERRORS_ONLY 251 #defineERRORS_ONLY 0
252 #endif 253
254 #ifENABLE_PARITY 255 #definePARITY_MASK 0x08
256 #else 257 #definePARITY_MASK 0x00
258 #endif 259
260 enumchip_type{ 261 unknown = 0x00,
262 tmc1800 = 0x01,
263 tmc18c50 = 0x02,
264 tmc18c30 = 0x03,
265 };
266
267 enum{ 268 in_arbitration = 0x02,
269 in_selection = 0x04,
270 in_other = 0x08,
271 disconnect = 0x10,
272 aborted = 0x20,
273 sent_ident = 0x40,
274 };
275
276 enum in_port_type { 277 Read_SCSI_Data = 0,
278 SCSI_Status = 1,
279 TMC_Status = 2,
280 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 281 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 282 LSB_ID_Code = 5,
283 MSB_ID_Code = 6,
284 Read_Loopback = 7,
285 SCSI_Data_NoACK = 8,
286 Interrupt_Status = 9,
287 Configuration1 = 10,
288 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 289 Read_FIFO = 12,
290 FIFO_Data_Count = 14
291 };
292
293 enum out_port_type { 294 Write_SCSI_Data = 0,
295 SCSI_Cntl = 1,
296 Interrupt_Cntl = 2,
297 SCSI_Mode_Cntl = 3,
298 TMC_Cntl = 4,
299 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 300 Write_Loopback = 7,
301 IO_Control = 11, /* tmc18c30 only */ 302 Write_FIFO = 12
303 };
304
305 staticintport_base = 0;
306 staticvoid *bios_base = NULL;
307 staticintbios_major = 0;
308 staticintbios_minor = 0;
309 staticintPCI_bus = 0;
310 staticintQuantum = 0; /* Quantum board variant */ 311 staticintinterrupt_level = 0;
312 staticvolatileintin_command = 0;
313 staticScsi_Cmnd *current_SC = NULL;
314 staticenumchip_typechip = unknown;
315 staticintadapter_mask = 0;
316 staticintthis_id = 0;
317 staticintsetup_called = 0;
318
319 #ifDEBUG_RACE 320 staticvolatileintin_interrupt_flag = 0;
321 #endif 322
323 staticintSCSI_Mode_Cntl_port;
324 staticintFIFO_Data_Count_port;
325 staticintInterrupt_Cntl_port;
326 staticintInterrupt_Status_port;
327 staticintRead_FIFO_port;
328 staticintRead_SCSI_Data_port;
329 staticintSCSI_Cntl_port;
330 staticintSCSI_Data_NoACK_port;
331 staticintSCSI_Status_port;
332 staticintTMC_Cntl_port;
333 staticintTMC_Status_port;
334 staticintWrite_FIFO_port;
335 staticintWrite_SCSI_Data_port;
336
337 staticintFIFO_Size = 0x2000; /* 8k FIFO for 338 pre-tmc18c30 chips */ 339
340 externvoidfdomain_16x0_intr( intirq, structpt_regs * regs );
341
342 staticvoid *addresses[] = { 343 (void *)0xc8000,
344 (void *)0xca000,
345 (void *)0xce000,
346 (void *)0xde000,
347 (void *)0xd0000, /* Extra addresses for PCI boards */ 348 (void *)0xe0000,
349 };
350 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
351
352 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
353 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
354
355 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
356
357 /* 358
359 READ THIS BEFORE YOU ADD A SIGNATURE! 360
361 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 362
363 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 364
365 This driver works *ONLY* for Future Domain cards using the TMC-1800, 366 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 367 and 1680. 368
369 The following BIOS signature signatures are for boards which do *NOT* 370 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 371 Seagate driver): 372
373 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 374 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 375 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 376 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 377 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 378 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 379 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 380
381 */ 382
383 structsignature{ 384 constchar *signature;
385 intsig_offset;
386 intsig_length;
387 intmajor_bios_version;
388 intminor_bios_version;
389 intflag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ 390 }signatures[] = { 391 /* 1 2 3 4 5 6 */ 392 /* 123456789012345678901234567890123456789012345678901234567890 */ 393 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
394 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
395 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
396 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
397 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
398 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
399 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
400 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
401 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
402 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
403 /* This next signature may not be a 3.5 bios */ 404 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
405 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
406 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
407 { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 },
408 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
409
410 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE 411 Also, fix the disk geometry code for your signature and send your 412 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 413 signatures! 414
415 Note that the last line will match a "generic" 18XX bios. Because 416 Future Domain has changed the host SCSI ID and/or the location of the 417 geometry information in the on-board RAM area for each of the first 418 three BIOS's, it is still important to enter a fully qualified 419 signature in the table for any new BIOS's (after the host SCSI ID and 420 geometry location are verified). */ 421 };
422
423 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
424
425 staticvoidprint_banner( structScsi_Host *shpnt )
426 { 427 if (!shpnt) return; /* This won't ever happen */ 428
429 if (bios_major < 0 && bios_minor < 0) { 430 printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n",
431 shpnt->host_no, shpnt->this_id );
432 }else{ 433 printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
434
435 if (bios_major >= 0) printk( "%d.", bios_major );
436 elseprintk( "?." );
437
438 if (bios_minor >= 0) printk( "%d", bios_minor );
439 elseprintk( "?." );
440
441 printk( " at 0x%x using scsi id %d\n",
442 (unsigned)bios_base, shpnt->this_id );
443 } 444
445 /* If this driver works for later FD PCI 446 boards, we will have to modify banner 447 for additional PCI cards, but for now if 448 it's PCI it's a TMC-3260 - JTM */ 449 printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
450 shpnt->host_no,
451 chip == tmc1800 ? "TMC-1800"
452 : (chip == tmc18c50 ? "TMC-18C50"
453 : (chip == tmc18c30 ?
454 (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30")
455 : "Unknown")),
456 port_base );
457
458 if (interrupt_level) printk( "%d", interrupt_level );
459 elseprintk( "<none>" );
460
461 printk( "\n" );
462 } 463
464 voidfdomain_setup( char *str, int *ints )
/* */ 465 { 466 if (setup_called++ || ints[0] < 2 || ints[0] > 3) { 467 printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
468 printk( "fdomain: bad LILO parameters?\n" );
469 } 470
471 port_base = ints[0] >= 1 ? ints[1] : 0;
472 interrupt_level = ints[0] >= 2 ? ints[2] : 0;
473 adapter_mask = ints[0] >= 3 ? (1 << ints[3]) : 0;
474
475 bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ 476 } 477
478
479 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 480 { 481 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 482
483 while (jiffies < the_time);
484 } 485
486 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 487 { 488 outb( 0, SCSI_Cntl_port );
489 outb( 0, SCSI_Mode_Cntl_port );
490 if (chip == tmc18c50 || chip == tmc18c30)
491 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 492 else 493 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
494 } 495
496 staticintfdomain_is_valid_port( intport )
/* */ 497 { 498 #ifDEBUG_DETECT 499 printk( " (%x%x),",
500 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
501 #endif 502
503 /* The MCA ID is a unique id for each MCA compatible board. We 504 are using ISA boards, but Future Domain provides the MCA ID 505 anyway. We can use this ID to ensure that this is a Future 506 Domain TMC-1660/TMC-1680. 507 */ 508
509 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 510 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
511 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
512 chip = tmc1800;
513 }else{/* test for 0xe960 id */ 514 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
515 chip = tmc18c50;
516
517 #if 0
518
519 /* Try to toggle 32-bit mode. This only 520 works on an 18c30 chip. (User reports 521 say that this doesn't work at all, so 522 we'll use the other method.) */ 523
524 outb( 0x80, port + IO_Control );
525 if ((inb( port + Configuration2 ) & 0x80) == 0x80) { 526 outb( 0x00, port + IO_Control );
527 if ((inb( port + Configuration2 ) & 0x80) == 0x00) { 528 chip = tmc18c30;
529 FIFO_Size = 0x800; /* 2k FIFO */ 530 } 531 } 532 #else 533
534 /* That should have worked, but appears to 535 have problems. Lets assume it is an 536 18c30 if the RAM is disabled. */ 537
538 if (inb( port + Configuration2 ) & 0x02) { 539 chip = tmc18c30;
540 FIFO_Size = 0x800; /* 2k FIFO */ 541 } 542 #endif 543 /* If that failed, we are an 18c50. */ 544 } 545
546 return 1;
547 } 548
549 staticintfdomain_test_loopback( void )
/* */ 550 { 551 inti;
552 intresult;
553
554 for (i = 0; i < 255; i++) { 555 outb( i, port_base + Write_Loopback );
556 result = inb( port_base + Read_Loopback );
557 if (i != result)
558 return 1;
559 } 560 return 0;
561 } 562
563 /* fdomain_get_irq assumes that we have a valid MCA ID for a 564 TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the 565 bios_base matches these ports. If someone was unlucky enough to have 566 purchased more than one Future Domain board, then they will have to 567 modify this code, as we only detect one board here. [The one with the 568 lowest bios_base.] 569
570 Note that this routine is only used for systems without a PCI BIOS32 571 (e.g., ISA bus). For PCI bus systems, this routine will likely fail 572 unless one of the IRQs listed in the ints array is used by the board. 573 Sometimes it is possible to use the computer's BIOS setup screen to 574 configure a PCI system so that one of these IRQs will be used by the 575 Future Domain card. */ 576
577 staticintfdomain_get_irq( intbase )
/* */ 578 { 579 intoptions = inb( base + Configuration1 );
580
581 #ifDEBUG_DETECT 582 printk( " Options = %x\n", options );
583 #endif 584
585 /* Check for board with lowest bios_base -- 586 this isn't valid for the 18c30 or for 587 boards on the PCI bus, so just assume we 588 have the right board. */ 589
590 if (chip != tmc18c30 591 && !PCI_bus 592 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
593
594 returnints[ (options & 0x0e) >> 1 ];
595 } 596
597 staticintfdomain_isa_detect( int *irq, int *iobase )
/* */ 598 { 599 inti;
600 intbase;
601 intflag = 0;
602
603 if (bios_major == 2) { 604 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 605 Assuming the ROM is enabled (otherwise we wouldn't have been 606 able to read the ROM signature :-), then the ROM sets up the 607 RAM area with some magic numbers, such as a list of port 608 base addresses and a list of the disk "geometry" reported to 609 DOS (this geometry has nothing to do with physical geometry). 610 */ 611
612 switch (Quantum) { 613 case 2: /* ISA_200S */ 614 case 3: /* ISA_250MG */ 615 base = *((char *)bios_base + 0x1fa2)
616 + (*((char *)bios_base + 0x1fa3) << 8);
617 break;
618 case 4: /* ISA_200S (another one) */ 619 base = *((char *)bios_base + 0x1fa3)
620 + (*((char *)bios_base + 0x1fa4) << 8);
621 break;
622 default:
623 base = *((char *)bios_base + 0x1fcc)
624 + (*((char *)bios_base + 0x1fcd) << 8);
625 break;
626 } 627
628 #ifDEBUG_DETECT 629 printk( " %x,", base );
630 #endif 631
632 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 633 if (base == ports[i])
634 ++flag;
635 } 636
637 if (flag && fdomain_is_valid_port( base )) { 638 *irq = fdomain_get_irq( base );
639 *iobase = base;
640 return 1;
641 } 642
643 /* This is a bad sign. It usually means that someone patched the 644 BIOS signature list (the signatures variable) to contain a BIOS 645 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ 646
647 #ifDEBUG_DETECT 648 printk( " RAM FAILED, " );
649 #endif 650 } 651
652 /* Anyway, the alternative to finding the address in the RAM is to just 653 search through every possible port address for one that is attached 654 to the Future Domain card. Don't panic, though, about reading all 655 these random port addresses -- there are rumors that the Future 656 Domain BIOS does something very similar. 657
658 Do not, however, check ports which the kernel knows are being used by 659 another driver. */ 660
661 for (i = 0; i < PORT_COUNT; i++) { 662 base = ports[i];
663 if (check_region( base, 0x10 )) { 664 #ifDEBUG_DETECT 665 printk( " (%x inuse),", base );
666 #endif 667 continue;
668 } 669 #ifDEBUG_DETECT 670 printk( " %x,", base );
671 #endif 672 if ((flag = fdomain_is_valid_port( base ))) break;
673 } 674
675 if (!flag) return 0; /* iobase not found */ 676
677 *irq = fdomain_get_irq( base );
678 *iobase = base;
679
680 return 1; /* success */ 681 } 682
683 staticintfdomain_pci_nobios_detect( int *irq, int *iobase )
/* */ 684 { 685 inti;
686 intflag = 0;
687
688 /* The proper way of doing this is to use ask the PCI bus for the device 689 IRQ and interrupt level. But we can't do that if PCI BIOS32 support 690 isn't compiled into the kernel, or if a PCI BIOS32 isn't present. 691
692 Instead, we scan down a bunch of addresses (Future Domain tech 693 support says we will probably find the address before we get to 694 0xf800). This works fine on some systems -- other systems may have 695 to scan more addresses. If you have to modify this section for your 696 installation, please send mail to faith@cs.unc.edu. */ 697
698 for (i = 0xfff8; i > 0xe000; i -= 8) { 699 if (check_region( i, 0x10 )) { 700 #ifDEBUG_DETECT 701 printk( " (%x inuse)," , i );
702 #endif 703 continue;
704 } 705 if ((flag = fdomain_is_valid_port( i ))) break;
706 } 707
708 if (!flag) return 0; /* iobase not found */ 709
710 *irq = fdomain_get_irq( i );
711 *iobase = i;
712
713 return 1; /* success */ 714 } 715
716 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* 717 iobase) This function gets the Interrupt Level and I/O base address from 718 the PCI configuration registers. The I/O base address is masked with 719 0xfff8 since on my card the address read from the PCI config registers 720 is off by one from the actual I/O base address necessary for accessing 721 the status and control registers on the card (PCI config register gives 722 0xf801, actual address is 0xf800). This is likely a bug in the FD 723 config code that writes to the PCI registers, however using a mask 724 should be safe since I think the scan done by the card to determine the 725 I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at 726 least the old scan code we used to use to get the I/O base did... Also, 727 the device ID from the PCI config registers is 0x0 and should be 0x60e9 728 as it is in the status registers (offset 5 from I/O base). If this is 729 changed in future hardware/BIOS changes it will need to be fixed in this 730 detection function. Comments, bug reports, etc... on this function 731 should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ 732
733 #ifdefCONFIG_PCI 734 staticintfdomain_pci_bios_detect( int *irq, int *iobase )
/* */ 735 { 736 interror;
737 unsignedcharpci_bus, pci_dev_fn; /* PCI bus & device function */ 738 unsignedcharpci_irq; /* PCI interrupt line */ 739 unsignedintpci_base; /* PCI I/O base address */ 740 unsignedshortpci_vendor, pci_device; /* PCI vendor & device IDs */ 741
742 /* If the PCI BIOS doesn't exist, use the old-style detection routines. 743 Otherwise, get the I/O base address and interrupt from the PCI config 744 registers. */ 745
746 if (!pcibios_present()) returnfdomain_pci_nobios_detect( irq, iobase );
747
748 #ifDEBUG_DETECT 749 /* Tell how to print a list of the known PCI devices from bios32 and 750 list vendor and device IDs being used if in debug mode. */ 751
752 printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
753 printk( "\nTMC-3260 detect:"
754 " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
755 PCI_VENDOR_ID_FD,
756 PCI_DEVICE_ID_FD_36C70 );
757 #endif 758
759 /* We will have to change this if more than 1 PCI bus is present and the 760 FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, 761 which is not supported by bios32 right now anyway). This should 762 probably be done by a call to pcibios_find_device but I can't get it 763 to work... Also the device ID reported from the PCI config registers 764 does not match the device ID quoted in the tech manual or available 765 from offset 5 from the I/O base address. It should be 0x60E9, but it 766 is 0x0 if read from the PCI config registers. I guess the FD folks 767 neglected to write it to the PCI registers... This loop is necessary 768 to get the device function (at least until someone can get 769 pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ 770
771 pci_bus = 0;
772
773 for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { 774 pcibios_read_config_word( pci_bus,
775 pci_dev_fn,
776 PCI_VENDOR_ID,
777 &pci_vendor );
778
779 if (pci_vendor == PCI_VENDOR_ID_FD) { 780 pcibios_read_config_word( pci_bus,
781 pci_dev_fn,
782 PCI_DEVICE_ID,
783 &pci_device );
784
785 if (pci_device == PCI_DEVICE_ID_FD_36C70) { 786 /* Break out once we have the correct device. If other FD 787 PCI devices are added to this driver we will need to add 788 an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ 789 break;
790 }else{ 791 /* If we can't find an FD scsi card we give up. */ 792 return 0;
793 } 794 } 795 } 796
797 #ifDEBUG_DETECT 798 printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
799 pci_bus,
800 (pci_dev_fn & 0xf8) >> 3,
801 pci_dev_fn & 7 );
802 #endif 803
804 /* We now have the appropriate device function for the FD board so we 805 just read the PCI config info from the registers. */ 806
807 if ((error = pcibios_read_config_dword( pci_bus,
808 pci_dev_fn,
809 PCI_BASE_ADDRESS_0,
810 &pci_base ))
811 || (error = pcibios_read_config_byte( pci_bus,
812 pci_dev_fn,
813 PCI_INTERRUPT_LINE,
814 &pci_irq ))) { 815 printk ( "PCI ERROR: Future Domain 36C70 not initializing"
816 " due to error reading configuration space\n" );
817 return 0;
818 }else{ 819 #ifDEBUG_DETECT 820 printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
821 pci_irq, pci_base );
822 #endif 823
824 /* Now we have the I/O base address and interrupt from the PCI 825 configuration registers. Unfortunately it seems that the I/O base 826 address is off by one on my card so I mask it with 0xfff8. This 827 must be some kind of goof in the FD code that does the autoconfig 828 and writes to the PCI registers (or maybe I just don't understand 829 something). If they fix it in later versions of the card or BIOS 830 we may have to adjust the address based on the signature or 831 something... */ 832
833 *irq = pci_irq;
834 *iobase = (pci_base & 0xfff8);
835
836 #ifDEBUG_DETECT 837 printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
838 printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
839 #endif 840
841 if (!fdomain_is_valid_port( *iobase )) return 0;
842 return 1;
843 } 844 return 0;
845 } 846 #endif 847
848 intfdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* */ 849 { 850 inti, j;
851 intretcode;
852 structScsi_Host *shpnt;
853 #ifDO_DETECT 854 constintbuflen = 255;
855 Scsi_CmndSCinit;
856 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
857 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
858 unsignedchardo_read_capacity[] = {READ_CAPACITY,
859 0, 0, 0, 0, 0, 0, 0, 0, 0 };
860 unsignedcharbuf[buflen];
861 #endif 862
863 #ifDEBUG_DETECT 864 printk( "fdomain_16x0_detect()," );
865 #endif 866 tpnt->proc_dir = &proc_scsi_fdomain;
867
868 if (setup_called) { 869 #ifDEBUG_DETECT 870 printk( "no BIOS, using port_base = 0x%x, irq = %d\n",
871 port_base, interrupt_level );
872 #endif 873 if (!fdomain_is_valid_port( port_base )) { 874 printk( "fdomain: cannot locate chip at port base 0x%x\n",
875 port_base );
876 printk( "fdomain: bad LILO parameters?\n" );
877 return 0;
878 } 879 }else{ 880 intflag = 0;
881
882 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 883 #ifDEBUG_DETECT 884 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
885 #endif 886 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 887 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
888 signatures[j].signature, signatures[j].sig_length )) { 889 bios_major = signatures[j].major_bios_version;
890 bios_minor = signatures[j].minor_bios_version;
891 PCI_bus = (signatures[j].flag == 1);
892 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
893 bios_base = addresses[i];
894 } 895 } 896 } 897
898 if (!bios_base) { 899 #ifDEBUG_DETECT 900 printk( " FAILED: NO BIOS\n" );
901 #endif 902 return 0;
903 } 904
905 if (!PCI_bus) { 906 flag = fdomain_isa_detect( &interrupt_level, &port_base );
907 }else{ 908 #ifdefCONFIG_PCI 909 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
910 #else 911 flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
912 #endif 913 } 914
915 if (!flag) { 916 #ifDEBUG_DETECT 917 printk( " FAILED: NO PORT\n" );
918 #endif 919 #ifdefCONFIG_PCI 920 printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
921 printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" );
922 #endif 923 return 0; /* Cannot find valid set of ports */ 924 } 925 } 926
927 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
928 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
929 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
930 Interrupt_Status_port = port_base + Interrupt_Status;
931 Read_FIFO_port = port_base + Read_FIFO;
932 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
933 SCSI_Cntl_port = port_base + SCSI_Cntl;
934 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
935 SCSI_Status_port = port_base + SCSI_Status;
936 TMC_Cntl_port = port_base + TMC_Cntl;
937 TMC_Status_port = port_base + TMC_Status;
938 Write_FIFO_port = port_base + Write_FIFO;
939 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
940
941 fdomain_16x0_reset( NULL );
942
943 if (fdomain_test_loopback()) { 944 #ifDEBUG_DETECT 945 printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
946 #endif 947 if (setup_called) { 948 printk( "fdomain: loopback test failed at port base 0x%x\n",
949 port_base );
950 printk( "fdomain: bad LILO parameters?\n" );
951 } 952 return 0;
953 } 954
955 if (this_id) { 956 tpnt->this_id = (this_id & 0x7);
957 adapter_mask = (1 << tpnt->this_id);
958 }else{ 959 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 960 tpnt->this_id = 7;
961 adapter_mask = 0x80;
962 }else{ 963 tpnt->this_id = 6;
964 adapter_mask = 0x40;
965 } 966 } 967
968 /* Print out a banner here in case we can't 969 get resources. */ 970
971 shpnt = scsi_register( tpnt, 0 );
972 print_banner( shpnt );
973
974 /* Log IRQ with kernel */ 975 if (!interrupt_level) { 976 panic( "fdomain: *NO* interrupt level selected!\n" );
977 }else{ 978 /* Register the IRQ with the kernel */ 979
980 retcode = request_irq( interrupt_level,
981 fdomain_16x0_intr, SA_INTERRUPT, "fdomain" );
982
983 if (retcode < 0) { 984 if (retcode == -EINVAL) { 985 printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
986 printk( " This shouldn't happen!\n" );
987 printk( " Send mail to faith@cs.unc.edu\n" );
988 }elseif (retcode == -EBUSY) { 989 printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
990 printk( " Please use another IRQ!\n" );
991 }else{ 992 printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
993 printk( " This shouldn't happen!\n" );
994 printk( " Send mail to faith@cs.unc.edu\n" );
995 } 996 panic( "fdomain: Driver requires interruptions\n" );
997 } 998 } 999
1000 /* Log I/O ports with kernel */1001 request_region( port_base, 0x10, "fdomain" );
1002
1003 #ifDO_DETECT1004
1005 /* These routines are here because of the way the SCSI bus behaves after1006 a reset. This appropriate behavior was not handled correctly by the1007 higher level SCSI routines when I first wrote this driver. Now,1008 however, correct scan routines are part of scsi.c and these routines1009 are no longer needed. However, this code is still good for1010 debugging. */1011
1012 SCinit.request_buffer = SCinit.buffer = buf;
1013 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
1014 SCinit.use_sg = 0;
1015 SCinit.lun = 0;
1016
1017 printk( "fdomain: detection routine scanning for devices:\n" );
1018 for (i = 0; i < 8; i++) {1019 SCinit.target = i;
1020 if (i == tpnt->this_id) /* Skip host adapter */1021 continue;
1022 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1023 retcode = fdomain_16x0_command(&SCinit);
1024 if (!retcode) {1025 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
1026 retcode = fdomain_16x0_command(&SCinit);
1027 if (!retcode) {1028 printk( " SCSI ID %d: ", i );
1029 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
1030 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
1031 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
1032 retcode = fdomain_16x0_command(&SCinit);
1033 if (!retcode) {1034 unsignedlongblocks, size, capacity;
1035
1036 blocks = (buf[0] << 24) | (buf[1] << 16)
1037 | (buf[2] << 8) | buf[3];
1038 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
1039 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
1040
1041 printk( "%lu MB (%lu byte blocks)",
1042 ((capacity + 5L) / 10L), size );
1043 }else{1044 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1045 retcode = fdomain_16x0_command(&SCinit);
1046 }1047 printk ("\n" );
1048 }else{1049 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
1050 retcode = fdomain_16x0_command(&SCinit);
1051 }1052 }1053 }1054 #endif1055
1056 return 1; /* Maximum of one adapter will be detected. */1057 }1058
1059 constchar *fdomain_16x0_info( structScsi_Host *ignore )
/* */1060 {1061 staticcharbuffer[80];
1062 char *pt;
1063
1064 strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
1065 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */1066 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1067 pt = strrchr( buffer, '$') - 1;
1068 if (!pt) /* Stripped RCS Revision string? */1069 pt = buffer + strlen( buffer ) - 1;
1070 if (*pt != ' ')
1071 ++pt;
1072 *pt = '\0';
1073 }else{/* Assume VERSION is a number */1074 strcat( buffer, " " VERSION );
1075 }1076
1077 returnbuffer;
1078 }1079
1080 #if 0
1081 /* First pass at /proc information routine. */1082 /*1083 * inout : decides on the direction of the dataflow and the meaning of the 1084 * variables1085 * buffer: If inout==FALSE data is beeing written to it else read from it1086 * *start: If inout==FALSE start of the valid data in the buffer1087 * offset: If inout==FALSE offset from the beginning of the imaginary file 1088 * from which we start writing into the buffer1089 * length: If inout==FALSE max number of bytes to be written into the buffer 1090 * else number of bytes in the buffer1091 */1092 int fdomain_16x0_proc_info( char *buffer, char **start, off_toffset,
/* */1093 intlength, inthostno, intinout )
1094 {1095 intlen = 0;
1096 constchar *info = fdomain_16x0_info( NULL );
1097
1098 if (inout) return -ENOSYS;
1099
1100 strcpy( buffer, info );
1101 len += strlen( info );
1102
1103 return( len );
1104 }1105 #endif1106
1107 #if 0
1108 staticint fdomain_arbitrate( void )
/* */1109 {1110 intstatus = 0;
1111 unsignedlongtimeout;
1112
1113 #ifEVERY_ACCESS1114 printk( "fdomain_arbitrate()\n" );
1115 #endif1116
1117 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1118 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */1119 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1120
1121 timeout = jiffies + 50; /* 500 mS */1122 while (jiffies < timeout) {1123 status = inb( TMC_Status_port ); /* Read adapter status */1124 if (status & 0x02) /* Arbitration complete */1125 return 0;
1126 }1127
1128 /* Make bus idle */1129 fdomain_make_bus_idle();
1130
1131 #ifEVERY_ACCESS1132 printk( "Arbitration failed, status = %x\n", status );
1133 #endif1134 #ifERRORS_ONLY1135 printk( "fdomain: Arbitration failed, status = %x\n", status );
1136 #endif1137 return 1;
1138 }1139 #endif1140
1141 staticintfdomain_select( inttarget )
/* */1142 {1143 intstatus;
1144 unsignedlongtimeout;
1145 staticintflag = 0;
1146
1147
1148 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1149 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
1150
1151 /* Stop arbitration and enable parity */1152 outb( PARITY_MASK, TMC_Cntl_port );
1153
1154 timeout = jiffies + 35; /* 350mS -- because of timeouts1155 (was 250mS) */1156
1157 while (jiffies < timeout) {1158 status = inb( SCSI_Status_port ); /* Read adapter status */1159 if (status & 1) {/* Busy asserted */1160 /* Enable SCSI Bus (on error, should make bus idle with 0) */1161 outb( 0x80, SCSI_Cntl_port );
1162 return 0;
1163 }1164 }1165 /* Make bus idle */1166 fdomain_make_bus_idle();
1167 #ifEVERY_ACCESS1168 if (!target) printk( "Selection failed\n" );
1169 #endif1170 #ifERRORS_ONLY1171 if (!target) {1172 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */1173 ++flag;
1174 else1175 printk( "fdomain: Selection failed\n" );
1176 }1177 #endif1178 return 1;
1179 }1180
1181 voidmy_done( interror )
/* */1182 {1183 if (in_command) {1184 in_command = 0;
1185 outb( 0x00, Interrupt_Cntl_port );
1186 fdomain_make_bus_idle();
1187 current_SC->result = error;
1188 if (current_SC->scsi_done)
1189 current_SC->scsi_done( current_SC );
1190 elsepanic( "fdomain: current_SC->scsi_done() == NULL" );
1191 }else{1192 panic( "fdomain: my_done() called outside of command\n" );
1193 }1194 #ifDEBUG_RACE1195 in_interrupt_flag = 0;
1196 #endif1197 }1198
1199 voidfdomain_16x0_intr( intirq, structpt_regs * regs )
/* */1200 {1201 intstatus;
1202 intdone = 0;
1203 unsigneddata_count;
1204
1205 /* The fdomain_16x0_intr is only called via1206 the interrupt handler. The goal of the1207 sti() here is to allow other1208 interruptions while this routine is1209 running. */1210
1211 sti(); /* Yes, we really want sti() here */1212
1213 outb( 0x00, Interrupt_Cntl_port );
1214
1215 /* We usually have one spurious interrupt after each command. Ignore it. */1216 if (!in_command || !current_SC) {/* Spurious interrupt */1217 #ifEVERY_ACCESS1218 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1219 in_command, current_SC );
1220 #endif1221 return;
1222 }1223
1224 /* Abort calls my_done, so we do nothing here. */1225 if (current_SC->SCp.phase & aborted) {1226 #ifDEBUG_ABORT1227 printk( "Interrupt after abort, ignoring\n" );
1228 #endif1229 /*1230 return; */1231 }1232
1233 #ifDEBUG_RACE1234 ++in_interrupt_flag;
1235 #endif1236
1237 if (current_SC->SCp.phase & in_arbitration) {1238 status = inb( TMC_Status_port ); /* Read adapter status */1239 if (!(status & 0x02)) {1240 #ifEVERY_ACCESS1241 printk( " AFAIL " );
1242 #endif1243 my_done( DID_BUS_BUSY << 16 );
1244 return;
1245 }1246 current_SC->SCp.phase = in_selection;
1247
1248 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
1249
1250 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */1251 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
1252
1253 /* Stop arbitration and enable parity */1254 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1255 #ifDEBUG_RACE1256 in_interrupt_flag = 0;
1257 #endif1258 return;
1259 }elseif (current_SC->SCp.phase & in_selection) {1260 status = inb( SCSI_Status_port );
1261 if (!(status & 0x01)) {1262 /* Try again, for slow devices */1263 if (fdomain_select( current_SC->target )) {1264 #ifEVERY_ACCESS1265 printk( " SFAIL " );
1266 #endif1267 my_done( DID_NO_CONNECT << 16 );
1268 return;
1269 }else{1270 #ifEVERY_ACCESS1271 printk( " AltSel " );
1272 #endif1273 /* Stop arbitration and enable parity */1274 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
1275 }1276 }1277 current_SC->SCp.phase = in_other;
1278 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1279 outb( 0x80, SCSI_Cntl_port );
1280 #ifDEBUG_RACE1281 in_interrupt_flag = 0;
1282 #endif1283 return;
1284 }1285
1286 /* current_SC->SCp.phase == in_other: this is the body of the routine */1287
1288 status = inb( SCSI_Status_port );
1289
1290 if (status & 0x10) {/* REQ */1291
1292 switch (status & 0x0e) {1293
1294 case 0x08: /* COMMAND OUT */1295 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
1296 Write_SCSI_Data_port );
1297 #ifEVERY_ACCESS1298 printk( "CMD = %x,",
1299 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1300 #endif1301 break;
1302 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */1303 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1304 current_SC->SCp.have_data_in = -1;
1305 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1306 }1307 break;
1308 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */1309 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {1310 current_SC->SCp.have_data_in = 1;
1311 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1312 }1313 break;
1314 case 0x0c: /* STATUS IN */1315 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
1316 #ifEVERY_ACCESS1317 printk( "Status = %x, ", current_SC->SCp.Status );
1318 #endif1319 #ifERRORS_ONLY1320 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {1321 printk( "fdomain: target = %d, command = %x, status = %x\n",
1322 current_SC->target,
1323 current_SC->cmnd[0],
1324 current_SC->SCp.Status );
1325 }1326 #endif1327 break;
1328 case 0x0a: /* MESSAGE OUT */1329 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */1330 break;
1331 case 0x0e: /* MESSAGE IN */1332 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1333 #ifEVERY_ACCESS1334 printk( "Message = %x, ", current_SC->SCp.Message );
1335 #endif1336 if (!current_SC->SCp.Message) ++done;
1337 #ifDEBUG_MESSAGES || EVERY_ACCESS1338 if (current_SC->SCp.Message) {1339 printk( "fdomain: message = %x\n", current_SC->SCp.Message );
1340 }1341 #endif1342 break;
1343 }1344 }1345
1346 if (chip == tmc18001347 && !current_SC->SCp.have_data_in1348 && (current_SC->SCp.sent_command1349 >= current_SC->cmd_len)) {1350 /* We have to get the FIFO direction1351 correct, so I've made a table based1352 on the SCSI Standard of which commands1353 appear to require a DATA OUT phase.1354 */1355 /*1356 p. 94: Command for all device types1357 CHANGE DEFINITION 40 DATA OUT1358 COMPARE 39 DATA OUT1359 COPY 18 DATA OUT1360 COPY AND VERIFY 3a DATA OUT1361 INQUIRY 12 1362 LOG SELECT 4c DATA OUT1363 LOG SENSE 4d1364 MODE SELECT (6) 15 DATA OUT1365 MODE SELECT (10) 55 DATA OUT1366 MODE SENSE (6) 1a1367 MODE SENSE (10) 5a1368 READ BUFFER 3c1369 RECEIVE DIAGNOSTIC RESULTS 1c1370 REQUEST SENSE 031371 SEND DIAGNOSTIC 1d DATA OUT1372 TEST UNIT READY 001373 WRITE BUFFER 3b DATA OUT1374
1375 p.178: Commands for direct-access devices (not listed on p. 94)1376 FORMAT UNIT 04 DATA OUT1377 LOCK-UNLOCK CACHE 361378 PRE-FETCH 341379 PREVENT-ALLOW MEDIUM REMOVAL 1e1380 READ (6)/RECEIVE 081381 READ (10) 3c1382 READ CAPACITY 251383 READ DEFECT DATA (10) 371384 READ LONG 3e1385 REASSIGN BLOCKS 07 DATA OUT1386 RELEASE 171387 RESERVE 16 DATA OUT1388 REZERO UNIT/REWIND 011389 SEARCH DATA EQUAL (10) 31 DATA OUT1390 SEARCH DATA HIGH (10) 30 DATA OUT1391 SEARCH DATA LOW (10) 32 DATA OUT1392 SEEK (6) 0b1393 SEEK (10) 2b1394 SET LIMITS (10) 331395 START STOP UNIT 1b1396 SYNCHRONIZE CACHE 351397 VERIFY (10) 2f1398 WRITE (6)/PRINT/SEND 0a DATA OUT1399 WRITE (10)/SEND 2a DATA OUT1400 WRITE AND VERIFY (10) 2e DATA OUT1401 WRITE LONG 3f DATA OUT1402 WRITE SAME 41 DATA OUT ?1403
1404 p. 261: Commands for sequential-access devices (not previously listed)1405 ERASE 191406 LOAD UNLOAD 1b1407 LOCATE 2b1408 READ BLOCK LIMITS 051409 READ POSITION 341410 READ REVERSE 0f1411 RECOVER BUFFERED DATA 141412 SPACE 111413 WRITE FILEMARKS 10 ?1414
1415 p. 298: Commands for printer devices (not previously listed)1416 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1417 SLEW AND PRINT 0b DATA OUT -- same as seek1418 STOP PRINT 1b1419 SYNCHRONIZE BUFFER 101420
1421 p. 315: Commands for processor devices (not previously listed)1422 1423 p. 321: Commands for write-once devices (not previously listed)1424 MEDIUM SCAN 381425 READ (12) a81426 SEARCH DATA EQUAL (12) b1 DATA OUT1427 SEARCH DATA HIGH (12) b0 DATA OUT1428 SEARCH DATA LOW (12) b2 DATA OUT1429 SET LIMITS (12) b31430 VERIFY (12) af1431 WRITE (12) aa DATA OUT1432 WRITE AND VERIFY (12) ae DATA OUT1433
1434 p. 332: Commands for CD-ROM devices (not previously listed)1435 PAUSE/RESUME 4b1436 PLAY AUDIO (10) 451437 PLAY AUDIO (12) a51438 PLAY AUDIO MSF 471439 PLAY TRACK RELATIVE (10) 491440 PLAY TRACK RELATIVE (12) a91441 READ HEADER 441442 READ SUB-CHANNEL 421443 READ TOC 431444
1445 p. 370: Commands for scanner devices (not previously listed)1446 GET DATA BUFFER STATUS 341447 GET WINDOW 251448 OBJECT POSITION 311449 SCAN 1b1450 SET WINDOW 24 DATA OUT1451
1452 p. 391: Commands for optical memory devices (not listed)1453 ERASE (10) 2c1454 ERASE (12) ac1455 MEDIUM SCAN 38 DATA OUT1456 READ DEFECT DATA (12) b71457 READ GENERATION 291458 READ UPDATED BLOCK 2d1459 UPDATE BLOCK 3d DATA OUT1460
1461 p. 419: Commands for medium changer devices (not listed)1462 EXCHANGE MEDIUM 461463 INITIALIZE ELEMENT STATUS 071464 MOVE MEDIUM a51465 POSITION TO ELEMENT 2b1466 READ ELEMENT STATUS b81467 REQUEST VOL. ELEMENT ADDRESS b51468 SEND VOLUME TAG b6 DATA OUT1469
1470 p. 454: Commands for communications devices (not listed previously)1471 GET MESSAGE (6) 081472 GET MESSAGE (10) 281473 GET MESSAGE (12) a81474 */1475
1476 switch (current_SC->cmnd[0]) {1477 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1478 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1479 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1480
1481 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1482 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1483 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1484 case 0x3f: case 0x41:
1485
1486 case 0xb1: case 0xb0: case 0xb2:
1487 case 0xaa: case 0xae:
1488
1489 case 0x24:
1490
1491 case 0x38: case 0x3d:
1492
1493 case 0xb6:
1494
1495 case 0xea: /* alternate number for WRITE LONG */1496
1497 current_SC->SCp.have_data_in = -1;
1498 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1499 break;
1500
1501 case 0x00:
1502 default:
1503
1504 current_SC->SCp.have_data_in = 1;
1505 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1506 break;
1507 }1508 }1509
1510 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1511 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1512 #ifEVERY_ACCESS1513 printk( "DC=%d, ", data_count ) ;
1514 #endif1515 if (data_count > current_SC->SCp.this_residual)
1516 data_count = current_SC->SCp.this_residual;
1517 if (data_count > 0) {1518 #ifEVERY_ACCESS1519 printk( "%d OUT, ", data_count );
1520 #endif1521 if (data_count == 1) {1522 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1523 --current_SC->SCp.this_residual;
1524 }else{1525 data_count >>= 1;
1526 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1527 current_SC->SCp.ptr += 2 * data_count;
1528 current_SC->SCp.this_residual -= 2 * data_count;
1529 }1530 }1531 if (!current_SC->SCp.this_residual) {1532 if (current_SC->SCp.buffers_residual) {1533 --current_SC->SCp.buffers_residual;
1534 ++current_SC->SCp.buffer;
1535 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1536 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1537 }else1538 break;
1539 }1540 }1541 }1542
1543 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1544 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1545 #ifEVERY_ACCESS1546 printk( "DC=%d, ", data_count );
1547 #endif1548 if (data_count > current_SC->SCp.this_residual)
1549 data_count = current_SC->SCp.this_residual;
1550 if (data_count) {1551 #ifEVERY_ACCESS1552 printk( "%d IN, ", data_count );
1553 #endif1554 if (data_count == 1) {1555 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1556 --current_SC->SCp.this_residual;
1557 }else{1558 data_count >>= 1; /* Number of words */1559 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1560 current_SC->SCp.ptr += 2 * data_count;
1561 current_SC->SCp.this_residual -= 2 * data_count;
1562 }1563 }1564 if (!current_SC->SCp.this_residual1565 && current_SC->SCp.buffers_residual) {1566 --current_SC->SCp.buffers_residual;
1567 ++current_SC->SCp.buffer;
1568 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1569 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1570 }1571 }1572 }1573
1574 if (done) {1575 #ifEVERY_ACCESS1576 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1577 #endif1578
1579 #ifERRORS_ONLY1580 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1581 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1582 unsignedcharkey;
1583 unsignedcharcode;
1584 unsignedcharqualifier;
1585
1586 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1587 & 0x0f;
1588 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1589 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1590 + 13));
1591
1592 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1593 && !(key == NOT_READY1594 && code == 0x04
1595 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1596 && !(key == ILLEGAL_REQUEST && (code == 0x25
1597 || code == 0x24
1598 || !code)))
1599
1600 printk( "fdomain: REQUEST SENSE "
1601 "Key = %x, Code = %x, Qualifier = %x\n",
1602 key, code, qualifier );
1603 }1604 }1605 #endif1606 #ifEVERY_ACCESS1607 printk( "BEFORE MY_DONE. . ." );
1608 #endif1609 my_done( (current_SC->SCp.Status & 0xff)
1610 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1611 #ifEVERY_ACCESS1612 printk( "RETURNING.\n" );
1613 #endif1614
1615 }else{1616 if (current_SC->SCp.phase & disconnect) {1617 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1618 outb( 0x00, SCSI_Cntl_port );
1619 }else{1620 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1621 }1622 }1623 #ifDEBUG_RACE1624 in_interrupt_flag = 0;
1625 #endif1626 return;
1627 }1628
1629 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1630 {1631 if (in_command) {1632 panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1633 }1634 #ifEVERY_ACCESS1635 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1636 SCpnt->target,
1637 *(unsignedchar *)SCpnt->cmnd,
1638 SCpnt->use_sg,
1639 SCpnt->request_bufflen );
1640 #endif1641
1642 fdomain_make_bus_idle();
1643
1644 current_SC = SCpnt; /* Save this for the done function */1645 current_SC->scsi_done = done;
1646
1647 /* Initialize static data */1648
1649 if (current_SC->use_sg) {1650 current_SC->SCp.buffer =
1651 (structscatterlist *)current_SC->request_buffer;
1652 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1653 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1654 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1655 }else{1656 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1657 current_SC->SCp.this_residual = current_SC->request_bufflen;
1658 current_SC->SCp.buffer = NULL;
1659 current_SC->SCp.buffers_residual = 0;
1660 }1661
1662
1663 current_SC->SCp.Status = 0;
1664 current_SC->SCp.Message = 0;
1665 current_SC->SCp.have_data_in = 0;
1666 current_SC->SCp.sent_command = 0;
1667 current_SC->SCp.phase = in_arbitration;
1668
1669 /* Start arbitration */1670 outb( 0x00, Interrupt_Cntl_port );
1671 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1672 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1673 ++in_command;
1674 outb( 0x20, Interrupt_Cntl_port );
1675 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1676
1677 return 0;
1678 }1679
1680 /* The following code, which simulates the old-style command function, was1681 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1682 1992 Tommy Thorn. */1683
1684 staticvolatileintinternal_done_flag = 0;
1685 staticvolatileintinternal_done_errcode = 0;
1686
1687 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1688 {1689 internal_done_errcode = SCpnt->result;
1690 ++internal_done_flag;
1691 }1692
1693 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1694 {1695 fdomain_16x0_queue( SCpnt, internal_done );
1696
1697 while (!internal_done_flag)
1698 ;
1699 internal_done_flag = 0;
1700 returninternal_done_errcode;
1701 }1702
1703 /* End of code derived from Tommy Thorn's work. */1704
1705 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1706 {1707 unsignedintimr;
1708 unsignedintirr;
1709 unsignedintisr;
1710
1711 if (!SCpnt || !SCpnt->host) {1712 printk( "fdomain: cannot provide detailed information\n" );
1713 }1714
1715 printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
1716 print_banner( SCpnt->host );
1717 switch (SCpnt->SCp.phase) {1718 casein_arbitration: printk( "arbitration " ); break;
1719 casein_selection: printk( "selection " ); break;
1720 casein_other: printk( "other " ); break;
1721 default: printk( "unknown " ); break;
1722 }1723
1724 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1725 SCpnt->SCp.phase,
1726 SCpnt->target,
1727 *(unsignedchar *)SCpnt->cmnd,
1728 SCpnt->use_sg,
1729 SCpnt->request_bufflen );
1730 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1731 SCpnt->SCp.sent_command,
1732 SCpnt->SCp.have_data_in,
1733 SCpnt->timeout );
1734 #ifDEBUG_RACE1735 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1736 #endif1737
1738 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1739 outb( 0x0a, 0xa0 );
1740 irr = inb( 0xa0 ) << 8;
1741 outb( 0x0a, 0x20 );
1742 irr += inb( 0x20 );
1743 outb( 0x0b, 0xa0 );
1744 isr = inb( 0xa0 ) << 8;
1745 outb( 0x0b, 0x20 );
1746 isr += inb( 0x20 );
1747
1748 /* Print out interesting information */1749 printk( "IMR = 0x%04x", imr );
1750 if (imr & (1 << interrupt_level))
1751 printk( " (masked)" );
1752 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1753
1754 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1755 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1756 if (inb( TMC_Status_port & 1))
1757 printk( " (interrupt)" );
1758 printk( "\n" );
1759 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1760 if (inb( Interrupt_Status_port ) & 0x08)
1761 printk( " (enabled)" );
1762 printk( "\n" );
1763 if (chip == tmc18c50 || chip == tmc18c30) {1764 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1765 printk( "Int. Condition = 0x%02x\n",
1766 inb( port_base + Interrupt_Cond ) );
1767 }1768 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1769 if (chip == tmc18c50 || chip == tmc18c30)
1770 printk( "Configuration 2 = 0x%02x\n",
1771 inb( port_base + Configuration2 ) );
1772 }1773
1774 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1775 {1776 unsignedlongflags;
1777 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1778 printk( "fdomain: abort " );
1779 #endif1780
1781 save_flags( flags );
1782 cli();
1783 if (!in_command) {1784 #ifEVERY_ACCESS || ERRORS_ONLY1785 printk( " (not in command)\n" );
1786 #endif1787 restore_flags( flags );
1788 returnSCSI_ABORT_NOT_RUNNING;
1789 }elseprintk( "\n" );
1790
1791 #ifDEBUG_ABORT1792 print_info( SCpnt );
1793 #endif1794
1795 fdomain_make_bus_idle();
1796
1797 current_SC->SCp.phase |= aborted;
1798
1799 current_SC->result = DID_ABORT << 16;
1800
1801 restore_flags( flags );
1802
1803 /* Aborts are not done well. . . */1804 my_done( DID_ABORT << 16 );
1805
1806 returnSCSI_ABORT_SUCCESS;
1807 }1808
1809 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1810 {1811 #ifDEBUG_RESET1812 staticintcalled_once = 0;
1813 #endif1814
1815 #ifERRORS_ONLY1816 if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
1817 #endif1818
1819 #ifDEBUG_RESET1820 if (called_once) print_info( current_SC );
1821 called_once = 1;
1822 #endif1823
1824 outb( 1, SCSI_Cntl_port );
1825 do_pause( 2 );
1826 outb( 0, SCSI_Cntl_port );
1827 do_pause( 115 );
1828 outb( 0, SCSI_Mode_Cntl_port );
1829 outb( PARITY_MASK, TMC_Cntl_port );
1830
1831 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1832 is probably hosed at this point. We will, however, try to keep1833 things going by informing the high-level code that we need help. */1834
1835 returnSCSI_RESET_WAKEUP;
1836 }1837
1838 #include "sd.h"
1839 #include "scsi_ioctl.h"
1840
1841 intfdomain_16x0_biosparam( Scsi_Disk *disk, kdev_tdev, int *info_array )
/* */1842 {1843 intdrive;
1844 unsignedcharbuf[512 + sizeof( int ) * 2];
1845 intsize = disk->capacity;
1846 int *sizes = (int *)buf;
1847 unsignedchar *data = (unsignedchar *)(sizes + 2);
1848 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1849 intretcode;
1850 structdrive_info{1851 unsignedshortcylinders;
1852 unsignedcharheads;
1853 unsignedcharsectors;
1854 } *i;
1855
1856 /* NOTES:1857 The RAM area starts at 0x1f00 from the bios_base address.1858
1859 For BIOS Version 2.0:1860 1861 The drive parameter table seems to start at 0x1f30.1862 The first byte's purpose is not known.1863 Next is the cylinder, head, and sector information.1864 The last 4 bytes appear to be the drive's size in sectors.1865 The other bytes in the drive parameter table are unknown.1866 If anyone figures them out, please send me mail, and I will1867 update these notes.1868
1869 Tape drives do not get placed in this table.1870
1871 There is another table at 0x1fea:1872 If the byte is 0x01, then the SCSI ID is not in use.1873 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1874 although tapes don't seem to be in this table. I haven't1875 seen any other numbers (in a limited sample).1876
1877 0x1f2d is a drive count (i.e., not including tapes)1878
1879 The table at 0x1fcc are I/O ports addresses for the various1880 operations. I calculate these by hand in this driver code.1881
1882 1883 1884 For the ISA-200S version of BIOS Version 2.0:1885
1886 The drive parameter table starts at 0x1f33.1887
1888 WARNING: Assume that the table entry is 25 bytes long. Someone needs1889 to check this for the Quantum ISA-200S card.1890
1891 1892 1893 For BIOS Version 3.2:1894
1895 The drive parameter table starts at 0x1f70. Each entry is1896 0x0a bytes long. Heads are one less than we need to report.1897 */1898
1899 drive = MINOR(dev) / 16;
1900
1901 if (bios_major == 2) {1902 switch (Quantum) {1903 case 2: /* ISA_200S */1904 /* The value of 25 has never been verified.1905 It should probably be 15. */1906 i = (structdrive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1907 break;
1908 case 3: /* ISA_250MG */1909 i = (structdrive_info *)( (char *)bios_base + 0x1f36 + drive * 15 );
1910 break;
1911 case 4: /* ISA_200S (another one) */1912 i = (structdrive_info *)( (char *)bios_base + 0x1f34 + drive * 15 );
1913 break;
1914 default:
1915 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1916 break;
1917 }1918 info_array[0] = i->heads;
1919 info_array[1] = i->sectors;
1920 info_array[2] = i->cylinders;
1921 }elseif (bios_major == 3
1922 && bios_minor >= 0
1923 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1924 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1925 info_array[0] = i->heads + 1;
1926 info_array[1] = i->sectors;
1927 info_array[2] = i->cylinders;
1928 }else{/* 3.4 BIOS (and up?) */1929 /* This algorithm was provided by Future Domain (much thanks!). */1930
1931 sizes[0] = 0; /* zero bytes out */1932 sizes[1] = 512; /* one sector in */1933 memcpy( data, do_read, sizeof( do_read ) );
1934 retcode = kernel_scsi_ioctl( disk->device,
1935 SCSI_IOCTL_SEND_COMMAND,
1936 (void *)buf );
1937 if (!retcode/* SCSI command ok */1938 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1939 && data[0x1c2]) {/* Partition type */1940
1941 /* The partition table layout is as follows:1942
1943 Start: 0x1b3h1944 Offset: 0 = partition status1945 1 = starting head1946 2 = starting sector and cylinder (word, encoded)1947 4 = partition type1948 5 = ending head1949 6 = ending sector and cylinder (word, encoded)1950 8 = starting absolute sector (double word)1951 c = number of sectors (double word)1952 Signature: 0x1fe = 0x55aa1953
1954 So, this algorithm assumes:1955 1) the first partition table is in use,1956 2) the data in the first entry is correct, and1957 3) partitions never divide cylinders1958
1959 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1960 as well as for Linux. Note also, that Linux doesn't pay any1961 attention to the fields that are used by this algorithm -- it1962 only uses the absolute sector data. Recent versions of Linux's1963 fdisk(1) will fill this data in correctly, and forthcoming1964 versions will check for consistency.1965
1966 Checking for a non-zero partition type is not part of the1967 Future Domain algorithm, but it seemed to be a reasonable thing1968 to do, especially in the Linux and BSD worlds. */1969
1970 info_array[0] = data[0x1c3] + 1; /* heads */1971 info_array[1] = data[0x1c4] & 0x3f; /* sectors */1972 }else{1973
1974 /* Note that this new method guarantees that there will always be1975 less than 1024 cylinders on a platter. This is good for drives1976 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */1977
1978 if ((unsignedint)size >= 0x7e0000U) {1979 info_array[0] = 0xff; /* heads = 255 */1980 info_array[1] = 0x3f; /* sectors = 63 */1981 }elseif ((unsignedint)size >= 0x200000U) {1982 info_array[0] = 0x80; /* heads = 128 */1983 info_array[1] = 0x3f; /* sectors = 63 */1984 }else{1985 info_array[0] = 0x40; /* heads = 64 */1986 info_array[1] = 0x20; /* sectors = 32 */1987 }1988 }1989 /* For both methods, compute the cylinders */1990 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
1991 }1992
1993 return 0;
1994 }1995
1996 #ifdefMODULE1997 /* Eventually this will go into an include file, but this will be later */1998 Scsi_Host_Templatedriver_template = FDOMAIN_16X0;
1999
2000 #include "scsi_module.c"
2001 #endif