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: Wed Dec 7 09:36:57 1994 by faith@cs.unc.edu 4 * Author: Rickard E. Faith, faith@cs.unc.edu 5 * Copyright 1992, 1993, 1994 Rickard E. Faith 6 * 7 * $Id: fdomain.c,v 5.22 1994/12/07 15:15:46 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 SCSI adapter. 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 All of the alpha testers deserve much thanks. 141
142
143
144 NOTES ON USER DEFINABLE OPTIONS: 145
146 DEBUG: This turns on the printing of various debug information. 147
148 ENABLE_PARITY: This turns on SCSI parity checking. With the current 149 driver, all attached devices must support SCSI parity. If none of your 150 devices support parity, then you can probably get the driver to work by 151 turning this option off. I have no way of testing this, however. 152
153 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the 154 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by 155 the SCSI device, an interrupt will be raised. Therefore, this could be as 156 low as 0, or as high as 16. Note, however, that values which are too high 157 or too low seem to prevent any interrupts from occurring, and thereby lock 158 up the machine. I have found that 2 is a good number, but throughput may 159 be increased by changing this value to values which are close to 2. 160 Please let me know if you try any different values. 161
162 DO_DETECT: This activates some old scan code which was needed before the 163 high level drivers got fixed. If you are having trouble with the driver, 164 turning this on should not hurt, and might help. Please let me know if 165 this is the case, since this code will be removed from future drivers. 166
167 RESELECTION: This is no longer an option, since I gave up trying to 168 implement it in version 4.x of this driver. It did not improve 169 performance at all and made the driver unstable (because I never found one 170 of the two race conditions which were introduced by the multiple 171 outstanding command code). The instability seems a very high price to pay 172 just so that you don't have to wait for the tape to rewind. If you want 173 this feature implemented, send me patches. I'll be happy to send a copy 174 of my (broken) driver to anyone who would like to see a copy. 175
176 **************************************************************************/ 177
178 #include <linux/sched.h>
179 #include <asm/io.h>
180 #include "../block/blk.h"
181 #include "scsi.h"
182 #include "hosts.h"
183 #include "fdomain.h"
184 #include <asm/system.h>
185 #include <linux/errno.h>
186 #include <linux/string.h>
187 #include <linux/ioport.h>
188
189 #defineVERSION "$Revision: 5.22 $"
190
191 /* START OF USER DEFINABLE OPTIONS */ 192
193 #defineDEBUG 1 /* Enable debugging output */ 194 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 195 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 196 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 197
198 /* END OF USER DEFINABLE OPTIONS */ 199
200 #ifDEBUG 201 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 202 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 203 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 204 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 205 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 206 #defineDEBUG_RESET 1 /* Debug reset() routine */ 207 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 208 #else 209 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 210 #defineERRORS_ONLY 0
211 #defineDEBUG_DETECT 0
212 #defineDEBUG_MESSAGES 0
213 #defineDEBUG_ABORT 0
214 #defineDEBUG_RESET 0
215 #defineDEBUG_RACE 0
216 #endif 217
218 /* Errors are reported on the line, so we don't need to report them again */ 219 #ifEVERY_ACCESS 220 #undefERRORS_ONLY 221 #defineERRORS_ONLY 0
222 #endif 223
224 #ifENABLE_PARITY 225 #definePARITY_MASK 0x08
226 #else 227 #definePARITY_MASK 0x00
228 #endif 229
230 enumchip_type{ 231 unknown = 0x00,
232 tmc1800 = 0x01,
233 tmc18c50 = 0x02,
234 tmc18c30 = 0x03,
235 };
236
237 enum{ 238 in_arbitration = 0x02,
239 in_selection = 0x04,
240 in_other = 0x08,
241 disconnect = 0x10,
242 aborted = 0x20,
243 sent_ident = 0x40,
244 };
245
246 enum in_port_type { 247 Read_SCSI_Data = 0,
248 SCSI_Status = 1,
249 TMC_Status = 2,
250 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 251 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 252 LSB_ID_Code = 5,
253 MSB_ID_Code = 6,
254 Read_Loopback = 7,
255 SCSI_Data_NoACK = 8,
256 Interrupt_Status = 9,
257 Configuration1 = 10,
258 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 259 Read_FIFO = 12,
260 FIFO_Data_Count = 14
261 };
262
263 enum out_port_type { 264 Write_SCSI_Data = 0,
265 SCSI_Cntl = 1,
266 Interrupt_Cntl = 2,
267 SCSI_Mode_Cntl = 3,
268 TMC_Cntl = 4,
269 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 270 Write_Loopback = 7,
271 IO_Control = 11, /* tmc18c30 only */ 272 Write_FIFO = 12
273 };
274
275 staticintport_base = 0;
276 staticvoid *bios_base = NULL;
277 staticintbios_major = 0;
278 staticintbios_minor = 0;
279 staticintPCI_bus = 0;
280 staticintISA_200S = 0; /* Quantum ISA-200S */ 281 staticintinterrupt_level = 0;
282 staticvolatileintin_command = 0;
283 staticScsi_Cmnd *current_SC = NULL;
284 staticenumchip_typechip = unknown;
285 staticintadapter_mask = 0x40;
286 #ifDEBUG_RACE 287 staticvolatileintin_interrupt_flag = 0;
288 #endif 289
290 staticintSCSI_Mode_Cntl_port;
291 staticintFIFO_Data_Count_port;
292 staticintInterrupt_Cntl_port;
293 staticintInterrupt_Status_port;
294 staticintRead_FIFO_port;
295 staticintRead_SCSI_Data_port;
296 staticintSCSI_Cntl_port;
297 staticintSCSI_Data_NoACK_port;
298 staticintSCSI_Status_port;
299 staticintTMC_Cntl_port;
300 staticintTMC_Status_port;
301 staticintWrite_FIFO_port;
302 staticintWrite_SCSI_Data_port;
303
304 staticintFIFO_Size = 0x2000; /* 8k FIFO for 305 pre-tmc18c30 chips */ 306
307 externvoidfdomain_16x0_intr( intunused );
308
309 staticvoid *addresses[] = { 310 (void *)0xc8000,
311 (void *)0xca000,
312 (void *)0xce000,
313 (void *)0xde000,
314 (void *)0xd0000, /* Extra addresses for PCI boards */ 315 };
316 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
317
318 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
319 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
320
321 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
322
323 /* 324
325 READ THIS BEFORE YOU ADD A SIGNATURE! 326
327 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 328
329 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 330
331 This driver works *ONLY* for Future Domain cards using the TMC-1800, 332 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 333 and 1680. 334
335 The following BIOS signature signatures are for boards which do *NOT* 336 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 337 Seagate driver): 338
339 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 340 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 341 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 342 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 343 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 344 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 345 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 346
347 */ 348
349 structsignature{ 350 char *signature;
351 intsig_offset;
352 intsig_length;
353 intmajor_bios_version;
354 intminor_bios_version;
355 intflag; /* 1 == PCI_bus, 2 == ISA_200S */ 356 }signatures[] = { 357 /* 1 2 3 4 5 6 */ 358 /* 123456789012345678901234567890123456789012345678901234567890 */ 359 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
360 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
361 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
362 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
363 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
364 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
365 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
366 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
367 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
368
369 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE 370 Also, fix the disk geometry code for your signature and send your 371 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 372 signatures! 373
374 Note that the last line will match a "generic" 18XX bios. Because 375 Future Domain has changed the host SCSI ID and/or the location of the 376 geometry information in the on-board RAM area for each of the first 377 three BIOS's, it is still important to enter a fully qualified 378 signature in the table for any new BIOS's (after the host SCSI ID and 379 geometry location are verified.) */ 380 };
381
382 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
383
384 staticvoidprint_banner( structScsi_Host * shpnt )
385 { 386 printk( "%s", fdomain_16x0_info(shpnt) );
387 printk( "Future Domain: BIOS version %d.%d, %s\n",
388 bios_major, bios_minor,
389 chip == tmc1800 ? "TMC-1800"
390 : (chip == tmc18c50 ? "TMC-18C50"
391 : (chip == tmc18c30 ? "TMC-18C30" : "Unknown")) );
392
393 if (interrupt_level) { 394 printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
395 (unsigned)bios_base, port_base, interrupt_level );
396 }else{ 397 printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
398 (unsigned)bios_base, port_base );
399 } 400 } 401
402 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 403 { 404 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 405
406 while (jiffies < the_time);
407 } 408
409 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 410 { 411 outb( 0, SCSI_Cntl_port );
412 outb( 0, SCSI_Mode_Cntl_port );
413 if (chip == tmc18c50 || chip == tmc18c30)
414 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 415 else 416 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
417 } 418
419 staticintfdomain_is_valid_port( intport )
/* */ 420 { 421 intoptions;
422
423 #ifDEBUG_DETECT 424 printk( " (%x%x),",
425 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
426 #endif 427
428 /* The MCA ID is a unique id for each MCA compatible board. We 429 are using ISA boards, but Future Domain provides the MCA ID 430 anyway. We can use this ID to ensure that this is a Future 431 Domain TMC-1660/TMC-1680. 432 */ 433
434 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 435 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
436 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
437 chip = tmc1800;
438 }else{/* test for 0xe960 id */ 439 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
440 chip = tmc18c50;
441
442 #if 0
443
444 /* Try to toggle 32-bit mode. This only 445 works on an 18c30 chip. (User reports 446 say that this doesn't work at all, so 447 we'll use the other method.) */ 448
449 outb( 0x80, port + IO_Control );
450 if (inb( port + Configuration2 ) & 0x80 == 0x80) { 451 outb( 0x00, port + IO_Control );
452 if (inb( port + Configuration2 ) & 0x80 == 0x00) { 453 chip = tmc18c30;
454 FIFO_Size = 0x800; /* 2k FIFO */ 455 } 456 } 457 #else 458
459 /* That should have worked, but appears to 460 have problems. Lets assume it is an 461 18c30 if the RAM is disabled. */ 462
463 if (inb( port + Configuration2 ) & 0x02) { 464 chip = tmc18c30;
465 FIFO_Size = 0x800; /* 2k FIFO */ 466 } 467 #endif 468 /* If that failed, we are an 18c50. */ 469 } 470
471 /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board. 472 Now, check to be sure the bios_base matches these ports. If someone 473 was unlucky enough to have purchased more than one Future Domain 474 board, then they will have to modify this code, as we only detect one 475 board here. [The one with the lowest bios_base.] */ 476
477 options = inb( port + Configuration1 );
478
479 #ifDEBUG_DETECT 480 printk( " Options = %x\n", options );
481 #endif 482
483 /* Check for board with lowest bios_base -- 484 this isn't valid for the 18c30 or for 485 boards on the PCI bus, so just assume we 486 have the right board. */ 487
488 if (chip != tmc18c30 489 && !PCI_bus 490 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
491
492 /* Get the IRQ from the options. */ 493
494 interrupt_level = ints[ (options & 0x0e) >> 1 ];
495
496 return 1;
497 } 498
499 staticintfdomain_test_loopback( void )
/* */ 500 { 501 inti;
502 intresult;
503
504 for (i = 0; i < 255; i++) { 505 outb( i, port_base + Write_Loopback );
506 result = inb( port_base + Read_Loopback );
507 if (i != result)
508 return 1;
509 } 510 return 0;
511 } 512
513 intfdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* */ 514 { 515 inti, j;
516 intflag = 0;
517 intretcode;
518 #ifDO_DETECT 519 constintbuflen = 255;
520 Scsi_CmndSCinit;
521 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
522 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
523 unsignedchardo_read_capacity[] = {READ_CAPACITY,
524 0, 0, 0, 0, 0, 0, 0, 0, 0 };
525 unsignedcharbuf[buflen];
526 #endif 527
528 #ifDEBUG_DETECT 529 printk( "fdomain_16x0_detect()," );
530 #endif 531
532 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 533 #ifDEBUG_DETECT 534 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
535 #endif 536 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 537 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
538 signatures[j].signature, signatures[j].sig_length )) { 539 bios_major = signatures[j].major_bios_version;
540 bios_minor = signatures[j].minor_bios_version;
541 PCI_bus = (signatures[j].flag == 1);
542 ISA_200S = (signatures[j].flag == 2);
543 bios_base = addresses[i];
544 } 545 } 546 } 547
548 if (!bios_base) { 549 #ifDEBUG_DETECT 550 printk( " FAILED: NO BIOS\n" );
551 #endif 552 return 0;
553 } 554
555 if (bios_major == 2) { 556 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 557 Assuming the ROM is enabled (otherwise we wouldn't have been 558 able to read the ROM signature :-), then the ROM sets up the 559 RAM area with some magic numbers, such as a list of port 560 base addresses and a list of the disk "geometry" reported to 561 DOS (this geometry has nothing to do with physical geometry). 562 */ 563
564 if (ISA_200S) {/* The Quantum board is slightly different. */ 565 port_base = *((char *)bios_base + 0x1fa2)
566 + (*((char *)bios_base + 0x1fa3) << 8);
567 }else{ 568 port_base = *((char *)bios_base + 0x1fcc)
569 + (*((char *)bios_base + 0x1fcd) << 8);
570 } 571
572 #ifDEBUG_DETECT 573 printk( " %x,", port_base );
574 #endif 575
576 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 577 if (port_base == ports[i])
578 ++flag;
579 } 580
581 if (flag)
582 flag = fdomain_is_valid_port( port_base );
583 } 584
585 if (!flag) {/* Cannot get port base from BIOS RAM */ 586
587 /* This is a bad sign. It usually means that someone patched the 588 BIOS signature list (the signatures variable) to contain a BIOS 589 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. It 590 also means that we don't have a Version 2.0 BIOS :-) 591 */ 592
593 #ifDEBUG_DETECT 594 if (bios_major != 2) printk( " RAM FAILED, " );
595 #endif 596
597 /* Anyway, the alternative to finding the address in the RAM is to 598 just search through every possible port address for one that is 599 attached to the Future Domain card. Don't panic, though, about 600 reading all these random port addresses -- there are rumors that 601 the Future Domain BIOS does something very similar. 602
603 Do not, however, check ports which the kernel knows are being used 604 by another driver. */ 605
606 if (!PCI_bus) { 607 for (i = 0; !flag && i < PORT_COUNT; i++) { 608 port_base = ports[i];
609 if (check_region( port_base, 0x10 )) { 610 #ifDEBUG_DETECT 611 printk( " (%x inuse),", port_base );
612 #endif 613 continue;
614 } 615 #ifDEBUG_DETECT 616 printk( " %x,", port_base );
617 #endif 618 flag = fdomain_is_valid_port( port_base );
619 } 620 }else{ 621
622 /* The proper way of doing this is to use ask the PCI bus for the 623 device IRQ and interrupt level. 624
625 Until the Linux kernel supports this sort of PCI bus query, we 626 scan down a bunch of addresses (Future Domain tech support says 627 we will probably find the address before we get to 0xf800). 628 This works fine on some systems -- other systems may have to 629 scan more addresses. If you have to modify this section for 630 your installation, please send mail to faith@cs.unc.edu. */ 631
632 for (i = 0xff00; !flag && i > 0xf000; i -= 8) { 633 port_base = i;
634 if (check_region( port_base, 0x10 )) { 635 #ifDEBUG_DETECT 636 printk( " (%x inuse)," , port_base );
637 #endif 638 continue;
639 } 640 flag = fdomain_is_valid_port( port_base );
641 } 642 } 643 } 644
645 if (!flag) { 646 #ifDEBUG_DETECT 647 printk( " FAILED: NO PORT\n" );
648 #endif 649 return 0; /* Cannot find valid set of ports */ 650 } 651
652 print_banner(NULL);
653
654 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
655 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
656 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
657 Interrupt_Status_port = port_base + Interrupt_Status;
658 Read_FIFO_port = port_base + Read_FIFO;
659 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
660 SCSI_Cntl_port = port_base + SCSI_Cntl;
661 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
662 SCSI_Status_port = port_base + SCSI_Status;
663 TMC_Cntl_port = port_base + TMC_Cntl;
664 TMC_Status_port = port_base + TMC_Status;
665 Write_FIFO_port = port_base + Write_FIFO;
666 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
667
668 fdomain_16x0_reset( NULL );
669
670 if (fdomain_test_loopback()) { 671 #ifDEBUG_DETECT 672 printk( "Future Domain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
673 #endif 674 return 0;
675 }/* Log IRQ with kernel */ 676
677 if (!interrupt_level) { 678 panic( "Future Domain: *NO* interrupt level selected!\n" );
679 }else{ 680 /* Register the IRQ with the kernel */ 681
682 retcode = request_irq( interrupt_level, fdomain_16x0_intr, SA_INTERRUPT, "FDomain");
683
684 if (retcode < 0) { 685 if (retcode == -EINVAL) { 686 printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
687 printk( " This shouldn't happen!\n" );
688 printk( " Send mail to faith@cs.unc.edu\n" );
689 }elseif (retcode == -EBUSY) { 690 printk( "Future Domain: IRQ %d is already in use!\n",
691 interrupt_level );
692 printk( " Please use another IRQ!\n" );
693 }else{ 694 printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
695 printk( " This shouldn't happen!\n" );
696 printk( " Send mail to faith@cs.unc.edu\n" );
697 } 698 panic( "Future Domain: Driver requires interruptions\n" );
699 }else{ 700 printk( "Future Domain: IRQ %d requested from kernel\n",
701 interrupt_level );
702 } 703 } 704
705 /* Log I/O ports with kernel */ 706
707 register_iomem( port_base, 0x10 ,"fdomain");
708
709 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 710 adapter_mask = 0x80;
711 tpnt->this_id = 7;
712 } 713
714 #ifDO_DETECT 715
716 /* These routines are here because of the way the SCSI bus behaves after 717 a reset. This appropriate behavior was not handled correctly by the 718 higher level SCSI routines when I first wrote this driver. Now, 719 however, correct scan routines are part of scsi.c and these routines 720 are no longer needed. However, this code is still good for 721 debugging. */ 722
723 SCinit.request_buffer = SCinit.buffer = buf;
724 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
725 SCinit.use_sg = 0;
726 SCinit.lun = 0;
727
728 printk( "Future Domain detection routine scanning for devices:\n" );
729 for (i = 0; i < 8; i++) { 730 SCinit.target = i;
731 if (i == tpnt->this_id) /* Skip host adapter */ 732 continue;
733 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
734 retcode = fdomain_16x0_command(&SCinit);
735 if (!retcode) { 736 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
737 retcode = fdomain_16x0_command(&SCinit);
738 if (!retcode) { 739 printk( " SCSI ID %d: ", i );
740 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
741 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
742 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
743 retcode = fdomain_16x0_command(&SCinit);
744 if (!retcode) { 745 unsignedlongblocks, size, capacity;
746
747 blocks = (buf[0] << 24) | (buf[1] << 16)
748 | (buf[2] << 8) | buf[3];
749 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
750 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
751
752 printk( "%lu MB (%lu byte blocks)",
753 ((capacity + 5L) / 10L), size );
754 }else{ 755 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
756 retcode = fdomain_16x0_command(&SCinit);
757 } 758 printk ("\n" );
759 }else{ 760 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
761 retcode = fdomain_16x0_command(&SCinit);
762 } 763 } 764 } 765 #endif 766
767 return 1;
768 } 769
770 constchar *fdomain_16x0_info(structScsi_Host * shpnt)
/* */ 771 { 772 staticcharbuffer[80];
773 char *pt;
774
775 strcpy( buffer, "Future Domain: TMC-16x0 SCSI driver, version" );
776 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */ 777 strcat( buffer, strchr( VERSION, ':' ) + 1 );
778 pt = strrchr( buffer, '$') - 1;
779 if (!pt) /* Stripped RCS Revision string? */ 780 pt = buffer + strlen( buffer ) - 1;
781 if (*pt != ' ')
782 ++pt;
783 *pt++ = '\n';
784 *pt = '\0';
785 }else{/* Assume VERSION is a number */ 786 strcat( buffer, " " VERSION "\n" );
787 } 788
789 returnbuffer;
790 } 791
792 #if 0
793 staticint fdomain_arbitrate( void )
/* */ 794 { 795 intstatus = 0;
796 unsignedlongtimeout;
797
798 #ifEVERY_ACCESS 799 printk( "fdomain_arbitrate()\n" );
800 #endif 801
802 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ 803 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ 804 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ 805
806 timeout = jiffies + 50; /* 500 mS */ 807 while (jiffies < timeout) { 808 status = inb( TMC_Status_port ); /* Read adapter status */ 809 if (status & 0x02) /* Arbitration complete */ 810 return 0;
811 } 812
813 /* Make bus idle */ 814 fdomain_make_bus_idle();
815
816 #ifEVERY_ACCESS 817 printk( "Arbitration failed, status = %x\n", status );
818 #endif 819 #ifERRORS_ONLY 820 printk( "Future Domain: Arbitration failed, status = %x\n", status );
821 #endif 822 return 1;
823 } 824 #endif 825
826 staticintfdomain_select( inttarget )
/* */ 827 { 828 intstatus;
829 unsignedlongtimeout;
830 staticintflag = 0;
831
832
833 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ 834 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
835
836 /* Stop arbitration and enable parity */ 837 outb( PARITY_MASK, TMC_Cntl_port );
838
839 timeout = jiffies + 35; /* 350mS -- because of timeouts 840 (was 250mS) */ 841
842 while (jiffies < timeout) { 843 status = inb( SCSI_Status_port ); /* Read adapter status */ 844 if (status & 1) {/* Busy asserted */ 845 /* Enable SCSI Bus (on error, should make bus idle with 0) */ 846 outb( 0x80, SCSI_Cntl_port );
847 return 0;
848 } 849 } 850 /* Make bus idle */ 851 fdomain_make_bus_idle();
852 #ifEVERY_ACCESS 853 if (!target) printk( "Selection failed\n" );
854 #endif 855 #ifERRORS_ONLY 856 if (!target) { 857 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */ 858 ++flag;
859 else 860 printk( "Future Domain: Selection failed\n" );
861 } 862 #endif 863 return 1;
864 } 865
866 voidmy_done( interror )
/* */ 867 { 868 if (in_command) { 869 in_command = 0;
870 outb( 0x00, Interrupt_Cntl_port );
871 fdomain_make_bus_idle();
872 current_SC->result = error;
873 if (current_SC->scsi_done)
874 current_SC->scsi_done( current_SC );
875 elsepanic( "Future Domain: current_SC->scsi_done() == NULL" );
876 }else{ 877 panic( "Future Domain: my_done() called outside of command\n" );
878 } 879 #ifDEBUG_RACE 880 in_interrupt_flag = 0;
881 #endif 882 } 883
884 voidfdomain_16x0_intr( intunused )
/* */ 885 { 886 intstatus;
887 intdone = 0;
888 unsigneddata_count;
889
890 sti();
891
892 outb( 0x00, Interrupt_Cntl_port );
893
894 /* We usually have one spurious interrupt after each command. Ignore it. */ 895 if (!in_command || !current_SC) {/* Spurious interrupt */ 896 #ifEVERY_ACCESS 897 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
898 in_command, current_SC );
899 #endif 900 return;
901 } 902
903 /* Abort calls my_done, so we do nothing here. */ 904 if (current_SC->SCp.phase & aborted) { 905 #ifDEBUG_ABORT 906 printk( "Interrupt after abort, ignoring\n" );
907 #endif 908 /* 909 return; */ 910 } 911
912 #ifDEBUG_RACE 913 ++in_interrupt_flag;
914 #endif 915
916 if (current_SC->SCp.phase & in_arbitration) { 917 status = inb( TMC_Status_port ); /* Read adapter status */ 918 if (!(status & 0x02)) { 919 #ifEVERY_ACCESS 920 printk( " AFAIL " );
921 #endif 922 my_done( DID_BUS_BUSY << 16 );
923 return;
924 } 925 current_SC->SCp.phase = in_selection;
926
927 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
928
929 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ 930 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
931
932 /* Stop arbitration and enable parity */ 933 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
934 #ifDEBUG_RACE 935 in_interrupt_flag = 0;
936 #endif 937 return;
938 }elseif (current_SC->SCp.phase & in_selection) { 939 status = inb( SCSI_Status_port );
940 if (!(status & 0x01)) { 941 /* Try again, for slow devices */ 942 if (fdomain_select( current_SC->target )) { 943 #ifEVERY_ACCESS 944 printk( " SFAIL " );
945 #endif 946 my_done( DID_NO_CONNECT << 16 );
947 return;
948 }else{ 949 #ifEVERY_ACCESS 950 printk( " AltSel " );
951 #endif 952 /* Stop arbitration and enable parity */ 953 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
954 } 955 } 956 current_SC->SCp.phase = in_other;
957 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
958 outb( 0x80, SCSI_Cntl_port );
959 #ifDEBUG_RACE 960 in_interrupt_flag = 0;
961 #endif 962 return;
963 } 964
965 /* current_SC->SCp.phase == in_other: this is the body of the routine */ 966
967 status = inb( SCSI_Status_port );
968
969 if (status & 0x10) {/* REQ */ 970
971 switch (status & 0x0e) { 972
973 case 0x08: /* COMMAND OUT */ 974 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
975 Write_SCSI_Data_port );
976 #ifEVERY_ACCESS 977 printk( "CMD = %x,",
978 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
979 #endif 980 break;
981 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ 982 if (chip != tmc1800 && !current_SC->SCp.have_data_in) { 983 current_SC->SCp.have_data_in = -1;
984 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
985 } 986 break;
987 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ 988 if (chip != tmc1800 && !current_SC->SCp.have_data_in) { 989 current_SC->SCp.have_data_in = 1;
990 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
991 } 992 break;
993 case 0x0c: /* STATUS IN */ 994 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
995 #ifEVERY_ACCESS 996 printk( "Status = %x, ", current_SC->SCp.Status );
997 #endif 998 #ifERRORS_ONLY 999 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {1000 printk( "Future Domain: target = %d, command = %x, "
1001 "Status = %x\n",
1002 current_SC->target, current_SC->cmnd[0],
1003 current_SC->SCp.Status );
1004 }1005 #endif1006 break;
1007 case 0x0a: /* MESSAGE OUT */1008 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */1009 break;
1010 case 0x0e: /* MESSAGE IN */1011 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1012 #ifEVERY_ACCESS1013 printk( "Message = %x, ", current_SC->SCp.Message );
1014 #endif1015 if (!current_SC->SCp.Message) ++done;
1016 #ifDEBUG_MESSAGES || EVERY_ACCESS1017 if (current_SC->SCp.Message) {1018 printk( "Future Domain: Message = %x\n",
1019 current_SC->SCp.Message );
1020 }1021 #endif1022 break;
1023 }1024 }1025
1026 if (chip == tmc18001027 && !current_SC->SCp.have_data_in1028 && (current_SC->SCp.sent_command1029 >= current_SC->cmd_len)) {1030 /* We have to get the FIFO direction1031 correct, so I've made a table based1032 on the SCSI Standard of which commands1033 appear to require a DATA OUT phase.1034 */1035 /*1036 p. 94: Command for all device types1037 CHANGE DEFINITION 40 DATA OUT1038 COMPARE 39 DATA OUT1039 COPY 18 DATA OUT1040 COPY AND VERIFY 3a DATA OUT1041 INQUIRY 12 1042 LOG SELECT 4c DATA OUT1043 LOG SENSE 4d1044 MODE SELECT (6) 15 DATA OUT1045 MODE SELECT (10) 55 DATA OUT1046 MODE SENSE (6) 1a1047 MODE SENSE (10) 5a1048 READ BUFFER 3c1049 RECEIVE DIAGNOSTIC RESULTS 1c1050 REQUEST SENSE 031051 SEND DIAGNOSTIC 1d DATA OUT1052 TEST UNIT READY 001053 WRITE BUFFER 3b DATA OUT1054
1055 p.178: Commands for direct-access devices (not listed on p. 94)1056 FORMAT UNIT 04 DATA OUT1057 LOCK-UNLOCK CACHE 361058 PRE-FETCH 341059 PREVENT-ALLOW MEDIUM REMOVAL 1e1060 READ (6)/RECEIVE 081061 READ (10) 3c1062 READ CAPACITY 251063 READ DEFECT DATA (10) 371064 READ LONG 3e1065 REASSIGN BLOCKS 07 DATA OUT1066 RELEASE 171067 RESERVE 16 DATA OUT1068 REZERO UNIT/REWIND 011069 SEARCH DATA EQUAL (10) 31 DATA OUT1070 SEARCH DATA HIGH (10) 30 DATA OUT1071 SEARCH DATA LOW (10) 32 DATA OUT1072 SEEK (6) 0b1073 SEEK (10) 2b1074 SET LIMITS (10) 331075 START STOP UNIT 1b1076 SYNCHRONIZE CACHE 351077 VERIFY (10) 2f1078 WRITE (6)/PRINT/SEND 0a DATA OUT1079 WRITE (10)/SEND 2a DATA OUT1080 WRITE AND VERIFY (10) 2e DATA OUT1081 WRITE LONG 3f DATA OUT1082 WRITE SAME 41 DATA OUT ?1083
1084 p. 261: Commands for sequential-access devices (not previously listed)1085 ERASE 191086 LOAD UNLOAD 1b1087 LOCATE 2b1088 READ BLOCK LIMITS 051089 READ POSITION 341090 READ REVERSE 0f1091 RECOVER BUFFERED DATA 141092 SPACE 111093 WRITE FILEMARKS 10 ?1094
1095 p. 298: Commands for printer devices (not previously listed)1096 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1097 SLEW AND PRINT 0b DATA OUT -- same as seek1098 STOP PRINT 1b1099 SYNCHRONIZE BUFFER 101100
1101 p. 315: Commands for processor devices (not previously listed)1102 1103 p. 321: Commands for write-once devices (not previously listed)1104 MEDIUM SCAN 381105 READ (12) a81106 SEARCH DATA EQUAL (12) b1 DATA OUT1107 SEARCH DATA HIGH (12) b0 DATA OUT1108 SEARCH DATA LOW (12) b2 DATA OUT1109 SET LIMITS (12) b31110 VERIFY (12) af1111 WRITE (12) aa DATA OUT1112 WRITE AND VERIFY (12) ae DATA OUT1113
1114 p. 332: Commands for CD-ROM devices (not previously listed)1115 PAUSE/RESUME 4b1116 PLAY AUDIO (10) 451117 PLAY AUDIO (12) a51118 PLAY AUDIO MSF 471119 PLAY TRACK RELATIVE (10) 491120 PLAY TRACK RELATIVE (12) a91121 READ HEADER 441122 READ SUB-CHANNEL 421123 READ TOC 431124
1125 p. 370: Commands for scanner devices (not previously listed)1126 GET DATA BUFFER STATUS 341127 GET WINDOW 251128 OBJECT POSITION 311129 SCAN 1b1130 SET WINDOW 24 DATA OUT1131
1132 p. 391: Commands for optical memory devices (not listed)1133 ERASE (10) 2c1134 ERASE (12) ac1135 MEDIUM SCAN 38 DATA OUT1136 READ DEFECT DATA (12) b71137 READ GENERATION 291138 READ UPDATED BLOCK 2d1139 UPDATE BLOCK 3d DATA OUT1140
1141 p. 419: Commands for medium changer devices (not listed)1142 EXCHANGE MEDIUM 461143 INITIALIZE ELEMENT STATUS 071144 MOVE MEDIUM a51145 POSITION TO ELEMENT 2b1146 READ ELEMENT STATUS b81147 REQUEST VOL. ELEMENT ADDRESS b51148 SEND VOLUME TAG b6 DATA OUT1149
1150 p. 454: Commands for communications devices (not listed previously)1151 GET MESSAGE (6) 081152 GET MESSAGE (10) 281153 GET MESSAGE (12) a81154 */1155
1156 switch (current_SC->cmnd[0]) {1157 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1158 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1159 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1160
1161 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1162 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1163 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1164 case 0x3f: case 0x41:
1165
1166 case 0xb1: case 0xb0: case 0xb2:
1167 case 0xaa: case 0xae:
1168
1169 case 0x24:
1170
1171 case 0x38: case 0x3d:
1172
1173 case 0xb6:
1174
1175 case 0xea: /* alternate number for WRITE LONG */1176
1177 current_SC->SCp.have_data_in = -1;
1178 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1179 break;
1180
1181 case 0x00:
1182 default:
1183
1184 current_SC->SCp.have_data_in = 1;
1185 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1186 break;
1187 }1188 }1189
1190 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1191 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1192 #ifEVERY_ACCESS1193 printk( "DC=%d, ", data_count ) ;
1194 #endif1195 if (data_count > current_SC->SCp.this_residual)
1196 data_count = current_SC->SCp.this_residual;
1197 if (data_count > 0) {1198 #ifEVERY_ACCESS1199 printk( "%d OUT, ", data_count );
1200 #endif1201 if (data_count == 1) {1202 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1203 --current_SC->SCp.this_residual;
1204 }else{1205 data_count >>= 1;
1206 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1207 current_SC->SCp.ptr += 2 * data_count;
1208 current_SC->SCp.this_residual -= 2 * data_count;
1209 }1210 }1211 if (!current_SC->SCp.this_residual) {1212 if (current_SC->SCp.buffers_residual) {1213 --current_SC->SCp.buffers_residual;
1214 ++current_SC->SCp.buffer;
1215 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1216 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1217 }else1218 break;
1219 }1220 }1221 }1222
1223 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1224 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1225 #ifEVERY_ACCESS1226 printk( "DC=%d, ", data_count );
1227 #endif1228 if (data_count > current_SC->SCp.this_residual)
1229 data_count = current_SC->SCp.this_residual;
1230 if (data_count) {1231 #ifEVERY_ACCESS1232 printk( "%d IN, ", data_count );
1233 #endif1234 if (data_count == 1) {1235 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1236 --current_SC->SCp.this_residual;
1237 }else{1238 data_count >>= 1; /* Number of words */1239 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1240 current_SC->SCp.ptr += 2 * data_count;
1241 current_SC->SCp.this_residual -= 2 * data_count;
1242 }1243 }1244 if (!current_SC->SCp.this_residual1245 && current_SC->SCp.buffers_residual) {1246 --current_SC->SCp.buffers_residual;
1247 ++current_SC->SCp.buffer;
1248 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1249 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1250 }1251 }1252 }1253
1254 if (done) {1255 #ifEVERY_ACCESS1256 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1257 #endif1258
1259 #ifERRORS_ONLY1260 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1261 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1262 unsignedcharkey;
1263 unsignedcharcode;
1264 unsignedcharqualifier;
1265
1266 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1267 & 0x0f;
1268 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1269 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1270 + 13));
1271
1272 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1273 && !(key == NOT_READY1274 && code == 0x04
1275 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1276 && !(key == ILLEGAL_REQUEST && (code == 0x25
1277 || code == 0x24
1278 || !code)))
1279
1280 printk( "Future Domain: REQUEST SENSE "
1281 "Key = %x, Code = %x, Qualifier = %x\n",
1282 key, code, qualifier );
1283 }1284 }1285 #endif1286 #ifEVERY_ACCESS1287 printk( "BEFORE MY_DONE. . ." );
1288 #endif1289 my_done( (current_SC->SCp.Status & 0xff)
1290 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1291 #ifEVERY_ACCESS1292 printk( "RETURNING.\n" );
1293 #endif1294
1295 }else{1296 if (current_SC->SCp.phase & disconnect) {1297 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1298 outb( 0x00, SCSI_Cntl_port );
1299 }else{1300 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1301 }1302 }1303 #ifDEBUG_RACE1304 in_interrupt_flag = 0;
1305 #endif1306 return;
1307 }1308
1309 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1310 {1311 if (in_command) {1312 panic( "Future Domain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1313 }1314 #ifEVERY_ACCESS1315 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1316 SCpnt->target,
1317 *(unsignedchar *)SCpnt->cmnd,
1318 SCpnt->use_sg,
1319 SCpnt->request_bufflen );
1320 #endif1321
1322 fdomain_make_bus_idle();
1323
1324 current_SC = SCpnt; /* Save this for the done function */1325 current_SC->scsi_done = done;
1326
1327 /* Initialize static data */1328
1329 if (current_SC->use_sg) {1330 current_SC->SCp.buffer =
1331 (structscatterlist *)current_SC->request_buffer;
1332 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1333 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1334 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1335 }else{1336 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1337 current_SC->SCp.this_residual = current_SC->request_bufflen;
1338 current_SC->SCp.buffer = NULL;
1339 current_SC->SCp.buffers_residual = 0;
1340 }1341
1342
1343 current_SC->SCp.Status = 0;
1344 current_SC->SCp.Message = 0;
1345 current_SC->SCp.have_data_in = 0;
1346 current_SC->SCp.sent_command = 0;
1347 current_SC->SCp.phase = in_arbitration;
1348
1349 /* Start arbitration */1350 outb( 0x00, Interrupt_Cntl_port );
1351 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1352 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1353 ++in_command;
1354 outb( 0x20, Interrupt_Cntl_port );
1355 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1356
1357 return 0;
1358 }1359
1360 /* The following code, which simulates the old-style command function, was1361 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1362 1992 Tommy Thorn. */1363
1364 staticvolatileintinternal_done_flag = 0;
1365 staticvolatileintinternal_done_errcode = 0;
1366
1367 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1368 {1369 internal_done_errcode = SCpnt->result;
1370 ++internal_done_flag;
1371 }1372
1373 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1374 {1375 fdomain_16x0_queue( SCpnt, internal_done );
1376
1377 while (!internal_done_flag)
1378 ;
1379 internal_done_flag = 0;
1380 returninternal_done_errcode;
1381 }1382
1383 /* End of code derived from Tommy Thorn's work. */1384
1385 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1386 {1387 unsignedintimr;
1388 unsignedintirr;
1389 unsignedintisr;
1390
1391 print_banner(SCpnt->host);
1392 switch (SCpnt->SCp.phase) {1393 casein_arbitration: printk( "arbitration " ); break;
1394 casein_selection: printk( "selection " ); break;
1395 casein_other: printk( "other " ); break;
1396 default: printk( "unknown " ); break;
1397 }1398
1399 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1400 SCpnt->SCp.phase,
1401 SCpnt->target,
1402 *(unsignedchar *)SCpnt->cmnd,
1403 SCpnt->use_sg,
1404 SCpnt->request_bufflen );
1405 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1406 SCpnt->SCp.sent_command,
1407 SCpnt->SCp.have_data_in,
1408 SCpnt->timeout );
1409 #ifDEBUG_RACE1410 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1411 #endif1412
1413 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1414 outb( 0x0a, 0xa0 );
1415 irr = inb( 0xa0 ) << 8;
1416 outb( 0x0a, 0x20 );
1417 irr += inb( 0x20 );
1418 outb( 0x0b, 0xa0 );
1419 isr = inb( 0xa0 ) << 8;
1420 outb( 0x0b, 0x20 );
1421 isr += inb( 0x20 );
1422
1423 /* Print out interesting information */1424 printk( "IMR = 0x%04x", imr );
1425 if (imr & (1 << interrupt_level))
1426 printk( " (masked)" );
1427 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1428
1429 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1430 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1431 if (inb( TMC_Status_port & 1))
1432 printk( " (interrupt)" );
1433 printk( "\n" );
1434 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1435 if (inb( Interrupt_Status_port ) & 0x08)
1436 printk( " (enabled)" );
1437 printk( "\n" );
1438 if (chip == tmc18c50 || chip == tmc18c30) {1439 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1440 printk( "Int. Condition = 0x%02x\n",
1441 inb( port_base + Interrupt_Cond ) );
1442 }1443 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1444 if (chip == tmc18c50 || chip == tmc18c30)
1445 printk( "Configuration 2 = 0x%02x\n",
1446 inb( port_base + Configuration2 ) );
1447 }1448
1449 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1450 {1451 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1452 printk( "Future Domain: Abort " );
1453 #endif1454
1455 cli();
1456 if (!in_command) {1457 #ifEVERY_ACCESS || ERRORS_ONLY1458 printk( " (not in command)\n" );
1459 #endif1460 sti();
1461 returnSCSI_ABORT_NOT_RUNNING;
1462 }1463
1464 #ifDEBUG_ABORT1465 print_info( SCpnt );
1466 #endif1467
1468 fdomain_make_bus_idle();
1469
1470 current_SC->SCp.phase |= aborted;
1471
1472 current_SC->result = DID_ABORT << 16;
1473
1474 sti();
1475
1476 /* Aborts are not done well. . . */1477 my_done( DID_ABORT << 16 );
1478
1479 returnSCSI_ABORT_SUCCESS;
1480 }1481
1482 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1483 {1484 #ifDEBUG_RESET1485 staticintcalled_once = 0;
1486 #endif1487
1488 #ifERRORS_ONLY1489 printk( "Future Domain: SCSI Bus Reset\n" );
1490 #endif1491
1492 #ifDEBUG_RESET1493 if (called_once) print_info( current_SC );
1494 called_once = 1;
1495 #endif1496
1497 outb( 1, SCSI_Cntl_port );
1498 do_pause( 2 );
1499 outb( 0, SCSI_Cntl_port );
1500 do_pause( 115 );
1501 outb( 0, SCSI_Mode_Cntl_port );
1502 outb( PARITY_MASK, TMC_Cntl_port );
1503
1504 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1505 is probably hosed at this point. We will, however, try to keep1506 things going by informing the high-level code that we need help. */1507
1508 returnSCSI_RESET_WAKEUP;
1509 }1510
1511 #include "sd.h"
1512 #include "scsi_ioctl.h"
1513
1514 intfdomain_16x0_biosparam( Scsi_Disk *disk, intdev, int *info_array )
/* */1515 {1516 intdrive;
1517 unsignedcharbuf[512 + sizeof( int ) * 2];
1518 intsize = disk->capacity;
1519 int *sizes = (int *)buf;
1520 unsignedchar *data = (unsignedchar *)(sizes + 2);
1521 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1522 intretcode;
1523 structdrive_info{1524 unsignedshortcylinders;
1525 unsignedcharheads;
1526 unsignedcharsectors;
1527 } *i;
1528
1529 /* NOTES:1530 The RAM area starts at 0x1f00 from the bios_base address.1531
1532 For BIOS Version 2.0:1533 1534 The drive parameter table seems to start at 0x1f30.1535 The first byte's purpose is not known.1536 Next is the cylinder, head, and sector information.1537 The last 4 bytes appear to be the drive's size in sectors.1538 The other bytes in the drive parameter table are unknown.1539 If anyone figures them out, please send me mail, and I will1540 update these notes.1541
1542 Tape drives do not get placed in this table.1543
1544 There is another table at 0x1fea:1545 If the byte is 0x01, then the SCSI ID is not in use.1546 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1547 although tapes don't seem to be in this table. I haven't1548 seen any other numbers (in a limited sample).1549
1550 0x1f2d is a drive count (i.e., not including tapes)1551
1552 The table at 0x1fcc are I/O ports addresses for the various1553 operations. I calculate these by hand in this driver code.1554
1555 1556 1557 For the ISA-200S version of BIOS Version 2.0:1558
1559 The drive parameter table starts at 0x1f33.1560
1561 WARNING: Assume that the table entry is 25 bytes long. Someone needs1562 to check this for the Quantum ISA-200S card.1563
1564 1565 1566 For BIOS Version 3.2:1567
1568 The drive parameter table starts at 0x1f70. Each entry is1569 0x0a bytes long. Heads are one less than we need to report.1570 */1571
1572 drive = MINOR(dev) / 16;
1573
1574 if (bios_major == 2) {1575 if (ISA_200S) {1576 i = (structdrive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1577 }else{1578 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1579 }1580 info_array[0] = i->heads;
1581 info_array[1] = i->sectors;
1582 info_array[2] = i->cylinders;
1583 }elseif (bios_major == 3 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1584 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1585 info_array[0] = i->heads + 1;
1586 info_array[1] = i->sectors;
1587 info_array[2] = i->cylinders;
1588 }else{/* 3.4 BIOS (and up?) */1589 /* This algorithm was provided by Future Domain (much thanks!). */1590
1591 sizes[0] = 0; /* zero bytes out */1592 sizes[1] = 512; /* one sector in */1593 memcpy( data, do_read, sizeof( do_read ) );
1594 retcode = kernel_scsi_ioctl( disk->device,
1595 SCSI_IOCTL_SEND_COMMAND,
1596 (void *)buf );
1597 if (!retcode/* SCSI command ok */1598 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1599 && data[0x1c2]) {/* Partition type */1600
1601 /* The partition table layout is as follows:1602
1603 Start: 0x1b3h1604 Offset: 0 = partition status1605 1 = starting head1606 2 = starting sector and cylinder (word, encoded)1607 4 = partition type1608 5 = ending head1609 6 = ending sector and cylinder (word, encoded)1610 8 = starting absolute sector (double word)1611 c = number of sectors (double word)1612 Signature: 0x1fe = 0x55aa1613
1614 So, this algorithm assumes:1615 1) the first partition table is in use,1616 2) the data in the first entry is correct, and1617 3) partitions never divide cylinders1618
1619 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1620 as well as for Linux. Note also, that Linux doesn't pay any1621 attention to the fields that are used by this algorithm -- it1622 only uses the absolute sector data. Recent versions of Linux's1623 fdisk(1) will fill this data in correctly, and forthcoming1624 versions will check for consistency.1625
1626 Checking for a non-zero partition type is not part of the1627 Future Domain algorithm, but it seemed to be a reasonable thing1628 to do, especially in the Linux and BSD worlds. */1629
1630 info_array[0] = data[0x1c3] + 1; /* heads */1631 info_array[1] = data[0x1c4] & 0x3f; /* sectors */1632 }else{1633
1634 /* Note that this new method guarantees that there will always be1635 less than 1024 cylinders on a platter. This is good for drives1636 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */1637
1638 if ((unsignedint)size >= 0x7e0000U) {1639 info_array[0] = 0xff; /* heads = 255 */1640 info_array[1] = 0x3f; /* sectors = 63 */1641 }elseif ((unsignedint)size >= 0x200000U) {1642 info_array[0] = 0x80; /* heads = 128 */1643 info_array[1] = 0x3f; /* sectors = 63 */1644 }else{1645 info_array[0] = 0x40; /* heads = 64 */1646 info_array[1] = 0x20; /* sectors = 32 */1647 }1648 }1649 /* For both methods, compute the cylinders */1650 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
1651 }1652
1653 return 0;
1654 }