Bug Summary

File:obj-scan-build/../linux/src/drivers/scsi/fdomain.c
Location:line 1796, column 39
Description:Access to field 'host' results in a dereference of a null pointer (loaded from variable 'SCpnt')

Annotated Source Code

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