Linux 2.2.0
[davej-history.git] / drivers / scsi / advansys.c
blobdc46aa27e9b02b5934ef1f31722b59e70be6134e
1 /* $Id: advansys.c,v 1.50 1998/05/08 23:39:15 bobf Exp bobf $ */
2 #define ASC_VERSION "3.1E" /* AdvanSys Driver Version */
4 /*
5 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
6 *
7 * Copyright (c) 1995-1998 Advanced System Products, Inc.
8 * All Rights Reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that redistributions of source
12 * code retain the above copyright notice and this comment without
13 * modification.
15 * There is an AdvanSys Linux WWW page at:
16 * http://www.advansys.com/linux.html
18 * The latest version of the AdvanSys driver is available at:
19 * ftp://ftp.advansys.com/pub/linux/linux.tgz
21 * Please send questions, comments, bug reports to:
22 * bobf@advansys.com (Bob Frey)
27 Documentation for the AdvanSys Driver
29 A. Linux Kernel Testing
30 B. Adapters Supported by this Driver
31 C. Linux v1.2.X - Directions for Adding the AdvanSys Driver
32 D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver
33 E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver
34 F. Source Comments
35 G. Driver Compile Time Options and Debugging
36 H. Driver LILO Option
37 I. Release History
38 J. Known Problems or Issues
39 K. Credits
40 L. AdvanSys Contact Information
42 A. Linux Kernel Testing
44 This driver has been tested in the following Linux kernels: v1.2.13,
45 v1.3.57, v2.0.33, v2.1.77. These kernel versions are major releases
46 of Linux or the latest Linux kernel versions available when this version
47 of the driver was released. The driver should also work in earlier
48 versions of the Linux kernel. Beginning with v1.3.58 the AdvanSys driver
49 is included with all Linux kernels. Please refer to sections C, D, and
50 E for instructions on adding or upgrading the AdvanSys driver.
52 B. Adapters Supported by this Driver
54 AdvanSys (Advanced System Products, Inc.) manufactures the following
55 RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
56 (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
57 buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
58 transfer) SCSI Host Adapters for the PCI bus.
60 The CDB counts below indicate the number of SCSI CDB (Command
61 Descriptor Block) requests that can be stored in the RISC chip
62 cache and board LRAM. A CDB is a single SCSI command. The driver
63 detect routine will display the number of CDBs available for each
64 adapter detected. The number of CDBs used by the driver can be
65 lowered in the BIOS by changing the 'Host Queue Size' adapter setting.
67 Connectivity Products:
68 ABP510/5150 - Bus-Master ISA (240 CDB) (Footnote 1)
69 ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1, 3)
70 ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) (Footnote 4)
71 ABP920 - Bus-Master PCI (16 CDB)
72 ABP930 - Bus-Master PCI (16 CDB) (Footnote 5)
73 ABP930U - Bus-Master PCI Ultra (16 CDB)
74 ABP930UA - Bus-Master PCI Ultra (16 CDB)
75 ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2)
76 ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) (Footnote 2)
78 Single Channel Products:
79 ABP542 - Bus-Master ISA with floppy (240 CDB)
80 ABP742 - Bus-Master EISA (240 CDB)
81 ABP842 - Bus-Master VL (240 CDB)
82 ABP940 - Bus-Master PCI (240 CDB)
83 ABP940U - Bus-Master PCI Ultra (240 CDB)
84 ABP970 - Bus-Master PCI MAC/PC (240 CDB)
85 ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
86 ABP940UW - Bus-Master PCI Ultra-Wide (240 CDB)
88 Multi Channel Products:
89 ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
90 ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
91 ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
92 ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
93 ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
95 Footnotes:
96 1. This board has been shipped by HP with the 4020i CD-R drive.
97 The board has no BIOS so it cannot control a boot device, but
98 it can control any secondary SCSI device.
99 2. This board has been sold by Iomega as a Jaz Jet PCI adapter.
100 3. This board has been sold by SIIG as the i540 SpeedMaster.
101 4. This board has been sold by SIIG as the i542 SpeedMaster.
102 5. This board has been sold by SIIG as the Fast SCSI Pro PCI.
104 C. Linux v1.2.X - Directions for Adding the AdvanSys Driver
106 These directions apply to v1.2.13. For versions that follow v1.2.13.
107 but precede v1.3.57 some of the changes for Linux v1.3.X listed
108 below may need to be modified or included. A patch is available
109 for v1.2.13 from the AdvanSys WWW and FTP sites.
111 There are two source files: advansys.h and advansys.c. Copy
112 both of these files to the directory /usr/src/linux/drivers/scsi.
114 1. Add the following line to /usr/src/linux/arch/i386/config.in
115 after "comment 'SCSI low-level drivers'":
117 bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
119 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
120 after "#include "hosts.h"":
122 #ifdef CONFIG_SCSI_ADVANSYS
123 #include "advansys.h"
124 #endif
126 and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
128 #ifdef CONFIG_SCSI_ADVANSYS
129 ADVANSYS,
130 #endif
132 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
134 ifdef CONFIG_SCSI_ADVANSYS
135 SCSI_SRCS := $(SCSI_SRCS) advansys.c
136 SCSI_OBJS := $(SCSI_OBJS) advansys.o
137 else
138 SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
139 endif
141 4. (Optional) If you would like to enable the LILO command line
142 and /etc/lilo.conf 'advansys' option, make the following changes.
143 This option can be used to disable I/O port scanning or to limit
144 I/O port scanning to specific addresses. Refer to the 'Driver
145 LILO Option' section below. Add the following lines to
146 /usr/src/linux/init/main.c in the prototype section:
148 extern void advansys_setup(char *str, int *ints);
150 and add the following lines to the bootsetups[] array.
152 #ifdef CONFIG_SCSI_ADVANSYS
153 { "advansys=", advansys_setup },
154 #endif
156 5. If you have the HP 4020i CD-R driver and Linux v1.2.X you should
157 add a fix to the CD-ROM target driver. This fix will allow
158 you to mount CDs with the iso9660 file system. Linux v1.3.X
159 already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
160 and function get_sectorsize() after the line:
162 if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
164 add the following line:
166 if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
168 6. In the directory /usr/src/linux run 'make config' to configure
169 the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
170 make the kernel. If the AdvanSys driver is not configured, then
171 a loadable module can be built by running 'make modules' and
172 'make modules_install'. Use 'insmod' and 'rmmod' to install
173 and remove advansys.o.
175 D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver
177 These directions apply to v1.3.57. For versions that precede v1.3.57
178 some of these changes may need to be modified or eliminated. A patch
179 is available for v1.3.57 from the AdvanSys WWW and FTP sites.
180 Beginning with v1.3.58 this driver is included with the Linux
181 distribution eliminating the need for making any changes.
183 There are two source files: advansys.h and advansys.c. Copy
184 both of these files to the directory /usr/src/linux/drivers/scsi.
186 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
187 after "comment 'SCSI low-level drivers'":
189 dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
191 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
192 after "#include "hosts.h"":
194 #ifdef CONFIG_SCSI_ADVANSYS
195 #include "advansys.h"
196 #endif
198 and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
200 #ifdef CONFIG_SCSI_ADVANSYS
201 ADVANSYS,
202 #endif
204 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
206 ifeq ($(CONFIG_SCSI_ADVANSYS),y)
207 L_OBJS += advansys.o
208 else
209 ifeq ($(CONFIG_SCSI_ADVANSYS),m)
210 M_OBJS += advansys.o
211 endif
212 endif
214 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
215 in the enum scsi_directory_inos array:
217 PROC_SCSI_ADVANSYS,
219 5. (Optional) If you would like to enable the LILO command line
220 and /etc/lilo.conf 'advansys' option, make the following changes.
221 This option can be used to disable I/O port scanning or to limit
222 I/O port scanning to specific addresses. Refer to the 'Driver
223 LILO Option' section below. Add the following lines to
224 /usr/src/linux/init/main.c in the prototype section:
226 extern void advansys_setup(char *str, int *ints);
228 and add the following lines to the bootsetups[] array.
230 #ifdef CONFIG_SCSI_ADVANSYS
231 { "advansys=", advansys_setup },
232 #endif
234 6. In the directory /usr/src/linux run 'make config' to configure
235 the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
236 make the kernel. If the AdvanSys driver is not configured, then
237 a loadable module can be built by running 'make modules' and
238 'make modules_install'. Use 'insmod' and 'rmmod' to install
239 and remove advansys.o.
241 E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver
243 To upgrade the AdvanSys driver in a Linux v1.3.58 and newer
244 kernel, first check the version of the current driver. The
245 version is defined by the manifest constant ASC_VERSION at
246 the beginning of advansys.c. The new driver should have a
247 ASC_VERSION value greater than the current version. To install
248 the new driver rename advansys.c and advansys.h in the Linux
249 kernel source tree drivers/scsi directory to different names
250 or save them to a different directory in case you want to revert
251 to the old version of the driver. After the old driver is saved
252 copy the new advansys.c and advansys.h to drivers/scsi, rebuild
253 the kernel, and install the new kernel. No other changes are needed.
255 F. Source Comments
257 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
259 2. This driver should be maintained in multiple files. But to make
260 it easier to include with Linux and to follow Linux conventions,
261 the whole driver is maintained in the source files advansys.h and
262 advansys.c. In this file logical sections of the driver begin with
263 a comment that contains '---'. The following are the logical sections
264 of the driver below.
266 --- Linux Version
267 --- Linux Include Files
268 --- Driver Options
269 --- Debugging Header
270 --- Asc Library Constants and Macros
271 --- Adv Library Constants and Macros
272 --- Driver Constants and Macros
273 --- Driver Structures
274 --- Driver Data
275 --- Driver Function Prototypes
276 --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
277 --- Loadable Driver Support
278 --- Miscellaneous Driver Functions
279 --- Functions Required by the Asc Library
280 --- Functions Required by the Adv Library
281 --- Tracing and Debugging Functions
282 --- Asc Library Functions
283 --- Adv Library Functions
285 3. The string 'XXX' is used to flag code that needs to be re-written
286 or that contains a problem that needs to be addressed.
288 4. I have stripped comments from and reformatted the source for the
289 Asc Library and Adv Library to reduce the size of this file. This
290 source can be found under the following headings. The Asc Library
291 is used to support Narrow Boards. The Adv Library is used to
292 support Wide Boards.
294 --- Asc Library Constants and Macros
295 --- Adv Library Constants and Macros
296 --- Asc Library Functions
297 --- Adv Library Functions
299 G. Driver Compile Time Options and Debugging
301 In this source file the following constants can be defined. They are
302 defined in the source below. Both of these options are enabled by
303 default.
305 1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled)
307 Enabling this option adds assertion logic statements to the
308 driver. If an assertion fails a message will be displayed to
309 the console, but the system will continue to operate. Any
310 assertions encountered should be reported to the person
311 responsible for the driver. Assertion statements may proactively
312 detect problems with the driver and facilitate fixing these
313 problems. Enabling assertions will add a small overhead to the
314 execution of the driver.
316 2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled)
318 Enabling this option adds tracing functions to the driver and
319 the ability to set a driver tracing level at boot time. This
320 option will also export symbols not required outside the driver to
321 the kernel name space. This option is very useful for debugging
322 the driver, but it will add to the size of the driver execution
323 image and add overhead to the execution of the driver.
325 The amount of debugging output can be controlled with the global
326 variable 'asc_dbglvl'. The higher the number the more output. By
327 default the debug level is 0.
329 If the driver is loaded at boot time and the LILO Driver Option
330 is included in the system, the debug level can be changed by
331 specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The
332 first three hex digits of the pseudo I/O Port must be set to
333 'deb' and the fourth hex digit specifies the debug level: 0 - F.
334 The following command line will look for an adapter at 0x330
335 and set the debug level to 2.
337 linux advansys=0x330,0,0,0,0xdeb2
339 If the driver is built as a loadable module this variable can be
340 defined when the driver is loaded. The following insmod command
341 will set the debug level to one.
343 insmod advansys.o asc_dbglvl=1
345 Debugging Message Levels:
346 0: Errors Only
347 1: High-Level Tracing
348 2-N: Verbose Tracing
350 I don't know the approved way for turning on printk()s to the
351 console. Here's a program I use to do this. Debug output is
352 logged in /var/adm/messages.
354 main()
356 syscall(103, 7, 0, 0);
359 I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
360 prevents most level 1 debug messages from being lost.
362 3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0)
364 Enabling this option adds statistics collection and display
365 through /proc to the driver. The information is useful for
366 monitoring driver and device performance. It will add to the
367 size of the driver execution image and add minor overhead to
368 the execution of the driver.
370 Statistics are maintained on a per adapter basis. Driver entry
371 point call counts and transfer size counts are maintained.
372 Statistics are only available for kernels greater than or equal
373 to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured.
375 AdvanSys SCSI adapter files have the following path name format:
377 /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
379 This information can be displayed with cat. For example:
381 cat /proc/scsi/advansys/0
383 When ADVANSYS_STATS is not defined the AdvanSys /proc files only
384 contain adapter and device configuration information.
386 H. Driver LILO Option
388 If init/main.c is modified as described in the 'Directions for Adding
389 the AdvanSys Driver to Linux' section (B.4.) above, the driver will
390 recognize the 'advansys' LILO command line and /etc/lilo.conf option.
391 This option can be used to either disable I/O port scanning or to limit
392 scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
393 PCI boards will still be searched for and detected. This option only
394 affects searching for ISA and VL boards.
396 Examples:
397 1. Eliminate I/O port scanning:
398 boot: linux advansys=
400 boot: linux advansys=0x0
401 2. Limit I/O port scanning to one I/O port:
402 boot: linux advansys=0x110
403 3. Limit I/O port scanning to four I/O ports:
404 boot: linux advansys=0x110,0x210,0x230,0x330
406 For a loadable module the same effect can be achieved by setting
407 the 'asc_iopflag' variable and 'asc_ioport' array when loading
408 the driver, e.g.
410 insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
412 If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1)
413 I/O Port may be added to specify the driver debug level. Refer to
414 the 'Driver Compile Time Options and Debugging' section above for
415 more information.
417 I. Release History
419 BETA-1.0 (12/23/95):
420 First Release
422 BETA-1.1 (12/28/95):
423 1. Prevent advansys_detect() from being called twice.
424 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
426 1.2 (1/12/96):
427 1. Prevent re-entrancy in the interrupt handler which
428 resulted in the driver hanging Linux.
429 2. Fix problem that prevented ABP-940 cards from being
430 recognized on some PCI motherboards.
431 3. Add support for the ABP-5140 PnP ISA card.
432 4. Fix check condition return status.
433 5. Add conditionally compiled code for Linux v1.3.X.
435 1.3 (2/23/96):
436 1. Fix problem in advansys_biosparam() that resulted in the
437 wrong drive geometry being returned for drives > 1GB with
438 extended translation enabled.
439 2. Add additional tracing during device initialization.
440 3. Change code that only applies to ISA PnP adapter.
441 4. Eliminate 'make dep' warning.
442 5. Try to fix problem with handling resets by increasing their
443 timeout value.
445 1.4 (5/8/96):
446 1. Change definitions to eliminate conflicts with other subsystems.
447 2. Add versioning code for the shared interrupt changes.
448 3. Eliminate problem in asc_rmqueue() with iterating after removing
449 a request.
450 4. Remove reset request loop problem from the "Known Problems or
451 Issues" section. This problem was isolated and fixed in the
452 mid-level SCSI driver.
454 1.5 (8/8/96):
455 1. Add support for ABP-940U (PCI Ultra) adapter.
456 2. Add support for IRQ sharing by setting the SA_SHIRQ flag for
457 request_irq and supplying a dev_id pointer to both request_irq()
458 and free_irq().
459 3. In AscSearchIOPortAddr11() restore a call to check_region() which
460 should be used before I/O port probing.
461 4. Fix bug in asc_prt_hex() which resulted in the displaying
462 the wrong data.
463 5. Incorporate miscellaneous Asc Library bug fixes and new microcode.
464 6. Change driver versioning to be specific to each Linux sub-level.
465 7. Change statistics gathering to be per adapter instead of global
466 to the driver.
467 8. Add more information and statistics to the adapter /proc file:
468 /proc/scsi/advansys[0...].
469 9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list.
470 This problem has been addressed with the SCSI mid-level changes
471 made in v1.3.89. The advansys_select_queue_depths() function
472 was added for the v1.3.89 changes.
474 1.6 (9/10/96):
475 1. Incorporate miscellaneous Asc Library bug fixes and new microcode.
477 1.7 (9/25/96):
478 1. Enable clustering and optimize the setting of the maximum number
479 of scatter gather elements for any particular board. Clustering
480 increases CPU utilization, but results in a relatively larger
481 increase in I/O throughput.
482 2. Improve the performance of the request queuing functions by
483 adding a last pointer to the queue structure.
484 3. Correct problems with reset and abort request handling that
485 could have hung or crashed Linux.
486 4. Add more information to the adapter /proc file:
487 /proc/scsi/advansys[0...].
488 5. Remove the request timeout issue form the driver issues list.
489 6. Miscellaneous documentation additions and changes.
491 1.8 (10/4/96):
492 1. Make changes to handle the new v2.1.0 kernel memory mapping
493 in which a kernel virtual address may not be equivalent to its
494 bus or DMA memory address.
495 2. Change abort and reset request handling to make it yet even
496 more robust.
497 3. Try to mitigate request starvation by sending ordered requests
498 to heavily loaded, tag queuing enabled devices.
499 4. Maintain statistics on request response time.
500 5. Add request response time statistics and other information to
501 the adapter /proc file: /proc/scsi/advansys[0...].
503 1.9 (10/21/96):
504 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
505 make use of mid-level SCSI driver device queue depth flow
506 control mechanism. This will eliminate aborts caused by a
507 device being unable to keep up with requests and eliminate
508 repeat busy or QUEUE FULL status returned by a device.
509 2. Incorporate miscellaneous Asc Library bug fixes.
510 3. To allow the driver to work in kernels with broken module
511 support set 'cmd_per_lun' if the driver is compiled as a
512 module. This change affects kernels v1.3.89 to present.
513 4. Remove PCI BIOS address from the driver banner. The PCI BIOS
514 is relocated by the motherboard BIOS and its new address can
515 not be determined by the driver.
516 5. Add mid-level SCSI queue depth information to the adapter
517 /proc file: /proc/scsi/advansys[0...].
519 2.0 (11/14/96):
520 1. Change allocation of global structures used for device
521 initialization to guarantee they are in DMA-able memory.
522 Previously when the driver was loaded as a module these
523 structures might not have been in DMA-able memory, causing
524 device initialization to fail.
526 2.1 (12/30/96):
527 1. In advansys_reset(), if the request is a synchronous reset
528 request, even if the request serial number has changed, then
529 complete the request.
530 2. Add Asc Library bug fixes including new microcode.
531 3. Clear inquiry buffer before using it.
532 4. Correct ifdef typo.
534 2.2 (1/15/97):
535 1. Add Asc Library bug fixes including new microcode.
536 2. Add synchronous data transfer rate information to the
537 adapter /proc file: /proc/scsi/advansys[0...].
538 3. Change ADVANSYS_DEBUG to be disabled by default. This
539 will reduce the size of the driver image, eliminate execution
540 overhead, and remove unneeded symbols from the kernel symbol
541 space that were previously added by the driver.
542 4. Add new compile-time option ADVANSYS_ASSERT for assertion
543 code that used to be defined within ADVANSYS_DEBUG. This
544 option is enabled by default.
546 2.8 (5/26/97):
547 1. Change version number to 2.8 to synchronize the Linux driver
548 version numbering with other AdvanSys drivers.
549 2. Reformat source files without tabs to present the same view
550 of the file to everyone regardless of the editor tab setting
551 being used.
552 3. Add Asc Library bug fixes.
554 3.1A (1/8/98):
555 1. Change version number to 3.1 to indicate that support for
556 Ultra-Wide adapters (ABP-940UW) is included in this release.
557 2. Add Asc Library (Narrow Board) bug fixes.
558 3. Report an underrun condition with the host status byte set
559 to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which
560 causes the underrun condition to be ignored. When Linux defines
561 its own DID_UNDERRUN the constant defined in this file can be
562 removed.
563 4. Add patch to AscWaitTixISRDone().
564 5. Add support for up to 16 different AdvanSys host adapter SCSI
565 channels in one system. This allows four cards with four channels
566 to be used in one system.
568 3.1B (1/9/98):
569 1. Handle that PCI register base addresses are not always page
570 aligned even though ioremap() requires that the address argument
571 be page aligned.
573 3.1C (1/10/98):
574 1. Update latest BIOS version checked for from the /proc file.
575 2. Don't set microcode SDTR variable at initialization. Instead
576 wait until device capabilities have been detected from an Inquiry
577 command.
579 3.1D (1/21/98):
580 1. Improve performance when the driver is compiled as module by
581 allowing up to 64 scatter-gather elements instead of 8.
583 3.1E (5/1/98):
584 1. Set time delay in AscWaitTixISRDone() to 1000 ms.
585 2. Include SMP locking changes.
586 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS
587 access functions.
588 4. Update board serial number printing.
589 5. Try allocating an IRQ both with and without the SA_INTERRUPT
590 flag set to allow IRQ sharing with drivers that do not set
591 the SA_INTERRUPT flag. Also display a more descriptive error
592 message if request_irq() fails.
593 5. Update to latest Asc and Adv Libraries.
595 J. Known Problems or Issues
597 1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around
598 the queue depth flow control code when mid-level SCSI changes
599 are included in Linux.
601 K. Credits
603 Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
604 basis for the Linux v1.3.X changes which were included in the
605 1.2 release.
607 Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug
608 in advansys_biosparam() which was fixed in the 1.3 release.
610 Erik Ratcliffe <erik@caldera.com> has done testing of the
611 AdvanSys driver in the Caldera releases.
613 Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
614 AscWaitTixISRDone() which he found necessary to make the
615 driver work with a SCSI-1 disk.
617 Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide
618 support in the 3.1A driver.
620 L. AdvanSys Contact Information
622 Mail: Advanced System Products, Inc.
623 1150 Ringwood Court
624 San Jose, CA 95131
625 Operator: 1-408-383-9400
626 FAX: 1-408-383-9612
627 Tech Support: 1-800-525-7440/1-408-467-2930
628 BBS: 1-408-383-9540 (14400,N,8,1)
629 Interactive FAX: 1-408-383-9753
630 Customer Direct Sales: 1-800-525-7443/1-408-383-5777
631 Tech Support E-Mail: support@advansys.com
632 FTP Site: ftp.advansys.com (login: anonymous)
633 Web Site: http://www.advansys.com
639 * --- Linux Version
642 /* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
643 #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
645 #ifndef LINUX_VERSION_CODE
646 #include <linux/version.h>
647 #endif /* LINUX_VERSION_CODE */
651 * --- Linux Include Files
654 #include <linux/config.h>
655 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
656 #ifdef MODULE
657 #include <linux/module.h>
658 #endif /* MODULE */
659 #endif /* version >= v1.3.0 */
660 #include <linux/string.h>
661 #include <linux/sched.h>
662 #include <linux/kernel.h>
663 #include <linux/types.h>
664 #include <linux/ioport.h>
665 #include <linux/delay.h>
666 #include <linux/malloc.h>
667 #include <linux/mm.h>
668 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
669 #include <linux/proc_fs.h>
670 #endif /* version >= v1.3.0 */
671 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,23)
672 #include <linux/init.h>
673 #endif /* version >= v2.1.23 */
674 #include <asm/io.h>
675 #include <asm/system.h>
676 #include <asm/dma.h>
677 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
678 #include "../block/blk.h"
679 #else /* version >= v1.3.0 */
680 #include <linux/blk.h>
681 #include <linux/stat.h>
682 #endif /* version >= v1.3.0 */
683 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95)
684 #include <asm/spinlock.h>
685 #endif /* version >= 2.1.95 */
686 #include "scsi.h"
687 #include "hosts.h"
688 #include "sd.h"
689 #include "advansys.h"
690 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,93)
691 #ifdef CONFIG_PCI
692 #include <linux/pci.h>
693 #endif /* CONFIG_PCI */
694 #else /* version < v2.1.93 */
696 * For earlier than v2.1.93 the driver has its own PCI configuration.
697 * If PCI is not needed in a kernel before v2.1.93 this define can be
698 * turned-off to make the driver object smaller.
700 #define ASC_CONFIG_PCI
701 #endif /* version < v2.1.93 */
704 * If Linux eventually defines a DID_UNDERRUN, the constant here can be
705 * removed. The current value of zero for DID_UNDERRUN results in underrun
706 * conditions being ignored.
708 #define DID_UNDERRUN 0
712 * --- Driver Options
715 /* Enable driver assertions. */
716 #define ADVANSYS_ASSERT
718 /* Enable driver tracing. */
719 /* #define ADVANSYS_DEBUG */
722 * Because of no /proc to display them, statistics are disabled
723 * for versions prior to v1.3.0.
725 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
726 #undef ADVANSYS_STATS /* Disable statistics */
727 #else /* version >= v1.3.0 */
728 #define ADVANSYS_STATS /* Enable statistics. */
729 #endif /* version >= v1.3.0 */
733 * --- Debugging Header
736 #ifdef ADVANSYS_DEBUG
737 #define STATIC
738 #else /* ADVANSYS_DEBUG */
739 #define STATIC static
740 #endif /* ADVANSYS_DEBUG */
744 * --- Asc Library Constants and Macros
747 #define ASC_LIB_VERSION_MAJOR 1
748 #define ASC_LIB_VERSION_MINOR 22
749 #define ASC_LIB_SERIAL_NUMBER 113
751 typedef unsigned char uchar;
753 #ifndef NULL
754 #define NULL (0)
755 #endif
756 #ifndef TRUE
757 #define TRUE (1)
758 #endif
759 #ifndef FALSE
760 #define FALSE (0)
761 #endif
762 #define REG register
763 #define rchar REG __s8
764 #define rshort REG __s16
765 #define rint REG __s32
766 #define rlong REG __s32
767 #define ruchar REG __u8
768 #define rushort REG __u16
769 #define ruint REG __u32
770 #define rulong REG __u32
771 #define NULLPTR (void *)0
772 #define FNULLPTR (void *)0UL
773 #define EOF (-1)
774 #define EOS '\0'
775 #define ERR (-1)
776 #define UB_ERR (uchar)(0xFF)
777 #define UW_ERR (uint)(0xFFFF)
778 #define UL_ERR (ulong)(0xFFFFFFFFUL)
779 #define iseven_word(val) ((((uint)val) & (uint)0x0001) == 0)
780 #define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
781 #define toeven_word(val) (((uint)val) & (uint)0xFFFE)
782 #define biton(val, bits) (((uint)(val >> bits) & (uint)0x0001) != 0)
783 #define bitoff(val, bits) (((uint)(val >> bits) & (uint)0x0001) == 0)
784 #define lbiton(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) != 0)
785 #define lbitoff(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) == 0)
786 #define absh(val) ((val) < 0 ? -(val) : (val))
787 #define swapbyte(ch) ((((ch) << 4) | ((ch) >> 4)))
788 #ifndef GBYTE
789 #define GBYTE (0x40000000UL)
790 #endif
791 #ifndef MBYTE
792 #define MBYTE (0x100000UL)
793 #endif
794 #ifndef KBYTE
795 #define KBYTE (0x400)
796 #endif
797 #define HI_BYTE(x) (*((__u8 *)(&x)+1))
798 #define LO_BYTE(x) (*((__u8 *)&x))
799 #define HI_WORD(x) (*((__u16 *)(&x)+1))
800 #define LO_WORD(x) (*((__u16 *)&x))
801 #ifndef MAKEWORD
802 #define MAKEWORD(lo, hi) ((__u16) (((__u16) lo) | ((__u16) hi << 8)))
803 #endif
804 #ifndef MAKELONG
805 #define MAKELONG(lo, hi) ((__u32) (((__u32) lo) | ((__u32) hi << 16)))
806 #endif
807 #define SwapWords(dWord) ((__u32) ((dWord >> 16) | (dWord << 16)))
808 #define SwapBytes(word) ((__u16) ((word >> 8) | (word << 8)))
809 #define BigToLittle(dWord) ((__u32) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
810 #define LittleToBig(dWord) BigToLittle(dWord)
811 #define AscPCIConfigVendorIDRegister 0x0000
812 #define AscPCIConfigDeviceIDRegister 0x0002
813 #define AscPCIConfigCommandRegister 0x0004
814 #define AscPCIConfigStatusRegister 0x0006
815 #define AscPCIConfigRevisionIDRegister 0x0008
816 #define AscPCIConfigCacheSize 0x000C
817 #define AscPCIConfigLatencyTimer 0x000D
818 #define AscPCIIOBaseRegister 0x0010
819 #define AscPCICmdRegBits_IOMemBusMaster 0x0007
820 #define ASC_PCI_ID2BUS(id) ((id) & 0xFF)
821 #define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F)
822 #define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7)
823 #define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
824 #define ASC_PCI_VENDORID 0x10CD
825 #define ASC_PCI_DEVICEID_1200A 0x1100
826 #define ASC_PCI_DEVICEID_1200B 0x1200
827 #define ASC_PCI_DEVICEID_ULTRA 0x1300
828 #define ASC_PCI_REVISION_3150 0x02
829 #define ASC_PCI_REVISION_3050 0x03
831 #define ASC_DVCLIB_CALL_DONE (1)
832 #define ASC_DVCLIB_CALL_FAILED (0)
833 #define ASC_DVCLIB_CALL_ERROR (-1)
835 #define PortAddr unsigned short /* port address size */
836 #define Ptr2Func ulong
837 #define inp(port) inb(port)
838 #define inpw(port) inw(port)
839 #define inpl(port) inl(port)
840 #define outp(port, byte) outb((byte), (port))
841 #define outpw(port, word) outw((word), (port))
842 #define outpl(port, long) outl((long), (port))
843 #define ASC_MAX_SG_QUEUE 7
844 #define ASC_MAX_SG_LIST SG_ALL
846 #define ASC_CS_TYPE unsigned short
847 #ifndef asc_ptr_type
848 #define asc_ptr_type
849 #endif
851 #ifndef ASC_GET_PTR2FUNC
852 #define ASC_GET_PTR2FUNC(fun) (Ptr2Func)(fun)
853 #endif
854 #define FLIP_BYTE_NIBBLE(x) (((x<<4)& 0xFF) | (x>>4))
855 #define ASC_IS_ISA (0x0001)
856 #define ASC_IS_ISAPNP (0x0081)
857 #define ASC_IS_EISA (0x0002)
858 #define ASC_IS_PCI (0x0004)
859 #define ASC_IS_PCI_ULTRA (0x0104)
860 #define ASC_IS_PCMCIA (0x0008)
861 #define ASC_IS_MCA (0x0020)
862 #define ASC_IS_VL (0x0040)
863 #define ASC_ISA_PNP_PORT_ADDR (0x279)
864 #define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
865 #define ASC_IS_WIDESCSI_16 (0x0100)
866 #define ASC_IS_WIDESCSI_32 (0x0200)
867 #define ASC_IS_BIG_ENDIAN (0x8000)
868 #define ASC_CHIP_MIN_VER_VL (0x01)
869 #define ASC_CHIP_MAX_VER_VL (0x07)
870 #define ASC_CHIP_MIN_VER_PCI (0x09)
871 #define ASC_CHIP_MAX_VER_PCI (0x0F)
872 #define ASC_CHIP_VER_PCI_BIT (0x08)
873 #define ASC_CHIP_MIN_VER_ISA (0x11)
874 #define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
875 #define ASC_CHIP_MAX_VER_ISA (0x27)
876 #define ASC_CHIP_VER_ISA_BIT (0x30)
877 #define ASC_CHIP_VER_ISAPNP_BIT (0x20)
878 #define ASC_CHIP_VER_ASYN_BUG (0x21)
879 #define ASC_CHIP_VER_PCI 0x08
880 #define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
881 #define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
882 #define ASC_CHIP_MIN_VER_EISA (0x41)
883 #define ASC_CHIP_MAX_VER_EISA (0x47)
884 #define ASC_CHIP_VER_EISA_BIT (0x40)
885 #define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
886 #define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
887 #define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
888 #define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
889 #define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
890 #define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
891 #define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
892 #define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
893 #define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
894 #define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
895 #define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
896 #ifndef inpw_noswap
897 #define inpw_noswap(port) inpw(port)
898 #endif
899 #ifndef outpw_noswap
900 #define outpw_noswap(port, data) outpw(port, data)
901 #endif
902 #define ASC_SCSI_ID_BITS 3
903 #define ASC_SCSI_TIX_TYPE uchar
904 #define ASC_ALL_DEVICE_BIT_SET 0xFF
905 #ifdef ASC_WIDESCSI_16
906 #undef ASC_SCSI_ID_BITS
907 #define ASC_SCSI_ID_BITS 4
908 #define ASC_ALL_DEVICE_BIT_SET 0xFFFF
909 #endif
910 #ifdef ASC_WIDESCSI_32
911 #undef ASC_SCSI_ID_BITS
912 #define ASC_SCSI_ID_BITS 5
913 #define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL
914 #endif
915 #if ASC_SCSI_ID_BITS == 3
916 #define ASC_SCSI_BIT_ID_TYPE uchar
917 #define ASC_MAX_TID 7
918 #define ASC_MAX_LUN 7
919 #define ASC_SCSI_WIDTH_BIT_SET 0xFF
920 #elif ASC_SCSI_ID_BITS == 4
921 #define ASC_SCSI_BIT_ID_TYPE ushort
922 #define ASC_MAX_TID 15
923 #define ASC_MAX_LUN 7
924 #define ASC_SCSI_WIDTH_BIT_SET 0xFFFF
925 #elif ASC_SCSI_ID_BITS == 5
926 #define ASC_SCSI_BIT_ID_TYPE ulong
927 #define ASC_MAX_TID 31
928 #define ASC_MAX_LUN 7
929 #define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF
930 #else
931 #error ASC_SCSI_ID_BITS definition is wrong
932 #endif
933 #define ASC_MAX_SENSE_LEN 32
934 #define ASC_MIN_SENSE_LEN 14
935 #define ASC_MAX_CDB_LEN 12
936 #define ASC_SCSI_RESET_HOLD_TIME_US 60
937 #define SCSICMD_TestUnitReady 0x00
938 #define SCSICMD_Rewind 0x01
939 #define SCSICMD_Rezero 0x01
940 #define SCSICMD_RequestSense 0x03
941 #define SCSICMD_Format 0x04
942 #define SCSICMD_FormatUnit 0x04
943 #define SCSICMD_Read6 0x08
944 #define SCSICMD_Write6 0x0A
945 #define SCSICMD_Seek6 0x0B
946 #define SCSICMD_Inquiry 0x12
947 #define SCSICMD_Verify6 0x13
948 #define SCSICMD_ModeSelect6 0x15
949 #define SCSICMD_ModeSense6 0x1A
950 #define SCSICMD_StartStopUnit 0x1B
951 #define SCSICMD_LoadUnloadTape 0x1B
952 #define SCSICMD_ReadCapacity 0x25
953 #define SCSICMD_Read10 0x28
954 #define SCSICMD_Write10 0x2A
955 #define SCSICMD_Seek10 0x2B
956 #define SCSICMD_Erase10 0x2C
957 #define SCSICMD_WriteAndVerify10 0x2E
958 #define SCSICMD_Verify10 0x2F
959 #define SCSICMD_WriteBuffer 0x3B
960 #define SCSICMD_ReadBuffer 0x3C
961 #define SCSICMD_ReadLong 0x3E
962 #define SCSICMD_WriteLong 0x3F
963 #define SCSICMD_ReadTOC 0x43
964 #define SCSICMD_ReadHeader 0x44
965 #define SCSICMD_ModeSelect10 0x55
966 #define SCSICMD_ModeSense10 0x5A
967 #define SCSI_TYPE_DASD 0x00
968 #define SCSI_TYPE_SASD 0x01
969 #define SCSI_TYPE_PRN 0x02
970 #define SCSI_TYPE_PROC 0x03
971 #define SCSI_TYPE_WORM 0x04
972 #define SCSI_TYPE_CDROM 0x05
973 #define SCSI_TYPE_SCANNER 0x06
974 #define SCSI_TYPE_OPTMEM 0x07
975 #define SCSI_TYPE_MED_CHG 0x08
976 #define SCSI_TYPE_COMM 0x09
977 #define SCSI_TYPE_UNKNOWN 0x1F
978 #define SCSI_TYPE_NO_DVC 0xFF
979 #define ASC_SCSIDIR_NOCHK 0x00
980 #define ASC_SCSIDIR_T2H 0x08
981 #define ASC_SCSIDIR_H2T 0x10
982 #define ASC_SCSIDIR_NODATA 0x18
983 #define SCSI_SENKEY_NO_SENSE 0x00
984 #define SCSI_SENKEY_UNDEFINED 0x01
985 #define SCSI_SENKEY_NOT_READY 0x02
986 #define SCSI_SENKEY_MEDIUM_ERR 0x03
987 #define SCSI_SENKEY_HW_ERR 0x04
988 #define SCSI_SENKEY_ILLEGAL 0x05
989 #define SCSI_SENKEY_ATTENTION 0x06
990 #define SCSI_SENKEY_PROTECTED 0x07
991 #define SCSI_SENKEY_BLANK 0x08
992 #define SCSI_SENKEY_V_UNIQUE 0x09
993 #define SCSI_SENKEY_CPY_ABORT 0x0A
994 #define SCSI_SENKEY_ABORT 0x0B
995 #define SCSI_SENKEY_EQUAL 0x0C
996 #define SCSI_SENKEY_VOL_OVERFLOW 0x0D
997 #define SCSI_SENKEY_MISCOMP 0x0E
998 #define SCSI_SENKEY_RESERVED 0x0F
999 #define SCSI_ASC_NOMEDIA 0x3A
1000 #define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
1001 #define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
1002 #define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
1003 #define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
1004 #define SS_GOOD 0x00
1005 #define SS_CHK_CONDITION 0x02
1006 #define SS_CONDITION_MET 0x04
1007 #define SS_TARGET_BUSY 0x08
1008 #define SS_INTERMID 0x10
1009 #define SS_INTERMID_COND_MET 0x14
1010 #define SS_RSERV_CONFLICT 0x18
1011 #define SS_CMD_TERMINATED 0x22
1012 #define SS_QUEUE_FULL 0x28
1013 #define MS_CMD_DONE 0x00
1014 #define MS_EXTEND 0x01
1015 #define MS_SDTR_LEN 0x03
1016 #define MS_SDTR_CODE 0x01
1017 #define MS_WDTR_LEN 0x02
1018 #define MS_WDTR_CODE 0x03
1019 #define MS_MDP_LEN 0x05
1020 #define MS_MDP_CODE 0x00
1021 #define M1_SAVE_DATA_PTR 0x02
1022 #define M1_RESTORE_PTRS 0x03
1023 #define M1_DISCONNECT 0x04
1024 #define M1_INIT_DETECTED_ERR 0x05
1025 #define M1_ABORT 0x06
1026 #define M1_MSG_REJECT 0x07
1027 #define M1_NO_OP 0x08
1028 #define M1_MSG_PARITY_ERR 0x09
1029 #define M1_LINK_CMD_DONE 0x0A
1030 #define M1_LINK_CMD_DONE_WFLAG 0x0B
1031 #define M1_BUS_DVC_RESET 0x0C
1032 #define M1_ABORT_TAG 0x0D
1033 #define M1_CLR_QUEUE 0x0E
1034 #define M1_INIT_RECOVERY 0x0F
1035 #define M1_RELEASE_RECOVERY 0x10
1036 #define M1_KILL_IO_PROC 0x11
1037 #define M2_QTAG_MSG_SIMPLE 0x20
1038 #define M2_QTAG_MSG_HEAD 0x21
1039 #define M2_QTAG_MSG_ORDERED 0x22
1040 #define M2_IGNORE_WIDE_RESIDUE 0x23
1042 typedef struct {
1043 uchar peri_dvc_type:5;
1044 uchar peri_qualifier:3;
1045 } ASC_SCSI_INQ0;
1047 typedef struct {
1048 uchar dvc_type_modifier:7;
1049 uchar rmb:1;
1050 } ASC_SCSI_INQ1;
1052 typedef struct {
1053 uchar ansi_apr_ver:3;
1054 uchar ecma_ver:3;
1055 uchar iso_ver:2;
1056 } ASC_SCSI_INQ2;
1058 typedef struct {
1059 uchar rsp_data_fmt:4;
1060 uchar res:2;
1061 uchar TemIOP:1;
1062 uchar aenc:1;
1063 } ASC_SCSI_INQ3;
1065 typedef struct {
1066 uchar StfRe:1;
1067 uchar CmdQue:1;
1068 uchar Reserved:1;
1069 uchar Linked:1;
1070 uchar Sync:1;
1071 uchar WBus16:1;
1072 uchar WBus32:1;
1073 uchar RelAdr:1;
1074 } ASC_SCSI_INQ7;
1076 typedef struct {
1077 ASC_SCSI_INQ0 byte0;
1078 ASC_SCSI_INQ1 byte1;
1079 ASC_SCSI_INQ2 byte2;
1080 ASC_SCSI_INQ3 byte3;
1081 uchar add_len;
1082 uchar res1;
1083 uchar res2;
1084 ASC_SCSI_INQ7 byte7;
1085 uchar vendor_id[8];
1086 uchar product_id[16];
1087 uchar product_rev_level[4];
1088 } ASC_SCSI_INQUIRY;
1090 typedef struct asc_req_sense {
1091 uchar err_code:7;
1092 uchar info_valid:1;
1093 uchar segment_no;
1094 uchar sense_key:4;
1095 uchar reserved_bit:1;
1096 uchar sense_ILI:1;
1097 uchar sense_EOM:1;
1098 uchar file_mark:1;
1099 uchar info1[4];
1100 uchar add_sense_len;
1101 uchar cmd_sp_info[4];
1102 uchar asc;
1103 uchar ascq;
1104 uchar fruc;
1105 uchar sks_byte0:7;
1106 uchar sks_valid:1;
1107 uchar sks_bytes[2];
1108 uchar notused[2];
1109 uchar ex_sense_code;
1110 uchar info2[4];
1111 } ASC_REQ_SENSE;
1113 #define ASC_SG_LIST_PER_Q 7
1114 #define QS_FREE 0x00
1115 #define QS_READY 0x01
1116 #define QS_DISC1 0x02
1117 #define QS_DISC2 0x04
1118 #define QS_BUSY 0x08
1119 #define QS_ABORTED 0x40
1120 #define QS_DONE 0x80
1121 #define QC_NO_CALLBACK 0x01
1122 #define QC_SG_SWAP_QUEUE 0x02
1123 #define QC_SG_HEAD 0x04
1124 #define QC_DATA_IN 0x08
1125 #define QC_DATA_OUT 0x10
1126 #define QC_URGENT 0x20
1127 #define QC_MSG_OUT 0x40
1128 #define QC_REQ_SENSE 0x80
1129 #define QCSG_SG_XFER_LIST 0x02
1130 #define QCSG_SG_XFER_MORE 0x04
1131 #define QCSG_SG_XFER_END 0x08
1132 #define QD_IN_PROGRESS 0x00
1133 #define QD_NO_ERROR 0x01
1134 #define QD_ABORTED_BY_HOST 0x02
1135 #define QD_WITH_ERROR 0x04
1136 #define QD_INVALID_REQUEST 0x80
1137 #define QD_INVALID_HOST_NUM 0x81
1138 #define QD_INVALID_DEVICE 0x82
1139 #define QD_ERR_INTERNAL 0xFF
1140 #define QHSTA_NO_ERROR 0x00
1141 #define QHSTA_M_SEL_TIMEOUT 0x11
1142 #define QHSTA_M_DATA_OVER_RUN 0x12
1143 #define QHSTA_M_DATA_UNDER_RUN 0x12
1144 #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
1145 #define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
1146 #define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1147 #define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
1148 #define QHSTA_D_HOST_ABORT_FAILED 0x23
1149 #define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
1150 #define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1151 #define QHSTA_D_ASPI_NO_BUF_POOL 0x26
1152 #define QHSTA_M_WTM_TIMEOUT 0x41
1153 #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
1154 #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
1155 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1156 #define QHSTA_M_TARGET_STATUS_BUSY 0x45
1157 #define QHSTA_M_BAD_TAG_CODE 0x46
1158 #define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
1159 #define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
1160 #define QHSTA_D_LRAM_CMP_ERROR 0x81
1161 #define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1162 #define ASC_FLAG_SCSIQ_REQ 0x01
1163 #define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1164 #define ASC_FLAG_BIOS_ASYNC_IO 0x04
1165 #define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1166 #define ASC_FLAG_WIN16 0x10
1167 #define ASC_FLAG_WIN32 0x20
1168 #define ASC_FLAG_ISA_OVER_16MB 0x40
1169 #define ASC_FLAG_DOS_VM_CALLBACK 0x80
1170 #define ASC_TAG_FLAG_EXTRA_BYTES 0x10
1171 #define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
1172 #define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
1173 #define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
1174 #define ASC_SCSIQ_CPY_BEG 4
1175 #define ASC_SCSIQ_SGHD_CPY_BEG 2
1176 #define ASC_SCSIQ_B_FWD 0
1177 #define ASC_SCSIQ_B_BWD 1
1178 #define ASC_SCSIQ_B_STATUS 2
1179 #define ASC_SCSIQ_B_QNO 3
1180 #define ASC_SCSIQ_B_CNTL 4
1181 #define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1182 #define ASC_SCSIQ_D_DATA_ADDR 8
1183 #define ASC_SCSIQ_D_DATA_CNT 12
1184 #define ASC_SCSIQ_B_SENSE_LEN 20
1185 #define ASC_SCSIQ_DONE_INFO_BEG 22
1186 #define ASC_SCSIQ_D_SRBPTR 22
1187 #define ASC_SCSIQ_B_TARGET_IX 26
1188 #define ASC_SCSIQ_B_CDB_LEN 28
1189 #define ASC_SCSIQ_B_TAG_CODE 29
1190 #define ASC_SCSIQ_W_VM_ID 30
1191 #define ASC_SCSIQ_DONE_STATUS 32
1192 #define ASC_SCSIQ_HOST_STATUS 33
1193 #define ASC_SCSIQ_SCSI_STATUS 34
1194 #define ASC_SCSIQ_CDB_BEG 36
1195 #define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1196 #define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1197 #define ASC_SCSIQ_B_SG_WK_QP 49
1198 #define ASC_SCSIQ_B_SG_WK_IX 50
1199 #define ASC_SCSIQ_W_REQ_COUNT 52
1200 #define ASC_SCSIQ_B_LIST_CNT 6
1201 #define ASC_SCSIQ_B_CUR_LIST_CNT 7
1202 #define ASC_SGQ_B_SG_CNTL 4
1203 #define ASC_SGQ_B_SG_HEAD_QP 5
1204 #define ASC_SGQ_B_SG_LIST_CNT 6
1205 #define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1206 #define ASC_SGQ_LIST_BEG 8
1207 #define ASC_DEF_SCSI1_QNG 4
1208 #define ASC_MAX_SCSI1_QNG 4
1209 #define ASC_DEF_SCSI2_QNG 16
1210 #define ASC_MAX_SCSI2_QNG 32
1211 #define ASC_TAG_CODE_MASK 0x23
1212 #define ASC_STOP_REQ_RISC_STOP 0x01
1213 #define ASC_STOP_ACK_RISC_STOP 0x03
1214 #define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1215 #define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1216 #define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1217 #define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
1218 #define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
1219 #define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
1220 #define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
1221 #define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
1222 #define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
1223 #define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
1225 typedef struct asc_scisq_1 {
1226 uchar status;
1227 uchar q_no;
1228 uchar cntl;
1229 uchar sg_queue_cnt;
1230 uchar target_id;
1231 uchar target_lun;
1232 ulong data_addr;
1233 ulong data_cnt;
1234 ulong sense_addr;
1235 uchar sense_len;
1236 uchar extra_bytes;
1237 } ASC_SCSIQ_1;
1239 typedef struct asc_scisq_2 {
1240 ulong srb_ptr;
1241 uchar target_ix;
1242 uchar flag;
1243 uchar cdb_len;
1244 uchar tag_code;
1245 ushort vm_id;
1246 } ASC_SCSIQ_2;
1248 typedef struct asc_scsiq_3 {
1249 uchar done_stat;
1250 uchar host_stat;
1251 uchar scsi_stat;
1252 uchar scsi_msg;
1253 } ASC_SCSIQ_3;
1255 typedef struct asc_scsiq_4 {
1256 uchar cdb[ASC_MAX_CDB_LEN];
1257 uchar y_first_sg_list_qp;
1258 uchar y_working_sg_qp;
1259 uchar y_working_sg_ix;
1260 uchar y_res;
1261 ushort x_req_count;
1262 ushort x_reconnect_rtn;
1263 ulong x_saved_data_addr;
1264 ulong x_saved_data_cnt;
1265 } ASC_SCSIQ_4;
1267 typedef struct asc_q_done_info {
1268 ASC_SCSIQ_2 d2;
1269 ASC_SCSIQ_3 d3;
1270 uchar q_status;
1271 uchar q_no;
1272 uchar cntl;
1273 uchar sense_len;
1274 uchar extra_bytes;
1275 uchar res;
1276 ulong remain_bytes;
1277 } ASC_QDONE_INFO;
1279 typedef struct asc_sg_list {
1280 ulong addr;
1281 ulong bytes;
1282 } ASC_SG_LIST;
1284 typedef struct asc_sg_head {
1285 ushort entry_cnt;
1286 ushort queue_cnt;
1287 ushort entry_to_copy;
1288 ushort res;
1289 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
1290 } ASC_SG_HEAD;
1292 #define ASC_MIN_SG_LIST 2
1294 typedef struct asc_min_sg_head {
1295 ushort entry_cnt;
1296 ushort queue_cnt;
1297 ushort entry_to_copy;
1298 ushort res;
1299 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
1300 } ASC_MIN_SG_HEAD;
1302 #define QCX_SORT (0x0001)
1303 #define QCX_COALEASE (0x0002)
1305 typedef struct asc_scsi_q {
1306 ASC_SCSIQ_1 q1;
1307 ASC_SCSIQ_2 q2;
1308 uchar *cdbptr;
1309 ASC_SG_HEAD *sg_head;
1310 } ASC_SCSI_Q;
1312 typedef struct asc_scsi_req_q {
1313 ASC_SCSIQ_1 r1;
1314 ASC_SCSIQ_2 r2;
1315 uchar *cdbptr;
1316 ASC_SG_HEAD *sg_head;
1317 uchar *sense_ptr;
1318 ASC_SCSIQ_3 r3;
1319 uchar cdb[ASC_MAX_CDB_LEN];
1320 uchar sense[ASC_MIN_SENSE_LEN];
1321 } ASC_SCSI_REQ_Q;
1323 typedef struct asc_scsi_bios_req_q {
1324 ASC_SCSIQ_1 r1;
1325 ASC_SCSIQ_2 r2;
1326 uchar *cdbptr;
1327 ASC_SG_HEAD *sg_head;
1328 uchar *sense_ptr;
1329 ASC_SCSIQ_3 r3;
1330 uchar cdb[ASC_MAX_CDB_LEN];
1331 uchar sense[ASC_MIN_SENSE_LEN];
1332 } ASC_SCSI_BIOS_REQ_Q;
1334 typedef struct asc_risc_q {
1335 uchar fwd;
1336 uchar bwd;
1337 ASC_SCSIQ_1 i1;
1338 ASC_SCSIQ_2 i2;
1339 ASC_SCSIQ_3 i3;
1340 ASC_SCSIQ_4 i4;
1341 } ASC_RISC_Q;
1343 typedef struct asc_sg_list_q {
1344 uchar seq_no;
1345 uchar q_no;
1346 uchar cntl;
1347 uchar sg_head_qp;
1348 uchar sg_list_cnt;
1349 uchar sg_cur_list_cnt;
1350 } ASC_SG_LIST_Q;
1352 typedef struct asc_risc_sg_list_q {
1353 uchar fwd;
1354 uchar bwd;
1355 ASC_SG_LIST_Q sg;
1356 ASC_SG_LIST sg_list[7];
1357 } ASC_RISC_SG_LIST_Q;
1359 #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1360 #define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1361 #define ASCQ_ERR_NO_ERROR 0
1362 #define ASCQ_ERR_IO_NOT_FOUND 1
1363 #define ASCQ_ERR_LOCAL_MEM 2
1364 #define ASCQ_ERR_CHKSUM 3
1365 #define ASCQ_ERR_START_CHIP 4
1366 #define ASCQ_ERR_INT_TARGET_ID 5
1367 #define ASCQ_ERR_INT_LOCAL_MEM 6
1368 #define ASCQ_ERR_HALT_RISC 7
1369 #define ASCQ_ERR_GET_ASPI_ENTRY 8
1370 #define ASCQ_ERR_CLOSE_ASPI 9
1371 #define ASCQ_ERR_HOST_INQUIRY 0x0A
1372 #define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1373 #define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1374 #define ASCQ_ERR_Q_STATUS 0x0D
1375 #define ASCQ_ERR_WR_SCSIQ 0x0E
1376 #define ASCQ_ERR_PC_ADDR 0x0F
1377 #define ASCQ_ERR_SYN_OFFSET 0x10
1378 #define ASCQ_ERR_SYN_XFER_TIME 0x11
1379 #define ASCQ_ERR_LOCK_DMA 0x12
1380 #define ASCQ_ERR_UNLOCK_DMA 0x13
1381 #define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1382 #define ASCQ_ERR_MICRO_CODE_HALT 0x15
1383 #define ASCQ_ERR_SET_LRAM_ADDR 0x16
1384 #define ASCQ_ERR_CUR_QNG 0x17
1385 #define ASCQ_ERR_SG_Q_LINKS 0x18
1386 #define ASCQ_ERR_SCSIQ_PTR 0x19
1387 #define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1388 #define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1389 #define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1390 #define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1391 #define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1392 #define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1393 #define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1394 #define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1395 #define ASCQ_ERR_SEND_SCSI_Q 0x22
1396 #define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1397 #define ASCQ_ERR_RESET_SDTR 0x24
1398 #define ASC_WARN_NO_ERROR 0x0000
1399 #define ASC_WARN_IO_PORT_ROTATE 0x0001
1400 #define ASC_WARN_EEPROM_CHKSUM 0x0002
1401 #define ASC_WARN_IRQ_MODIFIED 0x0004
1402 #define ASC_WARN_AUTO_CONFIG 0x0008
1403 #define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1404 #define ASC_WARN_EEPROM_RECOVER 0x0020
1405 #define ASC_WARN_CFG_MSW_RECOVER 0x0040
1406 #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
1407 #define ASC_IERR_WRITE_EEPROM 0x0001
1408 #define ASC_IERR_MCODE_CHKSUM 0x0002
1409 #define ASC_IERR_SET_PC_ADDR 0x0004
1410 #define ASC_IERR_START_STOP_CHIP 0x0008
1411 #define ASC_IERR_IRQ_NO 0x0010
1412 #define ASC_IERR_SET_IRQ_NO 0x0020
1413 #define ASC_IERR_CHIP_VERSION 0x0040
1414 #define ASC_IERR_SET_SCSI_ID 0x0080
1415 #define ASC_IERR_GET_PHY_ADDR 0x0100
1416 #define ASC_IERR_BAD_SIGNATURE 0x0200
1417 #define ASC_IERR_NO_BUS_TYPE 0x0400
1418 #define ASC_IERR_SCAM 0x0800
1419 #define ASC_IERR_SET_SDTR 0x1000
1420 #define ASC_IERR_RW_LRAM 0x8000
1421 #define ASC_DEF_IRQ_NO 10
1422 #define ASC_MAX_IRQ_NO 15
1423 #define ASC_MIN_IRQ_NO 10
1424 #define ASC_MIN_REMAIN_Q (0x02)
1425 #define ASC_DEF_MAX_TOTAL_QNG (0xF0)
1426 #define ASC_MIN_TAG_Q_PER_DVC (0x04)
1427 #define ASC_DEF_TAG_Q_PER_DVC (0x04)
1428 #define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1429 #define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
1430 #define ASC_MAX_TOTAL_QNG 240
1431 #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
1432 #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
1433 #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1434 #define ASC_MAX_INRAM_TAG_QNG 16
1435 #define ASC_IOADR_TABLE_MAX_IX 11
1436 #define ASC_IOADR_GAP 0x10
1437 #define ASC_SEARCH_IOP_GAP 0x10
1438 #define ASC_MIN_IOP_ADDR (PortAddr)0x0100
1439 #define ASC_MAX_IOP_ADDR (PortAddr)0x3F0
1440 #define ASC_IOADR_1 (PortAddr)0x0110
1441 #define ASC_IOADR_2 (PortAddr)0x0130
1442 #define ASC_IOADR_3 (PortAddr)0x0150
1443 #define ASC_IOADR_4 (PortAddr)0x0190
1444 #define ASC_IOADR_5 (PortAddr)0x0210
1445 #define ASC_IOADR_6 (PortAddr)0x0230
1446 #define ASC_IOADR_7 (PortAddr)0x0250
1447 #define ASC_IOADR_8 (PortAddr)0x0330
1448 #define ASC_IOADR_DEF ASC_IOADR_8
1449 #define ASC_LIB_SCSIQ_WK_SP 256
1450 #define ASC_MAX_SYN_XFER_NO 16
1451 #define ASC_SYN_MAX_OFFSET 0x0F
1452 #define ASC_DEF_SDTR_OFFSET 0x0F
1453 #define ASC_DEF_SDTR_INDEX 0x00
1454 #define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
1455 #define SYN_XFER_NS_0 25
1456 #define SYN_XFER_NS_1 30
1457 #define SYN_XFER_NS_2 35
1458 #define SYN_XFER_NS_3 40
1459 #define SYN_XFER_NS_4 50
1460 #define SYN_XFER_NS_5 60
1461 #define SYN_XFER_NS_6 70
1462 #define SYN_XFER_NS_7 85
1463 #define SYN_ULTRA_XFER_NS_0 12
1464 #define SYN_ULTRA_XFER_NS_1 19
1465 #define SYN_ULTRA_XFER_NS_2 25
1466 #define SYN_ULTRA_XFER_NS_3 32
1467 #define SYN_ULTRA_XFER_NS_4 38
1468 #define SYN_ULTRA_XFER_NS_5 44
1469 #define SYN_ULTRA_XFER_NS_6 50
1470 #define SYN_ULTRA_XFER_NS_7 57
1471 #define SYN_ULTRA_XFER_NS_8 63
1472 #define SYN_ULTRA_XFER_NS_9 69
1473 #define SYN_ULTRA_XFER_NS_10 75
1474 #define SYN_ULTRA_XFER_NS_11 82
1475 #define SYN_ULTRA_XFER_NS_12 88
1476 #define SYN_ULTRA_XFER_NS_13 94
1477 #define SYN_ULTRA_XFER_NS_14 100
1478 #define SYN_ULTRA_XFER_NS_15 107
1480 typedef struct ext_msg {
1481 uchar msg_type;
1482 uchar msg_len;
1483 uchar msg_req;
1484 union {
1485 struct {
1486 uchar sdtr_xfer_period;
1487 uchar sdtr_req_ack_offset;
1488 } sdtr;
1489 struct {
1490 uchar wdtr_width;
1491 } wdtr;
1492 struct {
1493 uchar mdp_b3;
1494 uchar mdp_b2;
1495 uchar mdp_b1;
1496 uchar mdp_b0;
1497 } mdp;
1498 } u_ext_msg;
1499 uchar res;
1500 } EXT_MSG;
1502 #define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
1503 #define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
1504 #define wdtr_width u_ext_msg.wdtr.wdtr_width
1505 #define mdp_b3 u_ext_msg.mdp_b3
1506 #define mdp_b2 u_ext_msg.mdp_b2
1507 #define mdp_b1 u_ext_msg.mdp_b1
1508 #define mdp_b0 u_ext_msg.mdp_b0
1510 typedef struct asc_dvc_cfg {
1511 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1512 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1513 ASC_SCSI_BIT_ID_TYPE disc_enable;
1514 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
1515 uchar chip_scsi_id:4;
1516 uchar isa_dma_speed:4;
1517 uchar isa_dma_channel;
1518 uchar chip_version;
1519 ushort pci_device_id;
1520 ushort lib_serial_no;
1521 ushort lib_version;
1522 ushort mcode_date;
1523 ushort mcode_version;
1524 uchar max_tag_qng[ASC_MAX_TID + 1];
1525 uchar *overrun_buf;
1526 uchar sdtr_period_offset[ASC_MAX_TID + 1];
1527 ushort pci_slot_info;
1528 uchar adapter_info[6];
1529 } ASC_DVC_CFG;
1531 #define ASC_DEF_DVC_CNTL 0xFFFF
1532 #define ASC_DEF_CHIP_SCSI_ID 7
1533 #define ASC_DEF_ISA_DMA_SPEED 4
1534 #define ASC_INIT_STATE_NULL 0x0000
1535 #define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1536 #define ASC_INIT_STATE_END_GET_CFG 0x0002
1537 #define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1538 #define ASC_INIT_STATE_END_SET_CFG 0x0008
1539 #define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1540 #define ASC_INIT_STATE_END_LOAD_MC 0x0020
1541 #define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1542 #define ASC_INIT_STATE_END_INQUIRY 0x0080
1543 #define ASC_INIT_RESET_SCSI_DONE 0x0100
1544 #define ASC_INIT_STATE_WITHOUT_EEP 0x8000
1545 #define ASC_PCI_DEVICE_ID_REV_A 0x1100
1546 #define ASC_PCI_DEVICE_ID_REV_B 0x1200
1547 #define ASC_BUG_FIX_IF_NOT_DWB 0x0001
1548 #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
1549 #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1550 #define ASC_MIN_TAGGED_CMD 7
1551 #define ASC_MAX_SCSI_RESET_WAIT 30
1553 typedef struct asc_dvc_var {
1554 PortAddr iop_base;
1555 ushort err_code;
1556 ushort dvc_cntl;
1557 ushort bug_fix_cntl;
1558 ushort bus_type;
1559 Ptr2Func isr_callback;
1560 Ptr2Func exe_callback;
1561 ASC_SCSI_BIT_ID_TYPE init_sdtr;
1562 ASC_SCSI_BIT_ID_TYPE sdtr_done;
1563 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1564 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1565 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1566 ASC_SCSI_BIT_ID_TYPE start_motor;
1567 uchar scsi_reset_wait;
1568 uchar chip_no;
1569 char is_in_int;
1570 uchar max_total_qng;
1571 uchar cur_total_qng;
1572 uchar in_critical_cnt;
1573 uchar irq_no;
1574 uchar last_q_shortage;
1575 ushort init_state;
1576 uchar cur_dvc_qng[ASC_MAX_TID + 1];
1577 uchar max_dvc_qng[ASC_MAX_TID + 1];
1578 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
1579 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
1580 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
1581 ASC_DVC_CFG *cfg;
1582 Ptr2Func saved_ptr2func;
1583 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
1584 char redo_scam;
1585 ushort res2;
1586 uchar dos_int13_table[ASC_MAX_TID + 1];
1587 ulong max_dma_count;
1588 ASC_SCSI_BIT_ID_TYPE no_scam;
1589 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1590 uchar max_sdtr_index;
1591 uchar host_init_sdtr_index;
1592 ulong drv_ptr;
1593 ulong uc_break;
1594 ulong res7;
1595 ulong res8;
1596 } ASC_DVC_VAR;
1598 typedef int (* ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO *);
1599 typedef int (* ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
1601 typedef struct asc_dvc_inq_info {
1602 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1603 } ASC_DVC_INQ_INFO;
1605 typedef struct asc_cap_info {
1606 ulong lba;
1607 ulong blk_size;
1608 } ASC_CAP_INFO;
1610 typedef struct asc_cap_info_array {
1611 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1612 } ASC_CAP_INFO_ARRAY;
1614 #define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
1615 #define ASC_MCNTL_NULL_TARGET (ushort)0x0002
1616 #define ASC_CNTL_INITIATOR (ushort)0x0001
1617 #define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
1618 #define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
1619 #define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
1620 #define ASC_CNTL_NO_SCAM (ushort)0x0010
1621 #define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
1622 #define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
1623 #define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
1624 #define ASC_CNTL_RESET_SCSI (ushort)0x0200
1625 #define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
1626 #define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
1627 #define ASC_CNTL_SCSI_PARITY (ushort)0x1000
1628 #define ASC_CNTL_BURST_MODE (ushort)0x2000
1629 #define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
1630 #define ASC_EEP_DVC_CFG_BEG_VL 2
1631 #define ASC_EEP_MAX_DVC_ADDR_VL 15
1632 #define ASC_EEP_DVC_CFG_BEG 32
1633 #define ASC_EEP_MAX_DVC_ADDR 45
1634 #define ASC_EEP_DEFINED_WORDS 10
1635 #define ASC_EEP_MAX_ADDR 63
1636 #define ASC_EEP_RES_WORDS 0
1637 #define ASC_EEP_MAX_RETRY 20
1638 #define ASC_MAX_INIT_BUSY_RETRY 8
1639 #define ASC_EEP_ISA_PNP_WSIZE 16
1641 typedef struct asceep_config {
1642 ushort cfg_lsw;
1643 ushort cfg_msw;
1644 uchar init_sdtr;
1645 uchar disc_enable;
1646 uchar use_cmd_qng;
1647 uchar start_motor;
1648 uchar max_total_qng;
1649 uchar max_tag_qng;
1650 uchar bios_scan;
1651 uchar power_up_wait;
1652 uchar no_scam;
1653 uchar chip_scsi_id:4;
1654 uchar isa_dma_speed:4;
1655 uchar dos_int13_table[ASC_MAX_TID + 1];
1656 uchar adapter_info[6];
1657 ushort cntl;
1658 ushort chksum;
1659 } ASCEEP_CONFIG;
1661 #define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
1662 #define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
1663 #define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
1665 #define ASC_EEP_CMD_READ 0x80
1666 #define ASC_EEP_CMD_WRITE 0x40
1667 #define ASC_EEP_CMD_WRITE_ABLE 0x30
1668 #define ASC_EEP_CMD_WRITE_DISABLE 0x00
1669 #define ASC_OVERRUN_BSIZE 0x00000048UL
1670 #define ASC_CTRL_BREAK_ONCE 0x0001
1671 #define ASC_CTRL_BREAK_STAY_IDLE 0x0002
1672 #define ASCV_MSGOUT_BEG 0x0000
1673 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1674 #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1675 #define ASCV_BREAK_SAVED_CODE (ushort)0x0006
1676 #define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1677 #define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1678 #define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1679 #define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1680 #define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1681 #define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
1682 #define ASCV_BREAK_ADDR (ushort)0x0028
1683 #define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
1684 #define ASCV_BREAK_CONTROL (ushort)0x002C
1685 #define ASCV_BREAK_HIT_COUNT (ushort)0x002E
1687 #define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
1688 #define ASCV_MCODE_CHKSUM_W (ushort)0x0032
1689 #define ASCV_MCODE_SIZE_W (ushort)0x0034
1690 #define ASCV_STOP_CODE_B (ushort)0x0036
1691 #define ASCV_DVC_ERR_CODE_B (ushort)0x0037
1692 #define ASCV_OVERRUN_PADDR_D (ushort)0x0038
1693 #define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
1694 #define ASCV_HALTCODE_W (ushort)0x0040
1695 #define ASCV_CHKSUM_W (ushort)0x0042
1696 #define ASCV_MC_DATE_W (ushort)0x0044
1697 #define ASCV_MC_VER_W (ushort)0x0046
1698 #define ASCV_NEXTRDY_B (ushort)0x0048
1699 #define ASCV_DONENEXT_B (ushort)0x0049
1700 #define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
1701 #define ASCV_SCSIBUSY_B (ushort)0x004B
1702 #define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
1703 #define ASCV_CURCDB_B (ushort)0x004D
1704 #define ASCV_RCLUN_B (ushort)0x004E
1705 #define ASCV_BUSY_QHEAD_B (ushort)0x004F
1706 #define ASCV_DISC1_QHEAD_B (ushort)0x0050
1707 #define ASCV_DISC_ENABLE_B (ushort)0x0052
1708 #define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
1709 #define ASCV_HOSTSCSI_ID_B (ushort)0x0055
1710 #define ASCV_MCODE_CNTL_B (ushort)0x0056
1711 #define ASCV_NULL_TARGET_B (ushort)0x0057
1712 #define ASCV_FREE_Q_HEAD_W (ushort)0x0058
1713 #define ASCV_DONE_Q_TAIL_W (ushort)0x005A
1714 #define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
1715 #define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
1716 #define ASCV_HOST_FLAG_B (ushort)0x005D
1717 #define ASCV_TOTAL_READY_Q_B (ushort)0x0064
1718 #define ASCV_VER_SERIAL_B (ushort)0x0065
1719 #define ASCV_HALTCODE_SAVED_W (ushort)0x0066
1720 #define ASCV_WTM_FLAG_B (ushort)0x0068
1721 #define ASCV_RISC_FLAG_B (ushort)0x006A
1722 #define ASCV_REQ_SG_LIST_QP (ushort)0x006B
1723 #define ASC_HOST_FLAG_IN_ISR 0x01
1724 #define ASC_HOST_FLAG_ACK_INT 0x02
1725 #define ASC_RISC_FLAG_GEN_INT 0x01
1726 #define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1727 #define IOP_CTRL (0x0F)
1728 #define IOP_STATUS (0x0E)
1729 #define IOP_INT_ACK IOP_STATUS
1730 #define IOP_REG_IFC (0x0D)
1731 #define IOP_SYN_OFFSET (0x0B)
1732 #define IOP_EXTRA_CONTROL (0x0D)
1733 #define IOP_REG_PC (0x0C)
1734 #define IOP_RAM_ADDR (0x0A)
1735 #define IOP_RAM_DATA (0x08)
1736 #define IOP_EEP_DATA (0x06)
1737 #define IOP_EEP_CMD (0x07)
1738 #define IOP_VERSION (0x03)
1739 #define IOP_CONFIG_HIGH (0x04)
1740 #define IOP_CONFIG_LOW (0x02)
1741 #define IOP_SIG_BYTE (0x01)
1742 #define IOP_SIG_WORD (0x00)
1743 #define IOP_REG_DC1 (0x0E)
1744 #define IOP_REG_DC0 (0x0C)
1745 #define IOP_REG_SB (0x0B)
1746 #define IOP_REG_DA1 (0x0A)
1747 #define IOP_REG_DA0 (0x08)
1748 #define IOP_REG_SC (0x09)
1749 #define IOP_DMA_SPEED (0x07)
1750 #define IOP_REG_FLAG (0x07)
1751 #define IOP_FIFO_H (0x06)
1752 #define IOP_FIFO_L (0x04)
1753 #define IOP_REG_ID (0x05)
1754 #define IOP_REG_QP (0x03)
1755 #define IOP_REG_IH (0x02)
1756 #define IOP_REG_IX (0x01)
1757 #define IOP_REG_AX (0x00)
1758 #define IFC_REG_LOCK (0x00)
1759 #define IFC_REG_UNLOCK (0x09)
1760 #define IFC_WR_EN_FILTER (0x10)
1761 #define IFC_RD_NO_EEPROM (0x10)
1762 #define IFC_SLEW_RATE (0x20)
1763 #define IFC_ACT_NEG (0x40)
1764 #define IFC_INP_FILTER (0x80)
1765 #define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
1766 #define SC_SEL (uchar)(0x80)
1767 #define SC_BSY (uchar)(0x40)
1768 #define SC_ACK (uchar)(0x20)
1769 #define SC_REQ (uchar)(0x10)
1770 #define SC_ATN (uchar)(0x08)
1771 #define SC_IO (uchar)(0x04)
1772 #define SC_CD (uchar)(0x02)
1773 #define SC_MSG (uchar)(0x01)
1774 #define SEC_SCSI_CTL (uchar)(0x80)
1775 #define SEC_ACTIVE_NEGATE (uchar)(0x40)
1776 #define SEC_SLEW_RATE (uchar)(0x20)
1777 #define SEC_ENABLE_FILTER (uchar)(0x10)
1778 #define ASC_HALT_EXTMSG_IN (ushort)0x8000
1779 #define ASC_HALT_CHK_CONDITION (ushort)0x8100
1780 #define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
1781 #define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
1782 #define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
1783 #define ASC_HALT_SDTR_REJECTED (ushort)0x4000
1784 #define ASC_MAX_QNO 0xF8
1785 #define ASC_DATA_SEC_BEG (ushort)0x0080
1786 #define ASC_DATA_SEC_END (ushort)0x0080
1787 #define ASC_CODE_SEC_BEG (ushort)0x0080
1788 #define ASC_CODE_SEC_END (ushort)0x0080
1789 #define ASC_QADR_BEG (0x4000)
1790 #define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
1791 #define ASC_QADR_END (ushort)0x7FFF
1792 #define ASC_QLAST_ADR (ushort)0x7FC0
1793 #define ASC_QBLK_SIZE 0x40
1794 #define ASC_BIOS_DATA_QBEG 0xF8
1795 #define ASC_MIN_ACTIVE_QNO 0x01
1796 #define ASC_QLINK_END 0xFF
1797 #define ASC_EEPROM_WORDS 0x10
1798 #define ASC_MAX_MGS_LEN 0x10
1799 #define ASC_BIOS_ADDR_DEF 0xDC00
1800 #define ASC_BIOS_SIZE 0x3800
1801 #define ASC_BIOS_RAM_OFF 0x3800
1802 #define ASC_BIOS_RAM_SIZE 0x800
1803 #define ASC_BIOS_MIN_ADDR 0xC000
1804 #define ASC_BIOS_MAX_ADDR 0xEC00
1805 #define ASC_BIOS_BANK_SIZE 0x0400
1806 #define ASC_MCODE_START_ADDR 0x0080
1807 #define ASC_CFG0_HOST_INT_ON 0x0020
1808 #define ASC_CFG0_BIOS_ON 0x0040
1809 #define ASC_CFG0_VERA_BURST_ON 0x0080
1810 #define ASC_CFG0_SCSI_PARITY_ON 0x0800
1811 #define ASC_CFG1_SCSI_TARGET_ON 0x0080
1812 #define ASC_CFG1_LRAM_8BITS_ON 0x0800
1813 #define ASC_CFG_MSW_CLR_MASK 0x3080
1814 #define CSW_TEST1 (ASC_CS_TYPE)0x8000
1815 #define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
1816 #define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
1817 #define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
1818 #define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
1819 #define CSW_TEST2 (ASC_CS_TYPE)0x0400
1820 #define CSW_TEST3 (ASC_CS_TYPE)0x0200
1821 #define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
1822 #define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
1823 #define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
1824 #define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
1825 #define CSW_HALTED (ASC_CS_TYPE)0x0010
1826 #define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
1827 #define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
1828 #define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
1829 #define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
1830 #define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
1831 #define CIW_INT_ACK (ASC_CS_TYPE)0x0100
1832 #define CIW_TEST1 (ASC_CS_TYPE)0x0200
1833 #define CIW_TEST2 (ASC_CS_TYPE)0x0400
1834 #define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
1835 #define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
1836 #define CC_CHIP_RESET (uchar)0x80
1837 #define CC_SCSI_RESET (uchar)0x40
1838 #define CC_HALT (uchar)0x20
1839 #define CC_SINGLE_STEP (uchar)0x10
1840 #define CC_DMA_ABLE (uchar)0x08
1841 #define CC_TEST (uchar)0x04
1842 #define CC_BANK_ONE (uchar)0x02
1843 #define CC_DIAG (uchar)0x01
1844 #define ASC_1000_ID0W 0x04C1
1845 #define ASC_1000_ID0W_FIX 0x00C1
1846 #define ASC_1000_ID1B 0x25
1847 #define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50)
1848 #define ASC_EISA_SMALL_IOP_GAP (0x0020)
1849 #define ASC_EISA_MIN_IOP_ADDR (0x0C30)
1850 #define ASC_EISA_MAX_IOP_ADDR (0xFC50)
1851 #define ASC_EISA_REV_IOP_MASK (0x0C83)
1852 #define ASC_EISA_PID_IOP_MASK (0x0C80)
1853 #define ASC_EISA_CFG_IOP_MASK (0x0C86)
1854 #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
1855 #define ASC_EISA_ID_740 0x01745004UL
1856 #define ASC_EISA_ID_750 0x01755004UL
1857 #define INS_HALTINT (ushort)0x6281
1858 #define INS_HALT (ushort)0x6280
1859 #define INS_SINT (ushort)0x6200
1860 #define INS_RFLAG_WTM (ushort)0x7380
1861 #define ASC_MC_SAVE_CODE_WSIZE 0x500
1862 #define ASC_MC_SAVE_DATA_WSIZE 0x40
1864 typedef struct asc_mc_saved {
1865 ushort data[ASC_MC_SAVE_DATA_WSIZE];
1866 ushort code[ASC_MC_SAVE_CODE_WSIZE];
1867 } ASC_MC_SAVED;
1869 #define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
1870 #define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1871 #define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1872 #define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1873 #define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1874 #define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1875 #define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1876 #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1877 #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1878 #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1879 #define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)) ;
1880 #define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)) ;
1881 #define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data) ;
1882 #define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)) ;
1883 #define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1884 #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1885 #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1886 #define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1887 #define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1888 #define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1889 #define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1890 #define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1891 #define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1892 #define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1893 #define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1894 #define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1895 #define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1896 #define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1897 #define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1898 #define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1899 #define AscGetChipLramDataNoSwap(port) (ushort)inpw_noswap((port)+IOP_RAM_DATA)
1900 #define AscSetChipLramDataNoSwap(port, data) outpw_noswap((port)+IOP_RAM_DATA, data)
1901 #define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1902 #define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1903 #define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1904 #define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1905 #define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1906 #define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1907 #define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1908 #define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1909 #define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1910 #define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1911 #define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1912 #define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1913 #define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1914 #define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1915 #define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1916 #define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1917 #define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1918 #define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1919 #define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1920 #define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1921 #define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1922 #define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1923 #define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1924 #define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1925 #define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1926 #define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1927 #define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1928 #define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1929 #define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1930 #define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1931 #define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1932 #define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1933 #define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1934 #define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1935 #define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1936 #define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1937 #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1938 #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1940 STATIC int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1941 STATIC int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1942 STATIC void AscWaitEEPRead(void);
1943 STATIC void AscWaitEEPWrite(void);
1944 STATIC ushort AscReadEEPWord(PortAddr, uchar);
1945 STATIC ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1946 STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1947 STATIC int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1948 STATIC int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1949 STATIC int AscStartChip(PortAddr);
1950 STATIC int AscStopChip(PortAddr);
1951 STATIC void AscSetChipIH(PortAddr, ushort);
1952 STATIC int AscIsChipHalted(PortAddr);
1953 STATIC void AscAckInterrupt(PortAddr);
1954 STATIC void AscDisableInterrupt(PortAddr);
1955 STATIC void AscEnableInterrupt(PortAddr);
1956 STATIC void AscSetBank(PortAddr, uchar);
1957 STATIC int AscResetChipAndScsiBus(ASC_DVC_VAR *);
1958 STATIC ushort AscGetIsaDmaChannel(PortAddr);
1959 STATIC ushort AscSetIsaDmaChannel(PortAddr, ushort);
1960 STATIC uchar AscSetIsaDmaSpeed(PortAddr, uchar);
1961 STATIC uchar AscGetIsaDmaSpeed(PortAddr);
1962 STATIC uchar AscReadLramByte(PortAddr, ushort);
1963 STATIC ushort AscReadLramWord(PortAddr, ushort);
1964 STATIC ulong AscReadLramDWord(PortAddr, ushort);
1965 STATIC void AscWriteLramWord(PortAddr, ushort, ushort);
1966 STATIC void AscWriteLramDWord(PortAddr, ushort, ulong);
1967 STATIC void AscWriteLramByte(PortAddr, ushort, uchar);
1968 STATIC ulong AscMemSumLramWord(PortAddr, ushort, rint);
1969 STATIC void AscMemWordSetLram(PortAddr, ushort, ushort, rint);
1970 STATIC void AscMemWordCopyToLram(PortAddr, ushort, ushort *, int);
1971 STATIC void AscMemDWordCopyToLram(PortAddr, ushort, ulong *, int);
1972 STATIC void AscMemWordCopyFromLram(PortAddr, ushort, ushort *, int);
1973 STATIC ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1974 STATIC ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
1975 STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1976 STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
1977 STATIC int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
1978 STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
1979 STATIC uchar AscCalSDTRData(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
1980 STATIC void AscSetChipSDTR(PortAddr, uchar, uchar);
1981 STATIC uchar AscGetSynPeriodIndex(ASC_DVC_VAR asc_ptr_type *, ruchar);
1982 STATIC uchar AscAllocFreeQueue(PortAddr, uchar);
1983 STATIC uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1984 STATIC int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
1985 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
1986 STATIC int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
1987 #endif /* version >= v1.3.89 */
1988 STATIC int AscHostReqRiscHalt(PortAddr);
1989 STATIC int AscStopQueueExe(PortAddr);
1990 STATIC int AscStartQueueExe(PortAddr);
1991 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
1992 STATIC int AscCleanUpDiscQueue(PortAddr);
1993 #endif /* version >= v1.3.89 */
1994 STATIC int AscCleanUpBusyQueue(PortAddr);
1995 STATIC int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
1996 STATIC int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
1997 STATIC ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar *,
1998 ulong);
1999 STATIC int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
2000 ASC_SCSI_Q * scsiq,
2001 uchar n_q_required);
2002 STATIC int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *,
2003 ASC_SCSI_Q *, uchar);
2004 STATIC int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
2005 ASC_SCSI_Q *, uchar);
2006 STATIC int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
2007 STATIC int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
2008 STATIC ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *);
2009 STATIC int AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
2010 STATIC ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
2011 STATIC int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
2012 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2013 STATIC int _AscWaitQDone(PortAddr, ASC_SCSI_Q *);
2014 #endif /* version >= v1.3.89 */
2015 STATIC int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
2016 STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
2017 ASC_QDONE_INFO *, ulong);
2018 STATIC int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
2019 STATIC int AscCompareString(uchar *, uchar *, int);
2020 STATIC ushort AscGetEisaChipCfg(PortAddr);
2021 STATIC ulong AscGetEisaProductID(PortAddr);
2022 STATIC PortAddr AscSearchIOPortAddrEISA(PortAddr);
2023 STATIC uchar AscGetChipScsiCtrl(PortAddr);
2024 STATIC uchar AscSetChipScsiID(PortAddr, uchar);
2025 STATIC uchar AscGetChipVersion(PortAddr, ushort);
2026 STATIC ushort AscGetChipBusType(PortAddr);
2027 STATIC ulong AscLoadMicroCode(PortAddr, ushort, ushort *, ushort);
2028 STATIC int AscFindSignature(PortAddr);
2029 STATIC PortAddr AscSearchIOPortAddr11(PortAddr);
2030 STATIC void AscToggleIRQAct(PortAddr);
2031 STATIC void AscSetISAPNPWaitForKey(void);
2032 STATIC uchar AscGetChipIRQ(PortAddr, ushort);
2033 STATIC uchar AscSetChipIRQ(PortAddr, uchar, ushort);
2034 STATIC ushort AscGetChipBiosAddress(PortAddr, ushort);
2035 STATIC int DvcEnterCritical(void);
2036 STATIC void DvcLeaveCritical(int);
2037 STATIC void DvcInPortWords(PortAddr, ushort *, int);
2038 STATIC void DvcOutPortWords(PortAddr, ushort *, int);
2039 STATIC void DvcOutPortDWords(PortAddr, ulong *, int);
2040 STATIC uchar DvcReadPCIConfigByte(ASC_DVC_VAR asc_ptr_type *, ushort);
2041 STATIC void DvcWritePCIConfigByte(ASC_DVC_VAR asc_ptr_type *,
2042 ushort, uchar);
2043 STATIC ushort AscGetChipBiosAddress(PortAddr, ushort);
2044 STATIC void DvcSleepMilliSecond(ulong);
2045 STATIC void DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type *, ulong);
2046 STATIC ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar *,
2047 ulong, ASC_SG_HEAD *);
2048 STATIC void DvcPutScsiQ(PortAddr, ushort, ushort *, int);
2049 STATIC void DvcGetQinfo(PortAddr, ushort, ushort *, int);
2050 STATIC PortAddr AscSearchIOPortAddr(PortAddr, ushort);
2051 STATIC ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
2052 STATIC ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
2053 STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
2054 STATIC void AscAsyncFix(ASC_DVC_VAR asc_ptr_type *, uchar,
2055 ASC_SCSI_INQUIRY *);
2056 STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
2057 STATIC void AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *,
2058 uchar, ASC_SCSI_INQUIRY *);
2059 STATIC int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
2060 STATIC int AscISR(ASC_DVC_VAR asc_ptr_type *);
2061 STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar,
2062 uchar);
2063 STATIC int AscSgListToQueue(int);
2064 STATIC int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
2065 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2066 STATIC int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
2067 #endif /* version >= v1.3.89 */
2068 STATIC int AscResetSB(ASC_DVC_VAR asc_ptr_type *);
2069 STATIC void AscEnableIsaDma(uchar);
2070 STATIC ulong AscGetMaxDmaCount(ushort);
2074 * --- Adv Library Constants and Macros
2077 #define ADV_LIB_VERSION_MAJOR 3
2078 #define ADV_LIB_VERSION_MINOR 45
2080 /* d_os_dep.h */
2081 #define ADV_OS_LINUX
2084 * Define Adv Library required special types.
2086 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
2087 #define AdvPortAddr unsigned short /* I/O Port address size */
2088 #else /* version >= v1,3,0 */
2089 #define AdvPortAddr unsigned long /* Virtual memory address size */
2090 #endif /* version >= v1,3,0 */
2093 * Define Adv Library required memory access macros.
2095 #define ADV_MEM_READB(addr) readb(addr)
2096 #define ADV_MEM_READW(addr) readw(addr)
2097 #define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
2098 #define ADV_MEM_WRITEW(addr, word) writew(word, addr)
2101 * The I/O memory mapping function names changed in 2.1.X.
2103 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
2104 #define ioremap vremap
2105 #define iounmap vfree
2106 #endif /* version < v2.1.0 */
2109 * Define total number of simultaneous maximum element scatter-gather
2110 * requests, i.e. ADV_TOT_SG_LIST * ADV_MAX_SG_LIST is the total number
2111 * of simultaneous scatter-gather elements supported per wide adapter.
2113 #define ADV_TOT_SG_LIST 64
2116 * Define Adv Library required per request scatter-gather element limit.
2118 #define ADV_MAX_SG_LIST 64
2121 * Scatter-Gather Definitions per request.
2123 * Because SG block memory is allocated in virtual memory but is
2124 * referenced by the microcode as physical memory, we need to do
2125 * calculations to insure there will be enough physically contiguous
2126 * memory to support ADV_MAX_SG_LIST SG entries.
2129 /* Number of SG blocks needed. */
2130 #define ADV_NUM_SG_BLOCK \
2131 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
2133 /* Total contiguous memory needed for SG blocks. */
2134 #define ADV_SG_TOTAL_MEM_SIZE \
2135 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
2137 #define ASC_PAGE_SIZE PAGE_SIZE
2140 * Number of page crossings possible for the total contiguous virtual memory
2141 * needed for SG blocks.
2143 * We need to allocate this many additional SG blocks in virtual memory to
2144 * insure there will be space for ADV_NUM_SG_BLOCK physically contiguous
2145 * scatter-gather blocks.
2147 #define ADV_NUM_PAGE_CROSSING \
2148 ((ADV_SG_TOTAL_MEM_SIZE + (ASC_PAGE_SIZE - 1))/ASC_PAGE_SIZE)
2151 * Define Adv Library Assertion Macro.
2154 #define ADV_ASSERT(a) ASC_ASSERT(a)
2156 /* a_condor.h */
2157 #define ADV_PCI_VENDOR_ID 0x10CD
2158 #define ADV_PCI_DEVICE_ID_REV_A 0x2300
2160 #define ASC_EEP_DVC_CFG_BEGIN (0x00)
2161 #define ASC_EEP_DVC_CFG_END (0x15)
2162 #define ASC_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
2163 #define ASC_EEP_MAX_WORD_ADDR (0x1E)
2165 #define ASC_EEP_DELAY_MS 100
2168 * EEPROM bits reference by the RISC after initialization.
2170 #define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
2171 #define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
2172 #define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
2175 * EEPROM configuration format
2177 * Field naming convention:
2179 * *_enable indicates the field enables or disables the feature. The
2180 * value is never reset.
2182 * *_able indicates both whether a feature should be enabled or disabled
2183 * and whether a device isi capable of the feature. At initialization
2184 * this field may be set, but later if a device is found to be incapable
2185 * of the feature, the field is cleared.
2187 * Default values are maintained in a_init.c in the structure
2188 * Default_EEPROM_Config.
2190 typedef struct adveep_config
2192 /* Word Offset, Description */
2194 ushort cfg_lsw; /* 00 power up initialization */
2195 /* bit 13 set - Term Polarity Control */
2196 /* bit 14 set - BIOS Enable */
2197 /* bit 15 set - Big Endian Mode */
2198 ushort cfg_msw; /* 01 unused */
2199 ushort disc_enable; /* 02 disconnect enable */
2200 ushort wdtr_able; /* 03 Wide DTR able */
2201 ushort sdtr_able; /* 04 Synchronous DTR able */
2202 ushort start_motor; /* 05 send start up motor */
2203 ushort tagqng_able; /* 06 tag queuing able */
2204 ushort bios_scan; /* 07 BIOS device control */
2205 ushort scam_tolerant; /* 08 no scam */
2207 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2208 uchar bios_boot_delay; /* power up wait */
2210 uchar scsi_reset_delay; /* 10 reset delay */
2211 uchar bios_id_lun; /* first boot device scsi id & lun */
2212 /* high nibble is lun */
2213 /* low nibble is scsi id */
2215 uchar termination; /* 11 0 - automatic */
2216 /* 1 - low off / high off */
2217 /* 2 - low off / high on */
2218 /* 3 - low on / high on */
2219 /* There is no low on / high off */
2221 uchar reserved1; /* reserved byte (not used) */
2223 ushort bios_ctrl; /* 12 BIOS control bits */
2224 /* bit 0 set: BIOS don't act as initiator. */
2225 /* bit 1 set: BIOS > 1 GB support */
2226 /* bit 2 set: BIOS > 2 Disk Support */
2227 /* bit 3 set: BIOS don't support removables */
2228 /* bit 4 set: BIOS support bootable CD */
2229 /* bit 5 set: */
2230 /* bit 6 set: BIOS support multiple LUNs */
2231 /* bit 7 set: BIOS display of message */
2232 /* bit 8 set: */
2233 /* bit 9 set: Reset SCSI bus during init. */
2234 /* bit 10 set: */
2235 /* bit 11 set: No verbose initialization. */
2236 /* bit 12 set: SCSI parity enabled */
2237 /* bit 13 set: */
2238 /* bit 14 set: */
2239 /* bit 15 set: */
2240 ushort ultra_able; /* 13 ULTRA speed able */
2241 ushort reserved2; /* 14 reserved */
2242 uchar max_host_qng; /* 15 maximum host queuing */
2243 uchar max_dvc_qng; /* maximum per device queuing */
2244 ushort dvc_cntl; /* 16 control bit for driver */
2245 ushort bug_fix; /* 17 control bit for bug fix */
2246 ushort serial_number_word1; /* 18 Board serial number word 1 */
2247 ushort serial_number_word2; /* 19 Board serial number word 2 */
2248 ushort serial_number_word3; /* 20 Board serial number word 3 */
2249 ushort check_sum; /* 21 EEP check sum */
2250 uchar oem_name[16]; /* 22 OEM name */
2251 ushort dvc_err_code; /* 30 last device driver error code */
2252 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2253 ushort adv_err_addr; /* 32 last uc error address */
2254 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2255 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2256 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2257 ushort num_of_err; /* 36 number of error */
2258 } ADVEEP_CONFIG;
2261 * EEPROM Commands
2263 #define ASC_EEP_CMD_DONE 0x0200
2264 #define ASC_EEP_CMD_DONE_ERR 0x0001
2266 /* cfg_word */
2267 #define EEP_CFG_WORD_BIG_ENDIAN 0x8000
2269 /* bios_ctrl */
2270 #define BIOS_CTRL_BIOS 0x0001
2271 #define BIOS_CTRL_EXTENDED_XLAT 0x0002
2272 #define BIOS_CTRL_GT_2_DISK 0x0004
2273 #define BIOS_CTRL_BIOS_REMOVABLE 0x0008
2274 #define BIOS_CTRL_BOOTABLE_CD 0x0010
2275 #define BIOS_CTRL_MULTIPLE_LUN 0x0040
2276 #define BIOS_CTRL_DISPLAY_MSG 0x0080
2277 #define BIOS_CTRL_NO_SCAM 0x0100
2278 #define BIOS_CTRL_RESET_SCSI_BUS 0x0200
2279 #define BIOS_CTRL_INIT_VERBOSE 0x0800
2280 #define BIOS_CTRL_SCSI_PARITY 0x1000
2283 * ASC 3550 Internal Memory Size - 8KB
2285 #define ADV_CONDOR_MEMSIZE 0x2000 /* 8 KB Internal Memory */
2288 * ASC 3550 I/O Length - 64 bytes
2290 #define ADV_CONDOR_IOLEN 0x40 /* I/O Port Range in bytes */
2293 * Byte I/O register address from base of 'iop_base'.
2295 #define IOPB_INTR_STATUS_REG 0x00
2296 #define IOPB_CHIP_ID_1 0x01
2297 #define IOPB_INTR_ENABLES 0x02
2298 #define IOPB_CHIP_TYPE_REV 0x03
2299 #define IOPB_RES_ADDR_4 0x04
2300 #define IOPB_RES_ADDR_5 0x05
2301 #define IOPB_RAM_DATA 0x06
2302 #define IOPB_RES_ADDR_7 0x07
2303 #define IOPB_FLAG_REG 0x08
2304 #define IOPB_RES_ADDR_9 0x09
2305 #define IOPB_RISC_CSR 0x0A
2306 #define IOPB_RES_ADDR_B 0x0B
2307 #define IOPB_RES_ADDR_C 0x0C
2308 #define IOPB_RES_ADDR_D 0x0D
2309 #define IOPB_RES_ADDR_E 0x0E
2310 #define IOPB_RES_ADDR_F 0x0F
2311 #define IOPB_MEM_CFG 0x10
2312 #define IOPB_RES_ADDR_11 0x11
2313 #define IOPB_RES_ADDR_12 0x12
2314 #define IOPB_RES_ADDR_13 0x13
2315 #define IOPB_FLASH_PAGE 0x14
2316 #define IOPB_RES_ADDR_15 0x15
2317 #define IOPB_RES_ADDR_16 0x16
2318 #define IOPB_RES_ADDR_17 0x17
2319 #define IOPB_FLASH_DATA 0x18
2320 #define IOPB_RES_ADDR_19 0x19
2321 #define IOPB_RES_ADDR_1A 0x1A
2322 #define IOPB_RES_ADDR_1B 0x1B
2323 #define IOPB_RES_ADDR_1C 0x1C
2324 #define IOPB_RES_ADDR_1D 0x1D
2325 #define IOPB_RES_ADDR_1E 0x1E
2326 #define IOPB_RES_ADDR_1F 0x1F
2327 #define IOPB_DMA_CFG0 0x20
2328 #define IOPB_DMA_CFG1 0x21
2329 #define IOPB_TICKLE 0x22
2330 #define IOPB_DMA_REG_WR 0x23
2331 #define IOPB_SDMA_STATUS 0x24
2332 #define IOPB_SCSI_BYTE_CNT 0x25
2333 #define IOPB_HOST_BYTE_CNT 0x26
2334 #define IOPB_BYTE_LEFT_TO_XFER 0x27
2335 #define IOPB_BYTE_TO_XFER_0 0x28
2336 #define IOPB_BYTE_TO_XFER_1 0x29
2337 #define IOPB_BYTE_TO_XFER_2 0x2A
2338 #define IOPB_BYTE_TO_XFER_3 0x2B
2339 #define IOPB_ACC_GRP 0x2C
2340 #define IOPB_RES_ADDR_2D 0x2D
2341 #define IOPB_DEV_ID 0x2E
2342 #define IOPB_RES_ADDR_2F 0x2F
2343 #define IOPB_SCSI_DATA 0x30
2344 #define IOPB_RES_ADDR_31 0x31
2345 #define IOPB_RES_ADDR_32 0x32
2346 #define IOPB_SCSI_DATA_HSHK 0x33
2347 #define IOPB_SCSI_CTRL 0x34
2348 #define IOPB_RES_ADDR_35 0x35
2349 #define IOPB_RES_ADDR_36 0x36
2350 #define IOPB_RES_ADDR_37 0x37
2351 #define IOPB_RES_ADDR_38 0x38
2352 #define IOPB_RES_ADDR_39 0x39
2353 #define IOPB_RES_ADDR_3A 0x3A
2354 #define IOPB_RES_ADDR_3B 0x3B
2355 #define IOPB_RFIFO_CNT 0x3C
2356 #define IOPB_RES_ADDR_3D 0x3D
2357 #define IOPB_RES_ADDR_3E 0x3E
2358 #define IOPB_RES_ADDR_3F 0x3F
2361 * Word I/O register address from base of 'iop_base'.
2363 #define IOPW_CHIP_ID_0 0x00 /* CID0 */
2364 #define IOPW_CTRL_REG 0x02 /* CC */
2365 #define IOPW_RAM_ADDR 0x04 /* LA */
2366 #define IOPW_RAM_DATA 0x06 /* LD */
2367 #define IOPW_RES_ADDR_08 0x08
2368 #define IOPW_RISC_CSR 0x0A /* CSR */
2369 #define IOPW_SCSI_CFG0 0x0C /* CFG0 */
2370 #define IOPW_SCSI_CFG1 0x0E /* CFG1 */
2371 #define IOPW_RES_ADDR_10 0x10
2372 #define IOPW_SEL_MASK 0x12 /* SM */
2373 #define IOPW_RES_ADDR_14 0x14
2374 #define IOPW_FLASH_ADDR 0x16 /* FA */
2375 #define IOPW_RES_ADDR_18 0x18
2376 #define IOPW_EE_CMD 0x1A /* EC */
2377 #define IOPW_EE_DATA 0x1C /* ED */
2378 #define IOPW_SFIFO_CNT 0x1E /* SFC */
2379 #define IOPW_RES_ADDR_20 0x20
2380 #define IOPW_Q_BASE 0x22 /* QB */
2381 #define IOPW_QP 0x24 /* QP */
2382 #define IOPW_IX 0x26 /* IX */
2383 #define IOPW_SP 0x28 /* SP */
2384 #define IOPW_PC 0x2A /* PC */
2385 #define IOPW_RES_ADDR_2C 0x2C
2386 #define IOPW_RES_ADDR_2E 0x2E
2387 #define IOPW_SCSI_DATA 0x30 /* SD */
2388 #define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
2389 #define IOPW_SCSI_CTRL 0x34 /* SC */
2390 #define IOPW_HSHK_CFG 0x36 /* HCFG */
2391 #define IOPW_SXFR_STATUS 0x36 /* SXS */
2392 #define IOPW_SXFR_CNTL 0x38 /* SXL */
2393 #define IOPW_SXFR_CNTH 0x3A /* SXH */
2394 #define IOPW_RES_ADDR_3C 0x3C
2395 #define IOPW_RFIFO_DATA 0x3E /* RFD */
2398 * Doubleword I/O register address from base of 'iop_base'.
2400 #define IOPDW_RES_ADDR_0 0x00
2401 #define IOPDW_RAM_DATA 0x04
2402 #define IOPDW_RES_ADDR_8 0x08
2403 #define IOPDW_RES_ADDR_C 0x0C
2404 #define IOPDW_RES_ADDR_10 0x10
2405 #define IOPDW_RES_ADDR_14 0x14
2406 #define IOPDW_RES_ADDR_18 0x18
2407 #define IOPDW_RES_ADDR_1C 0x1C
2408 #define IOPDW_SDMA_ADDR0 0x20
2409 #define IOPDW_SDMA_ADDR1 0x24
2410 #define IOPDW_SDMA_COUNT 0x28
2411 #define IOPDW_SDMA_ERROR 0x2C
2412 #define IOPDW_RDMA_ADDR0 0x30
2413 #define IOPDW_RDMA_ADDR1 0x34
2414 #define IOPDW_RDMA_COUNT 0x38
2415 #define IOPDW_RDMA_ERROR 0x3C
2417 #define ADV_CHIP_ID_BYTE 0x25
2418 #define ADV_CHIP_ID_WORD 0x04C1
2420 #define ADV_SC_SCSI_BUS_RESET 0x2000
2422 #define ADV_INTR_ENABLE_HOST_INTR 0x01
2423 #define ADV_INTR_ENABLE_SEL_INTR 0x02
2424 #define ADV_INTR_ENABLE_DPR_INTR 0x04
2425 #define ADV_INTR_ENABLE_RTA_INTR 0x08
2426 #define ADV_INTR_ENABLE_RMA_INTR 0x10
2427 #define ADV_INTR_ENABLE_RST_INTR 0x20
2428 #define ADV_INTR_ENABLE_DPE_INTR 0x40
2429 #define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
2431 #define ADV_INTR_STATUS_INTRA 0x01
2432 #define ADV_INTR_STATUS_INTRB 0x02
2433 #define ADV_INTR_STATUS_INTRC 0x04
2435 #define ADV_RISC_CSR_STOP (0x0000)
2436 #define ADV_RISC_TEST_COND (0x2000)
2437 #define ADV_RISC_CSR_RUN (0x4000)
2438 #define ADV_RISC_CSR_SINGLE_STEP (0x8000)
2440 #define ADV_CTRL_REG_HOST_INTR 0x0100
2441 #define ADV_CTRL_REG_SEL_INTR 0x0200
2442 #define ADV_CTRL_REG_DPR_INTR 0x0400
2443 #define ADV_CTRL_REG_RTA_INTR 0x0800
2444 #define ADV_CTRL_REG_RMA_INTR 0x1000
2445 #define ADV_CTRL_REG_RES_BIT14 0x2000
2446 #define ADV_CTRL_REG_DPE_INTR 0x4000
2447 #define ADV_CTRL_REG_POWER_DONE 0x8000
2448 #define ADV_CTRL_REG_ANY_INTR 0xFF00
2450 #define ADV_CTRL_REG_CMD_RESET 0x00C6
2451 #define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
2452 #define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
2453 #define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
2454 #define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
2456 #define ADV_SCSI_CTRL_RSTOUT 0x2000
2458 #define AdvIsIntPending(port) \
2459 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
2462 * SCSI_CFG0 Register bit definitions
2464 #define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
2465 #define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
2466 #define EVEN_PARITY 0x1000 /* Select Even Parity */
2467 #define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
2468 #define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
2469 #define PRIM_MODE 0x0100 /* Primitive SCSI mode */
2470 #define SCAM_EN 0x0080 /* Enable SCAM selection */
2471 #define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
2472 #define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
2473 #define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
2474 #define OUR_ID 0x000F /* SCSI ID */
2477 * SCSI_CFG1 Register bit definitions
2479 #define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
2480 #define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
2481 #define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
2482 #define FILTER_SEL 0x0C00 /* Filter Period Selection */
2483 #define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
2484 #define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
2485 #define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
2486 #define ACTIVE_DBL 0x0200 /* Disable Active Negation */
2487 #define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
2488 #define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
2489 #define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
2490 #define TERM_CTL 0x0030 /* External SCSI Termination Bits */
2491 #define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
2492 #define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
2493 #define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
2495 #define CABLE_ILLEGAL_A 0x7
2496 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
2498 #define CABLE_ILLEGAL_B 0xB
2499 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
2502 The following table details the SCSI_CFG1 Termination Polarity,
2503 Termination Control and Cable Detect bits.
2505 Cable Detect | Termination
2506 Bit 3 2 1 0 | 5 4 | Notes
2507 _____________|________|____________________
2508 1 1 1 0 | on on | Internal wide only
2509 1 1 0 1 | on on | Internal narrow only
2510 1 0 1 1 | on on | External narrow only
2511 0 x 1 1 | on on | External wide only
2512 1 1 0 0 | on off| Internal wide and internal narrow
2513 1 0 1 0 | on off| Internal wide and external narrow
2514 0 x 1 0 | off off| Internal wide and external wide
2515 1 0 0 1 | on off| Internal narrow and external narrow
2516 0 x 0 1 | on off| Internal narrow and external wide
2517 1 1 1 1 | on on | No devices are attached
2518 x 0 0 0 | on on | Illegal (all 3 connectors are used)
2519 0 x 0 0 | on on | Illegal (all 3 connectors are used)
2521 x means don't-care (either '0' or '1')
2523 If term_pol (bit 13) is '0' (active-low terminator enable), then:
2524 'on' is '0' and 'off' is '1'.
2526 If term_pol bit is '1' (meaning active-hi terminator enable), then:
2527 'on' is '1' and 'off' is '0'.
2531 * MEM_CFG Register bit definitions
2533 #define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
2534 #define FAST_EE_CLK 0x20 /* Diagnostic Bit */
2535 #define RAM_SZ 0x1C /* Specify size of RAM to RISC */
2536 #define RAM_SZ_2KB 0x00 /* 2 KB */
2537 #define RAM_SZ_4KB 0x04 /* 4 KB */
2538 #define RAM_SZ_8KB 0x08 /* 8 KB */
2539 #define RAM_SZ_16KB 0x0C /* 16 KB */
2540 #define RAM_SZ_32KB 0x10 /* 32 KB */
2541 #define RAM_SZ_64KB 0x14 /* 64 KB */
2544 * DMA_CFG0 Register bit definitions
2546 * This register is only accessible to the host.
2548 #define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
2549 #define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
2550 #define FIFO_THRESH_16B 0x00 /* 16 bytes */
2551 #define FIFO_THRESH_32B 0x20 /* 32 bytes */
2552 #define FIFO_THRESH_48B 0x30 /* 48 bytes */
2553 #define FIFO_THRESH_64B 0x40 /* 64 bytes */
2554 #define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
2555 #define FIFO_THRESH_96B 0x60 /* 96 bytes */
2556 #define FIFO_THRESH_112B 0x70 /* 112 bytes */
2557 #define START_CTL 0x0C /* DMA start conditions */
2558 #define START_CTL_TH 0x00 /* Wait threshold level (default) */
2559 #define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
2560 #define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
2561 #define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
2562 #define READ_CMD 0x03 /* Memory Read Method */
2563 #define READ_CMD_MR 0x00 /* Memory Read */
2564 #define READ_CMD_MRL 0x02 /* Memory Read Long */
2565 #define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
2567 /* a_advlib.h */
2570 * Adv Library Status Definitions
2572 #define ADV_TRUE 1
2573 #define ADV_FALSE 0
2574 #define ADV_NOERROR 1
2575 #define ADV_SUCCESS 1
2576 #define ADV_BUSY 0
2577 #define ADV_ERROR (-1)
2581 * ASC_DVC_VAR 'warn_code' values
2583 #define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
2584 #define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
2585 #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
2586 #define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
2588 #define ADV_MAX_TID 15 /* max. target identifier */
2589 #define ADV_MAX_LUN 7 /* max. logical unit number */
2593 * AscInitGetConfig() and AscInitAsc1000Driver() Definitions
2595 * Error code values are set in ASC_DVC_VAR 'err_code'.
2597 #define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
2598 #define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
2599 #define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
2600 #define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
2601 #define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
2602 #define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
2603 #define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
2604 #define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
2605 #define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
2606 #define ASC_IERR_RW_LRAM 0x8000 /* read/write local RAM error */
2609 * Fixed locations of microcode operating variables.
2611 #define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
2612 #define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
2613 #define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
2614 #define ASC_MC_STACK_BEGIN 0x002E /* microcode stack begin */
2615 #define ASC_MC_STACK_END 0x0030 /* microcode stack end */
2616 #define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
2617 #define ASC_MC_VERSION_NUM 0x003A /* microcode number */
2618 #define ASCV_VER_SERIAL_W 0x003C /* used in dos_init */
2619 #define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
2620 #define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
2621 #define ASC_MC_HALTCODE 0x0094 /* microcode halt code */
2622 #define ASC_MC_CALLERPC 0x0096 /* microcode halt caller PC */
2623 #define ASC_MC_ADAPTER_SCSI_ID 0x0098 /* one ID byte + reserved */
2624 #define ASC_MC_ULTRA_ABLE 0x009C
2625 #define ASC_MC_SDTR_ABLE 0x009E
2626 #define ASC_MC_TAGQNG_ABLE 0x00A0
2627 #define ASC_MC_DISC_ENABLE 0x00A2
2628 #define ASC_MC_IDLE_CMD 0x00A6
2629 #define ASC_MC_IDLE_PARA_STAT 0x00A8
2630 #define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
2631 #define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
2632 #define ASC_MC_DEFAULT_MEM_CFG 0x00B0
2633 #define ASC_MC_DEFAULT_SEL_MASK 0x00B2
2634 #define ASC_MC_RISC_NEXT_READY 0x00B4
2635 #define ASC_MC_RISC_NEXT_DONE 0x00B5
2636 #define ASC_MC_SDTR_DONE 0x00B6
2637 #define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
2638 #define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
2639 #define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
2640 #define ASC_MC_WDTR_ABLE 0x0120 /* Wide Transfer TID bitmask. */
2641 #define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
2642 #define ASC_MC_WDTR_DONE 0x0124
2643 #define ASC_MC_HOST_NEXT_READY 0x0128 /* Host Next Ready RQL Entry. */
2644 #define ASC_MC_HOST_NEXT_DONE 0x0129 /* Host Next Done RQL Entry. */
2647 * BIOS LRAM variable absolute offsets.
2649 #define BIOS_CODESEG 0x54
2650 #define BIOS_CODELEN 0x56
2651 #define BIOS_SIGNATURE 0x58
2652 #define BIOS_VERSION 0x5A
2653 #define BIOS_SIGNATURE 0x58
2656 * Microcode Control Flags
2658 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
2659 * and handled by the microcode.
2661 #define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
2664 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
2666 #define HSHK_CFG_WIDE_XFR 0x8000
2667 #define HSHK_CFG_RATE 0x0F00
2668 #define HSHK_CFG_OFFSET 0x001F
2671 * LRAM RISC Queue Lists (LRAM addresses 0x1200 - 0x19FF)
2673 * Each of the 255 Adv Library/Microcode RISC queue lists or mailboxes
2674 * starting at LRAM address 0x1200 is 8 bytes and has the following
2675 * structure. Only 253 of these are actually used for command queues.
2678 #define ASC_MC_RISC_Q_LIST_BASE 0x1200
2679 #define ASC_MC_RISC_Q_LIST_SIZE 0x0008
2680 #define ASC_MC_RISC_Q_TOTAL_CNT 0x00FF /* Num. queue slots in LRAM. */
2681 #define ASC_MC_RISC_Q_FIRST 0x0001
2682 #define ASC_MC_RISC_Q_LAST 0x00FF
2684 #define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
2685 #define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
2686 #define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
2687 #define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
2689 /* RISC Queue List structure - 8 bytes */
2690 #define RQL_FWD 0 /* forward pointer (1 byte) */
2691 #define RQL_BWD 1 /* backward pointer (1 byte) */
2692 #define RQL_STATE 2 /* state byte - free, ready, done, aborted (1 byte) */
2693 #define RQL_TID 3 /* request target id (1 byte) */
2694 #define RQL_PHYADDR 4 /* request physical pointer (4 bytes) */
2696 /* RISC Queue List state values */
2697 #define ASC_MC_QS_FREE 0x00
2698 #define ASC_MC_QS_READY 0x01
2699 #define ASC_MC_QS_DONE 0x40
2700 #define ASC_MC_QS_ABORTED 0x80
2702 /* RISC Queue List pointer values */
2703 #define ASC_MC_NULL_Q 0x00 /* NULL_Q == 0 */
2704 #define ASC_MC_BIOS_Q 0xFF /* BIOS_Q = 255 */
2706 /* ASC_SCSI_REQ_Q 'cntl' field values */
2707 #define ASC_MC_QC_START_MOTOR 0x02 /* Issue start motor. */
2708 #define ASC_MC_QC_NO_OVERRUN 0x04 /* Don't report overrun. */
2709 #define ASC_MC_QC_FIRST_DMA 0x08 /* Internal microcode flag. */
2710 #define ASC_MC_QC_ABORTED 0x10 /* Request aborted by host. */
2711 #define ASC_MC_QC_REQ_SENSE 0x20 /* Auto-Request Sense. */
2712 #define ASC_MC_QC_DOS_REQ 0x80 /* Request issued by DOS. */
2716 * ASC_SCSI_REQ_Q 'a_flag' definitions
2718 * The Adv Library should limit use to the lower nibble (4 bits) of
2719 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2721 #define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2722 #define ADV_SCSIQ_DONE 0x02 /* request done */
2725 * Adapter temporary configuration structure
2727 * This structure can be discarded after initialization. Don't add
2728 * fields here needed after initialization.
2730 * Field naming convention:
2732 * *_enable indicates the field enables or disables a feature. The
2733 * value of the field is never reset.
2735 typedef struct adv_dvc_cfg {
2736 ushort disc_enable; /* enable disconnection */
2737 uchar chip_version; /* chip version */
2738 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2739 ushort pci_device_id; /* PCI device code number */
2740 ushort lib_version; /* Adv Library version number */
2741 ushort control_flag; /* Microcode Control Flag */
2742 ushort mcode_date; /* Microcode date */
2743 ushort mcode_version; /* Microcode version */
2744 ushort pci_slot_info; /* high byte device/function number */
2745 /* bits 7-3 device num., bits 2-0 function num. */
2746 /* low byte bus num. */
2747 ushort bios_boot_wait; /* BIOS boot time delay */
2748 ushort serial1; /* EEPROM serial number word 1 */
2749 ushort serial2; /* EEPROM serial number word 2 */
2750 ushort serial3; /* EEPROM serial number word 3 */
2751 } ADV_DVC_CFG;
2754 * Adapter operation variable structure.
2756 * One structure is required per host adapter.
2758 * Field naming convention:
2760 * *_able indicates both whether a feature should be enabled or disabled
2761 * and whether a device isi capable of the feature. At initialization
2762 * this field may be set, but later if a device is found to be incapable
2763 * of the feature, the field is cleared.
2765 typedef struct adv_dvc_var {
2766 AdvPortAddr iop_base; /* I/O port address */
2767 ushort err_code; /* fatal error code */
2768 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
2769 Ptr2Func isr_callback; /* pointer to function, called in AdvISR() */
2770 Ptr2Func sbreset_callback; /* pointer to function, called in AdvISR() */
2771 ushort wdtr_able; /* try WDTR for a device */
2772 ushort sdtr_able; /* try SDTR for a device */
2773 ushort ultra_able; /* try SDTR Ultra speed for a device */
2774 ushort tagqng_able; /* try tagged queuing with a device */
2775 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2776 ushort start_motor; /* start motor command allowed */
2777 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2778 uchar chip_no; /* should be assigned by caller */
2779 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2780 uchar cur_host_qng; /* total number of queue command */
2781 uchar irq_no; /* IRQ number */
2782 ushort no_scam; /* scam_tolerant of EEPROM */
2783 ushort idle_cmd_done; /* microcode idle command done set by AdvISR() */
2784 ulong drv_ptr; /* driver pointer to private structure */
2785 uchar chip_scsi_id; /* chip SCSI target ID */
2787 * Note: The following fields will not be used after initialization. The
2788 * driver may discard the buffer after initialization is done.
2790 ADV_DVC_CFG *cfg; /* temporary configuration structure */
2791 } ADV_DVC_VAR;
2793 #define NO_OF_SG_PER_BLOCK 15
2795 typedef struct asc_sg_block {
2796 uchar reserved1;
2797 uchar reserved2;
2798 uchar first_entry_no; /* starting entry number */
2799 uchar last_entry_no; /* last entry number */
2800 struct asc_sg_block *sg_ptr; /* links to the next sg block */
2801 struct {
2802 ulong sg_addr; /* SG element address */
2803 ulong sg_count; /* SG element count */
2804 } sg_list[NO_OF_SG_PER_BLOCK];
2805 } ADV_SG_BLOCK;
2808 * ASC_SCSI_REQ_Q - microcode request structure
2810 * All fields in this structure up to byte 60 are used by the microcode.
2811 * The microcode makes assumptions about the size and ordering of fields
2812 * in this structure. Do not change the structure definition here without
2813 * coordinating the change with the microcode.
2815 typedef struct adv_scsi_req_q {
2816 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2817 uchar sg_entry_cnt; /* SG element count. Zero for no SG. */
2818 uchar target_id; /* Device target identifier. */
2819 uchar target_lun; /* Device target logical unit number. */
2820 ulong data_addr; /* Data buffer physical address. */
2821 ulong data_cnt; /* Data count. Ucode sets to residual. */
2822 ulong sense_addr; /* Sense buffer physical address. */
2823 ulong srb_ptr; /* Driver request pointer. */
2824 uchar a_flag; /* Adv Library flag field. */
2825 uchar sense_len; /* Auto-sense length. Ucode sets to residual. */
2826 uchar cdb_len; /* SCSI CDB length. */
2827 uchar tag_code; /* SCSI-2 Tag Queue Code: 00, 20-22. */
2828 uchar done_status; /* Completion status. */
2829 uchar scsi_status; /* SCSI status byte. */
2830 uchar host_status; /* Ucode host status. */
2831 uchar ux_sg_ix; /* Ucode working SG variable. */
2832 uchar cdb[12]; /* SCSI command block. */
2833 ulong sg_real_addr; /* SG list physical address. */
2834 struct adv_scsi_req_q *free_scsiq_link;
2835 ulong ux_wk_data_cnt; /* Saved data count at disconnection. */
2836 struct adv_scsi_req_q *scsiq_ptr;
2837 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2839 * End of microcode structure - 60 bytes. The rest of the structure
2840 * is used by the Adv Library and ignored by the microcode.
2842 ulong vsense_addr; /* Sense buffer virtual address. */
2843 ulong vdata_addr; /* Data buffer virtual address. */
2844 uchar orig_sense_len; /* Original length of sense buffer. */
2845 } ADV_SCSI_REQ_Q; /* BIOS - 70 bytes, DOS - 76 bytes, W95, WNT - 69 bytes */
2848 * Microcode idle loop commands
2850 #define IDLE_CMD_COMPLETED 0
2851 #define IDLE_CMD_STOP_CHIP 0x0001
2852 #define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2853 #define IDLE_CMD_SEND_INT 0x0004
2854 #define IDLE_CMD_ABORT 0x0008
2855 #define IDLE_CMD_DEVICE_RESET 0x0010
2856 #define IDLE_CMD_SCSI_RESET 0x0020
2859 * AdvSendIdleCmd() flag definitions.
2861 #define ADV_NOWAIT 0x01
2864 * Wait loop time out values.
2866 #define SCSI_WAIT_10_SEC 10 /* 10 seconds */
2867 #define SCSI_MS_PER_SEC 1000 /* milliseconds per second */
2870 * Device drivers must define the following functions.
2872 STATIC int DvcEnterCritical(void);
2873 STATIC void DvcLeaveCritical(int);
2874 STATIC void DvcSleepMilliSecond(ulong);
2875 STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
2876 STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
2877 STATIC ulong DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2878 uchar *, long *, int);
2879 STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
2882 * Adv Library functions available to drivers.
2884 STATIC int AdvExeScsiQueue(ADV_DVC_VAR *,
2885 ADV_SCSI_REQ_Q *);
2886 STATIC int AdvISR(ADV_DVC_VAR *);
2887 STATIC int AdvInitGetConfig(ADV_DVC_VAR *);
2888 STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2889 STATIC int AdvResetSB(ADV_DVC_VAR *);
2892 * Internal Adv Library functions.
2894 STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ulong, int);
2895 STATIC void AdvResetChip(ADV_DVC_VAR *);
2896 STATIC int AdvSendScsiCmd(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2897 STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2898 STATIC int AdvInitFromEEP(ADV_DVC_VAR *);
2899 STATIC ushort AdvGetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *);
2900 STATIC void AdvSetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *);
2901 STATIC void AdvWaitEEPCmd(AdvPortAddr);
2902 STATIC ushort AdvReadEEPWord(AdvPortAddr, int);
2903 STATIC void AdvResetSCSIBus(ADV_DVC_VAR *);
2906 * PCI Bus Definitions
2908 #define AscPCICmdRegBits_BusMastering 0x0007
2909 #define AscPCICmdRegBits_ParErrRespCtrl 0x0040
2911 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
2913 /* Read byte from a register. */
2914 #define AdvReadByteRegister(iop_base, reg_off) \
2915 (inp((iop_base) + (reg_off)))
2917 /* Write byte to a register. */
2918 #define AdvWriteByteRegister(iop_base, reg_off, byte) \
2919 (outp((iop_base) + (reg_off), (byte)))
2921 /* Read word (2 bytes) from a register. */
2922 #define AdvReadWordRegister(iop_base, reg_off) \
2923 (inpw((iop_base) + (reg_off)))
2925 /* Write word (2 bytes) to a register. */
2926 #define AdvWriteWordRegister(iop_base, reg_off, word) \
2927 (outpw((iop_base) + (reg_off), (word)))
2929 /* Read byte from LRAM. */
2930 #define AdvReadByteLram(iop_base, addr, byte) \
2931 do { \
2932 outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
2933 (byte) = inp((iop_base) + IOPB_RAM_DATA); \
2934 } while (0)
2936 /* Write byte to LRAM. */
2937 #define AdvWriteByteLram(iop_base, addr, byte) \
2938 (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
2939 outp((iop_base) + IOPB_RAM_DATA, (byte)))
2941 /* Read word (2 bytes) from LRAM. */
2942 #define AdvReadWordLram(iop_base, addr, word) \
2943 do { \
2944 outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
2945 (word) = inpw((iop_base) + IOPW_RAM_DATA); \
2946 } while (0)
2948 /* Write word (2 bytes) to LRAM. */
2949 #define AdvWriteWordLram(iop_base, addr, word) \
2950 (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
2951 outpw((iop_base) + IOPW_RAM_DATA, (word)))
2953 /* Write double word (4 bytes) to LRAM */
2954 /* Because of unspecified C language ordering don't use auto-increment. */
2955 #define AdvWriteDWordLram(iop_base, addr, dword) \
2956 ((outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
2957 outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword) & 0xFFFF))), \
2958 (outpw((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2959 outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword >> 16) & 0xFFFF))))
2961 /* Read word (2 bytes) from LRAM assuming that the address is already set. */
2962 #define AdvReadWordAutoIncLram(iop_base) \
2963 (inpw((iop_base) + IOPW_RAM_DATA))
2965 /* Write word (2 bytes) to LRAM assuming that the address is already set. */
2966 #define AdvWriteWordAutoIncLram(iop_base, word) \
2967 (outpw((iop_base) + IOPW_RAM_DATA, (word)))
2969 #else /* version >= v1,3,0 */
2971 /* Read byte from a register. */
2972 #define AdvReadByteRegister(iop_base, reg_off) \
2973 (ADV_MEM_READB((iop_base) + (reg_off)))
2975 /* Write byte to a register. */
2976 #define AdvWriteByteRegister(iop_base, reg_off, byte) \
2977 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2979 /* Read word (2 bytes) from a register. */
2980 #define AdvReadWordRegister(iop_base, reg_off) \
2981 (ADV_MEM_READW((iop_base) + (reg_off)))
2983 /* Write word (2 bytes) to a register. */
2984 #define AdvWriteWordRegister(iop_base, reg_off, word) \
2985 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2987 /* Read byte from LRAM. */
2988 #define AdvReadByteLram(iop_base, addr, byte) \
2989 do { \
2990 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2991 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2992 } while (0)
2994 /* Write byte to LRAM. */
2995 #define AdvWriteByteLram(iop_base, addr, byte) \
2996 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2997 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2999 /* Read word (2 bytes) from LRAM. */
3000 #define AdvReadWordLram(iop_base, addr, word) \
3001 do { \
3002 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3003 (word) = ADV_MEM_READW((iop_base) + IOPW_RAM_DATA); \
3004 } while (0)
3006 /* Write word (2 bytes) to LRAM. */
3007 #define AdvWriteWordLram(iop_base, addr, word) \
3008 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3009 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3011 /* Write double word (4 bytes) to LRAM */
3012 /* Because of unspecified C language ordering don't use auto-increment. */
3013 #define AdvWriteDWordLram(iop_base, addr, dword) \
3014 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3015 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3016 (ushort) ((dword) & 0xFFFF))), \
3017 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3018 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3019 (ushort) ((dword >> 16) & 0xFFFF))))
3021 /* Read word (2 bytes) from LRAM assuming that the address is already set. */
3022 #define AdvReadWordAutoIncLram(iop_base) \
3023 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
3025 /* Write word (2 bytes) to LRAM assuming that the address is already set. */
3026 #define AdvWriteWordAutoIncLram(iop_base, word) \
3027 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3029 #endif /* version >= v1,3,0 */
3032 * Define macro to check for Condor signature.
3034 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
3035 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
3037 #define AdvFindSignature(iop_base) \
3038 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
3039 ADV_CHIP_ID_BYTE) && \
3040 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
3041 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
3044 * Define macro to Return the version number of the chip at 'iop_base'.
3046 * The second parameter 'bus_type' is currently unused.
3048 #define AdvGetChipVersion(iop_base, bus_type) \
3049 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
3052 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
3053 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
3055 * If the request has not yet been sent to the device it will simply be
3056 * aborted from RISC memory. If the request is disconnected it will be
3057 * aborted on reselection by sending an Abort Message to the target ID.
3059 * Return value:
3060 * ADV_TRUE(1) - Queue was successfully aborted.
3061 * ADV_FALSE(0) - Queue was not found on the active queue list.
3063 #define AdvAbortSRB(asc_dvc, srb_ptr) \
3064 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
3065 (ulong) (srb_ptr), 0)
3068 * Send a Bus Device Reset Message to the specified target ID.
3070 * All outstanding commands will be purged if sending the
3071 * Bus Device Reset Message is successful.
3073 * Return Value:
3074 * ADV_TRUE(1) - All requests on the target are purged.
3075 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
3076 * are not purged.
3078 #define AdvResetDevice(asc_dvc, target_id) \
3079 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
3080 (ulong) (target_id), 0)
3083 * SCSI Wide Type definition.
3085 #define ADV_SCSI_BIT_ID_TYPE ushort
3088 * AdvInitScsiTarget() 'cntl_flag' options.
3090 #define ADV_SCAN_LUN 0x01
3091 #define ADV_CAPINFO_NOLUN 0x02
3094 * Convert target id to target id bit mask.
3096 #define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
3099 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
3102 #define QD_NO_STATUS 0x00 /* Request not completed yet. */
3103 #define QD_NO_ERROR 0x01
3104 #define QD_ABORTED_BY_HOST 0x02
3105 #define QD_WITH_ERROR 0x04
3107 #define QHSTA_NO_ERROR 0x00
3108 #define QHSTA_M_SEL_TIMEOUT 0x11
3109 #define QHSTA_M_DATA_OVER_RUN 0x12
3110 #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
3111 #define QHSTA_M_QUEUE_ABORTED 0x15
3112 #define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
3113 #define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
3114 #define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
3115 #define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
3116 #define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
3117 #define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
3118 #define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
3119 /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
3120 #define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
3121 #define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
3122 #define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
3123 #define QHSTA_M_WTM_TIMEOUT 0x41
3124 #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
3125 #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
3126 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
3127 #define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
3129 typedef int (* ADV_ISR_CALLBACK)
3130 (ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3132 typedef int (* ADV_SBRESET_CALLBACK)
3133 (ADV_DVC_VAR *);
3136 * Default EEPROM Configuration structure defined in a_init.c.
3138 extern ADVEEP_CONFIG Default_EEPROM_Config;
3141 * DvcGetPhyAddr() flag arguments
3143 #define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
3144 #define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
3145 #define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
3146 #define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
3147 #define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
3149 /* Return the address that is aligned at the next doubleword >= to 'addr'. */
3150 #define ADV_DWALIGN(addr) (((ulong) (addr) + 0x3) & ~0x3)
3153 * Total contiguous memory needed for driver SG blocks.
3155 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
3156 * number of scatter-gather elements the driver supports in a
3157 * single request.
3160 #ifndef ADV_MAX_SG_LIST
3161 Forced Error: Driver must define ADV_MAX_SG_LIST.
3162 #endif /* ADV_MAX_SG_LIST */
3164 #define ADV_SG_LIST_MAX_BYTE_SIZE \
3165 (sizeof(ADV_SG_BLOCK) * \
3166 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
3169 * A driver may optionally define the assertion macro ADV_ASSERT() in
3170 * its d_os_dep.h file. If the macro has not already been defined,
3171 * then define the macro to a no-op.
3173 #ifndef ADV_ASSERT
3174 #define ADV_ASSERT(a)
3175 #endif /* ADV_ASSERT */
3179 * --- Driver Constants and Macros
3182 #define ASC_NUM_BOARD_SUPPORTED 16
3183 #define ASC_NUM_IOPORT_PROBE 4
3184 #define ASC_NUM_BUS 4
3186 /* Reference Scsi_Host hostdata */
3187 #define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
3189 /* asc_board_t flags */
3190 #define ASC_HOST_IN_RESET 0x01
3191 #define ASC_HOST_IN_ABORT 0x02
3192 #define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
3193 #define ASC_SELECT_QUEUE_DEPTHS 0x08
3195 #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
3196 #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
3198 #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
3201 * If the Linux kernel version supports freeing initialization code
3202 * and data after loading, define macros for this purpose. These macros
3203 * are not used when the driver is built as a module, cf. linux/init.h.
3205 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,23)
3206 #define ASC_INITFUNC(func) func
3207 #define ASC_INITDATA
3208 #define ASC_INIT
3209 #else /* version >= v2.1.23 */
3210 #define ASC_INITFUNC(func) __initfunc(func)
3211 #define ASC_INITDATA __initdata
3212 #define ASC_INIT __init
3213 #endif /* version >= v2.1.23 */
3215 #define ASC_INFO_SIZE 128 /* advansys_info() line size */
3217 /* /proc/scsi/advansys/[0...] related definitions */
3218 #define ASC_PRTBUF_SIZE 2048
3219 #define ASC_PRTLINE_SIZE 160
3221 #define ASC_PRT_NEXT() \
3222 if (cp) { \
3223 totlen += len; \
3224 leftlen -= len; \
3225 if (leftlen == 0) { \
3226 return totlen; \
3228 cp += len; \
3231 #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
3233 /* Asc Library return codes */
3234 #define ASC_TRUE 1
3235 #define ASC_FALSE 0
3236 #define ASC_NOERROR 1
3237 #define ASC_BUSY 0
3238 #define ASC_ERROR (-1)
3240 /* Scsi_Cmnd function return codes */
3241 #define STATUS_BYTE(byte) (byte)
3242 #define MSG_BYTE(byte) ((byte) << 8)
3243 #define HOST_BYTE(byte) ((byte) << 16)
3244 #define DRIVER_BYTE(byte) ((byte) << 24)
3247 * The following definitions and macros are OS independent interfaces to
3248 * the queue functions:
3249 * REQ - SCSI request structure
3250 * REQP - pointer to SCSI request structure
3251 * REQPTID(reqp) - reqp's target id
3252 * REQPNEXT(reqp) - reqp's next pointer
3253 * REQPNEXTP(reqp) - pointer to reqp's next pointer
3254 * REQPTIME(reqp) - reqp's time stamp value
3255 * REQTIMESTAMP() - system time stamp value
3257 typedef Scsi_Cmnd REQ, *REQP;
3258 #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
3259 #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
3260 #define REQPTID(reqp) ((reqp)->target)
3261 #define REQPTIME(reqp) ((reqp)->SCp.this_residual)
3262 #define REQTIMESTAMP() (jiffies)
3264 #define REQTIMESTAT(function, ascq, reqp, tid) \
3267 * If the request time stamp is less than the system time stamp, then \
3268 * maybe the system time stamp wrapped. Set the request time to zero.\
3269 */ \
3270 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
3271 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
3272 } else { \
3273 /* Indicate an error occurred with the assertion. */ \
3274 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
3275 REQPTIME(reqp) = 0; \
3277 /* Handle first minimum time case without external initialization. */ \
3278 if (((ascq)->q_tot_cnt[tid] == 1) || \
3279 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
3280 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
3281 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
3282 (function), (tid), (ascq)->q_min_tim[tid]); \
3284 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
3285 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
3286 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
3287 (function), tid, (ascq)->q_max_tim[tid]); \
3289 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
3290 /* Reset the time stamp field. */ \
3291 REQPTIME(reqp) = 0; \
3294 /* asc_enqueue() flags */
3295 #define ASC_FRONT 1
3296 #define ASC_BACK 2
3298 /* asc_dequeue_list() argument */
3299 #define ASC_TID_ALL (-1)
3301 /* Return non-zero, if the queue is empty. */
3302 #define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
3304 /* PCI configuration declarations */
3306 #define PCI_BASE_CLASS_PREDEFINED 0x00
3307 #define PCI_BASE_CLASS_MASS_STORAGE 0x01
3308 #define PCI_BASE_CLASS_NETWORK 0x02
3309 #define PCI_BASE_CLASS_DISPLAY 0x03
3310 #define PCI_BASE_CLASS_MULTIMEDIA 0x04
3311 #define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05
3312 #define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06
3314 /* MASS STORAGE */
3315 #define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00
3316 #define PCI_SUB_CLASS_IDE_CONTROLLER 0x01
3317 #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02
3318 #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03
3319 #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80
3321 /* NETWORK CONTROLLER */
3322 #define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00
3323 #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01
3324 #define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02
3325 #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80
3327 /* DISPLAY CONTROLLER */
3328 #define PCI_SUB_CLASS_VGA_CONTROLLER 0x00
3329 #define PCI_SUB_CLASS_XGA_CONTROLLER 0x01
3330 #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80
3332 /* MULTIMEDIA CONTROLLER */
3333 #define PCI_SUB_CLASS_VIDEO_DEVICE 0x00
3334 #define PCI_SUB_CLASS_AUDIO_DEVICE 0x01
3335 #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80
3337 /* MEMORY CONTROLLER */
3338 #define PCI_SUB_CLASS_RAM_CONTROLLER 0x00
3339 #define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01
3340 #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80
3342 /* BRIDGE CONTROLLER */
3343 #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00
3344 #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01
3345 #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02
3346 #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03
3347 #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04
3348 #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05
3349 #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80
3351 #define PCI_MAX_SLOT 0x1F
3352 #define PCI_MAX_BUS 0xFF
3353 #define PCI_IOADDRESS_MASK 0xFFFE
3354 #define ASC_PCI_VENDORID 0x10CD
3355 #define ASC_PCI_DEVICE_ID_CNT 4 /* PCI Device ID count. */
3356 #define ASC_PCI_DEVICE_ID_1100 0x1100
3357 #define ASC_PCI_DEVICE_ID_1200 0x1200
3358 #define ASC_PCI_DEVICE_ID_1300 0x1300
3359 #define ASC_PCI_DEVICE_ID_2300 0x2300
3361 /* PCI IO Port Addresses to generate special cycle */
3363 #define PCI_CONFIG_ADDRESS_MECH1 0x0CF8
3364 #define PCI_CONFIG_DATA_MECH1 0x0CFC
3366 #define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */
3368 #define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000
3369 #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00
3370 #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8
3372 #define PCI_DEVICE_FOUND 0x0000
3373 #define PCI_DEVICE_NOT_FOUND 0xffff
3375 #define SUBCLASS_OFFSET 0x0A
3376 #define CLASSCODE_OFFSET 0x0B
3377 #define VENDORID_OFFSET 0x00
3378 #define DEVICEID_OFFSET 0x02
3380 #ifndef ADVANSYS_STATS
3381 #define ASC_STATS(shp, counter)
3382 #define ASC_STATS_ADD(shp, counter, count)
3383 #else /* ADVANSYS_STATS */
3384 #define ASC_STATS(shp, counter) \
3385 (ASC_BOARDP(shp)->asc_stats.counter++)
3387 #define ASC_STATS_ADD(shp, counter, count) \
3388 (ASC_BOARDP(shp)->asc_stats.counter += (count))
3389 #endif /* ADVANSYS_STATS */
3391 #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
3393 /* If the result wraps when calculating tenths, return 0. */
3394 #define ASC_TENTHS(num, den) \
3395 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
3396 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
3399 * Display a message to the console.
3401 #define ASC_PRINT(s) \
3403 printk("advansys: "); \
3404 printk(s); \
3407 #define ASC_PRINT1(s, a1) \
3409 printk("advansys: "); \
3410 printk((s), (a1)); \
3413 #define ASC_PRINT2(s, a1, a2) \
3415 printk("advansys: "); \
3416 printk((s), (a1), (a2)); \
3419 #define ASC_PRINT3(s, a1, a2, a3) \
3421 printk("advansys: "); \
3422 printk((s), (a1), (a2), (a3)); \
3425 #define ASC_PRINT4(s, a1, a2, a3, a4) \
3427 printk("advansys: "); \
3428 printk((s), (a1), (a2), (a3), (a4)); \
3432 #ifndef ADVANSYS_DEBUG
3434 #define ASC_DBG(lvl, s)
3435 #define ASC_DBG1(lvl, s, a1)
3436 #define ASC_DBG2(lvl, s, a1, a2)
3437 #define ASC_DBG3(lvl, s, a1, a2, a3)
3438 #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
3439 #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
3440 #define ASC_DBG_PRT_SCSI_CMND(lvl, s)
3441 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
3442 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3443 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
3444 #define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3445 #define ASC_DBG_PRT_HEX(lvl, name, start, length)
3446 #define ASC_DBG_PRT_CDB(lvl, cdb, len)
3447 #define ASC_DBG_PRT_SENSE(lvl, sense, len)
3448 #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
3450 #else /* ADVANSYS_DEBUG */
3453 * Debugging Message Levels:
3454 * 0: Errors Only
3455 * 1: High-Level Tracing
3456 * 2-N: Verbose Tracing
3459 #define ASC_DBG(lvl, s) \
3461 if (asc_dbglvl >= (lvl)) { \
3462 printk(s); \
3466 #define ASC_DBG1(lvl, s, a1) \
3468 if (asc_dbglvl >= (lvl)) { \
3469 printk((s), (a1)); \
3473 #define ASC_DBG2(lvl, s, a1, a2) \
3475 if (asc_dbglvl >= (lvl)) { \
3476 printk((s), (a1), (a2)); \
3480 #define ASC_DBG3(lvl, s, a1, a2, a3) \
3482 if (asc_dbglvl >= (lvl)) { \
3483 printk((s), (a1), (a2), (a3)); \
3487 #define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
3489 if (asc_dbglvl >= (lvl)) { \
3490 printk((s), (a1), (a2), (a3), (a4)); \
3494 #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
3496 if (asc_dbglvl >= (lvl)) { \
3497 asc_prt_scsi_host(s); \
3501 #define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
3503 if (asc_dbglvl >= (lvl)) { \
3504 asc_prt_scsi_cmnd(s); \
3508 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
3510 if (asc_dbglvl >= (lvl)) { \
3511 asc_prt_asc_scsi_q(scsiqp); \
3515 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
3517 if (asc_dbglvl >= (lvl)) { \
3518 asc_prt_asc_qdone_info(qdone); \
3522 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
3524 if (asc_dbglvl >= (lvl)) { \
3525 asc_prt_adv_scsi_req_q(scsiqp); \
3529 #define ASC_DBG_PRT_HEX(lvl, name, start, length) \
3531 if (asc_dbglvl >= (lvl)) { \
3532 asc_prt_hex((name), (start), (length)); \
3536 #define ASC_DBG_PRT_CDB(lvl, cdb, len) \
3537 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
3539 #define ASC_DBG_PRT_SENSE(lvl, sense, len) \
3540 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
3542 #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
3543 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
3544 #endif /* ADVANSYS_DEBUG */
3546 #ifndef ADVANSYS_ASSERT
3547 #define ASC_ASSERT(a)
3548 #else /* ADVANSYS_ASSERT */
3550 #define ASC_ASSERT(a) \
3552 if (!(a)) { \
3553 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
3554 __FILE__, __LINE__); \
3558 #endif /* ADVANSYS_ASSERT */
3562 * --- Driver Structures
3565 #ifdef ADVANSYS_STATS
3567 /* Per board statistics structure */
3568 struct asc_stats {
3569 /* Driver Entrypoint Statistics */
3570 ulong command; /* # calls to advansys_command() */
3571 ulong queuecommand; /* # calls to advansys_queuecommand() */
3572 ulong abort; /* # calls to advansys_abort() */
3573 ulong reset; /* # calls to advansys_reset() */
3574 ulong biosparam; /* # calls to advansys_biosparam() */
3575 ulong interrupt; /* # advansys_interrupt() calls */
3576 ulong callback; /* # calls to asc/adv_isr_callback() */
3577 ulong done; /* # calls to request's scsi_done function */
3578 ulong build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
3579 ulong adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
3580 ulong adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
3581 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
3582 ulong exe_noerror; /* # ASC_NOERROR returns. */
3583 ulong exe_busy; /* # ASC_BUSY returns. */
3584 ulong exe_error; /* # ASC_ERROR returns. */
3585 ulong exe_unknown; /* # unknown returns. */
3586 /* Data Transfer Statistics */
3587 ulong cont_cnt; /* # non-scatter-gather I/O requests received */
3588 ulong cont_xfer; /* # contiguous transfer 512-bytes */
3589 ulong sg_cnt; /* # scatter-gather I/O requests received */
3590 ulong sg_elem; /* # scatter-gather elements */
3591 ulong sg_xfer; /* # scatter-gather transfer 512-bytes */
3593 #endif /* ADVANSYS_STATS */
3596 * Request queuing structure
3598 typedef struct asc_queue {
3599 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
3600 REQP q_first[ADV_MAX_TID+1]; /* first queued request */
3601 REQP q_last[ADV_MAX_TID+1]; /* last queued request */
3602 #ifdef ADVANSYS_STATS
3603 short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */
3604 short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */
3605 ulong q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */
3606 ulong q_tot_tim[ADV_MAX_TID+1]; /* total time queued */
3607 ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */
3608 ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */
3609 #endif /* ADVANSYS_STATS */
3610 } asc_queue_t;
3613 * Adv Library Request Structures
3615 * The following two se structures are used to process Wide Board requests.
3616 * One structure is needed for each command received from the Mid-Level SCSI
3617 * driver.
3619 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
3620 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
3621 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
3622 * Mid-Level SCSI request structure.
3624 * The adv_sgblk_t structure is used to handle requests that include
3625 * scatter-gather elements.
3627 typedef struct adv_sgblk {
3628 ADV_SG_BLOCK sg_block[ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING];
3629 uchar align2[4]; /* Sgblock structure padding. */
3630 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
3631 } adv_sgblk_t;
3633 typedef struct adv_req {
3634 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
3635 uchar align1[4]; /* Request structure padding. */
3636 Scsi_Cmnd *cmndp; /* Mid-Level SCSI command pointer. */
3637 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
3638 struct adv_req *next_reqp; /* Next Request Structure. */
3639 } adv_req_t;
3642 * Structure allocated for each board.
3644 * This structure is allocated by scsi_register() at the end
3645 * of the 'Scsi_Host' structure starting at the 'hostdata'
3646 * field. It is guaranteed to be allocated from DMA-able memory.
3648 typedef struct asc_board {
3649 int id; /* Board Id */
3650 uint flags; /* Board flags */
3651 union {
3652 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
3653 ADV_DVC_VAR adv_dvc_var; /* Wide board */
3654 } dvc_var;
3655 union {
3656 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
3657 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
3658 } dvc_cfg;
3659 asc_queue_t active; /* Active command queue */
3660 asc_queue_t waiting; /* Waiting command queue */
3661 asc_queue_t done; /* Done command queue */
3662 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
3663 Scsi_Device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */
3664 ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */
3665 #if ASC_QUEUE_FLOW_CONTROL
3666 ushort nerrcnt[ADV_MAX_TID+1]; /* No error request count */
3667 #endif /* ASC_QUEUE_FLOW_CONTROL */
3668 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
3669 ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */
3670 union {
3671 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
3672 ADVEEP_CONFIG adv_eep; /* Wide EEPROM config. */
3673 } eep_config;
3674 ulong last_reset; /* Saved last reset time */
3675 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3676 /* /proc/scsi/advansys/[0...] */
3677 char *prtbuf; /* Statistics Print Buffer */
3678 #endif /* version >= v1.3.0 */
3679 #ifdef ADVANSYS_STATS
3680 struct asc_stats asc_stats; /* Board statistics */
3681 #endif /* ADVANSYS_STATS */
3683 * The following fields are used only for Narrow Boards.
3685 /* The following three structures must be in DMA-able memory. */
3686 ASC_SCSI_REQ_Q scsireqq;
3687 ASC_CAP_INFO cap_info;
3688 ASC_SCSI_INQUIRY inquiry;
3689 uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */
3691 * The following fields are used only for Wide Boards.
3693 void *ioremap_addr; /* I/O Memory remap address. */
3694 ushort ioport; /* I/O Port address. */
3695 adv_req_t *orig_reqp; /* adv_req_t memory block. */
3696 adv_req_t *adv_reqp; /* Request structures. */
3697 adv_sgblk_t *orig_sgblkp; /* adv_sgblk_t memory block. */
3698 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
3699 ushort bios_signature; /* BIOS Signature. */
3700 ushort bios_version; /* BIOS Version. */
3701 ushort bios_codeseg; /* BIOS Code Segment. */
3702 ushort bios_codelen; /* BIOS Code Segment Length. */
3703 } asc_board_t;
3706 * PCI configuration structures
3708 typedef struct _PCI_DATA_
3710 uchar type;
3711 uchar bus;
3712 uchar slot;
3713 uchar func;
3714 uchar offset;
3715 } PCI_DATA;
3717 typedef struct _PCI_DEVICE_
3719 ushort vendorID;
3720 ushort deviceID;
3721 ushort slotNumber;
3722 ushort slotFound;
3723 uchar busNumber;
3724 uchar maxBusNumber;
3725 uchar devFunc;
3726 ushort startSlot;
3727 ushort endSlot;
3728 uchar bridge;
3729 uchar type;
3730 } PCI_DEVICE;
3732 typedef struct _PCI_CONFIG_SPACE_
3734 ushort vendorID;
3735 ushort deviceID;
3736 ushort command;
3737 ushort status;
3738 uchar revision;
3739 uchar classCode[3];
3740 uchar cacheSize;
3741 uchar latencyTimer;
3742 uchar headerType;
3743 uchar bist;
3744 ulong baseAddress[6];
3745 ushort reserved[4];
3746 ulong optionRomAddr;
3747 ushort reserved2[4];
3748 uchar irqLine;
3749 uchar irqPin;
3750 uchar minGnt;
3751 uchar maxLatency;
3752 } PCI_CONFIG_SPACE;
3756 * --- Driver Data
3759 /* Note: All driver global data should be initialized. */
3761 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3762 struct proc_dir_entry proc_scsi_advansys =
3764 PROC_SCSI_ADVANSYS, /* unsigned short low_ino */
3765 8, /* unsigned short namelen */
3766 "advansys", /* const char *name */
3767 S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */
3768 2 /* nlink_t nlink */
3770 #endif /* version >= v1.3.0 */
3772 /* Number of boards detected in system. */
3773 STATIC int asc_board_count = 0;
3774 STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
3776 /* Overrun buffer shared between all boards. */
3777 STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
3780 * Global structures required to issue a command.
3782 STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
3783 STATIC ASC_SG_HEAD asc_sg_head = { 0 };
3785 /* List of supported bus types. */
3786 STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
3787 ASC_IS_ISA,
3788 ASC_IS_VL,
3789 ASC_IS_EISA,
3790 ASC_IS_PCI,
3793 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
3794 #ifdef ASC_CONFIG_PCI
3795 STATIC int pci_scan_method ASC_INITDATA = -1;
3796 #endif /* ASC_CONFIG_PCI */
3797 #endif /* version < v2.1.93 */
3800 * Used with the LILO 'advansys' option to eliminate or
3801 * limit I/O port probing at boot time, cf. advansys_setup().
3803 STATIC int asc_iopflag = ASC_FALSE;
3804 STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
3806 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
3808 * In kernels earlier than v1.3.0, kmalloc() does not work
3809 * during driver initialization. Therefore statically declare
3810 * 16 elements of each structure. v1.3.0 kernels will probably
3811 * not need any more than this number.
3813 uchar adv_req_buf[16 * sizeof(adv_req_t)] = { 0 };
3814 uchar adv_sgblk_buf[16 * sizeof(adv_sgblk_t)] = { 0 };
3815 #endif /* version >= v1,3,0 */
3817 #ifdef ADVANSYS_DEBUG
3818 STATIC char *
3819 asc_bus_name[ASC_NUM_BUS] = {
3820 "ASC_IS_ISA",
3821 "ASC_IS_VL",
3822 "ASC_IS_EISA",
3823 "ASC_IS_PCI",
3826 STATIC int asc_dbglvl = 0;
3827 #endif /* ADVANSYS_DEBUG */
3829 /* Declaration for Asc Library internal data referenced by driver. */
3830 STATIC PortAddr _asc_def_iop_base[];
3834 * --- Driver Function Prototypes
3836 * advansys.h contains function prototypes for functions global to Linux.
3839 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3840 STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int);
3841 #endif /* version >= v1.3.0 */
3842 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
3843 STATIC void advansys_interrupt(int, struct pt_regs *);
3844 #else /* version >= v1.3.70 */
3845 STATIC void advansys_interrupt(int, void *, struct pt_regs *);
3846 #endif /* version >= v1.3.70 */
3847 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
3848 STATIC void advansys_select_queue_depths(struct Scsi_Host *,
3849 Scsi_Device *);
3850 #endif /* version >= v1.3.89 */
3851 STATIC void advansys_command_done(Scsi_Cmnd *);
3852 STATIC void asc_scsi_done_list(Scsi_Cmnd *);
3853 STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
3854 STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *);
3855 STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
3856 STATIC int adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *);
3857 STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
3858 STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3859 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
3860 #ifdef ASC_CONFIG_PCI
3861 STATIC int asc_srch_pci_dev(PCI_DEVICE *);
3862 STATIC uchar asc_scan_method(void);
3863 STATIC int asc_pci_find_dev(PCI_DEVICE *);
3864 STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
3865 STATIC ushort asc_get_cfg_word(PCI_DATA *);
3866 STATIC uchar asc_get_cfg_byte(PCI_DATA *);
3867 STATIC void asc_put_cfg_byte(PCI_DATA *, uchar);
3868 #endif /* ASC_CONFIG_PCI */
3869 #endif /* version < v2.1.93 */
3870 STATIC void asc_enqueue(asc_queue_t *, REQP, int);
3871 STATIC REQP asc_dequeue(asc_queue_t *, int);
3872 STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
3873 STATIC int asc_rmqueue(asc_queue_t *, REQP);
3874 STATIC int asc_isqueued(asc_queue_t *, REQP);
3875 STATIC void asc_execute_queue(asc_queue_t *);
3876 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3877 STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int);
3878 STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
3879 STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
3880 STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
3881 STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
3882 STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
3883 STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
3884 STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
3885 STATIC int asc_prt_line(char *, int, char *fmt, ...);
3886 #endif /* version >= v1.3.0 */
3888 /* Declaration for Asc Library internal functions reference by driver. */
3889 STATIC int AscFindSignature(PortAddr);
3890 STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
3892 #ifdef ADVANSYS_STATS
3893 STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int);
3894 #endif /* ADVANSYS_STATS */
3896 #ifdef ADVANSYS_DEBUG
3897 STATIC void asc_prt_scsi_host(struct Scsi_Host *);
3898 STATIC void asc_prt_scsi_cmnd(Scsi_Cmnd *);
3899 STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
3900 STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
3901 STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
3902 STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
3903 STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
3904 STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
3905 STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
3906 STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
3907 STATIC void asc_prt_hex(char *f, uchar *, int);
3908 #endif /* ADVANSYS_DEBUG */
3910 #ifdef ADVANSYS_ASSERT
3911 STATIC int interrupts_enabled(void);
3912 #endif /* ADVANSYS_ASSERT */
3916 * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
3919 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3921 * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
3923 * *buffer: I/O buffer
3924 * **start: if inout == FALSE pointer into buffer where user read should start
3925 * offset: current offset into a /proc/scsi/advansys/[0...] file
3926 * length: length of buffer
3927 * hostno: Scsi_Host host_no
3928 * inout: TRUE - user is writing; FALSE - user is reading
3930 * Return the number of bytes read from or written to a
3931 * /proc/scsi/advansys/[0...] file.
3933 * Note: This function uses the per board buffer 'prtbuf' which is
3934 * allocated when the board is initialized in advansys_detect(). The
3935 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
3936 * used to write to the buffer. The way asc_proc_copy() is written
3937 * if 'prtbuf' is too small it will not be overwritten. Instead the
3938 * user just won't get all the available statistics.
3941 advansys_proc_info(char *buffer, char **start, off_t offset, int length,
3942 int hostno, int inout)
3944 #ifdef CONFIG_PROC_FS
3946 struct Scsi_Host *shp;
3947 asc_board_t *boardp;
3948 int i;
3949 char *cp;
3950 int cplen;
3951 int cnt;
3952 int totcnt;
3953 int leftlen;
3954 char *curbuf;
3955 off_t advoffset;
3956 Scsi_Device *scd;
3958 ASC_DBG(1, "advansys_proc_info: begin\n");
3961 * User write not supported.
3963 if (inout == TRUE) {
3964 return(-ENOSYS);
3968 * User read of /proc/scsi/advansys/[0...] file.
3971 /* Find the specified board. */
3972 for (i = 0; i < asc_board_count; i++) {
3973 if (asc_host[i]->host_no == hostno) {
3974 break;
3977 if (i == asc_board_count) {
3978 return(-ENOENT);
3981 shp = asc_host[i];
3982 boardp = ASC_BOARDP(shp);
3984 /* Copy read data starting at the beginning of the buffer. */
3985 *start = buffer;
3986 curbuf = buffer;
3987 advoffset = 0;
3988 totcnt = 0;
3989 leftlen = length;
3992 * Get board configuration information.
3994 * advansys_info() returns the board string from its own static buffer.
3996 cp = (char *) advansys_info(shp);
3997 strcat(cp, "\n");
3998 cplen = strlen(cp);
3999 /* Copy board information. */
4000 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4001 totcnt += cnt;
4002 leftlen -= cnt;
4003 if (leftlen == 0) {
4004 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4005 return totcnt;
4007 advoffset += cplen;
4008 curbuf += cnt;
4011 * Display Wide Board BIOS Information.
4013 if (ASC_WIDE_BOARD(boardp)) {
4014 cp = boardp->prtbuf;
4015 cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
4016 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4017 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4018 totcnt += cnt;
4019 leftlen -= cnt;
4020 if (leftlen == 0) {
4021 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4022 return totcnt;
4024 advoffset += cplen;
4025 curbuf += cnt;
4029 * Display driver information for each device attached to the board.
4031 cp = boardp->prtbuf;
4032 cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
4033 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4034 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4035 totcnt += cnt;
4036 leftlen -= cnt;
4037 if (leftlen == 0) {
4038 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4039 return totcnt;
4041 advoffset += cplen;
4042 curbuf += cnt;
4045 * Display target driver information for each device attached
4046 * to the board.
4048 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75)
4049 for (scd = scsi_devices; scd; scd = scd->next)
4050 #else /* version >= v2.1.75 */
4051 for (scd = shp->host_queue; scd; scd = scd->next)
4052 #endif /* version >= v2.1.75 */
4054 if (scd->host == shp) {
4055 cp = boardp->prtbuf;
4057 * Note: If proc_print_scsidevice() writes more than
4058 * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'.
4060 proc_print_scsidevice(scd, cp, &cplen, 0);
4061 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4062 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4063 totcnt += cnt;
4064 leftlen -= cnt;
4065 if (leftlen == 0) {
4066 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4067 return totcnt;
4069 advoffset += cplen;
4070 curbuf += cnt;
4075 * Display EEPROM configuration for the board.
4077 cp = boardp->prtbuf;
4078 if (ASC_NARROW_BOARD(boardp)) {
4079 cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4080 } else {
4081 cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4083 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4084 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4085 totcnt += cnt;
4086 leftlen -= cnt;
4087 if (leftlen == 0) {
4088 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4089 return totcnt;
4091 advoffset += cplen;
4092 curbuf += cnt;
4095 * Display driver configuration and information for the board.
4097 cp = boardp->prtbuf;
4098 cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
4099 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4100 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4101 totcnt += cnt;
4102 leftlen -= cnt;
4103 if (leftlen == 0) {
4104 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4105 return totcnt;
4107 advoffset += cplen;
4108 curbuf += cnt;
4110 #ifdef ADVANSYS_STATS
4112 * Display driver statistics for the board.
4114 cp = boardp->prtbuf;
4115 cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
4116 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4117 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4118 totcnt += cnt;
4119 leftlen -= cnt;
4120 if (leftlen == 0) {
4121 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4122 return totcnt;
4124 advoffset += cplen;
4125 curbuf += cnt;
4126 #endif /* ADVANSYS_STATS */
4129 * Display Asc Library dynamic configuration information
4130 * for the board.
4132 cp = boardp->prtbuf;
4133 if (ASC_NARROW_BOARD(boardp)) {
4134 cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
4135 } else {
4136 cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
4138 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4139 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4140 totcnt += cnt;
4141 leftlen -= cnt;
4142 if (leftlen == 0) {
4143 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4144 return totcnt;
4146 advoffset += cplen;
4147 curbuf += cnt;
4149 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4151 return totcnt;
4152 #else /* CONFIG_PROC_FS */
4153 return 0;
4154 #endif /* CONFIG_PROC_FS */
4157 #endif /* version >= v1.3.0 */
4159 * advansys_detect()
4161 * Detect function for AdvanSys adapters.
4163 * Argument is a pointer to the host driver's scsi_hosts entry.
4165 * Return number of adapters found.
4167 * Note: Because this function is called during system initialization
4168 * it must not call SCSI mid-level functions including scsi_malloc()
4169 * and scsi_free().
4171 ASC_INITFUNC(
4173 advansys_detect(Scsi_Host_Template *tpnt)
4176 static int detect_called = ASC_FALSE;
4177 int iop;
4178 int bus;
4179 struct Scsi_Host *shp;
4180 asc_board_t *boardp;
4181 ASC_DVC_VAR *asc_dvc_varp = NULL;
4182 ADV_DVC_VAR *adv_dvc_varp = NULL;
4183 int ioport = 0;
4184 int share_irq = FALSE;
4185 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4186 #ifdef ASC_CONFIG_PCI
4187 PCI_DEVICE pciDevice;
4188 PCI_CONFIG_SPACE pciConfig;
4189 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4190 unsigned long pci_memory_address;
4191 #endif /* version >= v1,3,0 */
4192 #endif /* ASC_CONFIG_PCI */
4193 #else /* version >= v2.1.93 */
4194 #ifdef CONFIG_PCI
4195 struct pci_dev *pci_devp = NULL;
4196 int pci_device_id_cnt = 0;
4197 unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
4198 ASC_PCI_DEVICE_ID_1100,
4199 ASC_PCI_DEVICE_ID_1200,
4200 ASC_PCI_DEVICE_ID_1300,
4201 ASC_PCI_DEVICE_ID_2300
4203 unsigned long pci_memory_address;
4204 #endif /* CONFIG_PCI */
4205 #endif /* version >= v2.1.93 */
4206 int warn_code, err_code;
4207 int ret;
4209 if (detect_called == ASC_FALSE) {
4210 detect_called = ASC_TRUE;
4211 } else {
4212 printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n");
4213 return 0;
4216 ASC_DBG(1, "advansys_detect: begin\n");
4218 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4219 tpnt->proc_dir = &proc_scsi_advansys;
4220 #endif /* version >= v1.3.0 */
4222 asc_board_count = 0;
4225 * If I/O port probing has been modified, then verify and
4226 * clean-up the 'asc_ioport' list.
4228 if (asc_iopflag == ASC_TRUE) {
4229 for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
4230 ASC_DBG2(1, "advansys_detect: asc_ioport[%d] %x\n",
4231 ioport, asc_ioport[ioport]);
4232 if (asc_ioport[ioport] != 0) {
4233 for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
4234 if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
4235 break;
4238 if (iop == ASC_IOADR_TABLE_MAX_IX) {
4239 printk(
4240 "AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
4241 asc_ioport[ioport]);
4242 asc_ioport[ioport] = 0;
4246 ioport = 0;
4249 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4250 #ifdef ASC_CONFIG_PCI
4251 memset(&pciDevice, 0, sizeof(PCI_DEVICE));
4252 memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
4253 pciDevice.maxBusNumber = PCI_MAX_BUS;
4254 pciDevice.endSlot = PCI_MAX_SLOT;
4255 #endif /* ASC_CONFIG_PCI */
4256 #endif /* version < v2.1.93 */
4258 for (bus = 0; bus < ASC_NUM_BUS; bus++) {
4260 ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
4261 bus, asc_bus_name[bus]);
4262 iop = 0;
4264 while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
4266 ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
4267 asc_board_count);
4269 switch (asc_bus[bus]) {
4270 case ASC_IS_ISA:
4271 case ASC_IS_VL:
4272 if (asc_iopflag == ASC_FALSE) {
4273 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
4274 } else {
4276 * ISA and VL I/O port scanning has either been
4277 * eliminated or limited to selected ports on
4278 * the LILO command line, /etc/lilo.conf, or
4279 * by setting variables when the module was loaded.
4281 ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
4282 ioport_try_again:
4283 iop = 0;
4284 for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
4285 if ((iop = asc_ioport[ioport]) != 0) {
4286 break;
4289 if (iop) {
4290 ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
4291 iop);
4292 if (check_region(iop, ASC_IOADR_GAP) != 0) {
4293 printk(
4294 "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
4295 /* Don't try this I/O port twice. */
4296 asc_ioport[ioport] = 0;
4297 goto ioport_try_again;
4298 } else if (AscFindSignature(iop) == ASC_FALSE) {
4299 printk(
4300 "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
4301 /* Don't try this I/O port twice. */
4302 asc_ioport[ioport] = 0;
4303 goto ioport_try_again;
4304 } else {
4306 * If this isn't an ISA board, then it must be
4307 * a VL board. If currently looking an ISA
4308 * board is being looked for then try for
4309 * another ISA board in 'asc_ioport'.
4311 if (asc_bus[bus] == ASC_IS_ISA &&
4312 (AscGetChipVersion(iop, ASC_IS_ISA) &
4313 ASC_CHIP_VER_ISA_BIT) == 0) {
4315 * Don't clear 'asc_ioport[ioport]'. Try
4316 * this board again for VL. Increment
4317 * 'ioport' past this board.
4319 ioport++;
4320 goto ioport_try_again;
4324 * This board appears good, don't try the I/O port
4325 * again by clearing its value. Increment 'ioport'
4326 * for the next iteration.
4328 asc_ioport[ioport++] = 0;
4331 break;
4333 case ASC_IS_EISA:
4334 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
4335 break;
4337 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4338 #ifdef ASC_CONFIG_PCI
4339 case ASC_IS_PCI:
4340 if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
4341 iop = 0;
4342 } else {
4343 ASC_DBG2(2,
4344 "advansys_detect: slotFound %d, busNumber %d\n",
4345 pciDevice.slotFound, pciDevice.busNumber);
4346 asc_get_pci_cfg(&pciDevice, &pciConfig);
4347 iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
4348 ASC_DBG2(1,
4349 "advansys_detect: vendorID %X, deviceID %X\n",
4350 pciConfig.vendorID, pciConfig.deviceID);
4351 ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
4352 iop, pciConfig.irqLine);
4354 break;
4355 #endif /* ASC_CONFIG_PCI */
4356 #else /* version >= v2.1.93 */
4357 #ifdef CONFIG_PCI
4358 case ASC_IS_PCI:
4359 while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) {
4360 if ((pci_devp = pci_find_device(ASC_PCI_VENDORID,
4361 pci_device_id[pci_device_id_cnt], pci_devp)) == NULL) {
4362 pci_device_id_cnt++;
4363 } else {
4364 break;
4367 if (pci_devp == NULL) {
4368 iop = 0;
4369 } else {
4370 ASC_DBG2(2,
4371 "advansys_detect: devfn %d, bus number %d\n",
4372 pci_devp->devfn, pci_devp->bus->number);
4373 iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK;
4374 ASC_DBG2(1,
4375 "advansys_detect: vendorID %X, deviceID %X\n",
4376 pci_devp->vendor, pci_devp->device);
4377 ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
4378 iop, pci_devp->irq);
4380 break;
4381 #endif /* CONFIG_PCI */
4382 #endif /* version >= v2.1.93 */
4384 default:
4385 ASC_PRINT1("advansys_detect: unknown bus type: %d\n",
4386 asc_bus[bus]);
4387 break;
4389 ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
4392 * Adapter not found, try next bus type.
4394 if (iop == 0) {
4395 break;
4399 * Adapter found.
4401 * Register the adapter, get its configuration, and
4402 * initialize it.
4404 ASC_DBG(2, "advansys_detect: scsi_register()\n");
4405 shp = scsi_register(tpnt, sizeof(asc_board_t));
4407 /* Save a pointer to the Scsi_host of each board found. */
4408 asc_host[asc_board_count++] = shp;
4410 /* Initialize private per board data */
4411 boardp = ASC_BOARDP(shp);
4412 memset(boardp, 0, sizeof(asc_board_t));
4413 boardp->id = asc_board_count - 1;
4416 * Handle both narrow and wide boards.
4418 * If a Wide board was detected, set the board structure
4419 * wide board flag. Set-up the board structure based on
4420 * the board type.
4422 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4423 #ifdef ASC_CONFIG_PCI
4424 if (asc_bus[bus] == ASC_IS_PCI &&
4425 pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) {
4426 boardp->flags |= ASC_IS_WIDE_BOARD;
4428 #endif /* ASC_CONFIG_PCI */
4429 #else /* version >= v2.1.93 */
4430 #ifdef CONFIG_PCI
4431 if (asc_bus[bus] == ASC_IS_PCI &&
4432 pci_devp->device == ASC_PCI_DEVICE_ID_2300) {
4433 boardp->flags |= ASC_IS_WIDE_BOARD;
4435 #endif /* CONFIG_PCI */
4436 #endif /* version >= v2.1.93 */
4438 if (ASC_NARROW_BOARD(boardp)) {
4439 ASC_DBG(1, "advansys_detect: narrow board\n");
4440 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4441 asc_dvc_varp->bus_type = asc_bus[bus];
4442 asc_dvc_varp->drv_ptr = (ulong) boardp;
4443 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
4444 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
4445 asc_dvc_varp->iop_base = iop;
4446 asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback;
4447 } else {
4448 ASC_DBG(1, "advansys_detect: wide board\n");
4449 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4450 adv_dvc_varp->drv_ptr = (ulong) boardp;
4451 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
4452 adv_dvc_varp->isr_callback = (Ptr2Func) adv_isr_callback;
4454 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
4455 adv_dvc_varp->iop_base = iop;
4456 #else /* version >= v1,3,0 */
4458 * Map the board's registers into virtual memory for
4459 * PCI slave access. Only memory accesses are used to
4460 * access the board's registers.
4462 * Note: The PCI register base address is not always
4463 * page aligned, but the address passed to ioremap()
4464 * must be page aligned. It is guaranteed that the
4465 * PCI register base address will not cross a page
4466 * boundary.
4468 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4469 #ifdef ASC_CONFIG_PCI
4470 pci_memory_address = pciConfig.baseAddress[1];
4471 if ((boardp->ioremap_addr =
4472 ioremap(pci_memory_address & PAGE_MASK,
4473 PAGE_SIZE)) == 0) {
4474 ASC_PRINT3(
4475 "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
4476 boardp->id, pci_memory_address, ADV_CONDOR_IOLEN);
4477 scsi_unregister(shp);
4478 asc_board_count--;
4479 continue;
4481 adv_dvc_varp->iop_base = (AdvPortAddr)
4482 (boardp->ioremap_addr +
4483 (pci_memory_address - (pci_memory_address & PAGE_MASK)));
4484 #endif /* ASC_CONFIG_PCI */
4485 #else /* version >= v2.1.93 */
4486 #ifdef CONFIG_PCI
4487 pci_memory_address = pci_devp->base_address[1];
4488 if ((boardp->ioremap_addr =
4489 ioremap(pci_memory_address & PAGE_MASK,
4490 PAGE_SIZE)) == 0) {
4491 ASC_PRINT3(
4492 "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
4493 boardp->id, pci_memory_address, ADV_CONDOR_IOLEN);
4494 scsi_unregister(shp);
4495 asc_board_count--;
4496 continue;
4498 adv_dvc_varp->iop_base = (AdvPortAddr)
4499 (boardp->ioremap_addr +
4500 (pci_memory_address - (pci_memory_address & PAGE_MASK)));
4501 #endif /* CONFIG_PCI */
4502 #endif /* version >= v2.1.93 */
4503 #endif /* version >= v1,3,0 */
4506 * Even though it isn't used to access the board in
4507 * kernels greater than or equal to v1.3.0, save
4508 * the I/O Port address so that it can be reported and
4509 * displayed.
4511 boardp->ioport = iop;
4514 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4516 * Allocate buffer for printing information from
4517 * /proc/scsi/advansys/[0...].
4519 if ((boardp->prtbuf =
4520 kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
4521 ASC_PRINT3(
4522 "advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n",
4523 boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
4524 scsi_unregister(shp);
4525 asc_board_count--;
4526 continue;
4528 #endif /* version >= v1.3.0 */
4530 if (ASC_NARROW_BOARD(boardp)) {
4532 * Set the board bus type and PCI IRQ before
4533 * calling AscInitGetConfig().
4535 switch (asc_dvc_varp->bus_type) {
4536 case ASC_IS_ISA:
4537 shp->unchecked_isa_dma = TRUE;
4538 share_irq = FALSE;
4539 break;
4540 case ASC_IS_VL:
4541 shp->unchecked_isa_dma = FALSE;
4542 share_irq = FALSE;
4543 break;
4544 case ASC_IS_EISA:
4545 shp->unchecked_isa_dma = FALSE;
4546 share_irq = TRUE;
4547 break;
4548 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4549 #ifdef ASC_CONFIG_PCI
4550 case ASC_IS_PCI:
4551 shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine;
4552 asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
4553 asc_dvc_varp->cfg->pci_slot_info =
4554 ASC_PCI_MKID(pciDevice.busNumber,
4555 pciDevice.slotFound,
4556 pciDevice.devFunc);
4557 shp->unchecked_isa_dma = FALSE;
4558 share_irq = TRUE;
4559 break;
4560 #endif /* ASC_CONFIG_PCI */
4561 #else /* version >= v2.1.93 */
4562 #ifdef CONFIG_PCI
4563 case ASC_IS_PCI:
4564 shp->irq = asc_dvc_varp->irq_no = pci_devp->irq;
4565 asc_dvc_varp->cfg->pci_device_id = pci_devp->device;
4566 asc_dvc_varp->cfg->pci_slot_info =
4567 ASC_PCI_MKID(pci_devp->bus->number,
4568 PCI_SLOT(pci_devp->devfn),
4569 PCI_FUNC(pci_devp->devfn));
4570 shp->unchecked_isa_dma = FALSE;
4571 share_irq = TRUE;
4572 break;
4573 #endif /* CONFIG_PCI */
4574 #endif /* version >= v2.1.93 */
4575 default:
4576 ASC_PRINT2(
4577 "advansys_detect: board %d: unknown adapter type: %d\n",
4578 boardp->id, asc_dvc_varp->bus_type);
4579 shp->unchecked_isa_dma = TRUE;
4580 share_irq = FALSE;
4581 break;
4583 } else {
4585 * For Wide boards set PCI information before calling
4586 * AdvInitGetConfig().
4588 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4589 #ifdef ASC_CONFIG_PCI
4590 shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine;
4591 adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
4592 adv_dvc_varp->cfg->pci_slot_info =
4593 ASC_PCI_MKID(pciDevice.busNumber,
4594 pciDevice.slotFound,
4595 pciDevice.devFunc);
4596 shp->unchecked_isa_dma = FALSE;
4597 share_irq = TRUE;
4598 #endif /* ASC_CONFIG_PCI */
4599 #else /* version >= v2.1.93 */
4600 #ifdef CONFIG_PCI
4601 shp->irq = adv_dvc_varp->irq_no = pci_devp->irq;
4602 adv_dvc_varp->cfg->pci_device_id = pci_devp->device;
4603 adv_dvc_varp->cfg->pci_slot_info =
4604 ASC_PCI_MKID(pci_devp->bus->number,
4605 PCI_SLOT(pci_devp->devfn),
4606 PCI_FUNC(pci_devp->devfn));
4607 shp->unchecked_isa_dma = FALSE;
4608 share_irq = TRUE;
4609 #endif /* CONFIG_PCI */
4610 #endif /* version >= v2.1.93 */
4614 * Read the board configuration.
4616 if (ASC_NARROW_BOARD(boardp)) {
4618 * NOTE: AscInitGetConfig() may change the board's
4619 * bus_type value. The asc_bus[bus] value should no
4620 * longer be used. If the bus_type field must be
4621 * referenced only use the bit-wise AND operator "&".
4623 ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
4624 switch(ret = AscInitGetConfig(asc_dvc_varp)) {
4625 case 0: /* No error */
4626 break;
4627 case ASC_WARN_IO_PORT_ROTATE:
4628 ASC_PRINT1(
4629 "AscInitGetConfig: board %d: I/O port address modified\n",
4630 boardp->id);
4631 break;
4632 case ASC_WARN_AUTO_CONFIG:
4633 ASC_PRINT1(
4634 "AscInitGetConfig: board %d: I/O port increment switch enabled\n",
4635 boardp->id);
4636 break;
4637 case ASC_WARN_EEPROM_CHKSUM:
4638 ASC_PRINT1(
4639 "AscInitGetConfig: board %d: EEPROM checksum error\n",
4640 boardp->id);
4641 break;
4642 case ASC_WARN_IRQ_MODIFIED:
4643 ASC_PRINT1(
4644 "AscInitGetConfig: board %d: IRQ modified\n",
4645 boardp->id);
4646 break;
4647 case ASC_WARN_CMD_QNG_CONFLICT:
4648 ASC_PRINT1(
4649 "AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
4650 boardp->id);
4651 break;
4652 default:
4653 ASC_PRINT2(
4654 "AscInitGetConfig: board %d: unknown warning: %x\n",
4655 boardp->id, ret);
4656 break;
4658 if ((err_code = asc_dvc_varp->err_code) != 0) {
4659 ASC_PRINT3(
4660 "AscInitGetConfig: board %d error: init_state %x, err_code %x\n",
4661 boardp->id, asc_dvc_varp->init_state,
4662 asc_dvc_varp->err_code);
4664 } else {
4665 ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n");
4666 if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
4667 ASC_PRINT2("AdvInitGetConfig: board %d: warning: %x\n",
4668 boardp->id, ret);
4670 if ((err_code = adv_dvc_varp->err_code) != 0) {
4671 ASC_PRINT2(
4672 "AdvInitGetConfig: board %d error: err_code %x\n",
4673 boardp->id, adv_dvc_varp->err_code);
4677 if (err_code != 0) {
4678 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4679 kfree(boardp->prtbuf);
4680 #endif /* version >= v1.3.0 */
4681 scsi_unregister(shp);
4682 asc_board_count--;
4683 continue;
4687 * Save the EEPROM configuration so that it can be displayed
4688 * from /proc/scsi/advansys/[0...].
4690 if (ASC_NARROW_BOARD(boardp)) {
4692 ASCEEP_CONFIG *ep;
4695 * Set the adapter's target id bit in the 'init_tidmask' field.
4697 boardp->init_tidmask |=
4698 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
4701 * Save EEPROM settings for the board.
4703 ep = &boardp->eep_config.asc_eep;
4705 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
4706 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
4707 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
4708 ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed;
4709 ep->start_motor = asc_dvc_varp->start_motor;
4710 ep->cntl = asc_dvc_varp->dvc_cntl;
4711 ep->no_scam = asc_dvc_varp->no_scam;
4712 ep->max_total_qng = asc_dvc_varp->max_total_qng;
4713 ep->chip_scsi_id = asc_dvc_varp->cfg->chip_scsi_id;
4714 /* 'max_tag_qng' is set to the same value for every device. */
4715 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
4716 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
4717 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
4718 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
4719 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
4720 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
4721 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
4722 ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6];
4725 * Modify board configuration.
4727 ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
4728 switch (ret = AscInitSetConfig(asc_dvc_varp)) {
4729 case 0: /* No error. */
4730 break;
4731 case ASC_WARN_IO_PORT_ROTATE:
4732 ASC_PRINT1(
4733 "AscInitSetConfig: board %d: I/O port address modified\n",
4734 boardp->id);
4735 break;
4736 case ASC_WARN_AUTO_CONFIG:
4737 ASC_PRINT1(
4738 "AscInitSetConfig: board %d: I/O port increment switch enabled\n",
4739 boardp->id);
4740 break;
4741 case ASC_WARN_EEPROM_CHKSUM:
4742 ASC_PRINT1(
4743 "AscInitSetConfig: board %d: EEPROM checksum error\n",
4744 boardp->id);
4745 break;
4746 case ASC_WARN_IRQ_MODIFIED:
4747 ASC_PRINT1(
4748 "AscInitSetConfig: board %d: IRQ modified\n",
4749 boardp->id);
4750 break;
4751 case ASC_WARN_CMD_QNG_CONFLICT:
4752 ASC_PRINT1(
4753 "AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
4754 boardp->id);
4755 break;
4756 default:
4757 ASC_PRINT2(
4758 "AscInitSetConfig: board %d: unknown warning: %x\n",
4759 boardp->id, ret);
4760 break;
4762 if (asc_dvc_varp->err_code != 0) {
4763 ASC_PRINT3(
4764 "AscInitSetConfig: board %d error: init_state %x, err_code %x\n",
4765 boardp->id, asc_dvc_varp->init_state,
4766 asc_dvc_varp->err_code);
4767 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4768 kfree(boardp->prtbuf);
4769 #endif /* version >= v1.3.0 */
4770 scsi_unregister(shp);
4771 asc_board_count--;
4772 continue;
4776 * Finish initializing the 'Scsi_Host' structure.
4778 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
4779 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
4780 shp->irq = asc_dvc_varp->irq_no;
4782 } else {
4784 ADVEEP_CONFIG *ep;
4787 * Save Wide EEP Configuration Information.
4789 ep = &boardp->eep_config.adv_eep;
4791 ep->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
4792 ep->max_host_qng = adv_dvc_varp->max_host_qng;
4793 ep->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
4794 ep->termination = adv_dvc_varp->cfg->termination;
4795 ep->disc_enable = adv_dvc_varp->cfg->disc_enable;
4796 ep->bios_ctrl = adv_dvc_varp->bios_ctrl;
4797 ep->wdtr_able = adv_dvc_varp->wdtr_able;
4798 ep->sdtr_able = adv_dvc_varp->sdtr_able;
4799 ep->ultra_able = adv_dvc_varp->ultra_able;
4800 ep->tagqng_able = adv_dvc_varp->tagqng_able;
4801 ep->start_motor = adv_dvc_varp->start_motor;
4802 ep->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait;
4803 ep->bios_boot_delay = adv_dvc_varp->cfg->bios_boot_wait;
4804 ep->serial_number_word1 = adv_dvc_varp->cfg->serial1;
4805 ep->serial_number_word2 = adv_dvc_varp->cfg->serial2;
4806 ep->serial_number_word3 = adv_dvc_varp->cfg->serial3;
4809 * Set the adapter's target id bit in the 'init_tidmask' field.
4811 boardp->init_tidmask |=
4812 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
4815 * Finish initializing the 'Scsi_Host' structure.
4817 shp->irq = adv_dvc_varp->irq_no;
4820 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
4822 * Channels are numbered beginning with 0. For AdvanSys One host
4823 * structure supports one channel. Multi-channel boards have a
4824 * separate host structure for each channel.
4826 shp->max_channel = 0;
4827 #endif /* version >= v1.3.89 */
4828 if (ASC_NARROW_BOARD(boardp)) {
4829 shp->max_id = ASC_MAX_TID + 1;
4830 shp->max_lun = ASC_MAX_LUN + 1;
4832 shp->io_port = asc_dvc_varp->iop_base;
4833 shp->n_io_port = ASC_IOADR_GAP;
4834 shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
4836 /* Set maximum number of queues the adapter can handle. */
4837 shp->can_queue = asc_dvc_varp->max_total_qng;
4838 } else {
4839 shp->max_id = ADV_MAX_TID + 1;
4840 shp->max_lun = ADV_MAX_LUN + 1;
4843 * Save the I/O Port address and length even though the
4844 * in v1.3.0 and greater kernels the region is not used
4845 * by a Wide board. Instead the board is accessed with
4846 * Memory Mapped I/O.
4848 shp->io_port = iop;
4849 shp->n_io_port = ADV_CONDOR_IOLEN;
4851 shp->this_id = adv_dvc_varp->chip_scsi_id;
4853 /* Set maximum number of queues the adapter can handle. */
4854 shp->can_queue = adv_dvc_varp->max_host_qng;
4857 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
4859 * In old kernels without tag queuing support and with memory
4860 * allocation problems set a conservative 'cmd_per_lun' value.
4862 #ifdef MODULE
4863 shp->cmd_per_lun = 1;
4864 #else /* MODULE */
4865 shp->cmd_per_lun = 4;
4866 #endif /* MODULE */
4867 ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
4868 #else /* version >= v1.3.89 */
4870 * Following v1.3.89, 'cmd_per_lun' is no longer needed
4871 * and should be set to zero.
4873 * But because of a bug introduced in v1.3.89 if the driver is
4874 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
4875 * SCSI function 'allocate_device' will panic. To allow the driver
4876 * to work as a module in these kernels set 'cmd_per_lun' to 1.
4878 #ifdef MODULE
4879 shp->cmd_per_lun = 1;
4880 #else /* MODULE */
4881 shp->cmd_per_lun = 0;
4882 #endif /* MODULE */
4884 * Use the host 'select_queue_depths' function to determine
4885 * the number of commands to queue per device.
4887 shp->select_queue_depths = advansys_select_queue_depths;
4888 #endif /* version >= v1.3.89 */
4891 * Set the maximum number of scatter-gather elements the
4892 * adapter can handle.
4894 if (ASC_NARROW_BOARD(boardp)) {
4896 * Allow two commands with 'sg_tablesize' scatter-gather
4897 * elements to be executed simultaneously. This value is
4898 * the theoretical hardware limit. It may be decreased
4899 * below.
4901 shp->sg_tablesize =
4902 (((asc_dvc_varp->max_total_qng - 2) / 2) *
4903 ASC_SG_LIST_PER_Q) + 1;
4904 } else {
4905 shp->sg_tablesize = ADV_MAX_SG_LIST;
4908 #ifdef MODULE
4910 * If the driver is compiled as a module, set a limit on the
4911 * 'sg_tablesize' value to prevent memory allocation failures.
4912 * Memory allocation errors are more likely to occur at module
4913 * load time, then at driver initialization time.
4915 if (shp->sg_tablesize > 64) {
4916 shp->sg_tablesize = 64;
4918 #endif /* MODULE */
4921 * The value of 'sg_tablesize' can not exceed the SCSI
4922 * mid-level driver definition of SG_ALL. SG_ALL also
4923 * must not be exceeded, because it is used to define the
4924 * size of the scatter-gather table in 'struct asc_sg_head'.
4926 if (shp->sg_tablesize > SG_ALL) {
4927 shp->sg_tablesize = SG_ALL;
4930 ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
4931 shp->sg_tablesize);
4933 /* BIOS start address. */
4934 if (ASC_NARROW_BOARD(boardp)) {
4935 shp->base = (char *) ((ulong) AscGetChipBiosAddress(
4936 asc_dvc_varp->iop_base,
4937 asc_dvc_varp->bus_type));
4938 } else {
4940 * Fill-in BIOS board variables. The Wide BIOS saves
4941 * information in LRAM that is used by the driver.
4943 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE,
4944 boardp->bios_signature);
4945 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION,
4946 boardp->bios_version);
4947 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG,
4948 boardp->bios_codeseg);
4949 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN,
4950 boardp->bios_codelen);
4952 ASC_DBG2(1,
4953 "advansys_detect: bios_signature %x, bios_version %x\n",
4954 boardp->bios_signature, boardp->bios_version);
4956 ASC_DBG2(1,
4957 "advansys_detect: bios_codeseg %x, bios_codelen %x\n",
4958 boardp->bios_codeseg, boardp->bios_codelen);
4961 * If the BIOS saved a valid signature, then fill in
4962 * the BIOS code segment base address.
4964 if (boardp->bios_signature == 0x55AA) {
4966 * Convert x86 realmode code segment to a linear
4967 * address by shifting left 4.
4969 shp->base = (uchar *) (boardp->bios_codeseg << 4);
4970 } else {
4971 shp->base = 0;
4976 * Register Board Resources - I/O Port, DMA, IRQ
4979 /* Register I/O port range. */
4980 ASC_DBG(2, "advansys_detect: request_region()\n");
4981 request_region(shp->io_port, shp->n_io_port, "advansys");
4983 /* Register DMA Channel for Narrow boards. */
4984 shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
4985 if (ASC_NARROW_BOARD(boardp)) {
4986 /* Register DMA channel for ISA bus. */
4987 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4988 shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
4989 if ((ret =
4990 request_dma(shp->dma_channel, "advansys")) != 0) {
4991 ASC_PRINT3(
4992 "advansys_detect: board %d: request_dma() %d failed %d\n",
4993 boardp->id, shp->dma_channel, ret);
4994 release_region(shp->io_port, shp->n_io_port);
4995 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4996 kfree(boardp->prtbuf);
4997 #endif /* version >= v1.3.0 */
4998 scsi_unregister(shp);
4999 asc_board_count--;
5000 continue;
5002 AscEnableIsaDma(shp->dma_channel);
5006 /* Register IRQ Number. */
5007 ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
5008 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5009 if ((ret = request_irq(shp->irq, advansys_interrupt,
5010 SA_INTERRUPT, "advansys")) != 0)
5011 #else /* version >= v1.3.70 */
5013 * If request_irq() fails with the SA_INTERRUPT flag set,
5014 * then try again without the SA_INTERRUPT flag set. This
5015 * allows IRQ sharing to work even with other drivers that
5016 * do not set the SA_INTERRUPT flag.
5018 * If SA_INTERRUPT is not set, then interrupts are enabled
5019 * before the driver interrupt function is called.
5021 if (((ret = request_irq(shp->irq, advansys_interrupt,
5022 SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
5023 "advansys", boardp)) != 0) &&
5024 ((ret = request_irq(shp->irq, advansys_interrupt,
5025 (share_irq == TRUE ? SA_SHIRQ : 0),
5026 "advansys", boardp)) != 0))
5027 #endif /* version >= v1.3.70 */
5029 if (ret == -EBUSY) {
5030 ASC_PRINT2(
5031 "advansys_detect: board %d: request_irq(): IRQ %d already in use.\n",
5032 boardp->id, shp->irq);
5033 } else if (ret == -EINVAL) {
5034 ASC_PRINT2(
5035 "advansys_detect: board %d: request_irq(): IRQ %d not valid.\n",
5036 boardp->id, shp->irq);
5037 } else {
5038 ASC_PRINT3(
5039 "advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n",
5040 boardp->id, shp->irq, ret);
5042 release_region(shp->io_port, shp->n_io_port);
5043 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5044 iounmap(boardp->ioremap_addr);
5045 #endif /* version >= v1,3,0 */
5046 if (shp->dma_channel != NO_ISA_DMA) {
5047 free_dma(shp->dma_channel);
5049 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5050 kfree(boardp->prtbuf);
5051 #endif /* version >= v1.3.0 */
5052 scsi_unregister(shp);
5053 asc_board_count--;
5054 continue;
5058 * Initialize board RISC chip and enable interrupts.
5060 if (ASC_NARROW_BOARD(boardp)) {
5061 ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
5062 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
5063 err_code = asc_dvc_varp->err_code;
5065 if (warn_code || err_code) {
5066 ASC_PRINT4(
5067 "AscInitAsc1000Driver: board %d: error: init_state %x, warn %x error %x\n",
5068 boardp->id, asc_dvc_varp->init_state,
5069 warn_code, err_code);
5071 } else {
5072 int req_cnt;
5073 adv_req_t *reqp = NULL;
5074 int sg_cnt;
5075 adv_sgblk_t *sgp = NULL;
5077 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
5078 req_cnt = sizeof(adv_req_buf)/sizeof(adv_req_t);
5079 sg_cnt = sizeof(adv_sgblk_buf)/sizeof(adv_sgblk_t);
5080 reqp = (adv_req_t *) &adv_req_buf[0];
5081 sgp = (adv_sgblk_t *) &adv_sgblk_buf[0];
5082 #else /* version >= v1.3.0 */
5084 * Allocate up to 'max_host_qng' request structures for
5085 * the Wide board.
5087 for (req_cnt = adv_dvc_varp->max_host_qng;
5088 req_cnt > 0; req_cnt--) {
5090 reqp = (adv_req_t *)
5091 kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
5093 ASC_DBG3(1,
5094 "advansys_detect: reqp %x, req_cnt %d, bytes %d\n",
5095 (unsigned) reqp, req_cnt, sizeof(adv_req_t) * req_cnt);
5097 if (reqp != NULL) {
5098 break;
5103 * Allocate up to ADV_TOT_SG_LIST request structures for
5104 * the Wide board.
5106 for (sg_cnt = ADV_TOT_SG_LIST; sg_cnt > 0; sg_cnt--) {
5108 sgp = (adv_sgblk_t *)
5109 kmalloc(sizeof(adv_sgblk_t) * sg_cnt, GFP_ATOMIC);
5111 ASC_DBG3(1,
5112 "advansys_detect: sgp %x, sg_cnt %d, bytes %d\n",
5113 (unsigned) sgp, sg_cnt, sizeof(adv_sgblk_t) * sg_cnt);
5115 if (sgp != NULL) {
5116 break;
5119 #endif /* version >= v1.3.0 */
5122 * If no request structures or scatter-gather structures could
5123 * be allocated, then return an error. Otherwise continue with
5124 * initialization.
5126 if (reqp == NULL) {
5127 ASC_PRINT1(
5128 "advansys_detect: board %d: error: failed to kmalloc() adv_req_t buffer.\n",
5129 boardp->id);
5130 err_code = ADV_ERROR;
5131 } else if (sgp == NULL) {
5132 kfree(reqp);
5133 ASC_PRINT1(
5134 "advansys_detect: board %d: error: failed to kmalloc() adv_sgblk_t buffer.\n",
5135 boardp->id);
5136 err_code = ADV_ERROR;
5137 } else {
5140 * Save original pointer for kfree() in case the
5141 * driver is built as a module and can be unloaded.
5143 boardp->orig_reqp = reqp;
5146 * Point 'adv_reqp' to the request structures and
5147 * link them together.
5149 req_cnt--;
5150 reqp[req_cnt].next_reqp = NULL;
5151 for (; req_cnt > 0; req_cnt--) {
5152 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
5154 boardp->adv_reqp = &reqp[0];
5157 * Save original pointer for kfree() in case the
5158 * driver is built as a module and can be unloaded.
5160 boardp->orig_sgblkp = sgp;
5163 * Point 'adv_sgblkp' to the request structures and
5164 * link them together.
5166 sg_cnt--;
5167 sgp[sg_cnt].next_sgblkp = NULL;
5168 for (; sg_cnt > 0; sg_cnt--) {
5169 sgp[sg_cnt - 1].next_sgblkp = &sgp[sg_cnt];
5171 boardp->adv_sgblkp = &sgp[0];
5173 ASC_DBG(2, "advansys_detect: AdvInitAsc3550Driver()\n");
5174 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
5175 err_code = adv_dvc_varp->err_code;
5177 if (warn_code || err_code) {
5178 ASC_PRINT3(
5179 "AdvInitAsc3550Driver: board %d: error: warn %x, error %x\n",
5180 boardp->id, warn_code, adv_dvc_varp->err_code);
5185 if (err_code != 0) {
5186 release_region(shp->io_port, shp->n_io_port);
5187 if (ASC_WIDE_BOARD(boardp)) {
5188 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5189 iounmap(boardp->ioremap_addr);
5190 #endif /* version >= v1,3,0 */
5191 if (boardp->orig_reqp) {
5192 kfree(boardp->orig_reqp);
5193 boardp->orig_reqp = boardp->adv_reqp = NULL;
5195 if (boardp->orig_sgblkp) {
5196 kfree(boardp->orig_sgblkp);
5197 boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5200 if (shp->dma_channel != NO_ISA_DMA) {
5201 free_dma(shp->dma_channel);
5203 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5204 kfree(boardp->prtbuf);
5205 #endif /* version >= v1.3.0 */
5206 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5207 free_irq(shp->irq);
5208 #else /* version >= v1.3.70 */
5209 free_irq(shp->irq, boardp);
5210 #endif /* version >= v1.3.70 */
5211 scsi_unregister(shp);
5212 asc_board_count--;
5213 continue;
5215 ASC_DBG_PRT_SCSI_HOST(2, shp);
5218 ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
5219 return asc_board_count;
5223 * advansys_release()
5225 * Release resources allocated for a single AdvanSys adapter.
5228 advansys_release(struct Scsi_Host *shp)
5230 asc_board_t *boardp;
5232 ASC_DBG(1, "advansys_release: begin\n");
5233 boardp = ASC_BOARDP(shp);
5234 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5235 free_irq(shp->irq);
5236 #else /* version >= v1.3.70 */
5237 free_irq(shp->irq, boardp);
5238 #endif /* version >= v1.3.70 */
5239 if (shp->dma_channel != NO_ISA_DMA) {
5240 ASC_DBG(1, "advansys_release: free_dma()\n");
5241 free_dma(shp->dma_channel);
5243 release_region(shp->io_port, shp->n_io_port);
5244 if (ASC_WIDE_BOARD(boardp)) {
5245 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5246 iounmap(boardp->ioremap_addr);
5247 #endif /* version >= v1,3,0 */
5248 if (boardp->orig_reqp) {
5249 kfree(boardp->orig_reqp);
5250 boardp->orig_reqp = boardp->adv_reqp = NULL;
5252 if (boardp->orig_sgblkp) {
5253 kfree(boardp->orig_sgblkp);
5254 boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5257 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5258 ASC_ASSERT(boardp->prtbuf != NULL);
5259 kfree(boardp->prtbuf);
5260 #endif /* version >= v1.3.0 */
5261 scsi_unregister(shp);
5262 ASC_DBG(1, "advansys_release: end\n");
5263 return 0;
5267 * advansys_info()
5269 * Return suitable for printing on the console with the argument
5270 * adapter's configuration information.
5272 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
5273 * otherwise the static 'info' array will be overrun.
5275 const char *
5276 advansys_info(struct Scsi_Host *shp)
5278 static char info[ASC_INFO_SIZE];
5279 asc_board_t *boardp;
5280 ASC_DVC_VAR *asc_dvc_varp;
5281 ADV_DVC_VAR *adv_dvc_varp;
5282 char *busname;
5284 boardp = ASC_BOARDP(shp);
5285 if (ASC_NARROW_BOARD(boardp)) {
5286 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5287 ASC_DBG(1, "advansys_info: begin\n");
5288 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
5289 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
5290 busname = "ISA PnP";
5291 } else {
5292 busname = "ISA";
5294 sprintf(info,
5295 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5296 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u",
5297 #else /* version >= v2.1.92 */
5298 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u",
5299 #endif /* version >= v2.1.92 */
5300 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5301 (unsigned) shp->base,
5302 shp->io_port, shp->n_io_port - 1,
5303 shp->irq, shp->dma_channel);
5304 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
5305 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
5306 == ASC_IS_PCI_ULTRA) {
5307 busname = "PCI Ultra";
5308 } else {
5309 busname = "PCI";
5311 sprintf(info,
5312 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5313 "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u",
5314 #else /* version >= v2.1.92 */
5315 "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u",
5316 #endif /* version >= v2.1.92 */
5317 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5318 shp->io_port, shp->n_io_port - 1, shp->irq);
5319 } else {
5320 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
5321 busname = "VL";
5322 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
5323 busname = "EISA";
5324 } else {
5325 busname = "?";
5326 ASC_PRINT2(
5327 "advansys_info: board %d: unknown bus type %d\n",
5328 boardp->id, asc_dvc_varp->bus_type);
5330 sprintf(info,
5331 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5332 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u",
5333 #else /* version >= v2.1.92 */
5334 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u",
5335 #endif /* version >= v2.1.92 */
5336 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5337 (unsigned) shp->base, shp->io_port - 1,
5338 shp->n_io_port, shp->irq);
5340 } else {
5342 * Wide Adapter Information
5344 * Memory-mapped I/O is used instead of I/O space to access
5345 * the adapter, but display the I/O Port range. The Memory
5346 * I/O address is displayed through the driver /proc file.
5348 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5349 if (boardp->bios_signature == 0x55AA) {
5350 sprintf(info,
5351 "AdvanSys SCSI %s: PCI Ultra-Wide: BIOS %X/%X, IO %X/%X, IRQ %u",
5352 ASC_VERSION,
5353 boardp->bios_codeseg << 4,
5354 boardp->bios_codelen > 0 ?
5355 (boardp->bios_codelen << 9) - 1 : 0,
5356 (unsigned) boardp->ioport, ADV_CONDOR_IOLEN - 1,
5357 shp->irq);
5358 } else {
5359 sprintf(info,
5360 "AdvanSys SCSI %s: PCI Ultra-Wide: IO %X/%X, IRQ %u",
5361 ASC_VERSION,
5362 (unsigned) boardp->ioport,
5363 (ADV_CONDOR_IOLEN - 1),
5364 shp->irq);
5367 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
5368 ASC_DBG(1, "advansys_info: end\n");
5369 return info;
5373 * advansys_command() - polled I/O entrypoint.
5375 * Apparently host drivers shouldn't return until the command
5376 * is finished.
5378 * Note: This is an old interface that is no longer used by the SCSI
5379 * mid-level driver. The new interface, advansys_queuecommand(),
5380 * currently handles all requests.
5383 advansys_command(Scsi_Cmnd *scp)
5385 ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
5386 ASC_STATS(scp->host, command);
5387 scp->SCp.Status = 0; /* Set to a known state */
5388 advansys_queuecommand(scp, advansys_command_done);
5389 while (scp->SCp.Status == 0) {
5390 continue;
5392 ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
5393 return scp->result;
5397 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
5399 * This function always returns 0. Command return status is saved
5400 * in the 'scp' result field.
5403 advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
5405 struct Scsi_Host *shp;
5406 asc_board_t *boardp;
5407 int flags;
5408 Scsi_Cmnd *done_scp;
5410 shp = scp->host;
5411 boardp = ASC_BOARDP(shp);
5412 ASC_STATS(shp, queuecommand);
5415 * Disable interrupts to preserve request ordering and provide
5416 * mutually exclusive access to global structures used to initiate
5417 * a request.
5419 save_flags(flags);
5420 cli();
5423 * Block new commands while handling a reset or abort request.
5425 if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5426 if (boardp->flags & ASC_HOST_IN_RESET) {
5427 ASC_DBG1(1,
5428 "advansys_queuecommand: scp %x blocked for reset request\n",
5429 (unsigned) scp);
5430 scp->result = HOST_BYTE(DID_RESET);
5431 } else {
5432 ASC_DBG1(1,
5433 "advansys_queuecommand: scp %x blocked for abort request\n",
5434 (unsigned) scp);
5435 scp->result = HOST_BYTE(DID_ABORT);
5439 * Add blocked requests to the board's 'done' queue. The queued
5440 * requests will be completed at the end of the abort or reset
5441 * handling.
5443 asc_enqueue(&boardp->done, scp, ASC_BACK);
5444 restore_flags(flags);
5445 return 0;
5449 * Attempt to execute any waiting commands for the board.
5451 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5452 ASC_DBG(1,
5453 "advansys_queuecommand: before asc_execute_queue() waiting\n");
5454 asc_execute_queue(&boardp->waiting);
5458 * Save the function pointer to Linux mid-level 'done' function
5459 * and attempt to execute the command.
5461 * If ASC_ERROR is returned the request has been added to the
5462 * board's 'active' queue and will be completed by the interrupt
5463 * handler.
5465 * If ASC_BUSY is returned add the request to the board's per
5466 * target waiting list.
5468 * If an error occurred, the request will have been placed on the
5469 * board's 'done' queue and must be completed before returning.
5471 scp->scsi_done = done;
5472 switch (asc_execute_scsi_cmnd(scp)) {
5473 case ASC_NOERROR:
5474 break;
5475 case ASC_BUSY:
5476 asc_enqueue(&boardp->waiting, scp, ASC_BACK);
5477 break;
5478 case ASC_ERROR:
5479 default:
5480 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5481 /* Interrupts could be enabled here. */
5482 asc_scsi_done_list(done_scp);
5483 break;
5486 restore_flags(flags);
5487 return 0;
5491 * advansys_abort()
5493 * Abort the command specified by 'scp'.
5496 advansys_abort(Scsi_Cmnd *scp)
5498 struct Scsi_Host *shp;
5499 asc_board_t *boardp;
5500 ASC_DVC_VAR *asc_dvc_varp;
5501 ADV_DVC_VAR *adv_dvc_varp;
5502 int flags;
5503 int do_scsi_done;
5504 int scp_found;
5505 Scsi_Cmnd *done_scp = NULL;
5506 int ret;
5508 /* Save current flags and disable interrupts. */
5509 save_flags(flags);
5510 cli();
5512 ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
5514 #ifdef ADVANSYS_STATS
5515 if (scp->host != NULL) {
5516 ASC_STATS(scp->host, abort);
5518 #endif /* ADVANSYS_STATS */
5520 #ifdef ADVANSYS_ASSERT
5521 do_scsi_done = ASC_ERROR;
5522 scp_found = ASC_ERROR;
5523 ret = ASC_ERROR;
5524 #endif /* ADVANSYS_ASSERT */
5526 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5527 if (scp->serial_number != scp->serial_number_at_timeout) {
5528 ASC_PRINT1(
5529 "advansys_abort: timeout serial number changed for request %x\n",
5530 (unsigned) scp);
5531 do_scsi_done = ASC_FALSE;
5532 scp_found = ASC_FALSE;
5533 ret = SCSI_ABORT_NOT_RUNNING;
5534 } else
5535 #endif /* version >= v1.3.89 */
5536 if ((shp = scp->host) == NULL) {
5537 scp->result = HOST_BYTE(DID_ERROR);
5538 do_scsi_done = ASC_TRUE;
5539 scp_found = ASC_FALSE;
5540 ret = SCSI_ABORT_ERROR;
5541 } else if ((boardp = ASC_BOARDP(shp))->flags &
5542 (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5543 ASC_PRINT2(
5544 "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
5545 boardp->id, boardp->flags);
5546 do_scsi_done = ASC_TRUE;
5547 if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5548 (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5549 scp_found = ASC_TRUE;
5550 } else {
5551 scp_found = ASC_FALSE;
5553 scp->result = HOST_BYTE(DID_ERROR);
5554 ret = SCSI_ABORT_ERROR;
5555 } else {
5556 /* Set abort flag to avoid nested reset or abort requests. */
5557 boardp->flags |= ASC_HOST_IN_ABORT;
5559 do_scsi_done = ASC_TRUE;
5560 if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
5562 * If asc_rmqueue() found the command on the waiting
5563 * queue, it had not been sent to the device. After
5564 * the queue is removed, no other handling is required.
5566 ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
5567 (unsigned) scp);
5568 scp_found = ASC_TRUE;
5569 scp->result = HOST_BYTE(DID_ABORT);
5570 ret = SCSI_ABORT_SUCCESS;
5571 } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
5573 * If asc_isqueued() found the command on the active
5574 * queue, it has been sent to the device. The command
5575 * will be returned through the interrupt handler after
5576 * it has been aborted.
5579 if (ASC_NARROW_BOARD(boardp)) {
5581 * Narrow Board
5583 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5584 scp->result = HOST_BYTE(DID_ABORT);
5586 /* sti(); - FIXME!!! Enable interrupts for AscAbortSRB() must be careful about io_lock. */
5587 ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
5588 (unsigned) scp);
5589 switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
5590 case ASC_TRUE:
5591 /* asc_isr_callback() will be called */
5592 ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
5593 ret = SCSI_ABORT_PENDING;
5594 break;
5595 case ASC_FALSE:
5596 /* Request has apparently already completed. */
5597 ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
5598 ret = SCSI_ABORT_NOT_RUNNING;
5599 break;
5600 case ASC_ERROR:
5601 default:
5602 ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
5603 ret = SCSI_ABORT_ERROR;
5604 break;
5606 cli();
5607 } else {
5609 * Wide Board
5611 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5612 scp->result = HOST_BYTE(DID_ABORT);
5614 ASC_DBG1(1, "advansys_abort: before AdvAbortSRB(), scp %x\n",
5615 (unsigned) scp);
5616 switch (AdvAbortSRB(adv_dvc_varp, (ulong) scp)) {
5617 case ASC_TRUE:
5618 /* asc_isr_callback() will be called */
5619 ASC_DBG(1, "advansys_abort: AdvAbortSRB() TRUE\n");
5620 ret = SCSI_ABORT_PENDING;
5621 break;
5622 case ASC_FALSE:
5623 /* Request has apparently already completed. */
5624 ASC_DBG(1, "advansys_abort: AdvAbortSRB() FALSE\n");
5625 ret = SCSI_ABORT_NOT_RUNNING;
5626 break;
5627 case ASC_ERROR:
5628 default:
5629 ASC_DBG(1, "advansys_abort: AdvAbortSRB() ERROR\n");
5630 ret = SCSI_ABORT_ERROR;
5631 break;
5634 * Ensure all requests completed by the microcode have
5635 * been processed by calling AdvISR().
5637 (void) AdvISR(adv_dvc_varp);
5641 * The request will either still be on the active queue
5642 * or have been added to the board's done queue.
5644 if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
5645 scp->result = HOST_BYTE(DID_ABORT);
5646 scp_found = ASC_TRUE;
5647 } else {
5648 scp_found = asc_rmqueue(&boardp->done, scp);
5649 ASC_ASSERT(scp_found == ASC_TRUE);
5652 } else {
5654 * The command was not found on the active or waiting queues.
5656 do_scsi_done = ASC_TRUE;
5657 scp_found = ASC_FALSE;
5658 ret = SCSI_ABORT_NOT_RUNNING;
5661 /* Clear abort flag. */
5662 boardp->flags &= ~ASC_HOST_IN_ABORT;
5665 * Because the ASC_HOST_IN_ABORT flag causes both
5666 * 'advansys_interrupt' and 'asc_isr_callback' to
5667 * queue requests to the board's 'done' queue and
5668 * prevents waiting commands from being executed,
5669 * these queued requests must be handled here.
5671 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5674 * Start any waiting commands for the board.
5676 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5677 ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
5678 asc_execute_queue(&boardp->waiting);
5682 /* Interrupts could be enabled here. */
5685 * Complete the request to be aborted, unless it has been
5686 * restarted as detected above, even if it was not found on
5687 * the device active or waiting queues.
5689 ASC_ASSERT(do_scsi_done != ASC_ERROR);
5690 ASC_ASSERT(scp_found != ASC_ERROR);
5691 if (do_scsi_done == ASC_TRUE) {
5692 if (scp->scsi_done == NULL) {
5693 ASC_PRINT1(
5694 "advansys_abort: aborted request scsi_done() is NULL, %x\n",
5695 (unsigned) scp);
5696 } else {
5697 if (scp_found == ASC_FALSE) {
5698 ASC_PRINT1(
5699 "advansys_abort: abort request not active or waiting, completing anyway %x\n",
5700 (unsigned) scp);
5702 ASC_STATS(scp->host, done);
5703 scp->scsi_done(scp);
5708 * It is possible for the request done function to re-enable
5709 * interrupts without confusing the driver. But here interrupts
5710 * aren't enabled until all requests have been completed.
5712 if (done_scp != NULL) {
5713 asc_scsi_done_list(done_scp);
5716 ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
5718 /* Re-enable interrupts, if they were enabled on entry. */
5719 restore_flags(flags);
5721 ASC_ASSERT(ret != ASC_ERROR);
5722 return ret;
5726 * advansys_reset()
5728 * Reset the device associated with the command 'scp'.
5731 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
5732 advansys_reset(Scsi_Cmnd *scp)
5733 #else /* version >= v1.3.89 */
5734 advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
5735 #endif /* version >= v1.3.89 */
5737 struct Scsi_Host *shp;
5738 asc_board_t *boardp;
5739 ASC_DVC_VAR *asc_dvc_varp;
5740 ADV_DVC_VAR *adv_dvc_varp;
5741 int flags;
5742 Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
5743 Scsi_Cmnd *tscp, *new_last_scp;
5744 int do_scsi_done;
5745 int scp_found;
5746 int status;
5747 int target;
5748 int ret;
5749 int device_reset = ASC_FALSE;
5751 /* Save current flags and disable interrupts. */
5752 save_flags(flags);
5753 cli();
5755 ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
5757 #ifdef ADVANSYS_STATS
5758 if (scp->host != NULL) {
5759 ASC_STATS(scp->host, reset);
5761 #endif /* ADVANSYS_STATS */
5763 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5764 if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) &&
5765 (scp->serial_number != scp->serial_number_at_timeout)) {
5766 ASC_PRINT1(
5767 "advansys_reset: timeout serial number changed for request %x\n",
5768 (unsigned) scp);
5769 do_scsi_done = ASC_FALSE;
5770 scp_found = ASC_FALSE;
5771 ret = SCSI_RESET_NOT_RUNNING;
5772 } else
5773 #endif /* version >= v1.3.89 */
5774 if ((shp = scp->host) == NULL) {
5775 scp->result = HOST_BYTE(DID_ERROR);
5776 do_scsi_done = ASC_TRUE;
5777 scp_found = ASC_FALSE;
5778 ret = SCSI_RESET_ERROR;
5779 } else if ((boardp = ASC_BOARDP(shp))->flags &
5780 (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5781 ASC_PRINT2(
5782 "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
5783 boardp->id, boardp->flags);
5784 do_scsi_done = ASC_TRUE;
5785 if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5786 (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5787 scp_found = ASC_TRUE;
5788 } else {
5789 scp_found = ASC_FALSE;
5791 scp->result = HOST_BYTE(DID_ERROR);
5792 ret = SCSI_RESET_ERROR;
5793 } else if (time_after_eq(jiffies, boardp->last_reset) &&
5794 time_before(jiffies, boardp->last_reset + (10 * HZ))) {
5796 * Don't allow a reset to be attempted within 10 seconds
5797 * of the last reset.
5799 * If 'jiffies' wrapping occurs, the reset request will go
5800 * through, because a wrapped 'jiffies' would not pass the
5801 * test above.
5803 ASC_DBG(1,
5804 "advansys_reset: reset within 10 sec of last reset ignored\n");
5805 do_scsi_done = ASC_TRUE;
5806 if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5807 (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5808 scp_found = ASC_TRUE;
5809 } else {
5810 scp_found = ASC_FALSE;
5812 scp->result = HOST_BYTE(DID_ERROR);
5813 ret = SCSI_RESET_ERROR;
5814 } else {
5815 do_scsi_done = ASC_TRUE;
5817 /* Set reset flag to avoid nested reset or abort requests. */
5818 boardp->flags |= ASC_HOST_IN_RESET;
5821 * If the request is on the target waiting or active queue
5822 * or the board done queue, then remove it and note that it
5823 * was found.
5825 if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
5826 ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
5827 scp_found = ASC_TRUE;
5828 } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
5829 ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
5830 scp_found = ASC_TRUE;
5831 } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
5832 scp_found = ASC_TRUE;
5833 } else {
5834 scp_found = ASC_FALSE;
5838 if (ASC_NARROW_BOARD(boardp)) {
5840 * Narrow Board
5842 * If the suggest reset bus flags are set, then reset the bus.
5843 * Otherwise only reset the device.
5845 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5846 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5847 if (reset_flags &
5848 (SCSI_RESET_SUGGEST_BUS_RESET |
5849 SCSI_RESET_SUGGEST_HOST_RESET)) {
5850 #endif /* version >= v1.3.89 */
5853 * Reset the target's SCSI bus.
5855 ASC_DBG(1, "advansys_reset: before AscResetSB()\n");
5856 /* sti(); FIXME!!! Enable interrupts for AscResetSB(). */
5857 status = AscResetSB(asc_dvc_varp);
5858 /* cli(); FIXME!!! */
5859 switch (status) {
5860 case ASC_TRUE:
5861 ASC_DBG(1, "advansys_reset: AscResetSB() success\n");
5862 ret = SCSI_RESET_SUCCESS;
5863 break;
5864 case ASC_ERROR:
5865 default:
5866 ASC_DBG(1, "advansys_reset: AscResetSB() failed\n");
5867 ret = SCSI_RESET_ERROR;
5868 break;
5871 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5872 } else {
5874 * Reset the specified device. If the device reset fails,
5875 * then reset the SCSI bus.
5878 ASC_DBG1(1,
5879 "advansys_reset: before AscResetDevice(), target %d\n",
5880 scp->target);
5881 /* sti(); FIXME!!! Enable interrupts for AscResetDevice(). */
5882 status = AscResetDevice(asc_dvc_varp, scp->target);
5883 /* cli(); FIXME!!! */
5885 switch (status) {
5886 case ASC_TRUE:
5887 ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
5888 device_reset = ASC_TRUE;
5889 ret = SCSI_RESET_SUCCESS;
5890 break;
5891 case ASC_ERROR:
5892 default:
5893 ASC_DBG(1,
5894 "advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n");
5895 /* sti(); FIXME!!! Enable interrupts for AscResetSB(). */
5896 status = AscResetSB(asc_dvc_varp);
5897 /* cli(); */
5898 switch (status) {
5899 case ASC_TRUE:
5900 ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
5901 ret = SCSI_RESET_SUCCESS;
5902 break;
5903 case ASC_ERROR:
5904 default:
5905 ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
5906 ret = SCSI_RESET_ERROR;
5907 break;
5909 break;
5912 #endif /* version >= v1.3.89 */
5913 } else {
5915 * Wide Board
5917 * If the suggest reset bus flags are set, then reset the bus.
5918 * Otherwise only reset the device.
5920 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5921 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5922 if (reset_flags &
5923 (SCSI_RESET_SUGGEST_BUS_RESET |
5924 SCSI_RESET_SUGGEST_HOST_RESET)) {
5925 #endif /* version >= v1.3.89 */
5928 * Reset the target's SCSI bus.
5930 ASC_DBG(1, "advansys_reset: before AdvResetSB()\n");
5931 switch (AdvResetSB(adv_dvc_varp)) {
5932 case ASC_TRUE:
5933 ASC_DBG(1, "advansys_reset: AdvResetSB() success\n");
5934 ret = SCSI_RESET_SUCCESS;
5935 break;
5936 case ASC_FALSE:
5937 default:
5938 ASC_DBG(1, "advansys_reset: AdvResetSB() failed\n");
5939 ret = SCSI_RESET_ERROR;
5940 break;
5943 * Ensure all requests completed by the microcode have
5944 * been processed by calling AdvISR().
5946 (void) AdvISR(adv_dvc_varp);
5947 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5948 } else {
5950 * Reset the specified device. If the device reset fails,
5951 * then reset the SCSI bus.
5954 ASC_DBG1(1,
5955 "advansys_reset: before AdvResetDevice(), target %d\n",
5956 scp->target);
5958 switch (AdvResetDevice(adv_dvc_varp, scp->target)) {
5959 case ASC_TRUE:
5960 ASC_DBG(1, "advansys_reset: AdvResetDevice() success\n");
5961 device_reset = ASC_TRUE;
5962 ret = SCSI_RESET_SUCCESS;
5963 break;
5964 case ASC_FALSE:
5965 default:
5966 ASC_DBG(1,
5967 "advansys_reset: AdvResetDevice() failed; Calling AdvResetSB()\n");
5969 switch (AdvResetSB(adv_dvc_varp)) {
5970 case ASC_TRUE:
5971 ASC_DBG(1, "advansys_reset: AdvResetSB() TRUE\n");
5972 ret = SCSI_RESET_SUCCESS;
5973 break;
5974 case ASC_FALSE:
5975 default:
5976 ASC_DBG(1, "advansys_reset: AdvResetSB() ERROR\n");
5977 ret = SCSI_RESET_ERROR;
5978 break;
5980 break;
5983 * Ensure all requests completed by the microcode have
5984 * been processed by calling AdvISR().
5986 (void) AdvISR(adv_dvc_varp);
5988 #endif /* version >= v1.3.89 */
5992 * Because the ASC_HOST_IN_RESET flag causes both
5993 * 'advansys_interrupt' and 'asc_isr_callback' to
5994 * queue requests to the board's 'done' queue and
5995 * prevents waiting commands from being executed,
5996 * these queued requests must be handled here.
5998 done_scp = asc_dequeue_list(&boardp->done, &last_scp,
5999 ASC_TID_ALL);
6002 * If a device reset was performed dequeue all waiting
6003 * and active requests for the device and set the request
6004 * status to DID_RESET.
6006 * If a SCSI bus reset was performed dequeue all waiting
6007 * and active requests for all devices and set the request
6008 * status to DID_RESET.
6010 if (device_reset == ASC_TRUE) {
6011 target = scp->target;
6012 } else {
6013 target = ASC_TID_ALL;
6017 * Add active requests to 'done_scp' and set the request status
6018 * to DID_RESET.
6020 if (done_scp == NULL) {
6021 done_scp = asc_dequeue_list(&boardp->active, &last_scp, target);
6022 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
6023 tscp->result = HOST_BYTE(DID_RESET);
6025 } else {
6026 ASC_ASSERT(last_scp != NULL);
6027 REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
6028 &new_last_scp, target);
6029 if (new_last_scp != NULL) {
6030 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6031 for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
6032 tscp->result = HOST_BYTE(DID_RESET);
6034 last_scp = new_last_scp;
6039 * Add waiting requests to 'done_scp' and set the request status
6040 * to DID_RESET.
6042 if (done_scp == NULL) {
6043 done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target);
6044 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
6045 tscp->result = HOST_BYTE(DID_RESET);
6047 } else {
6048 ASC_ASSERT(last_scp != NULL);
6049 REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
6050 &new_last_scp, target);
6051 if (new_last_scp != NULL) {
6052 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6053 for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
6054 tscp->result = HOST_BYTE(DID_RESET);
6056 last_scp = new_last_scp;
6060 /* Save the time of the most recently completed reset. */
6061 boardp->last_reset = jiffies;
6063 /* Clear reset flag. */
6064 boardp->flags &= ~ASC_HOST_IN_RESET;
6067 * Start any waiting commands for the board.
6069 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6070 ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6071 asc_execute_queue(&boardp->waiting);
6073 ret = SCSI_RESET_SUCCESS;
6076 /* Interrupts could be enabled here. */
6078 ASC_ASSERT(do_scsi_done != ASC_ERROR);
6079 ASC_ASSERT(scp_found != ASC_ERROR);
6080 if (do_scsi_done == ASC_TRUE) {
6081 if (scp->scsi_done == NULL) {
6082 ASC_PRINT1(
6083 "advansys_reset: reset request scsi_done() is NULL, %x\n",
6084 (unsigned) scp);
6085 } else {
6086 if (scp_found == ASC_FALSE) {
6087 ASC_PRINT1(
6088 "advansys_reset: reset request not active or waiting, completing anyway %x\n",
6089 (unsigned) scp);
6091 ASC_STATS(scp->host, done);
6092 scp->scsi_done(scp);
6097 * It is possible for the request done function to re-enable
6098 * interrupts without confusing the driver. But here interrupts
6099 * aren't enabled until requests have been completed.
6101 if (done_scp != NULL) {
6102 asc_scsi_done_list(done_scp);
6105 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
6107 /* Re-enable interrupts, if they were enabled on entry. */
6108 restore_flags(flags);
6110 ASC_ASSERT(ret != ASC_ERROR);
6111 return ret;
6115 * advansys_biosparam()
6117 * Translate disk drive geometry if the "BIOS greater than 1 GB"
6118 * support is enabled for a drive.
6120 * ip (information pointer) is an int array with the following definition:
6121 * ip[0]: heads
6122 * ip[1]: sectors
6123 * ip[2]: cylinders
6126 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
6127 advansys_biosparam(Disk *dp, int dep, int ip[])
6128 #else /* version >= v1.3.0 */
6129 advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
6130 #endif /* version >= v1.3.0 */
6132 asc_board_t *boardp;
6134 ASC_DBG(1, "advansys_biosparam: begin\n");
6135 ASC_STATS(dp->device->host, biosparam);
6136 boardp = ASC_BOARDP(dp->device->host);
6137 if (ASC_NARROW_BOARD(boardp)) {
6138 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
6139 ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
6140 ip[0] = 255;
6141 ip[1] = 63;
6142 } else {
6143 ip[0] = 64;
6144 ip[1] = 32;
6146 } else {
6147 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
6148 BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) {
6149 ip[0] = 255;
6150 ip[1] = 63;
6151 } else {
6152 ip[0] = 64;
6153 ip[1] = 32;
6156 ip[2] = dp->capacity / (ip[0] * ip[1]);
6157 ASC_DBG(1, "advansys_biosparam: end\n");
6158 return 0;
6162 * advansys_setup()
6164 * This function is called from init/main.c at boot time.
6165 * It it passed LILO parameters that can be set from the
6166 * LILO command line or in /etc/lilo.conf.
6168 * It is used by the AdvanSys driver to either disable I/O
6169 * port scanning or to limit scanning to 1 - 4 I/O ports.
6170 * Regardless of the option setting EISA and PCI boards
6171 * will still be searched for and detected. This option
6172 * only affects searching for ISA and VL boards.
6174 * If ADVANSYS_DEBUG is defined the driver debug level may
6175 * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
6177 * Examples:
6178 * 1. Eliminate I/O port scanning:
6179 * boot: linux advansys=
6180 * or
6181 * boot: linux advansys=0x0
6182 * 2. Limit I/O port scanning to one I/O port:
6183 * boot: linux advansys=0x110
6184 * 3. Limit I/O port scanning to four I/O ports:
6185 * boot: linux advansys=0x110,0x210,0x230,0x330
6186 * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
6187 * set the driver debug level to 2.
6188 * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
6190 * ints[0] - number of arguments
6191 * ints[1] - first argument
6192 * ints[2] - second argument
6193 * ...
6195 ASC_INITFUNC(
6196 void
6197 advansys_setup(char *str, int *ints)
6200 int i;
6202 if (asc_iopflag == ASC_TRUE) {
6203 printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
6204 return;
6207 asc_iopflag = ASC_TRUE;
6209 if (ints[0] > ASC_NUM_IOPORT_PROBE) {
6210 #ifdef ADVANSYS_DEBUG
6211 if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
6212 (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
6213 asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
6214 } else {
6215 #endif /* ADVANSYS_DEBUG */
6216 printk("AdvanSys SCSI: only %d I/O ports accepted\n",
6217 ASC_NUM_IOPORT_PROBE);
6218 #ifdef ADVANSYS_DEBUG
6220 #endif /* ADVANSYS_DEBUG */
6223 #ifdef ADVANSYS_DEBUG
6224 ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
6225 for (i = 1; i < ints[0]; i++) {
6226 ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
6228 ASC_DBG(1, "\n");
6229 #endif /* ADVANSYS_DEBUG */
6231 for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
6232 asc_ioport[i-1] = ints[i];
6233 ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
6234 i - 1, asc_ioport[i-1]);
6240 * --- Loadable Driver Support
6243 #ifdef MODULE
6244 Scsi_Host_Template driver_template = ADVANSYS;
6245 # include "scsi_module.c"
6246 #endif /* MODULE */
6250 * --- Miscellaneous Driver Functions
6254 * First-level interrupt handler.
6256 * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting
6257 * adapter's asc_board_t. Because all boards are currently checked
6258 * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id'
6259 * could be used to identify an interrupt passed to the AdvanSys driver,
6260 * which is for a device sharing an interrupt with an AdvanSys adapter.
6262 STATIC void
6263 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
6264 advansys_interrupt(int irq, struct pt_regs *regs)
6265 #else /* version >= v1.3.70 */
6266 advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
6267 #endif /* version >= v1.3.70 */
6269 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6270 int flags;
6271 #else /* version >= v2.1.95 */
6272 unsigned long flags;
6273 #endif /* version >= v2.1.95 */
6274 int i;
6275 asc_board_t *boardp;
6276 Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
6277 Scsi_Cmnd *new_last_scp;
6279 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6280 /* Disable interrupts, if they aren't already disabled. */
6281 save_flags(flags);
6282 cli();
6283 #else /* version >= v2.1.95 */
6285 * Disable interrupts, if they aren't already disabled and acquire
6286 * the I/O spinlock.
6288 spin_lock_irqsave(&io_request_lock, flags);
6289 #endif /* version >= v2.1.95 */
6291 ASC_DBG(1, "advansys_interrupt: begin\n");
6294 * Check for interrupts on all boards.
6295 * AscISR() will call asc_isr_callback().
6297 for (i = 0; i < asc_board_count; i++) {
6298 boardp = ASC_BOARDP(asc_host[i]);
6299 ASC_DBG2(2, "advansys_interrupt: i %d, boardp %lx\n",
6300 i, (ulong) boardp)
6301 if (ASC_NARROW_BOARD(boardp)) {
6303 * Narrow Board
6305 if (AscIsIntPending(asc_host[i]->io_port)) {
6306 ASC_STATS(asc_host[i], interrupt);
6307 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
6308 AscISR(&boardp->dvc_var.asc_dvc_var);
6310 } else {
6312 * Wide Board
6314 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
6315 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
6316 ASC_STATS(asc_host[i], interrupt);
6321 * Start waiting requests and create a list of completed requests.
6323 * If a reset or abort request is being performed for the board,
6324 * the reset or abort handler will complete pending requests after
6325 * it has completed.
6327 if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) {
6328 ASC_DBG2(1, "advansys_interrupt: done_scp %lx, last_scp %lx\n",
6329 (ulong) done_scp, (ulong) last_scp);
6331 /* Start any waiting commands for the board. */
6332 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6333 ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6334 asc_execute_queue(&boardp->waiting);
6338 * Add to the list of requests that must be completed.
6340 * 'done_scp' will always be NULL on the first iteration
6341 * of this loop. 'last_scp' is set at the same time as
6342 * 'done_scp'.
6344 if (done_scp == NULL) {
6345 done_scp = asc_dequeue_list(&boardp->done, &last_scp,
6346 ASC_TID_ALL);
6347 } else {
6348 ASC_ASSERT(last_scp != NULL);
6349 REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
6350 &new_last_scp, ASC_TID_ALL);
6351 if (new_last_scp != NULL) {
6352 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6353 last_scp = new_last_scp;
6359 /* Interrupts could be enabled here. */
6362 * It is possible for the request done function to re-enable
6363 * interrupts without confusing the driver. But here the
6364 * original flags aren't restored until all requests have been
6365 * completed.
6367 asc_scsi_done_list(done_scp);
6369 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6371 * Restore the original flags which will enable interrupts
6372 * if and only if they were enabled on entry.
6374 restore_flags(flags);
6375 #else /* version >= v2.1.95 */
6377 * Release the I/O spinlock and restore the original flags
6378 * which will enable interrupts if and only if they were
6379 * enabled on entry.
6381 spin_unlock_irqrestore(&io_request_lock, flags);
6382 #endif /* version >= v2.1.95 */
6384 ASC_DBG(1, "advansys_interrupt: end\n");
6385 return;
6388 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6390 * Set the number of commands to queue per device for the
6391 * specified host adapter.
6393 STATIC void
6394 advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
6396 Scsi_Device *device;
6397 asc_board_t *boardp;
6399 boardp = ASC_BOARDP(shp);
6400 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
6401 for (device = devicelist; device != NULL; device = device->next) {
6402 if (device->host != shp) {
6403 continue;
6406 * Save a pointer to the device and set its initial/maximum
6407 * queue depth.
6409 boardp->device[device->id] = device;
6410 if (ASC_NARROW_BOARD(boardp)) {
6411 device->queue_depth =
6412 boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id];
6413 } else {
6414 device->queue_depth =
6415 boardp->dvc_var.adv_dvc_var.max_dvc_qng;
6417 ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
6418 (unsigned) shp, device->id, device->queue_depth);
6421 #endif /* version >= v1.3.89 */
6424 * Function used only with polled I/O requests that are initiated by
6425 * advansys_command().
6427 STATIC void
6428 advansys_command_done(Scsi_Cmnd *scp)
6430 ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
6431 scp->SCp.Status = 1;
6435 * Complete all requests on the singly linked list pointed
6436 * to by 'scp'.
6438 * Interrupts can be enabled on entry.
6440 STATIC void
6441 asc_scsi_done_list(Scsi_Cmnd *scp)
6443 Scsi_Cmnd *tscp;
6445 ASC_DBG(2, "asc_scsi_done_list: begin\n");
6446 while (scp != NULL) {
6447 ASC_DBG1(3, "asc_scsi_done_list: scp %x\n", (unsigned) scp);
6448 tscp = REQPNEXT(scp);
6449 REQPNEXT(scp) = NULL;
6450 ASC_STATS(scp->host, done);
6451 ASC_ASSERT(scp->scsi_done != NULL);
6452 scp->scsi_done(scp);
6453 scp = tscp;
6455 ASC_DBG(2, "asc_scsi_done_list: done\n");
6456 return;
6460 * Execute a single 'Scsi_Cmnd'.
6462 * The function 'done' is called when the request has been completed.
6464 * Scsi_Cmnd:
6466 * host - board controlling device
6467 * device - device to send command
6468 * target - target of device
6469 * lun - lun of device
6470 * cmd_len - length of SCSI CDB
6471 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
6472 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
6474 * if (use_sg == 0) {
6475 * request_buffer - buffer address for request
6476 * request_bufflen - length of request buffer
6477 * } else {
6478 * request_buffer - pointer to scatterlist structure
6481 * sense_buffer - sense command buffer
6483 * result (4 bytes of an int):
6484 * Byte Meaning
6485 * 0 SCSI Status Byte Code
6486 * 1 SCSI One Byte Message Code
6487 * 2 Host Error Code
6488 * 3 Mid-Level Error Code
6490 * host driver fields:
6491 * SCp - Scsi_Pointer used for command processing status
6492 * scsi_done - used to save caller's done function
6493 * host_scribble - used for pointer to another Scsi_Cmnd
6495 * If this function returns ASC_NOERROR or ASC_ERROR the request
6496 * has been enqueued on the board's 'done' queue and must be
6497 * completed by the caller.
6499 * If ASC_BUSY is returned the request must be enqueued by the
6500 * caller and re-tried later.
6502 STATIC int
6503 asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
6505 asc_board_t *boardp;
6506 ASC_DVC_VAR *asc_dvc_varp;
6507 ADV_DVC_VAR *adv_dvc_varp;
6508 ADV_SCSI_REQ_Q *adv_scsiqp;
6509 Scsi_Device *device;
6510 int ret;
6512 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
6513 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
6514 (unsigned) scp, (unsigned) scp->scsi_done);
6516 boardp = ASC_BOARDP(scp->host);
6517 device = boardp->device[scp->target];
6519 if (ASC_NARROW_BOARD(boardp)) {
6521 * Build and execute Narrow Board request.
6524 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6527 * Build Asc Library request structure using the
6528 * global structures 'asc_scsi_req' and 'asc_sg_head'.
6530 * asc_build_req() can not return ASC_BUSY.
6532 if (asc_build_req(boardp, scp) == ASC_ERROR) {
6533 ASC_STATS(scp->host, build_error);
6534 return ASC_ERROR;
6538 * Execute the command. If there is no error, add the command
6539 * to the active queue.
6541 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
6542 case ASC_NOERROR:
6543 ASC_STATS(scp->host, exe_noerror);
6545 * Increment monotonically increasing per device successful
6546 * request counter. Wrapping doesn't matter.
6548 boardp->reqcnt[scp->target]++;
6550 #if ASC_QUEUE_FLOW_CONTROL
6552 * Conditionally increment the device queue depth.
6554 * If no error occurred and there have been 100 consecutive
6555 * successful requests and the current queue depth is less
6556 * than the maximum queue depth, then increment the current
6557 * queue depth.
6559 if (boardp->nerrcnt[scp->target]++ > 100) {
6560 boardp->nerrcnt[scp->target] = 0;
6561 if (device != NULL &&
6562 (device->queue_curr_depth < device->queue_depth) &&
6563 (!(boardp->queue_full &
6564 ADV_TID_TO_TIDMASK(scp->target)) ||
6565 (boardp->queue_full_cnt[scp->target] >
6566 device->queue_curr_depth))) {
6567 device->queue_curr_depth++;
6570 #endif /* ASC_QUEUE_FLOW_CONTROL */
6571 asc_enqueue(&boardp->active, scp, ASC_BACK);
6572 ASC_DBG(1,
6573 "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
6574 break;
6575 case ASC_BUSY:
6576 /* Caller must enqueue request and retry later. */
6577 ASC_STATS(scp->host, exe_busy);
6578 #if ASC_QUEUE_FLOW_CONTROL
6580 * Clear consecutive no error counter and if possible decrement
6581 * queue depth.
6583 boardp->nerrcnt[scp->target] = 0;
6584 if (device != NULL && device->queue_curr_depth > 1) {
6585 device->queue_curr_depth--;
6587 #endif /* ASC_QUEUE_FLOW_CONTROL */
6588 break;
6589 case ASC_ERROR:
6590 ASC_PRINT2(
6591 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
6592 boardp->id, asc_dvc_varp->err_code);
6593 ASC_STATS(scp->host, exe_error);
6594 #if ASC_QUEUE_FLOW_CONTROL
6595 /* Clear consecutive no error counter. */
6596 boardp->nerrcnt[scp->target] = 0;
6597 #endif /* ASC_QUEUE_FLOW_CONTROL */
6598 scp->result = HOST_BYTE(DID_ERROR);
6599 asc_enqueue(&boardp->done, scp, ASC_BACK);
6600 break;
6601 default:
6602 ASC_PRINT2(
6603 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
6604 boardp->id, asc_dvc_varp->err_code);
6605 ASC_STATS(scp->host, exe_unknown);
6606 #if ASC_QUEUE_FLOW_CONTROL
6607 /* Clear consecutive no error counter. */
6608 boardp->nerrcnt[scp->target] = 0;
6609 #endif /* ASC_QUEUE_FLOW_CONTROL */
6610 scp->result = HOST_BYTE(DID_ERROR);
6611 asc_enqueue(&boardp->done, scp, ASC_BACK);
6612 break;
6614 } else {
6616 * Build and execute Wide Board request.
6618 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6621 * Build and get a pointer to an Adv Library request structure.
6623 * If the request is successfully built then send it below,
6624 * otherwise return with an error.
6626 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
6627 case ASC_NOERROR:
6628 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
6629 break;
6630 case ASC_BUSY:
6631 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
6632 return ASC_BUSY;
6633 case ASC_ERROR:
6634 default:
6635 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
6636 ASC_STATS(scp->host, build_error);
6637 return ASC_ERROR;
6641 * Execute the command. If there is no error, add the command
6642 * to the active queue.
6644 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
6645 case ASC_NOERROR:
6646 ASC_STATS(scp->host, exe_noerror);
6648 * Increment monotonically increasing per device successful
6649 * request counter. Wrapping doesn't matter.
6651 boardp->reqcnt[scp->target]++;
6652 asc_enqueue(&boardp->active, scp, ASC_BACK);
6653 ASC_DBG(1,
6654 "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
6655 break;
6656 case ASC_BUSY:
6657 /* Caller must enqueue request and retry later. */
6658 ASC_STATS(scp->host, exe_busy);
6659 break;
6660 case ASC_ERROR:
6661 ASC_PRINT2(
6662 "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code %x\n",
6663 boardp->id, adv_dvc_varp->err_code);
6664 ASC_STATS(scp->host, exe_error);
6665 scp->result = HOST_BYTE(DID_ERROR);
6666 asc_enqueue(&boardp->done, scp, ASC_BACK);
6667 break;
6668 default:
6669 ASC_PRINT2(
6670 "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code %x\n",
6671 boardp->id, adv_dvc_varp->err_code);
6672 ASC_STATS(scp->host, exe_unknown);
6673 scp->result = HOST_BYTE(DID_ERROR);
6674 asc_enqueue(&boardp->done, scp, ASC_BACK);
6675 break;
6679 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
6680 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
6681 return ret;
6685 * Build a request structure for the Asc Library (Narrow Board).
6687 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
6688 * used to build the request.
6690 * If an error occurs, then return ASC_ERROR.
6692 STATIC int
6693 asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp)
6696 * Mutually exclusive access is required to 'asc_scsi_q' and
6697 * 'asc_sg_head' until after the request is started.
6699 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
6702 * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
6704 asc_scsi_q.q2.srb_ptr = (ulong) scp;
6707 * Build the ASC_SCSI_Q request.
6709 ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
6710 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
6711 scp->cmd_len = ASC_MAX_CDB_LEN;
6713 asc_scsi_q.cdbptr = &scp->cmnd[0];
6714 asc_scsi_q.q2.cdb_len = scp->cmd_len;
6715 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
6716 asc_scsi_q.q1.target_lun = scp->lun;
6717 asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
6718 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6719 asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
6720 #else /* version >= v2.0.0 */
6721 asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
6722 #endif /* version >= v2.0.0 */
6723 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
6726 * If there are any outstanding requests for the current target,
6727 * then every 255th request send an ORDERED request. This heuristic
6728 * tries to retain the benefit of request sorting while preventing
6729 * request starvation. 255 is the max number of tags or pending commands
6730 * a device may have outstanding.
6732 * The request count is incremented below for every successfully
6733 * started request.
6736 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->target] > 0) &&
6737 (boardp->reqcnt[scp->target] % 255) == 0) {
6738 asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
6739 } else {
6740 asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
6744 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
6745 * buffer command.
6747 if (scp->use_sg == 0) {
6749 * CDB request of single contiguous buffer.
6751 ASC_STATS(scp->host, cont_cnt);
6752 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6753 asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
6754 #else /* version >= v2.0.0 */
6755 asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
6756 #endif /* version >= v2.0.0 */
6757 asc_scsi_q.q1.data_cnt = scp->request_bufflen;
6758 ASC_STATS_ADD(scp->host, cont_xfer,
6759 ASC_CEILING(scp->request_bufflen, 512));
6760 asc_scsi_q.q1.sg_queue_cnt = 0;
6761 asc_scsi_q.sg_head = NULL;
6762 } else {
6764 * CDB scatter-gather request list.
6766 int sgcnt;
6767 struct scatterlist *slp;
6769 if (scp->use_sg > scp->host->sg_tablesize) {
6770 ASC_PRINT3(
6771 "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
6772 boardp->id, scp->use_sg, scp->host->sg_tablesize);
6773 scp->result = HOST_BYTE(DID_ERROR);
6774 asc_enqueue(&boardp->done, scp, ASC_BACK);
6775 return ASC_ERROR;
6778 ASC_STATS(scp->host, sg_cnt);
6781 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
6782 * structure to point to it.
6784 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
6786 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
6787 asc_scsi_q.sg_head = &asc_sg_head;
6788 asc_scsi_q.q1.data_cnt = 0;
6789 asc_scsi_q.q1.data_addr = 0;
6790 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
6791 ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt);
6794 * Convert scatter-gather list into ASC_SG_HEAD list.
6796 slp = (struct scatterlist *) scp->request_buffer;
6797 for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
6798 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6799 asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
6800 #else /* version >= v2.0.0 */
6801 asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
6802 #endif /* version >= v2.0.0 */
6803 asc_sg_head.sg_list[sgcnt].bytes = slp->length;
6804 ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
6808 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
6809 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
6811 return ASC_NOERROR;
6815 * Build a request structure for the Adv Library (Wide Board).
6817 * If an adv_req_t can not be allocated to issue the request,
6818 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
6820 STATIC int
6821 adv_build_req(asc_board_t *boardp, Scsi_Cmnd *scp,
6822 ADV_SCSI_REQ_Q **adv_scsiqpp)
6824 adv_req_t *reqp;
6825 ADV_SCSI_REQ_Q *scsiqp;
6826 int i;
6829 * Allocate an adv_req_t structure from the board to execute
6830 * the command.
6832 if (boardp->adv_reqp == NULL) {
6833 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
6834 ASC_STATS(scp->host, adv_build_noreq);
6835 return ASC_BUSY;
6836 } else {
6837 reqp = boardp->adv_reqp;
6838 boardp->adv_reqp = reqp->next_reqp;
6839 reqp->next_reqp = NULL;
6843 * Get 4-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
6845 scsiqp = (ADV_SCSI_REQ_Q *) ADV_DWALIGN(&reqp->scsi_req_q);
6846 memset(scsiqp, 0, sizeof(ADV_SCSI_REQ_Q));
6849 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
6851 scsiqp->srb_ptr = (ulong) reqp;
6854 * Set the adv_req_t 'cmndp' to point to the Scsi_Cmnd structure.
6856 reqp->cmndp = scp;
6859 * Build the ADV_SCSI_REQ_Q request.
6863 * Set CDB length and copy it to the request structure.
6865 ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
6866 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
6867 scp->cmd_len = ASC_MAX_CDB_LEN;
6869 scsiqp->cdb_len = scp->cmd_len;
6870 for (i = 0; i < scp->cmd_len; i++) {
6871 scsiqp->cdb[i] = scp->cmnd[i];
6874 scsiqp->target_id = scp->target;
6875 scsiqp->target_lun = scp->lun;
6877 scsiqp->vsense_addr = (ulong) &scp->sense_buffer[0];
6878 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6879 scsiqp->sense_addr = (ulong) &scp->sense_buffer[0];
6880 #else /* version >= v2.0.0 */
6881 scsiqp->sense_addr = virt_to_bus(&scp->sense_buffer[0]);
6882 #endif /* version >= v2.0.0 */
6883 scsiqp->sense_len = sizeof(scp->sense_buffer);
6886 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
6887 * buffer command.
6889 scsiqp->data_cnt = scp->request_bufflen;
6890 scsiqp->vdata_addr = (ulong) scp->request_buffer;
6891 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6892 scsiqp->data_addr = (ulong) scp->request_buffer;
6893 #else /* version >= v2.0.0 */
6894 scsiqp->data_addr = virt_to_bus(scp->request_buffer);
6895 #endif /* version >= v2.0.0 */
6897 if (scp->use_sg == 0) {
6899 * CDB request of single contiguous buffer.
6901 reqp->sgblkp = NULL;
6902 scsiqp->sg_list_ptr = NULL;
6903 ASC_STATS(scp->host, cont_cnt);
6904 ASC_STATS_ADD(scp->host, cont_xfer,
6905 ASC_CEILING(scp->request_bufflen, 512));
6906 } else {
6908 * CDB scatter-gather request list.
6910 if (scp->use_sg > ADV_MAX_SG_LIST) {
6911 ASC_PRINT3(
6912 "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
6913 boardp->id, scp->use_sg, scp->host->sg_tablesize);
6914 scp->result = HOST_BYTE(DID_ERROR);
6915 asc_enqueue(&boardp->done, scp, ASC_BACK);
6918 * Free the 'adv_req_t' structure by adding it back to the
6919 * board free list.
6921 reqp->next_reqp = boardp->adv_reqp;
6922 boardp->adv_reqp = reqp;
6924 return ASC_ERROR;
6928 * Allocate an 'adv_sgblk_t' structure from the board to
6929 * execute the command.
6931 if (boardp->adv_sgblkp == NULL) {
6932 ASC_DBG(1, "adv_build_req: no free adv_sgblk_t\n");
6933 ASC_STATS(scp->host, adv_build_nosg);
6935 * Free the 'adv_req_t' structure by adding it back to the
6936 * board free list.
6938 reqp->next_reqp = boardp->adv_reqp;
6939 boardp->adv_reqp = reqp;
6940 return ASC_BUSY;
6941 } else {
6942 reqp->sgblkp = boardp->adv_sgblkp;
6943 boardp->adv_sgblkp = reqp->sgblkp->next_sgblkp;
6944 reqp->sgblkp->next_sgblkp = NULL;
6948 * Build scatter-gather list.
6950 scsiqp->sg_list_ptr = (ADV_SG_BLOCK *)
6951 ADV_DWALIGN(&reqp->sgblkp->sg_block[0]);
6953 memset(scsiqp->sg_list_ptr, 0, sizeof(ADV_SG_BLOCK) *
6954 (ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING));
6956 if (adv_get_sglist(&boardp->dvc_var.adv_dvc_var, scsiqp, scp) ==
6957 ADV_ERROR) {
6960 * Free the adv_sgblk_t structure, if any, by adding it back
6961 * to the board free list.
6963 ASC_ASSERT(reqp->sgblkp != NULL);
6964 reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
6965 boardp->adv_sgblkp = reqp->sgblkp;
6968 * Free the adv_req_t structure by adding it back to the
6969 * board free list.
6971 reqp->next_reqp = boardp->adv_reqp;
6972 boardp->adv_reqp = reqp;
6974 return ADV_ERROR;
6977 ASC_STATS(scp->host, sg_cnt);
6978 ASC_STATS_ADD(scp->host, sg_elem, scp->use_sg);
6981 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
6982 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
6984 *adv_scsiqpp = scsiqp;
6986 return ASC_NOERROR;
6990 * Build scatter-gather list for Adv Library (Wide Board).
6992 * Return:
6993 * ADV_SUCCESS(1) - SG List successfully created
6994 * ADV_ERROR(-1) - SG List creation failed
6996 STATIC int
6997 adv_get_sglist(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp,
6998 Scsi_Cmnd *scp)
7000 ADV_SG_BLOCK *sg_block; /* virtual address of a SG */
7001 ulong sg_block_next_addr; /* block and its next */
7002 ulong sg_block_physical_addr;
7003 int sg_block_index, i; /* how many SG entries */
7004 struct scatterlist *slp;
7005 int sg_elem_cnt;
7007 slp = (struct scatterlist *) scp->request_buffer;
7008 sg_elem_cnt = scp->use_sg;
7010 sg_block = scsiqp->sg_list_ptr;
7011 sg_block_next_addr = (ulong) sg_block; /* allow math operation */
7012 sg_block_physical_addr =
7013 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7014 (ulong) scsiqp->sg_list_ptr;
7015 #else /* version >= v2.0.0 */
7016 virt_to_bus(scsiqp->sg_list_ptr);
7017 #endif /* version >= v2.0.0 */
7018 ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7019 sg_block_physical_addr);
7020 scsiqp->sg_real_addr = sg_block_physical_addr;
7022 sg_block_index = 0;
7025 sg_block->first_entry_no = sg_block_index;
7026 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
7028 sg_block->sg_list[i].sg_addr =
7029 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7030 (ulong) slp->address;
7031 #else /* version >= v2.0.0 */
7032 virt_to_bus(slp->address);
7033 #endif /* version >= v2.0.0 */
7034 sg_block->sg_list[i].sg_count = slp->length;
7035 ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
7037 if (--sg_elem_cnt == 0)
7038 { /* last entry, get out */
7039 scsiqp->sg_entry_cnt = sg_block_index + i + 1;
7040 sg_block->last_entry_no = sg_block_index + i;
7041 sg_block->sg_ptr = 0L; /* next link = NULL */
7042 return ADV_SUCCESS;
7044 slp++;
7046 sg_block_next_addr += sizeof(ADV_SG_BLOCK);
7047 sg_block_physical_addr += sizeof(ADV_SG_BLOCK);
7048 ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7049 sg_block_physical_addr);
7051 sg_block_index += NO_OF_SG_PER_BLOCK;
7052 sg_block->sg_ptr = (ADV_SG_BLOCK *) sg_block_physical_addr;
7053 sg_block->last_entry_no = sg_block_index - 1;
7054 sg_block = (ADV_SG_BLOCK *) sg_block_next_addr; /* virtual addr */
7056 while (1);
7057 /* NOTREACHED */
7061 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
7063 * Interrupt callback function for the Narrow SCSI Asc Library.
7065 STATIC void
7066 asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
7068 asc_board_t *boardp;
7069 Scsi_Cmnd *scp;
7070 struct Scsi_Host *shp;
7071 int underrun = ASC_FALSE;
7072 int i;
7074 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7075 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n",
7076 (unsigned) asc_dvc_varp, (unsigned) qdonep);
7077 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
7080 * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7081 * command that has been completed.
7083 scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
7084 ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
7086 if (scp == NULL) {
7087 ASC_PRINT("asc_isr_callback: scp is NULL\n");
7088 return;
7090 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7093 * If the request's host pointer is not valid, display a
7094 * message and return.
7096 shp = scp->host;
7097 for (i = 0; i < asc_board_count; i++) {
7098 if (asc_host[i] == shp) {
7099 break;
7102 if (i == asc_board_count) {
7103 ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n",
7104 (unsigned) scp, (unsigned) shp);
7105 return;
7108 ASC_STATS(shp, callback);
7109 ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
7112 * If the request isn't found on the active queue, it may
7113 * have been removed to handle a reset or abort request.
7114 * Display a message and return.
7116 boardp = ASC_BOARDP(shp);
7117 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
7118 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7119 ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
7120 boardp->id, (unsigned) scp);
7121 return;
7125 * Check for an underrun condition.
7127 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
7128 qdonep->remain_bytes <= scp->request_bufflen != 0) {
7129 ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
7130 (unsigned) qdonep->remain_bytes);
7131 underrun = ASC_TRUE;
7135 * 'qdonep' contains the command's ending status.
7137 switch (qdonep->d3.done_stat) {
7138 case QD_NO_ERROR:
7139 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
7140 switch (qdonep->d3.host_stat) {
7141 case QHSTA_NO_ERROR:
7142 scp->result = 0;
7143 break;
7144 default:
7145 /* QHSTA error occurred */
7146 scp->result = HOST_BYTE(DID_ERROR);
7147 break;
7151 * If an INQUIRY command completed successfully, then call
7152 * the AscInquiryHandling() function to set-up the device.
7154 if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 &&
7155 (scp->request_bufflen - qdonep->remain_bytes) >= 8)
7157 AscInquiryHandling(asc_dvc_varp, scp->target & 0x7,
7158 (ASC_SCSI_INQUIRY *) scp->request_buffer);
7162 * If there was an underrun without any other error,
7163 * set DID_ERROR to indicate the underrun error.
7165 * Note: There is no way yet to indicate the number
7166 * of underrun bytes.
7168 if (scp->result == 0 && underrun == ASC_TRUE) {
7169 scp->result = HOST_BYTE(DID_UNDERRUN);
7171 break;
7173 case QD_WITH_ERROR:
7174 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
7175 switch (qdonep->d3.host_stat) {
7176 case QHSTA_NO_ERROR:
7177 if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
7178 ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
7179 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7180 sizeof(scp->sense_buffer));
7182 * Note: The 'status_byte()' macro used by target drivers
7183 * defined in scsi.h shifts the status byte returned by
7184 * host drivers right by 1 bit. This is why target drivers
7185 * also use right shifted status byte definitions. For
7186 * instance target drivers use CHECK_CONDITION, defined to
7187 * 0x1, instead of the SCSI defined check condition value
7188 * of 0x2. Host drivers are supposed to return the status
7189 * byte as it is defined by SCSI.
7191 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7192 STATUS_BYTE(qdonep->d3.scsi_stat);
7193 } else {
7194 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
7196 break;
7198 default:
7199 /* QHSTA error occurred */
7200 ASC_DBG1(1, "asc_isr_callback: host_stat %x\n",
7201 qdonep->d3.host_stat);
7202 scp->result = HOST_BYTE(DID_BAD_TARGET);
7203 break;
7205 break;
7207 case QD_ABORTED_BY_HOST:
7208 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
7209 scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
7210 STATUS_BYTE(qdonep->d3.scsi_stat);
7211 break;
7213 default:
7214 ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
7215 scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
7216 STATUS_BYTE(qdonep->d3.scsi_stat);
7217 break;
7221 * If the 'init_tidmask' bit isn't already set for the target and the
7222 * current request finished normally, then set the bit for the target
7223 * to indicate that a device is present.
7225 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7226 qdonep->d3.done_stat == QD_NO_ERROR &&
7227 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
7228 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7232 * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7233 * function, add the command to the end of the board's done queue.
7234 * The done function for the command will be called from
7235 * advansys_interrupt().
7237 asc_enqueue(&boardp->done, scp, ASC_BACK);
7239 return;
7243 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
7245 * Callback function for the Wide SCSI Adv Library.
7247 STATIC void
7248 adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
7250 asc_board_t *boardp;
7251 adv_req_t *reqp;
7252 Scsi_Cmnd *scp;
7253 struct Scsi_Host *shp;
7254 int underrun = ASC_FALSE;
7255 int i;
7257 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7258 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %x, scsiqp %x\n",
7259 (unsigned) adv_dvc_varp, (unsigned) scsiqp);
7260 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
7263 * Get the adv_req_t structure for the command that has been
7264 * completed. The adv_req_t structure actually contains the
7265 * completed ADV_SCSI_REQ_Q structure.
7267 reqp = (adv_req_t *) scsiqp->srb_ptr;
7268 ASC_DBG1(1, "adv_isr_callback: reqp %x\n", (unsigned) reqp);
7269 if (reqp == NULL) {
7270 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
7271 return;
7275 * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7276 * command that has been completed.
7278 * Note: The adv_req_t request structure and adv_sgblk_t structure,
7279 * if any, * dropped, because a board structure pointer can not be
7280 * determined.
7282 scp = reqp->cmndp;
7283 ASC_DBG1(1, "adv_isr_callback: scp %x\n", (unsigned) scp);
7284 if (scp == NULL) {
7285 ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
7286 return;
7288 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7291 * If the request's host pointer is not valid, display a message
7292 * and return.
7294 shp = scp->host;
7295 for (i = 0; i < asc_board_count; i++) {
7296 if (asc_host[i] == shp) {
7297 break;
7301 * Note: If the host structure is not found, the adv_req_t request
7302 * structure and adv_sgblk_t structure, if any, is dropped.
7304 if (i == asc_board_count) {
7305 ASC_PRINT2("adv_isr_callback: scp %x has bad host pointer, host %x\n",
7306 (unsigned) scp, (unsigned) shp);
7307 return;
7310 ASC_STATS(shp, callback);
7311 ASC_DBG1(1, "adv_isr_callback: shp %x\n", (unsigned) shp);
7314 * If the request isn't found on the active queue, it may have been
7315 * removed to handle a reset or abort request. Display a message and
7316 * return.
7318 * Note: Because the structure may still be in use don't attempt
7319 * to free the adv_req_t and adv_sgblk_t, if any, structures.
7321 boardp = ASC_BOARDP(shp);
7322 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
7323 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7324 ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n",
7325 boardp->id, (unsigned) scp);
7326 return;
7330 * Check for an underrun condition.
7332 if (scp->request_bufflen != 0 && scsiqp->data_cnt != 0) {
7333 ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n",
7334 scsiqp->data_cnt);
7335 underrun = ASC_TRUE;
7339 * 'done_status' contains the command's ending status.
7341 switch (scsiqp->done_status) {
7342 case QD_NO_ERROR:
7343 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
7344 switch (scsiqp->host_status) {
7345 case QHSTA_NO_ERROR:
7346 scp->result = 0;
7347 break;
7348 default:
7349 /* QHSTA error occurred. */
7350 ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
7351 scsiqp->host_status);
7352 scp->result = HOST_BYTE(DID_ERROR);
7353 break;
7356 * If there was an underrun without any other error,
7357 * set DID_ERROR to indicate the underrun error.
7359 * Note: There is no way yet to indicate the number
7360 * of underrun bytes.
7362 if (scp->result == 0 && underrun == ASC_TRUE) {
7363 scp->result = HOST_BYTE(DID_UNDERRUN);
7365 break;
7367 case QD_WITH_ERROR:
7368 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
7369 switch (scsiqp->host_status) {
7370 case QHSTA_NO_ERROR:
7371 if (scsiqp->scsi_status == SS_CHK_CONDITION) {
7372 ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n");
7373 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7374 sizeof(scp->sense_buffer));
7376 * Note: The 'status_byte()' macro used by target drivers
7377 * defined in scsi.h shifts the status byte returned by
7378 * host drivers right by 1 bit. This is why target drivers
7379 * also use right shifted status byte definitions. For
7380 * instance target drivers use CHECK_CONDITION, defined to
7381 * 0x1, instead of the SCSI defined check condition value
7382 * of 0x2. Host drivers are supposed to return the status
7383 * byte as it is defined by SCSI.
7385 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7386 STATUS_BYTE(scsiqp->scsi_status);
7387 } else {
7388 scp->result = STATUS_BYTE(scsiqp->scsi_status);
7390 break;
7392 default:
7393 /* Some other QHSTA error occurred. */
7394 ASC_DBG1(1, "adv_isr_callback: host_status %x\n",
7395 scsiqp->host_status);
7396 scp->result = HOST_BYTE(DID_BAD_TARGET);
7397 break;
7399 break;
7401 case QD_ABORTED_BY_HOST:
7402 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
7403 scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
7404 break;
7406 default:
7407 ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status);
7408 scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
7409 break;
7413 * If the 'init_tidmask' bit isn't already set for the target and the
7414 * current request finished normally, then set the bit for the target
7415 * to indicate that a device is present.
7417 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7418 scsiqp->done_status == QD_NO_ERROR &&
7419 scsiqp->host_status == QHSTA_NO_ERROR) {
7420 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7424 * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7425 * function, add the command to the end of the board's done queue.
7426 * The done function for the command will be called from
7427 * advansys_interrupt().
7429 asc_enqueue(&boardp->done, scp, ASC_BACK);
7432 * Free the adv_sgblk_t structure, if any, by adding it back
7433 * to the board free list.
7435 if (reqp->sgblkp != NULL) {
7436 reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
7437 boardp->adv_sgblkp = reqp->sgblkp;
7441 * Free the adv_req_t structure used with the command by adding
7442 * it back to the board free list.
7444 reqp->next_reqp = boardp->adv_reqp;
7445 boardp->adv_reqp = reqp;
7447 ASC_DBG(1, "adv_isr_callback: done\n");
7449 return;
7452 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
7453 #ifdef ASC_CONFIG_PCI
7455 * Search for an AdvanSys PCI device in the PCI configuration space.
7457 ASC_INITFUNC(
7458 STATIC int
7459 asc_srch_pci_dev(PCI_DEVICE *pciDevice)
7462 int ret = PCI_DEVICE_NOT_FOUND;
7464 ASC_DBG(2, "asc_srch_pci_dev: begin\n");
7466 if (pci_scan_method == -1) {
7467 pci_scan_method = asc_scan_method();
7469 pciDevice->type = pci_scan_method;
7470 ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
7472 ret = asc_pci_find_dev(pciDevice);
7473 ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
7474 if (ret == PCI_DEVICE_FOUND) {
7475 pciDevice->slotNumber = pciDevice->slotFound + 1;
7476 pciDevice->startSlot = pciDevice->slotFound + 1;
7477 } else {
7478 if (pciDevice->bridge > pciDevice->busNumber) {
7479 ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
7480 pciDevice->bridge, pciDevice->busNumber);
7481 pciDevice->busNumber++;
7482 pciDevice->slotNumber = 0;
7483 pciDevice->startSlot = 0;
7484 pciDevice->endSlot = 0x0f;
7485 ret = asc_srch_pci_dev(pciDevice);
7486 ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
7490 ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
7491 return ret;
7495 * Determine the access method to be used for 'pciDevice'.
7497 ASC_INITFUNC(
7498 STATIC uchar
7499 asc_scan_method(void)
7502 ushort data;
7503 PCI_DATA pciData;
7504 uchar type;
7505 uchar slot;
7507 ASC_DBG(2, "asc_scan_method: begin\n");
7508 memset(&pciData, 0, sizeof(pciData));
7509 for (type = 1; type < 3; type++) {
7510 pciData.type = type;
7511 for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
7512 pciData.slot = slot;
7513 data = asc_get_cfg_word(&pciData);
7514 if ((data != 0xFFFF) && (data != 0x0000)) {
7515 ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
7516 return (type);
7520 ASC_DBG1(4, "asc_scan_method: type %d\n", type);
7521 return (type);
7525 * Check for an AdvanSys PCI device in 'pciDevice'.
7527 * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
7529 ASC_INITFUNC(
7530 STATIC int
7531 asc_pci_find_dev(PCI_DEVICE *pciDevice)
7534 PCI_DATA pciData;
7535 ushort vendorid, deviceid;
7536 uchar classcode, subclass;
7537 uchar lslot;
7539 ASC_DBG(3, "asc_pci_find_dev: begin\n");
7540 pciData.type = pciDevice->type;
7541 pciData.bus = pciDevice->busNumber;
7542 pciData.func = pciDevice->devFunc;
7543 lslot = pciDevice->startSlot;
7544 for (; lslot < pciDevice->endSlot; lslot++) {
7545 pciData.slot = lslot;
7546 pciData.offset = VENDORID_OFFSET;
7547 vendorid = asc_get_cfg_word(&pciData);
7548 ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
7549 if (vendorid != 0xffff) {
7550 pciData.offset = DEVICEID_OFFSET;
7551 deviceid = asc_get_cfg_word(&pciData);
7552 ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
7553 if ((vendorid == ASC_PCI_VENDORID) &&
7554 ((deviceid == ASC_PCI_DEVICE_ID_1100) ||
7555 (deviceid == ASC_PCI_DEVICE_ID_1200) ||
7556 (deviceid == ASC_PCI_DEVICE_ID_1300) ||
7557 (deviceid == ASC_PCI_DEVICE_ID_2300))) {
7558 pciDevice->slotFound = lslot;
7559 ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
7560 return PCI_DEVICE_FOUND;
7561 } else {
7562 pciData.offset = SUBCLASS_OFFSET;
7563 subclass = asc_get_cfg_byte(&pciData);
7564 pciData.offset = CLASSCODE_OFFSET;
7565 classcode = asc_get_cfg_byte(&pciData);
7566 if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
7567 (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
7568 pciDevice->bridge++;
7570 ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
7571 subclass, classcode);
7575 return PCI_DEVICE_NOT_FOUND;
7579 * Read PCI configuration data into 'pciConfig'.
7581 ASC_INITFUNC(
7582 STATIC void
7583 asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
7586 PCI_DATA pciData;
7587 uchar counter;
7588 uchar *localConfig;
7590 ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ",
7591 pciDevice->slotFound);
7593 pciData.type = pciDevice->type;
7594 pciData.bus = pciDevice->busNumber;
7595 pciData.slot = pciDevice->slotFound;
7596 pciData.func = pciDevice->devFunc;
7597 localConfig = (uchar *) pciConfig;
7599 for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
7600 pciData.offset = counter;
7601 *localConfig = asc_get_cfg_byte(&pciData);
7602 ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
7603 localConfig++;
7605 ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
7609 * Read a word (16 bits) from the PCI configuration space.
7611 * The configuration mechanism is checked for the correct access method.
7613 ASC_INITFUNC(
7614 STATIC ushort
7615 asc_get_cfg_word(PCI_DATA *pciData)
7618 ushort tmp;
7619 ulong address;
7620 ulong lbus = pciData->bus;
7621 ulong lslot = pciData->slot;
7622 ulong lfunc = pciData->func;
7623 uchar t2CFA, t2CF8;
7624 ulong t1CF8, t1CFC;
7626 ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
7627 pciData->type, lbus, lslot, lfunc);
7630 * Check type of configuration mechanism.
7632 if (pciData->type == 2) {
7634 * Save registers to be restored later.
7636 t2CFA = inp(0xCFA); /* save PCI bus register */
7637 t2CF8 = inp(0xCF8); /* save config space enable register */
7640 * Write the bus and enable registers.
7642 /* set for type 1 cycle, if needed */
7643 outp(0xCFA, pciData->bus);
7644 /* set the function number */
7645 outp(0xCF8, 0x10 | (pciData->func << 1)) ;
7648 * Read the configuration space type 2 locations.
7650 tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
7652 outp(0xCFA, t2CFA); /* save PCI bus register */
7653 outp(0xCF8, t2CF8); /* save config space enable register */
7654 } else {
7656 * Type 1 or 3 configuration mechanism.
7658 * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
7660 t1CF8 = inpl(0xCF8);
7661 t1CFC = inpl(0xCFC);
7664 * enable <31>, bus = <23:16>, slot = <15:11>,
7665 * func = <10:8>, reg = <7:2>
7667 address = (ulong) ((lbus << 16) | (lslot << 11) |
7668 (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
7671 * Write out the address to CONFIG_ADDRESS.
7673 outpl(0xCF8, address);
7676 * Read in word from CONFIG_DATA.
7678 tmp = (ushort) ((inpl(0xCFC) >>
7679 ((pciData->offset & 2) * 8)) & 0xFFFF);
7682 * Restore registers.
7684 outpl(0xCF8, t1CF8);
7685 outpl(0xCFC, t1CFC);
7687 ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
7688 return tmp;
7692 * Reads a byte from the PCI configuration space.
7694 * The configuration mechanism is checked for the correct access method.
7696 ASC_INITFUNC(
7697 STATIC uchar
7698 asc_get_cfg_byte(PCI_DATA *pciData)
7701 uchar tmp;
7702 ulong address;
7703 ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
7704 uchar t2CFA, t2CF8;
7705 ulong t1CF8, t1CFC;
7707 ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
7710 * Check type of configuration mechanism.
7712 if (pciData->type == 2) {
7714 * Save registers to be restored later.
7716 t2CFA = inp(0xCFA); /* save PCI bus register */
7717 t2CF8 = inp(0xCF8); /* save config space enable register */
7720 * Write the bus and enable registers.
7722 /* set for type 1 cycle, if needed */
7723 outp(0xCFA, pciData->bus);
7724 /* set the function number */
7725 outp(0xCF8, 0x10 | (pciData->func << 1));
7728 * Read configuration space type 2 locations.
7730 tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
7733 * Restore registers.
7735 outp(0xCF8, t2CF8); /* restore the enable register */
7736 outp(0xCFA, t2CFA); /* restore PCI bus register */
7737 } else {
7739 * Type 1 or 3 configuration mechanism.
7741 * Save CONFIG_ADDRESS and CONFIG_DATA register values.
7743 t1CF8 = inpl(0xCF8);
7744 t1CFC = inpl(0xCFC);
7747 * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
7748 * reg = <7:2>
7750 address = (ulong) ((lbus << 16) | (lslot << 11) |
7751 (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
7754 * Write out address to CONFIG_ADDRESS.
7756 outpl(0xCF8, address);
7759 * Read in word from CONFIG_DATA.
7761 tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
7764 * Restore registers.
7766 outpl(0xCF8, t1CF8);
7767 outpl(0xCFC, t1CFC);
7769 ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
7770 return tmp;
7774 * Write a byte to the PCI configuration space.
7776 ASC_INITFUNC(
7777 STATIC void
7778 asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
7781 ulong tmpl;
7782 ulong address;
7783 ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
7784 uchar t2CFA, t2CF8;
7785 ulong t1CF8, t1CFC;
7787 ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n",
7788 pciData->type, byte_data);
7791 * Check type of configuration mechanism.
7793 if (pciData->type == 2) {
7796 * Save registers to be restored later.
7798 t2CFA = inp(0xCFA); /* save PCI bus register */
7799 t2CF8 = inp(0xCF8); /* save config space enable register */
7802 * Write bus and enable registers.
7804 outp(0xCFA, pciData->bus);
7807 * Set the function number.
7809 outp(0xCF8, 0x10 | (pciData->func << 1));
7812 * Write the configuration space type 2 locations.
7814 outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data);
7817 * Restore registers.
7819 outp(0xCF8, t2CF8); /* restore the enable register */
7820 outp(0xCFA, t2CFA); /* restore PCI bus register */
7821 } else {
7824 * Type 1 or 3 configuration mechanism.
7826 * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
7828 t1CF8 = inpl(0xCF8);
7829 t1CFC = inpl(0xCFC);
7832 * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
7833 * reg = <7:2>
7835 address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) |
7836 (pciData->offset & 0xFC) | 0x80000000L);
7838 * Write out address to CONFIG_ADDRESS.
7840 outpl(0xCF8, address);
7843 * Write double word to CONFIG_DATA preserving the bytes
7844 * in the double not written.
7846 tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8));
7847 outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8)));
7850 * Restore registers.
7852 outpl(0xCF8, t1CF8);
7853 outpl(0xCFC, t1CFC);
7855 ASC_DBG(4, "asc_put_cfg_byte: end\n");
7857 #endif /* ASC_CONFIG_PCI */
7858 #endif /* version < v2.1.93 */
7861 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
7862 * to indicate a command is queued for the device.
7864 * 'flag' may be either ASC_FRONT or ASC_BACK.
7866 * 'REQPNEXT(reqp)' returns reqp's next pointer.
7868 STATIC void
7869 asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
7871 int tid;
7873 ASC_DBG3(3, "asc_enqueue: ascq %x, reqp %x, flag %d\n",
7874 (unsigned) ascq, (unsigned) reqp, flag);
7875 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7876 ASC_ASSERT(reqp != NULL);
7877 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
7878 tid = REQPTID(reqp);
7879 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
7880 if (flag == ASC_FRONT) {
7881 REQPNEXT(reqp) = ascq->q_first[tid];
7882 ascq->q_first[tid] = reqp;
7883 /* If the queue was empty, set the last pointer. */
7884 if (ascq->q_last[tid] == NULL) {
7885 ascq->q_last[tid] = reqp;
7887 } else { /* ASC_BACK */
7888 if (ascq->q_last[tid] != NULL) {
7889 REQPNEXT(ascq->q_last[tid]) = reqp;
7891 ascq->q_last[tid] = reqp;
7892 REQPNEXT(reqp) = NULL;
7893 /* If the queue was empty, set the first pointer. */
7894 if (ascq->q_first[tid] == NULL) {
7895 ascq->q_first[tid] = reqp;
7898 /* The queue has at least one entry, set its bit. */
7899 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
7900 #ifdef ADVANSYS_STATS
7901 /* Maintain request queue statistics. */
7902 ascq->q_tot_cnt[tid]++;
7903 ascq->q_cur_cnt[tid]++;
7904 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
7905 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
7906 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
7907 tid, ascq->q_max_cnt[tid]);
7909 REQPTIME(reqp) = REQTIMESTAMP();
7910 #endif /* ADVANSYS_STATS */
7911 ASC_DBG1(3, "asc_enqueue: reqp %x\n", (unsigned) reqp);
7912 return;
7916 * Return first queued 'REQP' on the specified queue for
7917 * the specified target device. Clear the 'tidmask' bit for
7918 * the device if no more commands are left queued for it.
7920 * 'REQPNEXT(reqp)' returns reqp's next pointer.
7922 STATIC REQP
7923 asc_dequeue(asc_queue_t *ascq, int tid)
7925 REQP reqp;
7927 ASC_DBG2(3, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid);
7928 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7929 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
7930 if ((reqp = ascq->q_first[tid]) != NULL) {
7931 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
7932 ascq->q_first[tid] = REQPNEXT(reqp);
7933 /* If the queue is empty, clear its bit and the last pointer. */
7934 if (ascq->q_first[tid] == NULL) {
7935 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
7936 ASC_ASSERT(ascq->q_last[tid] == reqp);
7937 ascq->q_last[tid] = NULL;
7939 #ifdef ADVANSYS_STATS
7940 /* Maintain request queue statistics. */
7941 ascq->q_cur_cnt[tid]--;
7942 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
7943 REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
7944 #endif /* ADVANSYS_STATS */
7946 ASC_DBG1(3, "asc_dequeue: reqp %x\n", (unsigned) reqp);
7947 return reqp;
7951 * Return a pointer to a singly linked list of all the requests queued
7952 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
7954 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
7955 * the last request returned in the singly linked list.
7957 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
7958 * then all queued requests are concatenated into one list and
7959 * returned.
7961 * Note: If 'lastpp' is used to append a new list to the end of
7962 * an old list, only change the old list last pointer if '*lastpp'
7963 * (or the function return value) is not NULL, i.e. use a temporary
7964 * variable for 'lastpp' and check its value after the function return
7965 * before assigning it to the list last pointer.
7967 * Unfortunately collecting queuing time statistics adds overhead to
7968 * the function that isn't inherent to the function's algorithm.
7970 STATIC REQP
7971 asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
7973 REQP firstp, lastp;
7974 int i;
7976 ASC_DBG2(3, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid);
7977 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7978 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
7981 * If 'tid' is not ASC_TID_ALL, return requests only for
7982 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
7983 * requests for all tids.
7985 if (tid != ASC_TID_ALL) {
7986 /* Return all requests for the specified 'tid'. */
7987 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
7988 /* List is empty; Set first and last return pointers to NULL. */
7989 firstp = lastp = NULL;
7990 } else {
7991 firstp = ascq->q_first[tid];
7992 lastp = ascq->q_last[tid];
7993 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
7994 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
7995 #ifdef ADVANSYS_STATS
7997 REQP reqp;
7998 ascq->q_cur_cnt[tid] = 0;
7999 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
8000 REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
8003 #endif /* ADVANSYS_STATS */
8005 } else {
8006 /* Return all requests for all tids. */
8007 firstp = lastp = NULL;
8008 for (i = 0; i <= ADV_MAX_TID; i++) {
8009 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
8010 if (firstp == NULL) {
8011 firstp = ascq->q_first[i];
8012 lastp = ascq->q_last[i];
8013 } else {
8014 ASC_ASSERT(lastp != NULL);
8015 REQPNEXT(lastp) = ascq->q_first[i];
8016 lastp = ascq->q_last[i];
8018 ascq->q_first[i] = ascq->q_last[i] = NULL;
8019 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8020 #ifdef ADVANSYS_STATS
8021 ascq->q_cur_cnt[i] = 0;
8022 #endif /* ADVANSYS_STATS */
8025 #ifdef ADVANSYS_STATS
8027 REQP reqp;
8028 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
8029 REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
8032 #endif /* ADVANSYS_STATS */
8034 if (lastpp) {
8035 *lastpp = lastp;
8037 ASC_DBG1(3, "asc_dequeue_list: firstp %x\n", (unsigned) firstp);
8038 return firstp;
8042 * Remove the specified 'REQP' from the specified queue for
8043 * the specified target device. Clear the 'tidmask' bit for the
8044 * device if no more commands are left queued for it.
8046 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
8048 * Return ASC_TRUE if the command was found and removed,
8049 * otherwise return ASC_FALSE.
8051 STATIC int
8052 asc_rmqueue(asc_queue_t *ascq, REQP reqp)
8054 REQP currp, prevp;
8055 int tid;
8056 int ret = ASC_FALSE;
8058 ASC_DBG2(3, "asc_rmqueue: ascq %x, reqp %x\n",
8059 (unsigned) ascq, (unsigned) reqp);
8060 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8061 ASC_ASSERT(reqp != NULL);
8063 tid = REQPTID(reqp);
8064 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8067 * Handle the common case of 'reqp' being the first
8068 * entry on the queue.
8070 if (reqp == ascq->q_first[tid]) {
8071 ret = ASC_TRUE;
8072 ascq->q_first[tid] = REQPNEXT(reqp);
8073 /* If the queue is now empty, clear its bit and the last pointer. */
8074 if (ascq->q_first[tid] == NULL) {
8075 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
8076 ASC_ASSERT(ascq->q_last[tid] == reqp);
8077 ascq->q_last[tid] = NULL;
8079 } else if (ascq->q_first[tid] != NULL) {
8080 ASC_ASSERT(ascq->q_last[tid] != NULL);
8082 * Because the case of 'reqp' being the first entry has been
8083 * handled above and it is known the queue is not empty, if
8084 * 'reqp' is found on the queue it is guaranteed the queue will
8085 * not become empty and that 'q_first[tid]' will not be changed.
8087 * Set 'prevp' to the first entry, 'currp' to the second entry,
8088 * and search for 'reqp'.
8090 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
8091 currp; prevp = currp, currp = REQPNEXT(currp)) {
8092 if (currp == reqp) {
8093 ret = ASC_TRUE;
8094 REQPNEXT(prevp) = REQPNEXT(currp);
8095 REQPNEXT(reqp) = NULL;
8096 if (ascq->q_last[tid] == reqp) {
8097 ascq->q_last[tid] = prevp;
8099 break;
8103 #ifdef ADVANSYS_STATS
8104 /* Maintain request queue statistics. */
8105 if (ret == ASC_TRUE) {
8106 ascq->q_cur_cnt[tid]--;
8107 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
8109 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
8110 #endif /* ADVANSYS_STATS */
8111 ASC_DBG2(3, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret);
8112 return ret;
8116 * If the specified 'REQP' is queued on the specified queue for
8117 * the specified target device, return ASC_TRUE.
8119 STATIC int
8120 asc_isqueued(asc_queue_t *ascq, REQP reqp)
8122 REQP treqp;
8123 int tid;
8124 int ret = ASC_FALSE;
8126 ASC_DBG2(3, "asc_isqueued: ascq %x, reqp %x\n",
8127 (unsigned) ascq, (unsigned) reqp);
8128 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8129 ASC_ASSERT(reqp != NULL);
8131 tid = REQPTID(reqp);
8132 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8134 for (treqp = ascq->q_first[tid]; treqp; treqp = REQPNEXT(treqp)) {
8135 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
8136 if (treqp == reqp) {
8137 ret = ASC_TRUE;
8138 break;
8141 ASC_DBG1(3, "asc_isqueued: ret %x\n", ret);
8142 return ret;
8146 * Execute as many queued requests as possible for the specified queue.
8148 * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd.
8150 STATIC void
8151 asc_execute_queue(asc_queue_t *ascq)
8153 ADV_SCSI_BIT_ID_TYPE scan_tidmask;
8154 REQP reqp;
8155 int i;
8157 ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq);
8158 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8160 * Execute queued commands for devices attached to
8161 * the current board in round-robin fashion.
8163 scan_tidmask = ascq->q_tidmask;
8164 do {
8165 for (i = 0; i <= ADV_MAX_TID; i++) {
8166 if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
8167 if ((reqp = asc_dequeue(ascq, i)) == NULL) {
8168 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8169 } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp)
8170 == ASC_BUSY) {
8171 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8172 /* Put the request back at front of the list. */
8173 asc_enqueue(ascq, reqp, ASC_FRONT);
8177 } while (scan_tidmask);
8178 return;
8181 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
8183 * asc_prt_board_devices()
8185 * Print driver information for devices attached to the board.
8187 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8188 * cf. asc_prt_line().
8190 * Return the number of characters copied into 'cp'. No more than
8191 * 'cplen' characters will be copied to 'cp'.
8193 STATIC int
8194 asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
8196 asc_board_t *boardp;
8197 int leftlen;
8198 int totlen;
8199 int len;
8200 int chip_scsi_id;
8201 int i;
8203 boardp = ASC_BOARDP(shp);
8204 leftlen = cplen;
8205 totlen = len = 0;
8207 len = asc_prt_line(cp, leftlen,
8208 "\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no);
8209 ASC_PRT_NEXT();
8211 if (ASC_NARROW_BOARD(boardp)) {
8212 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8213 } else {
8214 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8217 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
8218 ASC_PRT_NEXT();
8219 for (i = 0; i <= ADV_MAX_TID; i++) {
8220 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
8221 len = asc_prt_line(cp, leftlen, " %X,", i);
8222 ASC_PRT_NEXT();
8225 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
8226 ASC_PRT_NEXT();
8228 return totlen;
8232 * Display Wide Board BIOS Information.
8234 STATIC int
8235 asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen)
8237 asc_board_t *boardp;
8238 int leftlen;
8239 int totlen;
8240 int len;
8241 int upgrade = ASC_FALSE;
8242 ushort major, minor, letter;
8244 boardp = ASC_BOARDP(shp);
8245 leftlen = cplen;
8246 totlen = len = 0;
8248 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
8249 ASC_PRT_NEXT();
8252 * If the BIOS saved a valid signature, then fill in
8253 * the BIOS code segment base address.
8255 if (boardp->bios_signature != 0x55AA) {
8256 len = asc_prt_line(cp, leftlen, "Pre-3.1\n");
8257 ASC_PRT_NEXT();
8258 upgrade = ASC_TRUE;
8259 } else {
8260 major = (boardp->bios_version >> 12) & 0xF;
8261 minor = (boardp->bios_version >> 8) & 0xF;
8262 letter = (boardp->bios_version & 0xFF);
8264 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
8265 major, minor, letter >= 26 ? '?' : letter + 'A');
8266 ASC_PRT_NEXT();
8268 /* Current available ROM BIOS release is 3.1C. */
8269 if (major < 3 || (major <= 3 && minor < 1) ||
8270 (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) {
8271 upgrade = ASC_TRUE;
8274 if (upgrade == ASC_TRUE) {
8275 len = asc_prt_line(cp, leftlen,
8276 "Newer version of ROM BIOS available: ftp://ftp.advansys.com/pub\n");
8277 ASC_PRT_NEXT();
8280 return totlen;
8284 * Add serial number to information bar if signature AAh
8285 * is found in at bit 15-9 (7 bits) of word 1.
8287 * Serial Number consists fo 12 alpha-numeric digits.
8289 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
8290 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
8291 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
8292 * 5 - Product revision (A-J) Word0: " "
8294 * Signature Word1: 15-9 (7 bits)
8295 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
8296 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
8298 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
8300 * Note 1: Only production cards will have a serial number.
8302 * Note 2: Signature is most significant 7 bits (0xFE).
8304 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
8306 STATIC int
8307 asc_get_eeprom_string(ushort *serialnum, uchar *cp)
8309 ushort w, num;
8311 if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) {
8312 return ASC_FALSE;
8313 } else {
8315 * First word - 6 digits.
8317 w = serialnum[0];
8319 /* Product type - 1st digit. */
8320 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
8321 /* Product type is P=Prototype */
8322 *cp += 0x8;
8324 cp++;
8326 /* Manufacturing location - 2nd digit. */
8327 *cp++ = 'A' + ((w & 0x1C00) >> 10);
8329 /* Product ID - 3rd, 4th digits. */
8330 num = w & 0x3FF;
8331 *cp++ = '0' + (num / 100);
8332 num %= 100;
8333 *cp++ = '0' + (num / 10);
8335 /* Product revision - 5th digit. */
8336 *cp++ = 'A' + (num % 10);
8339 * Second word
8341 w = serialnum[1];
8344 * Year - 6th digit.
8346 * If bit 15 of third word is set, then the
8347 * last digit of the year is greater than 7.
8349 if (serialnum[2] & 0x8000) {
8350 *cp++ = '8' + ((w & 0x1C0) >> 6);
8351 } else {
8352 *cp++ = '0' + ((w & 0x1C0) >> 6);
8355 /* Week of year - 7th, 8th digits. */
8356 num = w & 0x003F;
8357 *cp++ = '0' + num / 10;
8358 num %= 10;
8359 *cp++ = '0' + num;
8362 * Third word
8364 w = serialnum[2] & 0x7FFF;
8366 /* Serial number - 9th digit. */
8367 *cp++ = 'A' + (w / 1000);
8369 /* 10th, 11th, 12th digits. */
8370 num = w % 1000;
8371 *cp++ = '0' + num / 100;
8372 num %= 100;
8373 *cp++ = '0' + num / 10;
8374 num %= 10;
8375 *cp++ = '0' + num;
8377 *cp = '\0'; /* Null Terminate the string. */
8378 return ASC_TRUE;
8383 * asc_prt_asc_board_eeprom()
8385 * Print board EEPROM configuration.
8387 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8388 * cf. asc_prt_line().
8390 * Return the number of characters copied into 'cp'. No more than
8391 * 'cplen' characters will be copied to 'cp'.
8393 STATIC int
8394 asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8396 asc_board_t *boardp;
8397 ASC_DVC_VAR *asc_dvc_varp;
8398 int leftlen;
8399 int totlen;
8400 int len;
8401 ASCEEP_CONFIG *ep;
8402 int i;
8403 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
8404 uchar serialstr[13];
8406 boardp = ASC_BOARDP(shp);
8407 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
8408 ep = &boardp->eep_config.asc_eep;
8410 leftlen = cplen;
8411 totlen = len = 0;
8413 len = asc_prt_line(cp, leftlen,
8414 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8415 ASC_PRT_NEXT();
8417 if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) ==
8418 ASC_TRUE) {
8419 len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8420 ASC_PRT_NEXT();
8421 } else {
8422 if (ep->adapter_info[5] == 0xBB) {
8423 len = asc_prt_line(cp, leftlen,
8424 " Default Settings Used for EEPROM-less Adapter.\n");
8425 ASC_PRT_NEXT();
8426 } else {
8427 len = asc_prt_line(cp, leftlen,
8428 " Serial Number Signature Not Present.\n");
8429 ASC_PRT_NEXT();
8433 len = asc_prt_line(cp, leftlen,
8434 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8435 ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng);
8436 ASC_PRT_NEXT();
8438 len = asc_prt_line(cp, leftlen,
8439 " cntl %x, no_scam %x\n",
8440 ep->cntl, ep->no_scam);
8441 ASC_PRT_NEXT();
8443 len = asc_prt_line(cp, leftlen,
8444 " Target ID: ");
8445 ASC_PRT_NEXT();
8446 for (i = 0; i <= ASC_MAX_TID; i++) {
8447 len = asc_prt_line(cp, leftlen, " %d", i);
8448 ASC_PRT_NEXT();
8450 len = asc_prt_line(cp, leftlen, "\n");
8451 ASC_PRT_NEXT();
8453 len = asc_prt_line(cp, leftlen,
8454 " Disconnects: ");
8455 ASC_PRT_NEXT();
8456 for (i = 0; i <= ASC_MAX_TID; i++) {
8457 len = asc_prt_line(cp, leftlen, " %c",
8458 (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8459 ASC_PRT_NEXT();
8461 len = asc_prt_line(cp, leftlen, "\n");
8462 ASC_PRT_NEXT();
8464 len = asc_prt_line(cp, leftlen,
8465 " Command Queuing: ");
8466 ASC_PRT_NEXT();
8467 for (i = 0; i <= ASC_MAX_TID; i++) {
8468 len = asc_prt_line(cp, leftlen, " %c",
8469 (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8470 ASC_PRT_NEXT();
8472 len = asc_prt_line(cp, leftlen, "\n");
8473 ASC_PRT_NEXT();
8475 len = asc_prt_line(cp, leftlen,
8476 " Start Motor: ");
8477 ASC_PRT_NEXT();
8478 for (i = 0; i <= ASC_MAX_TID; i++) {
8479 len = asc_prt_line(cp, leftlen, " %c",
8480 (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8481 ASC_PRT_NEXT();
8483 len = asc_prt_line(cp, leftlen, "\n");
8484 ASC_PRT_NEXT();
8486 len = asc_prt_line(cp, leftlen,
8487 " Synchronous Transfer:");
8488 ASC_PRT_NEXT();
8489 for (i = 0; i <= ASC_MAX_TID; i++) {
8490 len = asc_prt_line(cp, leftlen, " %c",
8491 (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8492 ASC_PRT_NEXT();
8494 len = asc_prt_line(cp, leftlen, "\n");
8495 ASC_PRT_NEXT();
8497 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
8498 len = asc_prt_line(cp, leftlen,
8499 " Host ISA DMA speed: %d MB/S\n",
8500 isa_dma_speed[ep->isa_dma_speed]);
8501 ASC_PRT_NEXT();
8504 return totlen;
8508 * asc_prt_adv_board_eeprom()
8510 * Print board EEPROM configuration.
8512 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8513 * cf. asc_prt_line().
8515 * Return the number of characters copied into 'cp'. No more than
8516 * 'cplen' characters will be copied to 'cp'.
8518 STATIC int
8519 asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8521 asc_board_t *boardp;
8522 ADV_DVC_VAR *adv_dvc_varp;
8523 int leftlen;
8524 int totlen;
8525 int len;
8526 int i;
8527 char *termstr;
8528 uchar serialstr[13];
8529 ADVEEP_CONFIG *ep;
8531 boardp = ASC_BOARDP(shp);
8532 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
8533 ep = &boardp->eep_config.adv_eep;
8535 leftlen = cplen;
8536 totlen = len = 0;
8538 len = asc_prt_line(cp, leftlen,
8539 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8540 ASC_PRT_NEXT();
8542 if (asc_get_eeprom_string(&ep->serial_number_word1, serialstr) ==
8543 ASC_TRUE) {
8544 len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8545 ASC_PRT_NEXT();
8546 } else {
8547 len = asc_prt_line(cp, leftlen,
8548 " Serial Number Signature Not Present.\n");
8549 ASC_PRT_NEXT();
8552 len = asc_prt_line(cp, leftlen,
8553 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8554 ep->adapter_scsi_id, ep->max_host_qng, ep->max_dvc_qng);
8555 ASC_PRT_NEXT();
8557 switch (ep->termination) {
8558 case 1:
8559 termstr = "Low Off/High Off";
8560 break;
8561 case 2:
8562 termstr = "Low Off/High On";
8563 break;
8564 case 3:
8565 termstr = "Low On/High On";
8566 break;
8567 default:
8568 case 0:
8569 termstr = "Automatic";
8570 break;
8573 len = asc_prt_line(cp, leftlen,
8574 " termination: %u (%s), bios_ctrl: %x\n",
8575 ep->termination, termstr, ep->bios_ctrl);
8576 ASC_PRT_NEXT();
8578 len = asc_prt_line(cp, leftlen,
8579 " Target ID: ");
8580 ASC_PRT_NEXT();
8581 for (i = 0; i <= ADV_MAX_TID; i++) {
8582 len = asc_prt_line(cp, leftlen, " %X", i);
8583 ASC_PRT_NEXT();
8585 len = asc_prt_line(cp, leftlen, "\n");
8586 ASC_PRT_NEXT();
8588 len = asc_prt_line(cp, leftlen,
8589 " Disconnects: ");
8590 ASC_PRT_NEXT();
8591 for (i = 0; i <= ADV_MAX_TID; i++) {
8592 len = asc_prt_line(cp, leftlen, " %c",
8593 (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8594 ASC_PRT_NEXT();
8596 len = asc_prt_line(cp, leftlen, "\n");
8597 ASC_PRT_NEXT();
8599 len = asc_prt_line(cp, leftlen,
8600 " Command Queuing: ");
8601 ASC_PRT_NEXT();
8602 for (i = 0; i <= ADV_MAX_TID; i++) {
8603 len = asc_prt_line(cp, leftlen, " %c",
8604 (ep->tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8605 ASC_PRT_NEXT();
8607 len = asc_prt_line(cp, leftlen, "\n");
8608 ASC_PRT_NEXT();
8610 len = asc_prt_line(cp, leftlen,
8611 " Start Motor: ");
8612 ASC_PRT_NEXT();
8613 for (i = 0; i <= ADV_MAX_TID; i++) {
8614 len = asc_prt_line(cp, leftlen, " %c",
8615 (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8616 ASC_PRT_NEXT();
8618 len = asc_prt_line(cp, leftlen, "\n");
8619 ASC_PRT_NEXT();
8621 len = asc_prt_line(cp, leftlen,
8622 " Synchronous Transfer:");
8623 ASC_PRT_NEXT();
8624 for (i = 0; i <= ADV_MAX_TID; i++) {
8625 len = asc_prt_line(cp, leftlen, " %c",
8626 (ep->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8627 ASC_PRT_NEXT();
8629 len = asc_prt_line(cp, leftlen, "\n");
8630 ASC_PRT_NEXT();
8632 len = asc_prt_line(cp, leftlen,
8633 " Ultra Transfer: ");
8634 ASC_PRT_NEXT();
8635 for (i = 0; i <= ADV_MAX_TID; i++) {
8636 len = asc_prt_line(cp, leftlen, " %c",
8637 (ep->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8638 ASC_PRT_NEXT();
8640 len = asc_prt_line(cp, leftlen, "\n");
8641 ASC_PRT_NEXT();
8643 len = asc_prt_line(cp, leftlen,
8644 " Wide Transfer: ");
8645 ASC_PRT_NEXT();
8646 for (i = 0; i <= ADV_MAX_TID; i++) {
8647 len = asc_prt_line(cp, leftlen, " %c",
8648 (ep->wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8649 ASC_PRT_NEXT();
8651 len = asc_prt_line(cp, leftlen, "\n");
8652 ASC_PRT_NEXT();
8654 return totlen;
8658 * asc_prt_driver_conf()
8660 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8661 * cf. asc_prt_line().
8663 * Return the number of characters copied into 'cp'. No more than
8664 * 'cplen' characters will be copied to 'cp'.
8666 STATIC int
8667 asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
8669 asc_board_t *boardp;
8670 int leftlen;
8671 int totlen;
8672 int len;
8673 int chip_scsi_id;
8674 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
8675 int i;
8676 #endif /* version >= v1.3.89 */
8678 boardp = ASC_BOARDP(shp);
8680 leftlen = cplen;
8681 totlen = len = 0;
8683 len = asc_prt_line(cp, leftlen,
8684 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
8685 shp->host_no);
8686 ASC_PRT_NEXT();
8688 len = asc_prt_line(cp, leftlen,
8689 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
8690 " host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
8691 shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
8692 #else /* version >= v1.3.89 */
8693 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
8694 shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
8695 shp->max_channel);
8696 #endif /* version >= v1.3.89 */
8697 ASC_PRT_NEXT();
8699 len = asc_prt_line(cp, leftlen,
8700 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
8701 " can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
8702 shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
8703 #else /* version >= v1.3.57 */
8704 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
8705 shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
8706 shp->cmd_per_lun);
8707 #endif /* version >= v1.3.57 */
8708 ASC_PRT_NEXT();
8710 len = asc_prt_line(cp, leftlen,
8711 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
8712 " unchecked_isa_dma %d, loaded_as_module %d\n",
8713 shp->unchecked_isa_dma, shp->loaded_as_module);
8714 #else /* version >= v1.3.57 */
8715 " unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
8716 shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
8717 #endif /* version >= v1.3.57 */
8718 ASC_PRT_NEXT();
8720 len = asc_prt_line(cp, leftlen, " flags %x, last_reset %x, jiffies %x\n",
8721 boardp->flags, boardp->last_reset, jiffies);
8722 ASC_PRT_NEXT();
8724 if (ASC_NARROW_BOARD(boardp)) {
8725 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8726 } else {
8727 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8730 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
8731 if (boardp->flags & ASC_SELECT_QUEUE_DEPTHS) {
8732 len = asc_prt_line(cp, leftlen, " queue_depth:");
8733 ASC_PRT_NEXT();
8734 for (i = 0; i <= ADV_MAX_TID; i++) {
8735 if ((chip_scsi_id == i) ||
8736 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8737 continue;
8739 if (boardp->device[i] == NULL) {
8740 continue;
8742 len = asc_prt_line(cp, leftlen, " %X:%d",
8743 i, boardp->device[i]->queue_depth);
8744 ASC_PRT_NEXT();
8746 len = asc_prt_line(cp, leftlen, "\n");
8747 ASC_PRT_NEXT();
8749 #endif /* version >= v1.3.89 */
8751 #if ASC_QUEUE_FLOW_CONTROL
8752 if (ASC_NARROW_BOARD(boardp)) {
8753 len = asc_prt_line(cp, leftlen, " queue_curr_depth:");
8754 ASC_PRT_NEXT();
8755 /* Use ASC_MAX_TID for Narrow Board. */
8756 for (i = 0; i <= ASC_MAX_TID; i++) {
8757 if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
8758 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8759 continue;
8761 if (boardp->device[i] == NULL) {
8762 continue;
8764 len = asc_prt_line(cp, leftlen, " %d:%d",
8765 i, boardp->device[i]->queue_curr_depth);
8766 ASC_PRT_NEXT();
8768 len = asc_prt_line(cp, leftlen, "\n");
8769 ASC_PRT_NEXT();
8771 len = asc_prt_line(cp, leftlen, " queue_count:");
8772 ASC_PRT_NEXT();
8773 /* Use ASC_MAX_TID for Narrow Board. */
8774 for (i = 0; i <= ASC_MAX_TID; i++) {
8775 if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
8776 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8777 continue;
8779 if (boardp->device[i] == NULL) {
8780 continue;
8782 len = asc_prt_line(cp, leftlen, " %d:%d",
8783 i, boardp->device[i]->queue_count);
8784 ASC_PRT_NEXT();
8786 len = asc_prt_line(cp, leftlen, "\n");
8787 ASC_PRT_NEXT();
8789 #endif /* ASC_QUEUE_FLOW_CONTROL */
8791 return totlen;
8795 * asc_prt_asc_board_info()
8797 * Print dynamic board configuration information.
8799 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8800 * cf. asc_prt_line().
8802 * Return the number of characters copied into 'cp'. No more than
8803 * 'cplen' characters will be copied to 'cp'.
8805 STATIC int
8806 asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen)
8808 asc_board_t *boardp;
8809 int leftlen;
8810 int totlen;
8811 int len;
8812 ASC_DVC_VAR *v;
8813 ASC_DVC_CFG *c;
8814 int i;
8816 boardp = ASC_BOARDP(shp);
8817 v = &boardp->dvc_var.asc_dvc_var;
8818 c = &boardp->dvc_cfg.asc_dvc_cfg;
8820 leftlen = cplen;
8821 totlen = len = 0;
8823 len = asc_prt_line(cp, leftlen,
8824 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
8825 shp->host_no);
8826 ASC_PRT_NEXT();
8828 len = asc_prt_line(cp, leftlen,
8829 " chip_version %u, lib_version %x, lib_serial_no %u, mcode_date %x\n",
8830 c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date);
8831 ASC_PRT_NEXT();
8833 len = asc_prt_line(cp, leftlen,
8834 " mcode_version %x, err_code %u\n",
8835 c->mcode_version, v->err_code);
8836 ASC_PRT_NEXT();
8838 /* Current number of commands waiting for the host. */
8839 len = asc_prt_line(cp, leftlen,
8840 " Total Command Pending: %d\n", v->cur_total_qng);
8841 ASC_PRT_NEXT();
8843 len = asc_prt_line(cp, leftlen,
8844 " Command Queuing:");
8845 ASC_PRT_NEXT();
8846 for (i = 0; i <= ASC_MAX_TID; i++) {
8847 if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8848 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8849 continue;
8851 len = asc_prt_line(cp, leftlen, " %d:%c",
8852 i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8853 ASC_PRT_NEXT();
8855 len = asc_prt_line(cp, leftlen, "\n");
8856 ASC_PRT_NEXT();
8858 /* Current number of commands waiting for a device. */
8859 len = asc_prt_line(cp, leftlen,
8860 " Command Queue Pending:");
8861 ASC_PRT_NEXT();
8862 for (i = 0; i <= ASC_MAX_TID; i++) {
8863 if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8864 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8865 continue;
8867 len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
8868 ASC_PRT_NEXT();
8870 len = asc_prt_line(cp, leftlen, "\n");
8871 ASC_PRT_NEXT();
8873 /* Current limit on number of commands that can be sent to a device. */
8874 len = asc_prt_line(cp, leftlen,
8875 " Command Queue Limit:");
8876 ASC_PRT_NEXT();
8877 for (i = 0; i <= ASC_MAX_TID; i++) {
8878 if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8879 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8880 continue;
8882 len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
8883 ASC_PRT_NEXT();
8885 len = asc_prt_line(cp, leftlen, "\n");
8886 ASC_PRT_NEXT();
8888 /* Indicate whether the device has returned queue full status. */
8889 len = asc_prt_line(cp, leftlen,
8890 " Command Queue Full:");
8891 ASC_PRT_NEXT();
8892 for (i = 0; i <= ASC_MAX_TID; i++) {
8893 if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8894 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8895 continue;
8897 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
8898 len = asc_prt_line(cp, leftlen, " %d:Y-%d",
8899 i, boardp->queue_full_cnt[i]);
8900 } else {
8901 len = asc_prt_line(cp, leftlen, " %d:N", i);
8903 ASC_PRT_NEXT();
8905 len = asc_prt_line(cp, leftlen, "\n");
8906 ASC_PRT_NEXT();
8908 len = asc_prt_line(cp, leftlen,
8909 " Synchronous Transfer:");
8910 ASC_PRT_NEXT();
8911 for (i = 0; i <= ASC_MAX_TID; i++) {
8912 if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8913 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8914 continue;
8916 len = asc_prt_line(cp, leftlen, " %d:%c",
8917 i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8918 ASC_PRT_NEXT();
8920 len = asc_prt_line(cp, leftlen, "\n");
8921 ASC_PRT_NEXT();
8923 for (i = 0; i <= ASC_MAX_TID; i++) {
8924 uchar syn_period_ix;
8926 if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8927 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8928 continue;
8930 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
8931 continue;
8933 syn_period_ix = (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1);
8934 len = asc_prt_line(cp, leftlen, " %d:", i);
8935 ASC_PRT_NEXT();
8937 len = asc_prt_line(cp, leftlen,
8938 " Transfer Period Factor: %d (%d.%d Mhz),",
8939 v->sdtr_period_tbl[syn_period_ix],
8940 250 / v->sdtr_period_tbl[syn_period_ix],
8941 ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix]));
8942 ASC_PRT_NEXT();
8944 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
8945 boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
8946 ASC_PRT_NEXT();
8949 return totlen;
8953 * asc_prt_adv_board_info()
8955 * Print dynamic board configuration information.
8957 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8958 * cf. asc_prt_line().
8960 * Return the number of characters copied into 'cp'. No more than
8961 * 'cplen' characters will be copied to 'cp'.
8963 STATIC int
8964 asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen)
8966 asc_board_t *boardp;
8967 int leftlen;
8968 int totlen;
8969 int len;
8970 int i;
8971 ADV_DVC_VAR *v;
8972 ADV_DVC_CFG *c;
8973 AdvPortAddr iop_base;
8974 ushort chip_scsi_id;
8975 ushort lramword;
8976 uchar lrambyte;
8977 ushort sdtr_able;
8978 ushort period;
8980 boardp = ASC_BOARDP(shp);
8981 v = &boardp->dvc_var.adv_dvc_var;
8982 c = &boardp->dvc_cfg.adv_dvc_cfg;
8983 iop_base = v->iop_base;
8984 chip_scsi_id = v->chip_scsi_id;
8986 leftlen = cplen;
8987 totlen = len = 0;
8989 len = asc_prt_line(cp, leftlen,
8990 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
8991 shp->host_no);
8992 ASC_PRT_NEXT();
8994 len = asc_prt_line(cp, leftlen,
8995 " iop_base %lx, cable_detect: %X, err_code %u, idle_cmd_done %u\n",
8996 v->iop_base,
8997 AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT,
8998 v->err_code, v->idle_cmd_done);
8999 ASC_PRT_NEXT();
9001 len = asc_prt_line(cp, leftlen,
9002 " chip_version %u, lib_version %x, mcode_date %x, mcode_version %x\n",
9003 c->chip_version, c->lib_version, c->mcode_date, c->mcode_version);
9004 ASC_PRT_NEXT();
9006 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, lramword);
9007 len = asc_prt_line(cp, leftlen,
9008 " Queuing Enabled:");
9009 ASC_PRT_NEXT();
9010 for (i = 0; i <= ADV_MAX_TID; i++) {
9011 if ((chip_scsi_id == i) ||
9012 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9013 continue;
9016 len = asc_prt_line(cp, leftlen, " %X:%c",
9017 i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9018 ASC_PRT_NEXT();
9020 len = asc_prt_line(cp, leftlen, "\n");
9021 ASC_PRT_NEXT();
9023 len = asc_prt_line(cp, leftlen,
9024 " Queue Limit:");
9025 ASC_PRT_NEXT();
9026 for (i = 0; i <= ADV_MAX_TID; i++) {
9027 if ((chip_scsi_id == i) ||
9028 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9029 continue;
9032 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte);
9034 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9035 ASC_PRT_NEXT();
9037 len = asc_prt_line(cp, leftlen, "\n");
9038 ASC_PRT_NEXT();
9040 len = asc_prt_line(cp, leftlen,
9041 " Command Pending:");
9042 ASC_PRT_NEXT();
9043 for (i = 0; i <= ADV_MAX_TID; i++) {
9044 if ((chip_scsi_id == i) ||
9045 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9046 continue;
9049 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte);
9051 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9052 ASC_PRT_NEXT();
9054 len = asc_prt_line(cp, leftlen, "\n");
9055 ASC_PRT_NEXT();
9057 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, lramword);
9058 len = asc_prt_line(cp, leftlen,
9059 " Wide Enabled:");
9060 ASC_PRT_NEXT();
9061 for (i = 0; i <= ADV_MAX_TID; i++) {
9062 if ((chip_scsi_id == i) ||
9063 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9064 continue;
9067 len = asc_prt_line(cp, leftlen, " %X:%c",
9068 i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9069 ASC_PRT_NEXT();
9071 len = asc_prt_line(cp, leftlen, "\n");
9072 ASC_PRT_NEXT();
9074 len = asc_prt_line(cp, leftlen,
9075 " Transfer Bit Width:");
9076 ASC_PRT_NEXT();
9077 for (i = 0; i <= ADV_MAX_TID; i++) {
9078 if ((chip_scsi_id == i) ||
9079 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9080 continue;
9083 AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9084 lramword);
9085 len = asc_prt_line(cp, leftlen, " %X:%d",
9086 i, (lramword & 0x8000) ? 16 : 8);
9087 ASC_PRT_NEXT();
9089 len = asc_prt_line(cp, leftlen, "\n");
9090 ASC_PRT_NEXT();
9092 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
9093 len = asc_prt_line(cp, leftlen,
9094 " Synchronous Enabled:");
9095 ASC_PRT_NEXT();
9096 for (i = 0; i <= ADV_MAX_TID; i++) {
9097 if ((chip_scsi_id == i) ||
9098 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9099 continue;
9102 len = asc_prt_line(cp, leftlen, " %X:%c",
9103 i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9104 ASC_PRT_NEXT();
9106 len = asc_prt_line(cp, leftlen, "\n");
9107 ASC_PRT_NEXT();
9109 for (i = 0; i <= ADV_MAX_TID; i++) {
9111 AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9112 lramword);
9113 lramword &= ~0x8000;
9115 if ((chip_scsi_id == i) ||
9116 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0) ||
9117 (lramword == 0)) {
9118 continue;
9121 len = asc_prt_line(cp, leftlen, " %X:", i);
9122 ASC_PRT_NEXT();
9124 period = (((lramword >> 8) * 25) + 50)/4;
9126 len = asc_prt_line(cp, leftlen,
9127 " Transfer Period Factor: %d (%d.%d Mhz),",
9128 period, 250/period, ASC_TENTHS(250, period));
9129 ASC_PRT_NEXT();
9131 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
9132 lramword & 0x1F);
9133 ASC_PRT_NEXT();
9136 return totlen;
9140 * asc_proc_copy()
9142 * Copy proc information to a read buffer taking into account the current
9143 * read offset in the file and the remaining space in the read buffer.
9145 STATIC int
9146 asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
9147 char *cp, int cplen)
9149 int cnt = 0;
9151 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
9152 (unsigned) offset, (unsigned) advoffset, cplen);
9153 if (offset <= advoffset) {
9154 /* Read offset below current offset, copy everything. */
9155 cnt = ASC_MIN(cplen, leftlen);
9156 ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9157 (unsigned) curbuf, (unsigned) cp, cnt);
9158 memcpy(curbuf, cp, cnt);
9159 } else if (offset < advoffset + cplen) {
9160 /* Read offset within current range, partial copy. */
9161 cnt = (advoffset + cplen) - offset;
9162 cp = (cp + cplen) - cnt;
9163 cnt = ASC_MIN(cnt, leftlen);
9164 ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9165 (unsigned) curbuf, (unsigned) cp, cnt);
9166 memcpy(curbuf, cp, cnt);
9168 return cnt;
9172 * asc_prt_line()
9174 * If 'cp' is NULL print to the console, otherwise print to a buffer.
9176 * Return 0 if printing to the console, otherwise return the number of
9177 * bytes written to the buffer.
9179 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
9180 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
9182 STATIC int
9183 asc_prt_line(char *buf, int buflen, char *fmt, ...)
9185 va_list args;
9186 int ret;
9187 char s[ASC_PRTLINE_SIZE];
9189 va_start(args, fmt);
9190 ret = vsprintf(s, fmt, args);
9191 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
9192 if (buf == NULL) {
9193 (void) printk(s);
9194 ret = 0;
9195 } else {
9196 ret = ASC_MIN(buflen, ret);
9197 memcpy(buf, s, ret);
9199 va_end(args);
9200 return ret;
9202 #endif /* version >= v1.3.0 */
9206 * --- Functions Required by the Asc Library
9210 * Delay for 'n' milliseconds. Don't use the 'jiffies'
9211 * global variable which is incremented once every 5 ms
9212 * from a timer interrupt, because this function may be
9213 * called when interrupts are disabled.
9215 STATIC void
9216 DvcSleepMilliSecond(ulong n)
9218 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
9219 mdelay(n);
9222 STATIC int
9223 DvcEnterCritical(void)
9225 int flags;
9227 save_flags(flags);
9228 cli();
9229 return flags;
9232 STATIC void
9233 DvcLeaveCritical(int flags)
9235 restore_flags(flags);
9238 STATIC ulong
9239 DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
9240 ASC_SG_HEAD *asc_sg_head_ptr)
9242 ulong buf_size;
9244 buf_size = buf_len;
9245 asc_sg_head_ptr->entry_cnt = 1;
9246 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9247 asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
9248 #else /* version >= v2.0.0 */
9249 asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
9250 #endif /* version >= v2.0.0 */
9251 asc_sg_head_ptr->sg_list[0].bytes = buf_size;
9252 return buf_size;
9256 * void
9257 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9259 * Calling/Exit State:
9260 * none
9262 * Description:
9263 * Output an ASC_SCSI_Q structure to the chip
9265 STATIC void
9266 DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9268 int i;
9270 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
9271 AscSetChipLramAddr(iop_base, s_addr);
9272 for (i = 0; i < words; i++, outbuf++) {
9273 if (i == 2 || i == 10) {
9274 continue;
9276 AscSetChipLramDataNoSwap(iop_base, *outbuf);
9281 * void
9282 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9284 * Calling/Exit State:
9285 * none
9287 * Description:
9288 * Input an ASC_QDONE_INFO structure from the chip
9290 STATIC void
9291 DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9293 int i;
9295 AscSetChipLramAddr(iop_base, s_addr);
9296 for (i = 0; i < words; i++, inbuf++) {
9297 if (i == 5) {
9298 continue;
9300 *inbuf = AscGetChipLramDataNoSwap(iop_base);
9302 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
9306 * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
9308 * Calling/Exit State:
9309 * none
9311 * Description:
9312 * output a buffer to an i/o port address
9314 STATIC void
9315 DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
9317 int i;
9319 for (i = 0; i < words; i++, outbuf++)
9320 outpw(iop_base, *outbuf);
9324 * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
9326 * Calling/Exit State:
9327 * none
9329 * Description:
9330 * input a buffer from an i/o port address
9332 STATIC void
9333 DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
9335 int i;
9337 for (i = 0; i < words; i++, inbuf++)
9338 *inbuf = inpw(iop_base);
9342 * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
9344 * Calling/Exit State:
9345 * none
9347 * Description:
9348 * output a buffer of 32-bit integers to an i/o port address in
9349 * 16 bit integer units
9351 STATIC void
9352 DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
9354 int i;
9355 int words;
9356 ushort *pw;
9358 pw = (ushort *) pdw;
9359 words = dwords << 1;
9360 for(i = 0; i < words; i++, pw++) {
9361 outpw(port, *pw);
9363 return;
9367 * Read a PCI configuration byte.
9369 ASC_INITFUNC(
9370 STATIC uchar
9371 DvcReadPCIConfigByte(
9372 ASC_DVC_VAR asc_ptr_type *asc_dvc,
9373 ushort offset)
9376 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9377 #ifdef ASC_CONFIG_PCI
9378 PCI_DATA pciData;
9380 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9381 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9382 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9383 pciData.offset = offset;
9384 pciData.type = pci_scan_method;
9385 return asc_get_cfg_byte(&pciData);
9386 #else /* ASC_CONFIG_PCI */
9387 return 0;
9388 #endif /* ASC_CONFIG_PCI */
9389 #else /* version >= v2.1.93 */
9390 #ifdef CONFIG_PCI
9391 uchar byte_data;
9392 pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9393 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9394 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9395 offset, &byte_data);
9396 return byte_data;
9397 #else /* CONFIG_PCI */
9398 return 0;
9399 #endif /* CONFIG_PCI */
9400 #endif /* version >= v2.1.93 */
9404 * Write a PCI configuration byte.
9406 ASC_INITFUNC(
9407 STATIC void
9408 DvcWritePCIConfigByte(
9409 ASC_DVC_VAR asc_ptr_type *asc_dvc,
9410 ushort offset,
9411 uchar byte_data)
9414 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9415 #ifdef ASC_CONFIG_PCI
9416 PCI_DATA pciData;
9418 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9419 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9420 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9421 pciData.offset = offset;
9422 pciData.type = pci_scan_method;
9423 asc_put_cfg_byte(&pciData, byte_data);
9424 #endif /* ASC_CONFIG_PCI */
9425 #else /* version >= v2.1.93 */
9426 #ifdef CONFIG_PCI
9427 pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9428 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9429 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9430 offset, byte_data);
9431 #endif /* CONFIG_PCI */
9432 #endif /* version >= v2.1.93 */
9436 * Return the BIOS address of the adapter at the specified
9437 * I/O port and with the specified bus type.
9439 ASC_INITFUNC(
9440 STATIC ushort
9441 AscGetChipBiosAddress(
9442 PortAddr iop_base,
9443 ushort bus_type
9447 ushort cfg_lsw ;
9448 ushort bios_addr ;
9451 * The PCI BIOS is re-located by the motherboard BIOS. Because
9452 * of this the driver can not determine where a PCI BIOS is
9453 * loaded and executes.
9455 if (bus_type & ASC_IS_PCI)
9457 return(0);
9460 if((bus_type & ASC_IS_EISA) != 0)
9462 cfg_lsw = AscGetEisaChipCfg(iop_base) ;
9463 cfg_lsw &= 0x000F ;
9464 bios_addr = (ushort)(ASC_BIOS_MIN_ADDR +
9465 (cfg_lsw * ASC_BIOS_BANK_SIZE)) ;
9466 return(bios_addr) ;
9467 }/* if */
9469 cfg_lsw = AscGetChipCfgLsw(iop_base) ;
9472 * ISA PnP uses the top bit as the 32K BIOS flag
9474 if (bus_type == ASC_IS_ISAPNP)
9476 cfg_lsw &= 0x7FFF;
9477 }/* if */
9479 bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
9480 ASC_BIOS_MIN_ADDR) ;
9481 return(bios_addr) ;
9486 * --- Functions Required by the Adv Library
9490 * DvcGetPhyAddr()
9492 * Return the physical address of 'vaddr' and set '*lenp' to the
9493 * number of physically contiguous bytes that follow 'vaddr'.
9494 * 'flag' indicates the type of structure whose physical address
9495 * is being translated.
9497 * Note: Because Linux currently doesn't page the kernel and all
9498 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
9500 ulong
9501 DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
9502 uchar *vaddr, long *lenp, int flag)
9504 ulong paddr;
9506 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9507 paddr = (ulong) vaddr;
9508 #else /* version >= v2.0.0 */
9509 paddr = virt_to_bus(vaddr);
9510 #endif /* version >= v2.0.0 */
9512 ASC_DBG4(4,
9513 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
9514 (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), paddr);
9516 return paddr;
9520 * Read a PCI configuration byte.
9522 ASC_INITFUNC(
9523 STATIC uchar
9524 DvcAdvReadPCIConfigByte(
9525 ADV_DVC_VAR *asc_dvc,
9526 ushort offset)
9529 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9530 #ifdef ASC_CONFIG_PCI
9531 PCI_DATA pciData;
9533 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9534 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9535 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9536 pciData.offset = offset;
9537 pciData.type = pci_scan_method;
9538 return asc_get_cfg_byte(&pciData);
9539 #else /* ASC_CONFIG_PCI */
9540 return 0;
9541 #endif /* ASC_CONFIG_PCI */
9542 #else /* version >= v2.1.93 */
9543 #ifdef CONFIG_PCI
9544 uchar byte_data;
9545 pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9546 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9547 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9548 offset, &byte_data);
9549 return byte_data;
9550 #else /* CONFIG_PCI */
9551 return 0;
9552 #endif /* CONFIG_PCI */
9553 #endif /* version >= v2.1.93 */
9557 * Write a PCI configuration byte.
9559 ASC_INITFUNC(
9560 STATIC void
9561 DvcAdvWritePCIConfigByte(
9562 ADV_DVC_VAR *asc_dvc,
9563 ushort offset,
9564 uchar byte_data)
9567 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9568 #ifdef ASC_CONFIG_PCI
9569 PCI_DATA pciData;
9571 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9572 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9573 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9574 pciData.offset = offset;
9575 pciData.type = pci_scan_method;
9576 asc_put_cfg_byte(&pciData, byte_data);
9577 #endif /* ASC_CONFIG_PCI */
9578 #else /* version >= v2.1.93 */
9579 #ifdef CONFIG_PCI
9580 pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9581 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9582 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9583 offset, byte_data);
9584 #endif /* CONFIG_PCI */
9585 #endif /* version >= v2.1.93 */
9589 * --- Tracing and Debugging Functions
9592 #ifdef ADVANSYS_STATS
9594 * asc_prt_board_stats()
9596 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9597 * cf. asc_prt_line().
9599 * Return the number of characters copied into 'cp'. No more than
9600 * 'cplen' characters will be copied to 'cp'.
9602 STATIC int
9603 asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
9605 int leftlen;
9606 int totlen;
9607 int len;
9608 struct asc_stats *s;
9609 int i;
9610 ushort chip_scsi_id;
9611 asc_board_t *boardp;
9612 asc_queue_t *active;
9613 asc_queue_t *waiting;
9615 leftlen = cplen;
9616 totlen = len = 0;
9618 boardp = ASC_BOARDP(shp);
9619 s = &boardp->asc_stats;
9621 len = asc_prt_line(cp, leftlen,
9622 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no);
9623 ASC_PRT_NEXT();
9625 len = asc_prt_line(cp, leftlen,
9626 " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n",
9627 s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
9628 ASC_PRT_NEXT();
9630 len = asc_prt_line(cp, leftlen,
9631 " interrupt %lu, callback %lu, done %lu\n",
9632 s->interrupt, s->callback, s->done);
9633 ASC_PRT_NEXT();
9635 len = asc_prt_line(cp, leftlen,
9636 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
9637 s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown);
9638 ASC_PRT_NEXT();
9640 if (ASC_NARROW_BOARD(boardp)) {
9641 len = asc_prt_line(cp, leftlen,
9642 " build_error %lu\n",
9643 s->build_error);
9644 } else {
9645 len = asc_prt_line(cp, leftlen,
9646 " build_error %lu, build_noreq %lu, build_nosg %lu\n",
9647 s->build_error, s->adv_build_noreq, s->adv_build_nosg);
9649 ASC_PRT_NEXT();
9652 * Display data transfer statistics.
9654 if (s->cont_cnt > 0) {
9655 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
9656 ASC_PRT_NEXT();
9658 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
9659 s->cont_xfer/2,
9660 ASC_TENTHS(s->cont_xfer, 2));
9661 ASC_PRT_NEXT();
9663 /* Contiguous transfer average size */
9664 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
9665 (s->cont_xfer/2)/s->cont_cnt,
9666 ASC_TENTHS((s->cont_xfer/2), s->cont_cnt));
9667 ASC_PRT_NEXT();
9670 if (s->sg_cnt > 0) {
9672 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
9673 s->sg_cnt, s->sg_elem);
9674 ASC_PRT_NEXT();
9676 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
9677 s->sg_xfer/2,
9678 ASC_TENTHS(s->sg_xfer, 2));
9679 ASC_PRT_NEXT();
9681 /* Scatter gather transfer statistics */
9682 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
9683 s->sg_elem/s->sg_cnt,
9684 ASC_TENTHS(s->sg_elem, s->sg_cnt));
9685 ASC_PRT_NEXT();
9687 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
9688 (s->sg_xfer/2)/s->sg_elem,
9689 ASC_TENTHS((s->sg_xfer/2), s->sg_elem));
9690 ASC_PRT_NEXT();
9692 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
9693 (s->sg_xfer/2)/s->sg_cnt,
9694 ASC_TENTHS((s->sg_xfer/2), s->sg_cnt));
9695 ASC_PRT_NEXT();
9699 * Display request queuing statistics.
9701 len = asc_prt_line(cp, leftlen,
9702 " Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ);
9703 ASC_PRT_NEXT();
9705 active = &ASC_BOARDP(shp)->active;
9706 waiting = &ASC_BOARDP(shp)->waiting;
9708 if (ASC_NARROW_BOARD(boardp)) {
9709 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
9710 } else {
9711 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
9714 for (i = 0; i <= ADV_MAX_TID; i++) {
9716 if ((chip_scsi_id == i) ||
9717 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9718 continue;
9721 if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
9722 len = asc_prt_line(cp, leftlen, " target %d\n", i);
9723 ASC_PRT_NEXT();
9725 len = asc_prt_line(cp, leftlen,
9726 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
9727 active->q_cur_cnt[i], active->q_max_cnt[i],
9728 active->q_tot_cnt[i],
9729 active->q_min_tim[i], active->q_max_tim[i],
9730 (active->q_tot_cnt[i] == 0) ? 0 :
9731 (active->q_tot_tim[i]/active->q_tot_cnt[i]),
9732 (active->q_tot_cnt[i] == 0) ? 0 :
9733 ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
9734 ASC_PRT_NEXT();
9736 len = asc_prt_line(cp, leftlen,
9737 " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
9738 waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
9739 waiting->q_tot_cnt[i],
9740 waiting->q_min_tim[i], waiting->q_max_tim[i],
9741 (waiting->q_tot_cnt[i] == 0) ? 0 :
9742 (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
9743 (waiting->q_tot_cnt[i] == 0) ? 0 :
9744 ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
9745 ASC_PRT_NEXT();
9749 return totlen;
9751 #endif /* ADVANSYS_STATS */
9753 #ifdef ADVANSYS_DEBUG
9755 * asc_prt_scsi_host()
9757 STATIC void
9758 asc_prt_scsi_host(struct Scsi_Host *s)
9760 asc_board_t *boardp;
9762 boardp = ASC_BOARDP(s);
9764 printk("Scsi_Host at addr %x\n", (unsigned) s);
9765 printk(
9766 " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
9767 (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
9768 (unsigned) s->last_reset);
9770 printk(
9771 " host_wait %x, host_queue %x, hostt %x, block %x,\n",
9772 (unsigned) s->host_wait, (unsigned) s->host_queue,
9773 (unsigned) s->hostt, (unsigned) s->block);
9775 printk(
9776 " wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
9777 s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
9778 s->irq, s->dma_channel);
9780 printk(
9781 " this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
9783 printk(
9784 " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
9785 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
9786 s->loaded_as_module);
9788 if (ASC_NARROW_BOARD(boardp)) {
9789 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
9790 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
9791 } else {
9792 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
9793 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
9798 * asc_prt_scsi_cmnd()
9800 STATIC void
9801 asc_prt_scsi_cmnd(Scsi_Cmnd *s)
9803 printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
9805 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
9806 printk(
9807 " host %x, device %x, target %u, lun %u\n",
9808 (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
9809 #else /* version >= v1.3.0 */
9810 printk(
9811 " host %x, device %x, target %u, lun %u, channel %u,\n",
9812 (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
9813 s->channel);
9814 #endif /* version >= v1.3.0 */
9816 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
9818 printk(
9819 " use_sg %u, sglist_len %u, abort_reason %x\n",
9820 s->use_sg, s->sglist_len, s->abort_reason);
9822 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
9823 printk(
9824 " retries %d, allowed %d\n",
9825 s->retries, s->allowed);
9826 #else /* version >= v1.3.89 */
9827 printk(
9828 " serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
9829 (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
9830 s->retries, s->allowed);
9831 #endif /* version >= v1.3.89 */
9833 printk(
9834 " timeout_per_command %d, timeout_total %d, timeout %d\n",
9835 s->timeout_per_command, s->timeout_total, s->timeout);
9837 printk(
9838 " internal_timeout %u, flags %u, this_count %d\n",
9839 s->internal_timeout, s->flags, s->this_count);
9841 printk(
9842 " scsi_done %x, done %x, host_scribble %x, result %x\n",
9843 (unsigned) s->scsi_done, (unsigned) s->done,
9844 (unsigned) s->host_scribble, s->result);
9846 printk(
9847 " tag %u, pid %u\n",
9848 (unsigned) s->tag, (unsigned) s->pid);
9852 * asc_prt_asc_dvc_var()
9854 STATIC void
9855 asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
9857 printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
9859 printk(
9860 " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
9861 h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
9863 printk(
9864 " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
9865 h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
9866 (unsigned) h->init_sdtr);
9868 printk(
9869 " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
9870 (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
9871 (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
9873 printk(
9874 " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
9875 (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
9876 (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
9878 printk(
9879 " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
9880 (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
9881 (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
9883 printk(
9884 " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
9885 (unsigned) h->last_q_shortage, (unsigned) h->init_state,
9886 (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
9888 printk(
9889 " cfg %x, saved_ptr2func %x\n",
9890 (unsigned) h->cfg, (unsigned) h->saved_ptr2func);
9894 * asc_prt_asc_dvc_cfg()
9896 STATIC void
9897 asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
9899 printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
9901 printk(
9902 " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n",
9903 h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable,
9904 h->sdtr_enable);
9906 printk(
9907 " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
9908 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
9909 h->chip_version);
9911 printk(
9912 " pci_device_id %d, lib_serial_no %x, lib_version %x, mcode_date %x,\n",
9913 h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
9915 printk(
9916 " mcode_version %d, overrun_buf %x\n",
9917 h->mcode_version, (unsigned) h->overrun_buf);
9921 * asc_prt_asc_scsi_q()
9923 STATIC void
9924 asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
9926 ASC_SG_HEAD *sgp;
9927 int i;
9929 printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
9931 printk(
9932 " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
9933 q->q2.target_ix, q->q1.target_lun,
9934 (unsigned) q->q2.srb_ptr, q->q2.tag_code);
9936 printk(
9937 " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
9938 (unsigned) q->q1.data_addr, q->q1.data_cnt,
9939 (unsigned) q->q1.sense_addr, q->q1.sense_len);
9941 printk(
9942 " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
9943 (unsigned) q->cdbptr, q->q2.cdb_len,
9944 (unsigned) q->sg_head, q->q1.sg_queue_cnt);
9946 if (q->sg_head) {
9947 sgp = q->sg_head;
9948 printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
9949 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
9950 for (i = 0; i < sgp->entry_cnt; i++) {
9951 printk(" [%u]: addr %x, bytes %lu\n",
9952 i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
9959 * asc_prt_asc_qdone_info()
9961 STATIC void
9962 asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
9964 printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
9965 printk(
9966 " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
9967 (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
9968 q->d2.tag_code, q->d3.done_stat);
9969 printk(
9970 " host_stat %x, scsi_stat %x, scsi_msg %x\n",
9971 q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
9975 * asc_prt_adv_dvc_var()
9977 * Display an ADV_DVC_VAR structure.
9979 STATIC void
9980 asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
9982 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h);
9984 printk(
9985 " iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
9986 (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able);
9988 printk(
9989 " isr_callback 0x%x, sdtr_able 0x%x, wdtr_able 0x%x\n",
9990 (unsigned) h->isr_callback, (unsigned) h->wdtr_able,
9991 (unsigned) h->sdtr_able);
9993 printk(
9994 " start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
9995 (unsigned) h->start_motor,
9996 (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
9998 printk(
9999 " max_host_qng 0x%x, cur_host_qng 0x%x, max_dvc_qng 0x%x\n",
10000 (unsigned) h->max_host_qng, (unsigned) h->cur_host_qng,
10001 (unsigned) h->max_dvc_qng);
10003 printk(
10004 " no_scam 0x%x, tagqng_able 0x%x, chip_scsi_id 0x%x, cfg 0x%lx\n",
10005 (unsigned) h->no_scam, (unsigned) h->tagqng_able,
10006 (unsigned) h->chip_scsi_id, (ulong) h->cfg);
10011 * asc_prt_adv_dvc_cfg()
10013 * Display an ADV_DVC_CFG structure.
10015 STATIC void
10016 asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
10018 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h);
10020 printk(
10021 " disc_enable 0x%x, termination 0x%x\n",
10022 h->disc_enable, h->termination);
10024 printk(
10025 " chip_version 0x%x, mcode_date 0x%x\n",
10026 h->chip_version, h->mcode_date);
10028 printk(
10029 " mcode_version 0x%x, pci_device_id 0x%x, lib_version 0x%x\n",
10030 h->mcode_version, h->pci_device_id, h->lib_version);
10032 printk(
10033 " control_flag 0x%x, pci_slot_info 0x%x\n",
10034 h->control_flag, h->pci_slot_info);
10038 * asc_prt_adv_scsi_req_q()
10040 * Display an ADV_SCSI_REQ_Q structure.
10042 STATIC void
10043 asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
10045 int i;
10046 struct asc_sg_block *sg_ptr;
10048 printk("ADV_SCSI_REQ_Q at addr %x\n", (unsigned) q);
10050 printk(
10051 " target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
10052 q->target_id, q->target_lun, q->srb_ptr, q->a_flag);
10054 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
10055 q->cntl, q->data_addr, q->vdata_addr);
10057 printk(
10058 " data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
10059 q->data_cnt, q->sense_addr, q->sense_len);
10061 printk(
10062 " cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
10063 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
10065 printk(
10066 " vsense_addr 0x%lx, scsiq_ptr 0x%lx, ux_wk_data_cnt %lu\n",
10067 (ulong) q->vsense_addr, (ulong) q->scsiq_ptr,
10068 (ulong) q->ux_wk_data_cnt);
10070 printk(
10071 " sg_list_ptr 0x%lx, sg_real_addr 0x%lx, sg_entry_cnt %u\n",
10072 (ulong) q->sg_list_ptr, (ulong) q->sg_real_addr, q->sg_entry_cnt);
10074 printk(
10075 " ux_sg_ix %u, orig_sense_len %u\n",
10076 q->ux_sg_ix, q->orig_sense_len);
10078 /* Display the request's ADV_SG_BLOCK structures. */
10079 for (sg_ptr = q->sg_list_ptr, i = 0; sg_ptr != NULL;
10080 sg_ptr = sg_ptr->sg_ptr, i++) {
10082 * 'sg_ptr' is a physical address. Convert it to a virtual
10083 * address by indexing 'i' into the virtual address array
10084 * 'sg_list_ptr'.
10086 * At the end of the each iteration of the loop 'sg_ptr' is
10087 * converted back into a physical address by setting 'sg_ptr'
10088 * to the next pointer 'sg_ptr->sg_ptr'.
10090 sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[i]);
10091 asc_prt_adv_sgblock(i, sg_ptr);
10096 * asc_prt_adv_sgblock()
10098 * Display an ADV_SG_BLOCK structure.
10100 STATIC void
10101 asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
10103 int i, s;
10105 /* Calculate starting entry number for the current block. */
10106 s = sgblockno * NO_OF_SG_PER_BLOCK;
10108 printk(" ADV_SG_BLOCK at addr 0x%lx (sgblockno %lu)\n",
10109 (ulong) b, (ulong) sgblockno);
10110 printk(
10111 " first_entry_no %lu, last_entry_no %lu, sg_ptr 0x%lx\n",
10112 (ulong) b->first_entry_no, (ulong) b->last_entry_no, (ulong) b->sg_ptr);
10113 ASC_ASSERT(b->first_entry_no - s >= 0);
10114 ASC_ASSERT(b->last_entry_no - s >= 0);
10115 ASC_ASSERT(b->last_entry_no - s <= NO_OF_SG_PER_BLOCK);
10116 ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
10117 ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
10118 ASC_ASSERT(b->first_entry_no - s <= b->last_entry_no - s);
10119 for (i = b->first_entry_no - s; i <= b->last_entry_no - s; i++) {
10120 printk(" [%lu]: sg_addr 0x%lx, sg_count 0x%lx\n",
10121 (ulong) i, (ulong) b->sg_list[i].sg_addr,
10122 (ulong) b->sg_list[i].sg_count);
10127 * asc_prt_hex()
10129 * Print hexadecimal output in 4 byte groupings 32 bytes
10130 * or 8 double-words per line.
10132 STATIC void
10133 asc_prt_hex(char *f, uchar *s, int l)
10135 int i;
10136 int j;
10137 int k;
10138 int m;
10140 printk("%s: (%d bytes)\n", f, l);
10142 for (i = 0; i < l; i += 32) {
10144 /* Display a maximum of 8 double-words per line. */
10145 if ((k = (l - i) / 4) >= 8) {
10146 k = 8;
10147 m = 0;
10148 } else {
10149 m = (l - i) % 4 ;
10152 for (j = 0; j < k; j++) {
10153 printk(" %2.2X%2.2X%2.2X%2.2X",
10154 (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
10155 (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
10158 switch (m) {
10159 case 0:
10160 default:
10161 break;
10162 case 1:
10163 printk(" %2.2X",
10164 (unsigned) s[i+(j*4)]);
10165 break;
10166 case 2:
10167 printk(" %2.2X%2.2X",
10168 (unsigned) s[i+(j*4)],
10169 (unsigned) s[i+(j*4)+1]);
10170 break;
10171 case 3:
10172 printk(" %2.2X%2.2X%2.2X",
10173 (unsigned) s[i+(j*4)+1],
10174 (unsigned) s[i+(j*4)+2],
10175 (unsigned) s[i+(j*4)+3]);
10176 break;
10179 printk("\n");
10182 #endif /* ADVANSYS_DEBUG */
10184 #ifdef ADVANSYS_ASSERT
10186 * interrupts_enabled()
10188 * Return 1 if interrupts are enabled, otherwise return 0.
10190 STATIC int
10191 interrupts_enabled(void)
10193 int flags;
10195 save_flags(flags);
10196 if (flags & 0x0200) {
10197 return ASC_TRUE;
10198 } else {
10199 return ASC_FALSE;
10202 #endif /* ADVANSYS_ASSERT */
10206 * --- Asc Library Functions
10209 ASC_INITFUNC(
10210 STATIC ushort
10211 AscGetEisaChipCfg(
10212 PortAddr iop_base
10216 PortAddr eisa_cfg_iop;
10218 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10219 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
10220 return (inpw(eisa_cfg_iop));
10223 ASC_INITFUNC(
10224 STATIC uchar
10225 AscSetChipScsiID(
10226 PortAddr iop_base,
10227 uchar new_host_id
10231 ushort cfg_lsw;
10233 if (AscGetChipScsiID(iop_base) == new_host_id) {
10234 return (new_host_id);
10236 cfg_lsw = AscGetChipCfgLsw(iop_base);
10237 cfg_lsw &= 0xF8FF;
10238 cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
10239 AscSetChipCfgLsw(iop_base, cfg_lsw);
10240 return (AscGetChipScsiID(iop_base));
10243 ASC_INITFUNC(
10244 STATIC uchar
10245 AscGetChipScsiCtrl(
10246 PortAddr iop_base
10250 uchar sc;
10252 AscSetBank(iop_base, 1);
10253 sc = inp(iop_base + IOP_REG_SC);
10254 AscSetBank(iop_base, 0);
10255 return (sc);
10258 ASC_INITFUNC(
10259 STATIC uchar
10260 AscGetChipVersion(
10261 PortAddr iop_base,
10262 ushort bus_type
10266 if ((bus_type & ASC_IS_EISA) != 0) {
10267 PortAddr eisa_iop;
10268 uchar revision;
10269 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10270 (PortAddr) ASC_EISA_REV_IOP_MASK;
10271 revision = inp(eisa_iop);
10272 return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
10274 return (AscGetChipVerNo(iop_base));
10277 ASC_INITFUNC(
10278 STATIC ushort
10279 AscGetChipBusType(
10280 PortAddr iop_base
10284 ushort chip_ver;
10286 chip_ver = AscGetChipVerNo(iop_base);
10287 if (
10288 (chip_ver >= ASC_CHIP_MIN_VER_VL)
10289 && (chip_ver <= ASC_CHIP_MAX_VER_VL)
10291 if (
10292 ((iop_base & 0x0C30) == 0x0C30)
10293 || ((iop_base & 0x0C50) == 0x0C50)
10295 return (ASC_IS_EISA);
10297 return (ASC_IS_VL);
10299 if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
10300 (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
10301 if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
10302 return (ASC_IS_ISAPNP);
10304 return (ASC_IS_ISA);
10305 } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
10306 (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
10307 return (ASC_IS_PCI);
10309 return (0);
10312 ASC_INITFUNC(
10313 STATIC ulong
10314 AscLoadMicroCode(
10315 PortAddr iop_base,
10316 ushort s_addr,
10317 ushort *mcode_buf,
10318 ushort mcode_size
10322 ulong chksum;
10323 ushort mcode_word_size;
10324 ushort mcode_chksum;
10326 mcode_word_size = (ushort) (mcode_size >> 1);
10327 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
10328 AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
10329 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
10330 mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
10331 (ushort) ASC_CODE_SEC_BEG,
10332 (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
10333 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
10334 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
10335 return (chksum);
10338 ASC_INITFUNC(
10339 STATIC int
10340 AscFindSignature(
10341 PortAddr iop_base
10345 ushort sig_word;
10347 if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
10348 sig_word = AscGetChipSignatureWord(iop_base);
10349 if ((sig_word == (ushort) ASC_1000_ID0W) ||
10350 (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
10351 return (1);
10354 return (0);
10357 STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
10358 STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
10360 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
10361 ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
10364 ASC_INITFUNC(
10365 STATIC PortAddr
10366 AscSearchIOPortAddr(
10367 PortAddr iop_beg,
10368 ushort bus_type
10372 if (bus_type & ASC_IS_VL) {
10373 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
10374 if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
10375 return (iop_beg);
10378 return (0);
10380 if (bus_type & ASC_IS_ISA) {
10381 if (_isa_pnp_inited == 0) {
10382 AscSetISAPNPWaitForKey();
10383 _isa_pnp_inited++;
10385 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
10386 if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
10387 return (iop_beg);
10390 return (0);
10392 if (bus_type & ASC_IS_EISA) {
10393 if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
10394 return (iop_beg);
10396 return (0);
10398 return (0);
10401 ASC_INITFUNC(
10402 STATIC PortAddr
10403 AscSearchIOPortAddr11(
10404 PortAddr s_addr
10408 int i;
10409 PortAddr iop_base;
10411 for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
10412 if (_asc_def_iop_base[i] > s_addr) {
10413 break;
10416 for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
10417 iop_base = _asc_def_iop_base[i];
10418 if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
10419 ASC_DBG1(1,
10420 "AscSearchIOPortAddr11: check_region() failed I/O port %x\n",
10421 iop_base);
10422 continue;
10424 ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base);
10425 if (AscFindSignature(iop_base)) {
10426 return (iop_base);
10429 return (0);
10432 ASC_INITFUNC(
10433 STATIC void
10434 AscToggleIRQAct(
10435 PortAddr iop_base
10439 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
10440 AscSetChipStatus(iop_base, 0);
10441 return;
10444 ASC_INITFUNC(
10445 STATIC void
10446 AscSetISAPNPWaitForKey(
10447 void)
10450 outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
10451 outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
10452 return;
10455 ASC_INITFUNC(
10456 STATIC uchar
10457 AscGetChipIRQ(
10458 PortAddr iop_base,
10459 ushort bus_type
10463 ushort cfg_lsw;
10464 uchar chip_irq;
10466 if ((bus_type & ASC_IS_EISA) != 0) {
10467 cfg_lsw = AscGetEisaChipCfg(iop_base);
10468 chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
10469 if ((chip_irq == 13) || (chip_irq > 15)) {
10470 return (0);
10472 return (chip_irq);
10474 if ((bus_type & ASC_IS_VL) != 0) {
10475 cfg_lsw = AscGetChipCfgLsw(iop_base);
10476 chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
10477 if ((chip_irq == 0) ||
10478 (chip_irq == 4) ||
10479 (chip_irq == 7)) {
10480 return (0);
10482 return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
10484 cfg_lsw = AscGetChipCfgLsw(iop_base);
10485 chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
10486 if (chip_irq == 3)
10487 chip_irq += (uchar) 2;
10488 return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
10491 ASC_INITFUNC(
10492 STATIC uchar
10493 AscSetChipIRQ(
10494 PortAddr iop_base,
10495 uchar irq_no,
10496 ushort bus_type
10500 ushort cfg_lsw;
10502 if ((bus_type & ASC_IS_VL) != 0) {
10503 if (irq_no != 0) {
10504 if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
10505 irq_no = 0;
10506 } else {
10507 irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
10510 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
10511 cfg_lsw |= (ushort) 0x0010;
10512 AscSetChipCfgLsw(iop_base, cfg_lsw);
10513 AscToggleIRQAct(iop_base);
10514 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
10515 cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
10516 AscSetChipCfgLsw(iop_base, cfg_lsw);
10517 AscToggleIRQAct(iop_base);
10518 return (AscGetChipIRQ(iop_base, bus_type));
10520 if ((bus_type & (ASC_IS_ISA)) != 0) {
10521 if (irq_no == 15)
10522 irq_no -= (uchar) 2;
10523 irq_no -= (uchar) ASC_MIN_IRQ_NO;
10524 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
10525 cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
10526 AscSetChipCfgLsw(iop_base, cfg_lsw);
10527 return (AscGetChipIRQ(iop_base, bus_type));
10529 return (0);
10532 ASC_INITFUNC(
10533 STATIC void
10534 AscEnableIsaDma(
10535 uchar dma_channel
10539 if (dma_channel < 4) {
10540 outp(0x000B, (ushort) (0xC0 | dma_channel));
10541 outp(0x000A, dma_channel);
10542 } else if (dma_channel < 8) {
10543 outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
10544 outp(0x00D4, (ushort) (dma_channel - 4));
10546 return;
10549 STATIC int
10550 AscIsrChipHalted(
10551 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
10554 EXT_MSG ext_msg;
10555 EXT_MSG out_msg;
10556 ushort halt_q_addr;
10557 int sdtr_accept;
10558 ushort int_halt_code;
10559 ASC_SCSI_BIT_ID_TYPE scsi_busy;
10560 ASC_SCSI_BIT_ID_TYPE target_id;
10561 PortAddr iop_base;
10562 uchar tag_code;
10563 uchar q_status;
10564 uchar halt_qp;
10565 uchar sdtr_data;
10566 uchar target_ix;
10567 uchar q_cntl, tid_no;
10568 uchar cur_dvc_qng;
10569 uchar asyn_sdtr;
10570 uchar scsi_status;
10571 asc_board_t *boardp;
10573 ASC_ASSERT(asc_dvc->drv_ptr != 0);
10574 boardp = (asc_board_t *) asc_dvc->drv_ptr;
10576 iop_base = asc_dvc->iop_base;
10577 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
10579 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
10580 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
10581 target_ix = AscReadLramByte(iop_base,
10582 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
10583 q_cntl = AscReadLramByte(iop_base,
10584 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
10585 tid_no = ASC_TIX_TO_TID(target_ix);
10586 target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
10587 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10589 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
10590 } else {
10591 asyn_sdtr = 0;
10593 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
10594 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10595 AscSetChipSDTR(iop_base, 0, tid_no);
10596 boardp->sdtr_data[tid_no] = 0;
10598 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10599 return (0);
10600 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
10601 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10602 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10603 boardp->sdtr_data[tid_no] = asyn_sdtr;
10605 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10606 return (0);
10607 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
10609 AscMemWordCopyFromLram(iop_base,
10610 ASCV_MSGIN_BEG,
10611 (ushort *) & ext_msg,
10612 (ushort) (sizeof (EXT_MSG) >> 1));
10614 if (ext_msg.msg_type == MS_EXTEND &&
10615 ext_msg.msg_req == MS_SDTR_CODE &&
10616 ext_msg.msg_len == MS_SDTR_LEN) {
10617 sdtr_accept = TRUE;
10618 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
10620 sdtr_accept = FALSE;
10621 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
10623 if ((ext_msg.xfer_period <
10624 asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) ||
10625 (ext_msg.xfer_period >
10626 asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) {
10627 sdtr_accept = FALSE;
10628 ext_msg.xfer_period =
10629 asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index];
10631 if (sdtr_accept) {
10632 sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10633 ext_msg.req_ack_offset);
10634 if ((sdtr_data == 0xFF)) {
10636 q_cntl |= QC_MSG_OUT;
10637 asc_dvc->init_sdtr &= ~target_id;
10638 asc_dvc->sdtr_done &= ~target_id;
10639 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10640 boardp->sdtr_data[tid_no] = asyn_sdtr;
10643 if (ext_msg.req_ack_offset == 0) {
10645 q_cntl &= ~QC_MSG_OUT;
10646 asc_dvc->init_sdtr &= ~target_id;
10647 asc_dvc->sdtr_done &= ~target_id;
10648 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10649 } else {
10650 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
10652 q_cntl &= ~QC_MSG_OUT;
10653 asc_dvc->sdtr_done |= target_id;
10654 asc_dvc->init_sdtr |= target_id;
10655 asc_dvc->pci_fix_asyn_xfer &= ~target_id;
10656 sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10657 ext_msg.req_ack_offset);
10658 AscSetChipSDTR(iop_base, sdtr_data, tid_no);
10659 boardp->sdtr_data[tid_no] = sdtr_data;
10660 } else {
10662 q_cntl |= QC_MSG_OUT;
10663 AscMsgOutSDTR(asc_dvc,
10664 ext_msg.xfer_period,
10665 ext_msg.req_ack_offset);
10666 asc_dvc->pci_fix_asyn_xfer &= ~target_id;
10667 sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10668 ext_msg.req_ack_offset);
10669 AscSetChipSDTR(iop_base, sdtr_data, tid_no);
10670 boardp->sdtr_data[tid_no] = sdtr_data;
10671 asc_dvc->sdtr_done |= target_id;
10672 asc_dvc->init_sdtr |= target_id;
10676 AscWriteLramByte(iop_base,
10677 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10678 q_cntl);
10679 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10680 return (0);
10681 } else if (ext_msg.msg_type == MS_EXTEND &&
10682 ext_msg.msg_req == MS_WDTR_CODE &&
10683 ext_msg.msg_len == MS_WDTR_LEN) {
10685 ext_msg.wdtr_width = 0;
10686 AscMemWordCopyToLram(iop_base,
10687 ASCV_MSGOUT_BEG,
10688 (ushort *) & ext_msg,
10689 (ushort) (sizeof (EXT_MSG) >> 1));
10690 q_cntl |= QC_MSG_OUT;
10691 AscWriteLramByte(iop_base,
10692 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10693 q_cntl);
10694 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10695 return (0);
10696 } else {
10698 ext_msg.msg_type = M1_MSG_REJECT;
10699 AscMemWordCopyToLram(iop_base,
10700 ASCV_MSGOUT_BEG,
10701 (ushort *) & ext_msg,
10702 (ushort) (sizeof (EXT_MSG) >> 1));
10703 q_cntl |= QC_MSG_OUT;
10704 AscWriteLramByte(iop_base,
10705 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10706 q_cntl);
10707 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10708 return (0);
10710 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
10712 q_cntl |= QC_REQ_SENSE;
10714 if ((asc_dvc->init_sdtr & target_id) != 0) {
10716 asc_dvc->sdtr_done &= ~target_id;
10718 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10719 q_cntl |= QC_MSG_OUT;
10720 AscMsgOutSDTR(asc_dvc,
10721 asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
10722 (uchar) (asc_dvc->max_sdtr_index - 1)],
10723 (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
10726 AscWriteLramByte(iop_base,
10727 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10728 q_cntl);
10730 tag_code = AscReadLramByte(iop_base,
10731 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
10732 tag_code &= 0xDC;
10733 if (
10734 (asc_dvc->pci_fix_asyn_xfer & target_id)
10735 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
10738 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
10739 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
10742 AscWriteLramByte(iop_base,
10743 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
10744 tag_code);
10746 q_status = AscReadLramByte(iop_base,
10747 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
10748 q_status |= (QS_READY | QS_BUSY);
10749 AscWriteLramByte(iop_base,
10750 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10751 q_status);
10753 scsi_busy = AscReadLramByte(iop_base,
10754 (ushort) ASCV_SCSIBUSY_B);
10755 scsi_busy &= ~target_id;
10756 AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10758 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10759 return (0);
10760 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
10762 AscMemWordCopyFromLram(iop_base,
10763 ASCV_MSGOUT_BEG,
10764 (ushort *) & out_msg,
10765 (ushort) (sizeof (EXT_MSG) >> 1));
10767 if ((out_msg.msg_type == MS_EXTEND) &&
10768 (out_msg.msg_len == MS_SDTR_LEN) &&
10769 (out_msg.msg_req == MS_SDTR_CODE)) {
10771 asc_dvc->init_sdtr &= ~target_id;
10772 asc_dvc->sdtr_done &= ~target_id;
10773 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10774 boardp->sdtr_data[tid_no] = asyn_sdtr;
10776 q_cntl &= ~QC_MSG_OUT;
10777 AscWriteLramByte(iop_base,
10778 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10779 q_cntl);
10780 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10781 return (0);
10782 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
10784 scsi_status = AscReadLramByte(iop_base,
10785 (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
10786 cur_dvc_qng = AscReadLramByte(iop_base,
10787 (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
10788 if ((cur_dvc_qng > 0) &&
10789 (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
10791 scsi_busy = AscReadLramByte(iop_base,
10792 (ushort) ASCV_SCSIBUSY_B);
10793 scsi_busy |= target_id;
10794 AscWriteLramByte(iop_base,
10795 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10796 asc_dvc->queue_full_or_busy |= target_id;
10798 if (scsi_status == SS_QUEUE_FULL) {
10799 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
10800 cur_dvc_qng -= 1;
10801 asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
10803 AscWriteLramByte(iop_base,
10804 (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG +
10805 (ushort) tid_no),
10806 cur_dvc_qng);
10809 * Set the device queue depth to the number of
10810 * active requests when the QUEUE FULL condition
10811 * was encountered.
10813 boardp->queue_full |= target_id;
10814 boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
10815 #if ASC_QUEUE_FLOW_CONTROL
10816 if (boardp->device[tid_no] != NULL &&
10817 boardp->device[tid_no]->queue_curr_depth >
10818 cur_dvc_qng) {
10819 boardp->device[tid_no]->queue_curr_depth =
10820 cur_dvc_qng;
10822 #endif /* ASC_QUEUE_FLOW_CONTROL */
10826 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10827 return (0);
10829 return (0);
10832 STATIC uchar
10833 _AscCopyLramScsiDoneQ(
10834 PortAddr iop_base,
10835 ushort q_addr,
10836 REG ASC_QDONE_INFO * scsiq,
10837 ulong max_dma_count
10840 ushort _val;
10841 uchar sg_queue_cnt;
10843 DvcGetQinfo(iop_base,
10844 (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
10845 (ushort *) scsiq,
10846 (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
10847 _val = AscReadLramWord(iop_base,
10848 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
10849 scsiq->q_status = (uchar) _val;
10850 scsiq->q_no = (uchar) (_val >> 8);
10851 _val = AscReadLramWord(iop_base,
10852 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
10853 scsiq->cntl = (uchar) _val;
10854 sg_queue_cnt = (uchar) (_val >> 8);
10855 _val = AscReadLramWord(iop_base,
10856 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
10857 scsiq->sense_len = (uchar) _val;
10858 scsiq->extra_bytes = (uchar) (_val >> 8);
10859 scsiq->remain_bytes = AscReadLramWord(iop_base,
10860 (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
10861 scsiq->remain_bytes &= max_dma_count;
10862 return (sg_queue_cnt);
10865 STATIC int
10866 AscIsrQDone(
10867 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
10870 uchar next_qp;
10871 uchar n_q_used;
10872 uchar sg_list_qp;
10873 uchar sg_queue_cnt;
10874 uchar q_cnt;
10875 uchar done_q_tail;
10876 uchar tid_no;
10877 ASC_SCSI_BIT_ID_TYPE scsi_busy;
10878 ASC_SCSI_BIT_ID_TYPE target_id;
10879 PortAddr iop_base;
10880 ushort q_addr;
10881 ushort sg_q_addr;
10882 uchar cur_target_qng;
10883 ASC_QDONE_INFO scsiq_buf;
10884 REG ASC_QDONE_INFO *scsiq;
10885 int false_overrun;
10886 ASC_ISR_CALLBACK asc_isr_callback;
10888 iop_base = asc_dvc->iop_base;
10889 asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
10890 n_q_used = 1;
10891 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
10892 done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
10893 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
10894 next_qp = AscReadLramByte(iop_base,
10895 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
10896 if (next_qp != ASC_QLINK_END) {
10897 AscPutVarDoneQTail(iop_base, next_qp);
10898 q_addr = ASC_QNO_TO_QADDR(next_qp);
10899 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
10900 asc_dvc->max_dma_count);
10901 AscWriteLramByte(iop_base,
10902 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10903 (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
10904 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
10905 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
10906 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
10907 sg_q_addr = q_addr;
10908 sg_list_qp = next_qp;
10909 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
10910 sg_list_qp = AscReadLramByte(iop_base,
10911 (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
10912 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
10913 if (sg_list_qp == ASC_QLINK_END) {
10914 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
10915 scsiq->d3.done_stat = QD_WITH_ERROR;
10916 scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
10917 goto FATAL_ERR_QDONE;
10919 AscWriteLramByte(iop_base,
10920 (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10921 QS_FREE);
10923 n_q_used = sg_queue_cnt + 1;
10924 AscPutVarDoneQTail(iop_base, sg_list_qp);
10926 if (asc_dvc->queue_full_or_busy & target_id) {
10927 cur_target_qng = AscReadLramByte(iop_base,
10928 (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
10929 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
10930 scsi_busy = AscReadLramByte(iop_base,
10931 (ushort) ASCV_SCSIBUSY_B);
10932 scsi_busy &= ~target_id;
10933 AscWriteLramByte(iop_base,
10934 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10935 asc_dvc->queue_full_or_busy &= ~target_id;
10938 if (asc_dvc->cur_total_qng >= n_q_used) {
10939 asc_dvc->cur_total_qng -= n_q_used;
10940 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
10941 asc_dvc->cur_dvc_qng[tid_no]--;
10943 } else {
10944 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
10945 scsiq->d3.done_stat = QD_WITH_ERROR;
10946 goto FATAL_ERR_QDONE;
10948 if ((scsiq->d2.srb_ptr == 0UL) ||
10949 ((scsiq->q_status & QS_ABORTED) != 0)) {
10950 return (0x11);
10951 } else if (scsiq->q_status == QS_DONE) {
10952 false_overrun = FALSE;
10953 if (scsiq->extra_bytes != 0) {
10954 scsiq->remain_bytes += (ulong) scsiq->extra_bytes;
10956 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
10957 if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) {
10958 if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
10959 scsiq->d3.done_stat = QD_NO_ERROR;
10960 scsiq->d3.host_stat = QHSTA_NO_ERROR;
10961 } else if (false_overrun) {
10962 scsiq->d3.done_stat = QD_NO_ERROR;
10963 scsiq->d3.host_stat = QHSTA_NO_ERROR;
10965 } else if (scsiq->d3.host_stat ==
10966 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
10967 AscStopChip(iop_base);
10968 AscSetChipControl(iop_base,
10969 (uchar) (CC_SCSI_RESET | CC_HALT));
10970 DvcDelayNanoSecond(asc_dvc, 60000);
10971 AscSetChipControl(iop_base, CC_HALT);
10972 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
10973 AscSetChipStatus(iop_base, 0);
10974 AscSetChipControl(iop_base, 0);
10977 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
10978 (*asc_isr_callback) (asc_dvc, scsiq);
10979 } else {
10980 if ((AscReadLramByte(iop_base,
10981 (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
10982 SCSICMD_StartStopUnit)) {
10983 asc_dvc->unit_not_ready &= ~target_id;
10984 if (scsiq->d3.done_stat != QD_NO_ERROR) {
10985 asc_dvc->start_motor &= ~target_id;
10989 return (1);
10990 } else {
10991 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
10992 FATAL_ERR_QDONE:
10993 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
10994 (*asc_isr_callback) (asc_dvc, scsiq);
10996 return (0x80);
10999 return (0);
11002 STATIC int
11003 AscISR(
11004 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11007 ASC_CS_TYPE chipstat;
11008 PortAddr iop_base;
11009 ushort saved_ram_addr;
11010 uchar ctrl_reg;
11011 uchar saved_ctrl_reg;
11012 int int_pending;
11013 int status;
11014 uchar host_flag;
11016 iop_base = asc_dvc->iop_base;
11017 int_pending = FALSE;
11018 if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
11019 || (asc_dvc->isr_callback == 0)
11021 return (ERR);
11023 if (asc_dvc->in_critical_cnt != 0) {
11024 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
11025 return (ERR);
11027 if (asc_dvc->is_in_int) {
11028 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
11029 return (ERR);
11031 asc_dvc->is_in_int = TRUE;
11032 ctrl_reg = AscGetChipControl(iop_base);
11033 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
11034 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
11035 chipstat = AscGetChipStatus(iop_base);
11036 if (chipstat & CSW_SCSI_RESET_LATCH) {
11037 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
11038 int_pending = TRUE;
11039 asc_dvc->sdtr_done = 0;
11040 saved_ctrl_reg &= (uchar) (~CC_HALT);
11041 while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
11042 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
11043 AscSetChipControl(iop_base, CC_HALT);
11044 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
11045 AscSetChipStatus(iop_base, 0);
11046 chipstat = AscGetChipStatus(iop_base);
11049 saved_ram_addr = AscGetChipLramAddr(iop_base);
11050 host_flag = AscReadLramByte(iop_base,
11051 ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR);
11052 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
11053 (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
11054 if ((chipstat & CSW_INT_PENDING)
11055 || (int_pending)
11057 AscAckInterrupt(iop_base);
11058 int_pending = TRUE;
11059 if ((chipstat & CSW_HALTED) &&
11060 (ctrl_reg & CC_SINGLE_STEP)) {
11061 if (AscIsrChipHalted(asc_dvc) == ERR) {
11062 goto ISR_REPORT_QDONE_FATAL_ERROR;
11063 } else {
11064 saved_ctrl_reg &= (uchar) (~CC_HALT);
11066 } else {
11067 ISR_REPORT_QDONE_FATAL_ERROR:
11068 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
11069 while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
11071 } else {
11072 do {
11073 if ((status = AscIsrQDone(asc_dvc)) == 1) {
11074 break;
11076 } while (status == 0x11);
11078 if ((status & 0x80) != 0)
11079 int_pending = ERR;
11082 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
11083 AscSetChipLramAddr(iop_base, saved_ram_addr);
11084 AscSetChipControl(iop_base, saved_ctrl_reg);
11085 asc_dvc->is_in_int = FALSE;
11086 return (int_pending);
11089 STATIC uchar _asc_mcode_buf[] ASC_INITDATA =
11091 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11092 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11095 0x00, 0x00, 0x00, 0x00, 0x91, 0x10, 0x0A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
11096 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11097 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
11098 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00,
11099 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
11100 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80,
11101 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
11102 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
11103 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00,
11104 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1,
11105 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0xA6, 0x97, 0xCE, 0x81, 0x00, 0x33,
11106 0x02, 0x00, 0xC0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00,
11107 0x84, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x03, 0xDE,
11108 0x00, 0x33, 0x05, 0x00, 0xC0, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60,
11109 0x00, 0xA2, 0x80, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x2C, 0x01, 0x80, 0x81, 0x03, 0x03, 0x80, 0x63,
11110 0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC0, 0x88, 0x03, 0x07, 0x02, 0x01,
11111 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98,
11112 0xCD, 0x04, 0x15, 0x23, 0xF6, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03,
11113 0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xC0, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01,
11114 0x00, 0x33, 0x0B, 0x00, 0xC0, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC0, 0x88,
11115 0x50, 0x04, 0x90, 0x81, 0x06, 0xAB, 0x8A, 0x01, 0x90, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x9A, 0x01,
11116 0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
11117 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xC6, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01,
11118 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xBC, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D,
11119 0x00, 0x33, 0x1B, 0x00, 0xC0, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
11120 0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01,
11121 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE,
11122 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
11123 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0,
11124 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x67, 0xEB,
11125 0x11, 0x23, 0xF6, 0x88, 0x04, 0x98, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x32, 0x02,
11126 0x7C, 0x95, 0x06, 0xA6, 0x3C, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0xC0, 0x88, 0x04, 0x01, 0x03, 0xD8,
11127 0xB2, 0x98, 0x6A, 0x96, 0x4E, 0x82, 0xFE, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D,
11128 0x02, 0xA6, 0x78, 0x02, 0x07, 0xA6, 0x66, 0x02, 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x6E, 0x02,
11129 0x00, 0x33, 0x10, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x50, 0x82, 0x60, 0x96, 0x50, 0x82, 0x04, 0x23,
11130 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61,
11131 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01,
11132 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xB6, 0x02, 0x07, 0xA6, 0x66, 0x02,
11133 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xC0, 0x02, 0x00, 0xA6, 0xC0, 0x02,
11134 0x00, 0x33, 0x12, 0x00, 0xC0, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x98, 0x02,
11135 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
11136 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xF6, 0x82, 0x18, 0x23, 0x04, 0x61,
11137 0x18, 0xA0, 0xEE, 0x02, 0x04, 0x01, 0x9C, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xC0, 0x88, 0x08, 0x31,
11138 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x20, 0x03, 0x00, 0xA6,
11139 0x20, 0x03, 0x07, 0xA6, 0x18, 0x03, 0x06, 0xA6, 0x1C, 0x03, 0x03, 0xA6, 0x20, 0x04, 0x02, 0xA6,
11140 0x78, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xFA, 0x82, 0x60, 0x96, 0xFA, 0x82,
11141 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01,
11142 0x00, 0xA2, 0x60, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, 0x7E, 0x98, 0x00, 0xA6,
11143 0x22, 0x03, 0x07, 0xA6, 0x58, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, 0x5C, 0x03, 0x01, 0xA6,
11144 0x22, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x3E, 0x83, 0x60, 0x96, 0x3E, 0x83,
11145 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0xC0, 0x88, 0x00, 0x01, 0x05, 0x05,
11146 0xFF, 0xA2, 0x7E, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x3A, 0x83, 0x05, 0x05, 0x15, 0x01,
11147 0x00, 0xA2, 0x9E, 0x03, 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
11148 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0x9A, 0x03, 0x12, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
11149 0xA8, 0x03, 0x00, 0xA6, 0xC0, 0x03, 0x12, 0x84, 0xA6, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA8, 0x03,
11150 0x07, 0xA6, 0xB6, 0x03, 0xD8, 0x83, 0x7C, 0x95, 0xAC, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC0, 0x88,
11151 0xA6, 0x98, 0x80, 0x42, 0x00, 0xA6, 0xC0, 0x03, 0x07, 0xA6, 0xCE, 0x03, 0xD8, 0x83, 0x7C, 0x95,
11152 0xC4, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC0, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
11153 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x12, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0xF6, 0x03, 0x80, 0x6B,
11154 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x10, 0x04, 0x07, 0xA6, 0x08, 0x04, 0x06, 0xA6,
11155 0x0C, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xF6, 0x83, 0x60, 0x96, 0xF6, 0x83,
11156 0x20, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
11157 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33,
11158 0x30, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC,
11159 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
11160 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01,
11161 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00,
11162 0x00, 0x33, 0x1D, 0x00, 0xC0, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
11163 0xC0, 0x88, 0x42, 0x23, 0xF6, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3,
11164 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23,
11165 0xF6, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF6, 0x88, 0x04, 0x98,
11166 0x00, 0xA2, 0xC0, 0x04, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF0, 0x81,
11167 0x47, 0x23, 0xF6, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x81,
11168 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xF6, 0x88, 0x04, 0x23,
11169 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33,
11170 0x27, 0x00, 0xC0, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01,
11171 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
11172 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04,
11173 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85,
11174 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
11175 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01,
11176 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01,
11177 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
11178 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05,
11179 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC0, 0x88, 0x04, 0xA0,
11180 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
11181 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85,
11182 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0,
11183 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
11184 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63,
11185 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF6, 0x88, 0x07, 0x23,
11186 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
11187 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03,
11188 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC0, 0x88, 0x1D, 0x01, 0x01, 0xD6,
11189 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
11190 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61,
11191 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01,
11192 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
11193 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6,
11194 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20,
11195 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
11196 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
11197 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43,
11198 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
11199 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06,
11200 0x00, 0x33, 0x2A, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6,
11201 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC0, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
11202 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01,
11203 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33,
11204 0x2C, 0x00, 0xC0, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
11205 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC0, 0x88, 0x00, 0x00, 0x80, 0x67,
11206 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61,
11207 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
11208 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05,
11209 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01,
11210 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
11211 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00,
11212 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00,
11213 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
11214 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33,
11215 0x07, 0x00, 0xC0, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01,
11216 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
11217 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63,
11218 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02,
11219 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
11220 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04,
11221 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08,
11222 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
11223 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01,
11224 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08,
11225 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
11226 0x00, 0x33, 0x3E, 0x00, 0xC0, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B,
11227 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09,
11228 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
11229 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E,
11230 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB2, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63,
11231 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, 0x13, 0x23,
11232 0xF6, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62,
11233 0xE0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7,
11234 0x41, 0x23, 0xF6, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
11237 STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf);
11238 STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012B5442UL;
11240 #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
11241 STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
11243 SCSICMD_Inquiry,
11244 SCSICMD_RequestSense,
11245 SCSICMD_ReadCapacity,
11246 SCSICMD_ReadTOC,
11247 SCSICMD_ModeSelect6,
11248 SCSICMD_ModeSense6,
11249 SCSICMD_ModeSelect10,
11250 SCSICMD_ModeSense10,
11251 0xFF,
11252 0xFF,
11253 0xFF,
11254 0xFF,
11255 0xFF,
11256 0xFF,
11257 0xFF,
11258 0xFF
11261 STATIC int
11262 AscExeScsiQueue(
11263 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11264 REG ASC_SCSI_Q * scsiq
11267 PortAddr iop_base;
11268 int last_int_level;
11269 int sta;
11270 int n_q_required;
11271 int disable_syn_offset_one_fix;
11272 int i;
11273 ulong addr;
11274 ASC_EXE_CALLBACK asc_exe_callback;
11275 ushort sg_entry_cnt = 0;
11276 ushort sg_entry_cnt_minus_one = 0;
11277 uchar target_ix;
11278 uchar tid_no;
11279 uchar sdtr_data;
11280 uchar extra_bytes;
11281 uchar scsi_cmd;
11282 uchar disable_cmd;
11283 ASC_SG_HEAD *sg_head;
11284 ulong data_cnt;
11286 iop_base = asc_dvc->iop_base;
11287 sg_head = scsiq->sg_head;
11288 asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
11289 if (asc_dvc->err_code != 0)
11290 return (ERR);
11291 if (scsiq == (ASC_SCSI_Q *) 0L) {
11292 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
11293 return (ERR);
11295 scsiq->q1.q_no = 0;
11296 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
11297 scsiq->q1.extra_bytes = 0;
11299 sta = 0;
11300 target_ix = scsiq->q2.target_ix;
11301 tid_no = ASC_TIX_TO_TID(target_ix);
11302 n_q_required = 1;
11303 if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
11304 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
11305 asc_dvc->sdtr_done &= ~scsiq->q1.target_id ;
11306 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11307 AscMsgOutSDTR(asc_dvc,
11308 asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
11309 (uchar) (asc_dvc->max_sdtr_index - 1)],
11310 (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
11311 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
11314 last_int_level = DvcEnterCritical();
11315 if (asc_dvc->in_critical_cnt != 0) {
11316 DvcLeaveCritical(last_int_level);
11317 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
11318 return (ERR);
11320 asc_dvc->in_critical_cnt++;
11321 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
11322 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
11323 asc_dvc->in_critical_cnt--;
11324 DvcLeaveCritical(last_int_level);
11325 return (ERR);
11327 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
11328 return (ERR);
11330 if (sg_entry_cnt == 1) {
11331 scsiq->q1.data_addr = sg_head->sg_list[0].addr;
11332 scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
11333 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
11335 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
11337 scsi_cmd = scsiq->cdbptr[0];
11338 disable_syn_offset_one_fix = FALSE;
11339 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
11340 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
11341 if (scsiq->q1.cntl & QC_SG_HEAD) {
11342 data_cnt = 0;
11343 for (i = 0; i < sg_entry_cnt; i++) {
11344 data_cnt += sg_head->sg_list[i].bytes;
11346 } else {
11347 data_cnt = scsiq->q1.data_cnt;
11349 if (data_cnt != 0UL) {
11350 if (data_cnt < 512UL) {
11351 disable_syn_offset_one_fix = TRUE;
11352 } else {
11353 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) {
11354 disable_cmd = _syn_offset_one_disable_cmd[i];
11355 if (disable_cmd == 0xFF) {
11356 break;
11358 if (scsi_cmd == disable_cmd) {
11359 disable_syn_offset_one_fix = TRUE;
11360 break;
11366 if (disable_syn_offset_one_fix) {
11367 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
11368 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
11369 ASC_TAG_FLAG_DISABLE_DISCONNECT);
11370 } else {
11371 scsiq->q2.tag_code &= 0x23;
11373 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
11374 if (asc_dvc->bug_fix_cntl) {
11375 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11376 if ((scsi_cmd == SCSICMD_Read6) ||
11377 (scsi_cmd == SCSICMD_Read10)) {
11378 addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr +
11379 sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
11380 extra_bytes = (uchar) ((ushort) addr & 0x0003);
11381 if ((extra_bytes != 0) &&
11382 ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
11383 == 0)) {
11384 scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
11385 scsiq->q1.extra_bytes = extra_bytes;
11386 sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
11387 (ulong) extra_bytes;
11392 sg_head->entry_to_copy = sg_head->entry_cnt;
11393 n_q_required = AscSgListToQueue(sg_entry_cnt);
11394 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
11395 (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11396 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11397 n_q_required)) == 1) {
11398 asc_dvc->in_critical_cnt--;
11399 if (asc_exe_callback != 0) {
11400 (*asc_exe_callback) (asc_dvc, scsiq);
11402 DvcLeaveCritical(last_int_level);
11403 return (sta);
11406 } else {
11407 if (asc_dvc->bug_fix_cntl) {
11408 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11409 if ((scsi_cmd == SCSICMD_Read6) ||
11410 (scsi_cmd == SCSICMD_Read10)) {
11411 addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
11412 extra_bytes = (uchar) ((ushort) addr & 0x0003);
11413 if ((extra_bytes != 0) &&
11414 ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
11415 == 0)) {
11416 if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
11417 scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
11418 scsiq->q1.data_cnt -= (ulong) extra_bytes;
11419 scsiq->q1.extra_bytes = extra_bytes;
11425 n_q_required = 1;
11426 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
11427 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11428 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11429 n_q_required)) == 1) {
11430 asc_dvc->in_critical_cnt--;
11431 if (asc_exe_callback != 0) {
11432 (*asc_exe_callback) (asc_dvc, scsiq);
11434 DvcLeaveCritical(last_int_level);
11435 return (sta);
11439 asc_dvc->in_critical_cnt--;
11440 DvcLeaveCritical(last_int_level);
11441 return (sta);
11444 STATIC int
11445 AscSendScsiQueue(
11446 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11447 REG ASC_SCSI_Q * scsiq,
11448 uchar n_q_required
11451 PortAddr iop_base;
11452 uchar free_q_head;
11453 uchar next_qp;
11454 uchar tid_no;
11455 uchar target_ix;
11456 int sta;
11458 iop_base = asc_dvc->iop_base;
11459 target_ix = scsiq->q2.target_ix;
11460 tid_no = ASC_TIX_TO_TID(target_ix);
11461 sta = 0;
11462 free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
11463 if (n_q_required > 1) {
11464 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
11465 free_q_head, (uchar) (n_q_required)))
11466 != (uchar) ASC_QLINK_END) {
11467 asc_dvc->last_q_shortage = 0;
11468 scsiq->sg_head->queue_cnt = n_q_required - 1;
11469 scsiq->q1.q_no = free_q_head;
11470 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
11471 free_q_head)) == 1) {
11472 AscPutVarFreeQHead(iop_base, next_qp);
11473 asc_dvc->cur_total_qng += (uchar) (n_q_required);
11474 asc_dvc->cur_dvc_qng[tid_no]++;
11476 return (sta);
11478 } else if (n_q_required == 1) {
11479 if ((next_qp = AscAllocFreeQueue(iop_base,
11480 free_q_head)) != ASC_QLINK_END) {
11481 scsiq->q1.q_no = free_q_head;
11482 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
11483 free_q_head)) == 1) {
11484 AscPutVarFreeQHead(iop_base, next_qp);
11485 asc_dvc->cur_total_qng++;
11486 asc_dvc->cur_dvc_qng[tid_no]++;
11488 return (sta);
11491 return (sta);
11494 STATIC int
11495 AscSgListToQueue(
11496 int sg_list
11499 int n_sg_list_qs;
11501 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
11502 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
11503 n_sg_list_qs++;
11504 return (n_sg_list_qs + 1);
11508 STATIC uint
11509 AscGetNumOfFreeQueue(
11510 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11511 uchar target_ix,
11512 uchar n_qs
11515 uint cur_used_qs;
11516 uint cur_free_qs;
11517 ASC_SCSI_BIT_ID_TYPE target_id;
11518 uchar tid_no;
11520 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
11521 tid_no = ASC_TIX_TO_TID(target_ix);
11522 if ((asc_dvc->unit_not_ready & target_id) ||
11523 (asc_dvc->queue_full_or_busy & target_id)) {
11524 return (0);
11526 if (n_qs == 1) {
11527 cur_used_qs = (uint) asc_dvc->cur_total_qng +
11528 (uint) asc_dvc->last_q_shortage +
11529 (uint) ASC_MIN_FREE_Q;
11530 } else {
11531 cur_used_qs = (uint) asc_dvc->cur_total_qng +
11532 (uint) ASC_MIN_FREE_Q;
11534 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
11535 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
11536 if (asc_dvc->cur_dvc_qng[tid_no] >=
11537 asc_dvc->max_dvc_qng[tid_no]) {
11538 return (0);
11540 return (cur_free_qs);
11542 if (n_qs > 1) {
11543 if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
11544 asc_dvc->last_q_shortage = n_qs;
11547 return (0);
11550 STATIC int
11551 AscPutReadyQueue(
11552 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11553 REG ASC_SCSI_Q * scsiq,
11554 uchar q_no
11557 ushort q_addr;
11558 uchar tid_no;
11559 uchar sdtr_data;
11560 uchar syn_period_ix;
11561 uchar syn_offset;
11562 PortAddr iop_base;
11564 iop_base = asc_dvc->iop_base;
11565 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
11566 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
11567 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
11568 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11569 syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
11570 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
11571 AscMsgOutSDTR(asc_dvc,
11572 asc_dvc->sdtr_period_tbl[syn_period_ix],
11573 syn_offset);
11574 scsiq->q1.cntl |= QC_MSG_OUT;
11576 q_addr = ASC_QNO_TO_QADDR(q_no);
11577 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
11578 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
11580 scsiq->q1.status = QS_FREE;
11581 AscMemWordCopyToLram(iop_base,
11582 (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
11583 (ushort *) scsiq->cdbptr,
11584 (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
11585 DvcPutScsiQ(iop_base,
11586 (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
11587 (ushort *) & scsiq->q1.cntl,
11588 (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
11589 AscWriteLramWord(iop_base,
11590 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
11591 (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
11592 return (1);
11595 STATIC int
11596 AscPutReadySgListQueue(
11597 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11598 REG ASC_SCSI_Q * scsiq,
11599 uchar q_no
11602 int sta;
11603 int i;
11604 ASC_SG_HEAD *sg_head;
11605 ASC_SG_LIST_Q scsi_sg_q;
11606 ulong saved_data_addr;
11607 ulong saved_data_cnt;
11608 PortAddr iop_base;
11609 ushort sg_list_dwords;
11610 ushort sg_index;
11611 ushort sg_entry_cnt;
11612 ushort q_addr;
11613 uchar next_qp;
11615 iop_base = asc_dvc->iop_base;
11616 sg_head = scsiq->sg_head;
11617 saved_data_addr = scsiq->q1.data_addr;
11618 saved_data_cnt = scsiq->q1.data_cnt;
11619 scsiq->q1.data_addr = sg_head->sg_list[0].addr;
11620 scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
11621 sg_entry_cnt = sg_head->entry_cnt - 1;
11622 if (sg_entry_cnt != 0) {
11623 scsiq->q1.cntl |= QC_SG_HEAD;
11624 q_addr = ASC_QNO_TO_QADDR(q_no);
11625 sg_index = 1;
11626 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
11627 scsi_sg_q.sg_head_qp = q_no;
11628 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
11629 for (i = 0; i < sg_head->queue_cnt; i++) {
11630 scsi_sg_q.seq_no = i + 1;
11631 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
11632 sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
11633 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
11634 if (i == 0) {
11635 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
11636 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
11637 } else {
11638 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
11639 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
11641 } else {
11642 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
11643 sg_list_dwords = sg_entry_cnt << 1;
11644 if (i == 0) {
11645 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
11646 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
11647 } else {
11648 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
11649 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
11651 sg_entry_cnt = 0;
11653 next_qp = AscReadLramByte(iop_base,
11654 (ushort) (q_addr + ASC_SCSIQ_B_FWD));
11655 scsi_sg_q.q_no = next_qp;
11656 q_addr = ASC_QNO_TO_QADDR(next_qp);
11657 AscMemWordCopyToLram(iop_base,
11658 (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
11659 (ushort *) & scsi_sg_q,
11660 (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
11661 AscMemDWordCopyToLram(iop_base,
11662 (ushort) (q_addr + ASC_SGQ_LIST_BEG),
11663 (ulong *) & sg_head->sg_list[sg_index],
11664 (ushort) sg_list_dwords);
11665 sg_index += ASC_SG_LIST_PER_Q;
11667 } else {
11668 scsiq->q1.cntl &= ~QC_SG_HEAD;
11670 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
11671 scsiq->q1.data_addr = saved_data_addr;
11672 scsiq->q1.data_cnt = saved_data_cnt;
11673 return (sta);
11676 STATIC int
11677 AscAbortSRB(
11678 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11679 ulong srb_ptr
11682 int sta;
11683 ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
11684 PortAddr iop_base;
11686 iop_base = asc_dvc->iop_base;
11687 sta = ERR;
11688 saved_unit_not_ready = asc_dvc->unit_not_ready;
11689 asc_dvc->unit_not_ready = 0xFF;
11690 AscWaitISRDone(asc_dvc);
11691 if (AscStopQueueExe(iop_base) == 1) {
11692 if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
11693 sta = 1;
11694 AscCleanUpBusyQueue(iop_base);
11695 AscStartQueueExe(iop_base);
11696 } else {
11697 sta = 0;
11698 AscStartQueueExe(iop_base);
11701 asc_dvc->unit_not_ready = saved_unit_not_ready;
11702 return (sta);
11705 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
11706 STATIC int
11707 AscResetDevice(
11708 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11709 uchar target_ix
11712 PortAddr iop_base;
11713 int sta;
11714 uchar tid_no;
11716 ASC_SCSI_BIT_ID_TYPE target_id;
11717 int i;
11718 ASC_SCSI_REQ_Q scsiq_buf;
11719 ASC_SCSI_REQ_Q *scsiq;
11720 uchar *buf;
11721 ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
11722 iop_base = asc_dvc->iop_base;
11723 tid_no = ASC_TIX_TO_TID(target_ix);
11724 target_id = ASC_TID_TO_TARGET_ID(tid_no);
11725 saved_unit_not_ready = asc_dvc->unit_not_ready;
11726 asc_dvc->unit_not_ready = target_id;
11727 sta = ERR;
11728 AscWaitTixISRDone(asc_dvc, target_ix);
11729 if (AscStopQueueExe(iop_base) == 1) {
11730 if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
11731 AscCleanUpBusyQueue(iop_base);
11732 AscStartQueueExe(iop_base);
11733 AscWaitTixISRDone(asc_dvc, target_ix);
11734 sta = TRUE;
11735 scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
11736 buf = (uchar *) & scsiq_buf;
11737 for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
11738 *buf++ = 0x00;
11740 scsiq->r1.status = (uchar) QS_READY;
11741 scsiq->r2.cdb_len = 6;
11742 scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
11743 scsiq->r1.target_id = target_id;
11744 scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
11745 scsiq->cdbptr = (uchar *) scsiq->cdb;
11746 scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
11747 AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
11748 M1_BUS_DVC_RESET);
11749 asc_dvc->unit_not_ready &= ~target_id;
11750 asc_dvc->sdtr_done |= target_id;
11751 if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq)
11752 == 1) {
11753 asc_dvc->unit_not_ready = target_id;
11754 DvcSleepMilliSecond(1000);
11755 _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq);
11756 if (AscStopQueueExe(iop_base) == 1) {
11757 AscCleanUpDiscQueue(iop_base);
11758 AscStartQueueExe(iop_base);
11759 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
11760 AscSetRunChipSynRegAtID(iop_base, tid_no,
11761 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11763 AscWaitTixISRDone(asc_dvc, target_ix);
11765 } else {
11766 sta = 0;
11768 asc_dvc->sdtr_done &= ~target_id;
11769 } else {
11770 sta = ERR;
11771 AscStartQueueExe(iop_base);
11774 asc_dvc->unit_not_ready = saved_unit_not_ready;
11775 return (sta);
11777 #endif /* version >= v1.3.89 */
11779 STATIC int
11780 AscResetSB(
11781 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11784 int sta;
11785 int i;
11786 PortAddr iop_base;
11788 iop_base = asc_dvc->iop_base;
11789 asc_dvc->unit_not_ready = 0xFF;
11790 sta = TRUE;
11791 AscWaitISRDone(asc_dvc);
11792 AscStopQueueExe(iop_base);
11793 asc_dvc->sdtr_done = 0;
11794 AscResetChipAndScsiBus(asc_dvc);
11795 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
11796 AscReInitLram(asc_dvc);
11797 for (i = 0; i <= ASC_MAX_TID; i++) {
11798 asc_dvc->cur_dvc_qng[i] = 0;
11799 if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) {
11800 AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11803 asc_dvc->err_code = 0;
11804 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11805 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11806 sta = ERR;
11808 if (AscStartChip(iop_base) == 0) {
11809 sta = ERR;
11811 AscStartQueueExe(iop_base);
11812 asc_dvc->unit_not_ready = 0;
11813 asc_dvc->queue_full_or_busy = 0;
11814 return (sta);
11817 STATIC int
11818 AscSetRunChipSynRegAtID(
11819 PortAddr iop_base,
11820 uchar tid_no,
11821 uchar sdtr_data
11824 int sta = FALSE;
11826 if (AscHostReqRiscHalt(iop_base)) {
11827 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
11828 AscStartChip(iop_base);
11829 return (sta);
11831 return (sta);
11834 STATIC int
11835 AscSetChipSynRegAtID(
11836 PortAddr iop_base,
11837 uchar id,
11838 uchar sdtr_data
11841 ASC_SCSI_BIT_ID_TYPE org_id;
11842 int i;
11843 int sta = TRUE;
11845 AscSetBank(iop_base, 1);
11846 org_id = AscReadChipDvcID(iop_base);
11847 for (i = 0; i <= ASC_MAX_TID; i++) {
11848 if (org_id == (0x01 << i))
11849 break;
11851 org_id = i;
11852 AscWriteChipDvcID(iop_base, id);
11853 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
11854 AscSetBank(iop_base, 0);
11855 AscSetChipSyn(iop_base, sdtr_data);
11856 if (AscGetChipSyn(iop_base) != sdtr_data) {
11857 sta = FALSE;
11859 } else {
11860 sta = FALSE;
11862 AscSetBank(iop_base, 1);
11863 AscWriteChipDvcID(iop_base, org_id);
11864 AscSetBank(iop_base, 0);
11865 return (sta);
11868 STATIC int
11869 AscReInitLram(
11870 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11873 AscInitLram(asc_dvc);
11874 AscInitQLinkVar(asc_dvc);
11875 return (0);
11878 STATIC ushort
11879 AscInitLram(
11880 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11883 uchar i;
11884 ushort s_addr;
11885 PortAddr iop_base;
11886 ushort warn_code;
11888 iop_base = asc_dvc->iop_base;
11889 warn_code = 0;
11890 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
11891 (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
11893 i = ASC_MIN_ACTIVE_QNO;
11894 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
11895 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11896 (uchar) (i + 1));
11897 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11898 (uchar) (asc_dvc->max_total_qng));
11899 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11900 (uchar) i);
11901 i++;
11902 s_addr += ASC_QBLK_SIZE;
11903 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
11904 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11905 (uchar) (i + 1));
11906 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11907 (uchar) (i - 1));
11908 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11909 (uchar) i);
11911 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11912 (uchar) ASC_QLINK_END);
11913 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11914 (uchar) (asc_dvc->max_total_qng - 1));
11915 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11916 (uchar) asc_dvc->max_total_qng);
11917 i++;
11918 s_addr += ASC_QBLK_SIZE;
11919 for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
11920 i++, s_addr += ASC_QBLK_SIZE) {
11921 AscWriteLramByte(iop_base,
11922 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
11923 AscWriteLramByte(iop_base,
11924 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
11925 AscWriteLramByte(iop_base,
11926 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
11928 return (warn_code);
11931 STATIC ushort
11932 AscInitQLinkVar(
11933 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11936 PortAddr iop_base;
11937 int i;
11938 ushort lram_addr;
11940 iop_base = asc_dvc->iop_base;
11941 AscPutRiscVarFreeQHead(iop_base, 1);
11942 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
11943 AscPutVarFreeQHead(iop_base, 1);
11944 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
11945 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
11946 (uchar) ((int) asc_dvc->max_total_qng + 1));
11947 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
11948 (uchar) ((int) asc_dvc->max_total_qng + 2));
11949 AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
11950 asc_dvc->max_total_qng);
11951 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
11952 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11953 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
11954 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
11955 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
11956 AscPutQDoneInProgress(iop_base, 0);
11957 lram_addr = ASC_QADR_BEG;
11958 for (i = 0; i < 32; i++, lram_addr += 2) {
11959 AscWriteLramWord(iop_base, lram_addr, 0);
11961 return (0);
11964 STATIC int
11965 AscSetLibErrorCode(
11966 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11967 ushort err_code
11970 if (asc_dvc->err_code == 0) {
11971 asc_dvc->err_code = err_code;
11972 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
11973 err_code);
11975 return (err_code);
11979 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
11980 STATIC int
11981 _AscWaitQDone(
11982 PortAddr iop_base,
11983 REG ASC_SCSI_Q * scsiq
11986 ushort q_addr;
11987 uchar q_status;
11988 int count = 0;
11990 while (scsiq->q1.q_no == 0) ;
11991 q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
11992 do {
11993 q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
11994 DvcSleepMilliSecond(100L);
11995 if (count++ > 30) {
11996 return (0);
11998 } while ((q_status & QS_READY) != 0);
11999 return (1);
12001 #endif /* version >= v1.3.89 */
12003 STATIC uchar
12004 AscMsgOutSDTR(
12005 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12006 uchar sdtr_period,
12007 uchar sdtr_offset
12010 EXT_MSG sdtr_buf;
12011 uchar sdtr_period_index;
12012 PortAddr iop_base;
12014 iop_base = asc_dvc->iop_base;
12015 sdtr_buf.msg_type = MS_EXTEND;
12016 sdtr_buf.msg_len = MS_SDTR_LEN;
12017 sdtr_buf.msg_req = MS_SDTR_CODE;
12018 sdtr_buf.xfer_period = sdtr_period;
12019 sdtr_offset &= ASC_SYN_MAX_OFFSET;
12020 sdtr_buf.req_ack_offset = sdtr_offset;
12021 if ((sdtr_period_index =
12022 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
12023 asc_dvc->max_sdtr_index) {
12024 AscMemWordCopyToLram(iop_base,
12025 ASCV_MSGOUT_BEG,
12026 (ushort *) & sdtr_buf,
12027 (ushort) (sizeof (EXT_MSG) >> 1));
12028 return ((sdtr_period_index << 4) | sdtr_offset);
12029 } else {
12031 sdtr_buf.req_ack_offset = 0;
12032 AscMemWordCopyToLram(iop_base,
12033 ASCV_MSGOUT_BEG,
12034 (ushort *) & sdtr_buf,
12035 (ushort) (sizeof (EXT_MSG) >> 1));
12036 return (0);
12040 STATIC uchar
12041 AscCalSDTRData(
12042 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12043 uchar sdtr_period,
12044 uchar syn_offset
12047 uchar byte;
12048 uchar sdtr_period_ix;
12050 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
12051 if (
12052 (sdtr_period_ix > asc_dvc->max_sdtr_index)
12054 return (0xFF);
12056 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
12057 return (byte);
12060 STATIC void
12061 AscSetChipSDTR(
12062 PortAddr iop_base,
12063 uchar sdtr_data,
12064 uchar tid_no
12067 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
12068 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
12069 return;
12072 STATIC uchar
12073 AscGetSynPeriodIndex(
12074 ASC_DVC_VAR asc_ptr_type * asc_dvc,
12075 ruchar syn_time
12078 ruchar *period_table;
12079 int max_index;
12080 int min_index;
12081 int i;
12083 period_table = asc_dvc->sdtr_period_tbl;
12084 max_index = (int) asc_dvc->max_sdtr_index;
12085 min_index = (int)asc_dvc->host_init_sdtr_index ;
12086 if ((syn_time <= period_table[max_index])) {
12087 for (i = min_index; i < (max_index - 1); i++) {
12088 if (syn_time <= period_table[i]) {
12089 return ((uchar) i);
12092 return ((uchar) max_index);
12093 } else {
12094 return ((uchar) (max_index + 1));
12098 STATIC uchar
12099 AscAllocFreeQueue(
12100 PortAddr iop_base,
12101 uchar free_q_head
12104 ushort q_addr;
12105 uchar next_qp;
12106 uchar q_status;
12108 q_addr = ASC_QNO_TO_QADDR(free_q_head);
12109 q_status = (uchar) AscReadLramByte(iop_base,
12110 (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
12111 next_qp = AscReadLramByte(iop_base,
12112 (ushort) (q_addr + ASC_SCSIQ_B_FWD));
12113 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
12114 return (next_qp);
12116 return (ASC_QLINK_END);
12119 STATIC uchar
12120 AscAllocMultipleFreeQueue(
12121 PortAddr iop_base,
12122 uchar free_q_head,
12123 uchar n_free_q
12126 uchar i;
12128 for (i = 0; i < n_free_q; i++) {
12129 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
12130 == ASC_QLINK_END) {
12131 return (ASC_QLINK_END);
12134 return (free_q_head);
12137 STATIC int
12138 AscRiscHaltedAbortSRB(
12139 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12140 ulong srb_ptr
12143 PortAddr iop_base;
12144 ushort q_addr;
12145 uchar q_no;
12146 ASC_QDONE_INFO scsiq_buf;
12147 ASC_QDONE_INFO *scsiq;
12148 ASC_ISR_CALLBACK asc_isr_callback;
12149 int last_int_level;
12151 iop_base = asc_dvc->iop_base;
12152 asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
12153 last_int_level = DvcEnterCritical();
12154 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
12155 for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
12156 q_no++) {
12157 q_addr = ASC_QNO_TO_QADDR(q_no);
12158 scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
12159 (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
12160 if (scsiq->d2.srb_ptr == srb_ptr) {
12161 _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
12162 if (((scsiq->q_status & QS_READY) != 0)
12163 && ((scsiq->q_status & QS_ABORTED) == 0)
12164 && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
12165 scsiq->q_status |= QS_ABORTED;
12166 scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
12167 AscWriteLramDWord(iop_base,
12168 (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
12169 0L);
12170 AscWriteLramByte(iop_base,
12171 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12172 scsiq->q_status);
12173 (*asc_isr_callback) (asc_dvc, scsiq);
12174 return (1);
12178 DvcLeaveCritical(last_int_level);
12179 return (0);
12182 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12183 STATIC int
12184 AscRiscHaltedAbortTIX(
12185 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12186 uchar target_ix
12189 PortAddr iop_base;
12190 ushort q_addr;
12191 uchar q_no;
12192 ASC_QDONE_INFO scsiq_buf;
12193 ASC_QDONE_INFO *scsiq;
12194 ASC_ISR_CALLBACK asc_isr_callback;
12195 int last_int_level;
12197 iop_base = asc_dvc->iop_base;
12198 asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
12199 last_int_level = DvcEnterCritical();
12200 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
12201 for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
12202 q_no++) {
12203 q_addr = ASC_QNO_TO_QADDR(q_no);
12204 _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
12205 if (((scsiq->q_status & QS_READY) != 0) &&
12206 ((scsiq->q_status & QS_ABORTED) == 0) &&
12207 ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
12208 if (scsiq->d2.target_ix == target_ix) {
12209 scsiq->q_status |= QS_ABORTED;
12210 scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
12211 AscWriteLramDWord(iop_base,
12212 (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
12213 0L);
12214 AscWriteLramByte(iop_base,
12215 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12216 scsiq->q_status);
12217 (*asc_isr_callback) (asc_dvc, scsiq);
12221 DvcLeaveCritical(last_int_level);
12222 return (1);
12224 #endif /* version >= v1.3.89 */
12226 STATIC int
12227 AscHostReqRiscHalt(
12228 PortAddr iop_base
12231 int count = 0;
12232 int sta = 0;
12233 uchar saved_stop_code;
12235 if (AscIsChipHalted(iop_base))
12236 return (1);
12237 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12238 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12239 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
12241 do {
12242 if (AscIsChipHalted(iop_base)) {
12243 sta = 1;
12244 break;
12246 DvcSleepMilliSecond(100);
12247 } while (count++ < 20);
12248 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
12249 return (sta);
12252 STATIC int
12253 AscStopQueueExe(
12254 PortAddr iop_base
12257 int count = 0;
12259 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
12260 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12261 ASC_STOP_REQ_RISC_STOP);
12262 do {
12263 if (
12264 AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
12265 ASC_STOP_ACK_RISC_STOP) {
12266 return (1);
12268 DvcSleepMilliSecond(100);
12269 } while (count++ < 20);
12271 return (0);
12274 STATIC int
12275 AscStartQueueExe(
12276 PortAddr iop_base
12279 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12280 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
12282 return (1);
12285 STATIC int
12286 AscCleanUpBusyQueue(
12287 PortAddr iop_base
12290 int count;
12291 uchar stop_code;
12293 count = 0;
12294 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12295 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12296 ASC_STOP_CLEAN_UP_BUSY_Q);
12297 do {
12298 stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12299 if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
12300 break;
12301 DvcSleepMilliSecond(100);
12302 } while (count++ < 20);
12304 return (1);
12307 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12308 STATIC int
12309 AscCleanUpDiscQueue(
12310 PortAddr iop_base
12313 int count;
12314 uchar stop_code;
12316 count = 0;
12317 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12318 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12319 ASC_STOP_CLEAN_UP_DISC_Q);
12320 do {
12321 stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12322 if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
12323 break;
12324 DvcSleepMilliSecond(100);
12325 } while (count++ < 20);
12327 return (1);
12329 #endif /* version >= v1.3.89 */
12331 STATIC int
12332 AscWaitTixISRDone(
12333 ASC_DVC_VAR asc_ptr_type * asc_dvc,
12334 uchar target_ix
12337 uchar cur_req;
12338 uchar tid_no;
12339 int i = 0;
12341 tid_no = ASC_TIX_TO_TID(target_ix);
12342 while (i++ < 10) {
12343 if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
12344 break;
12346 DvcSleepMilliSecond(1000L);
12347 if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
12348 break;
12351 return (1);
12354 STATIC int
12355 AscWaitISRDone(
12356 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12359 int tid;
12361 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12362 AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
12364 return (1);
12367 STATIC ulong
12368 AscGetOnePhyAddr(
12369 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12370 uchar * buf_addr,
12371 ulong buf_size
12374 ASC_MIN_SG_HEAD sg_head;
12376 sg_head.entry_cnt = ASC_MIN_SG_LIST;
12377 if (DvcGetSGList(asc_dvc, (uchar *) buf_addr,
12378 buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) {
12379 return (0L);
12381 if (sg_head.entry_cnt > 1) {
12382 return (0L);
12384 return (sg_head.sg_list[0].addr);
12387 STATIC void
12388 DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
12390 udelay(micro_sec);
12393 STATIC void
12394 DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type * asc_dvc, ulong nano_sec)
12396 udelay((nano_sec + 999)/1000);
12399 ASC_INITFUNC(
12400 STATIC ulong
12401 AscGetEisaProductID(
12402 PortAddr iop_base
12406 PortAddr eisa_iop;
12407 ushort product_id_high, product_id_low;
12408 ulong product_id;
12410 eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
12411 product_id_low = inpw(eisa_iop);
12412 product_id_high = inpw(eisa_iop + 2);
12413 product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
12414 return (product_id);
12417 ASC_INITFUNC(
12418 STATIC PortAddr
12419 AscSearchIOPortAddrEISA(
12420 PortAddr iop_base
12424 ulong eisa_product_id;
12426 if (iop_base == 0) {
12427 iop_base = ASC_EISA_MIN_IOP_ADDR;
12428 } else {
12429 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
12430 return (0);
12431 if ((iop_base & 0x0050) == 0x0050) {
12432 iop_base += ASC_EISA_BIG_IOP_GAP;
12433 } else {
12434 iop_base += ASC_EISA_SMALL_IOP_GAP;
12437 while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
12438 eisa_product_id = AscGetEisaProductID(iop_base);
12439 if ((eisa_product_id == ASC_EISA_ID_740) ||
12440 (eisa_product_id == ASC_EISA_ID_750)) {
12441 if (AscFindSignature(iop_base)) {
12442 inpw(iop_base + 4);
12443 return (iop_base);
12446 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
12447 return (0);
12448 if ((iop_base & 0x0050) == 0x0050) {
12449 iop_base += ASC_EISA_BIG_IOP_GAP;
12450 } else {
12451 iop_base += ASC_EISA_SMALL_IOP_GAP;
12454 return (0);
12457 STATIC int
12458 AscStartChip(
12459 PortAddr iop_base
12462 AscSetChipControl(iop_base, 0);
12463 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
12464 return (0);
12466 return (1);
12469 STATIC int
12470 AscStopChip(
12471 PortAddr iop_base
12474 uchar cc_val;
12476 cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
12477 AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
12478 AscSetChipIH(iop_base, INS_HALT);
12479 AscSetChipIH(iop_base, INS_RFLAG_WTM);
12480 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
12481 return (0);
12483 return (1);
12486 STATIC int
12487 AscIsChipHalted(
12488 PortAddr iop_base
12491 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
12492 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
12493 return (1);
12496 return (0);
12499 STATIC void
12500 AscSetChipIH(
12501 PortAddr iop_base,
12502 ushort ins_code
12505 AscSetBank(iop_base, 1);
12506 AscWriteChipIH(iop_base, ins_code);
12507 AscSetBank(iop_base, 0);
12508 return;
12511 STATIC void
12512 AscAckInterrupt(
12513 PortAddr iop_base
12516 uchar host_flag;
12517 uchar risc_flag;
12518 ushort loop;
12520 loop = 0;
12521 do {
12522 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
12523 if (loop++ > 0x7FFF) {
12524 break;
12526 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
12527 host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
12528 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
12529 (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
12530 AscSetChipStatus(iop_base, CIW_INT_ACK);
12531 loop = 0;
12532 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
12533 AscSetChipStatus(iop_base, CIW_INT_ACK);
12534 if (loop++ > 3) {
12535 break;
12538 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
12539 return;
12542 STATIC void
12543 AscDisableInterrupt(
12544 PortAddr iop_base
12547 ushort cfg;
12549 cfg = AscGetChipCfgLsw(iop_base);
12550 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
12551 return;
12554 STATIC void
12555 AscEnableInterrupt(
12556 PortAddr iop_base
12559 ushort cfg;
12561 cfg = AscGetChipCfgLsw(iop_base);
12562 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
12563 return;
12568 STATIC void
12569 AscSetBank(
12570 PortAddr iop_base,
12571 uchar bank
12574 uchar val;
12576 val = AscGetChipControl(iop_base) &
12577 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
12578 if (bank == 1) {
12579 val |= CC_BANK_ONE;
12580 } else if (bank == 2) {
12581 val |= CC_DIAG | CC_BANK_ONE;
12582 } else {
12583 val &= ~CC_BANK_ONE;
12585 AscSetChipControl(iop_base, val);
12586 return;
12589 STATIC int
12590 AscResetChipAndScsiBus(
12591 ASC_DVC_VAR *asc_dvc
12594 PortAddr iop_base;
12596 iop_base = asc_dvc->iop_base;
12597 while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
12598 AscStopChip(iop_base);
12599 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
12600 DvcDelayNanoSecond(asc_dvc, 60000);
12601 AscSetChipIH(iop_base, INS_RFLAG_WTM);
12602 AscSetChipIH(iop_base, INS_HALT);
12603 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
12604 AscSetChipControl(iop_base, CC_HALT);
12605 DvcSleepMilliSecond(200);
12606 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
12607 AscSetChipStatus(iop_base, 0);
12608 return (AscIsChipHalted(iop_base));
12611 ASC_INITFUNC(
12612 STATIC ulong
12613 AscGetMaxDmaCount(
12614 ushort bus_type
12618 if (bus_type & ASC_IS_ISA)
12619 return (ASC_MAX_ISA_DMA_COUNT);
12620 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
12621 return (ASC_MAX_VL_DMA_COUNT);
12622 return (ASC_MAX_PCI_DMA_COUNT);
12625 ASC_INITFUNC(
12626 STATIC ushort
12627 AscGetIsaDmaChannel(
12628 PortAddr iop_base
12632 ushort channel;
12634 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
12635 if (channel == 0x03)
12636 return (0);
12637 else if (channel == 0x00)
12638 return (7);
12639 return (channel + 4);
12642 ASC_INITFUNC(
12643 STATIC ushort
12644 AscSetIsaDmaChannel(
12645 PortAddr iop_base,
12646 ushort dma_channel
12650 ushort cfg_lsw;
12651 uchar value;
12653 if ((dma_channel >= 5) && (dma_channel <= 7)) {
12654 if (dma_channel == 7)
12655 value = 0x00;
12656 else
12657 value = dma_channel - 4;
12658 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
12659 cfg_lsw |= value;
12660 AscSetChipCfgLsw(iop_base, cfg_lsw);
12661 return (AscGetIsaDmaChannel(iop_base));
12663 return (0);
12666 ASC_INITFUNC(
12667 STATIC uchar
12668 AscSetIsaDmaSpeed(
12669 PortAddr iop_base,
12670 uchar speed_value
12674 speed_value &= 0x07;
12675 AscSetBank(iop_base, 1);
12676 AscWriteChipDmaSpeed(iop_base, speed_value);
12677 AscSetBank(iop_base, 0);
12678 return (AscGetIsaDmaSpeed(iop_base));
12681 ASC_INITFUNC(
12682 STATIC uchar
12683 AscGetIsaDmaSpeed(
12684 PortAddr iop_base
12688 uchar speed_value;
12690 AscSetBank(iop_base, 1);
12691 speed_value = AscReadChipDmaSpeed(iop_base);
12692 speed_value &= 0x07;
12693 AscSetBank(iop_base, 0);
12694 return (speed_value);
12697 ASC_INITFUNC(
12698 STATIC ushort
12699 AscReadPCIConfigWord(
12700 ASC_DVC_VAR asc_ptr_type *asc_dvc,
12701 ushort pci_config_offset)
12704 uchar lsb, msb;
12706 lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
12707 msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
12708 return ((ushort) ((msb << 8) | lsb));
12711 ASC_INITFUNC(
12712 STATIC ushort
12713 AscInitGetConfig(
12714 ASC_DVC_VAR asc_ptr_type * asc_dvc
12718 ushort warn_code;
12719 PortAddr iop_base;
12720 ushort PCIDeviceID;
12721 ushort PCIVendorID;
12722 uchar PCIRevisionID;
12723 uchar prevCmdRegBits;
12725 warn_code = 0;
12726 iop_base = asc_dvc->iop_base;
12727 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
12728 if (asc_dvc->err_code != 0) {
12729 return (UW_ERR);
12731 if (asc_dvc->bus_type == ASC_IS_PCI) {
12732 PCIVendorID = AscReadPCIConfigWord(asc_dvc,
12733 AscPCIConfigVendorIDRegister);
12735 PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
12736 AscPCIConfigDeviceIDRegister);
12738 PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
12739 AscPCIConfigRevisionIDRegister);
12741 if (PCIVendorID != ASC_PCI_VENDORID) {
12742 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12744 prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
12745 AscPCIConfigCommandRegister);
12747 if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
12748 AscPCICmdRegBits_IOMemBusMaster) {
12749 DvcWritePCIConfigByte(asc_dvc,
12750 AscPCIConfigCommandRegister,
12751 (prevCmdRegBits |
12752 AscPCICmdRegBits_IOMemBusMaster));
12754 if ((DvcReadPCIConfigByte(asc_dvc,
12755 AscPCIConfigCommandRegister)
12756 & AscPCICmdRegBits_IOMemBusMaster)
12757 != AscPCICmdRegBits_IOMemBusMaster) {
12758 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12761 if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) ||
12762 (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) {
12763 DvcWritePCIConfigByte(asc_dvc,
12764 AscPCIConfigLatencyTimer, 0x00);
12765 if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer)
12766 != 0x00) {
12767 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12769 } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) {
12770 if (DvcReadPCIConfigByte(asc_dvc,
12771 AscPCIConfigLatencyTimer) < 0x20) {
12772 DvcWritePCIConfigByte(asc_dvc,
12773 AscPCIConfigLatencyTimer, 0x20);
12775 if (DvcReadPCIConfigByte(asc_dvc,
12776 AscPCIConfigLatencyTimer) < 0x20) {
12777 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12783 if (AscFindSignature(iop_base)) {
12784 warn_code |= AscInitAscDvcVar(asc_dvc);
12785 warn_code |= AscInitFromEEP(asc_dvc);
12786 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
12787 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
12788 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
12790 } else {
12791 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12793 return(warn_code);
12796 ASC_INITFUNC(
12797 STATIC ushort
12798 AscInitSetConfig(
12799 ASC_DVC_VAR asc_ptr_type * asc_dvc
12803 ushort warn_code = 0;
12805 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12806 if (asc_dvc->err_code != 0)
12807 return (UW_ERR);
12808 if (AscFindSignature(asc_dvc->iop_base)) {
12809 warn_code |= AscInitFromAscDvcVar(asc_dvc);
12810 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12811 } else {
12812 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12814 return (warn_code);
12817 ASC_INITFUNC(
12818 STATIC ushort
12819 AscInitFromAscDvcVar(
12820 ASC_DVC_VAR asc_ptr_type * asc_dvc
12824 PortAddr iop_base;
12825 ushort cfg_msw;
12826 ushort warn_code;
12827 ushort pci_device_id;
12829 iop_base = asc_dvc->iop_base;
12830 pci_device_id = asc_dvc->cfg->pci_device_id;
12831 warn_code = 0;
12832 cfg_msw = AscGetChipCfgMsw(iop_base);
12833 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12834 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
12835 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12836 AscSetChipCfgMsw(iop_base, cfg_msw);
12838 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12839 asc_dvc->cfg->cmd_qng_enabled) {
12840 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12841 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12843 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12844 warn_code |= ASC_WARN_AUTO_CONFIG;
12846 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
12847 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
12848 != asc_dvc->irq_no) {
12849 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
12852 if (asc_dvc->bus_type & ASC_IS_PCI) {
12853 cfg_msw &= 0xFFC0;
12854 AscSetChipCfgMsw(iop_base, cfg_msw);
12855 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12856 } else {
12857 if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
12858 (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
12859 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12860 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12863 } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12864 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12865 == ASC_CHIP_VER_ASYN_BUG) {
12866 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12869 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12870 asc_dvc->cfg->chip_scsi_id) {
12871 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12873 if (asc_dvc->bus_type & ASC_IS_ISA) {
12874 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12875 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12877 return (warn_code);
12880 ASC_INITFUNC(
12881 STATIC ushort
12882 AscInitAsc1000Driver(
12883 ASC_DVC_VAR asc_ptr_type * asc_dvc
12887 ushort warn_code;
12888 PortAddr iop_base;
12889 extern ushort _asc_mcode_size;
12890 extern ulong _asc_mcode_chksum;
12891 extern uchar _asc_mcode_buf[];
12893 iop_base = asc_dvc->iop_base;
12894 warn_code = 0;
12895 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
12896 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
12897 AscResetChipAndScsiBus(asc_dvc);
12898 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
12900 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
12901 if (asc_dvc->err_code != 0)
12902 return (UW_ERR);
12903 if (!AscFindSignature(asc_dvc->iop_base)) {
12904 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12905 return (warn_code);
12907 AscDisableInterrupt(iop_base);
12908 warn_code |= AscInitLram(asc_dvc);
12909 if (asc_dvc->err_code != 0)
12910 return (UW_ERR);
12911 if (AscLoadMicroCode(iop_base, 0, (ushort *) _asc_mcode_buf,
12912 _asc_mcode_size) != _asc_mcode_chksum) {
12913 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
12914 return (warn_code);
12916 warn_code |= AscInitMicroCodeVar(asc_dvc);
12917 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
12918 AscEnableInterrupt(iop_base);
12919 return (warn_code);
12922 ASC_INITFUNC(
12923 STATIC ushort
12924 AscInitAscDvcVar(
12925 ASC_DVC_VAR asc_ptr_type * asc_dvc
12929 int i;
12930 PortAddr iop_base;
12931 ushort warn_code;
12932 uchar chip_version;
12934 iop_base = asc_dvc->iop_base;
12935 warn_code = 0;
12936 asc_dvc->err_code = 0;
12937 if ((asc_dvc->bus_type &
12938 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
12939 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
12941 AscSetChipControl(iop_base, CC_HALT);
12942 AscSetChipStatus(iop_base, 0);
12943 asc_dvc->bug_fix_cntl = 0;
12944 asc_dvc->pci_fix_asyn_xfer = 0;
12945 asc_dvc->pci_fix_asyn_xfer_always = 0;
12946 asc_dvc->init_state = 0;
12947 asc_dvc->sdtr_done = 0;
12948 asc_dvc->cur_total_qng = 0;
12949 asc_dvc->is_in_int = 0;
12950 asc_dvc->in_critical_cnt = 0;
12951 asc_dvc->last_q_shortage = 0;
12952 asc_dvc->use_tagged_qng = 0;
12953 asc_dvc->no_scam = 0;
12954 asc_dvc->unit_not_ready = 0;
12955 asc_dvc->queue_full_or_busy = 0;
12956 asc_dvc->redo_scam = 0 ;
12957 asc_dvc->res2 = 0 ;
12958 asc_dvc->host_init_sdtr_index = 0 ;
12959 asc_dvc->res7 = 0 ;
12960 asc_dvc->res8 = 0 ;
12961 asc_dvc->cfg->can_tagged_qng = 0 ;
12962 asc_dvc->cfg->cmd_qng_enabled = 0;
12963 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
12964 asc_dvc->init_sdtr = 0;
12965 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
12966 asc_dvc->scsi_reset_wait = 3;
12967 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
12968 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
12969 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
12970 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
12971 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
12972 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
12973 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
12974 ASC_LIB_VERSION_MINOR;
12975 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
12976 asc_dvc->cfg->chip_version = chip_version;
12977 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
12978 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
12979 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
12980 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
12981 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
12982 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
12983 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
12984 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
12985 asc_dvc->max_sdtr_index = 7;
12986 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
12987 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
12988 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
12989 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
12990 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
12991 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
12992 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
12993 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
12994 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
12995 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
12996 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
12997 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
12998 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
12999 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
13000 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
13001 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
13002 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
13003 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
13004 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
13005 asc_dvc->max_sdtr_index = 15;
13006 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
13008 AscSetExtraControl(iop_base,
13009 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13010 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
13011 AscSetExtraControl(iop_base,
13012 (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
13015 if (asc_dvc->bus_type == ASC_IS_PCI) {
13016 AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13019 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
13020 if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
13021 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
13022 asc_dvc->bus_type = ASC_IS_ISAPNP;
13024 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
13025 asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
13027 for (i = 0; i <= ASC_MAX_TID; i++) {
13028 asc_dvc->cur_dvc_qng[i] = 0;
13029 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
13030 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L;
13031 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L;
13032 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
13034 return (warn_code);
13037 ASC_INITFUNC(
13038 STATIC ushort
13039 AscInitFromEEP(
13040 ASC_DVC_VAR asc_ptr_type * asc_dvc
13044 ASCEEP_CONFIG eep_config_buf;
13045 ASCEEP_CONFIG *eep_config;
13046 PortAddr iop_base;
13047 ushort chksum;
13048 ushort warn_code;
13049 ushort cfg_msw, cfg_lsw;
13050 int i;
13051 int write_eep = 0;
13053 iop_base = asc_dvc->iop_base;
13054 warn_code = 0;
13055 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
13056 AscStopQueueExe(iop_base);
13057 if ((AscStopChip(iop_base) == FALSE) ||
13058 (AscGetChipScsiCtrl(iop_base) != 0)) {
13059 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
13060 AscResetChipAndScsiBus(asc_dvc);
13061 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
13063 if (AscIsChipHalted(iop_base) == FALSE) {
13064 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13065 return (warn_code);
13067 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13068 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13069 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13070 return (warn_code);
13072 eep_config = (ASCEEP_CONFIG *) & eep_config_buf;
13073 cfg_msw = AscGetChipCfgMsw(iop_base);
13074 cfg_lsw = AscGetChipCfgLsw(iop_base);
13075 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
13076 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
13077 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
13078 AscSetChipCfgMsw(iop_base, cfg_msw);
13080 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13081 if (chksum == 0) {
13082 chksum = 0xaa55;
13084 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
13085 warn_code |= ASC_WARN_AUTO_CONFIG;
13086 if (asc_dvc->cfg->chip_version == 3) {
13087 if (eep_config->cfg_lsw != cfg_lsw) {
13088 warn_code |= ASC_WARN_EEPROM_RECOVER;
13089 eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
13091 if (eep_config->cfg_msw != cfg_msw) {
13092 warn_code |= ASC_WARN_EEPROM_RECOVER;
13093 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
13097 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
13098 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
13099 if (chksum != eep_config->chksum) {
13100 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
13101 ASC_CHIP_VER_PCI_ULTRA_3050 )
13103 eep_config->init_sdtr = 0xFF;
13104 eep_config->disc_enable = 0xFF;
13105 eep_config->start_motor = 0xFF;
13106 eep_config->use_cmd_qng = 0;
13107 eep_config->max_total_qng = 0xF0;
13108 eep_config->max_tag_qng = 0x20;
13109 eep_config->cntl = 0xBFFF;
13110 eep_config->chip_scsi_id = 7;
13111 eep_config->no_scam = 0;
13112 eep_config->adapter_info[0] = 0;
13113 eep_config->adapter_info[1] = 0;
13114 eep_config->adapter_info[2] = 0;
13115 eep_config->adapter_info[3] = 0;
13116 eep_config->adapter_info[4] = 0;
13117 /* Indicate EEPROM-less board. */
13118 eep_config->adapter_info[5] = 0xBB;
13119 } else {
13120 write_eep = 1 ;
13121 warn_code |= ASC_WARN_EEPROM_CHKSUM ;
13124 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr ;
13125 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
13126 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
13127 asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
13128 asc_dvc->start_motor = eep_config->start_motor;
13129 asc_dvc->dvc_cntl = eep_config->cntl;
13130 asc_dvc->no_scam = eep_config->no_scam;
13131 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
13132 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
13133 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
13134 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
13135 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
13136 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
13137 if (!AscTestExternalLram(asc_dvc)) {
13138 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
13139 eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
13140 eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
13141 } else {
13142 eep_config->cfg_msw |= 0x0800;
13143 cfg_msw |= 0x0800;
13144 AscSetChipCfgMsw(iop_base, cfg_msw);
13145 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
13146 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
13148 } else {
13150 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
13151 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
13153 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
13154 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
13156 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
13157 eep_config->max_tag_qng = eep_config->max_total_qng;
13159 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
13160 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
13162 asc_dvc->max_total_qng = eep_config->max_total_qng;
13163 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
13164 eep_config->use_cmd_qng) {
13165 eep_config->disc_enable = eep_config->use_cmd_qng;
13166 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
13168 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
13169 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
13171 eep_config->chip_scsi_id &= ASC_MAX_TID;
13172 asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
13173 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
13174 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
13175 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
13178 for (i = 0; i <= ASC_MAX_TID; i++) {
13179 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
13180 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
13181 asc_dvc->cfg->sdtr_period_offset[i] =
13182 (uchar) (ASC_DEF_SDTR_OFFSET |
13183 (asc_dvc->host_init_sdtr_index << 4));
13185 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
13186 if (write_eep) {
13187 (void) AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13189 return (warn_code);
13192 ASC_INITFUNC(
13193 STATIC ushort
13194 AscInitMicroCodeVar(
13195 ASC_DVC_VAR asc_ptr_type * asc_dvc
13199 int i;
13200 ushort warn_code;
13201 PortAddr iop_base;
13202 ulong phy_addr;
13204 iop_base = asc_dvc->iop_base;
13205 warn_code = 0;
13206 for (i = 0; i <= ASC_MAX_TID; i++) {
13207 AscPutMCodeInitSDTRAtID(iop_base, i,
13208 asc_dvc->cfg->sdtr_period_offset[i]
13211 AscInitQLinkVar(asc_dvc);
13212 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
13213 asc_dvc->cfg->disc_enable);
13214 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
13215 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
13216 if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
13217 (uchar *) asc_dvc->cfg->overrun_buf,
13218 ASC_OVERRUN_BSIZE)) == 0L) {
13219 asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
13220 } else {
13221 phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
13222 AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
13223 AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
13224 ASC_OVERRUN_BSIZE - 8);
13226 asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
13227 (ushort) ASCV_MC_DATE_W);
13228 asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
13229 (ushort) ASCV_MC_VER_W);
13230 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13231 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13232 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13233 return (warn_code);
13235 if (AscStartChip(iop_base) != 1) {
13236 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13237 return (warn_code);
13239 return (warn_code);
13242 ASC_INITFUNC(
13243 STATIC int
13244 AscTestExternalLram(
13245 ASC_DVC_VAR asc_ptr_type * asc_dvc
13249 PortAddr iop_base;
13250 ushort q_addr;
13251 ushort saved_word;
13252 int sta;
13254 iop_base = asc_dvc->iop_base;
13255 sta = 0;
13256 q_addr = ASC_QNO_TO_QADDR(241);
13257 saved_word = AscReadLramWord(iop_base, q_addr);
13258 AscSetChipLramAddr(iop_base, q_addr);
13259 AscSetChipLramData(iop_base, 0x55AA);
13260 DvcSleepMilliSecond(10);
13261 AscSetChipLramAddr(iop_base, q_addr);
13262 if (AscGetChipLramData(iop_base) == 0x55AA) {
13263 sta = 1;
13264 AscWriteLramWord(iop_base, q_addr, saved_word);
13266 return (sta);
13269 ASC_INITFUNC(
13270 STATIC int
13271 AscWriteEEPCmdReg(
13272 PortAddr iop_base,
13273 uchar cmd_reg
13277 uchar read_back;
13278 int retry;
13280 retry = 0;
13281 while (TRUE) {
13282 AscSetChipEEPCmd(iop_base, cmd_reg);
13283 DvcSleepMilliSecond(1);
13284 read_back = AscGetChipEEPCmd(iop_base);
13285 if (read_back == cmd_reg) {
13286 return (1);
13288 if (retry++ > ASC_EEP_MAX_RETRY) {
13289 return (0);
13294 ASC_INITFUNC(
13295 STATIC int
13296 AscWriteEEPDataReg(
13297 PortAddr iop_base,
13298 ushort data_reg
13302 ushort read_back;
13303 int retry;
13305 retry = 0;
13306 while (TRUE) {
13307 AscSetChipEEPData(iop_base, data_reg);
13308 DvcSleepMilliSecond(1);
13309 read_back = AscGetChipEEPData(iop_base);
13310 if (read_back == data_reg) {
13311 return (1);
13313 if (retry++ > ASC_EEP_MAX_RETRY) {
13314 return (0);
13319 ASC_INITFUNC(
13320 STATIC void
13321 AscWaitEEPRead(
13322 void
13326 DvcSleepMilliSecond(1);
13327 return;
13330 ASC_INITFUNC(
13331 STATIC void
13332 AscWaitEEPWrite(
13333 void
13337 DvcSleepMilliSecond(20);
13338 return;
13341 ASC_INITFUNC(
13342 STATIC ushort
13343 AscReadEEPWord(
13344 PortAddr iop_base,
13345 uchar addr
13349 ushort read_wval;
13350 uchar cmd_reg;
13352 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
13353 AscWaitEEPRead();
13354 cmd_reg = addr | ASC_EEP_CMD_READ;
13355 AscWriteEEPCmdReg(iop_base, cmd_reg);
13356 AscWaitEEPRead();
13357 read_wval = AscGetChipEEPData(iop_base);
13358 AscWaitEEPRead();
13359 return (read_wval);
13362 ASC_INITFUNC(
13363 STATIC ushort
13364 AscWriteEEPWord(
13365 PortAddr iop_base,
13366 uchar addr,
13367 ushort word_val
13371 ushort read_wval;
13373 read_wval = AscReadEEPWord(iop_base, addr);
13374 if (read_wval != word_val) {
13375 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
13376 AscWaitEEPRead();
13377 AscWriteEEPDataReg(iop_base, word_val);
13378 AscWaitEEPRead();
13379 AscWriteEEPCmdReg(iop_base,
13380 (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
13381 AscWaitEEPWrite();
13382 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
13383 AscWaitEEPRead();
13384 return (AscReadEEPWord(iop_base, addr));
13386 return (read_wval);
13389 ASC_INITFUNC(
13390 STATIC ushort
13391 AscGetEEPConfig(
13392 PortAddr iop_base,
13393 ASCEEP_CONFIG * cfg_buf, ushort bus_type
13397 ushort wval;
13398 ushort sum;
13399 ushort *wbuf;
13400 int cfg_beg;
13401 int cfg_end;
13402 int s_addr;
13403 int isa_pnp_wsize;
13405 wbuf = (ushort *) cfg_buf;
13406 sum = 0;
13407 isa_pnp_wsize = 0;
13408 for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
13409 wval = AscReadEEPWord(iop_base, (uchar) s_addr);
13410 sum += wval;
13411 *wbuf = wval;
13413 if (bus_type & ASC_IS_VL) {
13414 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
13415 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
13416 } else {
13417 cfg_beg = ASC_EEP_DVC_CFG_BEG;
13418 cfg_end = ASC_EEP_MAX_DVC_ADDR;
13420 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
13421 s_addr++, wbuf++) {
13422 wval = AscReadEEPWord(iop_base, (uchar) s_addr);
13423 sum += wval;
13424 *wbuf = wval;
13426 *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
13427 return (sum);
13430 ASC_INITFUNC(
13431 STATIC int
13432 AscSetEEPConfigOnce(
13433 PortAddr iop_base,
13434 ASCEEP_CONFIG * cfg_buf, ushort bus_type
13438 int n_error;
13439 ushort *wbuf;
13440 ushort sum;
13441 int s_addr;
13442 int cfg_beg;
13443 int cfg_end;
13445 wbuf = (ushort *) cfg_buf;
13446 n_error = 0;
13447 sum = 0;
13448 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
13449 sum += *wbuf;
13450 if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
13451 n_error++;
13454 if (bus_type & ASC_IS_VL) {
13455 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
13456 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
13457 } else {
13458 cfg_beg = ASC_EEP_DVC_CFG_BEG;
13459 cfg_end = ASC_EEP_MAX_DVC_ADDR;
13461 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
13462 s_addr++, wbuf++) {
13463 sum += *wbuf;
13464 if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
13465 n_error++;
13468 *wbuf = sum;
13469 if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
13470 n_error++;
13472 wbuf = (ushort *) cfg_buf;
13473 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
13474 if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
13475 n_error++;
13478 for (s_addr = cfg_beg; s_addr <= cfg_end;
13479 s_addr++, wbuf++) {
13480 if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
13481 n_error++;
13484 return (n_error);
13487 ASC_INITFUNC(
13488 STATIC int
13489 AscSetEEPConfig(
13490 PortAddr iop_base,
13491 ASCEEP_CONFIG * cfg_buf, ushort bus_type
13495 int retry;
13496 int n_error;
13498 retry = 0;
13499 while (TRUE) {
13500 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
13501 bus_type)) == 0) {
13502 break;
13504 if (++retry > ASC_EEP_MAX_RETRY) {
13505 break;
13508 return (n_error);
13511 STATIC void
13512 AscAsyncFix(
13513 ASC_DVC_VAR asc_ptr_type *asc_dvc,
13514 uchar tid_no,
13515 ASC_SCSI_INQUIRY *inq)
13517 uchar dvc_type;
13518 ASC_SCSI_BIT_ID_TYPE tid_bits;
13520 dvc_type = inq->byte0.peri_dvc_type;
13521 tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
13523 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
13524 if (!(asc_dvc->init_sdtr & tid_bits)) {
13525 if ((dvc_type == SCSI_TYPE_CDROM) &&
13526 (AscCompareString((uchar *) inq->vendor_id,
13527 (uchar *) "HP ", 3) == 0)) {
13528 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
13530 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
13531 if ((dvc_type == SCSI_TYPE_PROC) ||
13532 (dvc_type == SCSI_TYPE_SCANNER)) {
13533 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13535 if ((dvc_type == SCSI_TYPE_SASD) &&
13536 (AscCompareString((uchar *) inq->vendor_id,
13537 (uchar *) "TANDBERG", 8) == 0) &&
13538 (AscCompareString((uchar *) inq->product_id,
13539 (uchar *) " TDC 36", 7) == 0)) {
13540 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13542 if ((dvc_type == SCSI_TYPE_SASD) &&
13543 (AscCompareString((uchar *) inq->vendor_id,
13544 (uchar *) "WANGTEK ", 8) == 0)) {
13545 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13548 if ((dvc_type == SCSI_TYPE_CDROM) &&
13549 (AscCompareString((uchar *) inq->vendor_id,
13550 (uchar *) "NEC ", 8) == 0) &&
13551 (AscCompareString((uchar *) inq->product_id,
13552 (uchar *) "CD-ROM DRIVE ", 16) == 0)) {
13553 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13556 if ((dvc_type == SCSI_TYPE_CDROM) &&
13557 (AscCompareString((uchar *) inq->vendor_id,
13558 (uchar *) "YAMAHA", 6) == 0) &&
13559 (AscCompareString((uchar *) inq->product_id,
13560 (uchar *) "CDR400", 6) == 0)) {
13561 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13563 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
13564 AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
13565 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
13569 return;
13572 STATIC int
13573 AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
13575 if ((inq->add_len >= 32) &&
13576 (AscCompareString((uchar *) inq->vendor_id,
13577 (uchar *) "QUANTUM XP34301", 15) == 0) &&
13578 (AscCompareString((uchar *) inq->product_rev_level,
13579 (uchar *) "1071", 4) == 0))
13581 return 0;
13583 return 1;
13586 STATIC void
13587 AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc,
13588 uchar tid_no, ASC_SCSI_INQUIRY *inq)
13590 ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
13591 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
13593 orig_init_sdtr = asc_dvc->init_sdtr;
13594 orig_use_tagged_qng = asc_dvc->use_tagged_qng;
13596 asc_dvc->init_sdtr &= ~tid_bit;
13597 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
13598 asc_dvc->use_tagged_qng &= ~tid_bit;
13600 if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) {
13601 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) {
13602 asc_dvc->init_sdtr |= tid_bit;
13604 if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) {
13605 if (AscTagQueuingSafe(inq)) {
13606 asc_dvc->use_tagged_qng |= tid_bit;
13607 asc_dvc->cfg->can_tagged_qng |= tid_bit;
13611 if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
13612 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
13613 asc_dvc->cfg->disc_enable);
13614 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
13615 asc_dvc->use_tagged_qng);
13616 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
13617 asc_dvc->cfg->can_tagged_qng);
13619 asc_dvc->max_dvc_qng[tid_no] =
13620 asc_dvc->cfg->max_tag_qng[tid_no];
13621 AscWriteLramByte(asc_dvc->iop_base,
13622 (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no),
13623 asc_dvc->max_dvc_qng[tid_no]);
13625 if (orig_init_sdtr != asc_dvc->init_sdtr) {
13626 AscAsyncFix(asc_dvc, tid_no, inq);
13628 return;
13631 STATIC int
13632 AscCompareString(
13633 ruchar * str1,
13634 ruchar * str2,
13635 int len
13638 int i;
13639 int diff;
13641 for (i = 0; i < len; i++) {
13642 diff = (int) (str1[i] - str2[i]);
13643 if (diff != 0)
13644 return (diff);
13646 return (0);
13649 STATIC uchar
13650 AscReadLramByte(
13651 PortAddr iop_base,
13652 ushort addr
13655 uchar byte_data;
13656 ushort word_data;
13658 if (isodd_word(addr)) {
13659 AscSetChipLramAddr(iop_base, addr - 1);
13660 word_data = AscGetChipLramData(iop_base);
13661 byte_data = (uchar) ((word_data >> 8) & 0xFF);
13662 } else {
13663 AscSetChipLramAddr(iop_base, addr);
13664 word_data = AscGetChipLramData(iop_base);
13665 byte_data = (uchar) (word_data & 0xFF);
13667 return (byte_data);
13670 STATIC ushort
13671 AscReadLramWord(
13672 PortAddr iop_base,
13673 ushort addr
13676 ushort word_data;
13678 AscSetChipLramAddr(iop_base, addr);
13679 word_data = AscGetChipLramData(iop_base);
13680 return (word_data);
13683 STATIC ulong
13684 AscReadLramDWord(
13685 PortAddr iop_base,
13686 ushort addr
13689 ushort val_low, val_high;
13690 ulong dword_data;
13692 AscSetChipLramAddr(iop_base, addr);
13693 val_low = AscGetChipLramData(iop_base);
13694 val_high = AscGetChipLramData(iop_base);
13695 dword_data = ((ulong) val_high << 16) | (ulong) val_low;
13696 return (dword_data);
13699 STATIC void
13700 AscWriteLramWord(
13701 PortAddr iop_base,
13702 ushort addr,
13703 ushort word_val
13706 AscSetChipLramAddr(iop_base, addr);
13707 AscSetChipLramData(iop_base, word_val);
13708 return;
13711 STATIC void
13712 AscWriteLramDWord(
13713 PortAddr iop_base,
13714 ushort addr,
13715 ulong dword_val
13718 ushort word_val;
13720 AscSetChipLramAddr(iop_base, addr);
13721 word_val = (ushort) dword_val;
13722 AscSetChipLramData(iop_base, word_val);
13723 word_val = (ushort) (dword_val >> 16);
13724 AscSetChipLramData(iop_base, word_val);
13725 return;
13728 STATIC void
13729 AscWriteLramByte(
13730 PortAddr iop_base,
13731 ushort addr,
13732 uchar byte_val
13735 ushort word_data;
13737 if (isodd_word(addr)) {
13738 addr--;
13739 word_data = AscReadLramWord(iop_base, addr);
13740 word_data &= 0x00FF;
13741 word_data |= (((ushort) byte_val << 8) & 0xFF00);
13742 } else {
13743 word_data = AscReadLramWord(iop_base, addr);
13744 word_data &= 0xFF00;
13745 word_data |= ((ushort) byte_val & 0x00FF);
13747 AscWriteLramWord(iop_base, addr, word_data);
13748 return;
13751 STATIC void
13752 AscMemWordCopyToLram(
13753 PortAddr iop_base,
13754 ushort s_addr,
13755 ushort * s_buffer,
13756 int words
13759 AscSetChipLramAddr(iop_base, s_addr);
13760 DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
13761 return;
13764 STATIC void
13765 AscMemDWordCopyToLram(
13766 PortAddr iop_base,
13767 ushort s_addr,
13768 ulong * s_buffer,
13769 int dwords
13772 AscSetChipLramAddr(iop_base, s_addr);
13773 DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
13774 return;
13777 STATIC void
13778 AscMemWordCopyFromLram(
13779 PortAddr iop_base,
13780 ushort s_addr,
13781 ushort * d_buffer,
13782 int words
13785 AscSetChipLramAddr(iop_base, s_addr);
13786 DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
13787 return;
13790 STATIC ulong
13791 AscMemSumLramWord(
13792 PortAddr iop_base,
13793 ushort s_addr,
13794 rint words
13797 ulong sum;
13798 int i;
13800 sum = 0L;
13801 for (i = 0; i < words; i++, s_addr += 2) {
13802 sum += AscReadLramWord(iop_base, s_addr);
13804 return (sum);
13807 STATIC void
13808 AscMemWordSetLram(
13809 PortAddr iop_base,
13810 ushort s_addr,
13811 ushort set_wval,
13812 rint words
13815 rint i;
13817 AscSetChipLramAddr(iop_base, s_addr);
13818 for (i = 0; i < words; i++) {
13819 AscSetChipLramData(iop_base, set_wval);
13821 return;
13826 * --- Adv Library Functions
13829 /* a_qswap.h */
13830 STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = {
13831 0x9C, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x44, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x01, 0xD6, 0x11, 0x00, 0x00, 0x70, 0x01,
13834 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x10, 0x2D, 0x03, 0x00, 0x00, 0x00, 0x00,
13835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13842 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13844 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
13845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12,
13850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13854 0x00, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x0C, 0x1C, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF2, 0xD6, 0x0A,
13855 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x3E, 0x57, 0x3C, 0x56, 0x0C, 0x1C, 0x00, 0xFC,
13856 0xA6, 0x00, 0x01, 0x58, 0xAA, 0x13, 0x20, 0xF0, 0xA6, 0x03, 0x06, 0xEC, 0xB9, 0x00, 0x0E, 0x47,
13857 0x03, 0xE6, 0x10, 0x00, 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0x06, 0xEA, 0xB9, 0x00, 0x47, 0x4B,
13858 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x4E, 0x12, 0x03, 0xF6, 0xC0, 0x00,
13859 0x00, 0xF2, 0x68, 0x0A, 0x41, 0x58, 0x03, 0xF6, 0xD0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x49, 0x44,
13860 0x59, 0xF0, 0x0A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x44, 0x58, 0x00, 0xF2,
13861 0xE2, 0x0D, 0x02, 0xCC, 0x4A, 0xE4, 0x01, 0x00, 0x55, 0xF0, 0x08, 0x03, 0x45, 0xF4, 0x02, 0x00,
13862 0x83, 0x5A, 0x04, 0xCC, 0x01, 0x4A, 0x12, 0x12, 0x00, 0xF2, 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4,
13863 0x01, 0x00, 0xE9, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0xFA, 0x10, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00,
13864 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0xCE, 0x47, 0x97, 0x13, 0x04, 0xEC, 0xB4, 0x00, 0x00, 0xF2,
13865 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, 0x00, 0x00, 0x12, 0x12, 0x3E, 0x57, 0x06, 0xCC, 0x45, 0xF4,
13866 0x02, 0x00, 0x83, 0x5A, 0x00, 0xCC, 0x00, 0xEA, 0xB4, 0x00, 0x92, 0x10, 0x00, 0xF0, 0x8C, 0x01,
13867 0x43, 0xF0, 0x5C, 0x02, 0x44, 0xF0, 0x60, 0x02, 0x45, 0xF0, 0x64, 0x02, 0x46, 0xF0, 0x68, 0x02,
13868 0x47, 0xF0, 0x6E, 0x02, 0x48, 0xF0, 0x9E, 0x02, 0xB9, 0x54, 0x62, 0x10, 0x00, 0x1C, 0x5A, 0x10,
13869 0x02, 0x1C, 0x56, 0x10, 0x1E, 0x1C, 0x52, 0x10, 0x00, 0xF2, 0x1E, 0x11, 0x50, 0x10, 0x06, 0xFC,
13870 0xA8, 0x00, 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x4E, 0x0A, 0x8C, 0x10, 0x01, 0xF6, 0x01, 0x00,
13871 0x01, 0xFA, 0xA8, 0x00, 0x00, 0xF2, 0x2C, 0x0B, 0x06, 0x10, 0xB9, 0x54, 0x01, 0xFA, 0xA8, 0x00,
13872 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x58, 0x0A, 0x01, 0xFC, 0xA8, 0x00, 0x20, 0x10, 0x58, 0x1C,
13873 0x00, 0xF2, 0x1C, 0x0B, 0x5A, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00,
13874 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x72, 0x01, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54,
13875 0x00, 0xFA, 0xA6, 0x00, 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x80, 0x01, 0x03, 0xF6,
13876 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x0A, 0x13, 0x00, 0xF2, 0x38, 0x10, 0x00, 0xF2,
13877 0x54, 0x0F, 0x24, 0x10, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x02, 0xF6, 0xD0, 0x00,
13878 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x49, 0x44, 0x5B, 0xF0, 0x04, 0x03, 0x00, 0xF2, 0x9C, 0x0F,
13879 0x00, 0xF0, 0x80, 0x01, 0x00, 0xF2, 0x14, 0x10, 0x0C, 0x1C, 0x02, 0x4B, 0xBF, 0x57, 0x9E, 0x43,
13880 0x77, 0x57, 0x07, 0x4B, 0x20, 0xF0, 0xA6, 0x03, 0x40, 0x1C, 0x1E, 0xF0, 0x30, 0x03, 0x26, 0xF0,
13881 0x2C, 0x03, 0xA0, 0xF0, 0x1A, 0x03, 0x11, 0xF0, 0xA6, 0x03, 0x12, 0x10, 0x9F, 0xF0, 0x3E, 0x03,
13882 0x46, 0x1C, 0x82, 0xE7, 0x05, 0x00, 0x9E, 0xE7, 0x11, 0x00, 0x00, 0xF0, 0x06, 0x0A, 0x0C, 0x1C,
13883 0x48, 0x1C, 0x46, 0x1C, 0x38, 0x54, 0x00, 0xEC, 0xBA, 0x00, 0x08, 0x44, 0x00, 0xEA, 0xBA, 0x00,
13884 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x08, 0x44, 0x00, 0x4C, 0x82, 0xE7, 0x02, 0x00,
13885 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x70, 0x03, 0x00, 0xF2, 0x60, 0x0B,
13886 0x06, 0xF0, 0x80, 0x03, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A,
13887 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x55, 0xF0, 0xAC, 0x04, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2,
13888 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x01, 0xF0,
13889 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x46, 0x1C, 0x0C, 0x1C, 0x67, 0x1B, 0xBF, 0x57, 0x77, 0x57,
13890 0x02, 0x4B, 0x48, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x96, 0xF0, 0xBC, 0x03,
13891 0xB1, 0xF0, 0xC0, 0x03, 0x1E, 0xF0, 0xFC, 0x09, 0x85, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0xBE, 0x00,
13892 0x98, 0x57, 0x14, 0x12, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11,
13893 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A,
13894 0x01, 0x48, 0x55, 0xF0, 0x98, 0x04, 0x03, 0x82, 0x03, 0xFC, 0xA0, 0x00, 0x9B, 0x57, 0x40, 0x12,
13895 0x69, 0x18, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x42, 0x04, 0x69, 0x08, 0x00, 0xF2, 0x12, 0x11,
13896 0x85, 0xF0, 0x02, 0x0A, 0x68, 0x08, 0x4C, 0x44, 0x28, 0x12, 0x44, 0x48, 0x03, 0xF6, 0xE0, 0x00,
13897 0x00, 0xF2, 0x68, 0x0A, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xCC, 0x01, 0x48, 0x55, 0xF0,
13898 0x98, 0x04, 0x4C, 0x44, 0xEF, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x14, 0x10, 0x08, 0x10,
13899 0x68, 0x18, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x04, 0x80, 0x18, 0xE4, 0x10, 0x00, 0x28, 0x12,
13900 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00,
13901 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00,
13902 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00,
13903 0x0C, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x82, 0xE7,
13904 0x02, 0x00, 0x1C, 0x90, 0x40, 0x5C, 0x00, 0x16, 0x01, 0xE6, 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D,
13905 0x01, 0xF0, 0x80, 0x01, 0x1E, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0xA0, 0x04, 0x42, 0x5B, 0x06, 0xF7,
13906 0x03, 0x00, 0x46, 0x59, 0xBF, 0x57, 0x77, 0x57, 0x01, 0xE6, 0x80, 0x00, 0x07, 0x80, 0x31, 0x44,
13907 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x56, 0x13, 0x20, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x4E, 0x12,
13908 0x00, 0xFC, 0xA2, 0x00, 0x98, 0x57, 0x55, 0xF0, 0x1C, 0x05, 0x31, 0xE4, 0x40, 0x00, 0x00, 0xFC,
13909 0xA0, 0x00, 0x98, 0x57, 0x36, 0x12, 0x4C, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x89, 0x48, 0x00, 0xF2,
13910 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x82, 0xE7, 0x06, 0x00, 0x1B, 0x80, 0x48, 0xE4, 0x22, 0x00,
13911 0x5B, 0xF0, 0x0C, 0x05, 0x48, 0xE4, 0x20, 0x00, 0x59, 0xF0, 0x10, 0x05, 0x00, 0xE6, 0x20, 0x00,
13912 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x83, 0x80, 0x04, 0x10, 0x00, 0xF2,
13913 0xA2, 0x0D, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x26, 0x01, 0x01, 0xEA, 0x27, 0x01, 0x04, 0x80,
13914 0x18, 0xE4, 0x10, 0x00, 0x36, 0x12, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x01, 0xE6, 0x06, 0x00,
13915 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4E, 0x0D,
13916 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x04, 0xE6, 0x02, 0x00,
13917 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0x20, 0x01,
13918 0x98, 0x57, 0x34, 0x12, 0x00, 0xFC, 0x24, 0x01, 0x98, 0x57, 0x2C, 0x13, 0xB9, 0x54, 0x00, 0xF2,
13919 0xF6, 0x0E, 0x86, 0xF0, 0xA8, 0x05, 0x03, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0x8C, 0x0E, 0x85, 0xF0,
13920 0x9E, 0x05, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC,
13921 0x24, 0x01, 0xB0, 0x57, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFC, 0x9E, 0x00, 0x98, 0x57, 0x5A, 0x12,
13922 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, 0x52, 0x13, 0x03, 0xE6, 0x0C, 0x00, 0x00, 0xFC, 0x9C, 0x00,
13923 0x98, 0x57, 0x04, 0x13, 0x03, 0xE6, 0x19, 0x00, 0x05, 0xE6, 0x08, 0x00, 0x00, 0xF6, 0x00, 0x01,
13924 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x04, 0x13, 0x05, 0xE6,
13925 0x0F, 0x00, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x86, 0xF0, 0x0A, 0x06, 0x00, 0xF2, 0xBA, 0x0E,
13926 0x85, 0xF0, 0x00, 0x06, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00,
13927 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0xF2,
13928 0xF6, 0x0E, 0x9C, 0x32, 0x4E, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x82, 0xE7,
13929 0x04, 0x00, 0xB1, 0xF0, 0x22, 0x06, 0x0A, 0xF0, 0x3E, 0x06, 0x05, 0xF0, 0xD6, 0x06, 0x06, 0xF0,
13930 0xDC, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x04, 0x80,
13931 0x18, 0xE4, 0x20, 0x00, 0x30, 0x12, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80,
13932 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2,
13933 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x99, 0xA4, 0x00, 0xF2, 0x12, 0x11,
13934 0x09, 0xE7, 0x00, 0x00, 0x9A, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x34, 0x12, 0x09, 0xE7,
13935 0x1B, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2,
13936 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2,
13937 0x12, 0x11, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF0,
13938 0x0C, 0x09, 0xBB, 0x55, 0x9A, 0x81, 0x03, 0xF7, 0x20, 0x00, 0x09, 0x6F, 0x93, 0x45, 0x55, 0xF0,
13939 0xE2, 0x06, 0xB1, 0xF0, 0xC2, 0x06, 0x0A, 0xF0, 0xBA, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0,
13940 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0x47, 0x10, 0x09, 0xE7, 0x08, 0x00,
13941 0x41, 0x10, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, 0x1E, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA,
13942 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x2C, 0x90, 0xAE, 0x90, 0x08, 0x50, 0x8A, 0x50, 0x38, 0x54,
13943 0x1F, 0x40, 0x00, 0xF2, 0xB4, 0x0D, 0x08, 0x10, 0x08, 0x90, 0x8A, 0x90, 0x30, 0x50, 0xB2, 0x50,
13944 0x9C, 0x32, 0x0C, 0x92, 0x8E, 0x92, 0x38, 0x54, 0x04, 0x80, 0x30, 0xE4, 0x08, 0x00, 0x04, 0x40,
13945 0x0C, 0x1C, 0x00, 0xF6, 0x03, 0x00, 0xB1, 0xF0, 0x26, 0x07, 0x9E, 0xF0, 0x3A, 0x07, 0x01, 0x48,
13946 0x55, 0xF0, 0xFC, 0x09, 0x0C, 0x1C, 0x10, 0x44, 0xED, 0x10, 0x0B, 0xF0, 0x5E, 0x07, 0x0C, 0xF0,
13947 0x62, 0x07, 0x05, 0xF0, 0x52, 0x07, 0x06, 0xF0, 0x58, 0x07, 0x09, 0xF0, 0x24, 0x09, 0x00, 0xF0,
13948 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0xCF, 0x10, 0x09, 0xE7, 0x08, 0x00, 0xC9, 0x10, 0x2E, 0x1C,
13949 0x02, 0x10, 0x2C, 0x1C, 0xAA, 0xF0, 0x64, 0x07, 0xAC, 0xF0, 0x72, 0x07, 0x40, 0x10, 0x34, 0x1C,
13950 0xF3, 0x10, 0xAD, 0xF0, 0x7C, 0x07, 0xC8, 0x10, 0x36, 0x1C, 0xE9, 0x10, 0x2B, 0xF0, 0x82, 0x08,
13951 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFE, 0x20, 0x12, 0x01, 0x58, 0xD2, 0xF0, 0x82, 0x08, 0x76, 0x18,
13952 0x18, 0xF4, 0x03, 0x00, 0xEC, 0x12, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xE2, 0x12,
13953 0x0B, 0xF0, 0x64, 0x07, 0x0C, 0xF0, 0x64, 0x07, 0x36, 0x1C, 0x34, 0x1C, 0xB7, 0x10, 0x38, 0x54,
13954 0xB9, 0x54, 0x84, 0x80, 0x19, 0xE4, 0x20, 0x00, 0xB2, 0x13, 0x85, 0x80, 0x81, 0x48, 0x66, 0x12,
13955 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x58, 0x13, 0x1F, 0x80, 0x08, 0x44, 0xC8, 0x44, 0x9F, 0x12,
13956 0x1F, 0x40, 0x34, 0x91, 0xB6, 0x91, 0x44, 0x55, 0xE5, 0x55, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49,
13957 0xBB, 0x55, 0x82, 0x81, 0xC0, 0x55, 0x48, 0xF4, 0x0F, 0x00, 0x5A, 0xF0, 0x1A, 0x08, 0x4A, 0xE4,
13958 0x17, 0x00, 0xD5, 0xF0, 0xFA, 0x07, 0x02, 0xF6, 0x0F, 0x00, 0x02, 0xF4, 0x02, 0x00, 0x02, 0xEA,
13959 0xB8, 0x00, 0x04, 0x91, 0x86, 0x91, 0x02, 0x4B, 0x2C, 0x90, 0x08, 0x50, 0x2E, 0x90, 0x0A, 0x50,
13960 0x2C, 0x51, 0xAE, 0x51, 0x00, 0xF2, 0xB6, 0x10, 0x38, 0x54, 0x00, 0xF2, 0xB4, 0x0D, 0x56, 0x10,
13961 0x34, 0x91, 0xB6, 0x91, 0x0C, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x41, 0x12, 0x0C, 0x91,
13962 0x8E, 0x91, 0x04, 0x80, 0x18, 0xE4, 0xF7, 0x00, 0x04, 0x40, 0x30, 0x90, 0xB2, 0x90, 0x36, 0x10,
13963 0x02, 0x80, 0x48, 0xE4, 0x10, 0x00, 0x31, 0x12, 0x82, 0xE7, 0x10, 0x00, 0x84, 0x80, 0x19, 0xE4,
13964 0x20, 0x00, 0x10, 0x13, 0x0C, 0x90, 0x8E, 0x90, 0x5D, 0xF0, 0x78, 0x07, 0x0C, 0x58, 0x8D, 0x58,
13965 0x00, 0xF0, 0x64, 0x07, 0x38, 0x54, 0xB9, 0x54, 0x19, 0x80, 0xF1, 0x10, 0x3A, 0x55, 0x19, 0x81,
13966 0xBB, 0x55, 0x10, 0x90, 0x92, 0x90, 0x10, 0x58, 0x91, 0x58, 0x14, 0x59, 0x95, 0x59, 0x00, 0xF0,
13967 0x64, 0x07, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x6C, 0x19, 0x19, 0x41, 0x7C, 0x10,
13968 0x6C, 0x19, 0x0C, 0x51, 0xED, 0x19, 0x8E, 0x51, 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFF, 0x02, 0x13,
13969 0x6A, 0x10, 0x01, 0x58, 0xD2, 0xF0, 0xC0, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x0A, 0x12,
13970 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0x06, 0x13, 0x9E, 0xE7, 0x16, 0x00, 0x4C, 0x10,
13971 0xD1, 0xF0, 0xCA, 0x08, 0x9E, 0xE7, 0x17, 0x00, 0x42, 0x10, 0xD0, 0xF0, 0xD4, 0x08, 0x9E, 0xE7,
13972 0x19, 0x00, 0x38, 0x10, 0xCF, 0xF0, 0xDE, 0x08, 0x9E, 0xE7, 0x20, 0x00, 0x2E, 0x10, 0xCE, 0xF0,
13973 0xE8, 0x08, 0x9E, 0xE7, 0x21, 0x00, 0x24, 0x10, 0xCD, 0xF0, 0xF2, 0x08, 0x9E, 0xE7, 0x22, 0x00,
13974 0x1A, 0x10, 0xCC, 0xF0, 0x04, 0x09, 0x84, 0x80, 0x19, 0xE4, 0x04, 0x00, 0x06, 0x12, 0x9E, 0xE7,
13975 0x12, 0x00, 0x08, 0x10, 0xCB, 0xF0, 0x0C, 0x09, 0x9E, 0xE7, 0x24, 0x00, 0xB1, 0xF0, 0x0C, 0x09,
13976 0x05, 0xF0, 0x1E, 0x09, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0xE4, 0x10, 0x00, 0xF2,
13977 0x60, 0x0B, 0xE9, 0x10, 0x9C, 0x32, 0x82, 0xE7, 0x20, 0x00, 0x32, 0x1C, 0xE9, 0x09, 0x00, 0xF2,
13978 0x12, 0x11, 0x85, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x01, 0xF0, 0x44, 0x09, 0x1E, 0xF0, 0xFC, 0x09,
13979 0x00, 0xF0, 0x38, 0x09, 0x30, 0x44, 0x06, 0x12, 0x9E, 0xE7, 0x42, 0x00, 0xB8, 0x10, 0x04, 0xF6,
13980 0x01, 0x00, 0xB3, 0x45, 0x74, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x22, 0x13, 0x4B, 0xE4,
13981 0x02, 0x00, 0x36, 0x12, 0x4B, 0xE4, 0x28, 0x00, 0xAC, 0x13, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2,
13982 0xC8, 0x11, 0x03, 0xF6, 0xD0, 0x00, 0xFA, 0x14, 0x82, 0xE7, 0x01, 0x00, 0x00, 0xF0, 0x80, 0x01,
13983 0x9E, 0xE7, 0x44, 0x00, 0x4B, 0xE4, 0x02, 0x00, 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x76, 0x10,
13984 0x00, 0xF2, 0xA2, 0x0D, 0x03, 0xE6, 0x02, 0x00, 0x6C, 0x10, 0x00, 0xF2, 0xA2, 0x0D, 0x19, 0x82,
13985 0x34, 0x46, 0x0A, 0x13, 0x03, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x43, 0x00, 0x68, 0x10, 0x04, 0x80,
13986 0x30, 0xE4, 0x20, 0x00, 0x04, 0x40, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x82, 0xE7,
13987 0x01, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x08, 0x03, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00,
13988 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x3E, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x3A, 0x12,
13989 0x04, 0x80, 0x18, 0xE4, 0xFD, 0x00, 0x04, 0x40, 0x1C, 0x1C, 0x9D, 0xF0, 0xEA, 0x09, 0x1C, 0x1C,
13990 0x9D, 0xF0, 0xF0, 0x09, 0xC1, 0x10, 0x9E, 0xE7, 0x13, 0x00, 0x0A, 0x10, 0x9E, 0xE7, 0x41, 0x00,
13991 0x04, 0x10, 0x9E, 0xE7, 0x24, 0x00, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0xD5, 0xF0, 0x8A, 0x02,
13992 0x04, 0xE6, 0x04, 0x00, 0x06, 0x10, 0x04, 0xE6, 0x04, 0x00, 0x9D, 0x41, 0x1C, 0x42, 0x9F, 0xE7,
13993 0x00, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x03, 0xF6, 0xE0, 0x00, 0x3C, 0x14, 0x44, 0x58, 0x45, 0x58,
13994 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x3C, 0x14, 0x1E, 0x1C,
13995 0x00, 0xF0, 0x80, 0x01, 0x12, 0x1C, 0x22, 0x1C, 0xD2, 0x14, 0x00, 0xF0, 0x72, 0x01, 0x83, 0x59,
13996 0x03, 0xDC, 0x73, 0x57, 0x80, 0x5D, 0x00, 0x16, 0x83, 0x59, 0x03, 0xDC, 0x38, 0x54, 0x70, 0x57,
13997 0x33, 0x54, 0x3B, 0x54, 0x80, 0x5D, 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x38, 0x54, 0x00, 0xCC,
13998 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x00, 0x4C, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x01, 0x00,
13999 0x0E, 0x12, 0x48, 0xE4, 0x05, 0x00, 0x08, 0x12, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11,
14000 0xC1, 0x5A, 0x3A, 0x55, 0x02, 0xEC, 0xB5, 0x00, 0x45, 0x59, 0x00, 0xF2, 0xF6, 0x0D, 0x83, 0x58,
14001 0x30, 0xE7, 0x00, 0x00, 0x10, 0x4D, 0x30, 0xE7, 0x40, 0x00, 0x10, 0x4F, 0x38, 0x90, 0xBA, 0x90,
14002 0x10, 0x5C, 0x80, 0x5C, 0x83, 0x5A, 0x10, 0x4E, 0x04, 0xEA, 0xB5, 0x00, 0x43, 0x5B, 0x03, 0xF4,
14003 0xE0, 0x00, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x0A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D,
14004 0x00, 0xF2, 0x38, 0x10, 0x00, 0x16, 0x08, 0x1C, 0x00, 0xFC, 0xAC, 0x00, 0x06, 0x58, 0x67, 0x18,
14005 0x18, 0xF4, 0x8F, 0xE1, 0x01, 0xFC, 0xAE, 0x00, 0x19, 0xF4, 0x70, 0x1E, 0xB0, 0x54, 0x07, 0x58,
14006 0x00, 0xFC, 0xB0, 0x00, 0x08, 0x58, 0x00, 0xFC, 0xB2, 0x00, 0x09, 0x58, 0x0A, 0x1C, 0x00, 0xE6,
14007 0x0F, 0x00, 0x00, 0xEA, 0xB9, 0x00, 0x38, 0x54, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFA, 0xB6, 0x00,
14008 0x18, 0x1C, 0x14, 0x1C, 0x10, 0x1C, 0x32, 0x1C, 0x12, 0x1C, 0x00, 0x16, 0x3E, 0x57, 0x0C, 0x14,
14009 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, 0xF5, 0x13, 0x00, 0x16, 0x00, 0xF2, 0xA2, 0x0D,
14010 0x02, 0x4B, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x20, 0x12, 0x44, 0x58,
14011 0x45, 0x58, 0x9E, 0xE7, 0x15, 0x00, 0x9C, 0xE7, 0x04, 0x00, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2,
14012 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x7A, 0x0A, 0x1E, 0x1C, 0xD5, 0x10, 0x00, 0x16,
14013 0x69, 0x08, 0x48, 0xE4, 0x04, 0x00, 0x64, 0x12, 0x48, 0xE4, 0x02, 0x00, 0x20, 0x12, 0x48, 0xE4,
14014 0x03, 0x00, 0x1A, 0x12, 0x48, 0xE4, 0x08, 0x00, 0x14, 0x12, 0x48, 0xE4, 0x01, 0x00, 0xF0, 0x12,
14015 0x48, 0xE4, 0x07, 0x00, 0x12, 0x12, 0x01, 0xE6, 0x07, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2,
14016 0x12, 0x11, 0x05, 0xF0, 0x60, 0x0B, 0x00, 0x16, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x99, 0x00,
14017 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0xE7, 0x12, 0x48, 0xE4, 0x06, 0x00, 0xE1, 0x12, 0x01, 0xE6,
14018 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7,
14019 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4,
14020 0x10, 0x00, 0x1C, 0x12, 0x82, 0xE7, 0x08, 0x00, 0x3C, 0x56, 0x03, 0x82, 0x00, 0xF2, 0xE2, 0x0D,
14021 0x30, 0xE7, 0x08, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x80, 0x01,
14022 0x6C, 0x19, 0xED, 0x19, 0x5D, 0xF0, 0xD4, 0x0B, 0x44, 0x55, 0xE5, 0x55, 0x59, 0xF0, 0x52, 0x0C,
14023 0x04, 0x55, 0xA5, 0x55, 0x1F, 0x80, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x49, 0x44,
14024 0x2E, 0x13, 0x01, 0xEC, 0xB8, 0x00, 0x41, 0xE4, 0x02, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x49, 0xE4,
14025 0x11, 0x00, 0x59, 0xF0, 0x2E, 0x0C, 0x01, 0xE6, 0x17, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x02, 0x4B,
14026 0x88, 0x90, 0xAC, 0x50, 0x8A, 0x90, 0xAE, 0x50, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80,
14027 0x10, 0x44, 0x02, 0x4B, 0x1F, 0x40, 0xC0, 0x44, 0x00, 0xF2, 0xB4, 0x0D, 0x04, 0x55, 0xA5, 0x55,
14028 0x9F, 0x10, 0x0C, 0x51, 0x8E, 0x51, 0x30, 0x90, 0xB2, 0x90, 0x00, 0x56, 0xA1, 0x56, 0x30, 0x50,
14029 0xB2, 0x50, 0x34, 0x90, 0xB6, 0x90, 0x40, 0x56, 0xE1, 0x56, 0x34, 0x50, 0xB6, 0x50, 0x65, 0x10,
14030 0xB1, 0xF0, 0x70, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0xE9, 0x09, 0x4B, 0xE4, 0x03, 0x00, 0x78, 0x12,
14031 0x4B, 0xE4, 0x02, 0x00, 0x01, 0x13, 0xB1, 0xF0, 0x86, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0x69, 0x08,
14032 0x48, 0xE4, 0x03, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0xCA, 0x0B,
14033 0xE8, 0x09, 0x3C, 0x56, 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x02, 0x13, 0xBB, 0x45, 0x4B, 0xE4,
14034 0x00, 0x00, 0x08, 0x12, 0x03, 0xE6, 0x01, 0x00, 0x04, 0xF6, 0x00, 0x80, 0xA8, 0x14, 0xD2, 0x14,
14035 0x30, 0x1C, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x10, 0x13, 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57,
14036 0x02, 0x13, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57,
14037 0x00, 0xFA, 0x24, 0x01, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B,
14038 0x00, 0xF2, 0x8C, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0xB1, 0xF0, 0xF8, 0x0C, 0x85, 0xF0, 0x86, 0x0B,
14039 0x69, 0x08, 0x48, 0xE4, 0x01, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0xFC, 0x14, 0x42, 0x58, 0x6C, 0x14,
14040 0x80, 0x14, 0x30, 0x1C, 0x4A, 0xF4, 0x02, 0x00, 0x55, 0xF0, 0x86, 0x0B, 0x4A, 0xF4, 0x01, 0x00,
14041 0x0E, 0x12, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x06, 0x13, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B,
14042 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2,
14043 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, 0x00, 0xF2, 0xBA, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0x4C, 0x1C,
14044 0xB1, 0xF0, 0x50, 0x0D, 0x85, 0xF0, 0x5C, 0x0D, 0x69, 0x08, 0xF3, 0x10, 0x86, 0xF0, 0x64, 0x0D,
14045 0x4E, 0x1C, 0x89, 0x48, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58,
14046 0x00, 0xDC, 0x18, 0xF4, 0xFF, 0x7F, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01,
14047 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x30, 0x56, 0x00, 0x5C,
14048 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x0B, 0x58,
14049 0x00, 0x16, 0x03, 0xF6, 0x24, 0x01, 0x00, 0xF2, 0x58, 0x0A, 0x03, 0xF6, 0xB6, 0x00, 0x00, 0xF2,
14050 0x58, 0x0A, 0x00, 0x16, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0x18, 0xF4, 0xFF, 0x00, 0x00, 0x54,
14051 0x00, 0x54, 0x00, 0x54, 0x00, 0xF4, 0x08, 0x00, 0xE1, 0x18, 0x80, 0x54, 0x03, 0x58, 0x00, 0xDD,
14052 0x01, 0xDD, 0x02, 0xDD, 0x03, 0xDC, 0x02, 0x4B, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x51, 0xB6, 0x51,
14053 0x00, 0x16, 0x45, 0x5A, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4,
14054 0x02, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56,
14055 0x05, 0xF4, 0x00, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x38, 0x54, 0xBB, 0x55, 0x3C, 0x56, 0xBD, 0x56,
14056 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x82, 0x0E, 0xE9, 0x09, 0xC1, 0x59, 0x00, 0xF2, 0x12, 0x11,
14057 0x85, 0xF0, 0x82, 0x0E, 0xE8, 0x0A, 0x83, 0x55, 0x83, 0x55, 0x4B, 0xF4, 0x90, 0x01, 0x5C, 0xF0,
14058 0x36, 0x0E, 0xBD, 0x56, 0x40, 0x10, 0x4B, 0xF4, 0x30, 0x00, 0x59, 0xF0, 0x48, 0x0E, 0x01, 0xF6,
14059 0x0C, 0x00, 0x00, 0xF6, 0x01, 0x00, 0x2E, 0x10, 0x02, 0xFC, 0x9C, 0x00, 0x9A, 0x57, 0x14, 0x13,
14060 0x4B, 0xF4, 0x64, 0x00, 0x59, 0xF0, 0x64, 0x0E, 0x03, 0xF6, 0x64, 0x00, 0x01, 0xF6, 0x19, 0x00,
14061 0x00, 0xF6, 0x01, 0x00, 0x43, 0xF4, 0x33, 0x00, 0x56, 0xF0, 0x76, 0x0E, 0x04, 0xF4, 0x00, 0x01,
14062 0x43, 0xF4, 0x19, 0x00, 0xF3, 0x10, 0xB4, 0x56, 0xC3, 0x58, 0x02, 0xFC, 0x9E, 0x00, 0x9A, 0x57,
14063 0x08, 0x13, 0x3C, 0x56, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x16, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00,
14064 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x02, 0x00, 0x00, 0xF2, 0x12, 0x11,
14065 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E,
14066 0x4E, 0x1C, 0x89, 0x49, 0x00, 0xF2, 0x12, 0x11, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2,
14067 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0,
14068 0xF2, 0x0E, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x89, 0x49,
14069 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x4E, 0x1C, 0x89, 0x4A, 0x00, 0xF2, 0x12, 0x11,
14070 0x00, 0x16, 0x3C, 0x56, 0x00, 0x16, 0x00, 0xEC, 0x26, 0x01, 0x48, 0xE4, 0x01, 0x00, 0x1E, 0x13,
14071 0x38, 0x44, 0x00, 0xEA, 0x26, 0x01, 0x49, 0xF4, 0x00, 0x00, 0x04, 0x12, 0x4E, 0x1C, 0x02, 0x10,
14072 0x4C, 0x1C, 0x01, 0xEC, 0x27, 0x01, 0x89, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x02, 0x14, 0x00, 0x16,
14073 0x85, 0xF0, 0x52, 0x0F, 0x38, 0x54, 0x00, 0xEA, 0x99, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x02, 0x80,
14074 0x48, 0xE4, 0x06, 0x00, 0x1C, 0x13, 0x00, 0xEC, 0x99, 0x00, 0x48, 0xE4, 0x01, 0x00, 0x0A, 0x12,
14075 0x04, 0x80, 0x30, 0xE4, 0x01, 0x00, 0x04, 0x40, 0x08, 0x10, 0x04, 0x80, 0x18, 0xE4, 0xFE, 0x00,
14076 0x04, 0x40, 0x00, 0x16, 0x02, 0xF6, 0xE0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x81, 0x48,
14077 0x22, 0x12, 0x00, 0x4E, 0x83, 0x5A, 0x90, 0x4C, 0x20, 0xE7, 0x00, 0x00, 0xC3, 0x58, 0x1B, 0xF4,
14078 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x8B, 0x55, 0x83, 0x59,
14079 0x00, 0x4E, 0x00, 0x16, 0x00, 0x4E, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x00, 0x4E,
14080 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x20, 0xE7, 0x00, 0x00, 0x00, 0x16, 0x02, 0xF6, 0xF0, 0x00,
14081 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x80, 0x4C,
14082 0xC3, 0x58, 0x1B, 0xF4, 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12,
14083 0x83, 0x59, 0x00, 0x4E, 0x00, 0x16, 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x3A, 0x55,
14084 0x02, 0xCC, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0xC0, 0x5A, 0x40, 0x5C, 0x38, 0x54, 0x00, 0xCD,
14085 0x01, 0xCC, 0x4A, 0x46, 0x0A, 0x13, 0x83, 0x59, 0x00, 0x4C, 0x01, 0x48, 0x16, 0x13, 0x0C, 0x10,
14086 0xC5, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0x4C, 0x01, 0x48, 0x08, 0x13, 0x05, 0xF6, 0xF0, 0x00,
14087 0x05, 0x57, 0x08, 0x10, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x8D, 0x56, 0x83, 0x5A, 0x80, 0x4C,
14088 0x05, 0x17, 0x00, 0x16, 0x02, 0x4B, 0x06, 0xF7, 0x04, 0x00, 0x62, 0x0B, 0x03, 0x82, 0x00, 0xF2,
14089 0xE2, 0x0D, 0x02, 0x80, 0x00, 0x4C, 0x45, 0xF4, 0x02, 0x00, 0x52, 0x14, 0x06, 0xF7, 0x02, 0x00,
14090 0x06, 0x14, 0x00, 0xF2, 0x54, 0x0F, 0x00, 0x16, 0x02, 0x4B, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C,
14091 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x1D, 0xF7, 0x3C, 0x00, 0xB8, 0xF0,
14092 0x4E, 0x10, 0x9C, 0x14, 0x01, 0x48, 0x1C, 0x13, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00,
14093 0xAF, 0x19, 0x03, 0x42, 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x02, 0xCC, 0x02, 0x41, 0x45, 0xF4,
14094 0x02, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, 0x3E, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x01, 0xF6,
14095 0xFF, 0x00, 0x38, 0x1C, 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x0E, 0xF7,
14096 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, 0x0F, 0x79, 0x1C, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x9C, 0x10,
14097 0x4E, 0x14, 0x01, 0x48, 0x06, 0x13, 0x45, 0xF4, 0x04, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0,
14098 0x82, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x02, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x2C, 0xBC, 0xAE, 0xBC,
14099 0xE2, 0x08, 0x00, 0xEC, 0xB8, 0x00, 0x02, 0x48, 0x1D, 0xF7, 0x80, 0x00, 0xB8, 0xF0, 0xCC, 0x10,
14100 0x1E, 0x14, 0x01, 0x48, 0x0E, 0x13, 0x0E, 0xF7, 0x80, 0x00, 0x38, 0x54, 0x03, 0x58, 0xAF, 0x19,
14101 0x82, 0x48, 0x00, 0x16, 0x82, 0x48, 0x12, 0x45, 0xD5, 0xF0, 0xBA, 0x10, 0x00, 0xF0, 0x9E, 0x02,
14102 0x39, 0xF0, 0xF8, 0x10, 0x38, 0x44, 0x00, 0x16, 0x7E, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x04, 0x13,
14103 0x61, 0x18, 0x00, 0x16, 0x38, 0x1C, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xF1, 0x12,
14104 0xE3, 0x10, 0x30, 0x44, 0x30, 0x44, 0x30, 0x44, 0xB1, 0xF0, 0x18, 0x11, 0x00, 0x16, 0x3E, 0x57,
14105 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x6A, 0x12, 0x45, 0x5A,
14106 0x00, 0xF2, 0xF6, 0x0D, 0x02, 0x4B, 0x70, 0x14, 0x34, 0x13, 0x02, 0x80, 0x48, 0xE4, 0x08, 0x00,
14107 0x18, 0x12, 0x9C, 0xE7, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2,
14108 0x7A, 0x0A, 0x1E, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x30, 0xE4, 0x10, 0x00, 0x04, 0x40,
14109 0x00, 0xF2, 0xE2, 0x0D, 0x20, 0xE7, 0x01, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x04, 0xDC,
14110 0x01, 0x4A, 0x24, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x43, 0x5B, 0x06, 0xEC, 0x98, 0x00,
14111 0x00, 0xF2, 0x38, 0x10, 0xC6, 0x59, 0x20, 0x14, 0x0A, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2,
14112 0x14, 0x10, 0xA7, 0x10, 0x83, 0x5A, 0xD7, 0x10, 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47,
14113 0x5A, 0xF0, 0x20, 0x11, 0xB9, 0x54, 0x00, 0x16, 0x14, 0x90, 0x96, 0x90, 0x02, 0xFC, 0xA8, 0x00,
14114 0x03, 0xFC, 0xAA, 0x00, 0x48, 0x55, 0x02, 0x13, 0xC9, 0x55, 0x00, 0x16, 0x00, 0xEC, 0xBA, 0x00,
14115 0x10, 0x44, 0x00, 0xEA, 0xBA, 0x00, 0x00, 0x16, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A,
14116 0x10, 0x44, 0x00, 0x4C, 0x00, 0x16
14119 unsigned short _adv_mcode_size ASC_INITDATA =
14120 sizeof(_adv_mcode_buf); /* 0x11D6 */
14121 unsigned long _adv_mcode_chksum ASC_INITDATA = 0x03494981UL;
14123 /* a_init.c */
14125 * EEPROM Configuration.
14127 * All drivers should use this structure to set the default EEPROM
14128 * configuration. The BIOS now uses this structure when it is built.
14129 * Additional structure information can be found in a_condor.h where
14130 * the structure is defined.
14132 STATIC ADVEEP_CONFIG
14133 Default_EEPROM_Config ASC_INITDATA = {
14134 ADV_EEPROM_BIOS_ENABLE, /* cfg_msw */
14135 0x0000, /* cfg_lsw */
14136 0xFFFF, /* disc_enable */
14137 0xFFFF, /* wdtr_able */
14138 0xFFFF, /* sdtr_able */
14139 0xFFFF, /* start_motor */
14140 0xFFFF, /* tagqng_able */
14141 0xFFFF, /* bios_scan */
14142 0, /* scam_tolerant */
14143 7, /* adapter_scsi_id */
14144 0, /* bios_boot_delay */
14145 3, /* scsi_reset_delay */
14146 0, /* bios_id_lun */
14147 0, /* termination */
14148 0, /* reserved1 */
14149 0xFFEF, /* bios_ctrl */
14150 0xFFFF, /* ultra_able */
14151 0, /* reserved2 */
14152 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
14153 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
14154 0, /* dvc_cntl */
14155 0, /* bug_fix */
14156 0, /* serial_number_word1 */
14157 0, /* serial_number_word2 */
14158 0, /* serial_number_word3 */
14159 0, /* check_sum */
14160 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */
14161 0, /* dvc_err_code */
14162 0, /* adv_err_code */
14163 0, /* adv_err_addr */
14164 0, /* saved_dvc_err_code */
14165 0, /* saved_adv_err_code */
14166 0, /* saved_adv_err_addr */
14167 0 /* num_of_err */
14171 * Initialize the ADV_DVC_VAR structure.
14173 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14175 * For a non-fatal error return a warning code. If there are no warnings
14176 * then 0 is returned.
14178 ASC_INITFUNC(
14180 AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
14183 ushort warn_code;
14184 AdvPortAddr iop_base;
14185 uchar pci_cmd_reg;
14186 int status;
14188 warn_code = 0;
14189 asc_dvc->err_code = 0;
14190 iop_base = asc_dvc->iop_base;
14193 * PCI Command Register
14196 if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
14197 AscPCIConfigCommandRegister))
14198 & AscPCICmdRegBits_BusMastering)
14199 != AscPCICmdRegBits_BusMastering)
14201 pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
14203 DvcAdvWritePCIConfigByte(asc_dvc,
14204 AscPCIConfigCommandRegister, pci_cmd_reg);
14206 if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister))
14207 & AscPCICmdRegBits_BusMastering)
14208 != AscPCICmdRegBits_BusMastering)
14210 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14215 * PCI Latency Timer
14217 * If the "latency timer" register is 0x20 or above, then we don't need
14218 * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
14219 * comes up less than 0x20).
14221 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
14222 DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20);
14223 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20)
14225 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14230 * Save the state of the PCI Configuration Command Register
14231 * "Parity Error Response Control" Bit. If the bit is clear (0),
14232 * in AdvInitAsc3550Driver() tell the microcode to ignore DMA
14233 * parity errors.
14235 asc_dvc->cfg->control_flag = 0;
14236 if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
14237 & AscPCICmdRegBits_ParErrRespCtrl)) == 0)
14239 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
14242 asc_dvc->cur_host_qng = 0;
14244 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
14245 ADV_LIB_VERSION_MINOR;
14246 asc_dvc->cfg->chip_version =
14247 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
14250 * Reset the chip to start and allow register writes.
14252 if (AdvFindSignature(iop_base) == 0)
14254 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
14255 return ADV_ERROR;
14257 else {
14259 AdvResetChip(asc_dvc);
14261 if ((status = AdvInitFromEEP(asc_dvc)) == ADV_ERROR)
14263 return ADV_ERROR;
14265 warn_code |= status;
14268 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14269 * Resets should be performed.
14271 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
14273 AdvResetSCSIBus(asc_dvc);
14277 return warn_code;
14281 * Initialize the ASC3550.
14283 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14285 * For a non-fatal error return a warning code. If there are no warnings
14286 * then 0 is returned.
14288 ASC_INITFUNC(
14290 AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
14293 AdvPortAddr iop_base;
14294 ushort warn_code;
14295 ulong sum;
14296 int begin_addr;
14297 int end_addr;
14298 int code_sum;
14299 int word;
14300 int rql_addr; /* RISC Queue List address */
14301 int i;
14302 ushort scsi_cfg1;
14303 uchar biosmem[ASC_MC_BIOSLEN]; /* BIOS RISC Memory 0x40-0x8F. */
14305 /* If there is already an error, don't continue. */
14306 if (asc_dvc->err_code != 0)
14308 return ADV_ERROR;
14311 warn_code = 0;
14312 iop_base = asc_dvc->iop_base;
14315 * Save the RISC memory BIOS region before writing the microcode.
14316 * The BIOS may already be loaded and using its RISC LRAM region
14317 * so its region must be saved and restored.
14319 * Note: This code makes the assumption, which is currently true,
14320 * that a chip reset does not clear RISC LRAM.
14322 for (i = 0; i < ASC_MC_BIOSLEN; i++)
14324 AdvReadByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
14328 * Load the Microcode
14330 * Write the microcode image to RISC memory starting at address 0.
14332 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14333 for (word = 0; word < _adv_mcode_size; word += 2)
14335 AdvWriteWordAutoIncLram(iop_base,
14336 *((ushort *) (&_adv_mcode_buf[word])));
14340 * Clear the rest of Condor's Internal RAM (8KB).
14342 for (; word < ADV_CONDOR_MEMSIZE; word += 2)
14344 AdvWriteWordAutoIncLram(iop_base, 0);
14348 * Verify the microcode checksum.
14350 sum = 0;
14351 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14352 for (word = 0; word < _adv_mcode_size; word += 2)
14354 sum += AdvReadWordAutoIncLram(iop_base);
14357 if (sum != _adv_mcode_chksum)
14359 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14360 return ADV_ERROR;
14364 * Restore the RISC memory BIOS region.
14366 for (i = 0; i < ASC_MC_BIOSLEN; i++)
14368 AdvWriteByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
14372 * Calculate and write the microcode code checksum to the microcode
14373 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14375 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14376 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14377 code_sum = 0;
14378 for (word = begin_addr; word < end_addr; word += 2)
14380 code_sum += *((ushort *) (&_adv_mcode_buf[word]));
14382 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
14385 * Read microcode version and date.
14387 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date);
14388 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version);
14391 * Initialize microcode operating variables
14393 AdvWriteWordLram(iop_base, ASC_MC_ADAPTER_SCSI_ID,
14394 asc_dvc->chip_scsi_id);
14397 * If the PCI Configuration Command Register "Parity Error Response
14398 * Control" Bit was clear (0), then set the microcode variable
14399 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14400 * to ignore DMA parity errors.
14402 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR)
14405 * Note: Don't remove the use of a temporary variable in
14406 * the following code, otherwise the Microsoft C compiler
14407 * will turn the following lines into a no-op.
14409 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14410 word |= CONTROL_FLAG_IGNORE_PERR;
14411 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14415 * Set default microcode operating variables for WDTR, SDTR, and
14416 * command tag queuing based on the EEPROM configuration values.
14418 * These ADV_DVC_VAR fields and the microcode variables will be
14419 * changed in AdvInquiryHandling() if it is found a device is
14420 * incapable of a particular feature.
14424 * Set the microcode ULTRA target mask from EEPROM value. The
14425 * SDTR target mask overrides the ULTRA target mask in the
14426 * microcode so it is safe to set this value without determining
14427 * whether the device supports SDTR.
14429 * Note: There is no way to know whether a device supports ULTRA
14430 * speed without attempting a SDTR ULTRA speed negotiation with
14431 * the device. The device will reject the speed if it does not
14432 * support it by responding with an SDTR message containing a
14433 * slower speed.
14435 AdvWriteWordLram(iop_base, ASC_MC_ULTRA_ABLE, asc_dvc->ultra_able);
14436 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable);
14440 * Set SCSI_CFG0 Microcode Default Value.
14442 * The microcode will set the SCSI_CFG0 register using this value
14443 * after it is started below.
14445 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14446 PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id);
14449 * Determine SCSI_CFG1 Microcode Default Value.
14451 * The microcode will set the SCSI_CFG1 register using this value
14452 * after it is started below.
14455 /* Read current SCSI_CFG1 Register value. */
14456 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14459 * If all three connectors are in use, return an error.
14461 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
14462 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0)
14464 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
14465 return ADV_ERROR;
14469 * If the internal narrow cable is reversed all of the SCSI_CTRL
14470 * register signals will be set. Check for and return an error if
14471 * this condition is found.
14473 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07)
14475 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14476 return ADV_ERROR;
14480 * If this is a differential board and a single-ended device
14481 * is attached to one of the connectors, return an error.
14483 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0)
14485 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
14486 return ADV_ERROR;
14490 * If automatic termination control is enabled, then set the
14491 * termination value based on a table listed in a_condor.h.
14493 * If manual termination was specified with an EEPROM setting
14494 * then 'termination' was set-up in AdvInitFromEEP() and
14495 * is ready to be 'ored' into SCSI_CFG1.
14497 if (asc_dvc->cfg->termination == 0)
14500 * The software always controls termination by setting TERM_CTL_SEL.
14501 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
14503 asc_dvc->cfg->termination |= TERM_CTL_SEL;
14505 switch(scsi_cfg1 & CABLE_DETECT)
14507 /* TERM_CTL_H: on, TERM_CTL_L: on */
14508 case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF:
14509 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
14510 break;
14512 /* TERM_CTL_H: on, TERM_CTL_L: off */
14513 case 0x1: case 0x5: case 0x9: case 0xA: case 0xC:
14514 asc_dvc->cfg->termination |= TERM_CTL_H;
14515 break;
14517 /* TERM_CTL_H: off, TERM_CTL_L: off */
14518 case 0x2: case 0x6:
14519 break;
14524 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
14526 scsi_cfg1 &= ~TERM_CTL;
14529 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
14530 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
14531 * referenced, because the hardware internally inverts
14532 * the Termination High and Low bits if TERM_POL is set.
14534 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
14537 * Set SCSI_CFG1 Microcode Default Value
14539 * Set filter value and possibly modified termination control
14540 * bits in the Microcode SCSI_CFG1 Register Value.
14542 * The microcode will set the SCSI_CFG1 register using this value
14543 * after it is started below.
14545 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
14546 FLTR_11_TO_20NS | scsi_cfg1);
14549 * Set SEL_MASK Microcode Default Value
14551 * The microcode will set the SEL_MASK register using this value
14552 * after it is started below.
14554 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14555 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
14558 * Link all the RISC Queue Lists together in a doubly-linked
14559 * NULL terminated list.
14561 * Skip the NULL (0) queue which is not used.
14563 for (i = 1, rql_addr = ASC_MC_RISC_Q_LIST_BASE + ASC_MC_RISC_Q_LIST_SIZE;
14564 i < ASC_MC_RISC_Q_TOTAL_CNT;
14565 i++, rql_addr += ASC_MC_RISC_Q_LIST_SIZE)
14568 * Set the current RISC Queue List's RQL_FWD and RQL_BWD pointers
14569 * in a one word write and set the state (RQL_STATE) to free.
14571 AdvWriteWordLram(iop_base, rql_addr, ((i + 1) + ((i - 1) << 8)));
14572 AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
14576 * Set the Host and RISC Queue List pointers.
14578 * Both sets of pointers are initialized with the same values:
14579 * ASC_MC_RISC_Q_FIRST(0x01) and ASC_MC_RISC_Q_LAST (0xFF).
14581 AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, ASC_MC_RISC_Q_FIRST);
14582 AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, ASC_MC_RISC_Q_LAST);
14584 AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_READY, ASC_MC_RISC_Q_FIRST);
14585 AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_DONE, ASC_MC_RISC_Q_LAST);
14588 * Finally, set up the last RISC Queue List (255) with
14589 * a NULL forward pointer.
14591 AdvWriteWordLram(iop_base, rql_addr, (ASC_MC_NULL_Q + ((i - 1) << 8)));
14592 AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
14594 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14595 (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR));
14598 * Note: Don't remove the use of a temporary variable in
14599 * the following code, otherwise the Microsoft C compiler
14600 * will turn the following lines into a no-op.
14602 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14603 AdvWriteWordRegister(iop_base, IOPW_PC, word);
14605 /* finally, finally, gentlemen, start your engine */
14606 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
14608 return warn_code;
14612 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
14613 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
14614 * all of this is done.
14616 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14618 * For a non-fatal error return a warning code. If there are no warnings
14619 * then 0 is returned.
14621 * Note: Chip is stopped on entry.
14623 ASC_INITFUNC(
14624 STATIC int
14625 AdvInitFromEEP(ADV_DVC_VAR *asc_dvc)
14628 AdvPortAddr iop_base;
14629 ushort warn_code;
14630 ADVEEP_CONFIG eep_config;
14631 int i;
14633 iop_base = asc_dvc->iop_base;
14635 warn_code = 0;
14638 * Read the board's EEPROM configuration.
14640 * Set default values if a bad checksum is found.
14642 if (AdvGetEEPConfig(iop_base, &eep_config) != eep_config.check_sum)
14644 warn_code |= ASC_WARN_EEPROM_CHKSUM;
14647 * Set EEPROM default values.
14649 for (i = 0; i < sizeof(ADVEEP_CONFIG); i++)
14651 *((uchar *) &eep_config + i) =
14652 *((uchar *) &Default_EEPROM_Config + i);
14656 * Assume the 6 byte board serial number that was read
14657 * from EEPROM is correct even if the EEPROM checksum
14658 * failed.
14660 eep_config.serial_number_word3 =
14661 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1);
14662 eep_config.serial_number_word2 =
14663 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2);
14664 eep_config.serial_number_word1 =
14665 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3);
14666 AdvSetEEPConfig(iop_base, &eep_config);
14670 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
14671 * EEPROM configuration that was read.
14673 * This is the mapping of EEPROM fields to Adv Library fields.
14675 asc_dvc->wdtr_able = eep_config.wdtr_able;
14676 asc_dvc->sdtr_able = eep_config.sdtr_able;
14677 asc_dvc->ultra_able = eep_config.ultra_able;
14678 asc_dvc->tagqng_able = eep_config.tagqng_able;
14679 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
14680 asc_dvc->max_host_qng = eep_config.max_host_qng;
14681 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
14682 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
14683 asc_dvc->start_motor = eep_config.start_motor;
14684 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
14685 asc_dvc->cfg->bios_boot_wait = eep_config.bios_boot_delay;
14686 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
14687 asc_dvc->no_scam = eep_config.scam_tolerant;
14688 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
14689 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
14690 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
14693 * Set the host maximum queuing (max. 253, min. 16) and the per device
14694 * maximum queuing (max. 63, min. 4).
14696 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG)
14698 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
14699 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG)
14701 /* If the value is zero, assume it is uninitialized. */
14702 if (eep_config.max_host_qng == 0)
14704 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
14705 } else
14707 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
14711 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG)
14713 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
14714 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG)
14716 /* If the value is zero, assume it is uninitialized. */
14717 if (eep_config.max_dvc_qng == 0)
14719 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
14720 } else
14722 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
14727 * If 'max_dvc_qng' is greater than 'max_host_qng', then
14728 * set 'max_dvc_qng' to 'max_host_qng'.
14730 if (eep_config.max_dvc_qng > eep_config.max_host_qng)
14732 eep_config.max_dvc_qng = eep_config.max_host_qng;
14736 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_CFG 'max_dvc_qng'
14737 * values based on possibly adjusted EEPROM values.
14739 asc_dvc->max_host_qng = eep_config.max_host_qng;
14740 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
14744 * If the EEPROM 'termination' field is set to automatic (0), then set
14745 * the ADV_DVC_CFG 'termination' field to automatic also.
14747 * If the termination is specified with a non-zero 'termination'
14748 * value check that a legal value is set and set the ADV_DVC_CFG
14749 * 'termination' field appropriately.
14751 if (eep_config.termination == 0)
14753 asc_dvc->cfg->termination = 0; /* auto termination */
14754 } else
14756 /* Enable manual control with low off / high off. */
14757 if (eep_config.termination == 1)
14759 asc_dvc->cfg->termination = TERM_CTL_SEL;
14761 /* Enable manual control with low off / high on. */
14762 } else if (eep_config.termination == 2)
14764 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
14766 /* Enable manual control with low on / high on. */
14767 } else if (eep_config.termination == 3)
14769 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
14770 } else
14773 * The EEPROM 'termination' field contains a bad value. Use
14774 * automatic termination instead.
14776 asc_dvc->cfg->termination = 0;
14777 warn_code |= ASC_WARN_EEPROM_TERMINATION;
14781 return warn_code;
14785 * Read EEPROM configuration into the specified buffer.
14787 * Return a checksum based on the EEPROM configuration read.
14789 ASC_INITFUNC(
14790 STATIC ushort
14791 AdvGetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
14794 ushort wval, chksum;
14795 ushort *wbuf;
14796 int eep_addr;
14798 wbuf = (ushort *) cfg_buf;
14799 chksum = 0;
14801 for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
14802 eep_addr < ASC_EEP_DVC_CFG_END;
14803 eep_addr++, wbuf++)
14805 wval = AdvReadEEPWord(iop_base, eep_addr);
14806 chksum += wval;
14807 *wbuf = wval;
14809 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14810 wbuf++;
14811 for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
14812 eep_addr < ASC_EEP_MAX_WORD_ADDR;
14813 eep_addr++, wbuf++)
14815 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14817 return chksum;
14821 * Read the EEPROM from specified location
14823 ASC_INITFUNC(
14824 STATIC ushort
14825 AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
14828 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14829 ASC_EEP_CMD_READ | eep_word_addr);
14830 AdvWaitEEPCmd(iop_base);
14831 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
14835 * Wait for EEPROM command to complete
14837 ASC_INITFUNC(
14838 STATIC void
14839 AdvWaitEEPCmd(AdvPortAddr iop_base)
14842 int eep_delay_ms;
14844 for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++)
14846 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE)
14848 break;
14850 DvcSleepMilliSecond(1);
14852 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0)
14854 ADV_ASSERT(0);
14856 return;
14860 * Write the EEPROM from 'cfg_buf'.
14862 ASC_INITFUNC(
14863 STATIC void
14864 AdvSetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
14867 ushort *wbuf;
14868 ushort addr, chksum;
14870 wbuf = (ushort *) cfg_buf;
14871 chksum = 0;
14873 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
14874 AdvWaitEEPCmd(iop_base);
14877 * Write EEPROM from word 0 to word 15
14879 for (addr = ASC_EEP_DVC_CFG_BEGIN;
14880 addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++)
14882 chksum += *wbuf;
14883 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
14884 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14885 AdvWaitEEPCmd(iop_base);
14886 DvcSleepMilliSecond(ASC_EEP_DELAY_MS);
14890 * Write EEPROM checksum at word 18
14892 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
14893 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14894 AdvWaitEEPCmd(iop_base);
14895 wbuf++; /* skip over check_sum */
14898 * Write EEPROM OEM name at words 19 to 26
14900 for (addr = ASC_EEP_DVC_CTL_BEGIN;
14901 addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++)
14903 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
14904 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14905 AdvWaitEEPCmd(iop_base);
14907 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
14908 AdvWaitEEPCmd(iop_base);
14909 return;
14913 * This function resets the chip and SCSI bus
14915 * It is up to the caller to add a delay to let the bus settle after
14916 * calling this function.
14918 * The SCSI_CFG0, SCSI_CFG1, and MEM_CFG registers are set-up in
14919 * AdvInitAsc3550Driver(). Here when doing a write to one of these
14920 * registers read first and then write.
14922 * Note: A SCSI Bus Reset can not be done until after the EEPROM
14923 * configuration is read to determine whether SCSI Bus Resets
14924 * should be performed.
14926 ASC_INITFUNC(
14927 STATIC void
14928 AdvResetChip(ADV_DVC_VAR *asc_dvc)
14931 AdvPortAddr iop_base;
14932 ushort word;
14933 uchar byte;
14935 iop_base = asc_dvc->iop_base;
14938 * Reset Chip.
14940 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14941 DvcSleepMilliSecond(100);
14942 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG);
14945 * Initialize Chip registers.
14947 * Note: Don't remove the use of a temporary variable in the following
14948 * code, otherwise the Microsoft C compiler will turn the following lines
14949 * into a no-op.
14951 byte = AdvReadByteRegister(iop_base, IOPB_MEM_CFG);
14952 byte |= RAM_SZ_8KB;
14953 AdvWriteByteRegister(iop_base, IOPB_MEM_CFG, byte);
14955 word = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14956 word &= ~BIG_ENDIAN;
14957 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, word);
14960 * Setting the START_CTL_EMFU 3:2 bits sets a FIFO threshold
14961 * of 128 bytes. This register is only accessible to the host.
14963 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14964 START_CTL_EMFU | READ_CMD_MRM);
14967 /* a_advlib.c */
14969 * Description:
14970 * Send a SCSI request to the ASC3550 chip
14972 * If there is no SG list for the request, set 'sg_entry_cnt' to 0.
14974 * If 'sg_real_addr' is non-zero on entry, AscGetSGList() will not be
14975 * called. It is assumed the caller has already initialized 'sg_real_addr'.
14977 * Return:
14978 * ADV_SUCCESS(1) - the request is in the mailbox
14979 * ADV_BUSY(0) - total request count > 253, try later
14980 * ADV_ERROR(-1) - invalid scsi request Q
14982 STATIC int
14983 AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc,
14984 ADV_SCSI_REQ_Q *scsiq)
14986 if (scsiq == (ADV_SCSI_REQ_Q *) 0L)
14988 /* 'scsiq' should never be NULL. */
14989 ADV_ASSERT(0);
14990 return ADV_ERROR;
14993 return AdvSendScsiCmd(asc_dvc, scsiq);
14997 * Reset SCSI Bus and purge all outstanding requests.
14999 * Return Value:
15000 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
15002 * Note: Should always return ADV_TRUE.
15004 STATIC int
15005 AdvResetSB(ADV_DVC_VAR *asc_dvc)
15007 int status;
15009 status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET, 0L, 0);
15011 AdvResetSCSIBus(asc_dvc);
15013 return status;
15017 * Reset SCSI Bus and delay.
15019 STATIC void
15020 AdvResetSCSIBus(ADV_DVC_VAR *asc_dvc)
15022 AdvPortAddr iop_base;
15023 ushort scsi_ctrl;
15025 iop_base = asc_dvc->iop_base;
15028 * The microcode currently sets the SCSI Bus Reset signal while
15029 * handling the AscSendIdleCmd() IDLE_CMD_SCSI_RESET command above.
15030 * But the SCSI Bus Reset Hold Time in the microcode is not deterministic
15031 * (it may in fact be for less than the SCSI Spec. minimum of 25 us).
15032 * Therefore on return the Adv Library sets the SCSI Bus Reset signal
15033 * for ASC_SCSI_RESET_HOLD_TIME_US, which is defined to be greater
15034 * than 25 us.
15036 scsi_ctrl = AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL);
15037 AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
15038 scsi_ctrl | ADV_SCSI_CTRL_RSTOUT);
15039 DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US);
15040 AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
15041 scsi_ctrl & ~ADV_SCSI_CTRL_RSTOUT);
15043 DvcSleepMilliSecond((ulong) asc_dvc->scsi_reset_wait * 1000);
15048 * Adv Library Interrupt Service Routine
15050 * This function is called by a driver's interrupt service routine.
15051 * The function disables and re-enables interrupts.
15053 * When a microcode idle command is completed, the ADV_DVC_VAR
15054 * 'idle_cmd_done' field is set to ADV_TRUE.
15056 * Note: AdvISR() can be called when interrupts are disabled or even
15057 * when there is no hardware interrupt condition present. It will
15058 * always check for completed idle commands and microcode requests.
15059 * This is an important feature that shouldn't be changed because it
15060 * allows commands to be completed from polling mode loops.
15062 * Return:
15063 * ADV_TRUE(1) - interrupt was pending
15064 * ADV_FALSE(0) - no interrupt was pending
15066 STATIC int
15067 AdvISR(ADV_DVC_VAR *asc_dvc)
15069 AdvPortAddr iop_base;
15070 uchar int_stat;
15071 ushort next_done_loc, target_bit;
15072 int completed_q;
15073 int flags;
15074 ADV_SCSI_REQ_Q *scsiq;
15075 ASC_REQ_SENSE *sense_data;
15076 int ret;
15078 flags = DvcEnterCritical();
15079 iop_base = asc_dvc->iop_base;
15081 if (AdvIsIntPending(iop_base))
15083 ret = ADV_TRUE;
15084 } else
15086 ret = ADV_FALSE;
15089 /* Reading the register clears the interrupt. */
15090 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
15092 if (int_stat & ADV_INTR_STATUS_INTRB)
15094 asc_dvc->idle_cmd_done = ADV_TRUE;
15098 * Notify the driver of a hardware detected SCSI Bus Reset.
15100 if (int_stat & ADV_INTR_STATUS_INTRC)
15102 if (asc_dvc->sbreset_callback != 0)
15104 (*(ADV_SBRESET_CALLBACK) asc_dvc->sbreset_callback)(asc_dvc);
15109 * ASC_MC_HOST_NEXT_DONE (0x129) is actually the last completed RISC
15110 * Queue List request. Its forward pointer (RQL_FWD) points to the
15111 * current completed RISC Queue List request.
15113 AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, next_done_loc);
15114 next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
15115 (next_done_loc * ASC_MC_RISC_Q_LIST_SIZE) + RQL_FWD;
15117 AdvReadByteLram(iop_base, next_done_loc, completed_q);
15119 /* Loop until all completed Q's are processed. */
15120 while (completed_q != ASC_MC_NULL_Q)
15122 AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, completed_q);
15124 next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
15125 (completed_q * ASC_MC_RISC_Q_LIST_SIZE);
15128 * Read the ADV_SCSI_REQ_Q virtual address pointer from
15129 * the RISC list entry. The microcode has changed the
15130 * ADV_SCSI_REQ_Q physical address to its virtual address.
15132 * Refer to comments at the end of AdvSendScsiCmd() for
15133 * more information on the RISC list structure.
15136 ushort lsw, msw;
15137 AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR, lsw);
15138 AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR + 2, msw);
15140 scsiq = (ADV_SCSI_REQ_Q *) (((ulong) msw << 16) | lsw);
15142 ADV_ASSERT(scsiq != NULL);
15144 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
15147 * Clear request microcode control flag.
15149 scsiq->cntl = 0;
15152 * Check Condition handling
15154 if ((scsiq->done_status == QD_WITH_ERROR) &&
15155 (scsiq->scsi_status == SS_CHK_CONDITION) &&
15156 (sense_data = (ASC_REQ_SENSE *) scsiq->vsense_addr) != 0 &&
15157 (scsiq->orig_sense_len - scsiq->sense_len) >= ASC_MIN_SENSE_LEN)
15160 * Command returned with a check condition and valid
15161 * sense data.
15165 * If the command that completed was a SCSI INQUIRY and
15166 * LUN 0 was sent the command, then process the INQUIRY
15167 * command information for the device.
15169 else if (scsiq->done_status == QD_NO_ERROR &&
15170 scsiq->cdb[0] == SCSICMD_Inquiry &&
15171 scsiq->target_lun == 0)
15173 AdvInquiryHandling(asc_dvc, scsiq);
15177 /* Change the RISC Queue List state to free. */
15178 AdvWriteByteLram(iop_base, next_done_loc + RQL_STATE, ASC_MC_QS_FREE);
15180 /* Get the RISC Queue List forward pointer. */
15181 AdvReadByteLram(iop_base, next_done_loc + RQL_FWD, completed_q);
15184 * Notify the driver of the completed request by passing
15185 * the ADV_SCSI_REQ_Q pointer to its callback function.
15187 ADV_ASSERT(asc_dvc->cur_host_qng > 0);
15188 asc_dvc->cur_host_qng--;
15189 scsiq->a_flag |= ADV_SCSIQ_DONE;
15190 (*(ADV_ISR_CALLBACK) asc_dvc->isr_callback)(asc_dvc, scsiq);
15192 * Note: After the driver callback function is called, 'scsiq'
15193 * can no longer be referenced.
15195 * Fall through and continue processing other completed
15196 * requests...
15200 * Disable interrupts again in case the driver inadvertently
15201 * enabled interrupts in its callback function.
15203 * The DvcEnterCritical() return value is ignored, because
15204 * the 'flags' saved when AdvISR() was first entered will be
15205 * used to restore the interrupt flag on exit.
15207 (void) DvcEnterCritical();
15209 DvcLeaveCritical(flags);
15210 return ret;
15214 * Send an idle command to the chip and wait for completion.
15216 * Interrupts do not have to be enabled on entry.
15218 * Return Values:
15219 * ADV_TRUE - command completed successfully
15220 * ADV_FALSE - command failed
15222 STATIC int
15223 AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
15224 ushort idle_cmd,
15225 ulong idle_cmd_parameter,
15226 int flags)
15228 int last_int_level;
15229 ulong i;
15230 AdvPortAddr iop_base;
15231 int ret;
15233 asc_dvc->idle_cmd_done = 0;
15235 last_int_level = DvcEnterCritical();
15236 iop_base = asc_dvc->iop_base;
15239 * Write the idle command value after the idle command parameter
15240 * has been written to avoid a race condition. If the order is not
15241 * followed, the microcode may process the idle command before the
15242 * parameters have been written to LRAM.
15244 AdvWriteDWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, idle_cmd_parameter);
15245 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
15246 DvcLeaveCritical(last_int_level);
15249 * If the 'flags' argument contains the ADV_NOWAIT flag, then
15250 * return with success.
15252 if (flags & ADV_NOWAIT)
15254 return ADV_TRUE;
15257 for (i = 0; i < SCSI_WAIT_10_SEC * SCSI_MS_PER_SEC; i++)
15260 * 'idle_cmd_done' is set by AdvISR().
15262 if (asc_dvc->idle_cmd_done)
15264 break;
15266 DvcSleepMilliSecond(1);
15269 * If interrupts were disabled on entry to AdvSendIdleCmd(),
15270 * then they will still be disabled here. Call AdvISR() to
15271 * check for the idle command completion.
15273 (void) AdvISR(asc_dvc);
15276 last_int_level = DvcEnterCritical();
15278 if (asc_dvc->idle_cmd_done == ADV_FALSE)
15280 ADV_ASSERT(0); /* The idle command should never timeout. */
15281 return ADV_FALSE;
15282 } else
15284 AdvReadWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, ret);
15285 return ret;
15290 * Send the SCSI request block to the adapter
15292 * Each of the 255 Adv Library/Microcode RISC Lists or mailboxes has the
15293 * following structure:
15295 * 0: RQL_FWD - RISC list forward pointer (1 byte)
15296 * 1: RQL_BWD - RISC list backward pointer (1 byte)
15297 * 2: RQL_STATE - RISC list state byte - free, ready, done, aborted (1 byte)
15298 * 3: RQL_TID - request target id (1 byte)
15299 * 4: RQL_PHYADDR - ADV_SCSI_REQ_Q physical pointer (4 bytes)
15301 * Return:
15302 * ADV_SUCCESS(1) - the request is in the mailbox
15303 * ADV_BUSY(0) - total request count > 253, try later
15305 STATIC int
15306 AdvSendScsiCmd(
15307 ADV_DVC_VAR *asc_dvc,
15308 ADV_SCSI_REQ_Q *scsiq)
15310 ushort next_ready_loc;
15311 uchar next_ready_loc_fwd;
15312 int last_int_level;
15313 AdvPortAddr iop_base;
15314 long req_size;
15315 ulong q_phy_addr;
15318 * The ADV_SCSI_REQ_Q 'target_id' field should never be equal
15319 * to the host adapter ID or exceed ADV_MAX_TID.
15321 if (scsiq->target_id == asc_dvc->chip_scsi_id ||
15322 scsiq->target_id > ADV_MAX_TID)
15324 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
15325 scsiq->done_status = QD_WITH_ERROR;
15326 return ADV_ERROR;
15329 iop_base = asc_dvc->iop_base;
15331 last_int_level = DvcEnterCritical();
15333 if (asc_dvc->cur_host_qng >= asc_dvc->max_host_qng)
15335 DvcLeaveCritical(last_int_level);
15336 return ADV_BUSY;
15337 } else
15339 ADV_ASSERT(asc_dvc->cur_host_qng < ASC_MC_RISC_Q_TOTAL_CNT);
15340 asc_dvc->cur_host_qng++;
15344 * Clear the ADV_SCSI_REQ_Q done flag.
15346 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
15349 * Save the original sense buffer length.
15351 * After the request completes 'sense_len' will be set to the residual
15352 * byte count of the Auto-Request Sense if a command returns CHECK
15353 * CONDITION and the Sense Data is valid indicated by 'host_status' not
15354 * being set to QHSTA_M_AUTO_REQ_SENSE_FAIL. To determine the valid
15355 * Sense Data Length subtract 'sense_len' from 'orig_sense_len'.
15357 scsiq->orig_sense_len = scsiq->sense_len;
15359 AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc);
15360 next_ready_loc = ASC_MC_RISC_Q_LIST_BASE +
15361 (next_ready_loc * ASC_MC_RISC_Q_LIST_SIZE);
15364 * Write the physical address of the Q to the mailbox.
15365 * We need to skip the first four bytes, because the microcode
15366 * uses them internally for linking Q's together.
15368 req_size = sizeof(ADV_SCSI_REQ_Q);
15369 q_phy_addr = DvcGetPhyAddr(asc_dvc, scsiq,
15370 (uchar *) scsiq, &req_size,
15371 ADV_IS_SCSIQ_FLAG);
15372 ADV_ASSERT(ADV_DWALIGN(q_phy_addr) == q_phy_addr);
15373 ADV_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
15375 scsiq->scsiq_ptr = (ADV_SCSI_REQ_Q *) scsiq;
15378 * The RISC list structure, which 'next_ready_loc' is a pointer
15379 * to in microcode LRAM, has the format detailed in the comment
15380 * header for this function.
15382 * Write the ADV_SCSI_REQ_Q physical pointer to 'next_ready_loc' request.
15384 AdvWriteDWordLram(iop_base, next_ready_loc + RQL_PHYADDR, q_phy_addr);
15386 /* Write target_id to 'next_ready_loc' request. */
15387 AdvWriteByteLram(iop_base, next_ready_loc + RQL_TID, scsiq->target_id);
15390 * Set the ASC_MC_HOST_NEXT_READY (0x128) microcode variable to
15391 * the 'next_ready_loc' request forward pointer.
15393 * Do this *before* changing the 'next_ready_loc' queue to QS_READY.
15394 * After the state is changed to QS_READY 'RQL_FWD' will be changed
15395 * by the microcode.
15397 * NOTE: The temporary variable 'next_ready_loc_fwd' is required to
15398 * prevent some compilers from optimizing out 'AdvReadByteLram()' if
15399 * it were used as the 3rd argument to 'AdvWriteByteLram()'.
15401 AdvReadByteLram(iop_base, next_ready_loc + RQL_FWD, next_ready_loc_fwd);
15402 AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc_fwd);
15405 * Change the state of 'next_ready_loc' request from QS_FREE to
15406 * QS_READY which will cause the microcode to pick it up and
15407 * execute it.
15409 * Can't reference 'next_ready_loc' after changing the request
15410 * state to QS_READY. The microcode now owns the request.
15412 AdvWriteByteLram(iop_base, next_ready_loc + RQL_STATE, ASC_MC_QS_READY);
15414 DvcLeaveCritical(last_int_level);
15415 return ADV_SUCCESS;
15419 * Inquiry Information Byte 7 Handling
15421 * Handle SCSI Inquiry Command information for a device by setting
15422 * microcode operating variables that affect WDTR, SDTR, and Tag
15423 * Queuing.
15425 STATIC void
15426 AdvInquiryHandling(
15427 ADV_DVC_VAR *asc_dvc,
15428 ADV_SCSI_REQ_Q *scsiq)
15430 AdvPortAddr iop_base;
15431 uchar tid;
15432 ASC_SCSI_INQUIRY *inq;
15433 ushort tidmask;
15434 ushort cfg_word;
15437 * AdvInquiryHandling() requires up to INQUIRY information Byte 7
15438 * to be available.
15440 * If less than 8 bytes of INQUIRY information were requested or less
15441 * than 8 bytes were transferred, then return. cdb[4] is the request
15442 * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
15443 * microcode to the transfer residual count.
15445 if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8)
15447 return;
15450 iop_base = asc_dvc->iop_base;
15451 tid = scsiq->target_id;
15452 inq = (ASC_SCSI_INQUIRY *) scsiq->vdata_addr;
15455 * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
15457 if (inq->byte3.rsp_data_fmt < 2 && inq->byte2.ansi_apr_ver < 2)
15459 return;
15460 } else
15463 * INQUIRY Byte 7 Handling
15465 * Use a device's INQUIRY byte 7 to determine whether it
15466 * supports WDTR, SDTR, and Tag Queuing. If the feature
15467 * is enabled in the EEPROM and the device supports the
15468 * feature, then enable it in the microcode.
15471 tidmask = ADV_TID_TO_TIDMASK(tid);
15474 * Wide Transfers
15476 * If the EEPROM enabled WDTR for the device and the device
15477 * supports wide bus (16 bit) transfers, then turn on the
15478 * device's 'wdtr_able' bit and write the new value to the
15479 * microcode.
15481 if ((asc_dvc->wdtr_able & tidmask) && inq->byte7.WBus16)
15483 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
15484 if ((cfg_word & tidmask) == 0)
15486 cfg_word |= tidmask;
15487 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
15490 * Clear the microcode "WDTR negotiation" done indicator
15491 * for the target to cause it to negotiate with the new
15492 * setting set above.
15494 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
15495 cfg_word &= ~tidmask;
15496 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
15501 * Synchronous Transfers
15503 * If the EEPROM enabled SDTR for the device and the device
15504 * supports synchronous transfers, then turn on the device's
15505 * 'sdtr_able' bit. Write the new value to the microcode.
15507 if ((asc_dvc->sdtr_able & tidmask) && inq->byte7.Sync)
15509 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
15510 if ((cfg_word & tidmask) == 0)
15512 cfg_word |= tidmask;
15513 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
15516 * Clear the microcode "SDTR negotiation" done indicator
15517 * for the target to cause it to negotiate with the new
15518 * setting set above.
15520 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
15521 cfg_word &= ~tidmask;
15522 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
15527 * If the EEPROM enabled Tag Queuing for device and the
15528 * device supports Tag Queuing, then turn on the device's
15529 * 'tagqng_enable' bit in the microcode and set the microcode
15530 * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
15531 * value.
15533 * Tag Queuing is disabled for the BIOS which runs in polled
15534 * mode and would see no benefit from Tag Queuing. Also by
15535 * disabling Tag Queuing in the BIOS devices with Tag Queuing
15536 * bugs will at least work with the BIOS.
15538 if ((asc_dvc->tagqng_able & tidmask) && inq->byte7.CmdQue)
15540 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
15541 cfg_word |= tidmask;
15542 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
15543 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
15544 asc_dvc->max_dvc_qng);