1 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver 2 * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu 3 * Revised: Thu Apr 7 20:30:09 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.16 1994/04/08 00:30:15 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 and TMC-1650/1670 SCSI host adapters. The 1650 and 1670 have a 25-pin 29 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. 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 35 chip. More recently, boards are being produced with the TMC-18C50 chip. 36 The latest and greatest board may not work with this driver. If you have 37 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, and 3.4. 42 The following chips are supported: TMC-1800, TMC-18C50. 43 Reports suggest that the driver will also work with the TMC-18C30 chip. 44 The support for the version 3.4 BIOS is new, as of March 1994, and may not 45 be stable. 46
47 If you have a TMC-8xx or TMC-9xx board, then this is not the driver for 48 your board. Please refer to the Seagate driver for more information and 49 possible support. 50
51 52
53 REFERENCES USED: 54
55 "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, 56 1990. 57
58 "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain 59 Corporation, January 1992. 60
61 "LXT SCSI Products: Specifications and OEM Technical Manual (Revision 62 B/September 1991)", Maxtor Corporation, 1991. 63
64 "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. 65
66 "Draft Proposed American National Standard: Small Computer System 67 Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, 68 revision 10h, October 17, 1991) 69
70 Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric 71 Youngdale (ericy@cais.com), 1992. 72
73 Private communication, Tuong Le (Future Domain Engineering department), 74 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and 75 TMC-18C30 detection.) 76
77 Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page 78 60 (2.39: Disk Partition Table Layout). 79
80 "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page 81 6-1. 82
83
84 85 NOTES ON REFERENCES: 86
87 The Maxtor manuals were free. Maxtor telephone technical support is 88 great! 89
90 The Future Domain manuals were $25 and $35. They document the chip, not 91 the TMC-16x0 boards, so some information I had to guess at. In 1992, 92 Future Domain sold DOS BIOS source for $250 and the UN*X driver source was 93 $750, but these required a non-disclosure agreement, so even if I could 94 have afforded them, they would *not* have been useful for writing this 95 publically distributable driver. Future Domain technical support has 96 provided some information on the phone and have sent a few useful FAXs. 97 They have been much more helpful since they started to recognize that the 98 word "Linux" refers to an operating system :-). 99
100 101
102 ALPHA TESTERS: 103
104 There are many other alpha testers that come and go as the driver 105 develops. The people listed here were most helpful in times of greatest 106 need (mostly early on -- I've probably left out a few worthy people in 107 more recent times): 108
109 Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken 110 Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari 111 Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad 112 Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com). 113
114 Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me 115 his 18C50-based card for debugging. He is the sole reason that this 116 driver works with the 18C50 chip. 117
118 Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for 119 the version 3.4 BIOS. 120
121 All of the alpha testers deserve much thanks. 122 123
124 125 NOTES ON USER DEFINABLE OPTIONS: 126
127 DEBUG: This turns on the printing of various debug informaiton. 128
129 ENABLE_PARITY: This turns on SCSI parity checking. With the current 130 driver, all attached devices must support SCSI parity. If none of your 131 devices support parity, then you can probably get the driver to work by 132 turning this option off. I have no way of testing this, however. 133
134 FIFO_COUNT: The host adapter has an 8K cache. When this many 512 byte 135 blocks are filled by the SCSI device, an interrupt will be raised. 136 Therefore, this could be as low as 0, or as high as 16. Note, however, 137 that values which are too high or too low seem to prevent any interrupts 138 from occuring, and thereby lock up the machine. I have found that 2 is a 139 good number, but throughput may be increased by changing this value to 140 values which are close to 2. Please let me know if you try any different 141 values. 142
143 DO_DETECT: This activates some old scan code which was needed before the 144 high level drivers got fixed. If you are having toruble with the driver, 145 turning this on should not hurt, and might help. Please let me know if 146 this is the case, since this code will be removed from future drivers. 147
148 RESELECTION: This is no longer an option, since I gave up trying to 149 implement it in version 4.x of this driver. It did not improve 150 performance at all and made the driver unstable (because I never found one 151 of the two race conditions which were introduced by multiple outstanding 152 commands). The instability seems a very high price to pay just so that 153 you don't have to wait for the tape to rewind. When I have time, I will 154 work on this again. In the interim, if anyone wants to work on the code, 155 I can give them my latest version. 156
157 **************************************************************************/ 158
159 #include <linux/sched.h>
160 #include <asm/io.h>
161 #include "../block/blk.h"
162 #include "scsi.h"
163 #include "hosts.h"
164 #include "fdomain.h"
165 #include <asm/system.h>
166 #include <linux/errno.h>
167 #include <linux/string.h>
168 #include <linux/ioport.h>
169
170 #defineVERSION "$Revision: 5.16 $"
171
172 /* START OF USER DEFINABLE OPTIONS */ 173
174 #defineDEBUG 1 /* Enable debugging output */ 175 #defineENABLE_PARITY 1 /* Enable SCSI Parity */ 176 #defineFIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ 177 #defineDO_DETECT 0 /* Do device detection here (see scsi.c) */ 178
179 /* END OF USER DEFINABLE OPTIONS */ 180
181 #ifDEBUG 182 #defineEVERY_ACCESS 0 /* Write a line on every scsi access */ 183 #defineERRORS_ONLY 1 /* Only write a line if there is an error */ 184 #defineDEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ 185 #defineDEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 186 #defineDEBUG_ABORT 1 /* Debug abort() routine */ 187 #defineDEBUG_RESET 1 /* Debug reset() routine */ 188 #defineDEBUG_RACE 1 /* Debug interrupt-driven race condition */ 189 #else 190 #defineEVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 191 #defineERRORS_ONLY 0
192 #defineDEBUG_DETECT 0
193 #defineDEBUG_MESSAGES 0
194 #defineDEBUG_ABORT 0
195 #defineDEBUG_RESET 0
196 #defineDEBUG_RACE 0
197 #endif 198
199 /* Errors are reported on the line, so we don't need to report them again */ 200 #ifEVERY_ACCESS 201 #undefERRORS_ONLY 202 #defineERRORS_ONLY 0
203 #endif 204
205 #ifENABLE_PARITY 206 #definePARITY_MASK 0x08
207 #else 208 #definePARITY_MASK 0x00
209 #endif 210
211 enumchip_type{ 212 unknown = 0x00,
213 tmc1800 = 0x01,
214 tmc18c50 = 0x02,
215 tmc18c30 = 0x03,
216 };
217
218 enum{ 219 in_arbitration = 0x02,
220 in_selection = 0x04,
221 in_other = 0x08,
222 disconnect = 0x10,
223 aborted = 0x20,
224 sent_ident = 0x40,
225 };
226
227 enum in_port_type { 228 Read_SCSI_Data = 0,
229 SCSI_Status = 1,
230 TMC_Status = 2,
231 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 232 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 233 LSB_ID_Code = 5,
234 MSB_ID_Code = 6,
235 Read_Loopback = 7,
236 SCSI_Data_NoACK = 8,
237 Interrupt_Status = 9,
238 Configuration1 = 10,
239 Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 240 Read_FIFO = 12,
241 FIFO_Data_Count = 14
242 };
243
244 enum out_port_type { 245 Write_SCSI_Data = 0,
246 SCSI_Cntl = 1,
247 Interrupt_Cntl = 2,
248 SCSI_Mode_Cntl = 3,
249 TMC_Cntl = 4,
250 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 251 Write_Loopback = 7,
252 IO_Control = 11, /* tmc18c30 only */ 253 Write_FIFO = 12
254 };
255
256 staticintport_base = 0;
257 staticvoid *bios_base = NULL;
258 staticintbios_major = 0;
259 staticintbios_minor = 0;
260 staticintinterrupt_level = 0;
261 staticintthis_host = 0;
262 staticvolatileintin_command = 0;
263 staticScsi_Cmnd *current_SC = NULL;
264 staticenumchip_typechip = unknown;
265 staticintadapter_mask = 0x40;
266 #ifDEBUG_RACE 267 staticvolatileintin_interrupt_flag = 0;
268 #endif 269
270 staticintSCSI_Mode_Cntl_port;
271 staticintFIFO_Data_Count_port;
272 staticintInterrupt_Cntl_port;
273 staticintInterrupt_Status_port;
274 staticintRead_FIFO_port;
275 staticintRead_SCSI_Data_port;
276 staticintSCSI_Cntl_port;
277 staticintSCSI_Data_NoACK_port;
278 staticintSCSI_Status_port;
279 staticintTMC_Cntl_port;
280 staticintTMC_Status_port;
281 staticintWrite_FIFO_port;
282 staticintWrite_SCSI_Data_port;
283
284 staticintFIFO_Size = 0x2000; /* 8k FIFO for 285 pre-tmc18c30 chips */ 286
287 externvoidfdomain_16x0_intr( intunused );
288
289 staticvoid *addresses[] = { 290 (void *)0xc8000,
291 (void *)0xca000,
292 (void *)0xce000,
293 (void *)0xde000 };
294 #defineADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
295
296 staticunsignedshortports[] = { 0x140, 0x150, 0x160, 0x170 };
297 #definePORT_COUNT (sizeof( ports ) / sizeof( unsignedshort ))
298
299 staticunsignedshortints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
300
301 /* 302
303 READ THIS BEFORE YOU ADD A SIGNATURE! 304
305 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! 306
307 READ EVERY WORD, ESPECIALLY THE WORD *NOT* 308
309 This driver works *ONLY* for Future Domain cards using the TMC-1800, 310 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, 311 and 1680. 312
313 The following BIOS signature signatures are for boards which do *NOT* 314 work with this driver (these TMC-8xx and TMC-9xx boards may work with the 315 Seagate driver): 316
317 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 318 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 319 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 320 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 321 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 322 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 323 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 324
325 */ 326
327 structsignature{ 328 char *signature;
329 intsig_offset;
330 intsig_length;
331 intmajor_bios_version;
332 intminor_bios_version;
333 }signatures[] = { 334 /* 1 2 3 4 5 6 */ 335 /* 123456789012345678901234567890123456789012345678901234567890 */ 336 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0 },
337 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0 },
338 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0 },
339 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2 },
340 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4 },
341 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1 },
342
343 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE 344 Also, fix the disk geometry code for your signature and send your 345 changes for faith@cs.unc.edu. Above all, do *NOT* change any old 346 signatures! 347
348 Note that the last line will match a "generic" 18XX bios. Because 349 Future Domain has changed the host SCSI ID and/or the location of the 350 geometry information in the on-board RAM area for each of the first 351 three BIOS's, it is still important to enter a fully qualified 352 signature in the table for any new BIOS's (after the host SCSI ID and 353 geometry location are verified.) */ 354 };
355
356 #defineSIGNATURE_COUNT (sizeof( signatures ) / sizeof( structsignature ))
357
358 staticvoidprint_banner( void )
359 { 360 printk( "%s", fdomain_16x0_info() );
361 printk( "Future Domain: BIOS version %d.%d, %s\n",
362 bios_major, bios_minor,
363 chip == tmc1800 ? "TMC-1800"
364 : (chip == tmc18c50 ? "TMC-18C50"
365 : (chip == tmc18c30 ? "TMC-18C30" : "Unknown")) );
366
367 if (interrupt_level) { 368 printk( "Future Domain: BIOS at %x; port base at %x; using IRQ %d\n",
369 (unsigned)bios_base, port_base, interrupt_level );
370 }else{ 371 printk( "Future Domain: BIOS at %x; port base at %x; *NO* IRQ\n",
372 (unsigned)bios_base, port_base );
373 } 374 } 375
376 staticvoiddo_pause( unsignedamount ) /* Pause for amount*10 milliseconds *//* */ 377 { 378 unsignedlongthe_time = jiffies + amount; /* 0.01 seconds per jiffy */ 379
380 while (jiffies < the_time);
381 } 382
383 inlinestaticvoidfdomain_make_bus_idle( void )
/* */ 384 { 385 outb( 0, SCSI_Cntl_port );
386 outb( 0, SCSI_Mode_Cntl_port );
387 if (chip == tmc18c50 || chip == tmc18c30)
388 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ 389 else 390 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
391 } 392
393 staticintfdomain_is_valid_port( intport )
/* */ 394 { 395 intoptions;
396
397 #ifDEBUG_DETECT 398 printk( " (%x%x),",
399 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
400 #endif 401
402 /* The MCA ID is a unique id for each MCA compatible board. We 403 are using ISA boards, but Future Domain provides the MCA ID 404 anyway. We can use this ID to ensure that this is a Future 405 Domain TMC-1660/TMC-1680. 406 */ 407
408 if (inb( port + LSB_ID_Code ) != 0xe9) {/* test for 0x6127 id */ 409 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
410 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
411 chip = tmc1800;
412 }else{/* test for 0xe960 id */ 413 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
414 chip = tmc18c50;
415
416 #if 0
417
418 /* Try to toggle 32-bit mode. This only 419 works on an 18c30 chip. (User reports 420 say that this doesn't work at all, so 421 we'll use the other method.) */ 422
423 outb( 0x80, port + IO_Control );
424 if (inb( port + Configuration2 ) & 0x80 == 0x80) { 425 outb( 0x00, port + IO_Control );
426 if (inb( port + Configuration2 ) & 0x80 == 0x00) { 427 chip = tmc18c30;
428 FIFO_Size = 0x800; /* 2k FIFO */ 429 } 430 } 431 #else 432
433 /* That should have worked, but appears to 434 have problems. Lets assume it is an 435 18c30 if the RAM is disabled. */ 436
437 if (inb( port + Configuration2 ) & 0x02) { 438 chip = tmc18c30;
439 FIFO_Size = 0x800; /* 2k FIFO */ 440 } 441 #endif 442 /* If that failed, we are an 18c50. */ 443 } 444
445 /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board. 446 Now, check to be sure the bios_base matches these ports. If someone 447 was unlucky enough to have purchased more than one Future Domain 448 board, then they will have to modify this code, as we only detect one 449 board here. [The one with the lowest bios_base.] */ 450
451 options = inb( port + Configuration1 );
452
453 #ifDEBUG_DETECT 454 printk( " Options = %x\n", options );
455 #endif 456
457 /* Check for board with lowest bios_base -- 458 this isn't valid for the 18c30, so just 459 assume we have the right board. */ 460
461 if (chip != tmc18c30 && addresses[ (options & 0xc0) >> 6 ] != bios_base)
462 return 0;
463
464 interrupt_level = ints[ (options & 0x0e) >> 1 ];
465
466 return 1;
467 } 468
469 staticintfdomain_test_loopback( void )
/* */ 470 { 471 inti;
472 intresult;
473
474 for (i = 0; i < 255; i++) { 475 outb( i, port_base + Write_Loopback );
476 result = inb( port_base + Read_Loopback );
477 if (i != result)
478 return 1;
479 } 480 return 0;
481 } 482
483 intfdomain_16x0_detect( inthostnum )
/* */ 484 { 485 inti, j;
486 intflag = 0;
487 structsigactionsa;
488 intretcode;
489 #ifDO_DETECT 490 constintbuflen = 255;
491 Scsi_CmndSCinit;
492 unsignedchardo_inquiry[] = {INQUIRY, 0, 0, 0, buflen, 0 };
493 unsignedchardo_request_sense[] = {REQUEST_SENSE, 0, 0, 0, buflen, 0 };
494 unsignedchardo_read_capacity[] = {READ_CAPACITY,
495 0, 0, 0, 0, 0, 0, 0, 0, 0 };
496 unsignedcharbuf[buflen];
497 #endif 498
499 #ifDEBUG_DETECT 500 printk( "fdomain_16x0_detect()," );
501 #endif 502
503 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { 504 #ifDEBUG_DETECT 505 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
506 #endif 507 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { 508 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
509 signatures[j].signature, signatures[j].sig_length )) { 510 bios_major = signatures[j].major_bios_version;
511 bios_minor = signatures[j].minor_bios_version;
512 bios_base = addresses[i];
513 } 514 } 515 } 516
517 if (!bios_base) { 518 #ifDEBUG_DETECT 519 printk( " FAILED: NO BIOS\n" );
520 #endif 521 return 0;
522 } 523
524 if (bios_major == 2) { 525 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. 526 Assuming the ROM is enabled (otherwise we wouldn't have been 527 able to read the ROM signature :-), then the ROM sets up the 528 RAM area with some magic numbers, such as a list of port 529 base addresses and a list of the disk "geometry" reported to 530 DOS (this geometry has nothing to do with physical geometry). 531 */ 532
533 port_base = *((char *)bios_base + 0x1fcc)
534 + (*((char *)bios_base + 0x1fcd) << 8);
535
536 #ifDEBUG_DETECT 537 printk( " %x,", port_base );
538 #endif 539
540 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { 541 if (port_base == ports[i])
542 ++flag;
543 } 544
545 if (flag)
546 flag = fdomain_is_valid_port( port_base );
547 } 548
549 if (!flag) {/* Cannot get port base from BIOS RAM */ 550
551 /* This is a bad sign. It usually means that someone patched the 552 BIOS signature list (the signatures variable) to contain a BIOS 553 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. It 554 also means that we don't have a Version 2.0 BIOS :-) 555 */ 556
557 #ifDEBUG_DETECT 558 if (bios_major != 2) printk( " RAM FAILED, " );
559 #endif 560
561 /* Anyway, the alternative to finding the address in the RAM is 562 to just search through every possible port address for one 563 that is attached to the Future Domain card. Don't panic, 564 though, about reading all these random port addresses--there 565 are rumors that the Future Domain BIOS does something very 566 similar. 567
568 Do not, however, check ports which the kernel knows are being used 569 by another driver. 570 */ 571
572 for (i = 0; !flag && i < PORT_COUNT; i++) { 573 port_base = ports[i];
574 if (check_region( port_base, 0x10 )) { 575 #ifDEBUG_DETECT 576 printk( " (%x inuse),", port_base );
577 #endif 578 continue;
579 } 580 #ifDEBUG_DETECT 581 printk( " %x,", port_base );
582 #endif 583 flag = fdomain_is_valid_port( port_base );
584 } 585 } 586
587 if (!flag) { 588 #ifDEBUG_DETECT 589 printk( " FAILED: NO PORT\n" );
590 #endif 591 return 0; /* Cannot find valid set of ports */ 592 } 593
594 print_banner();
595
596 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
597 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
598 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
599 Interrupt_Status_port = port_base + Interrupt_Status;
600 Read_FIFO_port = port_base + Read_FIFO;
601 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
602 SCSI_Cntl_port = port_base + SCSI_Cntl;
603 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
604 SCSI_Status_port = port_base + SCSI_Status;
605 TMC_Cntl_port = port_base + TMC_Cntl;
606 TMC_Status_port = port_base + TMC_Status;
607 Write_FIFO_port = port_base + Write_FIFO;
608 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
609
610 fdomain_16x0_reset( NULL );
611
612 if (fdomain_test_loopback()) { 613 #ifDEBUG_DETECT 614 printk( "Future Domain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
615 #endif 616 return 0;
617 } 618
619 this_host = hostnum;
620
621 /* Log IRQ with kernel */ 622
623 if (!interrupt_level) { 624 panic( "Future Domain: *NO* interrupt level selected!\n" );
625 }else{ 626 /* Register the IRQ with the kernel */ 627
628 sa.sa_handler = fdomain_16x0_intr;
629 sa.sa_flags = SA_INTERRUPT;
630 sa.sa_mask = 0;
631 sa.sa_restorer = NULL;
632
633 retcode = irqaction( interrupt_level, &sa );
634
635 if (retcode < 0) { 636 if (retcode == -EINVAL) { 637 printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
638 printk( " This shouldn't happen!\n" );
639 printk( " Send mail to faith@cs.unc.edu\n" );
640 }elseif (retcode == -EBUSY) { 641 printk( "Future Domain: IRQ %d is already in use!\n",
642 interrupt_level );
643 printk( " Please use another IRQ!\n" );
644 }else{ 645 printk( "Future Domain: Error getting IRQ %d\n", interrupt_level );
646 printk( " This shouldn't happen!\n" );
647 printk( " Send mail to faith@cs.unc.edu\n" );
648 } 649 panic( "Future Domain: Driver requires interruptions\n" );
650 }else{ 651 printk( "Future Domain: IRQ %d requested from kernel\n",
652 interrupt_level );
653 } 654 } 655
656 /* Log I/O ports with kernel */ 657
658 snarf_region( port_base, 0x10 );
659
660 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { 661 adapter_mask = 0x80;
662 scsi_hosts[this_host].this_id = 7;
663 } 664
665 #ifDO_DETECT 666
667 /* These routines are here because of the way the SCSI bus behaves after 668 a reset. This appropriate behavior was not handled correctly by the 669 higher level SCSI routines when I first wrote this driver. Now, 670 however, correct scan routines are part of scsi.c and these routines 671 are no longer needed. However, this code is still good for 672 debugging. */ 673
674 SCinit.request_buffer = SCinit.buffer = buf;
675 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
676 SCinit.use_sg = 0;
677 SCinit.lun = 0;
678
679 printk( "Future Domain detection routine scanning for devices:\n" );
680 for (i = 0; i < 8; i++) { 681 SCinit.target = i;
682 if (i == scsi_hosts[this_host].this_id) /* Skip host adapter */ 683 continue;
684 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
685 retcode = fdomain_16x0_command(&SCinit);
686 if (!retcode) { 687 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
688 retcode = fdomain_16x0_command(&SCinit);
689 if (!retcode) { 690 printk( " SCSI ID %d: ", i );
691 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
692 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
693 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
694 retcode = fdomain_16x0_command(&SCinit);
695 if (!retcode) { 696 unsignedlongblocks, size, capacity;
697
698 blocks = (buf[0] << 24) | (buf[1] << 16)
699 | (buf[2] << 8) | buf[3];
700 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
701 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
702
703 printk( "%lu MB (%lu byte blocks)",
704 ((capacity + 5L) / 10L), size );
705 }else{ 706 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
707 retcode = fdomain_16x0_command(&SCinit);
708 } 709 printk ("\n" );
710 }else{ 711 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
712 retcode = fdomain_16x0_command(&SCinit);
713 } 714 } 715 } 716 #endif 717
718 return 1;
719 } 720
721 constchar *fdomain_16x0_info(void)
/* */ 722 { 723 staticcharbuffer[80];
724 char *pt;
725
726 strcpy( buffer, "Future Domain: TMC-16x0 SCSI driver, version" );
727 if (strchr( VERSION, ':')) {/* Assume VERSION is an RCS Revision string */ 728 strcat( buffer, strchr( VERSION, ':' ) + 1 );
729 pt = strrchr( buffer, '$') - 1;
730 if (!pt) /* Stripped RCS Revision string? */ 731 pt = buffer + strlen( buffer ) - 1;
732 if (*pt != ' ')
733 ++pt;
734 *pt++ = '\n';
735 *pt = '\0';
736 }else{/* Assume VERSION is a number */ 737 strcat( buffer, " " VERSION "\n" );
738 } 739
740 returnbuffer;
741 } 742
743 #if 0
744 staticint fdomain_arbitrate( void )
/* */ 745 { 746 intstatus = 0;
747 unsignedlongtimeout;
748
749 #ifEVERY_ACCESS 750 printk( "fdomain_arbitrate()\n" );
751 #endif 752
753 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ 754 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ 755 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ 756
757 timeout = jiffies + 50; /* 500 mS */ 758 while (jiffies < timeout) { 759 status = inb( TMC_Status_port ); /* Read adapter status */ 760 if (status & 0x02) /* Arbitration complete */ 761 return 0;
762 } 763
764 /* Make bus idle */ 765 fdomain_make_bus_idle();
766
767 #ifEVERY_ACCESS 768 printk( "Arbitration failed, status = %x\n", status );
769 #endif 770 #ifERRORS_ONLY 771 printk( "Future Domain: Arbitration failed, status = %x\n", status );
772 #endif 773 return 1;
774 } 775 #endif 776
777 staticintfdomain_select( inttarget )
/* */ 778 { 779 intstatus;
780 unsignedlongtimeout;
781
782
783 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ 784 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
785
786 /* Stop arbitration and enable parity */ 787 outb( PARITY_MASK, TMC_Cntl_port );
788
789 #if 0
790 timeout = jiffies + 25; /* 250mS */ 791 #else 792 timeout = jiffies + 35; /* 350mS -- because of timeouts */ 793 #endif 794 while (jiffies < timeout) { 795 status = inb( SCSI_Status_port ); /* Read adapter status */ 796 if (status & 1) {/* Busy asserted */ 797 /* Enable SCSI Bus (on error, should make bus idle with 0) */ 798 outb( 0x80, SCSI_Cntl_port );
799 return 0;
800 } 801 } 802 /* Make bus idle */ 803 fdomain_make_bus_idle();
804 #ifEVERY_ACCESS 805 if (!target) printk( "Selection failed\n" );
806 #endif 807 #ifERRORS_ONLY 808 if (!target) printk( "Future Domain: Selection failed\n" );
809 #endif 810 return 1;
811 } 812
813 voidmy_done( interror )
/* */ 814 { 815 if (in_command) { 816 in_command = 0;
817 outb( 0x00, Interrupt_Cntl_port );
818 fdomain_make_bus_idle();
819 current_SC->result = error;
820 if (current_SC->scsi_done)
821 current_SC->scsi_done( current_SC );
822 elsepanic( "Future Domain: current_SC->scsi_done() == NULL" );
823 }else{ 824 panic( "Future Domain: my_done() called outside of command\n" );
825 } 826 #ifDEBUG_RACE 827 in_interrupt_flag = 0;
828 #endif 829 } 830
831 voidfdomain_16x0_intr( intunused )
/* */ 832 { 833 intstatus;
834 intdone = 0;
835 unsigneddata_count;
836
837 sti();
838
839 outb( 0x00, Interrupt_Cntl_port );
840
841 /* We usually have one spurious interrupt after each command. Ignore it. */ 842 if (!in_command || !current_SC) {/* Spurious interrupt */ 843 #ifEVERY_ACCESS 844 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
845 in_command, current_SC );
846 #endif 847 return;
848 } 849
850 /* Abort calls my_done, so we do nothing here. */ 851 if (current_SC->SCp.phase & aborted) { 852 #ifDEBUG_ABORT 853 printk( "Interrupt after abort, ignoring\n" );
854 #endif 855 /* 856 return; */ 857 } 858
859 #ifDEBUG_RACE 860 ++in_interrupt_flag;
861 #endif 862
863 if (current_SC->SCp.phase & in_arbitration) { 864 status = inb( TMC_Status_port ); /* Read adapter status */ 865 if (!(status & 0x02)) { 866 #ifEVERY_ACCESS 867 printk( " AFAIL " );
868 #endif 869 my_done( DID_BUS_BUSY << 16 );
870 return;
871 } 872 current_SC->SCp.phase = in_selection;
873
874 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
875
876 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ 877 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
878
879 /* Stop arbitration and enable parity */ 880 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
881 #ifDEBUG_RACE 882 in_interrupt_flag = 0;
883 #endif 884 return;
885 }elseif (current_SC->SCp.phase & in_selection) { 886 status = inb( SCSI_Status_port );
887 if (!(status & 0x01)) { 888 /* Try again, for slow devices */ 889 if (fdomain_select( current_SC->target )) { 890 #ifEVERY_ACCESS 891 printk( " SFAIL " );
892 #endif 893 my_done( DID_NO_CONNECT << 16 );
894 return;
895 }else{ 896 #ifEVERY_ACCESS 897 printk( " AltSel " );
898 #endif 899 /* Stop arbitration and enable parity */ 900 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
901 } 902 } 903 current_SC->SCp.phase = in_other;
904 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
905 outb( 0x80, SCSI_Cntl_port );
906 #ifDEBUG_RACE 907 in_interrupt_flag = 0;
908 #endif 909 return;
910 } 911
912 /* current_SC->SCp.phase == in_other: this is the body of the routine */ 913
914 status = inb( SCSI_Status_port );
915
916 if (status & 0x10) {/* REQ */ 917
918 switch (status & 0x0e) { 919
920 case 0x08: /* COMMAND OUT */ 921 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
922 Write_SCSI_Data_port );
923 #ifEVERY_ACCESS 924 printk( "CMD = %x,",
925 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
926 #endif 927 break;
928 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ 929 if (chip != tmc1800 && !current_SC->SCp.have_data_in) { 930 current_SC->SCp.have_data_in = -1;
931 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
932 } 933 break;
934 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ 935 if (chip != tmc1800 && !current_SC->SCp.have_data_in) { 936 current_SC->SCp.have_data_in = 1;
937 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
938 } 939 break;
940 case 0x0c: /* STATUS IN */ 941 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
942 #ifEVERY_ACCESS 943 printk( "Status = %x, ", current_SC->SCp.Status );
944 #endif 945 #ifERRORS_ONLY 946 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) { 947 printk( "Future Domain: target = %d, command = %x, "
948 "Status = %x\n",
949 current_SC->target, current_SC->cmnd[0],
950 current_SC->SCp.Status );
951 } 952 #endif 953 break;
954 case 0x0a: /* MESSAGE OUT */ 955 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */ 956 break;
957 case 0x0e: /* MESSAGE IN */ 958 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
959 #ifEVERY_ACCESS 960 printk( "Message = %x, ", current_SC->SCp.Message );
961 #endif 962 if (!current_SC->SCp.Message) ++done;
963 #ifDEBUG_MESSAGES || EVERY_ACCESS 964 if (current_SC->SCp.Message) { 965 printk( "Future Domain: Message = %x\n",
966 current_SC->SCp.Message );
967 } 968 #endif 969 break;
970 } 971 } 972
973 if (chip == tmc1800 974 && !current_SC->SCp.have_data_in 975 && (current_SC->SCp.sent_command 976 >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) { 977 /* We have to get the FIFO direction 978 correct, so I've made a table based 979 on the SCSI Standard of which commands 980 appear to require a DATA OUT phase. 981 */ 982 /* 983 p. 94: Command for all device types 984 CHANGE DEFINITION 40 DATA OUT 985 COMPARE 39 DATA OUT 986 COPY 18 DATA OUT 987 COPY AND VERIFY 3a DATA OUT 988 INQUIRY 12 989 LOG SELECT 4c DATA OUT 990 LOG SENSE 4d 991 MODE SELECT (6) 15 DATA OUT 992 MODE SELECT (10) 55 DATA OUT 993 MODE SENSE (6) 1a 994 MODE SENSE (10) 5a 995 READ BUFFER 3c 996 RECEIVE DIAGNOSTIC RESULTS 1c 997 REQUEST SENSE 03 998 SEND DIAGNOSTIC 1d DATA OUT 999 TEST UNIT READY 001000 WRITE BUFFER 3b DATA OUT1001
1002 p.178: Commands for direct-access devices (not listed on p. 94)1003 FORMAT UNIT 04 DATA OUT1004 LOCK-UNLOCK CACHE 361005 PRE-FETCH 341006 PREVENT-ALLOW MEDIUM REMOVAL 1e1007 READ (6)/RECEIVE 081008 READ (10) 3c1009 READ CAPACITY 251010 READ DEFECT DATA (10) 371011 READ LONG 3e1012 REASSIGN BLOCKS 07 DATA OUT1013 RELEASE 171014 RESERVE 16 DATA OUT1015 REZERO UNIT/REWIND 011016 SEARCH DATA EQUAL (10) 31 DATA OUT1017 SEARCH DATA HIGH (10) 30 DATA OUT1018 SEARCH DATA LOW (10) 32 DATA OUT1019 SEEK (6) 0b1020 SEEK (10) 2b1021 SET LIMITS (10) 331022 START STOP UNIT 1b1023 SYNCHRONIZE CACHE 351024 VERIFY (10) 2f1025 WRITE (6)/PRINT/SEND 0a DATA OUT1026 WRITE (10)/SEND 2a DATA OUT1027 WRITE AND VERIFY (10) 2e DATA OUT1028 WRITE LONG 3f DATA OUT1029 WRITE SAME 41 DATA OUT ?1030
1031 p. 261: Commands for sequential-access devices (not previously listed)1032 ERASE 191033 LOAD UNLOAD 1b1034 LOCATE 2b1035 READ BLOCK LIMITS 051036 READ POSITION 341037 READ REVERSE 0f1038 RECOVER BUFFERED DATA 141039 SPACE 111040 WRITE FILEMARKS 10 ?1041
1042 p. 298: Commands for printer devices (not previously listed)1043 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****1044 SLEW AND PRINT 0b DATA OUT -- same as seek1045 STOP PRINT 1b1046 SYNCHRONIZE BUFFER 101047
1048 p. 315: Commands for processor devices (not previously listed)1049 1050 p. 321: Commands for write-once devices (not previously listed)1051 MEDIUM SCAN 381052 READ (12) a81053 SEARCH DATA EQUAL (12) b1 DATA OUT1054 SEARCH DATA HIGH (12) b0 DATA OUT1055 SEARCH DATA LOW (12) b2 DATA OUT1056 SET LIMITS (12) b31057 VERIFY (12) af1058 WRITE (12) aa DATA OUT1059 WRITE AND VERIFY (12) ae DATA OUT1060
1061 p. 332: Commands for CD-ROM devices (not previously listed)1062 PAUSE/RESUME 4b1063 PLAY AUDIO (10) 451064 PLAY AUDIO (12) a51065 PLAY AUDIO MSF 471066 PLAY TRACK RELATIVE (10) 491067 PLAY TRACK RELATIVE (12) a91068 READ HEADER 441069 READ SUB-CHANNEL 421070 READ TOC 431071
1072 p. 370: Commands for scanner devices (not previously listed)1073 GET DATA BUFFER STATUS 341074 GET WINDOW 251075 OBJECT POSITION 311076 SCAN 1b1077 SET WINDOW 24 DATA OUT1078
1079 p. 391: Commands for optical memory devices (not listed)1080 ERASE (10) 2c1081 ERASE (12) ac1082 MEDIUM SCAN 38 DATA OUT1083 READ DEFECT DATA (12) b71084 READ GENERATION 291085 READ UPDATED BLOCK 2d1086 UPDATE BLOCK 3d DATA OUT1087
1088 p. 419: Commands for medium changer devices (not listed)1089 EXCHANGE MEDIUM 461090 INITIALIZE ELEMENT STATUS 071091 MOVE MEDIUM a51092 POSITION TO ELEMENT 2b1093 READ ELEMENT STATUS b81094 REQUEST VOL. ELEMENT ADDRESS b51095 SEND VOLUME TAG b6 DATA OUT1096
1097 p. 454: Commands for communications devices (not listed previously)1098 GET MESSAGE (6) 081099 GET MESSAGE (10) 281100 GET MESSAGE (12) a81101 */1102
1103 switch (current_SC->cmnd[0]) {1104 caseCHANGE_DEFINITION: caseCOMPARE: caseCOPY:
1105 caseCOPY_VERIFY: caseLOG_SELECT: caseMODE_SELECT:
1106 caseMODE_SELECT_10: caseSEND_DIAGNOSTIC: caseWRITE_BUFFER:
1107
1108 caseFORMAT_UNIT: caseREASSIGN_BLOCKS: caseRESERVE:
1109 caseSEARCH_EQUAL: caseSEARCH_HIGH: caseSEARCH_LOW:
1110 caseWRITE_6: caseWRITE_10: caseWRITE_VERIFY:
1111 case 0x3f: case 0x41:
1112
1113 case 0xb1: case 0xb0: case 0xb2:
1114 case 0xaa: case 0xae:
1115
1116 case 0x24:
1117
1118 case 0x38: case 0x3d:
1119
1120 case 0xb6:
1121
1122 case 0xea: /* alternate number for WRITE LONG */1123
1124 current_SC->SCp.have_data_in = -1;
1125 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1126 break;
1127
1128 case 0x00:
1129 default:
1130
1131 current_SC->SCp.have_data_in = 1;
1132 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1133 break;
1134 }1135 }1136
1137 if (current_SC->SCp.have_data_in == -1) {/* DATA OUT */1138 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {1139 #ifEVERY_ACCESS1140 printk( "DC=%d, ", data_count ) ;
1141 #endif1142 if (data_count > current_SC->SCp.this_residual)
1143 data_count = current_SC->SCp.this_residual;
1144 if (data_count > 0) {1145 #ifEVERY_ACCESS1146 printk( "%d OUT, ", data_count );
1147 #endif1148 if (data_count == 1) {1149 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1150 --current_SC->SCp.this_residual;
1151 }else{1152 data_count >>= 1;
1153 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1154 current_SC->SCp.ptr += 2 * data_count;
1155 current_SC->SCp.this_residual -= 2 * data_count;
1156 }1157 }1158 if (!current_SC->SCp.this_residual) {1159 if (current_SC->SCp.buffers_residual) {1160 --current_SC->SCp.buffers_residual;
1161 ++current_SC->SCp.buffer;
1162 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1163 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1164 }else1165 break;
1166 }1167 }1168 }1169
1170 if (current_SC->SCp.have_data_in == 1) {/* DATA IN */1171 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {1172 #ifEVERY_ACCESS1173 printk( "DC=%d, ", data_count );
1174 #endif1175 if (data_count > current_SC->SCp.this_residual)
1176 data_count = current_SC->SCp.this_residual;
1177 if (data_count) {1178 #ifEVERY_ACCESS1179 printk( "%d IN, ", data_count );
1180 #endif1181 if (data_count == 1) {1182 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1183 --current_SC->SCp.this_residual;
1184 }else{1185 data_count >>= 1; /* Number of words */1186 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1187 current_SC->SCp.ptr += 2 * data_count;
1188 current_SC->SCp.this_residual -= 2 * data_count;
1189 }1190 }1191 if (!current_SC->SCp.this_residual1192 && current_SC->SCp.buffers_residual) {1193 --current_SC->SCp.buffers_residual;
1194 ++current_SC->SCp.buffer;
1195 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1196 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1197 }1198 }1199 }1200
1201 if (done) {1202 #ifEVERY_ACCESS1203 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1204 #endif1205
1206 #ifERRORS_ONLY1207 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {1208 if ((unsignedchar)(*((char *)current_SC->request_buffer+2)) & 0x0f) {1209 unsignedcharkey;
1210 unsignedcharcode;
1211 unsignedcharqualifier;
1212
1213 key = (unsignedchar)(*((char *)current_SC->request_buffer + 2))
1214 & 0x0f;
1215 code = (unsignedchar)(*((char *)current_SC->request_buffer + 12));
1216 qualifier = (unsignedchar)(*((char *)current_SC->request_buffer1217 + 13));
1218
1219 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1220 && !(key == NOT_READY1221 && code == 0x04
1222 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1223 && !(key == ILLEGAL_REQUEST && (code == 0x25
1224 || code == 0x24
1225 || !code)))
1226
1227 printk( "Future Domain: REQUEST SENSE "
1228 "Key = %x, Code = %x, Qualifier = %x\n",
1229 key, code, qualifier );
1230 }1231 }1232 #endif1233 #ifEVERY_ACCESS1234 printk( "BEFORE MY_DONE. . ." );
1235 #endif1236 my_done( (current_SC->SCp.Status & 0xff)
1237 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1238 #ifEVERY_ACCESS1239 printk( "RETURNING.\n" );
1240 #endif1241
1242 }else{1243 if (current_SC->SCp.phase & disconnect) {1244 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1245 outb( 0x00, SCSI_Cntl_port );
1246 }else{1247 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1248 }1249 }1250 #ifDEBUG_RACE1251 in_interrupt_flag = 0;
1252 #endif1253 return;
1254 }1255
1256 intfdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* */1257 {1258 if (in_command) {1259 panic( "Future Domain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1260 }1261 #ifEVERY_ACCESS1262 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1263 SCpnt->target,
1264 *(unsignedchar *)SCpnt->cmnd,
1265 SCpnt->use_sg,
1266 SCpnt->request_bufflen );
1267 #endif1268
1269 fdomain_make_bus_idle();
1270
1271 current_SC = SCpnt; /* Save this for the done function */1272 current_SC->scsi_done = done;
1273
1274 /* Initialize static data */1275
1276 if (current_SC->use_sg) {1277 current_SC->SCp.buffer =
1278 (structscatterlist *)current_SC->request_buffer;
1279 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1280 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1281 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1282 }else{1283 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1284 current_SC->SCp.this_residual = current_SC->request_bufflen;
1285 current_SC->SCp.buffer = NULL;
1286 current_SC->SCp.buffers_residual = 0;
1287 }1288
1289
1290 current_SC->SCp.Status = 0;
1291 current_SC->SCp.Message = 0;
1292 current_SC->SCp.have_data_in = 0;
1293 current_SC->SCp.sent_command = 0;
1294 current_SC->SCp.phase = in_arbitration;
1295
1296 /* Start arbitration */1297 outb( 0x00, Interrupt_Cntl_port );
1298 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */1299 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */1300 ++in_command;
1301 outb( 0x20, Interrupt_Cntl_port );
1302 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */1303
1304 return 0;
1305 }1306
1307 /* The following code, which simulates the old-style command function, was1308 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)1309 1992 Tommy Thorn. */1310
1311 staticvolatileintinternal_done_flag = 0;
1312 staticvolatileintinternal_done_errcode = 0;
1313
1314 staticvoidinternal_done( Scsi_Cmnd *SCpnt )
/* */1315 {1316 internal_done_errcode = SCpnt->result;
1317 ++internal_done_flag;
1318 }1319
1320 intfdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* */1321 {1322 fdomain_16x0_queue( SCpnt, internal_done );
1323
1324 while (!internal_done_flag)
1325 ;
1326 internal_done_flag = 0;
1327 returninternal_done_errcode;
1328 }1329
1330 /* End of code derived from Tommy Thorn's work. */1331
1332 voidprint_info( Scsi_Cmnd *SCpnt )
/* */1333 {1334 unsignedintimr;
1335 unsignedintirr;
1336 unsignedintisr;
1337
1338 print_banner();
1339 switch (SCpnt->SCp.phase) {1340 casein_arbitration: printk( "arbitration " ); break;
1341 casein_selection: printk( "selection " ); break;
1342 casein_other: printk( "other " ); break;
1343 default: printk( "unknown " ); break;
1344 }1345
1346 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1347 SCpnt->SCp.phase,
1348 SCpnt->target,
1349 *(unsignedchar *)SCpnt->cmnd,
1350 SCpnt->use_sg,
1351 SCpnt->request_bufflen );
1352 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1353 SCpnt->SCp.sent_command,
1354 SCpnt->SCp.have_data_in,
1355 SCpnt->timeout );
1356 #ifDEBUG_RACE1357 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1358 #endif1359
1360 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1361 outb( 0x0a, 0xa0 );
1362 irr = inb( 0xa0 ) << 8;
1363 outb( 0x0a, 0x20 );
1364 irr += inb( 0x20 );
1365 outb( 0x0b, 0xa0 );
1366 isr = inb( 0xa0 ) << 8;
1367 outb( 0x0b, 0x20 );
1368 isr += inb( 0x20 );
1369
1370 /* Print out interesting information */1371 printk( "IMR = 0x%04x", imr );
1372 if (imr & (1 << interrupt_level))
1373 printk( " (masked)" );
1374 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1375
1376 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1377 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1378 if (inb( TMC_Status_port & 1))
1379 printk( " (interrupt)" );
1380 printk( "\n" );
1381 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1382 if (inb( Interrupt_Status_port ) & 0x08)
1383 printk( " (enabled)" );
1384 printk( "\n" );
1385 if (chip == tmc18c50 || chip == tmc18c30) {1386 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1387 printk( "Int. Condition = 0x%02x\n",
1388 inb( port_base + Interrupt_Cond ) );
1389 }1390 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1391 if (chip == tmc18c50 || chip == tmc18c30)
1392 printk( "Configuration 2 = 0x%02x\n",
1393 inb( port_base + Configuration2 ) );
1394 }1395
1396 intfdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* */1397 {1398 #ifEVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT1399 printk( "Future Domain: Abort " );
1400 #endif1401
1402 cli();
1403 if (!in_command) {1404 #ifEVERY_ACCESS || ERRORS_ONLY1405 printk( " (not in command)\n" );
1406 #endif1407 sti();
1408 returnSCSI_ABORT_NOT_RUNNING;
1409 }1410
1411 #ifDEBUG_ABORT1412 print_info( SCpnt );
1413 #endif1414
1415 fdomain_make_bus_idle();
1416
1417 current_SC->SCp.phase |= aborted;
1418
1419 current_SC->result = DID_ABORT << 16;
1420
1421 sti();
1422
1423 /* Aborts are not done well. . . */1424 my_done( DID_ABORT << 16 );
1425
1426 returnSCSI_ABORT_SUCCESS;
1427 }1428
1429 intfdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* */1430 {1431 #ifDEBUG_RESET1432 staticintcalled_once = 0;
1433 #endif1434
1435 #ifERRORS_ONLY1436 printk( "Future Domain: SCSI Bus Reset\n" );
1437 #endif1438
1439 #ifDEBUG_RESET1440 if (called_once) print_info( current_SC );
1441 called_once = 1;
1442 #endif1443
1444 outb( 1, SCSI_Cntl_port );
1445 do_pause( 2 );
1446 outb( 0, SCSI_Cntl_port );
1447 do_pause( 115 );
1448 outb( 0, SCSI_Mode_Cntl_port );
1449 outb( PARITY_MASK, TMC_Cntl_port );
1450
1451 /* Unless this is the very first call (i.e., SCPnt == NULL), everything1452 is probably hosed at this point. We will, however, try to keep1453 things going by informing the high-level code that we need help. */1454
1455 returnSCSI_RESET_WAKEUP;
1456 }1457
1458 #include "sd.h"
1459 #include "scsi_ioctl.h"
1460
1461 intfdomain_16x0_biosparam(Scsi_Disk * disk, intdev, int *info_array )
/* */1462 {1463 intdrive;
1464 intsize = disk->capacity;
1465 unsignedcharbuf[512 + sizeof( int ) * 2];
1466 int *sizes = (int *)buf;
1467 unsignedchar *data = (unsignedchar *)(sizes + 2);
1468 unsignedchardo_read[] = {READ_6, 0, 0, 0, 1, 0 };
1469 intretcode;
1470 structdrive_info{1471 unsignedshortcylinders;
1472 unsignedcharheads;
1473 unsignedcharsectors;
1474 } *i;
1475
1476 /* NOTES:1477 The RAM area starts at 0x1f00 from the bios_base address.1478
1479 For BIOS Version 2.0:1480 1481 The drive parameter table seems to start at 0x1f30.1482 The first byte's purpose is not known.1483 Next is the cylinder, head, and sector information.1484 The last 4 bytes appear to be the drive's size in sectors.1485 The other bytes in the drive parameter table are unknown.1486 If anyone figures them out, please send me mail, and I will1487 update these notes.1488
1489 Tape drives do not get placed in this table.1490
1491 There is another table at 0x1fea:1492 If the byte is 0x01, then the SCSI ID is not in use.1493 If the byte is 0x18 or 0x48, then the SCSI ID is in use,1494 although tapes don't seem to be in this table. I haven't1495 seen any other numbers (in a limited sample).1496
1497 0x1f2d is a drive count (i.e., not including tapes)1498
1499 The table at 0x1fcc are I/O ports addresses for the various1500 operations. I calculate these by hand in this driver code.1501
1502 For BIOS Version 3.2:1503
1504 The drive parameter table starts at 0x1f70. Each entry is1505 0x0a bytes long. Heads are one less than we need to report.1506 */1507
1508 drive = MINOR(dev) / 16;
1509
1510 if (bios_major == 2) {1511 i = (structdrive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1512 info_array[0] = i->heads;
1513 info_array[1] = i->sectors;
1514 info_array[2] = i->cylinders;
1515 }elseif (bios_major == 3 && bios_minor < 4) {/* 3.0 and 3.2 BIOS */1516 i = (structdrive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1517 info_array[0] = i->heads + 1;
1518 info_array[1] = i->sectors;
1519 info_array[2] = i->cylinders;
1520 }else{/* 3.4 BIOS (and up?) */1521 /* This algorithm was provided by Future Domain (much thanks!). */1522
1523 sizes[0] = 0; /* zero bytes out */1524 sizes[1] = 512; /* one sector in */1525 memcpy( data, do_read, sizeof( do_read ) );
1526 retcode = kernel_scsi_ioctl( disk->device,
1527 SCSI_IOCTL_SEND_COMMAND,
1528 (void *)buf );
1529 if (!retcode/* SCSI command ok */1530 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */1531 && data[0x1c2]) {/* Partition type */1532
1533 /* The partition table layout is as follows:1534
1535 Start: 0x1b3h1536 Offset: 0 = partition status1537 1 = starting head1538 2 = starting sector and cylinder (word, encoded)1539 4 = partition type1540 5 = ending head1541 6 = ending sector and cylinder (word, encoded)1542 8 = starting absolute sector (double word)1543 c = number of sectors (double word)1544 Signature: 0x1fe = 0x55aa1545
1546 So, this algorithm assumes:1547 1) the first partition table is in use,1548 2) the data in the first entry is correct, and1549 3) partitions never divide cylinders1550
1551 Note that (1) may be FALSE for NetBSD (and other BSD flavors),1552 as well as for Linux. Note also, that Linux doesn't pay any1553 attention to the fields that are used by this algorithm -- it1554 only uses the absolute sector data. Recent versions of Linux's1555 fdisk(1) will fill this data in correctly, and forthcoming1556 versions will check for consistency.1557
1558 Checking for a non-zero partition type is not part of the1559 Future Domain algorithm, but it seemed to be a reasonable thing1560 to do, especially in the Linux and BSD worlds. */1561
1562 info_array[0] = data[0x1c3] + 1; /* heads */1563 info_array[1] = data[0x1c4] & 0x3f; /* sectors */1564 }else{1565
1566 /* Note that this new method guarantees that there will always be1567 less than 1024 cylinders on a platter. This is good for drives1568 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */1569
1570 if ((unsignedint)size >= 0x7e0000U) {1571 info_array[0] = 0xff; /* heads = 255 */1572 info_array[1] = 0x3f; /* sectors = 63 */1573 }elseif ((unsignedint)size >= 0x200000U) {1574 info_array[0] = 0x80; /* heads = 128 */1575 info_array[1] = 0x3f; /* sectors = 63 */1576 }else{1577 info_array[0] = 0x40; /* heads = 64 */1578 info_array[1] = 0x20; /* sectors = 32 */1579 }1580 }1581 /* For both methods, compute the cylinders */1582 info_array[2] = (unsignedint)size / (info_array[0] * info_array[1] );
1583 }1584
1585 return 0;
1586 }