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