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: Sat Jan 14 21:39:15 1995 by faith@cs.unc.edu
4 * Author: Rickard E. Faith, faith@cs.unc.edu
5 * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
6 *
7 * $Id: fdomain.c,v 5.26 1995/01/15 02:39:19 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 Thanks to Adam Bowen for the signature to the 1610M/MER/MEX scsi cards,
141 and to Martin Andrews (andrewm@ccfadm.eeg.ccf.org) for the signature to
142 some random TMC-1680 repackaged by IBM.
143
144 All of the alpha testers deserve much thanks.
145
146
147
148 NOTES ON USER DEFINABLE OPTIONS:
149
150 DEBUG: This turns on the printing of various debug information.
151
152 ENABLE_PARITY: This turns on SCSI parity checking. With the current
153 driver, all attached devices must support SCSI parity. If none of your
154 devices support parity, then you can probably get the driver to work by
155 turning this option off. I have no way of testing this, however.
156
157 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
158 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by
159 the SCSI device, an interrupt will be raised. Therefore, this could be as
160 low as 0, or as high as 16. Note, however, that values which are too high
161 or too low seem to prevent any interrupts from occurring, and thereby lock
162 up the machine. I have found that 2 is a good number, but throughput may
163 be increased by changing this value to values which are close to 2.
164 Please let me know if you try any different values.
165
166 DO_DETECT: This activates some old scan code which was needed before the
167 high level drivers got fixed. If you are having trouble with the driver,
168 turning this on should not hurt, and might help. Please let me know if
169 this is the case, since this code will be removed from future drivers.
170
171 RESELECTION: This is no longer an option, since I gave up trying to
172 implement it in version 4.x of this driver. It did not improve
173 performance at all and made the driver unstable (because I never found one
174 of the two race conditions which were introduced by the multiple
175 outstanding command code). The instability seems a very high price to pay
176 just so that you don't have to wait for the tape to rewind. If you want
177 this feature implemented, send me patches. I'll be happy to send a copy
178 of my (broken) driver to anyone who would like to see a copy.
179
180 **************************************************************************/
181
182 #include <linux/sched.h>
183 #include <asm/io.h>
184 #include "../block/blk.h"
185 #include "scsi.h"
186 #include "hosts.h"
187 #include "fdomain.h"
188 #include <asm/system.h>
189 #include <linux/errno.h>
190 #include <linux/string.h>
191 #include <linux/ioport.h>
192
193 #define VERSION "$Revision: 5.26 $"
194
195 /* START OF USER DEFINABLE OPTIONS */
196
197 #define DEBUG 1 /* Enable debugging output */
198 #define ENABLE_PARITY 1 /* Enable SCSI Parity */
199 #define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */
200 #define DO_DETECT 0 /* Do device detection here (see scsi.c) */
201
202 /* END OF USER DEFINABLE OPTIONS */
203
204 #if DEBUG
205 #define EVERY_ACCESS 0 /* Write a line on every scsi access */
206 #define ERRORS_ONLY 1 /* Only write a line if there is an error */
207 #define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */
208 #define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
209 #define DEBUG_ABORT 1 /* Debug abort() routine */
210 #define DEBUG_RESET 1 /* Debug reset() routine */
211 #define DEBUG_RACE 1 /* Debug interrupt-driven race condition */
212 #else
213 #define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
214 #define ERRORS_ONLY 0
215 #define DEBUG_DETECT 0
216 #define DEBUG_MESSAGES 0
217 #define DEBUG_ABORT 0
218 #define DEBUG_RESET 0
219 #define DEBUG_RACE 0
220 #endif
221
222 /* Errors are reported on the line, so we don't need to report them again */
223 #if EVERY_ACCESS
224 #undef ERRORS_ONLY
225 #define ERRORS_ONLY 0
226 #endif
227
228 #if ENABLE_PARITY
229 #define PARITY_MASK 0x08
230 #else
231 #define PARITY_MASK 0x00
232 #endif
233
234 enum chip_type {
235 unknown = 0x00,
236 tmc1800 = 0x01,
237 tmc18c50 = 0x02,
238 tmc18c30 = 0x03,
239 };
240
241 enum {
242 in_arbitration = 0x02,
243 in_selection = 0x04,
244 in_other = 0x08,
245 disconnect = 0x10,
246 aborted = 0x20,
247 sent_ident = 0x40,
248 };
249
250 enum in_port_type {
251 Read_SCSI_Data = 0,
252 SCSI_Status = 1,
253 TMC_Status = 2,
254 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */
255 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */
256 LSB_ID_Code = 5,
257 MSB_ID_Code = 6,
258 Read_Loopback = 7,
259 SCSI_Data_NoACK = 8,
260 Interrupt_Status = 9,
261 Configuration1 = 10,
262 Configuration2 = 11, /* tmc18c50/tmc18c30 only */
263 Read_FIFO = 12,
264 FIFO_Data_Count = 14
265 };
266
267 enum out_port_type {
268 Write_SCSI_Data = 0,
269 SCSI_Cntl = 1,
270 Interrupt_Cntl = 2,
271 SCSI_Mode_Cntl = 3,
272 TMC_Cntl = 4,
273 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */
274 Write_Loopback = 7,
275 IO_Control = 11, /* tmc18c30 only */
276 Write_FIFO = 12
277 };
278
279 static int port_base = 0;
280 static void *bios_base = NULL;
281 static int bios_major = 0;
282 static int bios_minor = 0;
283 static int PCI_bus = 0;
284 static int ISA_200S = 0; /* Quantum ISA-200S */
285 static int interrupt_level = 0;
286 static volatile int in_command = 0;
287 static Scsi_Cmnd *current_SC = NULL;
288 static enum chip_type chip = unknown;
289 static int adapter_mask = 0x40;
290 #if DEBUG_RACE
291 static volatile int in_interrupt_flag = 0;
292 #endif
293
294 static int SCSI_Mode_Cntl_port;
295 static int FIFO_Data_Count_port;
296 static int Interrupt_Cntl_port;
297 static int Interrupt_Status_port;
298 static int Read_FIFO_port;
299 static int Read_SCSI_Data_port;
300 static int SCSI_Cntl_port;
301 static int SCSI_Data_NoACK_port;
302 static int SCSI_Status_port;
303 static int TMC_Cntl_port;
304 static int TMC_Status_port;
305 static int Write_FIFO_port;
306 static int Write_SCSI_Data_port;
307
308 static int FIFO_Size = 0x2000; /* 8k FIFO for
309 pre-tmc18c30 chips */
310
311 extern void fdomain_16x0_intr( int irq, struct pt_regs * regs );
312
313 static void *addresses[] = {
314 (void *)0xc8000,
315 (void *)0xca000,
316 (void *)0xce000,
317 (void *)0xde000,
318 (void *)0xd0000, /* Extra addresses for PCI boards */
319 (void *)0xe0000,
320 };
321 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
322
323 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
324 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
325
326 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
327
328 /*
329
330 READ THIS BEFORE YOU ADD A SIGNATURE!
331
332 READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME!
333
334 READ EVERY WORD, ESPECIALLY THE WORD *NOT*
335
336 This driver works *ONLY* for Future Domain cards using the TMC-1800,
337 TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670,
338 and 1680.
339
340 The following BIOS signature signatures are for boards which do *NOT*
341 work with this driver (these TMC-8xx and TMC-9xx boards may work with the
342 Seagate driver):
343
344 FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88
345 FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89
346 FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89
347 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90
348 FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
349 FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
350 FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92
351
352 */
353
354 struct signature {
355 char *signature;
356 int sig_offset;
357 int sig_length;
358 int major_bios_version;
359 int minor_bios_version;
360 int flag; /* 1 == PCI_bus, 2 == ISA_200S */
361 } signatures[] = {
362 /* 1 2 3 4 5 6 */
363 /* 123456789012345678901234567890123456789012345678901234567890 */
364 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
365 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
366 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
367 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
368 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
369 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
370 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
371 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
372 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
373 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
374 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
375
376 /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE
377 Also, fix the disk geometry code for your signature and send your
378 changes for faith@cs.unc.edu. Above all, do *NOT* change any old
379 signatures!
380
381 Note that the last line will match a "generic" 18XX bios. Because
382 Future Domain has changed the host SCSI ID and/or the location of the
383 geometry information in the on-board RAM area for each of the first
384 three BIOS's, it is still important to enter a fully qualified
385 signature in the table for any new BIOS's (after the host SCSI ID and
386 geometry location are verified). */
387 };
388
389 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
390
391 static void print_banner( struct Scsi_Host *shpnt )
392 {
393 if (!shpnt) return; /* This won't ever happen */
394
395 printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
396
397 if (bios_major >= 0) printk( "%d.", bios_major );
398 else printk( "?." );
399
400 if (bios_minor >= 0) printk( "%d", bios_minor );
401 else printk( "?." );
402
403 printk( " at 0x%x using scsi id %d\n",
404 (unsigned)bios_base, shpnt->this_id );
405
406 printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
407 shpnt->host_no,
408 chip == tmc1800 ? "TMC-1800"
409 : (chip == tmc18c50 ? "TMC-18C50"
410 : (chip == tmc18c30 ? "TMC-18C30" : "Unknown")),
411 port_base );
412
413 if (interrupt_level) printk( "%d", interrupt_level );
414 else printk( "<none>" );
415
416 if (PCI_bus) printk( " (PCI bus)" );
417 printk( "\n" );
418 }
419
420 static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
421 {
422 unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
423
424 while (jiffies < the_time);
425 }
426
427 inline static void fdomain_make_bus_idle( void )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
428 {
429 outb( 0, SCSI_Cntl_port );
430 outb( 0, SCSI_Mode_Cntl_port );
431 if (chip == tmc18c50 || chip == tmc18c30)
432 outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
433 else
434 outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
435 }
436
437 static int fdomain_is_valid_port( int port )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
438 {
439 int options;
440
441 #if DEBUG_DETECT
442 printk( " (%x%x),",
443 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
444 #endif
445
446 /* The MCA ID is a unique id for each MCA compatible board. We
447 are using ISA boards, but Future Domain provides the MCA ID
448 anyway. We can use this ID to ensure that this is a Future
449 Domain TMC-1660/TMC-1680.
450 */
451
452 if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
453 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
454 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
455 chip = tmc1800;
456 } else { /* test for 0xe960 id */
457 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
458 chip = tmc18c50;
459
460 #if 0
461
462 /* Try to toggle 32-bit mode. This only
463 works on an 18c30 chip. (User reports
464 say that this doesn't work at all, so
465 we'll use the other method.) */
466
467 outb( 0x80, port + IO_Control );
468 if (inb( port + Configuration2 ) & 0x80 == 0x80) {
469 outb( 0x00, port + IO_Control );
470 if (inb( port + Configuration2 ) & 0x80 == 0x00) {
471 chip = tmc18c30;
472 FIFO_Size = 0x800; /* 2k FIFO */
473 }
474 }
475 #else
476
477 /* That should have worked, but appears to
478 have problems. Lets assume it is an
479 18c30 if the RAM is disabled. */
480
481 if (inb( port + Configuration2 ) & 0x02) {
482 chip = tmc18c30;
483 FIFO_Size = 0x800; /* 2k FIFO */
484 }
485 #endif
486 /* If that failed, we are an 18c50. */
487 }
488
489 /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
490 Now, check to be sure the bios_base matches these ports. If someone
491 was unlucky enough to have purchased more than one Future Domain
492 board, then they will have to modify this code, as we only detect one
493 board here. [The one with the lowest bios_base.] */
494
495 options = inb( port + Configuration1 );
496
497 #if DEBUG_DETECT
498 printk( " Options = %x\n", options );
499 #endif
500
501 /* Check for board with lowest bios_base --
502 this isn't valid for the 18c30 or for
503 boards on the PCI bus, so just assume we
504 have the right board. */
505
506 if (chip != tmc18c30
507 && !PCI_bus
508 && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
509
510 /* Get the IRQ from the options. */
511
512 interrupt_level = ints[ (options & 0x0e) >> 1 ];
513
514 return 1;
515 }
516
517 static int fdomain_test_loopback( void )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
518 {
519 int i;
520 int result;
521
522 for (i = 0; i < 255; i++) {
523 outb( i, port_base + Write_Loopback );
524 result = inb( port_base + Read_Loopback );
525 if (i != result)
526 return 1;
527 }
528 return 0;
529 }
530
531 int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
532 {
533 int i, j;
534 int flag = 0;
535 int retcode;
536 struct Scsi_Host *shpnt;
537 #if DO_DETECT
538 const int buflen = 255;
539 Scsi_Cmnd SCinit;
540 unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
541 unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 };
542 unsigned char do_read_capacity[] = { READ_CAPACITY,
543 0, 0, 0, 0, 0, 0, 0, 0, 0 };
544 unsigned char buf[buflen];
545 #endif
546
547 #if DEBUG_DETECT
548 printk( "fdomain_16x0_detect()," );
549 #endif
550
551 for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
552 #if DEBUG_DETECT
553 printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
554 #endif
555 for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
556 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
557 signatures[j].signature, signatures[j].sig_length )) {
558 bios_major = signatures[j].major_bios_version;
559 bios_minor = signatures[j].minor_bios_version;
560 PCI_bus = (signatures[j].flag == 1);
561 ISA_200S = (signatures[j].flag == 2);
562 bios_base = addresses[i];
563 }
564 }
565 }
566
567 if (!bios_base) {
568 #if DEBUG_DETECT
569 printk( " FAILED: NO BIOS\n" );
570 #endif
571 return 0;
572 }
573
574 if (bios_major == 2) {
575 /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
576 Assuming the ROM is enabled (otherwise we wouldn't have been
577 able to read the ROM signature :-), then the ROM sets up the
578 RAM area with some magic numbers, such as a list of port
579 base addresses and a list of the disk "geometry" reported to
580 DOS (this geometry has nothing to do with physical geometry).
581 */
582
583 if (ISA_200S) { /* The Quantum board is slightly different. */
584 port_base = *((char *)bios_base + 0x1fa2)
585 + (*((char *)bios_base + 0x1fa3) << 8);
586 } else {
587 port_base = *((char *)bios_base + 0x1fcc)
588 + (*((char *)bios_base + 0x1fcd) << 8);
589 }
590
591 #if DEBUG_DETECT
592 printk( " %x,", port_base );
593 #endif
594
595 for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
596 if (port_base == ports[i])
597 ++flag;
598 }
599
600 if (flag)
601 flag = fdomain_is_valid_port( port_base );
602 }
603
604 if (!flag) { /* Cannot get port base from BIOS RAM */
605
606 /* This is a bad sign. It usually means that someone patched the
607 BIOS signature list (the signatures variable) to contain a BIOS
608 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. It
609 also means that we don't have a Version 2.0 BIOS :-)
610 */
611
612 #if DEBUG_DETECT
613 if (bios_major != 2) printk( " RAM FAILED, " );
614 #endif
615
616 /* Anyway, the alternative to finding the address in the RAM is to
617 just search through every possible port address for one that is
618 attached to the Future Domain card. Don't panic, though, about
619 reading all these random port addresses -- there are rumors that
620 the Future Domain BIOS does something very similar.
621
622 Do not, however, check ports which the kernel knows are being used
623 by another driver. */
624
625 if (!PCI_bus) {
626 for (i = 0; !flag && i < PORT_COUNT; i++) {
627 port_base = ports[i];
628 if (check_region( port_base, 0x10 )) {
629 #if DEBUG_DETECT
630 printk( " (%x inuse),", port_base );
631 #endif
632 continue;
633 }
634 #if DEBUG_DETECT
635 printk( " %x,", port_base );
636 #endif
637 flag = fdomain_is_valid_port( port_base );
638 }
639 } else {
640
641 /* The proper way of doing this is to use ask the PCI bus for the
642 device IRQ and interrupt level.
643
644 Until the Linux kernel supports this sort of PCI bus query, we
645 scan down a bunch of addresses (Future Domain tech support says
646 we will probably find the address before we get to 0xf800).
647 This works fine on some systems -- other systems may have to
648 scan more addresses. If you have to modify this section for
649 your installation, please send mail to faith@cs.unc.edu. */
650
651 for (i = 0xff00; !flag && i > 0xf000; i -= 8) {
652 port_base = i;
653 if (check_region( port_base, 0x10 )) {
654 #if DEBUG_DETECT
655 printk( " (%x inuse)," , port_base );
656 #endif
657 continue;
658 }
659 flag = fdomain_is_valid_port( port_base );
660 }
661 }
662 }
663
664 if (!flag) {
665 #if DEBUG_DETECT
666 printk( " FAILED: NO PORT\n" );
667 #endif
668 return 0; /* Cannot find valid set of ports */
669 }
670
671 SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
672 FIFO_Data_Count_port = port_base + FIFO_Data_Count;
673 Interrupt_Cntl_port = port_base + Interrupt_Cntl;
674 Interrupt_Status_port = port_base + Interrupt_Status;
675 Read_FIFO_port = port_base + Read_FIFO;
676 Read_SCSI_Data_port = port_base + Read_SCSI_Data;
677 SCSI_Cntl_port = port_base + SCSI_Cntl;
678 SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
679 SCSI_Status_port = port_base + SCSI_Status;
680 TMC_Cntl_port = port_base + TMC_Cntl;
681 TMC_Status_port = port_base + TMC_Status;
682 Write_FIFO_port = port_base + Write_FIFO;
683 Write_SCSI_Data_port = port_base + Write_SCSI_Data;
684
685 fdomain_16x0_reset( NULL );
686
687 if (fdomain_test_loopback()) {
688 #if DEBUG_DETECT
689 printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
690 #endif
691 return 0;
692 }
693
694 if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
695 adapter_mask = 0x80;
696 tpnt->this_id = 7;
697 }
698
699 /* Print out a banner here in case we can't
700 get resources. */
701
702 shpnt = scsi_register( tpnt, 0 );
703 print_banner( shpnt );
704
705 /* Log IRQ with kernel */
706 if (!interrupt_level) {
707 panic( "fdomain: *NO* interrupt level selected!\n" );
708 } else {
709 /* Register the IRQ with the kernel */
710
711 retcode = request_irq( interrupt_level,
712 fdomain_16x0_intr, SA_INTERRUPT, "fdomain" );
713
714 if (retcode < 0) {
715 if (retcode == -EINVAL) {
716 printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
717 printk( " This shouldn't happen!\n" );
718 printk( " Send mail to faith@cs.unc.edu\n" );
719 } else if (retcode == -EBUSY) {
720 printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
721 printk( " Please use another IRQ!\n" );
722 } else {
723 printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
724 printk( " This shouldn't happen!\n" );
725 printk( " Send mail to faith@cs.unc.edu\n" );
726 }
727 panic( "fdomain: Driver requires interruptions\n" );
728 }
729 }
730
731 /* Log I/O ports with kernel */
732 request_region( port_base, 0x10, "fdomain" );
733
734 #if DO_DETECT
735
736 /* These routines are here because of the way the SCSI bus behaves after
737 a reset. This appropriate behavior was not handled correctly by the
738 higher level SCSI routines when I first wrote this driver. Now,
739 however, correct scan routines are part of scsi.c and these routines
740 are no longer needed. However, this code is still good for
741 debugging. */
742
743 SCinit.request_buffer = SCinit.buffer = buf;
744 SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
745 SCinit.use_sg = 0;
746 SCinit.lun = 0;
747
748 printk( "fdomain: detection routine scanning for devices:\n" );
749 for (i = 0; i < 8; i++) {
750 SCinit.target = i;
751 if (i == tpnt->this_id) /* Skip host adapter */
752 continue;
753 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
754 retcode = fdomain_16x0_command(&SCinit);
755 if (!retcode) {
756 memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
757 retcode = fdomain_16x0_command(&SCinit);
758 if (!retcode) {
759 printk( " SCSI ID %d: ", i );
760 for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
761 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
762 memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
763 retcode = fdomain_16x0_command(&SCinit);
764 if (!retcode) {
765 unsigned long blocks, size, capacity;
766
767 blocks = (buf[0] << 24) | (buf[1] << 16)
768 | (buf[2] << 8) | buf[3];
769 size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
770 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
771
772 printk( "%lu MB (%lu byte blocks)",
773 ((capacity + 5L) / 10L), size );
774 } else {
775 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
776 retcode = fdomain_16x0_command(&SCinit);
777 }
778 printk ("\n" );
779 } else {
780 memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
781 retcode = fdomain_16x0_command(&SCinit);
782 }
783 }
784 }
785 #endif
786
787 return 1; /* Maximum of one adapter will be detected. */
788 }
789
790 const char *fdomain_16x0_info( struct Scsi_Host *ignore )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
791 {
792 static char buffer[80];
793 char *pt;
794
795 strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
796 if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */
797 strcat( buffer, strchr( VERSION, ':' ) + 1 );
798 pt = strrchr( buffer, '$') - 1;
799 if (!pt) /* Stripped RCS Revision string? */
800 pt = buffer + strlen( buffer ) - 1;
801 if (*pt != ' ')
802 ++pt;
803 *pt = '\0';
804 } else { /* Assume VERSION is a number */
805 strcat( buffer, " " VERSION );
806 }
807
808 return buffer;
809 }
810
811 #if 0
812 static int fdomain_arbitrate( void )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
813 {
814 int status = 0;
815 unsigned long timeout;
816
817 #if EVERY_ACCESS
818 printk( "fdomain_arbitrate()\n" );
819 #endif
820
821 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
822 outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */
823 outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
824
825 timeout = jiffies + 50; /* 500 mS */
826 while (jiffies < timeout) {
827 status = inb( TMC_Status_port ); /* Read adapter status */
828 if (status & 0x02) /* Arbitration complete */
829 return 0;
830 }
831
832 /* Make bus idle */
833 fdomain_make_bus_idle();
834
835 #if EVERY_ACCESS
836 printk( "Arbitration failed, status = %x\n", status );
837 #endif
838 #if ERRORS_ONLY
839 printk( "fdomain: Arbitration failed, status = %x\n", status );
840 #endif
841 return 1;
842 }
843 #endif
844
845 static int fdomain_select( int target )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
846 {
847 int status;
848 unsigned long timeout;
849 static int flag = 0;
850
851
852 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
853 outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
854
855 /* Stop arbitration and enable parity */
856 outb( PARITY_MASK, TMC_Cntl_port );
857
858 timeout = jiffies + 35; /* 350mS -- because of timeouts
859 (was 250mS) */
860
861 while (jiffies < timeout) {
862 status = inb( SCSI_Status_port ); /* Read adapter status */
863 if (status & 1) { /* Busy asserted */
864 /* Enable SCSI Bus (on error, should make bus idle with 0) */
865 outb( 0x80, SCSI_Cntl_port );
866 return 0;
867 }
868 }
869 /* Make bus idle */
870 fdomain_make_bus_idle();
871 #if EVERY_ACCESS
872 if (!target) printk( "Selection failed\n" );
873 #endif
874 #if ERRORS_ONLY
875 if (!target) {
876 if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */
877 ++flag;
878 else
879 printk( "fdomain: Selection failed\n" );
880 }
881 #endif
882 return 1;
883 }
884
885 void my_done( int error )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
886 {
887 if (in_command) {
888 in_command = 0;
889 outb( 0x00, Interrupt_Cntl_port );
890 fdomain_make_bus_idle();
891 current_SC->result = error;
892 if (current_SC->scsi_done)
893 current_SC->scsi_done( current_SC );
894 else panic( "fdomain: current_SC->scsi_done() == NULL" );
895 } else {
896 panic( "fdomain: my_done() called outside of command\n" );
897 }
898 #if DEBUG_RACE
899 in_interrupt_flag = 0;
900 #endif
901 }
902
903 void fdomain_16x0_intr( int irq, struct pt_regs * regs )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
904 {
905 int status;
906 int done = 0;
907 unsigned data_count;
908
909 /* The fdomain_16x0_intr is only called via
910 the interrupt handler. The goal of the
911 sti() here is to allow other
912 interruptions while this routine is
913 running. */
914
915 sti(); /* Yes, we really want sti() here */
916
917 outb( 0x00, Interrupt_Cntl_port );
918
919 /* We usually have one spurious interrupt after each command. Ignore it. */
920 if (!in_command || !current_SC) { /* Spurious interrupt */
921 #if EVERY_ACCESS
922 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
923 in_command, current_SC );
924 #endif
925 return;
926 }
927
928 /* Abort calls my_done, so we do nothing here. */
929 if (current_SC->SCp.phase & aborted) {
930 #if DEBUG_ABORT
931 printk( "Interrupt after abort, ignoring\n" );
932 #endif
933 /*
934 return; */
935 }
936
937 #if DEBUG_RACE
938 ++in_interrupt_flag;
939 #endif
940
941 if (current_SC->SCp.phase & in_arbitration) {
942 status = inb( TMC_Status_port ); /* Read adapter status */
943 if (!(status & 0x02)) {
944 #if EVERY_ACCESS
945 printk( " AFAIL " );
946 #endif
947 my_done( DID_BUS_BUSY << 16 );
948 return;
949 }
950 current_SC->SCp.phase = in_selection;
951
952 outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
953
954 outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
955 outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
956
957 /* Stop arbitration and enable parity */
958 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
959 #if DEBUG_RACE
960 in_interrupt_flag = 0;
961 #endif
962 return;
963 } else if (current_SC->SCp.phase & in_selection) {
964 status = inb( SCSI_Status_port );
965 if (!(status & 0x01)) {
966 /* Try again, for slow devices */
967 if (fdomain_select( current_SC->target )) {
968 #if EVERY_ACCESS
969 printk( " SFAIL " );
970 #endif
971 my_done( DID_NO_CONNECT << 16 );
972 return;
973 } else {
974 #if EVERY_ACCESS
975 printk( " AltSel " );
976 #endif
977 /* Stop arbitration and enable parity */
978 outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
979 }
980 }
981 current_SC->SCp.phase = in_other;
982 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
983 outb( 0x80, SCSI_Cntl_port );
984 #if DEBUG_RACE
985 in_interrupt_flag = 0;
986 #endif
987 return;
988 }
989
990 /* current_SC->SCp.phase == in_other: this is the body of the routine */
991
992 status = inb( SCSI_Status_port );
993
994 if (status & 0x10) { /* REQ */
995
996 switch (status & 0x0e) {
997
998 case 0x08: /* COMMAND OUT */
999 outb( current_SC->cmnd[current_SC->SCp.sent_command++],
1000 Write_SCSI_Data_port );
1001 #if EVERY_ACCESS
1002 printk( "CMD = %x,",
1003 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1004 #endif
1005 break;
1006 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
1007 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
1008 current_SC->SCp.have_data_in = -1;
1009 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1010 }
1011 break;
1012 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
1013 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
1014 current_SC->SCp.have_data_in = 1;
1015 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1016 }
1017 break;
1018 case 0x0c: /* STATUS IN */
1019 current_SC->SCp.Status = inb( Read_SCSI_Data_port );
1020 #if EVERY_ACCESS
1021 printk( "Status = %x, ", current_SC->SCp.Status );
1022 #endif
1023 #if ERRORS_ONLY
1024 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
1025 printk( "fdomain: target = %d, command = %x, status = %x\n",
1026 current_SC->target,
1027 current_SC->cmnd[0],
1028 current_SC->SCp.Status );
1029 }
1030 #endif
1031 break;
1032 case 0x0a: /* MESSAGE OUT */
1033 outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
1034 break;
1035 case 0x0e: /* MESSAGE IN */
1036 current_SC->SCp.Message = inb( Read_SCSI_Data_port );
1037 #if EVERY_ACCESS
1038 printk( "Message = %x, ", current_SC->SCp.Message );
1039 #endif
1040 if (!current_SC->SCp.Message) ++done;
1041 #if DEBUG_MESSAGES || EVERY_ACCESS
1042 if (current_SC->SCp.Message) {
1043 printk( "fdomain: message = %x\n", current_SC->SCp.Message );
1044 }
1045 #endif
1046 break;
1047 }
1048 }
1049
1050 if (chip == tmc1800
1051 && !current_SC->SCp.have_data_in
1052 && (current_SC->SCp.sent_command
1053 >= current_SC->cmd_len)) {
1054 /* We have to get the FIFO direction
1055 correct, so I've made a table based
1056 on the SCSI Standard of which commands
1057 appear to require a DATA OUT phase.
1058 */
1059 /*
1060 p. 94: Command for all device types
1061 CHANGE DEFINITION 40 DATA OUT
1062 COMPARE 39 DATA OUT
1063 COPY 18 DATA OUT
1064 COPY AND VERIFY 3a DATA OUT
1065 INQUIRY 12
1066 LOG SELECT 4c DATA OUT
1067 LOG SENSE 4d
1068 MODE SELECT (6) 15 DATA OUT
1069 MODE SELECT (10) 55 DATA OUT
1070 MODE SENSE (6) 1a
1071 MODE SENSE (10) 5a
1072 READ BUFFER 3c
1073 RECEIVE DIAGNOSTIC RESULTS 1c
1074 REQUEST SENSE 03
1075 SEND DIAGNOSTIC 1d DATA OUT
1076 TEST UNIT READY 00
1077 WRITE BUFFER 3b DATA OUT
1078
1079 p.178: Commands for direct-access devices (not listed on p. 94)
1080 FORMAT UNIT 04 DATA OUT
1081 LOCK-UNLOCK CACHE 36
1082 PRE-FETCH 34
1083 PREVENT-ALLOW MEDIUM REMOVAL 1e
1084 READ (6)/RECEIVE 08
1085 READ (10) 3c
1086 READ CAPACITY 25
1087 READ DEFECT DATA (10) 37
1088 READ LONG 3e
1089 REASSIGN BLOCKS 07 DATA OUT
1090 RELEASE 17
1091 RESERVE 16 DATA OUT
1092 REZERO UNIT/REWIND 01
1093 SEARCH DATA EQUAL (10) 31 DATA OUT
1094 SEARCH DATA HIGH (10) 30 DATA OUT
1095 SEARCH DATA LOW (10) 32 DATA OUT
1096 SEEK (6) 0b
1097 SEEK (10) 2b
1098 SET LIMITS (10) 33
1099 START STOP UNIT 1b
1100 SYNCHRONIZE CACHE 35
1101 VERIFY (10) 2f
1102 WRITE (6)/PRINT/SEND 0a DATA OUT
1103 WRITE (10)/SEND 2a DATA OUT
1104 WRITE AND VERIFY (10) 2e DATA OUT
1105 WRITE LONG 3f DATA OUT
1106 WRITE SAME 41 DATA OUT ?
1107
1108 p. 261: Commands for sequential-access devices (not previously listed)
1109 ERASE 19
1110 LOAD UNLOAD 1b
1111 LOCATE 2b
1112 READ BLOCK LIMITS 05
1113 READ POSITION 34
1114 READ REVERSE 0f
1115 RECOVER BUFFERED DATA 14
1116 SPACE 11
1117 WRITE FILEMARKS 10 ?
1118
1119 p. 298: Commands for printer devices (not previously listed)
1120 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
1121 SLEW AND PRINT 0b DATA OUT -- same as seek
1122 STOP PRINT 1b
1123 SYNCHRONIZE BUFFER 10
1124
1125 p. 315: Commands for processor devices (not previously listed)
1126
1127 p. 321: Commands for write-once devices (not previously listed)
1128 MEDIUM SCAN 38
1129 READ (12) a8
1130 SEARCH DATA EQUAL (12) b1 DATA OUT
1131 SEARCH DATA HIGH (12) b0 DATA OUT
1132 SEARCH DATA LOW (12) b2 DATA OUT
1133 SET LIMITS (12) b3
1134 VERIFY (12) af
1135 WRITE (12) aa DATA OUT
1136 WRITE AND VERIFY (12) ae DATA OUT
1137
1138 p. 332: Commands for CD-ROM devices (not previously listed)
1139 PAUSE/RESUME 4b
1140 PLAY AUDIO (10) 45
1141 PLAY AUDIO (12) a5
1142 PLAY AUDIO MSF 47
1143 PLAY TRACK RELATIVE (10) 49
1144 PLAY TRACK RELATIVE (12) a9
1145 READ HEADER 44
1146 READ SUB-CHANNEL 42
1147 READ TOC 43
1148
1149 p. 370: Commands for scanner devices (not previously listed)
1150 GET DATA BUFFER STATUS 34
1151 GET WINDOW 25
1152 OBJECT POSITION 31
1153 SCAN 1b
1154 SET WINDOW 24 DATA OUT
1155
1156 p. 391: Commands for optical memory devices (not listed)
1157 ERASE (10) 2c
1158 ERASE (12) ac
1159 MEDIUM SCAN 38 DATA OUT
1160 READ DEFECT DATA (12) b7
1161 READ GENERATION 29
1162 READ UPDATED BLOCK 2d
1163 UPDATE BLOCK 3d DATA OUT
1164
1165 p. 419: Commands for medium changer devices (not listed)
1166 EXCHANGE MEDIUM 46
1167 INITIALIZE ELEMENT STATUS 07
1168 MOVE MEDIUM a5
1169 POSITION TO ELEMENT 2b
1170 READ ELEMENT STATUS b8
1171 REQUEST VOL. ELEMENT ADDRESS b5
1172 SEND VOLUME TAG b6 DATA OUT
1173
1174 p. 454: Commands for communications devices (not listed previously)
1175 GET MESSAGE (6) 08
1176 GET MESSAGE (10) 28
1177 GET MESSAGE (12) a8
1178 */
1179
1180 switch (current_SC->cmnd[0]) {
1181 case CHANGE_DEFINITION: case COMPARE: case COPY:
1182 case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
1183 case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
1184
1185 case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
1186 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
1187 case WRITE_6: case WRITE_10: case WRITE_VERIFY:
1188 case 0x3f: case 0x41:
1189
1190 case 0xb1: case 0xb0: case 0xb2:
1191 case 0xaa: case 0xae:
1192
1193 case 0x24:
1194
1195 case 0x38: case 0x3d:
1196
1197 case 0xb6:
1198
1199 case 0xea: /* alternate number for WRITE LONG */
1200
1201 current_SC->SCp.have_data_in = -1;
1202 outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
1203 break;
1204
1205 case 0x00:
1206 default:
1207
1208 current_SC->SCp.have_data_in = 1;
1209 outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
1210 break;
1211 }
1212 }
1213
1214 if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
1215 while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
1216 #if EVERY_ACCESS
1217 printk( "DC=%d, ", data_count ) ;
1218 #endif
1219 if (data_count > current_SC->SCp.this_residual)
1220 data_count = current_SC->SCp.this_residual;
1221 if (data_count > 0) {
1222 #if EVERY_ACCESS
1223 printk( "%d OUT, ", data_count );
1224 #endif
1225 if (data_count == 1) {
1226 outb( *current_SC->SCp.ptr++, Write_FIFO_port );
1227 --current_SC->SCp.this_residual;
1228 } else {
1229 data_count >>= 1;
1230 outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
1231 current_SC->SCp.ptr += 2 * data_count;
1232 current_SC->SCp.this_residual -= 2 * data_count;
1233 }
1234 }
1235 if (!current_SC->SCp.this_residual) {
1236 if (current_SC->SCp.buffers_residual) {
1237 --current_SC->SCp.buffers_residual;
1238 ++current_SC->SCp.buffer;
1239 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1240 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1241 } else
1242 break;
1243 }
1244 }
1245 }
1246
1247 if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
1248 while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
1249 #if EVERY_ACCESS
1250 printk( "DC=%d, ", data_count );
1251 #endif
1252 if (data_count > current_SC->SCp.this_residual)
1253 data_count = current_SC->SCp.this_residual;
1254 if (data_count) {
1255 #if EVERY_ACCESS
1256 printk( "%d IN, ", data_count );
1257 #endif
1258 if (data_count == 1) {
1259 *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
1260 --current_SC->SCp.this_residual;
1261 } else {
1262 data_count >>= 1; /* Number of words */
1263 insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
1264 current_SC->SCp.ptr += 2 * data_count;
1265 current_SC->SCp.this_residual -= 2 * data_count;
1266 }
1267 }
1268 if (!current_SC->SCp.this_residual
1269 && current_SC->SCp.buffers_residual) {
1270 --current_SC->SCp.buffers_residual;
1271 ++current_SC->SCp.buffer;
1272 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1273 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1274 }
1275 }
1276 }
1277
1278 if (done) {
1279 #if EVERY_ACCESS
1280 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1281 #endif
1282
1283 #if ERRORS_ONLY
1284 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1285 if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
1286 unsigned char key;
1287 unsigned char code;
1288 unsigned char qualifier;
1289
1290 key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
1291 & 0x0f;
1292 code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
1293 qualifier = (unsigned char)(*((char *)current_SC->request_buffer
1294 + 13));
1295
1296 if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
1297 && !(key == NOT_READY
1298 && code == 0x04
1299 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1300 && !(key == ILLEGAL_REQUEST && (code == 0x25
1301 || code == 0x24
1302 || !code)))
1303
1304 printk( "fdomain: REQUEST SENSE "
1305 "Key = %x, Code = %x, Qualifier = %x\n",
1306 key, code, qualifier );
1307 }
1308 }
1309 #endif
1310 #if EVERY_ACCESS
1311 printk( "BEFORE MY_DONE. . ." );
1312 #endif
1313 my_done( (current_SC->SCp.Status & 0xff)
1314 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1315 #if EVERY_ACCESS
1316 printk( "RETURNING.\n" );
1317 #endif
1318
1319 } else {
1320 if (current_SC->SCp.phase & disconnect) {
1321 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
1322 outb( 0x00, SCSI_Cntl_port );
1323 } else {
1324 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
1325 }
1326 }
1327 #if DEBUG_RACE
1328 in_interrupt_flag = 0;
1329 #endif
1330 return;
1331 }
1332
1333 int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1334 {
1335 if (in_command) {
1336 panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
1337 }
1338 #if EVERY_ACCESS
1339 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1340 SCpnt->target,
1341 *(unsigned char *)SCpnt->cmnd,
1342 SCpnt->use_sg,
1343 SCpnt->request_bufflen );
1344 #endif
1345
1346 fdomain_make_bus_idle();
1347
1348 current_SC = SCpnt; /* Save this for the done function */
1349 current_SC->scsi_done = done;
1350
1351 /* Initialize static data */
1352
1353 if (current_SC->use_sg) {
1354 current_SC->SCp.buffer =
1355 (struct scatterlist *)current_SC->request_buffer;
1356 current_SC->SCp.ptr = current_SC->SCp.buffer->address;
1357 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1358 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1359 } else {
1360 current_SC->SCp.ptr = (char *)current_SC->request_buffer;
1361 current_SC->SCp.this_residual = current_SC->request_bufflen;
1362 current_SC->SCp.buffer = NULL;
1363 current_SC->SCp.buffers_residual = 0;
1364 }
1365
1366
1367 current_SC->SCp.Status = 0;
1368 current_SC->SCp.Message = 0;
1369 current_SC->SCp.have_data_in = 0;
1370 current_SC->SCp.sent_command = 0;
1371 current_SC->SCp.phase = in_arbitration;
1372
1373 /* Start arbitration */
1374 outb( 0x00, Interrupt_Cntl_port );
1375 outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
1376 outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
1377 ++in_command;
1378 outb( 0x20, Interrupt_Cntl_port );
1379 outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
1380
1381 return 0;
1382 }
1383
1384 /* The following code, which simulates the old-style command function, was
1385 taken from Tommy Thorn's aha1542.c file. This code is Copyright (C)
1386 1992 Tommy Thorn. */
1387
1388 static volatile int internal_done_flag = 0;
1389 static volatile int internal_done_errcode = 0;
1390
1391 static void internal_done( Scsi_Cmnd *SCpnt )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1392 {
1393 internal_done_errcode = SCpnt->result;
1394 ++internal_done_flag;
1395 }
1396
1397 int fdomain_16x0_command( Scsi_Cmnd *SCpnt )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1398 {
1399 fdomain_16x0_queue( SCpnt, internal_done );
1400
1401 while (!internal_done_flag)
1402 ;
1403 internal_done_flag = 0;
1404 return internal_done_errcode;
1405 }
1406
1407 /* End of code derived from Tommy Thorn's work. */
1408
1409 void print_info( Scsi_Cmnd *SCpnt )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1410 {
1411 unsigned int imr;
1412 unsigned int irr;
1413 unsigned int isr;
1414
1415 if (!SCpnt || !SCpnt->host) {
1416 printk( "fdomain: cannot provide detailed information\n" );
1417 }
1418
1419 printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
1420 print_banner( SCpnt->host );
1421 switch (SCpnt->SCp.phase) {
1422 case in_arbitration: printk( "arbitration " ); break;
1423 case in_selection: printk( "selection " ); break;
1424 case in_other: printk( "other " ); break;
1425 default: printk( "unknown " ); break;
1426 }
1427
1428 printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1429 SCpnt->SCp.phase,
1430 SCpnt->target,
1431 *(unsigned char *)SCpnt->cmnd,
1432 SCpnt->use_sg,
1433 SCpnt->request_bufflen );
1434 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1435 SCpnt->SCp.sent_command,
1436 SCpnt->SCp.have_data_in,
1437 SCpnt->timeout );
1438 #if DEBUG_RACE
1439 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1440 #endif
1441
1442 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1443 outb( 0x0a, 0xa0 );
1444 irr = inb( 0xa0 ) << 8;
1445 outb( 0x0a, 0x20 );
1446 irr += inb( 0x20 );
1447 outb( 0x0b, 0xa0 );
1448 isr = inb( 0xa0 ) << 8;
1449 outb( 0x0b, 0x20 );
1450 isr += inb( 0x20 );
1451
1452 /* Print out interesting information */
1453 printk( "IMR = 0x%04x", imr );
1454 if (imr & (1 << interrupt_level))
1455 printk( " (masked)" );
1456 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1457
1458 printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
1459 printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
1460 if (inb( TMC_Status_port & 1))
1461 printk( " (interrupt)" );
1462 printk( "\n" );
1463 printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
1464 if (inb( Interrupt_Status_port ) & 0x08)
1465 printk( " (enabled)" );
1466 printk( "\n" );
1467 if (chip == tmc18c50 || chip == tmc18c30) {
1468 printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
1469 printk( "Int. Condition = 0x%02x\n",
1470 inb( port_base + Interrupt_Cond ) );
1471 }
1472 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1473 if (chip == tmc18c50 || chip == tmc18c30)
1474 printk( "Configuration 2 = 0x%02x\n",
1475 inb( port_base + Configuration2 ) );
1476 }
1477
1478 int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1479 {
1480 unsigned long flags;
1481 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1482 printk( "fdomain: abort " );
1483 #endif
1484
1485 save_flags( flags );
1486 cli();
1487 if (!in_command) {
1488 #if EVERY_ACCESS || ERRORS_ONLY
1489 printk( " (not in command)\n" );
1490 #endif
1491 restore_flags( flags );
1492 return SCSI_ABORT_NOT_RUNNING;
1493 }
1494
1495 #if DEBUG_ABORT
1496 print_info( SCpnt );
1497 #endif
1498
1499 fdomain_make_bus_idle();
1500
1501 current_SC->SCp.phase |= aborted;
1502
1503 current_SC->result = DID_ABORT << 16;
1504
1505 restore_flags( flags );
1506
1507 /* Aborts are not done well. . . */
1508 my_done( DID_ABORT << 16 );
1509
1510 return SCSI_ABORT_SUCCESS;
1511 }
1512
1513 int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1514 {
1515 #if DEBUG_RESET
1516 static int called_once = 0;
1517 #endif
1518
1519 #if ERRORS_ONLY
1520 if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
1521 #endif
1522
1523 #if DEBUG_RESET
1524 if (called_once) print_info( current_SC );
1525 called_once = 1;
1526 #endif
1527
1528 outb( 1, SCSI_Cntl_port );
1529 do_pause( 2 );
1530 outb( 0, SCSI_Cntl_port );
1531 do_pause( 115 );
1532 outb( 0, SCSI_Mode_Cntl_port );
1533 outb( PARITY_MASK, TMC_Cntl_port );
1534
1535 /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1536 is probably hosed at this point. We will, however, try to keep
1537 things going by informing the high-level code that we need help. */
1538
1539 return SCSI_RESET_WAKEUP;
1540 }
1541
1542 #include "sd.h"
1543 #include "scsi_ioctl.h"
1544
1545 int fdomain_16x0_biosparam( Scsi_Disk *disk, int dev, int *info_array )
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1546 {
1547 int drive;
1548 unsigned char buf[512 + sizeof( int ) * 2];
1549 int size = disk->capacity;
1550 int *sizes = (int *)buf;
1551 unsigned char *data = (unsigned char *)(sizes + 2);
1552 unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 };
1553 int retcode;
1554 struct drive_info {
1555 unsigned short cylinders;
1556 unsigned char heads;
1557 unsigned char sectors;
1558 } *i;
1559
1560 /* NOTES:
1561 The RAM area starts at 0x1f00 from the bios_base address.
1562
1563 For BIOS Version 2.0:
1564
1565 The drive parameter table seems to start at 0x1f30.
1566 The first byte's purpose is not known.
1567 Next is the cylinder, head, and sector information.
1568 The last 4 bytes appear to be the drive's size in sectors.
1569 The other bytes in the drive parameter table are unknown.
1570 If anyone figures them out, please send me mail, and I will
1571 update these notes.
1572
1573 Tape drives do not get placed in this table.
1574
1575 There is another table at 0x1fea:
1576 If the byte is 0x01, then the SCSI ID is not in use.
1577 If the byte is 0x18 or 0x48, then the SCSI ID is in use,
1578 although tapes don't seem to be in this table. I haven't
1579 seen any other numbers (in a limited sample).
1580
1581 0x1f2d is a drive count (i.e., not including tapes)
1582
1583 The table at 0x1fcc are I/O ports addresses for the various
1584 operations. I calculate these by hand in this driver code.
1585
1586
1587
1588 For the ISA-200S version of BIOS Version 2.0:
1589
1590 The drive parameter table starts at 0x1f33.
1591
1592 WARNING: Assume that the table entry is 25 bytes long. Someone needs
1593 to check this for the Quantum ISA-200S card.
1594
1595
1596
1597 For BIOS Version 3.2:
1598
1599 The drive parameter table starts at 0x1f70. Each entry is
1600 0x0a bytes long. Heads are one less than we need to report.
1601 */
1602
1603 drive = MINOR(dev) / 16;
1604
1605 if (bios_major == 2) {
1606 if (ISA_200S) {
1607 i = (struct drive_info *)( (char *)bios_base + 0x1f33 + drive * 25 );
1608 } else {
1609 i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );
1610 }
1611 info_array[0] = i->heads;
1612 info_array[1] = i->sectors;
1613 info_array[2] = i->cylinders;
1614 } else if (bios_major == 3
1615 && bios_minor >= 0
1616 && bios_minor < 4) { /* 3.0 and 3.2 BIOS */
1617 i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 );
1618 info_array[0] = i->heads + 1;
1619 info_array[1] = i->sectors;
1620 info_array[2] = i->cylinders;
1621 } else { /* 3.4 BIOS (and up?) */
1622 /* This algorithm was provided by Future Domain (much thanks!). */
1623
1624 sizes[0] = 0; /* zero bytes out */
1625 sizes[1] = 512; /* one sector in */
1626 memcpy( data, do_read, sizeof( do_read ) );
1627 retcode = kernel_scsi_ioctl( disk->device,
1628 SCSI_IOCTL_SEND_COMMAND,
1629 (void *)buf );
1630 if (!retcode /* SCSI command ok */
1631 && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
1632 && data[0x1c2]) { /* Partition type */
1633
1634 /* The partition table layout is as follows:
1635
1636 Start: 0x1b3h
1637 Offset: 0 = partition status
1638 1 = starting head
1639 2 = starting sector and cylinder (word, encoded)
1640 4 = partition type
1641 5 = ending head
1642 6 = ending sector and cylinder (word, encoded)
1643 8 = starting absolute sector (double word)
1644 c = number of sectors (double word)
1645 Signature: 0x1fe = 0x55aa
1646
1647 So, this algorithm assumes:
1648 1) the first partition table is in use,
1649 2) the data in the first entry is correct, and
1650 3) partitions never divide cylinders
1651
1652 Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1653 as well as for Linux. Note also, that Linux doesn't pay any
1654 attention to the fields that are used by this algorithm -- it
1655 only uses the absolute sector data. Recent versions of Linux's
1656 fdisk(1) will fill this data in correctly, and forthcoming
1657 versions will check for consistency.
1658
1659 Checking for a non-zero partition type is not part of the
1660 Future Domain algorithm, but it seemed to be a reasonable thing
1661 to do, especially in the Linux and BSD worlds. */
1662
1663 info_array[0] = data[0x1c3] + 1; /* heads */
1664 info_array[1] = data[0x1c4] & 0x3f; /* sectors */
1665 } else {
1666
1667 /* Note that this new method guarantees that there will always be
1668 less than 1024 cylinders on a platter. This is good for drives
1669 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1670
1671 if ((unsigned int)size >= 0x7e0000U) {
1672 info_array[0] = 0xff; /* heads = 255 */
1673 info_array[1] = 0x3f; /* sectors = 63 */
1674 } else if ((unsigned int)size >= 0x200000U) {
1675 info_array[0] = 0x80; /* heads = 128 */
1676 info_array[1] = 0x3f; /* sectors = 63 */
1677 } else {
1678 info_array[0] = 0x40; /* heads = 64 */
1679 info_array[1] = 0x20; /* sectors = 32 */
1680 }
1681 }
1682 /* For both methods, compute the cylinders */
1683 info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
1684 }
1685
1686 return 0;
1687 }