* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / scsi / advansys.c
blob60b7b037ea6517feb1bbefe247b450c147890058
1 /* $Id: advansys.c,v 1.59 1999/09/08 18:50:51 bobf Exp bobf $ */
2 #define ASC_VERSION "3.2G" /* AdvanSys Driver Version */
4 /*
5 * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
6 *
7 * Copyright (c) 1995-1999 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/Fix List
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.38, v2.2.12, and v2.3.16. These kernel versions are major
46 releases of Linux or the latest Linux kernel versions available when
47 this version of the driver was released. The driver should also work
48 in earlier versions of the Linux kernel. Beginning with v1.3.58 the
49 AdvanSys driver is included with all Linux kernels. Please refer to
50 sections C, D, and E for instructions on adding or upgrading the
51 AdvanSys driver.
53 B. Adapters Supported by this Driver
55 AdvanSys (Advanced System Products, Inc.) manufactures the following
56 RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
57 (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
58 buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
59 transfer) SCSI Host Adapters for the PCI bus.
61 The CDB counts below indicate the number of SCSI CDB (Command
62 Descriptor Block) requests that can be stored in the RISC chip
63 cache and board LRAM. A CDB is a single SCSI command. The driver
64 detect routine will display the number of CDBs available for each
65 adapter detected. The number of CDBs used by the driver can be
66 lowered in the BIOS by changing the 'Host Queue Size' adapter setting.
68 Connectivity Products:
69 ABP510/5150 - Bus-Master ISA (240 CDB)
70 ABP5140 - Bus-Master ISA PnP (16 CDB)
71 ABP5142 - Bus-Master ISA PnP with floppy (16 CDB)
72 ABP902/3902 - Bus-Master PCI (16 CDB)
73 ABP3905 - Bus-Master PCI (16 CDB)
74 ABP915 - Bus-Master PCI (16 CDB)
75 ABP920 - Bus-Master PCI (16 CDB)
76 ABP3922 - Bus-Master PCI (16 CDB)
77 ABP3925 - Bus-Master PCI (16 CDB)
78 ABP930 - Bus-Master PCI (16 CDB)
79 ABP930U - Bus-Master PCI Ultra (16 CDB)
80 ABP930UA - Bus-Master PCI Ultra (16 CDB)
81 ABP960 - Bus-Master PCI MAC/PC (16 CDB)
82 ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
84 Single Channel Products:
85 ABP542 - Bus-Master ISA with floppy (240 CDB)
86 ABP742 - Bus-Master EISA (240 CDB)
87 ABP842 - Bus-Master VL (240 CDB)
88 ABP940 - Bus-Master PCI (240 CDB)
89 ABP940U - Bus-Master PCI Ultra (240 CDB)
90 ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB)
91 ABP970 - Bus-Master PCI MAC/PC (240 CDB)
92 ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
93 ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB)
94 ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB)
95 ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB)
96 ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB)
98 Multi-Channel Products:
99 ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
100 ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
101 ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
102 ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel)
103 ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
104 ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
105 ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.)
107 C. Linux v1.2.X - Directions for Adding the AdvanSys Driver
109 These directions apply to v1.2.13. For versions that follow v1.2.13.
110 but precede v1.3.57 some of the changes for Linux v1.3.X listed
111 below may need to be modified or included. A patch is available
112 for v1.2.13 from the AdvanSys WWW and FTP sites.
114 There are two source files: advansys.h and advansys.c. Copy
115 both of these files to the directory /usr/src/linux/drivers/scsi.
117 1. Add the following line to /usr/src/linux/arch/i386/config.in
118 after "comment 'SCSI low-level drivers'":
120 bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
122 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
123 after "#include "hosts.h"":
125 #ifdef CONFIG_SCSI_ADVANSYS
126 #include "advansys.h"
127 #endif
129 and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
131 #ifdef CONFIG_SCSI_ADVANSYS
132 ADVANSYS,
133 #endif
135 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
137 ifdef CONFIG_SCSI_ADVANSYS
138 SCSI_SRCS := $(SCSI_SRCS) advansys.c
139 SCSI_OBJS := $(SCSI_OBJS) advansys.o
140 else
141 SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
142 endif
144 4. (Optional) If you would like to enable the LILO command line
145 and /etc/lilo.conf 'advansys' option, make the following changes.
146 This option can be used to disable I/O port scanning or to limit
147 I/O port scanning to specific addresses. Refer to the 'Driver
148 LILO Option' section below. Add the following lines to
149 /usr/src/linux/init/main.c in the prototype section:
151 extern void advansys_setup(char *str, int *ints);
153 and add the following lines to the bootsetups[] array.
155 #ifdef CONFIG_SCSI_ADVANSYS
156 { "advansys=", advansys_setup },
157 #endif
159 5. If you have the HP 4020i CD-R driver and Linux v1.2.X you should
160 add a fix to the CD-ROM target driver. This fix will allow
161 you to mount CDs with the iso9660 file system. Linux v1.3.X
162 already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
163 and function get_sectorsize() after the line:
165 if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
167 add the following line:
169 if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
171 6. In the directory /usr/src/linux run 'make config' to configure
172 the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
173 make the kernel. If the AdvanSys driver is not configured, then
174 a loadable module can be built by running 'make modules' and
175 'make modules_install'. Use 'insmod' and 'rmmod' to install
176 and remove advansys.o.
178 D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver
180 These directions apply to v1.3.57. For versions that precede v1.3.57
181 some of these changes may need to be modified or eliminated. A patch
182 is available for v1.3.57 from the AdvanSys WWW and FTP sites.
183 Beginning with v1.3.58 this driver is included with the Linux
184 distribution eliminating the need for making any changes.
186 There are two source files: advansys.h and advansys.c. Copy
187 both of these files to the directory /usr/src/linux/drivers/scsi.
189 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
190 after "comment 'SCSI low-level drivers'":
192 dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
194 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
195 after "#include "hosts.h"":
197 #ifdef CONFIG_SCSI_ADVANSYS
198 #include "advansys.h"
199 #endif
201 and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
203 #ifdef CONFIG_SCSI_ADVANSYS
204 ADVANSYS,
205 #endif
207 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
209 ifeq ($(CONFIG_SCSI_ADVANSYS),y)
210 L_OBJS += advansys.o
211 else
212 ifeq ($(CONFIG_SCSI_ADVANSYS),m)
213 M_OBJS += advansys.o
214 endif
215 endif
217 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
218 in the enum scsi_directory_inos array:
220 PROC_SCSI_ADVANSYS,
222 5. (Optional) If you would like to enable the LILO command line
223 and /etc/lilo.conf 'advansys' option, make the following changes.
224 This option can be used to disable I/O port scanning or to limit
225 I/O port scanning to specific addresses. Refer to the 'Driver
226 LILO Option' section below. Add the following lines to
227 /usr/src/linux/init/main.c in the prototype section:
229 extern void advansys_setup(char *str, int *ints);
231 and add the following lines to the bootsetups[] array.
233 #ifdef CONFIG_SCSI_ADVANSYS
234 { "advansys=", advansys_setup },
235 #endif
237 6. In the directory /usr/src/linux run 'make config' to configure
238 the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
239 make the kernel. If the AdvanSys driver is not configured, then
240 a loadable module can be built by running 'make modules' and
241 'make modules_install'. Use 'insmod' and 'rmmod' to install
242 and remove advansys.o.
244 E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver
246 To upgrade the AdvanSys driver in a Linux v1.3.58 and newer
247 kernel, first check the version of the current driver. The
248 version is defined by the manifest constant ASC_VERSION at
249 the beginning of advansys.c. The new driver should have a
250 ASC_VERSION value greater than the current version. To install
251 the new driver rename advansys.c and advansys.h in the Linux
252 kernel source tree drivers/scsi directory to different names
253 or save them to a different directory in case you want to revert
254 to the old version of the driver. After the old driver is saved
255 copy the new advansys.c and advansys.h to drivers/scsi, rebuild
256 the kernel, and install the new kernel. No other changes are needed.
258 F. Source Comments
260 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
262 2. This driver should be maintained in multiple files. But to make
263 it easier to include with Linux and to follow Linux conventions,
264 the whole driver is maintained in the source files advansys.h and
265 advansys.c. In this file logical sections of the driver begin with
266 a comment that contains '---'. The following are the logical sections
267 of the driver below.
269 --- Linux Version
270 --- Linux Include Files
271 --- Driver Options
272 --- Debugging Header
273 --- Asc Library Constants and Macros
274 --- Adv Library Constants and Macros
275 --- Driver Constants and Macros
276 --- Driver Structures
277 --- Driver Data
278 --- Driver Function Prototypes
279 --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
280 --- Loadable Driver Support
281 --- Miscellaneous Driver Functions
282 --- Functions Required by the Asc Library
283 --- Functions Required by the Adv Library
284 --- Tracing and Debugging Functions
285 --- Asc Library Functions
286 --- Adv Library Functions
288 3. The string 'XXX' is used to flag code that needs to be re-written
289 or that contains a problem that needs to be addressed.
291 4. I have stripped comments from and reformatted the source for the
292 Asc Library and Adv Library to reduce the size of this file. This
293 source can be found under the following headings. The Asc Library
294 is used to support Narrow Boards. The Adv Library is used to
295 support Wide Boards.
297 --- Asc Library Constants and Macros
298 --- Adv Library Constants and Macros
299 --- Asc Library Functions
300 --- Adv Library Functions
302 G. Driver Compile Time Options and Debugging
304 In this source file the following constants can be defined. They are
305 defined in the source below. Both of these options are enabled by
306 default.
308 1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled)
310 Enabling this option adds assertion logic statements to the
311 driver. If an assertion fails a message will be displayed to
312 the console, but the system will continue to operate. Any
313 assertions encountered should be reported to the person
314 responsible for the driver. Assertion statements may proactively
315 detect problems with the driver and facilitate fixing these
316 problems. Enabling assertions will add a small overhead to the
317 execution of the driver.
319 2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled)
321 Enabling this option adds tracing functions to the driver and
322 the ability to set a driver tracing level at boot time. This
323 option will also export symbols not required outside the driver to
324 the kernel name space. This option is very useful for debugging
325 the driver, but it will add to the size of the driver execution
326 image and add overhead to the execution of the driver.
328 The amount of debugging output can be controlled with the global
329 variable 'asc_dbglvl'. The higher the number the more output. By
330 default the debug level is 0.
332 If the driver is loaded at boot time and the LILO Driver Option
333 is included in the system, the debug level can be changed by
334 specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The
335 first three hex digits of the pseudo I/O Port must be set to
336 'deb' and the fourth hex digit specifies the debug level: 0 - F.
337 The following command line will look for an adapter at 0x330
338 and set the debug level to 2.
340 linux advansys=0x330,0,0,0,0xdeb2
342 If the driver is built as a loadable module this variable can be
343 defined when the driver is loaded. The following insmod command
344 will set the debug level to one.
346 insmod advansys.o asc_dbglvl=1
348 Debugging Message Levels:
349 0: Errors Only
350 1: High-Level Tracing
351 2-N: Verbose Tracing
353 I don't know the approved way for turning on printk()s to the
354 console. Here's a program I use to do this. Debug output is
355 logged in /var/adm/messages.
357 main()
359 syscall(103, 7, 0, 0);
362 I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
363 prevents most level 1 debug messages from being lost.
365 3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0)
367 Enabling this option adds statistics collection and display
368 through /proc to the driver. The information is useful for
369 monitoring driver and device performance. It will add to the
370 size of the driver execution image and add minor overhead to
371 the execution of the driver.
373 Statistics are maintained on a per adapter basis. Driver entry
374 point call counts and transfer size counts are maintained.
375 Statistics are only available for kernels greater than or equal
376 to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured.
378 AdvanSys SCSI adapter files have the following path name format:
380 /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
382 This information can be displayed with cat. For example:
384 cat /proc/scsi/advansys/0
386 When ADVANSYS_STATS is not defined the AdvanSys /proc files only
387 contain adapter and device configuration information.
389 H. Driver LILO Option
391 If init/main.c is modified as described in the 'Directions for Adding
392 the AdvanSys Driver to Linux' section (B.4.) above, the driver will
393 recognize the 'advansys' LILO command line and /etc/lilo.conf option.
394 This option can be used to either disable I/O port scanning or to limit
395 scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
396 PCI boards will still be searched for and detected. This option only
397 affects searching for ISA and VL boards.
399 Examples:
400 1. Eliminate I/O port scanning:
401 boot: linux advansys=
403 boot: linux advansys=0x0
404 2. Limit I/O port scanning to one I/O port:
405 boot: linux advansys=0x110
406 3. Limit I/O port scanning to four I/O ports:
407 boot: linux advansys=0x110,0x210,0x230,0x330
409 For a loadable module the same effect can be achieved by setting
410 the 'asc_iopflag' variable and 'asc_ioport' array when loading
411 the driver, e.g.
413 insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
415 If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1)
416 I/O Port may be added to specify the driver debug level. Refer to
417 the 'Driver Compile Time Options and Debugging' section above for
418 more information.
420 I. Release History
422 BETA-1.0 (12/23/95):
423 First Release
425 BETA-1.1 (12/28/95):
426 1. Prevent advansys_detect() from being called twice.
427 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
429 1.2 (1/12/96):
430 1. Prevent re-entrancy in the interrupt handler which
431 resulted in the driver hanging Linux.
432 2. Fix problem that prevented ABP-940 cards from being
433 recognized on some PCI motherboards.
434 3. Add support for the ABP-5140 PnP ISA card.
435 4. Fix check condition return status.
436 5. Add conditionally compiled code for Linux v1.3.X.
438 1.3 (2/23/96):
439 1. Fix problem in advansys_biosparam() that resulted in the
440 wrong drive geometry being returned for drives > 1GB with
441 extended translation enabled.
442 2. Add additional tracing during device initialization.
443 3. Change code that only applies to ISA PnP adapter.
444 4. Eliminate 'make dep' warning.
445 5. Try to fix problem with handling resets by increasing their
446 timeout value.
448 1.4 (5/8/96):
449 1. Change definitions to eliminate conflicts with other subsystems.
450 2. Add versioning code for the shared interrupt changes.
451 3. Eliminate problem in asc_rmqueue() with iterating after removing
452 a request.
453 4. Remove reset request loop problem from the "Known Problems or
454 Issues" section. This problem was isolated and fixed in the
455 mid-level SCSI driver.
457 1.5 (8/8/96):
458 1. Add support for ABP-940U (PCI Ultra) adapter.
459 2. Add support for IRQ sharing by setting the SA_SHIRQ flag for
460 request_irq and supplying a dev_id pointer to both request_irq()
461 and free_irq().
462 3. In AscSearchIOPortAddr11() restore a call to check_region() which
463 should be used before I/O port probing.
464 4. Fix bug in asc_prt_hex() which resulted in the displaying
465 the wrong data.
466 5. Incorporate miscellaneous Asc Library bug fixes and new microcode.
467 6. Change driver versioning to be specific to each Linux sub-level.
468 7. Change statistics gathering to be per adapter instead of global
469 to the driver.
470 8. Add more information and statistics to the adapter /proc file:
471 /proc/scsi/advansys[0...].
472 9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list.
473 This problem has been addressed with the SCSI mid-level changes
474 made in v1.3.89. The advansys_select_queue_depths() function
475 was added for the v1.3.89 changes.
477 1.6 (9/10/96):
478 1. Incorporate miscellaneous Asc Library bug fixes and new microcode.
480 1.7 (9/25/96):
481 1. Enable clustering and optimize the setting of the maximum number
482 of scatter gather elements for any particular board. Clustering
483 increases CPU utilization, but results in a relatively larger
484 increase in I/O throughput.
485 2. Improve the performance of the request queuing functions by
486 adding a last pointer to the queue structure.
487 3. Correct problems with reset and abort request handling that
488 could have hung or crashed Linux.
489 4. Add more information to the adapter /proc file:
490 /proc/scsi/advansys[0...].
491 5. Remove the request timeout issue form the driver issues list.
492 6. Miscellaneous documentation additions and changes.
494 1.8 (10/4/96):
495 1. Make changes to handle the new v2.1.0 kernel memory mapping
496 in which a kernel virtual address may not be equivalent to its
497 bus or DMA memory address.
498 2. Change abort and reset request handling to make it yet even
499 more robust.
500 3. Try to mitigate request starvation by sending ordered requests
501 to heavily loaded, tag queuing enabled devices.
502 4. Maintain statistics on request response time.
503 5. Add request response time statistics and other information to
504 the adapter /proc file: /proc/scsi/advansys[0...].
506 1.9 (10/21/96):
507 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
508 make use of mid-level SCSI driver device queue depth flow
509 control mechanism. This will eliminate aborts caused by a
510 device being unable to keep up with requests and eliminate
511 repeat busy or QUEUE FULL status returned by a device.
512 2. Incorporate miscellaneous Asc Library bug fixes.
513 3. To allow the driver to work in kernels with broken module
514 support set 'cmd_per_lun' if the driver is compiled as a
515 module. This change affects kernels v1.3.89 to present.
516 4. Remove PCI BIOS address from the driver banner. The PCI BIOS
517 is relocated by the motherboard BIOS and its new address can
518 not be determined by the driver.
519 5. Add mid-level SCSI queue depth information to the adapter
520 /proc file: /proc/scsi/advansys[0...].
522 2.0 (11/14/96):
523 1. Change allocation of global structures used for device
524 initialization to guarantee they are in DMA-able memory.
525 Previously when the driver was loaded as a module these
526 structures might not have been in DMA-able memory, causing
527 device initialization to fail.
529 2.1 (12/30/96):
530 1. In advansys_reset(), if the request is a synchronous reset
531 request, even if the request serial number has changed, then
532 complete the request.
533 2. Add Asc Library bug fixes including new microcode.
534 3. Clear inquiry buffer before using it.
535 4. Correct ifdef typo.
537 2.2 (1/15/97):
538 1. Add Asc Library bug fixes including new microcode.
539 2. Add synchronous data transfer rate information to the
540 adapter /proc file: /proc/scsi/advansys[0...].
541 3. Change ADVANSYS_DEBUG to be disabled by default. This
542 will reduce the size of the driver image, eliminate execution
543 overhead, and remove unneeded symbols from the kernel symbol
544 space that were previously added by the driver.
545 4. Add new compile-time option ADVANSYS_ASSERT for assertion
546 code that used to be defined within ADVANSYS_DEBUG. This
547 option is enabled by default.
549 2.8 (5/26/97):
550 1. Change version number to 2.8 to synchronize the Linux driver
551 version numbering with other AdvanSys drivers.
552 2. Reformat source files without tabs to present the same view
553 of the file to everyone regardless of the editor tab setting
554 being used.
555 3. Add Asc Library bug fixes.
557 3.1A (1/8/98):
558 1. Change version number to 3.1 to indicate that support for
559 Ultra-Wide adapters (ABP-940UW) is included in this release.
560 2. Add Asc Library (Narrow Board) bug fixes.
561 3. Report an underrun condition with the host status byte set
562 to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which
563 causes the underrun condition to be ignored. When Linux defines
564 its own DID_UNDERRUN the constant defined in this file can be
565 removed.
566 4. Add patch to AscWaitTixISRDone().
567 5. Add support for up to 16 different AdvanSys host adapter SCSI
568 channels in one system. This allows four cards with four channels
569 to be used in one system.
571 3.1B (1/9/98):
572 1. Handle that PCI register base addresses are not always page
573 aligned even though ioremap() requires that the address argument
574 be page aligned.
576 3.1C (1/10/98):
577 1. Update latest BIOS version checked for from the /proc file.
578 2. Don't set microcode SDTR variable at initialization. Instead
579 wait until device capabilities have been detected from an Inquiry
580 command.
582 3.1D (1/21/98):
583 1. Improve performance when the driver is compiled as module by
584 allowing up to 64 scatter-gather elements instead of 8.
586 3.1E (5/1/98):
587 1. Set time delay in AscWaitTixISRDone() to 1000 ms.
588 2. Include SMP locking changes.
589 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS
590 access functions.
591 4. Update board serial number printing.
592 5. Try allocating an IRQ both with and without the SA_INTERRUPT
593 flag set to allow IRQ sharing with drivers that do not set
594 the SA_INTERRUPT flag. Also display a more descriptive error
595 message if request_irq() fails.
596 6. Update to latest Asc and Adv Libraries.
598 3.2A (7/22/99):
599 1. Update Adv Library to 4.16 which includes support for
600 the ASC38C0800 (Ultra2/LVD) IC.
602 3.2B (8/23/99):
603 1. Correct PCI compile time option for v2.1.93 and greater
604 kernels, advansys_info() string, and debug compile time
605 option.
606 2. Correct DvcSleepMilliSecond() for v2.1.0 and greater
607 kernels. This caused an LVD detection/BIST problem problem
608 among other things.
609 3. Sort PCI cards by PCI Bus, Slot, Function ascending order
610 to be consistent with the BIOS.
611 4. Update to Asc Library S121 and Adv Library 5.2.
613 3.2C (8/24/99):
614 1. Correct PCI card detection bug introduced in 3.2B that
615 prevented PCI cards from being detected in kernels older
616 than v2.1.93.
618 3.2D (8/26/99):
619 1. Correct /proc device synchronous speed information display.
620 Also when re-negotiation is pending for a target device
621 note this condition with an * and footnote.
622 2. Correct initialization problem with Ultra-Wide cards that
623 have a pre-3.2 BIOS. A microcode variable changed locations
624 in 3.2 and greater BIOSes which caused WDTR to be attempted
625 erroneously with drives that don't support WDTR.
627 3.2E (8/30/99):
628 1. Fix compile error caused by v2.3.13 PCI structure change.
629 2. Remove field from ASCEEP_CONFIG that resulted in an EEPROM
630 checksum error for ISA cards.
631 3. Remove ASC_QUEUE_FLOW_CONTROL conditional code. The mid-level
632 SCSI changes that it depended on were never included in Linux.
634 3.2F (9/3/99):
635 1. Handle new initial function code added in v2.3.16 for all
636 driver versions.
638 3.2G (9/8/99):
639 1. Fix PCI board detection in v2.3.13 and greater kernels.
640 2. Fix comiple errors in v2.3.X with debugging enabled.
642 J. Known Problems/Fix List (XXX)
644 1. Need to add memory mapping workaround. Test the memory mapping.
645 If it doesn't work revert to I/O port access. Can a test be done
646 safely?
647 2. Handle an interrupt not working. Keep an interrupt counter in
648 the interrupt handler. In the timeout function if the interrupt
649 has not occurred then print a message and run in polled mode.
650 3. Allow bus type scanning order to be changed.
651 4. Need to add support for target mode commands, cf. CAM XPT.
652 5 Need to add support for new Linux SCSI error handling method.
653 6. Need to fix sti/cli code in Asc Library.
654 7. Need to fix abort code in Adv Library.
655 8. Reduce io_request_lock hold time.
656 9. Add big-endian support for Alpha.
658 K. Credits
660 Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
661 basis for the Linux v1.3.X changes which were included in the
662 1.2 release.
664 Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug
665 in advansys_biosparam() which was fixed in the 1.3 release.
667 Erik Ratcliffe <erik@caldera.com> has done testing of the
668 AdvanSys driver in the Caldera releases.
670 Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
671 AscWaitTixISRDone() which he found necessary to make the
672 driver work with a SCSI-1 disk.
674 Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide
675 support in the 3.1A driver.
677 Doug Gilbert <dgilbert@interlog.com> has made changes and
678 suggestions to improve the driver and done testing.
680 L. AdvanSys Contact Information
682 Mail: Advanced System Products, Inc.
683 1150 Ringwood Court
684 San Jose, CA 95131
685 Operator/Sales: 1-408-383-9400
686 FAX: 1-408-383-9612
687 Tech Support: 1-408-467-2930
688 Tech Support E-Mail: support@advansys.com
689 FTP Site: ftp.advansys.com (login: anonymous)
690 Web Site: http://www.advansys.com
696 * --- Linux Version
699 /* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
700 #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
702 #ifndef LINUX_VERSION_CODE
703 #include <linux/version.h>
704 #endif /* LINUX_VERSION_CODE */
708 * --- Linux Include Files
711 #include <linux/config.h>
712 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
713 #ifdef MODULE
714 #include <linux/module.h>
715 #endif /* MODULE */
716 #endif /* version >= v1.3.0 */
717 #include <linux/string.h>
718 #include <linux/sched.h>
719 #include <linux/kernel.h>
720 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
721 #include <linux/head.h>
722 #endif /* verions < v2.1.0 */
723 #include <linux/types.h>
724 #include <linux/ioport.h>
725 #include <linux/delay.h>
726 #include <linux/malloc.h>
727 #include <linux/mm.h>
728 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
729 #include <linux/proc_fs.h>
730 #endif /* version >= v1.3.0 */
731 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,23)
732 #include <linux/init.h>
733 #endif /* version >= v2.1.23 */
734 #include <asm/io.h>
735 #include <asm/system.h>
736 #include <asm/dma.h>
737 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
738 #include "../block/blk.h"
739 #else /* version >= v1.3.0 */
740 #include <linux/blk.h>
741 #include <linux/stat.h>
742 #endif /* version >= v1.3.0 */
743 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95)
744 #include <linux/spinlock.h>
745 #endif /* version >= 2.1.95 */
746 #include "scsi.h"
747 #include "hosts.h"
748 #include "sd.h"
749 #include "advansys.h"
750 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,93)
751 #ifdef CONFIG_PCI
752 #include <linux/pci.h>
753 #endif /* CONFIG_PCI */
754 #else /* version < v2.1.93 */
756 * For earlier than v2.1.93 the driver has its own PCI configuration.
757 * If PCI is not needed in a kernel before v2.1.93 this define can be
758 * turned-off to make the driver object smaller.
760 #define ASC_CONFIG_PCI
761 #endif /* version < v2.1.93 */
764 * If Linux eventually defines a DID_UNDERRUN, the constant here can be
765 * removed. The current value of zero for DID_UNDERRUN results in underrun
766 * conditions being ignored.
768 #define DID_UNDERRUN 0
772 * --- Driver Options
775 /* Enable driver assertions. */
776 #define ADVANSYS_ASSERT
778 /* Enable driver tracing. */
779 /* #define ADVANSYS_DEBUG */
782 * Because of no /proc to display them, statistics are disabled
783 * for versions prior to v1.3.0.
785 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
786 #undef ADVANSYS_STATS /* Disable statistics */
787 #else /* version >= v1.3.0 */
788 #define ADVANSYS_STATS /* Enable statistics. */
789 #endif /* version >= v1.3.0 */
793 * --- Debugging Header
796 #ifdef ADVANSYS_DEBUG
797 #define STATIC
798 #else /* ADVANSYS_DEBUG */
799 #define STATIC static
800 #endif /* ADVANSYS_DEBUG */
804 * --- Asc Library Constants and Macros
807 #define ASC_LIB_VERSION_MAJOR 1
808 #define ASC_LIB_VERSION_MINOR 24
809 #define ASC_LIB_SERIAL_NUMBER 121
811 typedef unsigned char uchar;
813 #ifndef NULL
814 #define NULL (0)
815 #endif
816 #ifndef TRUE
817 #define TRUE (1)
818 #endif
819 #ifndef FALSE
820 #define FALSE (0)
821 #endif
822 #define REG register
823 #define rchar REG __s8
824 #define rshort REG __s16
825 #define rint REG __s32
826 #define rlong REG __s32
827 #define ruchar REG __u8
828 #define rushort REG __u16
829 #define ruint REG __u32
830 #define rulong REG __u32
831 #define NULLPTR (void *)0
832 #define FNULLPTR (void *)0UL
833 #define EOF (-1)
834 #define EOS '\0'
835 #define ERR (-1)
836 #define UB_ERR (uchar)(0xFF)
837 #define UW_ERR (uint)(0xFFFF)
838 #define UL_ERR (ulong)(0xFFFFFFFFUL)
839 #define iseven_word(val) ((((uint)val) & (uint)0x0001) == 0)
840 #define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
841 #define toeven_word(val) (((uint)val) & (uint)0xFFFE)
842 #define biton(val, bits) (((uint)(val >> bits) & (uint)0x0001) != 0)
843 #define bitoff(val, bits) (((uint)(val >> bits) & (uint)0x0001) == 0)
844 #define lbiton(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) != 0)
845 #define lbitoff(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) == 0)
846 #define absh(val) ((val) < 0 ? -(val) : (val))
847 #define swapbyte(ch) ((((ch) << 4) | ((ch) >> 4)))
848 #ifndef GBYTE
849 #define GBYTE (0x40000000UL)
850 #endif
851 #ifndef MBYTE
852 #define MBYTE (0x100000UL)
853 #endif
854 #ifndef KBYTE
855 #define KBYTE (0x400)
856 #endif
857 #define HI_BYTE(x) (*((__u8 *)(&x)+1))
858 #define LO_BYTE(x) (*((__u8 *)&x))
859 #define HI_WORD(x) (*((__u16 *)(&x)+1))
860 #define LO_WORD(x) (*((__u16 *)&x))
861 #ifndef MAKEWORD
862 #define MAKEWORD(lo, hi) ((__u16) (((__u16) lo) | ((__u16) hi << 8)))
863 #endif
864 #ifndef MAKELONG
865 #define MAKELONG(lo, hi) ((__u32) (((__u32) lo) | ((__u32) hi << 16)))
866 #endif
867 #define SwapWords(dWord) ((__u32) ((dWord >> 16) | (dWord << 16)))
868 #define SwapBytes(word) ((__u16) ((word >> 8) | (word << 8)))
869 #define BigToLittle(dWord) ((__u32) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
870 #define LittleToBig(dWord) BigToLittle(dWord)
871 #define AscPCIConfigVendorIDRegister 0x0000
872 #define AscPCIConfigDeviceIDRegister 0x0002
873 #define AscPCIConfigCommandRegister 0x0004
874 #define AscPCIConfigStatusRegister 0x0006
875 #define AscPCIConfigRevisionIDRegister 0x0008
876 #define AscPCIConfigCacheSize 0x000C
877 #define AscPCIConfigLatencyTimer 0x000D
878 #define AscPCIIOBaseRegister 0x0010
879 #define AscPCICmdRegBits_IOMemBusMaster 0x0007
880 #define ASC_PCI_ID2BUS(id) ((id) & 0xFF)
881 #define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F)
882 #define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7)
883 #define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
884 #define ASC_PCI_VENDORID 0x10CD
885 #define ASC_PCI_DEVICEID_1200A 0x1100
886 #define ASC_PCI_DEVICEID_1200B 0x1200
887 #define ASC_PCI_DEVICEID_ULTRA 0x1300
888 #define ASC_PCI_REVISION_3150 0x02
889 #define ASC_PCI_REVISION_3050 0x03
891 #define ASC_DVCLIB_CALL_DONE (1)
892 #define ASC_DVCLIB_CALL_FAILED (0)
893 #define ASC_DVCLIB_CALL_ERROR (-1)
896 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
897 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
898 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
899 * SRB structure.
901 #define CC_VERY_LONG_SG_LIST 0
902 #define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
904 #define PortAddr unsigned short /* port address size */
905 #define Ptr2Func ulong
906 #define inp(port) inb(port)
907 #define inpw(port) inw(port)
908 #define inpl(port) inl(port)
909 #define outp(port, byte) outb((byte), (port))
910 #define outpw(port, word) outw((word), (port))
911 #define outpl(port, long) outl((long), (port))
912 #define ASC_MAX_SG_QUEUE 7
913 #define ASC_MAX_SG_LIST SG_ALL
915 #define ASC_CS_TYPE unsigned short
916 #ifndef asc_ptr_type
917 #define asc_ptr_type
918 #endif
920 #ifndef ASC_GET_PTR2FUNC
921 #define ASC_GET_PTR2FUNC(fun) (Ptr2Func)(fun)
922 #endif
923 #define FLIP_BYTE_NIBBLE(x) (((x<<4)& 0xFF) | (x>>4))
924 #define ASC_IS_ISA (0x0001)
925 #define ASC_IS_ISAPNP (0x0081)
926 #define ASC_IS_EISA (0x0002)
927 #define ASC_IS_PCI (0x0004)
928 #define ASC_IS_PCI_ULTRA (0x0104)
929 #define ASC_IS_PCMCIA (0x0008)
930 #define ASC_IS_MCA (0x0020)
931 #define ASC_IS_VL (0x0040)
932 #define ASC_ISA_PNP_PORT_ADDR (0x279)
933 #define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
934 #define ASC_IS_WIDESCSI_16 (0x0100)
935 #define ASC_IS_WIDESCSI_32 (0x0200)
936 #define ASC_IS_BIG_ENDIAN (0x8000)
937 #define ASC_CHIP_MIN_VER_VL (0x01)
938 #define ASC_CHIP_MAX_VER_VL (0x07)
939 #define ASC_CHIP_MIN_VER_PCI (0x09)
940 #define ASC_CHIP_MAX_VER_PCI (0x0F)
941 #define ASC_CHIP_VER_PCI_BIT (0x08)
942 #define ASC_CHIP_MIN_VER_ISA (0x11)
943 #define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
944 #define ASC_CHIP_MAX_VER_ISA (0x27)
945 #define ASC_CHIP_VER_ISA_BIT (0x30)
946 #define ASC_CHIP_VER_ISAPNP_BIT (0x20)
947 #define ASC_CHIP_VER_ASYN_BUG (0x21)
948 #define ASC_CHIP_VER_PCI 0x08
949 #define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
950 #define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
951 #define ASC_CHIP_MIN_VER_EISA (0x41)
952 #define ASC_CHIP_MAX_VER_EISA (0x47)
953 #define ASC_CHIP_VER_EISA_BIT (0x40)
954 #define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
955 #define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
956 #define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
957 #define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
958 #define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
959 #define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
960 #define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
961 #define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
962 #define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
963 #define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
964 #define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
965 #ifndef inpw_noswap
966 #define inpw_noswap(port) inpw(port)
967 #endif
968 #ifndef outpw_noswap
969 #define outpw_noswap(port, data) outpw(port, data)
970 #endif
971 #define ASC_SCSI_ID_BITS 3
972 #define ASC_SCSI_TIX_TYPE uchar
973 #define ASC_ALL_DEVICE_BIT_SET 0xFF
974 #ifdef ASC_WIDESCSI_16
975 #undef ASC_SCSI_ID_BITS
976 #define ASC_SCSI_ID_BITS 4
977 #define ASC_ALL_DEVICE_BIT_SET 0xFFFF
978 #endif
979 #ifdef ASC_WIDESCSI_32
980 #undef ASC_SCSI_ID_BITS
981 #define ASC_SCSI_ID_BITS 5
982 #define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL
983 #endif
984 #if ASC_SCSI_ID_BITS == 3
985 #define ASC_SCSI_BIT_ID_TYPE uchar
986 #define ASC_MAX_TID 7
987 #define ASC_MAX_LUN 7
988 #define ASC_SCSI_WIDTH_BIT_SET 0xFF
989 #elif ASC_SCSI_ID_BITS == 4
990 #define ASC_SCSI_BIT_ID_TYPE ushort
991 #define ASC_MAX_TID 15
992 #define ASC_MAX_LUN 7
993 #define ASC_SCSI_WIDTH_BIT_SET 0xFFFF
994 #elif ASC_SCSI_ID_BITS == 5
995 #define ASC_SCSI_BIT_ID_TYPE ulong
996 #define ASC_MAX_TID 31
997 #define ASC_MAX_LUN 7
998 #define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF
999 #else
1000 #error ASC_SCSI_ID_BITS definition is wrong
1001 #endif
1002 #define ASC_MAX_SENSE_LEN 32
1003 #define ASC_MIN_SENSE_LEN 14
1004 #define ASC_MAX_CDB_LEN 12
1005 #define ASC_SCSI_RESET_HOLD_TIME_US 60
1006 #define SCSICMD_TestUnitReady 0x00
1007 #define SCSICMD_Rewind 0x01
1008 #define SCSICMD_Rezero 0x01
1009 #define SCSICMD_RequestSense 0x03
1010 #define SCSICMD_Format 0x04
1011 #define SCSICMD_FormatUnit 0x04
1012 #define SCSICMD_Read6 0x08
1013 #define SCSICMD_Write6 0x0A
1014 #define SCSICMD_Seek6 0x0B
1015 #define SCSICMD_Inquiry 0x12
1016 #define SCSICMD_Verify6 0x13
1017 #define SCSICMD_ModeSelect6 0x15
1018 #define SCSICMD_ModeSense6 0x1A
1019 #define SCSICMD_StartStopUnit 0x1B
1020 #define SCSICMD_LoadUnloadTape 0x1B
1021 #define SCSICMD_ReadCapacity 0x25
1022 #define SCSICMD_Read10 0x28
1023 #define SCSICMD_Write10 0x2A
1024 #define SCSICMD_Seek10 0x2B
1025 #define SCSICMD_Erase10 0x2C
1026 #define SCSICMD_WriteAndVerify10 0x2E
1027 #define SCSICMD_Verify10 0x2F
1028 #define SCSICMD_WriteBuffer 0x3B
1029 #define SCSICMD_ReadBuffer 0x3C
1030 #define SCSICMD_ReadLong 0x3E
1031 #define SCSICMD_WriteLong 0x3F
1032 #define SCSICMD_ReadTOC 0x43
1033 #define SCSICMD_ReadHeader 0x44
1034 #define SCSICMD_ModeSelect10 0x55
1035 #define SCSICMD_ModeSense10 0x5A
1036 #define SCSI_TYPE_DASD 0x00
1037 #define SCSI_TYPE_SASD 0x01
1038 #define SCSI_TYPE_PRN 0x02
1039 #define SCSI_TYPE_PROC 0x03
1040 #define SCSI_TYPE_WORM 0x04
1041 #define SCSI_TYPE_CDROM 0x05
1042 #define SCSI_TYPE_SCANNER 0x06
1043 #define SCSI_TYPE_OPTMEM 0x07
1044 #define SCSI_TYPE_MED_CHG 0x08
1045 #define SCSI_TYPE_COMM 0x09
1046 #define SCSI_TYPE_UNKNOWN 0x1F
1047 #define SCSI_TYPE_NO_DVC 0xFF
1048 #define INQ_CLOCKING_ST_ONLY 0x0
1049 #define INQ_CLOCKING_DT_ONLY 0x1
1050 #define INQ_CLOCKING_ST_AND_DT 0x3
1051 #define ASC_SCSIDIR_NOCHK 0x00
1052 #define ASC_SCSIDIR_T2H 0x08
1053 #define ASC_SCSIDIR_H2T 0x10
1054 #define ASC_SCSIDIR_NODATA 0x18
1055 #define SCSI_SENKEY_NO_SENSE 0x00
1056 #define SCSI_SENKEY_UNDEFINED 0x01
1057 #define SCSI_SENKEY_NOT_READY 0x02
1058 #define SCSI_SENKEY_MEDIUM_ERR 0x03
1059 #define SCSI_SENKEY_HW_ERR 0x04
1060 #define SCSI_SENKEY_ILLEGAL 0x05
1061 #define SCSI_SENKEY_ATTENTION 0x06
1062 #define SCSI_SENKEY_PROTECTED 0x07
1063 #define SCSI_SENKEY_BLANK 0x08
1064 #define SCSI_SENKEY_V_UNIQUE 0x09
1065 #define SCSI_SENKEY_CPY_ABORT 0x0A
1066 #define SCSI_SENKEY_ABORT 0x0B
1067 #define SCSI_SENKEY_EQUAL 0x0C
1068 #define SCSI_SENKEY_VOL_OVERFLOW 0x0D
1069 #define SCSI_SENKEY_MISCOMP 0x0E
1070 #define SCSI_SENKEY_RESERVED 0x0F
1071 #define SCSI_ASC_NOMEDIA 0x3A
1072 #define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
1073 #define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
1074 #define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
1075 #define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
1076 #define SS_GOOD 0x00
1077 #define SS_CHK_CONDITION 0x02
1078 #define SS_CONDITION_MET 0x04
1079 #define SS_TARGET_BUSY 0x08
1080 #define SS_INTERMID 0x10
1081 #define SS_INTERMID_COND_MET 0x14
1082 #define SS_RSERV_CONFLICT 0x18
1083 #define SS_CMD_TERMINATED 0x22
1084 #define SS_QUEUE_FULL 0x28
1085 #define MS_CMD_DONE 0x00
1086 #define MS_EXTEND 0x01
1087 #define MS_SDTR_LEN 0x03
1088 #define MS_SDTR_CODE 0x01
1089 #define MS_WDTR_LEN 0x02
1090 #define MS_WDTR_CODE 0x03
1091 #define MS_MDP_LEN 0x05
1092 #define MS_MDP_CODE 0x00
1093 #define M1_SAVE_DATA_PTR 0x02
1094 #define M1_RESTORE_PTRS 0x03
1095 #define M1_DISCONNECT 0x04
1096 #define M1_INIT_DETECTED_ERR 0x05
1097 #define M1_ABORT 0x06
1098 #define M1_MSG_REJECT 0x07
1099 #define M1_NO_OP 0x08
1100 #define M1_MSG_PARITY_ERR 0x09
1101 #define M1_LINK_CMD_DONE 0x0A
1102 #define M1_LINK_CMD_DONE_WFLAG 0x0B
1103 #define M1_BUS_DVC_RESET 0x0C
1104 #define M1_ABORT_TAG 0x0D
1105 #define M1_CLR_QUEUE 0x0E
1106 #define M1_INIT_RECOVERY 0x0F
1107 #define M1_RELEASE_RECOVERY 0x10
1108 #define M1_KILL_IO_PROC 0x11
1109 #define M2_QTAG_MSG_SIMPLE 0x20
1110 #define M2_QTAG_MSG_HEAD 0x21
1111 #define M2_QTAG_MSG_ORDERED 0x22
1112 #define M2_IGNORE_WIDE_RESIDUE 0x23
1114 typedef struct {
1115 uchar peri_dvc_type:5;
1116 uchar peri_qualifier:3;
1117 } ASC_SCSI_INQ0;
1119 typedef struct {
1120 uchar dvc_type_modifier:7;
1121 uchar rmb:1;
1122 } ASC_SCSI_INQ1;
1124 typedef struct {
1125 uchar ansi_apr_ver:3;
1126 uchar ecma_ver:3;
1127 uchar iso_ver:2;
1128 } ASC_SCSI_INQ2;
1130 typedef struct {
1131 uchar rsp_data_fmt:4;
1132 uchar res:2;
1133 uchar TemIOP:1;
1134 uchar aenc:1;
1135 } ASC_SCSI_INQ3;
1137 typedef struct {
1138 uchar StfRe:1;
1139 uchar CmdQue:1;
1140 uchar Reserved:1;
1141 uchar Linked:1;
1142 uchar Sync:1;
1143 uchar WBus16:1;
1144 uchar WBus32:1;
1145 uchar RelAdr:1;
1146 } ASC_SCSI_INQ7;
1148 typedef struct {
1149 ASC_SCSI_INQ0 byte0;
1150 ASC_SCSI_INQ1 byte1;
1151 ASC_SCSI_INQ2 byte2;
1152 ASC_SCSI_INQ3 byte3;
1153 uchar add_len;
1154 uchar res1;
1155 uchar res2;
1156 ASC_SCSI_INQ7 byte7;
1157 uchar vendor_id[8];
1158 uchar product_id[16];
1159 uchar product_rev_level[4];
1160 } ASC_SCSI_INQUIRY;
1162 typedef struct asc_req_sense {
1163 uchar err_code:7;
1164 uchar info_valid:1;
1165 uchar segment_no;
1166 uchar sense_key:4;
1167 uchar reserved_bit:1;
1168 uchar sense_ILI:1;
1169 uchar sense_EOM:1;
1170 uchar file_mark:1;
1171 uchar info1[4];
1172 uchar add_sense_len;
1173 uchar cmd_sp_info[4];
1174 uchar asc;
1175 uchar ascq;
1176 uchar fruc;
1177 uchar sks_byte0:7;
1178 uchar sks_valid:1;
1179 uchar sks_bytes[2];
1180 uchar notused[2];
1181 uchar ex_sense_code;
1182 uchar info2[4];
1183 } ASC_REQ_SENSE;
1185 #define ASC_SG_LIST_PER_Q 7
1186 #define QS_FREE 0x00
1187 #define QS_READY 0x01
1188 #define QS_DISC1 0x02
1189 #define QS_DISC2 0x04
1190 #define QS_BUSY 0x08
1191 #define QS_ABORTED 0x40
1192 #define QS_DONE 0x80
1193 #define QC_NO_CALLBACK 0x01
1194 #define QC_SG_SWAP_QUEUE 0x02
1195 #define QC_SG_HEAD 0x04
1196 #define QC_DATA_IN 0x08
1197 #define QC_DATA_OUT 0x10
1198 #define QC_URGENT 0x20
1199 #define QC_MSG_OUT 0x40
1200 #define QC_REQ_SENSE 0x80
1201 #define QCSG_SG_XFER_LIST 0x02
1202 #define QCSG_SG_XFER_MORE 0x04
1203 #define QCSG_SG_XFER_END 0x08
1204 #define QD_IN_PROGRESS 0x00
1205 #define QD_NO_ERROR 0x01
1206 #define QD_ABORTED_BY_HOST 0x02
1207 #define QD_WITH_ERROR 0x04
1208 #define QD_INVALID_REQUEST 0x80
1209 #define QD_INVALID_HOST_NUM 0x81
1210 #define QD_INVALID_DEVICE 0x82
1211 #define QD_ERR_INTERNAL 0xFF
1212 #define QHSTA_NO_ERROR 0x00
1213 #define QHSTA_M_SEL_TIMEOUT 0x11
1214 #define QHSTA_M_DATA_OVER_RUN 0x12
1215 #define QHSTA_M_DATA_UNDER_RUN 0x12
1216 #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
1217 #define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
1218 #define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1219 #define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
1220 #define QHSTA_D_HOST_ABORT_FAILED 0x23
1221 #define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
1222 #define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1223 #define QHSTA_D_ASPI_NO_BUF_POOL 0x26
1224 #define QHSTA_M_WTM_TIMEOUT 0x41
1225 #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
1226 #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
1227 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1228 #define QHSTA_M_TARGET_STATUS_BUSY 0x45
1229 #define QHSTA_M_BAD_TAG_CODE 0x46
1230 #define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
1231 #define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
1232 #define QHSTA_D_LRAM_CMP_ERROR 0x81
1233 #define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1234 #define ASC_FLAG_SCSIQ_REQ 0x01
1235 #define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1236 #define ASC_FLAG_BIOS_ASYNC_IO 0x04
1237 #define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1238 #define ASC_FLAG_WIN16 0x10
1239 #define ASC_FLAG_WIN32 0x20
1240 #define ASC_FLAG_ISA_OVER_16MB 0x40
1241 #define ASC_FLAG_DOS_VM_CALLBACK 0x80
1242 #define ASC_TAG_FLAG_EXTRA_BYTES 0x10
1243 #define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
1244 #define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
1245 #define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
1246 #define ASC_SCSIQ_CPY_BEG 4
1247 #define ASC_SCSIQ_SGHD_CPY_BEG 2
1248 #define ASC_SCSIQ_B_FWD 0
1249 #define ASC_SCSIQ_B_BWD 1
1250 #define ASC_SCSIQ_B_STATUS 2
1251 #define ASC_SCSIQ_B_QNO 3
1252 #define ASC_SCSIQ_B_CNTL 4
1253 #define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1254 #define ASC_SCSIQ_D_DATA_ADDR 8
1255 #define ASC_SCSIQ_D_DATA_CNT 12
1256 #define ASC_SCSIQ_B_SENSE_LEN 20
1257 #define ASC_SCSIQ_DONE_INFO_BEG 22
1258 #define ASC_SCSIQ_D_SRBPTR 22
1259 #define ASC_SCSIQ_B_TARGET_IX 26
1260 #define ASC_SCSIQ_B_CDB_LEN 28
1261 #define ASC_SCSIQ_B_TAG_CODE 29
1262 #define ASC_SCSIQ_W_VM_ID 30
1263 #define ASC_SCSIQ_DONE_STATUS 32
1264 #define ASC_SCSIQ_HOST_STATUS 33
1265 #define ASC_SCSIQ_SCSI_STATUS 34
1266 #define ASC_SCSIQ_CDB_BEG 36
1267 #define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1268 #define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1269 #define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
1270 #define ASC_SCSIQ_B_SG_WK_QP 49
1271 #define ASC_SCSIQ_B_SG_WK_IX 50
1272 #define ASC_SCSIQ_W_ALT_DC1 52
1273 #define ASC_SCSIQ_B_LIST_CNT 6
1274 #define ASC_SCSIQ_B_CUR_LIST_CNT 7
1275 #define ASC_SGQ_B_SG_CNTL 4
1276 #define ASC_SGQ_B_SG_HEAD_QP 5
1277 #define ASC_SGQ_B_SG_LIST_CNT 6
1278 #define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1279 #define ASC_SGQ_LIST_BEG 8
1280 #define ASC_DEF_SCSI1_QNG 4
1281 #define ASC_MAX_SCSI1_QNG 4
1282 #define ASC_DEF_SCSI2_QNG 16
1283 #define ASC_MAX_SCSI2_QNG 32
1284 #define ASC_TAG_CODE_MASK 0x23
1285 #define ASC_STOP_REQ_RISC_STOP 0x01
1286 #define ASC_STOP_ACK_RISC_STOP 0x03
1287 #define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1288 #define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1289 #define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1290 #define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
1291 #define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
1292 #define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
1293 #define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
1294 #define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
1295 #define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
1296 #define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
1298 typedef struct asc_scisq_1 {
1299 uchar status;
1300 uchar q_no;
1301 uchar cntl;
1302 uchar sg_queue_cnt;
1303 uchar target_id;
1304 uchar target_lun;
1305 ulong data_addr;
1306 ulong data_cnt;
1307 ulong sense_addr;
1308 uchar sense_len;
1309 uchar extra_bytes;
1310 } ASC_SCSIQ_1;
1312 typedef struct asc_scisq_2 {
1313 ulong srb_ptr;
1314 uchar target_ix;
1315 uchar flag;
1316 uchar cdb_len;
1317 uchar tag_code;
1318 ushort vm_id;
1319 } ASC_SCSIQ_2;
1321 typedef struct asc_scsiq_3 {
1322 uchar done_stat;
1323 uchar host_stat;
1324 uchar scsi_stat;
1325 uchar scsi_msg;
1326 } ASC_SCSIQ_3;
1328 typedef struct asc_scsiq_4 {
1329 uchar cdb[ASC_MAX_CDB_LEN];
1330 uchar y_first_sg_list_qp;
1331 uchar y_working_sg_qp;
1332 uchar y_working_sg_ix;
1333 uchar y_res;
1334 ushort x_req_count;
1335 ushort x_reconnect_rtn;
1336 ulong x_saved_data_addr;
1337 ulong x_saved_data_cnt;
1338 } ASC_SCSIQ_4;
1340 typedef struct asc_q_done_info {
1341 ASC_SCSIQ_2 d2;
1342 ASC_SCSIQ_3 d3;
1343 uchar q_status;
1344 uchar q_no;
1345 uchar cntl;
1346 uchar sense_len;
1347 uchar extra_bytes;
1348 uchar res;
1349 ulong remain_bytes;
1350 } ASC_QDONE_INFO;
1352 typedef struct asc_sg_list {
1353 ulong addr;
1354 ulong bytes;
1355 } ASC_SG_LIST;
1357 typedef struct asc_sg_head {
1358 ushort entry_cnt;
1359 ushort queue_cnt;
1360 ushort entry_to_copy;
1361 ushort res;
1362 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
1363 } ASC_SG_HEAD;
1365 #define ASC_MIN_SG_LIST 2
1367 typedef struct asc_min_sg_head {
1368 ushort entry_cnt;
1369 ushort queue_cnt;
1370 ushort entry_to_copy;
1371 ushort res;
1372 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
1373 } ASC_MIN_SG_HEAD;
1375 #define QCX_SORT (0x0001)
1376 #define QCX_COALEASE (0x0002)
1378 typedef struct asc_scsi_q {
1379 ASC_SCSIQ_1 q1;
1380 ASC_SCSIQ_2 q2;
1381 uchar *cdbptr;
1382 ASC_SG_HEAD *sg_head;
1383 ushort remain_sg_entry_cnt;
1384 ushort next_sg_index;
1385 } ASC_SCSI_Q;
1387 typedef struct asc_scsi_req_q {
1388 ASC_SCSIQ_1 r1;
1389 ASC_SCSIQ_2 r2;
1390 uchar *cdbptr;
1391 ASC_SG_HEAD *sg_head;
1392 uchar *sense_ptr;
1393 ASC_SCSIQ_3 r3;
1394 uchar cdb[ASC_MAX_CDB_LEN];
1395 uchar sense[ASC_MIN_SENSE_LEN];
1396 } ASC_SCSI_REQ_Q;
1398 typedef struct asc_scsi_bios_req_q {
1399 ASC_SCSIQ_1 r1;
1400 ASC_SCSIQ_2 r2;
1401 uchar *cdbptr;
1402 ASC_SG_HEAD *sg_head;
1403 uchar *sense_ptr;
1404 ASC_SCSIQ_3 r3;
1405 uchar cdb[ASC_MAX_CDB_LEN];
1406 uchar sense[ASC_MIN_SENSE_LEN];
1407 } ASC_SCSI_BIOS_REQ_Q;
1409 typedef struct asc_risc_q {
1410 uchar fwd;
1411 uchar bwd;
1412 ASC_SCSIQ_1 i1;
1413 ASC_SCSIQ_2 i2;
1414 ASC_SCSIQ_3 i3;
1415 ASC_SCSIQ_4 i4;
1416 } ASC_RISC_Q;
1418 typedef struct asc_sg_list_q {
1419 uchar seq_no;
1420 uchar q_no;
1421 uchar cntl;
1422 uchar sg_head_qp;
1423 uchar sg_list_cnt;
1424 uchar sg_cur_list_cnt;
1425 } ASC_SG_LIST_Q;
1427 typedef struct asc_risc_sg_list_q {
1428 uchar fwd;
1429 uchar bwd;
1430 ASC_SG_LIST_Q sg;
1431 ASC_SG_LIST sg_list[7];
1432 } ASC_RISC_SG_LIST_Q;
1434 #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1435 #define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1436 #define ASCQ_ERR_NO_ERROR 0
1437 #define ASCQ_ERR_IO_NOT_FOUND 1
1438 #define ASCQ_ERR_LOCAL_MEM 2
1439 #define ASCQ_ERR_CHKSUM 3
1440 #define ASCQ_ERR_START_CHIP 4
1441 #define ASCQ_ERR_INT_TARGET_ID 5
1442 #define ASCQ_ERR_INT_LOCAL_MEM 6
1443 #define ASCQ_ERR_HALT_RISC 7
1444 #define ASCQ_ERR_GET_ASPI_ENTRY 8
1445 #define ASCQ_ERR_CLOSE_ASPI 9
1446 #define ASCQ_ERR_HOST_INQUIRY 0x0A
1447 #define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1448 #define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1449 #define ASCQ_ERR_Q_STATUS 0x0D
1450 #define ASCQ_ERR_WR_SCSIQ 0x0E
1451 #define ASCQ_ERR_PC_ADDR 0x0F
1452 #define ASCQ_ERR_SYN_OFFSET 0x10
1453 #define ASCQ_ERR_SYN_XFER_TIME 0x11
1454 #define ASCQ_ERR_LOCK_DMA 0x12
1455 #define ASCQ_ERR_UNLOCK_DMA 0x13
1456 #define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1457 #define ASCQ_ERR_MICRO_CODE_HALT 0x15
1458 #define ASCQ_ERR_SET_LRAM_ADDR 0x16
1459 #define ASCQ_ERR_CUR_QNG 0x17
1460 #define ASCQ_ERR_SG_Q_LINKS 0x18
1461 #define ASCQ_ERR_SCSIQ_PTR 0x19
1462 #define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1463 #define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1464 #define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1465 #define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1466 #define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1467 #define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1468 #define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1469 #define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1470 #define ASCQ_ERR_SEND_SCSI_Q 0x22
1471 #define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1472 #define ASCQ_ERR_RESET_SDTR 0x24
1473 #define ASC_WARN_NO_ERROR 0x0000
1474 #define ASC_WARN_IO_PORT_ROTATE 0x0001
1475 #define ASC_WARN_EEPROM_CHKSUM 0x0002
1476 #define ASC_WARN_IRQ_MODIFIED 0x0004
1477 #define ASC_WARN_AUTO_CONFIG 0x0008
1478 #define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1479 #define ASC_WARN_EEPROM_RECOVER 0x0020
1480 #define ASC_WARN_CFG_MSW_RECOVER 0x0040
1481 #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
1482 #define ASC_IERR_WRITE_EEPROM 0x0001
1483 #define ASC_IERR_MCODE_CHKSUM 0x0002
1484 #define ASC_IERR_SET_PC_ADDR 0x0004
1485 #define ASC_IERR_START_STOP_CHIP 0x0008
1486 #define ASC_IERR_IRQ_NO 0x0010
1487 #define ASC_IERR_SET_IRQ_NO 0x0020
1488 #define ASC_IERR_CHIP_VERSION 0x0040
1489 #define ASC_IERR_SET_SCSI_ID 0x0080
1490 #define ASC_IERR_GET_PHY_ADDR 0x0100
1491 #define ASC_IERR_BAD_SIGNATURE 0x0200
1492 #define ASC_IERR_NO_BUS_TYPE 0x0400
1493 #define ASC_IERR_SCAM 0x0800
1494 #define ASC_IERR_SET_SDTR 0x1000
1495 #define ASC_IERR_RW_LRAM 0x8000
1496 #define ASC_DEF_IRQ_NO 10
1497 #define ASC_MAX_IRQ_NO 15
1498 #define ASC_MIN_IRQ_NO 10
1499 #define ASC_MIN_REMAIN_Q (0x02)
1500 #define ASC_DEF_MAX_TOTAL_QNG (0xF0)
1501 #define ASC_MIN_TAG_Q_PER_DVC (0x04)
1502 #define ASC_DEF_TAG_Q_PER_DVC (0x04)
1503 #define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1504 #define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
1505 #define ASC_MAX_TOTAL_QNG 240
1506 #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
1507 #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
1508 #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1509 #define ASC_MAX_INRAM_TAG_QNG 16
1510 #define ASC_IOADR_TABLE_MAX_IX 11
1511 #define ASC_IOADR_GAP 0x10
1512 #define ASC_SEARCH_IOP_GAP 0x10
1513 #define ASC_MIN_IOP_ADDR (PortAddr)0x0100
1514 #define ASC_MAX_IOP_ADDR (PortAddr)0x3F0
1515 #define ASC_IOADR_1 (PortAddr)0x0110
1516 #define ASC_IOADR_2 (PortAddr)0x0130
1517 #define ASC_IOADR_3 (PortAddr)0x0150
1518 #define ASC_IOADR_4 (PortAddr)0x0190
1519 #define ASC_IOADR_5 (PortAddr)0x0210
1520 #define ASC_IOADR_6 (PortAddr)0x0230
1521 #define ASC_IOADR_7 (PortAddr)0x0250
1522 #define ASC_IOADR_8 (PortAddr)0x0330
1523 #define ASC_IOADR_DEF ASC_IOADR_8
1524 #define ASC_LIB_SCSIQ_WK_SP 256
1525 #define ASC_MAX_SYN_XFER_NO 16
1526 #define ASC_SYN_MAX_OFFSET 0x0F
1527 #define ASC_DEF_SDTR_OFFSET 0x0F
1528 #define ASC_DEF_SDTR_INDEX 0x00
1529 #define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
1530 #define SYN_XFER_NS_0 25
1531 #define SYN_XFER_NS_1 30
1532 #define SYN_XFER_NS_2 35
1533 #define SYN_XFER_NS_3 40
1534 #define SYN_XFER_NS_4 50
1535 #define SYN_XFER_NS_5 60
1536 #define SYN_XFER_NS_6 70
1537 #define SYN_XFER_NS_7 85
1538 #define SYN_ULTRA_XFER_NS_0 12
1539 #define SYN_ULTRA_XFER_NS_1 19
1540 #define SYN_ULTRA_XFER_NS_2 25
1541 #define SYN_ULTRA_XFER_NS_3 32
1542 #define SYN_ULTRA_XFER_NS_4 38
1543 #define SYN_ULTRA_XFER_NS_5 44
1544 #define SYN_ULTRA_XFER_NS_6 50
1545 #define SYN_ULTRA_XFER_NS_7 57
1546 #define SYN_ULTRA_XFER_NS_8 63
1547 #define SYN_ULTRA_XFER_NS_9 69
1548 #define SYN_ULTRA_XFER_NS_10 75
1549 #define SYN_ULTRA_XFER_NS_11 82
1550 #define SYN_ULTRA_XFER_NS_12 88
1551 #define SYN_ULTRA_XFER_NS_13 94
1552 #define SYN_ULTRA_XFER_NS_14 100
1553 #define SYN_ULTRA_XFER_NS_15 107
1555 typedef struct ext_msg {
1556 uchar msg_type;
1557 uchar msg_len;
1558 uchar msg_req;
1559 union {
1560 struct {
1561 uchar sdtr_xfer_period;
1562 uchar sdtr_req_ack_offset;
1563 } sdtr;
1564 struct {
1565 uchar wdtr_width;
1566 } wdtr;
1567 struct {
1568 uchar mdp_b3;
1569 uchar mdp_b2;
1570 uchar mdp_b1;
1571 uchar mdp_b0;
1572 } mdp;
1573 } u_ext_msg;
1574 uchar res;
1575 } EXT_MSG;
1577 #define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
1578 #define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
1579 #define wdtr_width u_ext_msg.wdtr.wdtr_width
1580 #define mdp_b3 u_ext_msg.mdp_b3
1581 #define mdp_b2 u_ext_msg.mdp_b2
1582 #define mdp_b1 u_ext_msg.mdp_b1
1583 #define mdp_b0 u_ext_msg.mdp_b0
1585 typedef struct asc_dvc_cfg {
1586 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1587 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1588 ASC_SCSI_BIT_ID_TYPE disc_enable;
1589 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
1590 uchar chip_scsi_id:4;
1591 uchar isa_dma_speed:4;
1592 uchar isa_dma_channel;
1593 uchar chip_version;
1594 ushort pci_device_id;
1595 ushort lib_serial_no;
1596 ushort lib_version;
1597 ushort mcode_date;
1598 ushort mcode_version;
1599 uchar max_tag_qng[ASC_MAX_TID + 1];
1600 uchar *overrun_buf;
1601 uchar sdtr_period_offset[ASC_MAX_TID + 1];
1602 ushort pci_slot_info;
1603 uchar adapter_info[6];
1604 } ASC_DVC_CFG;
1606 #define ASC_DEF_DVC_CNTL 0xFFFF
1607 #define ASC_DEF_CHIP_SCSI_ID 7
1608 #define ASC_DEF_ISA_DMA_SPEED 4
1609 #define ASC_INIT_STATE_NULL 0x0000
1610 #define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1611 #define ASC_INIT_STATE_END_GET_CFG 0x0002
1612 #define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1613 #define ASC_INIT_STATE_END_SET_CFG 0x0008
1614 #define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1615 #define ASC_INIT_STATE_END_LOAD_MC 0x0020
1616 #define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1617 #define ASC_INIT_STATE_END_INQUIRY 0x0080
1618 #define ASC_INIT_RESET_SCSI_DONE 0x0100
1619 #define ASC_INIT_STATE_WITHOUT_EEP 0x8000
1620 #define ASC_PCI_DEVICE_ID_REV_A 0x1100
1621 #define ASC_PCI_DEVICE_ID_REV_B 0x1200
1622 #define ASC_BUG_FIX_IF_NOT_DWB 0x0001
1623 #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
1624 #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1625 #define ASC_MIN_TAGGED_CMD 7
1626 #define ASC_MAX_SCSI_RESET_WAIT 30
1628 typedef struct asc_dvc_var {
1629 PortAddr iop_base;
1630 ushort err_code;
1631 ushort dvc_cntl;
1632 ushort bug_fix_cntl;
1633 ushort bus_type;
1634 Ptr2Func isr_callback;
1635 Ptr2Func exe_callback;
1636 ASC_SCSI_BIT_ID_TYPE init_sdtr;
1637 ASC_SCSI_BIT_ID_TYPE sdtr_done;
1638 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1639 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1640 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1641 ASC_SCSI_BIT_ID_TYPE start_motor;
1642 uchar scsi_reset_wait;
1643 uchar chip_no;
1644 char is_in_int;
1645 uchar max_total_qng;
1646 uchar cur_total_qng;
1647 uchar in_critical_cnt;
1648 uchar irq_no;
1649 uchar last_q_shortage;
1650 ushort init_state;
1651 uchar cur_dvc_qng[ASC_MAX_TID + 1];
1652 uchar max_dvc_qng[ASC_MAX_TID + 1];
1653 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
1654 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
1655 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
1656 ASC_DVC_CFG *cfg;
1657 Ptr2Func saved_ptr2func;
1658 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
1659 char redo_scam;
1660 ushort res2;
1661 uchar dos_int13_table[ASC_MAX_TID + 1];
1662 ulong max_dma_count;
1663 ASC_SCSI_BIT_ID_TYPE no_scam;
1664 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1665 uchar max_sdtr_index;
1666 uchar host_init_sdtr_index;
1667 ulong drv_ptr;
1668 ulong uc_break;
1669 ulong res7;
1670 ulong res8;
1671 } ASC_DVC_VAR;
1673 typedef int (* ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO *);
1674 typedef int (* ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
1676 typedef struct asc_dvc_inq_info {
1677 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1678 } ASC_DVC_INQ_INFO;
1680 typedef struct asc_cap_info {
1681 ulong lba;
1682 ulong blk_size;
1683 } ASC_CAP_INFO;
1685 typedef struct asc_cap_info_array {
1686 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1687 } ASC_CAP_INFO_ARRAY;
1689 #define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
1690 #define ASC_MCNTL_NULL_TARGET (ushort)0x0002
1691 #define ASC_CNTL_INITIATOR (ushort)0x0001
1692 #define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
1693 #define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
1694 #define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
1695 #define ASC_CNTL_NO_SCAM (ushort)0x0010
1696 #define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
1697 #define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
1698 #define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
1699 #define ASC_CNTL_RESET_SCSI (ushort)0x0200
1700 #define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
1701 #define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
1702 #define ASC_CNTL_SCSI_PARITY (ushort)0x1000
1703 #define ASC_CNTL_BURST_MODE (ushort)0x2000
1704 #define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
1705 #define ASC_EEP_DVC_CFG_BEG_VL 2
1706 #define ASC_EEP_MAX_DVC_ADDR_VL 15
1707 #define ASC_EEP_DVC_CFG_BEG 32
1708 #define ASC_EEP_MAX_DVC_ADDR 45
1709 #define ASC_EEP_DEFINED_WORDS 10
1710 #define ASC_EEP_MAX_ADDR 63
1711 #define ASC_EEP_RES_WORDS 0
1712 #define ASC_EEP_MAX_RETRY 20
1713 #define ASC_MAX_INIT_BUSY_RETRY 8
1714 #define ASC_EEP_ISA_PNP_WSIZE 16
1716 typedef struct asceep_config {
1717 ushort cfg_lsw;
1718 ushort cfg_msw;
1719 uchar init_sdtr;
1720 uchar disc_enable;
1721 uchar use_cmd_qng;
1722 uchar start_motor;
1723 uchar max_total_qng;
1724 uchar max_tag_qng;
1725 uchar bios_scan;
1726 uchar power_up_wait;
1727 uchar no_scam;
1728 uchar chip_scsi_id:4;
1729 uchar isa_dma_speed:4;
1730 uchar dos_int13_table[ASC_MAX_TID + 1];
1731 uchar adapter_info[6];
1732 ushort cntl;
1733 ushort chksum;
1734 } ASCEEP_CONFIG;
1736 #define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
1737 #define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
1738 #define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
1740 #define ASC_EEP_CMD_READ 0x80
1741 #define ASC_EEP_CMD_WRITE 0x40
1742 #define ASC_EEP_CMD_WRITE_ABLE 0x30
1743 #define ASC_EEP_CMD_WRITE_DISABLE 0x00
1744 #define ASC_OVERRUN_BSIZE 0x00000048UL
1745 #define ASC_CTRL_BREAK_ONCE 0x0001
1746 #define ASC_CTRL_BREAK_STAY_IDLE 0x0002
1747 #define ASCV_MSGOUT_BEG 0x0000
1748 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1749 #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1750 #define ASCV_BREAK_SAVED_CODE (ushort)0x0006
1751 #define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1752 #define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1753 #define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1754 #define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1755 #define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1756 #define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
1757 #define ASCV_BREAK_ADDR (ushort)0x0028
1758 #define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
1759 #define ASCV_BREAK_CONTROL (ushort)0x002C
1760 #define ASCV_BREAK_HIT_COUNT (ushort)0x002E
1762 #define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
1763 #define ASCV_MCODE_CHKSUM_W (ushort)0x0032
1764 #define ASCV_MCODE_SIZE_W (ushort)0x0034
1765 #define ASCV_STOP_CODE_B (ushort)0x0036
1766 #define ASCV_DVC_ERR_CODE_B (ushort)0x0037
1767 #define ASCV_OVERRUN_PADDR_D (ushort)0x0038
1768 #define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
1769 #define ASCV_HALTCODE_W (ushort)0x0040
1770 #define ASCV_CHKSUM_W (ushort)0x0042
1771 #define ASCV_MC_DATE_W (ushort)0x0044
1772 #define ASCV_MC_VER_W (ushort)0x0046
1773 #define ASCV_NEXTRDY_B (ushort)0x0048
1774 #define ASCV_DONENEXT_B (ushort)0x0049
1775 #define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
1776 #define ASCV_SCSIBUSY_B (ushort)0x004B
1777 #define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
1778 #define ASCV_CURCDB_B (ushort)0x004D
1779 #define ASCV_RCLUN_B (ushort)0x004E
1780 #define ASCV_BUSY_QHEAD_B (ushort)0x004F
1781 #define ASCV_DISC1_QHEAD_B (ushort)0x0050
1782 #define ASCV_DISC_ENABLE_B (ushort)0x0052
1783 #define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
1784 #define ASCV_HOSTSCSI_ID_B (ushort)0x0055
1785 #define ASCV_MCODE_CNTL_B (ushort)0x0056
1786 #define ASCV_NULL_TARGET_B (ushort)0x0057
1787 #define ASCV_FREE_Q_HEAD_W (ushort)0x0058
1788 #define ASCV_DONE_Q_TAIL_W (ushort)0x005A
1789 #define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
1790 #define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
1791 #define ASCV_HOST_FLAG_B (ushort)0x005D
1792 #define ASCV_TOTAL_READY_Q_B (ushort)0x0064
1793 #define ASCV_VER_SERIAL_B (ushort)0x0065
1794 #define ASCV_HALTCODE_SAVED_W (ushort)0x0066
1795 #define ASCV_WTM_FLAG_B (ushort)0x0068
1796 #define ASCV_RISC_FLAG_B (ushort)0x006A
1797 #define ASCV_REQ_SG_LIST_QP (ushort)0x006B
1798 #define ASC_HOST_FLAG_IN_ISR 0x01
1799 #define ASC_HOST_FLAG_ACK_INT 0x02
1800 #define ASC_RISC_FLAG_GEN_INT 0x01
1801 #define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1802 #define IOP_CTRL (0x0F)
1803 #define IOP_STATUS (0x0E)
1804 #define IOP_INT_ACK IOP_STATUS
1805 #define IOP_REG_IFC (0x0D)
1806 #define IOP_SYN_OFFSET (0x0B)
1807 #define IOP_EXTRA_CONTROL (0x0D)
1808 #define IOP_REG_PC (0x0C)
1809 #define IOP_RAM_ADDR (0x0A)
1810 #define IOP_RAM_DATA (0x08)
1811 #define IOP_EEP_DATA (0x06)
1812 #define IOP_EEP_CMD (0x07)
1813 #define IOP_VERSION (0x03)
1814 #define IOP_CONFIG_HIGH (0x04)
1815 #define IOP_CONFIG_LOW (0x02)
1816 #define IOP_SIG_BYTE (0x01)
1817 #define IOP_SIG_WORD (0x00)
1818 #define IOP_REG_DC1 (0x0E)
1819 #define IOP_REG_DC0 (0x0C)
1820 #define IOP_REG_SB (0x0B)
1821 #define IOP_REG_DA1 (0x0A)
1822 #define IOP_REG_DA0 (0x08)
1823 #define IOP_REG_SC (0x09)
1824 #define IOP_DMA_SPEED (0x07)
1825 #define IOP_REG_FLAG (0x07)
1826 #define IOP_FIFO_H (0x06)
1827 #define IOP_FIFO_L (0x04)
1828 #define IOP_REG_ID (0x05)
1829 #define IOP_REG_QP (0x03)
1830 #define IOP_REG_IH (0x02)
1831 #define IOP_REG_IX (0x01)
1832 #define IOP_REG_AX (0x00)
1833 #define IFC_REG_LOCK (0x00)
1834 #define IFC_REG_UNLOCK (0x09)
1835 #define IFC_WR_EN_FILTER (0x10)
1836 #define IFC_RD_NO_EEPROM (0x10)
1837 #define IFC_SLEW_RATE (0x20)
1838 #define IFC_ACT_NEG (0x40)
1839 #define IFC_INP_FILTER (0x80)
1840 #define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
1841 #define SC_SEL (uchar)(0x80)
1842 #define SC_BSY (uchar)(0x40)
1843 #define SC_ACK (uchar)(0x20)
1844 #define SC_REQ (uchar)(0x10)
1845 #define SC_ATN (uchar)(0x08)
1846 #define SC_IO (uchar)(0x04)
1847 #define SC_CD (uchar)(0x02)
1848 #define SC_MSG (uchar)(0x01)
1849 #define SEC_SCSI_CTL (uchar)(0x80)
1850 #define SEC_ACTIVE_NEGATE (uchar)(0x40)
1851 #define SEC_SLEW_RATE (uchar)(0x20)
1852 #define SEC_ENABLE_FILTER (uchar)(0x10)
1853 #define ASC_HALT_EXTMSG_IN (ushort)0x8000
1854 #define ASC_HALT_CHK_CONDITION (ushort)0x8100
1855 #define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
1856 #define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
1857 #define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
1858 #define ASC_HALT_SDTR_REJECTED (ushort)0x4000
1859 #define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
1860 #define ASC_MAX_QNO 0xF8
1861 #define ASC_DATA_SEC_BEG (ushort)0x0080
1862 #define ASC_DATA_SEC_END (ushort)0x0080
1863 #define ASC_CODE_SEC_BEG (ushort)0x0080
1864 #define ASC_CODE_SEC_END (ushort)0x0080
1865 #define ASC_QADR_BEG (0x4000)
1866 #define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
1867 #define ASC_QADR_END (ushort)0x7FFF
1868 #define ASC_QLAST_ADR (ushort)0x7FC0
1869 #define ASC_QBLK_SIZE 0x40
1870 #define ASC_BIOS_DATA_QBEG 0xF8
1871 #define ASC_MIN_ACTIVE_QNO 0x01
1872 #define ASC_QLINK_END 0xFF
1873 #define ASC_EEPROM_WORDS 0x10
1874 #define ASC_MAX_MGS_LEN 0x10
1875 #define ASC_BIOS_ADDR_DEF 0xDC00
1876 #define ASC_BIOS_SIZE 0x3800
1877 #define ASC_BIOS_RAM_OFF 0x3800
1878 #define ASC_BIOS_RAM_SIZE 0x800
1879 #define ASC_BIOS_MIN_ADDR 0xC000
1880 #define ASC_BIOS_MAX_ADDR 0xEC00
1881 #define ASC_BIOS_BANK_SIZE 0x0400
1882 #define ASC_MCODE_START_ADDR 0x0080
1883 #define ASC_CFG0_HOST_INT_ON 0x0020
1884 #define ASC_CFG0_BIOS_ON 0x0040
1885 #define ASC_CFG0_VERA_BURST_ON 0x0080
1886 #define ASC_CFG0_SCSI_PARITY_ON 0x0800
1887 #define ASC_CFG1_SCSI_TARGET_ON 0x0080
1888 #define ASC_CFG1_LRAM_8BITS_ON 0x0800
1889 #define ASC_CFG_MSW_CLR_MASK 0x3080
1890 #define CSW_TEST1 (ASC_CS_TYPE)0x8000
1891 #define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
1892 #define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
1893 #define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
1894 #define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
1895 #define CSW_TEST2 (ASC_CS_TYPE)0x0400
1896 #define CSW_TEST3 (ASC_CS_TYPE)0x0200
1897 #define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
1898 #define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
1899 #define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
1900 #define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
1901 #define CSW_HALTED (ASC_CS_TYPE)0x0010
1902 #define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
1903 #define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
1904 #define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
1905 #define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
1906 #define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
1907 #define CIW_INT_ACK (ASC_CS_TYPE)0x0100
1908 #define CIW_TEST1 (ASC_CS_TYPE)0x0200
1909 #define CIW_TEST2 (ASC_CS_TYPE)0x0400
1910 #define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
1911 #define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
1912 #define CC_CHIP_RESET (uchar)0x80
1913 #define CC_SCSI_RESET (uchar)0x40
1914 #define CC_HALT (uchar)0x20
1915 #define CC_SINGLE_STEP (uchar)0x10
1916 #define CC_DMA_ABLE (uchar)0x08
1917 #define CC_TEST (uchar)0x04
1918 #define CC_BANK_ONE (uchar)0x02
1919 #define CC_DIAG (uchar)0x01
1920 #define ASC_1000_ID0W 0x04C1
1921 #define ASC_1000_ID0W_FIX 0x00C1
1922 #define ASC_1000_ID1B 0x25
1923 #define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50)
1924 #define ASC_EISA_SMALL_IOP_GAP (0x0020)
1925 #define ASC_EISA_MIN_IOP_ADDR (0x0C30)
1926 #define ASC_EISA_MAX_IOP_ADDR (0xFC50)
1927 #define ASC_EISA_REV_IOP_MASK (0x0C83)
1928 #define ASC_EISA_PID_IOP_MASK (0x0C80)
1929 #define ASC_EISA_CFG_IOP_MASK (0x0C86)
1930 #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
1931 #define ASC_EISA_ID_740 0x01745004UL
1932 #define ASC_EISA_ID_750 0x01755004UL
1933 #define INS_HALTINT (ushort)0x6281
1934 #define INS_HALT (ushort)0x6280
1935 #define INS_SINT (ushort)0x6200
1936 #define INS_RFLAG_WTM (ushort)0x7380
1937 #define ASC_MC_SAVE_CODE_WSIZE 0x500
1938 #define ASC_MC_SAVE_DATA_WSIZE 0x40
1940 typedef struct asc_mc_saved {
1941 ushort data[ASC_MC_SAVE_DATA_WSIZE];
1942 ushort code[ASC_MC_SAVE_CODE_WSIZE];
1943 } ASC_MC_SAVED;
1945 #define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
1946 #define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1947 #define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1948 #define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1949 #define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1950 #define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1951 #define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1952 #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1953 #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1954 #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1955 #define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
1956 #define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
1957 #define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1958 #define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1959 #define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1960 #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1961 #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1962 #define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1963 #define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1964 #define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1965 #define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1966 #define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1967 #define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1968 #define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1969 #define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1970 #define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1971 #define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1972 #define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1973 #define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1974 #define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1975 #define AscGetChipLramDataNoSwap(port) (ushort)inpw_noswap((port)+IOP_RAM_DATA)
1976 #define AscSetChipLramDataNoSwap(port, data) outpw_noswap((port)+IOP_RAM_DATA, data)
1977 #define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1978 #define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1979 #define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1980 #define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1981 #define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1982 #define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1983 #define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1984 #define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1985 #define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1986 #define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1987 #define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1988 #define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1989 #define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1990 #define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1991 #define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1992 #define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1993 #define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1994 #define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1995 #define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1996 #define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1997 #define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1998 #define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1999 #define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
2000 #define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
2001 #define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
2002 #define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
2003 #define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
2004 #define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
2005 #define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
2006 #define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
2007 #define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
2008 #define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
2009 #define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
2010 #define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
2011 #define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
2012 #define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
2013 #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
2014 #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
2016 STATIC int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
2017 STATIC int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
2018 STATIC void AscWaitEEPRead(void);
2019 STATIC void AscWaitEEPWrite(void);
2020 STATIC ushort AscReadEEPWord(PortAddr, uchar);
2021 STATIC ushort AscWriteEEPWord(PortAddr, uchar, ushort);
2022 STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
2023 STATIC int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
2024 STATIC int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
2025 STATIC int AscStartChip(PortAddr);
2026 STATIC int AscStopChip(PortAddr);
2027 STATIC void AscSetChipIH(PortAddr, ushort);
2028 STATIC int AscIsChipHalted(PortAddr);
2029 STATIC void AscAckInterrupt(PortAddr);
2030 STATIC void AscDisableInterrupt(PortAddr);
2031 STATIC void AscEnableInterrupt(PortAddr);
2032 STATIC void AscSetBank(PortAddr, uchar);
2033 STATIC int AscResetChipAndScsiBus(ASC_DVC_VAR *);
2034 STATIC ushort AscGetIsaDmaChannel(PortAddr);
2035 STATIC ushort AscSetIsaDmaChannel(PortAddr, ushort);
2036 STATIC uchar AscSetIsaDmaSpeed(PortAddr, uchar);
2037 STATIC uchar AscGetIsaDmaSpeed(PortAddr);
2038 STATIC uchar AscReadLramByte(PortAddr, ushort);
2039 STATIC ushort AscReadLramWord(PortAddr, ushort);
2040 STATIC ulong AscReadLramDWord(PortAddr, ushort);
2041 STATIC void AscWriteLramWord(PortAddr, ushort, ushort);
2042 STATIC void AscWriteLramDWord(PortAddr, ushort, ulong);
2043 STATIC void AscWriteLramByte(PortAddr, ushort, uchar);
2044 STATIC ulong AscMemSumLramWord(PortAddr, ushort, rint);
2045 STATIC void AscMemWordSetLram(PortAddr, ushort, ushort, rint);
2046 STATIC void AscMemWordCopyToLram(PortAddr, ushort, ushort *, int);
2047 STATIC void AscMemDWordCopyToLram(PortAddr, ushort, ulong *, int);
2048 STATIC void AscMemWordCopyFromLram(PortAddr, ushort, ushort *, int);
2049 STATIC ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
2050 STATIC ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
2051 STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
2052 STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
2053 STATIC int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
2054 STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
2055 STATIC uchar AscCalSDTRData(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
2056 STATIC void AscSetChipSDTR(PortAddr, uchar, uchar);
2057 STATIC uchar AscGetSynPeriodIndex(ASC_DVC_VAR asc_ptr_type *, ruchar);
2058 STATIC uchar AscAllocFreeQueue(PortAddr, uchar);
2059 STATIC uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
2060 STATIC int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
2061 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2062 STATIC int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
2063 #endif /* version >= v1.3.89 */
2064 STATIC int AscHostReqRiscHalt(PortAddr);
2065 STATIC int AscStopQueueExe(PortAddr);
2066 STATIC int AscStartQueueExe(PortAddr);
2067 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2068 STATIC int AscCleanUpDiscQueue(PortAddr);
2069 #endif /* version >= v1.3.89 */
2070 STATIC int AscCleanUpBusyQueue(PortAddr);
2071 STATIC int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
2072 STATIC int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
2073 STATIC ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar *,
2074 ulong);
2075 STATIC int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
2076 ASC_SCSI_Q * scsiq,
2077 uchar n_q_required);
2078 STATIC int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *,
2079 ASC_SCSI_Q *, uchar);
2080 STATIC int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
2081 ASC_SCSI_Q *, uchar);
2082 STATIC int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
2083 STATIC int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
2084 STATIC ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *);
2085 STATIC int AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
2086 STATIC ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
2087 STATIC int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
2088 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2089 STATIC int _AscWaitQDone(PortAddr, ASC_SCSI_Q *);
2090 #endif /* version >= v1.3.89 */
2091 STATIC int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
2092 STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
2093 ASC_QDONE_INFO *, ulong);
2094 STATIC int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
2095 STATIC int AscCompareString(uchar *, uchar *, int);
2096 STATIC ushort AscGetEisaChipCfg(PortAddr);
2097 STATIC ulong AscGetEisaProductID(PortAddr);
2098 STATIC PortAddr AscSearchIOPortAddrEISA(PortAddr);
2099 STATIC uchar AscGetChipScsiCtrl(PortAddr);
2100 STATIC uchar AscSetChipScsiID(PortAddr, uchar);
2101 STATIC uchar AscGetChipVersion(PortAddr, ushort);
2102 STATIC ushort AscGetChipBusType(PortAddr);
2103 STATIC ulong AscLoadMicroCode(PortAddr, ushort, ushort *, ushort);
2104 STATIC int AscFindSignature(PortAddr);
2105 STATIC PortAddr AscSearchIOPortAddr11(PortAddr);
2106 STATIC void AscToggleIRQAct(PortAddr);
2107 STATIC void AscSetISAPNPWaitForKey(void);
2108 STATIC uchar AscGetChipIRQ(PortAddr, ushort);
2109 STATIC uchar AscSetChipIRQ(PortAddr, uchar, ushort);
2110 STATIC ushort AscGetChipBiosAddress(PortAddr, ushort);
2111 STATIC int DvcEnterCritical(void);
2112 STATIC void DvcLeaveCritical(int);
2113 STATIC void DvcInPortWords(PortAddr, ushort *, int);
2114 STATIC void DvcOutPortWords(PortAddr, ushort *, int);
2115 STATIC void DvcOutPortDWords(PortAddr, ulong *, int);
2116 STATIC uchar DvcReadPCIConfigByte(ASC_DVC_VAR asc_ptr_type *, ushort);
2117 STATIC void DvcWritePCIConfigByte(ASC_DVC_VAR asc_ptr_type *,
2118 ushort, uchar);
2119 STATIC ushort AscGetChipBiosAddress(PortAddr, ushort);
2120 STATIC void DvcSleepMilliSecond(ulong);
2121 STATIC void DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type *, ulong);
2122 STATIC ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar *,
2123 ulong, ASC_SG_HEAD *);
2124 STATIC void DvcPutScsiQ(PortAddr, ushort, ushort *, int);
2125 STATIC void DvcGetQinfo(PortAddr, ushort, ushort *, int);
2126 STATIC PortAddr AscSearchIOPortAddr(PortAddr, ushort);
2127 STATIC ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
2128 STATIC ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
2129 STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
2130 STATIC void AscAsyncFix(ASC_DVC_VAR asc_ptr_type *, uchar,
2131 ASC_SCSI_INQUIRY *);
2132 STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
2133 STATIC void AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *,
2134 uchar, ASC_SCSI_INQUIRY *);
2135 STATIC int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
2136 STATIC int AscISR(ASC_DVC_VAR asc_ptr_type *);
2137 STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar,
2138 uchar);
2139 STATIC int AscSgListToQueue(int);
2140 STATIC int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
2141 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2142 STATIC int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
2143 #endif /* version >= v1.3.89 */
2144 STATIC int AscResetSB(ASC_DVC_VAR asc_ptr_type *);
2145 STATIC void AscEnableIsaDma(uchar);
2146 STATIC ulong AscGetMaxDmaCount(ushort);
2150 * --- Adv Library Constants and Macros
2153 #define ADV_LIB_VERSION_MAJOR 5
2154 #define ADV_LIB_VERSION_MINOR 2
2156 /* d_os_dep.h */
2157 #define ADV_OS_LINUX
2160 * Define Adv Library required special types.
2162 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
2163 #define AdvPortAddr unsigned short /* I/O Port address size */
2164 #else /* version >= v1,3,0 */
2165 #define AdvPortAddr unsigned long /* Virtual memory address size */
2166 #endif /* version >= v1,3,0 */
2169 * Define Adv Library required memory access macros.
2171 #define ADV_MEM_READB(addr) readb(addr)
2172 #define ADV_MEM_READW(addr) readw(addr)
2173 #define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
2174 #define ADV_MEM_WRITEW(addr, word) writew(word, addr)
2177 * The I/O memory mapping function names changed in 2.1.X.
2179 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
2180 #define ioremap vremap
2181 #define iounmap vfree
2182 #endif /* version < v2.1.0 */
2184 #define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
2187 * Define total number of simultaneous maximum element scatter-gather
2188 * requests, i.e. ADV_TOT_SG_LIST * ADV_MAX_SG_LIST is the total number
2189 * of simultaneous scatter-gather elements supported per wide adapter.
2191 #define ADV_TOT_SG_LIST 64
2194 * Define Adv Library required per request scatter-gather element limit.
2196 #define ADV_MAX_SG_LIST 64
2198 /* Number of SG blocks needed. */
2199 #define ADV_NUM_SG_BLOCK \
2200 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
2202 /* Total contiguous memory needed for SG blocks. */
2203 #define ADV_SG_TOTAL_MEM_SIZE \
2204 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
2206 #define ASC_PAGE_SIZE PAGE_SIZE
2208 #define ADV_NUM_PAGE_CROSSING \
2209 ((ADV_SG_TOTAL_MEM_SIZE + (ASC_PAGE_SIZE - 1))/ASC_PAGE_SIZE)
2211 #define ADV_ASSERT(a) ASC_ASSERT(a)
2213 /* a_condor.h */
2214 #define ADV_PCI_VENDOR_ID 0x10CD
2215 #define ADV_PCI_DEVICE_ID_REV_A 0x2300
2216 #define ADV_PCI_DEVID_38C0800_REV1 0x2500
2217 #define ADV_PCI_DEVID_38C1600_REV1 0x2700
2219 #define ASC_EEP_DVC_CFG_BEGIN (0x00)
2220 #define ASC_EEP_DVC_CFG_END (0x15)
2221 #define ASC_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
2222 #define ASC_EEP_MAX_WORD_ADDR (0x1E)
2224 #define ASC_EEP_DELAY_MS 100
2226 #define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
2227 #define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
2228 #define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
2229 #define ADV_EEPROM_CIS_LD 0x1000 /* EEPROM Bit 12 */
2231 typedef struct adveep_3550_config
2233 /* Word Offset, Description */
2235 ushort cfg_lsw; /* 00 power up initialization */
2236 /* bit 13 set - Term Polarity Control */
2237 /* bit 14 set - BIOS Enable */
2238 /* bit 15 set - Big Endian Mode */
2239 ushort cfg_msw; /* 01 unused */
2240 ushort disc_enable; /* 02 disconnect enable */
2241 ushort wdtr_able; /* 03 Wide DTR able */
2242 ushort sdtr_able; /* 04 Synchronous DTR able */
2243 ushort start_motor; /* 05 send start up motor */
2244 ushort tagqng_able; /* 06 tag queuing able */
2245 ushort bios_scan; /* 07 BIOS device control */
2246 ushort scam_tolerant; /* 08 no scam */
2248 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2249 uchar bios_boot_delay; /* power up wait */
2251 uchar scsi_reset_delay; /* 10 reset delay */
2252 uchar bios_id_lun; /* first boot device scsi id & lun */
2253 /* high nibble is lun */
2254 /* low nibble is scsi id */
2256 uchar termination; /* 11 0 - automatic */
2257 /* 1 - low off / high off */
2258 /* 2 - low off / high on */
2259 /* 3 - low on / high on */
2260 /* There is no low on / high off */
2262 uchar reserved1; /* reserved byte (not used) */
2264 ushort bios_ctrl; /* 12 BIOS control bits */
2265 /* bit 0 set: BIOS don't act as initiator. */
2266 /* bit 1 set: BIOS > 1 GB support */
2267 /* bit 2 set: BIOS > 2 Disk Support */
2268 /* bit 3 set: BIOS don't support removables */
2269 /* bit 4 set: BIOS support bootable CD */
2270 /* bit 5 set: */
2271 /* bit 6 set: BIOS support multiple LUNs */
2272 /* bit 7 set: BIOS display of message */
2273 /* bit 8 set: */
2274 /* bit 9 set: Reset SCSI bus during init. */
2275 /* bit 10 set: */
2276 /* bit 11 set: No verbose initialization. */
2277 /* bit 12 set: SCSI parity enabled */
2278 /* bit 13 set: */
2279 /* bit 14 set: */
2280 /* bit 15 set: */
2281 ushort ultra_able; /* 13 ULTRA speed able */
2282 ushort reserved2; /* 14 reserved */
2283 uchar max_host_qng; /* 15 maximum host queuing */
2284 uchar max_dvc_qng; /* maximum per device queuing */
2285 ushort dvc_cntl; /* 16 control bit for driver */
2286 ushort bug_fix; /* 17 control bit for bug fix */
2287 ushort serial_number_word1; /* 18 Board serial number word 1 */
2288 ushort serial_number_word2; /* 19 Board serial number word 2 */
2289 ushort serial_number_word3; /* 20 Board serial number word 3 */
2290 ushort check_sum; /* 21 EEP check sum */
2291 uchar oem_name[16]; /* 22 OEM name */
2292 ushort dvc_err_code; /* 30 last device driver error code */
2293 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2294 ushort adv_err_addr; /* 32 last uc error address */
2295 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2296 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2297 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2298 ushort num_of_err; /* 36 number of error */
2299 } ADVEEP_3550_CONFIG;
2301 typedef struct adveep_38C0800_config
2303 /* Word Offset, Description */
2305 ushort cfg_lsw; /* 00 power up initialization */
2306 /* bit 12 set - CIS Load */
2307 /* bit 13 set - Term Polarity Control */
2308 /* bit 14 set - BIOS Enable */
2309 /* bit 15 set - Big Endian Mode */
2310 ushort cfg_msw; /* 01 unused */
2311 ushort disc_enable; /* 02 disconnect enable */
2312 ushort wdtr_able; /* 03 Wide DTR able */
2313 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
2314 ushort start_motor; /* 05 send start up motor */
2315 ushort tagqng_able; /* 06 tag queuing able */
2316 ushort bios_scan; /* 07 BIOS device control */
2317 ushort scam_tolerant; /* 08 no scam */
2319 uchar adapter_scsi_id; /* 09 Host Adapter ID */
2320 uchar bios_boot_delay; /* power up wait */
2322 uchar scsi_reset_delay; /* 10 reset delay */
2323 uchar bios_id_lun; /* first boot device scsi id & lun */
2324 /* high nibble is lun */
2325 /* low nibble is scsi id */
2327 uchar termination_se; /* 11 0 - automatic */
2328 /* 1 - low off / high off */
2329 /* 2 - low off / high on */
2330 /* 3 - low on / high on */
2331 /* There is no low on / high off */
2333 uchar termination_lvd; /* 11 0 - automatic */
2334 /* 1 - low off / high off */
2335 /* 2 - low off / high on */
2336 /* 3 - low on / high on */
2337 /* There is no low on / high off */
2339 ushort bios_ctrl; /* 12 BIOS control bits */
2340 /* bit 0 set: BIOS don't act as initiator. */
2341 /* bit 1 set: BIOS > 1 GB support */
2342 /* bit 2 set: BIOS > 2 Disk Support */
2343 /* bit 3 set: BIOS don't support removables */
2344 /* bit 4 set: BIOS support bootable CD */
2345 /* bit 5 set: BIOS scan enabled */
2346 /* bit 6 set: BIOS support multiple LUNs */
2347 /* bit 7 set: BIOS display of message */
2348 /* bit 8 set: */
2349 /* bit 9 set: Reset SCSI bus during init. */
2350 /* bit 10 set: */
2351 /* bit 11 set: No verbose initialization. */
2352 /* bit 12 set: SCSI parity enabled */
2353 /* bit 13 set: */
2354 /* bit 14 set: */
2355 /* bit 15 set: */
2356 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
2357 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
2358 uchar max_host_qng; /* 15 maximum host queueing */
2359 uchar max_dvc_qng; /* maximum per device queuing */
2360 ushort dvc_cntl; /* 16 control bit for driver */
2361 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
2362 ushort serial_number_word1; /* 18 Board serial number word 1 */
2363 ushort serial_number_word2; /* 19 Board serial number word 2 */
2364 ushort serial_number_word3; /* 20 Board serial number word 3 */
2365 ushort check_sum; /* 21 EEP check sum */
2366 uchar oem_name[16]; /* 22 OEM name */
2367 ushort dvc_err_code; /* 30 last device driver error code */
2368 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2369 ushort adv_err_addr; /* 32 last uc error address */
2370 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2371 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2372 ushort saved_adv_err_addr; /* 35 saved last uc error address */
2373 ushort reserved36; /* 36 reserved */
2374 ushort reserved37; /* 37 reserved */
2375 ushort reserved38; /* 38 reserved */
2376 ushort reserved39; /* 39 reserved */
2377 ushort reserved40; /* 40 reserved */
2378 ushort reserved41; /* 41 reserved */
2379 ushort reserved42; /* 42 reserved */
2380 ushort reserved43; /* 43 reserved */
2381 ushort reserved44; /* 44 reserved */
2382 ushort reserved45; /* 45 reserved */
2383 ushort reserved46; /* 46 reserved */
2384 ushort reserved47; /* 47 reserved */
2385 ushort reserved48; /* 48 reserved */
2386 ushort reserved49; /* 49 reserved */
2387 ushort reserved50; /* 50 reserved */
2388 ushort reserved51; /* 51 reserved */
2389 ushort reserved52; /* 52 reserved */
2390 ushort reserved53; /* 53 reserved */
2391 ushort reserved54; /* 54 reserved */
2392 ushort reserved55; /* 55 reserved */
2393 ushort cisptr_lsw; /* 56 CIS PTR LSW */
2394 ushort cisprt_msw; /* 57 CIS PTR MSW */
2395 ushort subsysvid; /* 58 SubSystem Vendor ID */
2396 ushort subsysid; /* 59 SubSystem ID */
2397 ushort reserved60; /* 60 reserved */
2398 ushort reserved61; /* 61 reserved */
2399 ushort reserved62; /* 62 reserved */
2400 ushort reserved63; /* 63 reserved */
2401 } ADVEEP_38C0800_CONFIG;
2404 * EEPROM Commands
2406 #define ASC_EEP_CMD_DONE 0x0200
2407 #define ASC_EEP_CMD_DONE_ERR 0x0001
2409 /* cfg_word */
2410 #define EEP_CFG_WORD_BIG_ENDIAN 0x8000
2412 /* bios_ctrl */
2413 #define BIOS_CTRL_BIOS 0x0001
2414 #define BIOS_CTRL_EXTENDED_XLAT 0x0002
2415 #define BIOS_CTRL_GT_2_DISK 0x0004
2416 #define BIOS_CTRL_BIOS_REMOVABLE 0x0008
2417 #define BIOS_CTRL_BOOTABLE_CD 0x0010
2418 #define BIOS_CTRL_MULTIPLE_LUN 0x0040
2419 #define BIOS_CTRL_DISPLAY_MSG 0x0080
2420 #define BIOS_CTRL_NO_SCAM 0x0100
2421 #define BIOS_CTRL_RESET_SCSI_BUS 0x0200
2422 #define BIOS_CTRL_INIT_VERBOSE 0x0800
2423 #define BIOS_CTRL_SCSI_PARITY 0x1000
2425 #define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
2426 #define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */
2428 #define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
2429 #define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */
2431 #define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
2432 #define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */
2433 #define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */
2436 * Byte I/O register address from base of 'iop_base'.
2438 #define IOPB_INTR_STATUS_REG 0x00
2439 #define IOPB_CHIP_ID_1 0x01
2440 #define IOPB_INTR_ENABLES 0x02
2441 #define IOPB_CHIP_TYPE_REV 0x03
2442 #define IOPB_RES_ADDR_4 0x04
2443 #define IOPB_RES_ADDR_5 0x05
2444 #define IOPB_RAM_DATA 0x06
2445 #define IOPB_RES_ADDR_7 0x07
2446 #define IOPB_FLAG_REG 0x08
2447 #define IOPB_RES_ADDR_9 0x09
2448 #define IOPB_RISC_CSR 0x0A
2449 #define IOPB_RES_ADDR_B 0x0B
2450 #define IOPB_RES_ADDR_C 0x0C
2451 #define IOPB_RES_ADDR_D 0x0D
2452 #define IOPB_SOFT_OVER_WR 0x0E
2453 #define IOPB_RES_ADDR_F 0x0F
2454 #define IOPB_MEM_CFG 0x10
2455 #define IOPB_GPIO_CNTL 0x11
2456 #define IOPB_GPIO_DATA 0x12
2457 #define IOPB_RES_ADDR_13 0x13
2458 #define IOPB_FLASH_PAGE 0x14
2459 #define IOPB_RES_ADDR_15 0x15
2460 #define IOPB_RES_ADDR_16 0x16
2461 #define IOPB_RES_ADDR_17 0x17
2462 #define IOPB_FLASH_DATA 0x18
2463 #define IOPB_RES_ADDR_19 0x19
2464 #define IOPB_RES_ADDR_1A 0x1A
2465 #define IOPB_RES_ADDR_1B 0x1B
2466 #define IOPB_RES_ADDR_1C 0x1C
2467 #define IOPB_RES_ADDR_1D 0x1D
2468 #define IOPB_RES_ADDR_1E 0x1E
2469 #define IOPB_RES_ADDR_1F 0x1F
2470 #define IOPB_DMA_CFG0 0x20
2471 #define IOPB_DMA_CFG1 0x21
2472 #define IOPB_TICKLE 0x22
2473 #define IOPB_DMA_REG_WR 0x23
2474 #define IOPB_SDMA_STATUS 0x24
2475 #define IOPB_SCSI_BYTE_CNT 0x25
2476 #define IOPB_HOST_BYTE_CNT 0x26
2477 #define IOPB_BYTE_LEFT_TO_XFER 0x27
2478 #define IOPB_BYTE_TO_XFER_0 0x28
2479 #define IOPB_BYTE_TO_XFER_1 0x29
2480 #define IOPB_BYTE_TO_XFER_2 0x2A
2481 #define IOPB_BYTE_TO_XFER_3 0x2B
2482 #define IOPB_ACC_GRP 0x2C
2483 #define IOPB_RES_ADDR_2D 0x2D
2484 #define IOPB_DEV_ID 0x2E
2485 #define IOPB_RES_ADDR_2F 0x2F
2486 #define IOPB_SCSI_DATA 0x30
2487 #define IOPB_RES_ADDR_31 0x31
2488 #define IOPB_RES_ADDR_32 0x32
2489 #define IOPB_SCSI_DATA_HSHK 0x33
2490 #define IOPB_SCSI_CTRL 0x34
2491 #define IOPB_RES_ADDR_35 0x35
2492 #define IOPB_RES_ADDR_36 0x36
2493 #define IOPB_RES_ADDR_37 0x37
2494 #define IOPB_RAM_BIST 0x38
2495 #define IOPB_PLL_TEST 0x39
2496 #define IOPB_RES_ADDR_3A 0x3A
2497 #define IOPB_RES_ADDR_3B 0x3B
2498 #define IOPB_RFIFO_CNT 0x3C
2499 #define IOPB_RES_ADDR_3D 0x3D
2500 #define IOPB_RES_ADDR_3E 0x3E
2501 #define IOPB_RES_ADDR_3F 0x3F
2504 * Word I/O register address from base of 'iop_base'.
2506 #define IOPW_CHIP_ID_0 0x00 /* CID0 */
2507 #define IOPW_CTRL_REG 0x02 /* CC */
2508 #define IOPW_RAM_ADDR 0x04 /* LA */
2509 #define IOPW_RAM_DATA 0x06 /* LD */
2510 #define IOPW_RES_ADDR_08 0x08
2511 #define IOPW_RISC_CSR 0x0A /* CSR */
2512 #define IOPW_SCSI_CFG0 0x0C /* CFG0 */
2513 #define IOPW_SCSI_CFG1 0x0E /* CFG1 */
2514 #define IOPW_RES_ADDR_10 0x10
2515 #define IOPW_SEL_MASK 0x12 /* SM */
2516 #define IOPW_RES_ADDR_14 0x14
2517 #define IOPW_FLASH_ADDR 0x16 /* FA */
2518 #define IOPW_RES_ADDR_18 0x18
2519 #define IOPW_EE_CMD 0x1A /* EC */
2520 #define IOPW_EE_DATA 0x1C /* ED */
2521 #define IOPW_SFIFO_CNT 0x1E /* SFC */
2522 #define IOPW_RES_ADDR_20 0x20
2523 #define IOPW_Q_BASE 0x22 /* QB */
2524 #define IOPW_QP 0x24 /* QP */
2525 #define IOPW_IX 0x26 /* IX */
2526 #define IOPW_SP 0x28 /* SP */
2527 #define IOPW_PC 0x2A /* PC */
2528 #define IOPW_RES_ADDR_2C 0x2C
2529 #define IOPW_RES_ADDR_2E 0x2E
2530 #define IOPW_SCSI_DATA 0x30 /* SD */
2531 #define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
2532 #define IOPW_SCSI_CTRL 0x34 /* SC */
2533 #define IOPW_HSHK_CFG 0x36 /* HCFG */
2534 #define IOPW_SXFR_STATUS 0x36 /* SXS */
2535 #define IOPW_SXFR_CNTL 0x38 /* SXL */
2536 #define IOPW_SXFR_CNTH 0x3A /* SXH */
2537 #define IOPW_RES_ADDR_3C 0x3C
2538 #define IOPW_RFIFO_DATA 0x3E /* RFD */
2541 * Doubleword I/O register address from base of 'iop_base'.
2543 #define IOPDW_RES_ADDR_0 0x00
2544 #define IOPDW_RAM_DATA 0x04
2545 #define IOPDW_RES_ADDR_8 0x08
2546 #define IOPDW_RES_ADDR_C 0x0C
2547 #define IOPDW_RES_ADDR_10 0x10
2548 #define IOPDW_COMMA 0x14
2549 #define IOPDW_COMMB 0x18
2550 #define IOPDW_RES_ADDR_1C 0x1C
2551 #define IOPDW_SDMA_ADDR0 0x20
2552 #define IOPDW_SDMA_ADDR1 0x24
2553 #define IOPDW_SDMA_COUNT 0x28
2554 #define IOPDW_SDMA_ERROR 0x2C
2555 #define IOPDW_RDMA_ADDR0 0x30
2556 #define IOPDW_RDMA_ADDR1 0x34
2557 #define IOPDW_RDMA_COUNT 0x38
2558 #define IOPDW_RDMA_ERROR 0x3C
2560 #define ADV_CHIP_ID_BYTE 0x25
2561 #define ADV_CHIP_ID_WORD 0x04C1
2563 #define ADV_SC_SCSI_BUS_RESET 0x2000
2565 #define ADV_INTR_ENABLE_HOST_INTR 0x01
2566 #define ADV_INTR_ENABLE_SEL_INTR 0x02
2567 #define ADV_INTR_ENABLE_DPR_INTR 0x04
2568 #define ADV_INTR_ENABLE_RTA_INTR 0x08
2569 #define ADV_INTR_ENABLE_RMA_INTR 0x10
2570 #define ADV_INTR_ENABLE_RST_INTR 0x20
2571 #define ADV_INTR_ENABLE_DPE_INTR 0x40
2572 #define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
2574 #define ADV_INTR_STATUS_INTRA 0x01
2575 #define ADV_INTR_STATUS_INTRB 0x02
2576 #define ADV_INTR_STATUS_INTRC 0x04
2578 #define ADV_RISC_CSR_STOP (0x0000)
2579 #define ADV_RISC_TEST_COND (0x2000)
2580 #define ADV_RISC_CSR_RUN (0x4000)
2581 #define ADV_RISC_CSR_SINGLE_STEP (0x8000)
2583 #define ADV_CTRL_REG_HOST_INTR 0x0100
2584 #define ADV_CTRL_REG_SEL_INTR 0x0200
2585 #define ADV_CTRL_REG_DPR_INTR 0x0400
2586 #define ADV_CTRL_REG_RTA_INTR 0x0800
2587 #define ADV_CTRL_REG_RMA_INTR 0x1000
2588 #define ADV_CTRL_REG_RES_BIT14 0x2000
2589 #define ADV_CTRL_REG_DPE_INTR 0x4000
2590 #define ADV_CTRL_REG_POWER_DONE 0x8000
2591 #define ADV_CTRL_REG_ANY_INTR 0xFF00
2593 #define ADV_CTRL_REG_CMD_RESET 0x00C6
2594 #define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
2595 #define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
2596 #define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
2597 #define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
2599 #define ADV_TICKLE_NOP 0x00
2600 #define ADV_TICKLE_A 0x01
2601 #define ADV_TICKLE_B 0x02
2602 #define ADV_TICKLE_C 0x03
2604 #define ADV_SCSI_CTRL_RSTOUT 0x2000
2606 #define AdvIsIntPending(port) \
2607 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
2610 * SCSI_CFG0 Register bit definitions
2612 #define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
2613 #define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
2614 #define EVEN_PARITY 0x1000 /* Select Even Parity */
2615 #define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
2616 #define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
2617 #define PRIM_MODE 0x0100 /* Primitive SCSI mode */
2618 #define SCAM_EN 0x0080 /* Enable SCAM selection */
2619 #define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
2620 #define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
2621 #define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
2622 #define OUR_ID 0x000F /* SCSI ID */
2625 * SCSI_CFG1 Register bit definitions
2627 #define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
2628 #define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
2629 #define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
2630 #define FILTER_SEL 0x0C00 /* Filter Period Selection */
2631 #define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
2632 #define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
2633 #define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
2634 #define ACTIVE_DBL 0x0200 /* Disable Active Negation */
2635 #define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
2636 #define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
2637 #define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
2638 #define TERM_CTL 0x0030 /* External SCSI Termination Bits */
2639 #define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
2640 #define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
2641 #define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
2644 * Addendum for ASC-38C0800 Chip
2646 #define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
2647 #define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
2648 #define HVD 0x1000 /* HVD Device Detect */
2649 #define LVD 0x0800 /* LVD Device Detect */
2650 #define SE 0x0400 /* SE Device Detect */
2651 #define TERM_LVD 0x00C0 /* LVD Termination Bits */
2652 #define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
2653 #define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
2654 #define TERM_SE 0x0030 /* SE Termination Bits */
2655 #define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
2656 #define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
2657 #define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
2658 #define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
2659 #define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
2660 #define C_DET_SE 0x0003 /* SE Cable Detect Bits */
2661 #define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
2662 #define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
2665 #define CABLE_ILLEGAL_A 0x7
2666 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
2668 #define CABLE_ILLEGAL_B 0xB
2669 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
2672 * MEM_CFG Register bit definitions
2674 #define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
2675 #define FAST_EE_CLK 0x20 /* Diagnostic Bit */
2676 #define RAM_SZ 0x1C /* Specify size of RAM to RISC */
2677 #define RAM_SZ_2KB 0x00 /* 2 KB */
2678 #define RAM_SZ_4KB 0x04 /* 4 KB */
2679 #define RAM_SZ_8KB 0x08 /* 8 KB */
2680 #define RAM_SZ_16KB 0x0C /* 16 KB */
2681 #define RAM_SZ_32KB 0x10 /* 32 KB */
2682 #define RAM_SZ_64KB 0x14 /* 64 KB */
2685 * DMA_CFG0 Register bit definitions
2687 * This register is only accessible to the host.
2689 #define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
2690 #define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
2691 #define FIFO_THRESH_16B 0x00 /* 16 bytes */
2692 #define FIFO_THRESH_32B 0x20 /* 32 bytes */
2693 #define FIFO_THRESH_48B 0x30 /* 48 bytes */
2694 #define FIFO_THRESH_64B 0x40 /* 64 bytes */
2695 #define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
2696 #define FIFO_THRESH_96B 0x60 /* 96 bytes */
2697 #define FIFO_THRESH_112B 0x70 /* 112 bytes */
2698 #define START_CTL 0x0C /* DMA start conditions */
2699 #define START_CTL_TH 0x00 /* Wait threshold level (default) */
2700 #define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
2701 #define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
2702 #define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
2703 #define READ_CMD 0x03 /* Memory Read Method */
2704 #define READ_CMD_MR 0x00 /* Memory Read */
2705 #define READ_CMD_MRL 0x02 /* Memory Read Long */
2706 #define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
2709 * ASC-38C0800 RAM BIST Register bit definitions
2711 #define RAM_TEST_MODE 0x80
2712 #define PRE_TEST_MODE 0x40
2713 #define NORMAL_MODE 0x00
2714 #define RAM_TEST_DONE 0x10
2715 #define RAM_TEST_STATUS 0x0F
2716 #define RAM_TEST_HOST_ERROR 0x08
2717 #define RAM_TEST_INTRAM_ERROR 0x04
2718 #define RAM_TEST_RISC_ERROR 0x02
2719 #define RAM_TEST_SCSI_ERROR 0x01
2720 #define RAM_TEST_SUCCESS 0x00
2721 #define PRE_TEST_VALUE 0x05
2722 #define NORMAL_VALUE 0x00
2724 /* a_advlib.h */
2727 * Adv Library Status Definitions
2729 #define ADV_TRUE 1
2730 #define ADV_FALSE 0
2731 #define ADV_NOERROR 1
2732 #define ADV_SUCCESS 1
2733 #define ADV_BUSY 0
2734 #define ADV_ERROR (-1)
2738 * ASC_DVC_VAR 'warn_code' values
2740 #define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
2741 #define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
2742 #define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
2743 #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
2744 #define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
2746 #define ADV_MAX_TID 15 /* max. target identifier */
2747 #define ADV_MAX_LUN 7 /* max. logical unit number */
2751 * AscInitGetConfig() and AscInitAsc1000Driver() Definitions
2753 * Error code values are set in ASC_DVC_VAR 'err_code'.
2755 #define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
2756 #define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
2757 #define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
2758 #define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
2759 #define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
2760 #define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
2761 #define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
2762 #define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
2763 #define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
2764 #define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
2765 #define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
2766 #define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
2767 #define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
2768 #define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
2771 * Fixed locations of microcode operating variables.
2773 #define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
2774 #define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
2775 #define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
2776 #define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
2777 #define ASC_MC_VERSION_NUM 0x003A /* microcode number */
2778 #define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
2779 #define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
2780 #define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
2781 #define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
2782 #define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
2783 #define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
2784 #define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
2785 #define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
2786 #define ASC_MC_CHIP_TYPE 0x009A
2787 #define ASC_MC_INTRB_CODE 0x009B
2788 #define ASC_MC_WDTR_ABLE 0x009C
2789 #define ASC_MC_SDTR_ABLE 0x009E
2790 #define ASC_MC_TAGQNG_ABLE 0x00A0
2791 #define ASC_MC_DISC_ENABLE 0x00A2
2792 #define ASC_MC_IDLE_CMD_STATUS 0x00A4
2793 #define ASC_MC_IDLE_CMD 0x00A6
2794 #define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
2795 #define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
2796 #define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
2797 #define ASC_MC_DEFAULT_MEM_CFG 0x00B0
2798 #define ASC_MC_DEFAULT_SEL_MASK 0x00B2
2799 #define ASC_MC_SDTR_DONE 0x00B6
2800 #define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
2801 #define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
2802 #define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
2803 #define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
2804 #define ASC_MC_WDTR_DONE 0x0124
2805 #define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
2806 #define ASC_MC_ICQ 0x0160
2807 #define ASC_MC_IRQ 0x0164
2810 * BIOS LRAM variable absolute offsets.
2812 #define BIOS_CODESEG 0x54
2813 #define BIOS_CODELEN 0x56
2814 #define BIOS_SIGNATURE 0x58
2815 #define BIOS_VERSION 0x5A
2818 * Microcode Control Flags
2820 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
2821 * and handled by the microcode.
2823 #define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
2826 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
2828 #define HSHK_CFG_WIDE_XFR 0x8000
2829 #define HSHK_CFG_RATE 0x0F00
2830 #define HSHK_CFG_OFFSET 0x001F
2832 #define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
2833 #define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
2834 #define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
2835 #define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
2837 #define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
2838 #define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
2839 #define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
2840 #define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
2841 #define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
2843 #define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
2844 #define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
2845 #define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
2846 #define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
2847 #define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
2849 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
2850 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
2852 #define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2853 #define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
2855 typedef struct adv_carr_t
2857 ulong carr_va; /* Carrier Virtual Address */
2858 ulong carr_pa; /* Carrier Physical Address */
2859 ulong areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2861 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2863 * next_vpa [3:1] Reserved Bits
2864 * next_vpa [0] Done Flag set in Response Queue.
2866 ulong next_vpa;
2867 } ADV_CARR_T;
2870 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2872 #define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2874 #define ASC_RQ_DONE 0x00000001
2875 #define ASC_CQ_STOPPER 0x00000000
2877 #define ASC_GET_CARRP(carrp) ((ADV_CARR_T *) ((carrp) & ASC_NEXT_VPA_MASK))
2879 #define ADV_PAGE_SIZE 4096 /* Assume 4KB page size. */
2881 #define ADV_CARRIER_NUM_PAGE_CROSSING \
2882 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2883 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2885 #define ADV_CARRIER_BUFSIZE \
2886 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2889 * ASC_SCSI_REQ_Q 'a_flag' definitions
2891 * The Adv Library should limit use to the lower nibble (4 bits) of
2892 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2894 #define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2895 #define ADV_SCSIQ_DONE 0x02 /* request done */
2896 #define ADV_DONT_RETRY 0x08 /* don't do retry */
2898 #define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2899 #define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2900 #define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
2903 * Adapter temporary configuration structure
2905 * This structure can be discarded after initialization. Don't add
2906 * fields here needed after initialization.
2908 * Field naming convention:
2910 * *_enable indicates the field enables or disables a feature. The
2911 * value of the field is never reset.
2913 typedef struct adv_dvc_cfg {
2914 ushort disc_enable; /* enable disconnection */
2915 uchar chip_version; /* chip version */
2916 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2917 ushort pci_device_id; /* PCI device code number */
2918 ushort lib_version; /* Adv Library version number */
2919 ushort control_flag; /* Microcode Control Flag */
2920 ushort mcode_date; /* Microcode date */
2921 ushort mcode_version; /* Microcode version */
2922 ushort pci_slot_info; /* high byte device/function number */
2923 /* bits 7-3 device num., bits 2-0 function num. */
2924 /* low byte bus num. */
2925 ushort serial1; /* EEPROM serial number word 1 */
2926 ushort serial2; /* EEPROM serial number word 2 */
2927 ushort serial3; /* EEPROM serial number word 3 */
2928 } ADV_DVC_CFG;
2930 struct adv_dvc_var;
2931 struct adv_scsi_req_q;
2933 typedef void (* ADV_ISR_CALLBACK)
2934 (struct adv_dvc_var *, struct adv_scsi_req_q *);
2936 typedef void (* ADV_ASYNC_CALLBACK)
2937 (struct adv_dvc_var *, uchar);
2940 * Adapter operation variable structure.
2942 * One structure is required per host adapter.
2944 * Field naming convention:
2946 * *_able indicates both whether a feature should be enabled or disabled
2947 * and whether a device isi capable of the feature. At initialization
2948 * this field may be set, but later if a device is found to be incapable
2949 * of the feature, the field is cleared.
2951 typedef struct adv_dvc_var {
2952 AdvPortAddr iop_base; /* I/O port address */
2953 ushort err_code; /* fatal error code */
2954 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
2955 ADV_ISR_CALLBACK isr_callback;
2956 ADV_ASYNC_CALLBACK async_callback;
2957 ushort wdtr_able; /* try WDTR for a device */
2958 ushort sdtr_able; /* try SDTR for a device */
2959 ushort ultra_able; /* try SDTR Ultra speed for a device */
2960 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2961 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2962 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2963 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2964 ushort tagqng_able; /* try tagged queuing with a device */
2965 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2966 ushort start_motor; /* start motor command allowed */
2967 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2968 uchar chip_no; /* should be assigned by caller */
2969 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2970 uchar irq_no; /* IRQ number */
2971 ushort no_scam; /* scam_tolerant of EEPROM */
2972 ulong drv_ptr; /* driver pointer to private structure */
2973 uchar chip_scsi_id; /* chip SCSI target ID */
2974 uchar chip_type;
2975 uchar bist_err_code;
2976 ADV_CARR_T *carrier_buf;
2977 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2978 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2979 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2980 ushort carr_pending_cnt; /* Count of pending carriers. */
2982 * Note: The following fields will not be used after initialization. The
2983 * driver may discard the buffer after initialization is done.
2985 ADV_DVC_CFG *cfg; /* temporary configuration structure */
2986 } ADV_DVC_VAR;
2988 #define NO_OF_SG_PER_BLOCK 15
2990 typedef struct asc_sg_block {
2991 uchar reserved1;
2992 uchar reserved2;
2993 uchar reserved3;
2994 uchar sg_cnt; /* Valid entries in block. */
2995 struct asc_sg_block *sg_ptr; /* links to the next sg block */
2996 struct {
2997 ulong sg_addr; /* SG element address. */
2998 ulong sg_count; /* SG element count. */
2999 } sg_list[NO_OF_SG_PER_BLOCK];
3000 } ADV_SG_BLOCK;
3003 * ADV_SCSI_REQ_Q - microcode request structure
3005 * All fields in this structure up to byte 60 are used by the microcode.
3006 * The microcode makes assumptions about the size and ordering of fields
3007 * in this structure. Do not change the structure definition here without
3008 * coordinating the change with the microcode.
3010 typedef struct adv_scsi_req_q {
3011 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
3012 uchar reserved;
3013 uchar target_id; /* Device target identifier. */
3014 uchar target_lun; /* Device target logical unit number. */
3015 ulong data_addr; /* Data buffer physical address. */
3016 ulong data_cnt; /* Data count. Ucode sets to residual. */
3017 ulong sense_addr;
3018 ulong carr_pa;
3019 uchar mflag;
3020 uchar sense_len;
3021 uchar cdb_len; /* SCSI CDB length. */
3022 uchar scsi_cntl;
3023 uchar done_status; /* Completion status. */
3024 uchar scsi_status; /* SCSI status byte. */
3025 uchar host_status; /* Ucode host status. */
3026 uchar sg_working_ix;
3027 uchar cdb[12]; /* SCSI command block. */
3028 ulong sg_real_addr; /* SG list physical address. */
3029 ulong scsiq_rptr;
3030 ulong sg_working_data_cnt;
3031 struct adv_scsi_req_q *scsiq_ptr;
3032 ulong carr_va;
3034 * End of microcode structure - 60 bytes. The rest of the structure
3035 * is used by the Adv Library and ignored by the microcode.
3037 ulong srb_ptr;
3038 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
3039 ulong vdata_addr; /* Data buffer virtual address. */
3040 uchar a_flag;
3041 } ADV_SCSI_REQ_Q;
3044 * Microcode idle loop commands
3046 #define IDLE_CMD_COMPLETED 0
3047 #define IDLE_CMD_STOP_CHIP 0x0001
3048 #define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
3049 #define IDLE_CMD_SEND_INT 0x0004
3050 #define IDLE_CMD_ABORT 0x0008
3051 #define IDLE_CMD_DEVICE_RESET 0x0010
3052 #define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
3053 #define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
3054 #define IDLE_CMD_SCSIREQ 0x0080
3056 #define IDLE_CMD_STATUS_SUCCESS 0x0001
3057 #define IDLE_CMD_STATUS_FAILURE 0x0002
3060 * AdvSendIdleCmd() flag definitions.
3062 #define ADV_NOWAIT 0x01
3065 * Wait loop time out values.
3067 #define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
3068 #define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
3069 #define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
3070 #define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
3071 #define SCSI_MAX_RETRY 10 /* retry count */
3073 #define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
3074 #define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
3075 #define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
3077 #define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
3080 * Device drivers must define the following functions.
3082 STATIC int DvcEnterCritical(void);
3083 STATIC void DvcLeaveCritical(int);
3084 STATIC void DvcSleepMilliSecond(ulong);
3085 STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
3086 STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
3087 STATIC ulong DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
3088 uchar *, long *, int);
3089 STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
3092 * Adv Library functions available to drivers.
3094 STATIC int AdvExeScsiQueue(ADV_DVC_VAR *,
3095 ADV_SCSI_REQ_Q *);
3096 STATIC int AdvISR(ADV_DVC_VAR *);
3097 STATIC int AdvInitGetConfig(ADV_DVC_VAR *);
3098 STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *);
3099 STATIC int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
3100 STATIC int AdvResetChipAndSB(ADV_DVC_VAR *);
3101 STATIC int AdvResetSB(ADV_DVC_VAR *asc_dvc);
3104 * Internal Adv Library functions.
3106 STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ulong);
3107 STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3108 STATIC int AdvInitFrom3550EEP(ADV_DVC_VAR *);
3109 STATIC int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
3110 STATIC ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3111 STATIC void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
3112 STATIC ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3113 STATIC void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
3114 STATIC void AdvWaitEEPCmd(AdvPortAddr);
3115 STATIC ushort AdvReadEEPWord(AdvPortAddr, int);
3118 * PCI Bus Definitions
3120 #define AscPCICmdRegBits_BusMastering 0x0007
3121 #define AscPCICmdRegBits_ParErrRespCtrl 0x0040
3123 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
3125 /* Read byte from a register. */
3126 #define AdvReadByteRegister(iop_base, reg_off) (inp((iop_base) + (reg_off)))
3128 /* Write byte to a register. */
3129 #define AdvWriteByteRegister(iop_base, reg_off, byte) (outp((iop_base) + (reg_off), (byte)))
3131 /* Read word (2 bytes) from a register. */
3132 #define AdvReadWordRegister(iop_base, reg_off) (inpw((iop_base) + (reg_off)))
3134 /* Write word (2 bytes) to a register. */
3135 #define AdvWriteWordRegister(iop_base, reg_off, word) (outpw((iop_base) + (reg_off), (word)))
3137 /* Read byte from LRAM. */
3138 #define AdvReadByteLram(iop_base, addr, byte) \
3139 do { \
3140 outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
3141 (byte) = inp((iop_base) + IOPB_RAM_DATA); \
3142 } while (0)
3144 /* Write byte to LRAM. */
3145 #define AdvWriteByteLram(iop_base, addr, byte) \
3146 (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
3147 outp((iop_base) + IOPB_RAM_DATA, (byte)))
3149 /* Read word (2 bytes) from LRAM. */
3150 #define AdvReadWordLram(iop_base, addr, word) \
3151 do { \
3152 outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
3153 (word) = inpw((iop_base) + IOPW_RAM_DATA); \
3154 } while (0)
3156 /* Write word (2 bytes) to LRAM. */
3157 #define AdvWriteWordLram(iop_base, addr, word) \
3158 (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
3159 outpw((iop_base) + IOPW_RAM_DATA, (word)))
3161 /* Write double word (4 bytes) to LRAM */
3162 /* Because of unspecified C language ordering don't use auto-increment. */
3163 #define AdvWriteDWordLram(iop_base, addr, dword) \
3164 ((outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
3165 outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword) & 0xFFFF))), \
3166 (outpw((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3167 outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword >> 16) & 0xFFFF))))
3169 /* Read word (2 bytes) from LRAM assuming that the address is already set. */
3170 #define AdvReadWordAutoIncLram(iop_base) \
3171 (inpw((iop_base) + IOPW_RAM_DATA))
3173 /* Write word (2 bytes) to LRAM assuming that the address is already set. */
3174 #define AdvWriteWordAutoIncLram(iop_base, word) \
3175 (outpw((iop_base) + IOPW_RAM_DATA, (word)))
3177 #else /* version >= v1,3,0 */
3179 /* Read byte from a register. */
3180 #define AdvReadByteRegister(iop_base, reg_off) \
3181 (ADV_MEM_READB((iop_base) + (reg_off)))
3183 /* Write byte to a register. */
3184 #define AdvWriteByteRegister(iop_base, reg_off, byte) \
3185 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
3187 /* Read word (2 bytes) from a register. */
3188 #define AdvReadWordRegister(iop_base, reg_off) \
3189 (ADV_MEM_READW((iop_base) + (reg_off)))
3191 /* Write word (2 bytes) to a register. */
3192 #define AdvWriteWordRegister(iop_base, reg_off, word) \
3193 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
3195 /* Read byte from LRAM. */
3196 #define AdvReadByteLram(iop_base, addr, byte) \
3197 do { \
3198 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3199 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
3200 } while (0)
3202 /* Write byte to LRAM. */
3203 #define AdvWriteByteLram(iop_base, addr, byte) \
3204 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3205 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
3207 /* Read word (2 bytes) from LRAM. */
3208 #define AdvReadWordLram(iop_base, addr, word) \
3209 do { \
3210 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3211 (word) = ADV_MEM_READW((iop_base) + IOPW_RAM_DATA); \
3212 } while (0)
3214 /* Write word (2 bytes) to LRAM. */
3215 #define AdvWriteWordLram(iop_base, addr, word) \
3216 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3217 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3219 /* Write double word (4 bytes) to LRAM */
3220 /* Because of unspecified C language ordering don't use auto-increment. */
3221 #define AdvWriteDWordLram(iop_base, addr, dword) \
3222 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3223 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3224 (ushort) ((dword) & 0xFFFF))), \
3225 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3226 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3227 (ushort) ((dword >> 16) & 0xFFFF))))
3229 /* Read word (2 bytes) from LRAM assuming that the address is already set. */
3230 #define AdvReadWordAutoIncLram(iop_base) \
3231 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
3233 /* Write word (2 bytes) to LRAM assuming that the address is already set. */
3234 #define AdvWriteWordAutoIncLram(iop_base, word) \
3235 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3237 #endif /* version >= v1,3,0 */
3240 * Define macro to check for Condor signature.
3242 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
3243 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
3245 #define AdvFindSignature(iop_base) \
3246 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
3247 ADV_CHIP_ID_BYTE) && \
3248 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
3249 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
3252 * Define macro to Return the version number of the chip at 'iop_base'.
3254 * The second parameter 'bus_type' is currently unused.
3256 #define AdvGetChipVersion(iop_base, bus_type) \
3257 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
3260 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
3261 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
3263 * If the request has not yet been sent to the device it will simply be
3264 * aborted from RISC memory. If the request is disconnected it will be
3265 * aborted on reselection by sending an Abort Message to the target ID.
3267 * Return value:
3268 * ADV_TRUE(1) - Queue was successfully aborted.
3269 * ADV_FALSE(0) - Queue was not found on the active queue list.
3271 #define AdvAbortQueue(asc_dvc, scsiq) \
3272 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
3273 (ulong) (scsiq))
3276 * Send a Bus Device Reset Message to the specified target ID.
3278 * All outstanding commands will be purged if sending the
3279 * Bus Device Reset Message is successful.
3281 * Return Value:
3282 * ADV_TRUE(1) - All requests on the target are purged.
3283 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
3284 * are not purged.
3286 #define AdvResetDevice(asc_dvc, target_id) \
3287 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
3288 (ulong) (target_id))
3291 * SCSI Wide Type definition.
3293 #define ADV_SCSI_BIT_ID_TYPE ushort
3296 * AdvInitScsiTarget() 'cntl_flag' options.
3298 #define ADV_SCAN_LUN 0x01
3299 #define ADV_CAPINFO_NOLUN 0x02
3302 * Convert target id to target id bit mask.
3304 #define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
3307 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
3310 #define QD_NO_STATUS 0x00 /* Request not completed yet. */
3311 #define QD_NO_ERROR 0x01
3312 #define QD_ABORTED_BY_HOST 0x02
3313 #define QD_WITH_ERROR 0x04
3315 #define QHSTA_NO_ERROR 0x00
3316 #define QHSTA_M_SEL_TIMEOUT 0x11
3317 #define QHSTA_M_DATA_OVER_RUN 0x12
3318 #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
3319 #define QHSTA_M_QUEUE_ABORTED 0x15
3320 #define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
3321 #define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
3322 #define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
3323 #define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
3324 #define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
3325 #define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
3326 #define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
3327 /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
3328 #define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
3329 #define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
3330 #define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
3331 #define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
3332 #define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
3333 #define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
3334 #define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
3335 #define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
3336 #define QHSTA_M_WTM_TIMEOUT 0x41
3337 #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
3338 #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
3339 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
3340 #define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
3341 #define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
3342 #define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
3346 * Default EEPROM Configuration structure defined in a_init.c.
3348 extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
3349 extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
3352 * DvcGetPhyAddr() flag arguments
3354 #define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
3355 #define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
3356 #define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
3357 #define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
3358 #define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
3359 #define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
3361 /* Return the address that is aligned at the next doubleword >= to 'addr'. */
3362 #define ADV_DWALIGN(addr) (((ulong) (addr) + 0x3) & ~0x3)
3363 #define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
3366 * Total contiguous memory needed for driver SG blocks.
3368 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
3369 * number of scatter-gather elements the driver supports in a
3370 * single request.
3373 #ifndef ADV_MAX_SG_LIST
3374 Forced Error: Driver must define ADV_MAX_SG_LIST.
3375 #endif /* ADV_MAX_SG_LIST */
3377 #define ADV_SG_LIST_MAX_BYTE_SIZE \
3378 (sizeof(ADV_SG_BLOCK) * \
3379 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
3382 * A driver may optionally define the assertion macro ADV_ASSERT() in
3383 * its d_os_dep.h file. If the macro has not already been defined,
3384 * then define the macro to a no-op.
3386 #ifndef ADV_ASSERT
3387 #define ADV_ASSERT(a)
3388 #endif /* ADV_ASSERT */
3390 typedef struct {
3391 uchar peri_dvc_type : 5; /* peripheral device type */
3392 uchar peri_qualifier : 3; /* peripheral qualifier */
3393 uchar dvc_type_modifier : 7; /* device type modifier (for SCSI I) */
3394 uchar rmb : 1; /* RMB - removable medium bit */
3395 uchar ansi_apr_ver : 3; /* ANSI approved version */
3396 uchar ecma_ver : 3; /* ECMA version */
3397 uchar iso_ver : 2; /* ISO version */
3398 uchar rsp_data_fmt : 4; /* response data format */
3399 /* 0 SCSI 1 */
3400 /* 1 CCS */
3401 /* 2 SCSI-2 */
3402 /* 3-F reserved */
3403 uchar res1 : 2; /* reserved */
3404 uchar TemIOP : 1; /* terminate I/O process bit (see 5.6.22) */
3405 uchar aenc : 1; /* asynch. event notification (processor) */
3406 uchar add_len; /* additional length */
3407 uchar res2; /* reserved */
3408 uchar res3; /* reserved */
3409 uchar StfRe : 1; /* soft reset implemented */
3410 uchar CmdQue : 1; /* command queuing */
3411 uchar res4 : 1; /* reserved */
3412 uchar Linked : 1; /* linked command for this logical unit */
3413 uchar Sync : 1; /* synchronous data transfer */
3414 uchar WBus16 : 1; /* wide bus 16 bit data transfer */
3415 uchar WBus32 : 1; /* wide bus 32 bit data transfer */
3416 uchar RelAdr : 1; /* relative addressing mode */
3417 uchar vendor_id[8]; /* vendor identification */
3418 uchar product_id[16]; /* product identification */
3419 uchar product_rev_level[4]; /* product revision level */
3420 uchar vendor_specific[20]; /* vendor specific */
3421 uchar IUS : 1; /* information unit supported */
3422 uchar QAS : 1; /* quick arbitrate supported */
3423 uchar Clocking : 2; /* clocking field */
3424 uchar res5 : 4; /* reserved */
3425 uchar res6; /* reserved */
3426 } ADV_SCSI_INQUIRY; /* 58 bytes */
3430 * --- Driver Constants and Macros
3433 #define ASC_NUM_BOARD_SUPPORTED 16
3434 #define ASC_NUM_IOPORT_PROBE 4
3435 #define ASC_NUM_BUS 4
3437 /* Reference Scsi_Host hostdata */
3438 #define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
3440 /* asc_board_t flags */
3441 #define ASC_HOST_IN_RESET 0x01
3442 #define ASC_HOST_IN_ABORT 0x02
3443 #define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
3444 #define ASC_SELECT_QUEUE_DEPTHS 0x08
3446 #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
3447 #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
3449 #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
3452 * If the Linux kernel version supports freeing initialization code
3453 * and data after loading, define macros for this purpose. These macros
3454 * are not used when the driver is built as a module, cf. linux/init.h.
3456 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,23)
3457 #define ASC_INITFUNC(type, func) type func
3458 #define ASC_INITDATA
3459 #define ASC_INIT
3460 #else /* version >= v2.1.23 */
3461 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,16)
3462 #define ASC_INITFUNC(type, func) __initfunc(type func)
3463 #else /* version >= v2.3.16 */
3464 #define ASC_INITFUNC(type, func) type __init func
3465 #endif /* version >= v2.3.16 */
3466 #define ASC_INITDATA __initdata
3467 #define ASC_INIT __init
3468 #endif /* version >= v2.1.23 */
3470 #define ASC_INFO_SIZE 128 /* advansys_info() line size */
3472 /* /proc/scsi/advansys/[0...] related definitions */
3473 #define ASC_PRTBUF_SIZE 2048
3474 #define ASC_PRTLINE_SIZE 160
3476 #define ASC_PRT_NEXT() \
3477 if (cp) { \
3478 totlen += len; \
3479 leftlen -= len; \
3480 if (leftlen == 0) { \
3481 return totlen; \
3483 cp += len; \
3486 #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
3488 /* Asc Library return codes */
3489 #define ASC_TRUE 1
3490 #define ASC_FALSE 0
3491 #define ASC_NOERROR 1
3492 #define ASC_BUSY 0
3493 #define ASC_ERROR (-1)
3495 /* Scsi_Cmnd function return codes */
3496 #define STATUS_BYTE(byte) (byte)
3497 #define MSG_BYTE(byte) ((byte) << 8)
3498 #define HOST_BYTE(byte) ((byte) << 16)
3499 #define DRIVER_BYTE(byte) ((byte) << 24)
3502 * The following definitions and macros are OS independent interfaces to
3503 * the queue functions:
3504 * REQ - SCSI request structure
3505 * REQP - pointer to SCSI request structure
3506 * REQPTID(reqp) - reqp's target id
3507 * REQPNEXT(reqp) - reqp's next pointer
3508 * REQPNEXTP(reqp) - pointer to reqp's next pointer
3509 * REQPTIME(reqp) - reqp's time stamp value
3510 * REQTIMESTAMP() - system time stamp value
3512 typedef Scsi_Cmnd REQ, *REQP;
3513 #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
3514 #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
3515 #define REQPTID(reqp) ((reqp)->target)
3516 #define REQPTIME(reqp) ((reqp)->SCp.this_residual)
3517 #define REQTIMESTAMP() (jiffies)
3519 #define REQTIMESTAT(function, ascq, reqp, tid) \
3522 * If the request time stamp is less than the system time stamp, then \
3523 * maybe the system time stamp wrapped. Set the request time to zero.\
3524 */ \
3525 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
3526 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
3527 } else { \
3528 /* Indicate an error occurred with the assertion. */ \
3529 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
3530 REQPTIME(reqp) = 0; \
3532 /* Handle first minimum time case without external initialization. */ \
3533 if (((ascq)->q_tot_cnt[tid] == 1) || \
3534 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
3535 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
3536 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
3537 (function), (tid), (ascq)->q_min_tim[tid]); \
3539 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
3540 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
3541 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
3542 (function), tid, (ascq)->q_max_tim[tid]); \
3544 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
3545 /* Reset the time stamp field. */ \
3546 REQPTIME(reqp) = 0; \
3549 /* asc_enqueue() flags */
3550 #define ASC_FRONT 1
3551 #define ASC_BACK 2
3553 /* asc_dequeue_list() argument */
3554 #define ASC_TID_ALL (-1)
3556 /* Return non-zero, if the queue is empty. */
3557 #define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
3559 /* PCI configuration declarations */
3561 #define PCI_BASE_CLASS_PREDEFINED 0x00
3562 #define PCI_BASE_CLASS_MASS_STORAGE 0x01
3563 #define PCI_BASE_CLASS_NETWORK 0x02
3564 #define PCI_BASE_CLASS_DISPLAY 0x03
3565 #define PCI_BASE_CLASS_MULTIMEDIA 0x04
3566 #define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05
3567 #define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06
3569 /* MASS STORAGE */
3570 #define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00
3571 #define PCI_SUB_CLASS_IDE_CONTROLLER 0x01
3572 #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02
3573 #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03
3574 #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80
3576 /* NETWORK CONTROLLER */
3577 #define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00
3578 #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01
3579 #define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02
3580 #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80
3582 /* DISPLAY CONTROLLER */
3583 #define PCI_SUB_CLASS_VGA_CONTROLLER 0x00
3584 #define PCI_SUB_CLASS_XGA_CONTROLLER 0x01
3585 #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80
3587 /* MULTIMEDIA CONTROLLER */
3588 #define PCI_SUB_CLASS_VIDEO_DEVICE 0x00
3589 #define PCI_SUB_CLASS_AUDIO_DEVICE 0x01
3590 #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80
3592 /* MEMORY CONTROLLER */
3593 #define PCI_SUB_CLASS_RAM_CONTROLLER 0x00
3594 #define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01
3595 #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80
3597 /* BRIDGE CONTROLLER */
3598 #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00
3599 #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01
3600 #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02
3601 #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03
3602 #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04
3603 #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05
3604 #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80
3606 #define PCI_MAX_SLOT 0x1F
3607 #define PCI_MAX_BUS 0xFF
3608 #define PCI_IOADDRESS_MASK 0xFFFE
3609 #define ASC_PCI_VENDORID 0x10CD
3610 #define ASC_PCI_DEVICE_ID_CNT 5 /* PCI Device ID count. */
3611 #define ASC_PCI_DEVICE_ID_1100 0x1100
3612 #define ASC_PCI_DEVICE_ID_1200 0x1200
3613 #define ASC_PCI_DEVICE_ID_1300 0x1300
3614 #define ASC_PCI_DEVICE_ID_2300 0x2300 /* ASC-3550 */
3615 #define ASC_PCI_DEVICE_ID_2500 0x2500 /* ASC-38C0800 */
3617 /* PCI IO Port Addresses to generate special cycle */
3619 #define PCI_CONFIG_ADDRESS_MECH1 0x0CF8
3620 #define PCI_CONFIG_DATA_MECH1 0x0CFC
3622 #define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */
3624 #define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000
3625 #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00
3626 #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8
3628 #define PCI_DEVICE_FOUND 0x0000
3629 #define PCI_DEVICE_NOT_FOUND 0xffff
3631 #define SUBCLASS_OFFSET 0x0A
3632 #define CLASSCODE_OFFSET 0x0B
3633 #define VENDORID_OFFSET 0x00
3634 #define DEVICEID_OFFSET 0x02
3636 #ifndef ADVANSYS_STATS
3637 #define ASC_STATS(shp, counter)
3638 #define ASC_STATS_ADD(shp, counter, count)
3639 #else /* ADVANSYS_STATS */
3640 #define ASC_STATS(shp, counter) \
3641 (ASC_BOARDP(shp)->asc_stats.counter++)
3643 #define ASC_STATS_ADD(shp, counter, count) \
3644 (ASC_BOARDP(shp)->asc_stats.counter += (count))
3645 #endif /* ADVANSYS_STATS */
3647 #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
3649 /* If the result wraps when calculating tenths, return 0. */
3650 #define ASC_TENTHS(num, den) \
3651 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
3652 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
3655 * Display a message to the console.
3657 #define ASC_PRINT(s) \
3659 printk("advansys: "); \
3660 printk(s); \
3663 #define ASC_PRINT1(s, a1) \
3665 printk("advansys: "); \
3666 printk((s), (a1)); \
3669 #define ASC_PRINT2(s, a1, a2) \
3671 printk("advansys: "); \
3672 printk((s), (a1), (a2)); \
3675 #define ASC_PRINT3(s, a1, a2, a3) \
3677 printk("advansys: "); \
3678 printk((s), (a1), (a2), (a3)); \
3681 #define ASC_PRINT4(s, a1, a2, a3, a4) \
3683 printk("advansys: "); \
3684 printk((s), (a1), (a2), (a3), (a4)); \
3688 #ifndef ADVANSYS_DEBUG
3690 #define ASC_DBG(lvl, s)
3691 #define ASC_DBG1(lvl, s, a1)
3692 #define ASC_DBG2(lvl, s, a1, a2)
3693 #define ASC_DBG3(lvl, s, a1, a2, a3)
3694 #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
3695 #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
3696 #define ASC_DBG_PRT_SCSI_CMND(lvl, s)
3697 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
3698 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3699 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
3700 #define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3701 #define ASC_DBG_PRT_HEX(lvl, name, start, length)
3702 #define ASC_DBG_PRT_CDB(lvl, cdb, len)
3703 #define ASC_DBG_PRT_SENSE(lvl, sense, len)
3704 #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
3706 #else /* ADVANSYS_DEBUG */
3709 * Debugging Message Levels:
3710 * 0: Errors Only
3711 * 1: High-Level Tracing
3712 * 2-N: Verbose Tracing
3715 #define ASC_DBG(lvl, s) \
3717 if (asc_dbglvl >= (lvl)) { \
3718 printk(s); \
3722 #define ASC_DBG1(lvl, s, a1) \
3724 if (asc_dbglvl >= (lvl)) { \
3725 printk((s), (a1)); \
3729 #define ASC_DBG2(lvl, s, a1, a2) \
3731 if (asc_dbglvl >= (lvl)) { \
3732 printk((s), (a1), (a2)); \
3736 #define ASC_DBG3(lvl, s, a1, a2, a3) \
3738 if (asc_dbglvl >= (lvl)) { \
3739 printk((s), (a1), (a2), (a3)); \
3743 #define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
3745 if (asc_dbglvl >= (lvl)) { \
3746 printk((s), (a1), (a2), (a3), (a4)); \
3750 #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
3752 if (asc_dbglvl >= (lvl)) { \
3753 asc_prt_scsi_host(s); \
3757 #define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
3759 if (asc_dbglvl >= (lvl)) { \
3760 asc_prt_scsi_cmnd(s); \
3764 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
3766 if (asc_dbglvl >= (lvl)) { \
3767 asc_prt_asc_scsi_q(scsiqp); \
3771 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
3773 if (asc_dbglvl >= (lvl)) { \
3774 asc_prt_asc_qdone_info(qdone); \
3778 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
3780 if (asc_dbglvl >= (lvl)) { \
3781 asc_prt_adv_scsi_req_q(scsiqp); \
3785 #define ASC_DBG_PRT_HEX(lvl, name, start, length) \
3787 if (asc_dbglvl >= (lvl)) { \
3788 asc_prt_hex((name), (start), (length)); \
3792 #define ASC_DBG_PRT_CDB(lvl, cdb, len) \
3793 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
3795 #define ASC_DBG_PRT_SENSE(lvl, sense, len) \
3796 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
3798 #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
3799 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
3800 #endif /* ADVANSYS_DEBUG */
3802 #ifndef ADVANSYS_ASSERT
3803 #define ASC_ASSERT(a)
3804 #else /* ADVANSYS_ASSERT */
3806 #define ASC_ASSERT(a) \
3808 if (!(a)) { \
3809 printk("ASC_ASSERT() Failure: file %s, line %d\n", \
3810 __FILE__, __LINE__); \
3814 #endif /* ADVANSYS_ASSERT */
3818 * --- Driver Structures
3821 #ifdef ADVANSYS_STATS
3823 /* Per board statistics structure */
3824 struct asc_stats {
3825 /* Driver Entrypoint Statistics */
3826 ulong command; /* # calls to advansys_command() */
3827 ulong queuecommand; /* # calls to advansys_queuecommand() */
3828 ulong abort; /* # calls to advansys_abort() */
3829 ulong reset; /* # calls to advansys_reset() */
3830 ulong biosparam; /* # calls to advansys_biosparam() */
3831 ulong interrupt; /* # advansys_interrupt() calls */
3832 ulong callback; /* # calls to asc/adv_isr_callback() */
3833 ulong done; /* # calls to request's scsi_done function */
3834 ulong build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
3835 ulong adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
3836 ulong adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
3837 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
3838 ulong exe_noerror; /* # ASC_NOERROR returns. */
3839 ulong exe_busy; /* # ASC_BUSY returns. */
3840 ulong exe_error; /* # ASC_ERROR returns. */
3841 ulong exe_unknown; /* # unknown returns. */
3842 /* Data Transfer Statistics */
3843 ulong cont_cnt; /* # non-scatter-gather I/O requests received */
3844 ulong cont_xfer; /* # contiguous transfer 512-bytes */
3845 ulong sg_cnt; /* # scatter-gather I/O requests received */
3846 ulong sg_elem; /* # scatter-gather elements */
3847 ulong sg_xfer; /* # scatter-gather transfer 512-bytes */
3849 #endif /* ADVANSYS_STATS */
3852 * Request queuing structure
3854 typedef struct asc_queue {
3855 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
3856 REQP q_first[ADV_MAX_TID+1]; /* first queued request */
3857 REQP q_last[ADV_MAX_TID+1]; /* last queued request */
3858 #ifdef ADVANSYS_STATS
3859 short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */
3860 short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */
3861 ulong q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */
3862 ulong q_tot_tim[ADV_MAX_TID+1]; /* total time queued */
3863 ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */
3864 ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */
3865 #endif /* ADVANSYS_STATS */
3866 } asc_queue_t;
3869 * Adv Library Request Structures
3871 * The following two se structures are used to process Wide Board requests.
3872 * One structure is needed for each command received from the Mid-Level SCSI
3873 * driver.
3875 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
3876 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
3877 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
3878 * Mid-Level SCSI request structure.
3880 * The adv_sgblk_t structure is used to handle requests that include
3881 * scatter-gather elements.
3883 typedef struct adv_sgblk {
3884 ADV_SG_BLOCK sg_block[ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING];
3885 uchar align2[4]; /* Sgblock structure padding. */
3886 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
3887 } adv_sgblk_t;
3889 typedef struct adv_req {
3890 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
3891 uchar align1[4]; /* Request structure padding. */
3892 Scsi_Cmnd *cmndp; /* Mid-Level SCSI command pointer. */
3893 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
3894 struct adv_req *next_reqp; /* Next Request Structure. */
3895 } adv_req_t;
3898 * Structure allocated for each board.
3900 * This structure is allocated by scsi_register() at the end
3901 * of the 'Scsi_Host' structure starting at the 'hostdata'
3902 * field. It is guaranteed to be allocated from DMA-able memory.
3904 typedef struct asc_board {
3905 int id; /* Board Id */
3906 uint flags; /* Board flags */
3907 union {
3908 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
3909 ADV_DVC_VAR adv_dvc_var; /* Wide board */
3910 } dvc_var;
3911 union {
3912 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
3913 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
3914 } dvc_cfg;
3915 asc_queue_t active; /* Active command queue */
3916 asc_queue_t waiting; /* Waiting command queue */
3917 asc_queue_t done; /* Done command queue */
3918 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
3919 Scsi_Device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */
3920 ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */
3921 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
3922 ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */
3923 union {
3924 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
3925 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
3926 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
3927 } eep_config;
3928 ulong last_reset; /* Saved last reset time */
3929 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3930 /* /proc/scsi/advansys/[0...] */
3931 char *prtbuf; /* Statistics Print Buffer */
3932 #endif /* version >= v1.3.0 */
3933 #ifdef ADVANSYS_STATS
3934 struct asc_stats asc_stats; /* Board statistics */
3935 #endif /* ADVANSYS_STATS */
3937 * The following fields are used only for Narrow Boards.
3939 /* The following three structures must be in DMA-able memory. */
3940 ASC_SCSI_REQ_Q scsireqq;
3941 ASC_CAP_INFO cap_info;
3942 ASC_SCSI_INQUIRY inquiry;
3943 uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */
3945 * The following fields are used only for Wide Boards.
3947 void *ioremap_addr; /* I/O Memory remap address. */
3948 ushort ioport; /* I/O Port address. */
3949 ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */
3950 adv_req_t *orig_reqp; /* adv_req_t memory block. */
3951 adv_req_t *adv_reqp; /* Request structures. */
3952 adv_sgblk_t *orig_sgblkp; /* adv_sgblk_t memory block. */
3953 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
3954 ushort bios_signature; /* BIOS Signature. */
3955 ushort bios_version; /* BIOS Version. */
3956 ushort bios_codeseg; /* BIOS Code Segment. */
3957 ushort bios_codelen; /* BIOS Code Segment Length. */
3958 } asc_board_t;
3961 * PCI configuration structures
3963 typedef struct _PCI_DATA_
3965 uchar type;
3966 uchar bus;
3967 uchar slot;
3968 uchar func;
3969 uchar offset;
3970 } PCI_DATA;
3972 typedef struct _PCI_DEVICE_
3974 ushort vendorID;
3975 ushort deviceID;
3976 ushort slotNumber;
3977 ushort slotFound;
3978 uchar busNumber;
3979 uchar maxBusNumber;
3980 uchar devFunc;
3981 ushort startSlot;
3982 ushort endSlot;
3983 uchar bridge;
3984 uchar type;
3985 } PCI_DEVICE;
3987 typedef struct _PCI_CONFIG_SPACE_
3989 ushort vendorID;
3990 ushort deviceID;
3991 ushort command;
3992 ushort status;
3993 uchar revision;
3994 uchar classCode[3];
3995 uchar cacheSize;
3996 uchar latencyTimer;
3997 uchar headerType;
3998 uchar bist;
3999 ulong baseAddress[6];
4000 ushort reserved[4];
4001 ulong optionRomAddr;
4002 ushort reserved2[4];
4003 uchar irqLine;
4004 uchar irqPin;
4005 uchar minGnt;
4006 uchar maxLatency;
4007 } PCI_CONFIG_SPACE;
4011 * --- Driver Data
4014 /* Note: All driver global data should be initialized. */
4016 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4017 struct proc_dir_entry proc_scsi_advansys =
4019 PROC_SCSI_ADVANSYS, /* unsigned short low_ino */
4020 8, /* unsigned short namelen */
4021 "advansys", /* const char *name */
4022 S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */
4023 2 /* nlink_t nlink */
4025 #endif /* version >= v1.3.0 */
4027 /* Number of boards detected in system. */
4028 STATIC int asc_board_count = 0;
4029 STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
4031 /* Overrun buffer shared between all boards. */
4032 STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
4035 * Global structures required to issue a command.
4037 STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
4038 STATIC ASC_SG_HEAD asc_sg_head = { 0 };
4040 /* List of supported bus types. */
4041 STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
4042 ASC_IS_ISA,
4043 ASC_IS_VL,
4044 ASC_IS_EISA,
4045 ASC_IS_PCI,
4048 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4049 #ifdef ASC_CONFIG_PCI
4050 STATIC int pci_scan_method ASC_INITDATA = -1;
4051 #endif /* ASC_CONFIG_PCI */
4052 #endif /* version < v2.1.93 */
4055 * Used with the LILO 'advansys' option to eliminate or
4056 * limit I/O port probing at boot time, cf. advansys_setup().
4058 STATIC int asc_iopflag = ASC_FALSE;
4059 STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
4061 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
4063 * In kernels earlier than v1.3.0, kmalloc() does not work
4064 * during driver initialization. Therefore statically declare
4065 * 16 elements of each structure. v1.3.0 kernels will probably
4066 * not need any more than this number.
4068 uchar adv_carr_buf[20 * sizeof(ADV_CARR_T)] = { 0 };
4069 uchar adv_req_buf[16 * sizeof(adv_req_t)] = { 0 };
4070 uchar adv_sgblk_buf[16 * sizeof(adv_sgblk_t)] = { 0 };
4071 #endif /* version >= v1,3,0 */
4073 #ifdef ADVANSYS_DEBUG
4074 STATIC char *
4075 asc_bus_name[ASC_NUM_BUS] = {
4076 "ASC_IS_ISA",
4077 "ASC_IS_VL",
4078 "ASC_IS_EISA",
4079 "ASC_IS_PCI",
4082 STATIC int asc_dbglvl = 0;
4083 #endif /* ADVANSYS_DEBUG */
4085 /* Declaration for Asc Library internal data referenced by driver. */
4086 STATIC PortAddr _asc_def_iop_base[];
4090 * --- Driver Function Prototypes
4092 * advansys.h contains function prototypes for functions global to Linux.
4095 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4096 STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int);
4097 #endif /* version >= v1.3.0 */
4098 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
4099 STATIC void advansys_interrupt(int, struct pt_regs *);
4100 #else /* version >= v1.3.70 */
4101 STATIC void advansys_interrupt(int, void *, struct pt_regs *);
4102 #endif /* version >= v1.3.70 */
4103 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
4104 STATIC void advansys_select_queue_depths(struct Scsi_Host *,
4105 Scsi_Device *);
4106 #endif /* version >= v1.3.89 */
4107 STATIC void advansys_command_done(Scsi_Cmnd *);
4108 STATIC void asc_scsi_done_list(Scsi_Cmnd *);
4109 STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
4110 STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *);
4111 STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
4112 STATIC int adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *);
4113 STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
4114 STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
4115 STATIC void adv_async_callback(ADV_DVC_VAR *, uchar);
4116 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4117 #ifdef ASC_CONFIG_PCI
4118 STATIC int asc_srch_pci_dev(PCI_DEVICE *);
4119 STATIC uchar asc_scan_method(void);
4120 STATIC int asc_pci_find_dev(PCI_DEVICE *);
4121 STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
4122 STATIC ushort asc_get_cfg_word(PCI_DATA *);
4123 STATIC uchar asc_get_cfg_byte(PCI_DATA *);
4124 STATIC void asc_put_cfg_byte(PCI_DATA *, uchar);
4125 #endif /* ASC_CONFIG_PCI */
4126 #endif /* version < v2.1.93 */
4127 STATIC void asc_enqueue(asc_queue_t *, REQP, int);
4128 STATIC REQP asc_dequeue(asc_queue_t *, int);
4129 STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
4130 STATIC int asc_rmqueue(asc_queue_t *, REQP);
4131 STATIC int asc_isqueued(asc_queue_t *, REQP);
4132 STATIC void asc_execute_queue(asc_queue_t *);
4133 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4134 STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int);
4135 STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
4136 STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
4137 STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
4138 STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
4139 STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
4140 STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
4141 STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
4142 STATIC int asc_prt_line(char *, int, char *fmt, ...);
4143 #endif /* version >= v1.3.0 */
4145 /* Declaration for Asc Library internal functions referenced by driver. */
4146 STATIC int AscFindSignature(PortAddr);
4147 STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
4149 #ifdef ADVANSYS_STATS
4150 STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int);
4151 #endif /* ADVANSYS_STATS */
4153 #ifdef ADVANSYS_DEBUG
4154 STATIC void asc_prt_scsi_host(struct Scsi_Host *);
4155 STATIC void asc_prt_scsi_cmnd(Scsi_Cmnd *);
4156 STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
4157 STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
4158 STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
4159 STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
4160 STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
4161 STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
4162 STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
4163 STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
4164 STATIC void asc_prt_hex(char *f, uchar *, int);
4165 #endif /* ADVANSYS_DEBUG */
4167 #ifdef ADVANSYS_ASSERT
4168 STATIC int interrupts_enabled(void);
4169 #endif /* ADVANSYS_ASSERT */
4173 * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
4176 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4178 * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
4180 * *buffer: I/O buffer
4181 * **start: if inout == FALSE pointer into buffer where user read should start
4182 * offset: current offset into a /proc/scsi/advansys/[0...] file
4183 * length: length of buffer
4184 * hostno: Scsi_Host host_no
4185 * inout: TRUE - user is writing; FALSE - user is reading
4187 * Return the number of bytes read from or written to a
4188 * /proc/scsi/advansys/[0...] file.
4190 * Note: This function uses the per board buffer 'prtbuf' which is
4191 * allocated when the board is initialized in advansys_detect(). The
4192 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
4193 * used to write to the buffer. The way asc_proc_copy() is written
4194 * if 'prtbuf' is too small it will not be overwritten. Instead the
4195 * user just won't get all the available statistics.
4198 advansys_proc_info(char *buffer, char **start, off_t offset, int length,
4199 int hostno, int inout)
4201 #ifdef CONFIG_PROC_FS
4202 struct Scsi_Host *shp;
4203 asc_board_t *boardp;
4204 int i;
4205 char *cp;
4206 int cplen;
4207 int cnt;
4208 int totcnt;
4209 int leftlen;
4210 char *curbuf;
4211 off_t advoffset;
4212 Scsi_Device *scd;
4214 ASC_DBG(1, "advansys_proc_info: begin\n");
4217 * User write not supported.
4219 if (inout == TRUE) {
4220 return(-ENOSYS);
4224 * User read of /proc/scsi/advansys/[0...] file.
4227 /* Find the specified board. */
4228 for (i = 0; i < asc_board_count; i++) {
4229 if (asc_host[i]->host_no == hostno) {
4230 break;
4233 if (i == asc_board_count) {
4234 return(-ENOENT);
4237 shp = asc_host[i];
4238 boardp = ASC_BOARDP(shp);
4240 /* Copy read data starting at the beginning of the buffer. */
4241 *start = buffer;
4242 curbuf = buffer;
4243 advoffset = 0;
4244 totcnt = 0;
4245 leftlen = length;
4248 * Get board configuration information.
4250 * advansys_info() returns the board string from its own static buffer.
4252 cp = (char *) advansys_info(shp);
4253 strcat(cp, "\n");
4254 cplen = strlen(cp);
4255 /* Copy board information. */
4256 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4257 totcnt += cnt;
4258 leftlen -= cnt;
4259 if (leftlen == 0) {
4260 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4261 return totcnt;
4263 advoffset += cplen;
4264 curbuf += cnt;
4267 * Display Wide Board BIOS Information.
4269 if (ASC_WIDE_BOARD(boardp)) {
4270 cp = boardp->prtbuf;
4271 cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
4272 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4273 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4274 totcnt += cnt;
4275 leftlen -= cnt;
4276 if (leftlen == 0) {
4277 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4278 return totcnt;
4280 advoffset += cplen;
4281 curbuf += cnt;
4285 * Display driver information for each device attached to the board.
4287 cp = boardp->prtbuf;
4288 cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
4289 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4290 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4291 totcnt += cnt;
4292 leftlen -= cnt;
4293 if (leftlen == 0) {
4294 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4295 return totcnt;
4297 advoffset += cplen;
4298 curbuf += cnt;
4301 * Display target driver information for each device attached
4302 * to the board.
4304 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75)
4305 for (scd = scsi_devices; scd; scd = scd->next)
4306 #else /* version >= v2.1.75 */
4307 for (scd = shp->host_queue; scd; scd = scd->next)
4308 #endif /* version >= v2.1.75 */
4310 if (scd->host == shp) {
4311 cp = boardp->prtbuf;
4313 * Note: If proc_print_scsidevice() writes more than
4314 * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'.
4316 proc_print_scsidevice(scd, cp, &cplen, 0);
4317 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4318 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4319 totcnt += cnt;
4320 leftlen -= cnt;
4321 if (leftlen == 0) {
4322 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4323 return totcnt;
4325 advoffset += cplen;
4326 curbuf += cnt;
4331 * Display EEPROM configuration for the board.
4333 cp = boardp->prtbuf;
4334 if (ASC_NARROW_BOARD(boardp)) {
4335 cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4336 } else {
4337 cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4339 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4340 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4341 totcnt += cnt;
4342 leftlen -= cnt;
4343 if (leftlen == 0) {
4344 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4345 return totcnt;
4347 advoffset += cplen;
4348 curbuf += cnt;
4351 * Display driver configuration and information for the board.
4353 cp = boardp->prtbuf;
4354 cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
4355 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4356 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4357 totcnt += cnt;
4358 leftlen -= cnt;
4359 if (leftlen == 0) {
4360 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4361 return totcnt;
4363 advoffset += cplen;
4364 curbuf += cnt;
4366 #ifdef ADVANSYS_STATS
4368 * Display driver statistics for the board.
4370 cp = boardp->prtbuf;
4371 cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
4372 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4373 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4374 totcnt += cnt;
4375 leftlen -= cnt;
4376 if (leftlen == 0) {
4377 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4378 return totcnt;
4380 advoffset += cplen;
4381 curbuf += cnt;
4382 #endif /* ADVANSYS_STATS */
4385 * Display Asc Library dynamic configuration information
4386 * for the board.
4388 cp = boardp->prtbuf;
4389 if (ASC_NARROW_BOARD(boardp)) {
4390 cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
4391 } else {
4392 cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
4394 ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4395 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4396 totcnt += cnt;
4397 leftlen -= cnt;
4398 if (leftlen == 0) {
4399 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4400 return totcnt;
4402 advoffset += cplen;
4403 curbuf += cnt;
4405 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4407 return totcnt;
4408 #else /* CONFIG_PROC_FS */
4409 return 0;
4410 #endif /* CONFIG_PROC_FS */
4412 #endif /* version >= v1.3.0 */
4415 * advansys_detect()
4417 * Detect function for AdvanSys adapters.
4419 * Argument is a pointer to the host driver's scsi_hosts entry.
4421 * Return number of adapters found.
4423 * Note: Because this function is called during system initialization
4424 * it must not call SCSI mid-level functions including scsi_malloc()
4425 * and scsi_free().
4427 ASC_INITFUNC(
4428 int,
4429 advansys_detect(Scsi_Host_Template *tpnt)
4432 static int detect_called = ASC_FALSE;
4433 int iop;
4434 int bus;
4435 struct Scsi_Host *shp = NULL;
4436 asc_board_t *boardp = NULL;
4437 ASC_DVC_VAR *asc_dvc_varp = NULL;
4438 ADV_DVC_VAR *adv_dvc_varp = NULL;
4439 int ioport = 0;
4440 int share_irq = FALSE;
4441 int iolen = 0;
4442 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4443 #ifdef ASC_CONFIG_PCI
4444 int pci_init_search = 0;
4445 PCI_DEVICE pci_device[ASC_NUM_BOARD_SUPPORTED];
4446 int pci_card_cnt_max = 0;
4447 int pci_card_cnt = 0;
4448 PCI_DEVICE pciDevice;
4449 PCI_CONFIG_SPACE pciConfig;
4450 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4451 unsigned long pci_memory_address;
4452 #endif /* version >= v1,3,0 */
4453 #endif /* ASC_CONFIG_PCI */
4454 #else /* version >= v2.1.93 */
4455 #ifdef CONFIG_PCI
4456 int pci_init_search = 0;
4457 struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED];
4458 int pci_card_cnt_max = 0;
4459 int pci_card_cnt = 0;
4460 struct pci_dev *pci_devp = NULL;
4461 int pci_device_id_cnt = 0;
4462 unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
4463 ASC_PCI_DEVICE_ID_1100,
4464 ASC_PCI_DEVICE_ID_1200,
4465 ASC_PCI_DEVICE_ID_1300,
4466 ASC_PCI_DEVICE_ID_2300,
4467 ASC_PCI_DEVICE_ID_2500
4469 unsigned long pci_memory_address;
4470 #endif /* CONFIG_PCI */
4471 #endif /* version >= v2.1.93 */
4472 int warn_code, err_code;
4473 int ret;
4475 if (detect_called == ASC_FALSE) {
4476 detect_called = ASC_TRUE;
4477 } else {
4478 printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n");
4479 return 0;
4482 ASC_DBG(1, "advansys_detect: begin\n");
4484 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4485 tpnt->proc_dir = &proc_scsi_advansys;
4486 #endif /* version >= v1.3.0 */
4488 asc_board_count = 0;
4491 * If I/O port probing has been modified, then verify and
4492 * clean-up the 'asc_ioport' list.
4494 if (asc_iopflag == ASC_TRUE) {
4495 for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
4496 ASC_DBG2(1, "advansys_detect: asc_ioport[%d] %x\n",
4497 ioport, asc_ioport[ioport]);
4498 if (asc_ioport[ioport] != 0) {
4499 for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
4500 if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
4501 break;
4504 if (iop == ASC_IOADR_TABLE_MAX_IX) {
4505 printk(
4506 "AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
4507 asc_ioport[ioport]);
4508 asc_ioport[ioport] = 0;
4512 ioport = 0;
4515 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4516 #ifdef ASC_CONFIG_PCI
4517 memset(&pciDevice, 0, sizeof(PCI_DEVICE));
4518 memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
4519 pciDevice.maxBusNumber = PCI_MAX_BUS;
4520 pciDevice.endSlot = PCI_MAX_SLOT;
4521 #endif /* ASC_CONFIG_PCI */
4522 #endif /* version < v2.1.93 */
4524 for (bus = 0; bus < ASC_NUM_BUS; bus++) {
4526 ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
4527 bus, asc_bus_name[bus]);
4528 iop = 0;
4530 while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
4532 ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
4533 asc_board_count);
4535 switch (asc_bus[bus]) {
4536 case ASC_IS_ISA:
4537 case ASC_IS_VL:
4538 if (asc_iopflag == ASC_FALSE) {
4539 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
4540 } else {
4542 * ISA and VL I/O port scanning has either been
4543 * eliminated or limited to selected ports on
4544 * the LILO command line, /etc/lilo.conf, or
4545 * by setting variables when the module was loaded.
4547 ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
4548 ioport_try_again:
4549 iop = 0;
4550 for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
4551 if ((iop = asc_ioport[ioport]) != 0) {
4552 break;
4555 if (iop) {
4556 ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
4557 iop);
4558 if (check_region(iop, ASC_IOADR_GAP) != 0) {
4559 printk(
4560 "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
4561 /* Don't try this I/O port twice. */
4562 asc_ioport[ioport] = 0;
4563 goto ioport_try_again;
4564 } else if (AscFindSignature(iop) == ASC_FALSE) {
4565 printk(
4566 "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
4567 /* Don't try this I/O port twice. */
4568 asc_ioport[ioport] = 0;
4569 goto ioport_try_again;
4570 } else {
4572 * If this isn't an ISA board, then it must be
4573 * a VL board. If currently looking an ISA
4574 * board is being looked for then try for
4575 * another ISA board in 'asc_ioport'.
4577 if (asc_bus[bus] == ASC_IS_ISA &&
4578 (AscGetChipVersion(iop, ASC_IS_ISA) &
4579 ASC_CHIP_VER_ISA_BIT) == 0) {
4581 * Don't clear 'asc_ioport[ioport]'. Try
4582 * this board again for VL. Increment
4583 * 'ioport' past this board.
4585 ioport++;
4586 goto ioport_try_again;
4590 * This board appears good, don't try the I/O port
4591 * again by clearing its value. Increment 'ioport'
4592 * for the next iteration.
4594 asc_ioport[ioport++] = 0;
4597 break;
4599 case ASC_IS_EISA:
4600 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
4601 break;
4603 case ASC_IS_PCI:
4604 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4605 #ifdef ASC_CONFIG_PCI
4606 if (pci_init_search == 0) {
4607 int i, j;
4609 pci_init_search = 1;
4611 /* Find all PCI cards. */
4612 while (asc_srch_pci_dev(&pciDevice) == PCI_DEVICE_FOUND) {
4613 pci_device[pci_card_cnt_max++] = pciDevice;
4617 * Sort PCI cards in ascending order by PCI Bus, Slot,
4618 * and Device Number.
4620 for (i = 0; i < pci_card_cnt_max - 1; i++)
4622 for (j = i + 1; j < pci_card_cnt_max; j++) {
4623 if ((pci_device[j].busNumber <
4624 pci_device[i].busNumber) ||
4625 ((pci_device[j].busNumber ==
4626 pci_device[i].busNumber) &&
4627 (pci_device[j].slotNumber <
4628 pci_device[i].slotNumber)) ||
4629 ((pci_device[j].busNumber ==
4630 pci_device[i].busNumber) &&
4631 (pci_device[j].slotNumber ==
4632 pci_device[i].slotNumber) &&
4633 (pci_device[j].devFunc <
4634 pci_device[i].devFunc))) {
4635 pciDevice = pci_device[i];
4636 pci_device[i] = pci_device[j];
4637 pci_device[j] = pciDevice;
4642 pci_card_cnt = 0;
4643 } else {
4644 pci_card_cnt++;
4647 if (pci_card_cnt == pci_card_cnt_max) {
4648 iop = 0;
4649 } else {
4650 pciDevice = pci_device[pci_card_cnt];
4651 ASC_DBG2(2,
4652 "advansys_detect: slotFound %d, busNumber %d\n",
4653 pciDevice.slotFound, pciDevice.busNumber);
4654 asc_get_pci_cfg(&pciDevice, &pciConfig);
4655 iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
4656 ASC_DBG2(1,
4657 "advansys_detect: vendorID %X, deviceID %X\n",
4658 pciConfig.vendorID, pciConfig.deviceID);
4659 ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
4660 iop, pciConfig.irqLine);
4662 break;
4663 #endif /* ASC_CONFIG_PCI */
4664 #else /* version >= v2.1.93 */
4665 #ifdef CONFIG_PCI
4666 if (pci_init_search == 0) {
4667 int i, j;
4669 pci_init_search = 1;
4671 /* Find all PCI cards. */
4672 while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) {
4673 if ((pci_devp = pci_find_device(ASC_PCI_VENDORID,
4674 pci_device_id[pci_device_id_cnt], pci_devp)) ==
4675 NULL) {
4676 pci_device_id_cnt++;
4677 } else {
4678 pci_devicep[pci_card_cnt_max++] = pci_devp;
4683 * Sort PCI cards in ascending order by PCI Bus, Slot,
4684 * and Device Number.
4686 for (i = 0; i < pci_card_cnt_max - 1; i++)
4688 for (j = i + 1; j < pci_card_cnt_max; j++) {
4689 if ((pci_devicep[j]->bus->number <
4690 pci_devicep[i]->bus->number) ||
4691 ((pci_devicep[j]->bus->number ==
4692 pci_devicep[i]->bus->number) &&
4693 (pci_devicep[j]->devfn <
4694 pci_devicep[i]->devfn))) {
4695 pci_devp = pci_devicep[i];
4696 pci_devicep[i] = pci_devicep[j];
4697 pci_devicep[j] = pci_devp;
4702 pci_card_cnt = 0;
4703 } else {
4704 pci_card_cnt++;
4707 if (pci_card_cnt == pci_card_cnt_max) {
4708 iop = 0;
4709 } else {
4710 pci_devp = pci_devicep[pci_card_cnt];
4712 ASC_DBG2(2,
4713 "advansys_detect: devfn %d, bus number %d\n",
4714 pci_devp->devfn, pci_devp->bus->number);
4715 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,13)
4716 iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK;
4717 #else /* version >= v2.3.13 */
4718 iop = pci_devp->resource[0].start & PCI_IOADDRESS_MASK;
4719 #endif /* version >= v2.3.13 */
4720 ASC_DBG2(1,
4721 "advansys_detect: vendorID %X, deviceID %X\n",
4722 pci_devp->vendor, pci_devp->device);
4723 ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
4724 iop, pci_devp->irq);
4726 #endif /* CONFIG_PCI */
4727 #endif /* version >= v2.1.93 */
4728 break;
4730 default:
4731 ASC_PRINT1("advansys_detect: unknown bus type: %d\n",
4732 asc_bus[bus]);
4733 break;
4735 ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
4738 * Adapter not found, try next bus type.
4740 if (iop == 0) {
4741 break;
4745 * Adapter found.
4747 * Register the adapter, get its configuration, and
4748 * initialize it.
4750 ASC_DBG(2, "advansys_detect: scsi_register()\n");
4751 shp = scsi_register(tpnt, sizeof(asc_board_t));
4753 /* Save a pointer to the Scsi_host of each board found. */
4754 asc_host[asc_board_count++] = shp;
4756 /* Initialize private per board data */
4757 boardp = ASC_BOARDP(shp);
4758 memset(boardp, 0, sizeof(asc_board_t));
4759 boardp->id = asc_board_count - 1;
4762 * Handle both narrow and wide boards.
4764 * If a Wide board was detected, set the board structure
4765 * wide board flag. Set-up the board structure based on
4766 * the board type.
4768 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4769 #ifdef ASC_CONFIG_PCI
4770 if (asc_bus[bus] == ASC_IS_PCI &&
4771 (pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300 ||
4772 pciConfig.deviceID == ASC_PCI_DEVICE_ID_2500))
4774 boardp->flags |= ASC_IS_WIDE_BOARD;
4776 #endif /* ASC_CONFIG_PCI */
4777 #else /* version >= v2.1.93 */
4778 #ifdef CONFIG_PCI
4779 if (asc_bus[bus] == ASC_IS_PCI &&
4780 (pci_devp->device == ASC_PCI_DEVICE_ID_2300 ||
4781 pci_devp->device == ASC_PCI_DEVICE_ID_2500))
4783 boardp->flags |= ASC_IS_WIDE_BOARD;
4785 #endif /* CONFIG_PCI */
4786 #endif /* version >= v2.1.93 */
4788 if (ASC_NARROW_BOARD(boardp)) {
4789 ASC_DBG(1, "advansys_detect: narrow board\n");
4790 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4791 asc_dvc_varp->bus_type = asc_bus[bus];
4792 asc_dvc_varp->drv_ptr = (ulong) boardp;
4793 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
4794 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
4795 asc_dvc_varp->iop_base = iop;
4796 asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback;
4797 } else {
4798 ASC_DBG(1, "advansys_detect: wide board\n");
4799 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4800 adv_dvc_varp->drv_ptr = (ulong) boardp;
4801 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
4802 adv_dvc_varp->isr_callback = adv_isr_callback;
4803 adv_dvc_varp->async_callback = adv_async_callback;
4805 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4806 #ifdef ASC_CONFIG_PCI
4807 if (pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300)
4809 ASC_DBG(1, "advansys_detect: ASC-3550\n");
4810 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
4811 } else
4813 ASC_DBG(1, "advansys_detect: ASC-38C0800\n");
4814 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
4816 #endif /* ASC_CONFIG_PCI */
4817 #else /* version >= v2.1.93 */
4818 #ifdef CONFIG_PCI
4819 if (pci_devp->device == ASC_PCI_DEVICE_ID_2300)
4821 ASC_DBG(1, "advansys_detect: ASC-3550\n");
4822 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
4823 } else
4825 ASC_DBG(1, "advansys_detect: ASC-38C0800\n");
4826 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
4828 #endif /* CONFIG_PCI */
4829 #endif /* version >= v2.1.93 */
4831 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
4832 adv_dvc_varp->iop_base = iop;
4833 #else /* version >= v1,3,0 */
4835 * Map the board's registers into virtual memory for
4836 * PCI slave access. Only memory accesses are used to
4837 * access the board's registers.
4839 * Note: The PCI register base address is not always
4840 * page aligned, but the address passed to ioremap()
4841 * must be page aligned. It is guaranteed that the
4842 * PCI register base address will not cross a page
4843 * boundary.
4845 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
4847 iolen = ADV_3550_IOLEN;
4848 } else {
4849 iolen = ADV_38C0800_IOLEN;
4851 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4852 #ifdef ASC_CONFIG_PCI
4853 pci_memory_address = pciConfig.baseAddress[1];
4854 ASC_DBG1(1, "advansys_detect: pci_memory_address: %lu\n",
4855 pci_memory_address);
4856 if ((boardp->ioremap_addr =
4857 ioremap(pci_memory_address & PAGE_MASK,
4858 PAGE_SIZE)) == 0) {
4859 ASC_PRINT3(
4860 "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
4861 boardp->id, pci_memory_address, iolen);
4862 scsi_unregister(shp);
4863 asc_board_count--;
4864 continue;
4866 ASC_DBG1(1, "advansys_detect: ioremap_addr: %lx\n",
4867 (ulong) boardp->ioremap_addr);
4868 adv_dvc_varp->iop_base = (AdvPortAddr)
4869 (boardp->ioremap_addr +
4870 (pci_memory_address - (pci_memory_address & PAGE_MASK)));
4871 ASC_DBG1(1, "advansys_detect: iop_base: %lx\n",
4872 adv_dvc_varp->iop_base);
4873 #endif /* ASC_CONFIG_PCI */
4874 #else /* version >= v2.1.93 */
4875 #ifdef CONFIG_PCI
4876 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,13)
4877 pci_memory_address = pci_devp->base_address[1];
4878 #else /* version >= v2.3.13 */
4879 pci_memory_address = pci_devp->resource[1].start;
4880 #endif /* version >= v2.3.13 */
4881 ASC_DBG1(1, "advansys_detect: pci_memory_address: %lu\n",
4882 pci_memory_address);
4883 if ((boardp->ioremap_addr =
4884 ioremap(pci_memory_address & PAGE_MASK,
4885 PAGE_SIZE)) == 0) {
4886 ASC_PRINT3(
4887 "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
4888 boardp->id, pci_memory_address, iolen);
4889 scsi_unregister(shp);
4890 asc_board_count--;
4891 continue;
4893 ASC_DBG1(1, "advansys_detect: ioremap_addr: %lx\n",
4894 (ulong) boardp->ioremap_addr);
4895 adv_dvc_varp->iop_base = (AdvPortAddr)
4896 (boardp->ioremap_addr +
4897 (pci_memory_address - (pci_memory_address & PAGE_MASK)));
4898 ASC_DBG1(1, "advansys_detect: iop_base: %lx\n",
4899 adv_dvc_varp->iop_base);
4900 #endif /* CONFIG_PCI */
4901 #endif /* version >= v2.1.93 */
4902 #endif /* version >= v1,3,0 */
4905 * Even though it isn't used to access the board in
4906 * kernels greater than or equal to v1.3.0, save
4907 * the I/O Port address so that it can be reported and
4908 * displayed.
4910 boardp->ioport = iop;
4912 ASC_DBG2(1, "iopb_chip_id_1 %x, iopw_chip_id_0 %x\n",
4913 (ushort) inp(iop + 1), (ushort) inpw(iop));
4916 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4918 * Allocate buffer for printing information from
4919 * /proc/scsi/advansys/[0...].
4921 if ((boardp->prtbuf =
4922 kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
4923 ASC_PRINT3(
4924 "advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n",
4925 boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
4926 scsi_unregister(shp);
4927 asc_board_count--;
4928 continue;
4930 #endif /* version >= v1.3.0 */
4932 if (ASC_NARROW_BOARD(boardp)) {
4934 * Set the board bus type and PCI IRQ before
4935 * calling AscInitGetConfig().
4937 switch (asc_dvc_varp->bus_type) {
4938 case ASC_IS_ISA:
4939 shp->unchecked_isa_dma = TRUE;
4940 share_irq = FALSE;
4941 break;
4942 case ASC_IS_VL:
4943 shp->unchecked_isa_dma = FALSE;
4944 share_irq = FALSE;
4945 break;
4946 case ASC_IS_EISA:
4947 shp->unchecked_isa_dma = FALSE;
4948 share_irq = TRUE;
4949 break;
4950 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4951 #ifdef ASC_CONFIG_PCI
4952 case ASC_IS_PCI:
4953 shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine;
4954 asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
4955 asc_dvc_varp->cfg->pci_slot_info =
4956 ASC_PCI_MKID(pciDevice.busNumber,
4957 pciDevice.slotFound,
4958 pciDevice.devFunc);
4959 shp->unchecked_isa_dma = FALSE;
4960 share_irq = TRUE;
4961 break;
4962 #endif /* ASC_CONFIG_PCI */
4963 #else /* version >= v2.1.93 */
4964 #ifdef CONFIG_PCI
4965 case ASC_IS_PCI:
4966 shp->irq = asc_dvc_varp->irq_no = pci_devp->irq;
4967 asc_dvc_varp->cfg->pci_device_id = pci_devp->device;
4968 asc_dvc_varp->cfg->pci_slot_info =
4969 ASC_PCI_MKID(pci_devp->bus->number,
4970 PCI_SLOT(pci_devp->devfn),
4971 PCI_FUNC(pci_devp->devfn));
4972 shp->unchecked_isa_dma = FALSE;
4973 share_irq = TRUE;
4974 break;
4975 #endif /* CONFIG_PCI */
4976 #endif /* version >= v2.1.93 */
4977 default:
4978 ASC_PRINT2(
4979 "advansys_detect: board %d: unknown adapter type: %d\n",
4980 boardp->id, asc_dvc_varp->bus_type);
4981 shp->unchecked_isa_dma = TRUE;
4982 share_irq = FALSE;
4983 break;
4985 } else {
4987 * For Wide boards set PCI information before calling
4988 * AdvInitGetConfig().
4990 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4991 #ifdef ASC_CONFIG_PCI
4992 shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine;
4993 adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
4994 adv_dvc_varp->cfg->pci_slot_info =
4995 ASC_PCI_MKID(pciDevice.busNumber,
4996 pciDevice.slotFound,
4997 pciDevice.devFunc);
4998 shp->unchecked_isa_dma = FALSE;
4999 share_irq = TRUE;
5000 #endif /* ASC_CONFIG_PCI */
5001 #else /* version >= v2.1.93 */
5002 #ifdef CONFIG_PCI
5003 shp->irq = adv_dvc_varp->irq_no = pci_devp->irq;
5004 adv_dvc_varp->cfg->pci_device_id = pci_devp->device;
5005 adv_dvc_varp->cfg->pci_slot_info =
5006 ASC_PCI_MKID(pci_devp->bus->number,
5007 PCI_SLOT(pci_devp->devfn),
5008 PCI_FUNC(pci_devp->devfn));
5009 shp->unchecked_isa_dma = FALSE;
5010 share_irq = TRUE;
5011 #endif /* CONFIG_PCI */
5012 #endif /* version >= v2.1.93 */
5016 * Read the board configuration.
5018 if (ASC_NARROW_BOARD(boardp)) {
5020 * NOTE: AscInitGetConfig() may change the board's
5021 * bus_type value. The asc_bus[bus] value should no
5022 * longer be used. If the bus_type field must be
5023 * referenced only use the bit-wise AND operator "&".
5025 ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
5026 switch(ret = AscInitGetConfig(asc_dvc_varp)) {
5027 case 0: /* No error */
5028 break;
5029 case ASC_WARN_IO_PORT_ROTATE:
5030 ASC_PRINT1(
5031 "AscInitGetConfig: board %d: I/O port address modified\n",
5032 boardp->id);
5033 break;
5034 case ASC_WARN_AUTO_CONFIG:
5035 ASC_PRINT1(
5036 "AscInitGetConfig: board %d: I/O port increment switch enabled\n",
5037 boardp->id);
5038 break;
5039 case ASC_WARN_EEPROM_CHKSUM:
5040 ASC_PRINT1(
5041 "AscInitGetConfig: board %d: EEPROM checksum error\n",
5042 boardp->id);
5043 break;
5044 case ASC_WARN_IRQ_MODIFIED:
5045 ASC_PRINT1(
5046 "AscInitGetConfig: board %d: IRQ modified\n",
5047 boardp->id);
5048 break;
5049 case ASC_WARN_CMD_QNG_CONFLICT:
5050 ASC_PRINT1(
5051 "AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
5052 boardp->id);
5053 break;
5054 default:
5055 ASC_PRINT2(
5056 "AscInitGetConfig: board %d: unknown warning: %x\n",
5057 boardp->id, ret);
5058 break;
5060 if ((err_code = asc_dvc_varp->err_code) != 0) {
5061 ASC_PRINT3(
5062 "AscInitGetConfig: board %d error: init_state %x, err_code %x\n",
5063 boardp->id, asc_dvc_varp->init_state,
5064 asc_dvc_varp->err_code);
5066 } else {
5067 ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n");
5068 if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
5069 ASC_PRINT2("AdvInitGetConfig: board %d: warning: %x\n",
5070 boardp->id, ret);
5072 if ((err_code = adv_dvc_varp->err_code) != 0) {
5073 ASC_PRINT2(
5074 "AdvInitGetConfig: board %d error: err_code %x\n",
5075 boardp->id, adv_dvc_varp->err_code);
5079 if (err_code != 0) {
5080 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5081 kfree(boardp->prtbuf);
5082 #endif /* version >= v1.3.0 */
5083 scsi_unregister(shp);
5084 asc_board_count--;
5085 continue;
5089 * Save the EEPROM configuration so that it can be displayed
5090 * from /proc/scsi/advansys/[0...].
5092 if (ASC_NARROW_BOARD(boardp)) {
5094 ASCEEP_CONFIG *ep;
5097 * Set the adapter's target id bit in the 'init_tidmask' field.
5099 boardp->init_tidmask |=
5100 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
5103 * Save EEPROM settings for the board.
5105 ep = &boardp->eep_config.asc_eep;
5107 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
5108 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
5109 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
5110 ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed;
5111 ep->start_motor = asc_dvc_varp->start_motor;
5112 ep->cntl = asc_dvc_varp->dvc_cntl;
5113 ep->no_scam = asc_dvc_varp->no_scam;
5114 ep->max_total_qng = asc_dvc_varp->max_total_qng;
5115 ep->chip_scsi_id = asc_dvc_varp->cfg->chip_scsi_id;
5116 /* 'max_tag_qng' is set to the same value for every device. */
5117 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
5118 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
5119 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
5120 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
5121 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
5122 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
5123 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
5124 ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6];
5127 * Modify board configuration.
5129 ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
5130 switch (ret = AscInitSetConfig(asc_dvc_varp)) {
5131 case 0: /* No error. */
5132 break;
5133 case ASC_WARN_IO_PORT_ROTATE:
5134 ASC_PRINT1(
5135 "AscInitSetConfig: board %d: I/O port address modified\n",
5136 boardp->id);
5137 break;
5138 case ASC_WARN_AUTO_CONFIG:
5139 ASC_PRINT1(
5140 "AscInitSetConfig: board %d: I/O port increment switch enabled\n",
5141 boardp->id);
5142 break;
5143 case ASC_WARN_EEPROM_CHKSUM:
5144 ASC_PRINT1(
5145 "AscInitSetConfig: board %d: EEPROM checksum error\n",
5146 boardp->id);
5147 break;
5148 case ASC_WARN_IRQ_MODIFIED:
5149 ASC_PRINT1(
5150 "AscInitSetConfig: board %d: IRQ modified\n",
5151 boardp->id);
5152 break;
5153 case ASC_WARN_CMD_QNG_CONFLICT:
5154 ASC_PRINT1(
5155 "AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
5156 boardp->id);
5157 break;
5158 default:
5159 ASC_PRINT2(
5160 "AscInitSetConfig: board %d: unknown warning: %x\n",
5161 boardp->id, ret);
5162 break;
5164 if (asc_dvc_varp->err_code != 0) {
5165 ASC_PRINT3(
5166 "AscInitSetConfig: board %d error: init_state %x, err_code %x\n",
5167 boardp->id, asc_dvc_varp->init_state,
5168 asc_dvc_varp->err_code);
5169 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5170 kfree(boardp->prtbuf);
5171 #endif /* version >= v1.3.0 */
5172 scsi_unregister(shp);
5173 asc_board_count--;
5174 continue;
5178 * Finish initializing the 'Scsi_Host' structure.
5180 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
5181 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
5182 shp->irq = asc_dvc_varp->irq_no;
5184 } else {
5185 ADVEEP_3550_CONFIG *ep_3550;
5186 ADVEEP_38C0800_CONFIG *ep_38C0800;
5189 * Save Wide EEP Configuration Information.
5191 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
5193 ep_3550 = &boardp->eep_config.adv_3550_eep;
5195 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
5196 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
5197 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
5198 ep_3550->termination = adv_dvc_varp->cfg->termination;
5199 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
5200 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
5201 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
5202 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
5203 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
5204 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
5205 ep_3550->start_motor = adv_dvc_varp->start_motor;
5206 ep_3550->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait;
5207 ep_3550->serial_number_word1 =
5208 adv_dvc_varp->cfg->serial1;
5209 ep_3550->serial_number_word2 =
5210 adv_dvc_varp->cfg->serial2;
5211 ep_3550->serial_number_word3 =
5212 adv_dvc_varp->cfg->serial3;
5213 } else
5215 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
5217 ep_38C0800->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
5218 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
5219 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
5220 ep_38C0800->termination_lvd =
5221 adv_dvc_varp->cfg->termination;
5222 ep_38C0800->disc_enable = adv_dvc_varp->cfg->disc_enable;
5223 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
5224 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
5225 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
5226 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
5227 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
5228 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
5229 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
5230 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
5231 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
5232 ep_38C0800->scsi_reset_delay =
5233 adv_dvc_varp->scsi_reset_wait;
5234 ep_38C0800->serial_number_word1 =
5235 adv_dvc_varp->cfg->serial1;
5236 ep_38C0800->serial_number_word2 =
5237 adv_dvc_varp->cfg->serial2;
5238 ep_38C0800->serial_number_word3 =
5239 adv_dvc_varp->cfg->serial3;
5243 * Set the adapter's target id bit in the 'init_tidmask' field.
5245 boardp->init_tidmask |=
5246 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
5249 * Finish initializing the 'Scsi_Host' structure.
5251 shp->irq = adv_dvc_varp->irq_no;
5254 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5256 * Channels are numbered beginning with 0. For AdvanSys One host
5257 * structure supports one channel. Multi-channel boards have a
5258 * separate host structure for each channel.
5260 shp->max_channel = 0;
5261 #endif /* version >= v1.3.89 */
5262 if (ASC_NARROW_BOARD(boardp)) {
5263 shp->max_id = ASC_MAX_TID + 1;
5264 shp->max_lun = ASC_MAX_LUN + 1;
5266 shp->io_port = asc_dvc_varp->iop_base;
5267 shp->n_io_port = ASC_IOADR_GAP;
5268 shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
5270 /* Set maximum number of queues the adapter can handle. */
5271 shp->can_queue = asc_dvc_varp->max_total_qng;
5272 } else {
5273 shp->max_id = ADV_MAX_TID + 1;
5274 shp->max_lun = ADV_MAX_LUN + 1;
5277 * Save the I/O Port address and length even though the
5278 * in v1.3.0 and greater kernels the region is not used
5279 * by a Wide board. Instead the board is accessed with
5280 * Memory Mapped I/O.
5282 shp->io_port = iop;
5283 shp->n_io_port = iolen;
5285 shp->this_id = adv_dvc_varp->chip_scsi_id;
5287 /* Set maximum number of queues the adapter can handle. */
5288 shp->can_queue = adv_dvc_varp->max_host_qng;
5291 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
5293 * In old kernels without tag queuing support and with memory
5294 * allocation problems set a conservative 'cmd_per_lun' value.
5296 #ifdef MODULE
5297 shp->cmd_per_lun = 1;
5298 #else /* MODULE */
5299 shp->cmd_per_lun = 4;
5300 #endif /* MODULE */
5301 ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
5302 #else /* version >= v1.3.89 */
5304 * Following v1.3.89, 'cmd_per_lun' is no longer needed
5305 * and should be set to zero.
5307 * But because of a bug introduced in v1.3.89 if the driver is
5308 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
5309 * SCSI function 'allocate_device' will panic. To allow the driver
5310 * to work as a module in these kernels set 'cmd_per_lun' to 1.
5312 #ifdef MODULE
5313 shp->cmd_per_lun = 1;
5314 #else /* MODULE */
5315 shp->cmd_per_lun = 0;
5316 #endif /* MODULE */
5318 * Use the host 'select_queue_depths' function to determine
5319 * the number of commands to queue per device.
5321 shp->select_queue_depths = advansys_select_queue_depths;
5322 #endif /* version >= v1.3.89 */
5325 * Set the maximum number of scatter-gather elements the
5326 * adapter can handle.
5328 if (ASC_NARROW_BOARD(boardp)) {
5330 * Allow two commands with 'sg_tablesize' scatter-gather
5331 * elements to be executed simultaneously. This value is
5332 * the theoretical hardware limit. It may be decreased
5333 * below.
5335 shp->sg_tablesize =
5336 (((asc_dvc_varp->max_total_qng - 2) / 2) *
5337 ASC_SG_LIST_PER_Q) + 1;
5338 } else {
5339 shp->sg_tablesize = ADV_MAX_SG_LIST;
5342 #ifdef MODULE
5344 * If the driver is compiled as a module, set a limit on the
5345 * 'sg_tablesize' value to prevent memory allocation failures.
5346 * Memory allocation errors are more likely to occur at module
5347 * load time, then at driver initialization time.
5349 if (shp->sg_tablesize > 64) {
5350 shp->sg_tablesize = 64;
5352 #endif /* MODULE */
5355 * The value of 'sg_tablesize' can not exceed the SCSI
5356 * mid-level driver definition of SG_ALL. SG_ALL also
5357 * must not be exceeded, because it is used to define the
5358 * size of the scatter-gather table in 'struct asc_sg_head'.
5360 if (shp->sg_tablesize > SG_ALL) {
5361 shp->sg_tablesize = SG_ALL;
5364 ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
5365 shp->sg_tablesize);
5367 /* BIOS start address. */
5368 if (ASC_NARROW_BOARD(boardp)) {
5369 shp->base = (char *) ((ulong) AscGetChipBiosAddress(
5370 asc_dvc_varp->iop_base,
5371 asc_dvc_varp->bus_type));
5372 } else {
5374 * Fill-in BIOS board variables. The Wide BIOS saves
5375 * information in LRAM that is used by the driver.
5377 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE,
5378 boardp->bios_signature);
5379 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION,
5380 boardp->bios_version);
5381 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG,
5382 boardp->bios_codeseg);
5383 AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN,
5384 boardp->bios_codelen);
5386 ASC_DBG2(1,
5387 "advansys_detect: bios_signature %x, bios_version %x\n",
5388 boardp->bios_signature, boardp->bios_version);
5390 ASC_DBG2(1,
5391 "advansys_detect: bios_codeseg %x, bios_codelen %x\n",
5392 boardp->bios_codeseg, boardp->bios_codelen);
5395 * If the BIOS saved a valid signature, then fill in
5396 * the BIOS code segment base address.
5398 if (boardp->bios_signature == 0x55AA) {
5400 * Convert x86 realmode code segment to a linear
5401 * address by shifting left 4.
5403 shp->base = (uchar *) (boardp->bios_codeseg << 4);
5404 } else {
5405 shp->base = 0;
5410 * Register Board Resources - I/O Port, DMA, IRQ
5413 /* Register I/O port range. */
5414 ASC_DBG(2, "advansys_detect: request_region()\n");
5415 request_region(shp->io_port, shp->n_io_port, "advansys");
5417 /* Register DMA Channel for Narrow boards. */
5418 shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
5419 if (ASC_NARROW_BOARD(boardp)) {
5420 /* Register DMA channel for ISA bus. */
5421 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
5422 shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
5423 if ((ret =
5424 request_dma(shp->dma_channel, "advansys")) != 0) {
5425 ASC_PRINT3(
5426 "advansys_detect: board %d: request_dma() %d failed %d\n",
5427 boardp->id, shp->dma_channel, ret);
5428 release_region(shp->io_port, shp->n_io_port);
5429 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5430 kfree(boardp->prtbuf);
5431 #endif /* version >= v1.3.0 */
5432 scsi_unregister(shp);
5433 asc_board_count--;
5434 continue;
5436 AscEnableIsaDma(shp->dma_channel);
5440 /* Register IRQ Number. */
5441 ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
5442 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5443 if ((ret = request_irq(shp->irq, advansys_interrupt,
5444 SA_INTERRUPT, "advansys")) != 0)
5445 #else /* version >= v1.3.70 */
5447 * If request_irq() fails with the SA_INTERRUPT flag set,
5448 * then try again without the SA_INTERRUPT flag set. This
5449 * allows IRQ sharing to work even with other drivers that
5450 * do not set the SA_INTERRUPT flag.
5452 * If SA_INTERRUPT is not set, then interrupts are enabled
5453 * before the driver interrupt function is called.
5455 if (((ret = request_irq(shp->irq, advansys_interrupt,
5456 SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
5457 "advansys", boardp)) != 0) &&
5458 ((ret = request_irq(shp->irq, advansys_interrupt,
5459 (share_irq == TRUE ? SA_SHIRQ : 0),
5460 "advansys", boardp)) != 0))
5461 #endif /* version >= v1.3.70 */
5463 if (ret == -EBUSY) {
5464 ASC_PRINT2(
5465 "advansys_detect: board %d: request_irq(): IRQ %d already in use.\n",
5466 boardp->id, shp->irq);
5467 } else if (ret == -EINVAL) {
5468 ASC_PRINT2(
5469 "advansys_detect: board %d: request_irq(): IRQ %d not valid.\n",
5470 boardp->id, shp->irq);
5471 } else {
5472 ASC_PRINT3(
5473 "advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n",
5474 boardp->id, shp->irq, ret);
5476 release_region(shp->io_port, shp->n_io_port);
5477 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5478 iounmap(boardp->ioremap_addr);
5479 #endif /* version >= v1,3,0 */
5480 if (shp->dma_channel != NO_ISA_DMA) {
5481 free_dma(shp->dma_channel);
5483 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5484 kfree(boardp->prtbuf);
5485 #endif /* version >= v1.3.0 */
5486 scsi_unregister(shp);
5487 asc_board_count--;
5488 continue;
5492 * Initialize board RISC chip and enable interrupts.
5494 if (ASC_NARROW_BOARD(boardp)) {
5495 ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
5496 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
5497 err_code = asc_dvc_varp->err_code;
5499 if (warn_code || err_code) {
5500 ASC_PRINT4(
5501 "AscInitAsc1000Driver: board %d: error: init_state %x, warn %x error %x\n",
5502 boardp->id, asc_dvc_varp->init_state,
5503 warn_code, err_code);
5505 } else {
5506 ADV_CARR_T *carrp;
5507 int req_cnt;
5508 adv_req_t *reqp = NULL;
5509 int sg_cnt = 0;
5510 adv_sgblk_t *sgp = NULL;
5512 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
5513 carrp = (ADV_CARR_T *) &adv_carr_buf[0];
5514 req_cnt = sizeof(adv_req_buf)/sizeof(adv_req_t);
5515 sg_cnt = sizeof(adv_sgblk_buf)/sizeof(adv_sgblk_t);
5516 reqp = (adv_req_t *) &adv_req_buf[0];
5517 sgp = (adv_sgblk_t *) &adv_sgblk_buf[0];
5518 #else /* version >= v1.3.0 */
5520 * Allocate buffer carrier structures.
5522 carrp =
5523 (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC);
5524 ASC_DBG1(1, "advansys_detect: carrp %x\n", (unsigned) carrp);
5526 if (carrp == NULL) {
5527 goto kmalloc_error;
5531 * Allocate up to 'max_host_qng' request structures for
5532 * the Wide board.
5534 for (req_cnt = adv_dvc_varp->max_host_qng;
5535 req_cnt > 0; req_cnt--) {
5537 reqp = (adv_req_t *)
5538 kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
5540 ASC_DBG3(1,
5541 "advansys_detect: reqp %x, req_cnt %d, bytes %d\n",
5542 (unsigned) reqp, req_cnt, sizeof(adv_req_t) * req_cnt);
5544 if (reqp != NULL) {
5545 break;
5548 if (reqp == NULL)
5550 goto kmalloc_error;
5554 * Allocate up to ADV_TOT_SG_LIST request structures for
5555 * the Wide board.
5557 for (sg_cnt = ADV_TOT_SG_LIST; sg_cnt > 0; sg_cnt--) {
5559 sgp = (adv_sgblk_t *)
5560 kmalloc(sizeof(adv_sgblk_t) * sg_cnt, GFP_ATOMIC);
5562 ASC_DBG3(1,
5563 "advansys_detect: sgp %x, sg_cnt %d, bytes %d\n",
5564 (unsigned) sgp, sg_cnt, sizeof(adv_sgblk_t) * sg_cnt);
5566 if (sgp != NULL) {
5567 break;
5572 * If no request structures or scatter-gather structures could
5573 * be allocated, then return an error. Otherwise continue with
5574 * initialization.
5576 kmalloc_error:
5577 if (carrp == NULL)
5579 ASC_PRINT1(
5580 "advansys_detect: board %d: error: failed to kmalloc() carrier buffer.\n",
5581 boardp->id);
5582 err_code = ADV_ERROR;
5583 } else if (reqp == NULL) {
5584 kfree(carrp);
5585 ASC_PRINT1(
5586 "advansys_detect: board %d: error: failed to kmalloc() adv_req_t buffer.\n",
5587 boardp->id);
5588 err_code = ADV_ERROR;
5589 } else if (sgp == NULL) {
5590 kfree(carrp);
5591 kfree(reqp);
5592 ASC_PRINT1(
5593 "advansys_detect: board %d: error: failed to kmalloc() adv_sgblk_t buffer.\n",
5594 boardp->id);
5595 err_code = ADV_ERROR;
5596 } else {
5598 /* Save carrier buffer pointer. */
5599 boardp->orig_carrp = carrp;
5602 * Save original pointer for kfree() in case the
5603 * driver is built as a module and can be unloaded.
5605 boardp->orig_reqp = reqp;
5608 * Save original pointer for kfree() in case the
5609 * driver is built as a module and can be unloaded.
5611 boardp->orig_sgblkp = sgp;
5612 #endif /* version >= v1.3.0 */
5614 adv_dvc_varp->carrier_buf = carrp;
5617 * Point 'adv_reqp' to the request structures and
5618 * link them together.
5620 req_cnt--;
5621 reqp[req_cnt].next_reqp = NULL;
5622 for (; req_cnt > 0; req_cnt--) {
5623 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
5625 boardp->adv_reqp = &reqp[0];
5628 * Point 'adv_sgblkp' to the request structures and
5629 * link them together.
5631 sg_cnt--;
5632 sgp[sg_cnt].next_sgblkp = NULL;
5633 for (; sg_cnt > 0; sg_cnt--) {
5634 sgp[sg_cnt - 1].next_sgblkp = &sgp[sg_cnt];
5636 boardp->adv_sgblkp = &sgp[0];
5638 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
5640 ASC_DBG(2,
5641 "advansys_detect: AdvInitAsc3550Driver()\n");
5642 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
5643 } else {
5644 ASC_DBG(2,
5645 "advansys_detect: AdvInitAsc38C0800Driver()\n");
5646 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
5648 err_code = adv_dvc_varp->err_code;
5650 if (warn_code || err_code) {
5651 ASC_PRINT3(
5652 "AdvInitAsc3550/38C0800Driver: board %d: error: warn %x, error %x\n",
5653 boardp->id, warn_code, adv_dvc_varp->err_code);
5655 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5657 #endif /* version >= v1,3,0 */
5660 if (err_code != 0) {
5661 release_region(shp->io_port, shp->n_io_port);
5662 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5663 if (ASC_WIDE_BOARD(boardp)) {
5664 iounmap(boardp->ioremap_addr);
5665 if (boardp->orig_carrp) {
5666 kfree(boardp->orig_carrp);
5667 boardp->orig_carrp = NULL;
5669 if (boardp->orig_reqp) {
5670 kfree(boardp->orig_reqp);
5671 boardp->orig_reqp = boardp->adv_reqp = NULL;
5673 if (boardp->orig_sgblkp) {
5674 kfree(boardp->orig_sgblkp);
5675 boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5678 #endif /* version >= v1,3,0 */
5679 if (shp->dma_channel != NO_ISA_DMA) {
5680 free_dma(shp->dma_channel);
5682 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5683 kfree(boardp->prtbuf);
5684 #endif /* version >= v1.3.0 */
5685 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5686 free_irq(shp->irq);
5687 #else /* version >= v1.3.70 */
5688 free_irq(shp->irq, boardp);
5689 #endif /* version >= v1.3.70 */
5690 scsi_unregister(shp);
5691 asc_board_count--;
5692 continue;
5694 ASC_DBG_PRT_SCSI_HOST(2, shp);
5697 ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
5698 return asc_board_count;
5702 * advansys_release()
5704 * Release resources allocated for a single AdvanSys adapter.
5707 advansys_release(struct Scsi_Host *shp)
5709 asc_board_t *boardp;
5711 ASC_DBG(1, "advansys_release: begin\n");
5712 boardp = ASC_BOARDP(shp);
5713 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5714 free_irq(shp->irq);
5715 #else /* version >= v1.3.70 */
5716 free_irq(shp->irq, boardp);
5717 #endif /* version >= v1.3.70 */
5718 if (shp->dma_channel != NO_ISA_DMA) {
5719 ASC_DBG(1, "advansys_release: free_dma()\n");
5720 free_dma(shp->dma_channel);
5722 release_region(shp->io_port, shp->n_io_port);
5723 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5724 if (ASC_WIDE_BOARD(boardp)) {
5725 iounmap(boardp->ioremap_addr);
5726 if (boardp->orig_carrp) {
5727 kfree(boardp->orig_carrp);
5728 boardp->orig_carrp = NULL;
5730 if (boardp->orig_reqp) {
5731 kfree(boardp->orig_reqp);
5732 boardp->orig_reqp = boardp->adv_reqp = NULL;
5734 if (boardp->orig_sgblkp) {
5735 kfree(boardp->orig_sgblkp);
5736 boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5739 ASC_ASSERT(boardp->prtbuf != NULL);
5740 kfree(boardp->prtbuf);
5741 #endif /* version >= v1.3.0 */
5742 scsi_unregister(shp);
5743 ASC_DBG(1, "advansys_release: end\n");
5744 return 0;
5748 * advansys_info()
5750 * Return suitable for printing on the console with the argument
5751 * adapter's configuration information.
5753 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
5754 * otherwise the static 'info' array will be overrun.
5756 const char *
5757 advansys_info(struct Scsi_Host *shp)
5759 static char info[ASC_INFO_SIZE];
5760 asc_board_t *boardp;
5761 ASC_DVC_VAR *asc_dvc_varp;
5762 ADV_DVC_VAR *adv_dvc_varp;
5763 char *busname;
5764 int iolen;
5765 char *widename = NULL;
5767 boardp = ASC_BOARDP(shp);
5768 if (ASC_NARROW_BOARD(boardp)) {
5769 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5770 ASC_DBG(1, "advansys_info: begin\n");
5771 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
5772 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
5773 busname = "ISA PnP";
5774 } else {
5775 busname = "ISA";
5777 sprintf(info,
5778 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5779 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u",
5780 #else /* version >= v2.1.92 */
5781 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u",
5782 #endif /* version >= v2.1.92 */
5783 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5784 (unsigned) shp->base,
5785 shp->io_port, shp->n_io_port - 1,
5786 shp->irq, shp->dma_channel);
5787 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
5788 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
5789 == ASC_IS_PCI_ULTRA) {
5790 busname = "PCI Ultra";
5791 } else {
5792 busname = "PCI";
5794 sprintf(info,
5795 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5796 "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u",
5797 #else /* version >= v2.1.92 */
5798 "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u",
5799 #endif /* version >= v2.1.92 */
5800 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5801 shp->io_port, shp->n_io_port - 1, shp->irq);
5802 } else {
5803 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
5804 busname = "VL";
5805 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
5806 busname = "EISA";
5807 } else {
5808 busname = "?";
5809 ASC_PRINT2(
5810 "advansys_info: board %d: unknown bus type %d\n",
5811 boardp->id, asc_dvc_varp->bus_type);
5813 sprintf(info,
5814 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5815 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u",
5816 #else /* version >= v2.1.92 */
5817 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u",
5818 #endif /* version >= v2.1.92 */
5819 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5820 (unsigned) shp->base, shp->io_port - 1,
5821 shp->n_io_port, shp->irq);
5823 } else {
5825 * Wide Adapter Information
5827 * Memory-mapped I/O is used instead of I/O space to access
5828 * the adapter, but display the I/O Port range. The Memory
5829 * I/O address is displayed through the driver /proc file.
5831 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5832 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
5834 iolen = ADV_3550_IOLEN;
5835 widename = "Ultra-Wide";
5836 } else {
5837 iolen = ADV_38C0800_IOLEN;
5838 widename = "Ultra2-Wide";
5840 if (boardp->bios_signature == 0x55AA) {
5841 sprintf(info,
5842 "AdvanSys SCSI %s: PCI %s: BIOS %X/%X, IO %X/%X, IRQ %u",
5843 ASC_VERSION,
5844 widename,
5845 boardp->bios_codeseg << 4,
5846 boardp->bios_codelen > 0 ?
5847 (boardp->bios_codelen << 9) - 1 : 0,
5848 (unsigned) boardp->ioport, iolen - 1,
5849 shp->irq);
5850 } else {
5851 sprintf(info,
5852 "AdvanSys SCSI %s: PCI %s: IO %X/%X, IRQ %u",
5853 ASC_VERSION,
5854 widename,
5855 (unsigned) boardp->ioport,
5856 (iolen - 1),
5857 shp->irq);
5860 ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
5861 ASC_DBG(1, "advansys_info: end\n");
5862 return info;
5866 * advansys_command() - polled I/O entrypoint.
5868 * Apparently host drivers shouldn't return until the command
5869 * is finished.
5871 * Note: This is an old interface that is no longer used by the SCSI
5872 * mid-level driver. The new interface, advansys_queuecommand(),
5873 * currently handles all requests.
5876 advansys_command(Scsi_Cmnd *scp)
5878 ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
5879 ASC_STATS(scp->host, command);
5880 scp->SCp.Status = 0; /* Set to a known state */
5881 advansys_queuecommand(scp, advansys_command_done);
5882 while (scp->SCp.Status == 0) {
5883 continue;
5885 ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
5886 return scp->result;
5890 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
5892 * This function always returns 0. Command return status is saved
5893 * in the 'scp' result field.
5896 advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
5898 struct Scsi_Host *shp;
5899 asc_board_t *boardp;
5900 int flags;
5901 Scsi_Cmnd *done_scp;
5903 shp = scp->host;
5904 boardp = ASC_BOARDP(shp);
5905 ASC_STATS(shp, queuecommand);
5908 * Disable interrupts to preserve request ordering and provide
5909 * mutually exclusive access to global structures used to initiate
5910 * a request.
5912 save_flags(flags);
5913 cli();
5916 * Block new commands while handling a reset or abort request.
5918 if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5919 if (boardp->flags & ASC_HOST_IN_RESET) {
5920 ASC_DBG1(1,
5921 "advansys_queuecommand: scp %x blocked for reset request\n",
5922 (unsigned) scp);
5923 scp->result = HOST_BYTE(DID_RESET);
5924 } else {
5925 ASC_DBG1(1,
5926 "advansys_queuecommand: scp %x blocked for abort request\n",
5927 (unsigned) scp);
5928 scp->result = HOST_BYTE(DID_ABORT);
5932 * Add blocked requests to the board's 'done' queue. The queued
5933 * requests will be completed at the end of the abort or reset
5934 * handling.
5936 asc_enqueue(&boardp->done, scp, ASC_BACK);
5937 restore_flags(flags);
5938 return 0;
5942 * Attempt to execute any waiting commands for the board.
5944 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5945 ASC_DBG(1,
5946 "advansys_queuecommand: before asc_execute_queue() waiting\n");
5947 asc_execute_queue(&boardp->waiting);
5951 * Save the function pointer to Linux mid-level 'done' function
5952 * and attempt to execute the command.
5954 * If ASC_ERROR is returned the request has been added to the
5955 * board's 'active' queue and will be completed by the interrupt
5956 * handler.
5958 * If ASC_BUSY is returned add the request to the board's per
5959 * target waiting list.
5961 * If an error occurred, the request will have been placed on the
5962 * board's 'done' queue and must be completed before returning.
5964 scp->scsi_done = done;
5965 switch (asc_execute_scsi_cmnd(scp)) {
5966 case ASC_NOERROR:
5967 break;
5968 case ASC_BUSY:
5969 asc_enqueue(&boardp->waiting, scp, ASC_BACK);
5970 break;
5971 case ASC_ERROR:
5972 default:
5973 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5974 /* Interrupts could be enabled here. */
5975 asc_scsi_done_list(done_scp);
5976 break;
5979 restore_flags(flags);
5980 return 0;
5984 * advansys_abort()
5986 * Abort the command specified by 'scp'.
5989 advansys_abort(Scsi_Cmnd *scp)
5991 struct Scsi_Host *shp;
5992 asc_board_t *boardp;
5993 ASC_DVC_VAR *asc_dvc_varp;
5994 ADV_DVC_VAR *adv_dvc_varp;
5995 int flags;
5996 int do_scsi_done;
5997 int scp_found;
5998 Scsi_Cmnd *done_scp = NULL;
5999 int ret;
6001 /* Save current flags and disable interrupts. */
6002 save_flags(flags);
6003 cli();
6005 ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
6007 #ifdef ADVANSYS_STATS
6008 if (scp->host != NULL) {
6009 ASC_STATS(scp->host, abort);
6011 #endif /* ADVANSYS_STATS */
6013 #ifdef ADVANSYS_ASSERT
6014 do_scsi_done = ASC_ERROR;
6015 scp_found = ASC_ERROR;
6016 ret = ASC_ERROR;
6017 #endif /* ADVANSYS_ASSERT */
6019 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6020 if (scp->serial_number != scp->serial_number_at_timeout) {
6021 ASC_PRINT1(
6022 "advansys_abort: timeout serial number changed for request %x\n",
6023 (unsigned) scp);
6024 do_scsi_done = ASC_FALSE;
6025 scp_found = ASC_FALSE;
6026 ret = SCSI_ABORT_NOT_RUNNING;
6027 } else
6028 #endif /* version >= v1.3.89 */
6029 if ((shp = scp->host) == NULL) {
6030 scp->result = HOST_BYTE(DID_ERROR);
6031 do_scsi_done = ASC_TRUE;
6032 scp_found = ASC_FALSE;
6033 ret = SCSI_ABORT_ERROR;
6034 } else if ((boardp = ASC_BOARDP(shp))->flags &
6035 (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
6036 ASC_PRINT2(
6037 "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
6038 boardp->id, boardp->flags);
6039 do_scsi_done = ASC_TRUE;
6040 if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
6041 (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
6042 scp_found = ASC_TRUE;
6043 } else {
6044 scp_found = ASC_FALSE;
6046 scp->result = HOST_BYTE(DID_ERROR);
6047 ret = SCSI_ABORT_ERROR;
6048 } else {
6049 /* Set abort flag to avoid nested reset or abort requests. */
6050 boardp->flags |= ASC_HOST_IN_ABORT;
6052 do_scsi_done = ASC_TRUE;
6053 if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
6055 * If asc_rmqueue() found the command on the waiting
6056 * queue, it had not been sent to the device. After
6057 * the queue is removed, no other handling is required.
6059 ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
6060 (unsigned) scp);
6061 scp_found = ASC_TRUE;
6062 scp->result = HOST_BYTE(DID_ABORT);
6063 ret = SCSI_ABORT_SUCCESS;
6064 } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
6066 * If asc_isqueued() found the command on the active
6067 * queue, it has been sent to the device. The command
6068 * will be returned through the interrupt handler after
6069 * it has been aborted.
6072 if (ASC_NARROW_BOARD(boardp)) {
6074 * Narrow Board
6076 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6077 scp->result = HOST_BYTE(DID_ABORT);
6079 /* sti(); XXX */ /* Enable interrupts for AscAbortSRB(). */
6080 ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
6081 (unsigned) scp);
6082 switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
6083 case ASC_TRUE:
6084 /* asc_isr_callback() will be called */
6085 ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
6086 ret = SCSI_ABORT_PENDING;
6087 break;
6088 case ASC_FALSE:
6089 /* Request has apparently already completed. */
6090 ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
6091 ret = SCSI_ABORT_NOT_RUNNING;
6092 break;
6093 case ASC_ERROR:
6094 default:
6095 ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
6096 ret = SCSI_ABORT_ERROR;
6097 break;
6099 cli();
6100 } else {
6102 * Wide Board
6104 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6105 scp->result = HOST_BYTE(DID_ABORT);
6107 ASC_DBG1(1, "advansys_abort: before AdvAbortQueue(), scp %x\n",
6108 (unsigned) scp);
6109 #if 0 /* XXX */
6110 switch (AdvAbortQueue(adv_dvc_varp, (ulong) XXX)) {
6111 case ASC_TRUE:
6112 /* asc_isr_callback() will be called */
6113 ASC_DBG(1, "advansys_abort: AdvAbortQueue() TRUE\n");
6114 ret = SCSI_ABORT_PENDING;
6115 break;
6116 case ASC_FALSE:
6117 /* Request has apparently already completed. */
6118 ASC_DBG(1, "advansys_abort: AdvAbortQueue() FALSE\n");
6119 ret = SCSI_ABORT_NOT_RUNNING;
6120 break;
6121 case ASC_ERROR:
6122 default:
6123 ASC_DBG(1, "advansys_abort: AdvAbortQueue() ERROR\n");
6124 ret = SCSI_ABORT_ERROR;
6125 break;
6128 * Ensure all requests completed by the microcode have
6129 * been processed by calling AdvISR().
6131 (void) AdvISR(adv_dvc_varp);
6132 #else /* XXX */
6133 (void) AdvResetChipAndSB(adv_dvc_varp);
6134 ret = SCSI_ABORT_SUCCESS;
6135 #endif /* XXX */
6139 * The request will either still be on the active queue
6140 * or have been added to the board's done queue.
6142 if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
6143 scp->result = HOST_BYTE(DID_ABORT);
6144 scp_found = ASC_TRUE;
6145 } else {
6146 scp_found = asc_rmqueue(&boardp->done, scp);
6147 ASC_ASSERT(scp_found == ASC_TRUE);
6149 } else {
6151 * The command was not found on the active or waiting queues.
6153 do_scsi_done = ASC_TRUE;
6154 scp_found = ASC_FALSE;
6155 ret = SCSI_ABORT_NOT_RUNNING;
6158 /* Clear abort flag. */
6159 boardp->flags &= ~ASC_HOST_IN_ABORT;
6162 * Because the ASC_HOST_IN_ABORT flag causes both
6163 * 'advansys_interrupt' and 'asc_isr_callback' to
6164 * queue requests to the board's 'done' queue and
6165 * prevents waiting commands from being executed,
6166 * these queued requests must be handled here.
6168 done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
6171 * Start any waiting commands for the board.
6173 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6174 ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6175 asc_execute_queue(&boardp->waiting);
6179 /* Interrupts could be enabled here. */
6182 * Complete the request to be aborted, unless it has been
6183 * restarted as detected above, even if it was not found on
6184 * the device active or waiting queues.
6186 ASC_ASSERT(do_scsi_done != ASC_ERROR);
6187 ASC_ASSERT(scp_found != ASC_ERROR);
6188 if (do_scsi_done == ASC_TRUE) {
6189 if (scp->scsi_done == NULL) {
6190 ASC_PRINT1(
6191 "advansys_abort: aborted request scsi_done() is NULL, %x\n",
6192 (unsigned) scp);
6193 } else {
6194 if (scp_found == ASC_FALSE) {
6195 ASC_PRINT1(
6196 "advansys_abort: abort request not active or waiting, completing anyway %x\n",
6197 (unsigned) scp);
6199 ASC_STATS(scp->host, done);
6200 scp->scsi_done(scp);
6205 * It is possible for the request done function to re-enable
6206 * interrupts without confusing the driver. But here interrupts
6207 * aren't enabled until all requests have been completed.
6209 if (done_scp != NULL) {
6210 asc_scsi_done_list(done_scp);
6213 ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
6215 /* Re-enable interrupts, if they were enabled on entry. */
6216 restore_flags(flags);
6218 ASC_ASSERT(ret != ASC_ERROR);
6219 return ret;
6223 * advansys_reset()
6225 * Reset the device associated with the command 'scp'.
6228 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
6229 advansys_reset(Scsi_Cmnd *scp)
6230 #else /* version >= v1.3.89 */
6231 advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
6232 #endif /* version >= v1.3.89 */
6234 struct Scsi_Host *shp;
6235 asc_board_t *boardp;
6236 ASC_DVC_VAR *asc_dvc_varp;
6237 ADV_DVC_VAR *adv_dvc_varp;
6238 int flags;
6239 Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
6240 Scsi_Cmnd *tscp, *new_last_scp;
6241 int do_scsi_done;
6242 int scp_found;
6243 int status;
6244 int target;
6245 int ret;
6246 int device_reset = ASC_FALSE;
6248 /* Save current flags and disable interrupts. */
6249 save_flags(flags);
6250 cli();
6252 ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
6254 #ifdef ADVANSYS_STATS
6255 if (scp->host != NULL) {
6256 ASC_STATS(scp->host, reset);
6258 #endif /* ADVANSYS_STATS */
6260 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6261 if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) &&
6262 (scp->serial_number != scp->serial_number_at_timeout)) {
6263 ASC_PRINT1(
6264 "advansys_reset: timeout serial number changed for request %x\n",
6265 (unsigned) scp);
6266 do_scsi_done = ASC_FALSE;
6267 scp_found = ASC_FALSE;
6268 ret = SCSI_RESET_NOT_RUNNING;
6269 } else
6270 #endif /* version >= v1.3.89 */
6271 if ((shp = scp->host) == NULL) {
6272 scp->result = HOST_BYTE(DID_ERROR);
6273 do_scsi_done = ASC_TRUE;
6274 scp_found = ASC_FALSE;
6275 ret = SCSI_RESET_ERROR;
6276 } else if ((boardp = ASC_BOARDP(shp))->flags &
6277 (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
6278 ASC_PRINT2(
6279 "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
6280 boardp->id, boardp->flags);
6281 do_scsi_done = ASC_TRUE;
6282 if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
6283 (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
6284 scp_found = ASC_TRUE;
6285 } else {
6286 scp_found = ASC_FALSE;
6288 scp->result = HOST_BYTE(DID_ERROR);
6289 ret = SCSI_RESET_ERROR;
6290 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
6291 } else if (time_after_eq(jiffies, boardp->last_reset) &&
6292 time_before(jiffies, boardp->last_reset + (10 * HZ))) {
6293 #else /* version < v2.1.0 */
6294 } else if (jiffies >= boardp->last_reset &&
6295 jiffies < (boardp->last_reset + (10 * HZ))) {
6296 #endif /* version < v2.1.0 */
6298 * Don't allow a reset to be attempted within 10 seconds
6299 * of the last reset.
6301 * If 'jiffies' wrapping occurs, the reset request will go
6302 * through, because a wrapped 'jiffies' would not pass the
6303 * test above.
6305 ASC_DBG(1,
6306 "advansys_reset: reset within 10 sec of last reset ignored\n");
6307 do_scsi_done = ASC_TRUE;
6308 if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
6309 (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
6310 scp_found = ASC_TRUE;
6311 } else {
6312 scp_found = ASC_FALSE;
6314 scp->result = HOST_BYTE(DID_ERROR);
6315 ret = SCSI_RESET_ERROR;
6316 } else {
6317 do_scsi_done = ASC_TRUE;
6319 /* Set reset flag to avoid nested reset or abort requests. */
6320 boardp->flags |= ASC_HOST_IN_RESET;
6323 * If the request is on the target waiting or active queue
6324 * or the board done queue, then remove it and note that it
6325 * was found.
6327 if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
6328 ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
6329 scp_found = ASC_TRUE;
6330 } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
6331 ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
6332 scp_found = ASC_TRUE;
6333 } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
6334 scp_found = ASC_TRUE;
6335 } else {
6336 scp_found = ASC_FALSE;
6340 if (ASC_NARROW_BOARD(boardp)) {
6342 * Narrow Board
6344 * If the suggest reset bus flags are set, then reset the bus.
6345 * Otherwise only reset the device.
6347 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6348 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6349 if (reset_flags &
6350 (SCSI_RESET_SUGGEST_BUS_RESET |
6351 SCSI_RESET_SUGGEST_HOST_RESET)) {
6352 #endif /* version >= v1.3.89 */
6355 * Reset the target's SCSI bus.
6357 ASC_DBG(1, "advansys_reset: before AscResetSB()\n");
6358 /* sti(); XXX */ /* Enable interrupts for AscResetSB(). */
6359 status = AscResetSB(asc_dvc_varp);
6360 /* cli(); XXX */
6361 switch (status) {
6362 case ASC_TRUE:
6363 ASC_DBG(1, "advansys_reset: AscResetSB() success\n");
6364 ret = SCSI_RESET_SUCCESS;
6365 break;
6366 case ASC_ERROR:
6367 default:
6368 ASC_DBG(1, "advansys_reset: AscResetSB() failed\n");
6369 ret = SCSI_RESET_ERROR;
6370 break;
6373 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6374 } else {
6376 * Reset the specified device. If the device reset fails,
6377 * then reset the SCSI bus.
6380 ASC_DBG1(1,
6381 "advansys_reset: before AscResetDevice(), target %d\n",
6382 scp->target);
6383 /* sti(); XXX */ /* Enable interrupts for AscResetDevice(). */
6384 status = AscResetDevice(asc_dvc_varp, scp->target);
6385 /* cli(); XXX */
6387 switch (status) {
6388 case ASC_TRUE:
6389 ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
6390 device_reset = ASC_TRUE;
6391 ret = SCSI_RESET_SUCCESS;
6392 break;
6393 case ASC_ERROR:
6394 default:
6395 ASC_DBG(1,
6396 "advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n");
6397 /* sti(); XXX */ /* Enable interrupts for AscResetSB(). */
6398 status = AscResetSB(asc_dvc_varp);
6399 /* cli(); XXX */
6400 switch (status) {
6401 case ASC_TRUE:
6402 ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
6403 ret = SCSI_RESET_SUCCESS;
6404 break;
6405 case ASC_ERROR:
6406 default:
6407 ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
6408 ret = SCSI_RESET_ERROR;
6409 break;
6411 break;
6414 #endif /* version >= v1.3.89 */
6415 } else {
6417 * Wide Board
6419 * If the suggest reset bus flags are set, then reset the bus.
6420 * Otherwise only reset the device.
6422 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6423 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6424 if (reset_flags &
6425 (SCSI_RESET_SUGGEST_BUS_RESET |
6426 SCSI_RESET_SUGGEST_HOST_RESET)) {
6427 #endif /* version >= v1.3.89 */
6430 * Reset the target's SCSI bus.
6432 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
6433 switch (AdvResetChipAndSB(adv_dvc_varp)) {
6434 case ASC_TRUE:
6435 ASC_DBG(1,
6436 "advansys_reset: AdvResetChipAndSB() success\n");
6437 ret = SCSI_RESET_SUCCESS;
6438 break;
6439 case ASC_FALSE:
6440 default:
6441 ASC_DBG(1, "advansys_reset: AdvResetChipAndSB() failed\n");
6442 ret = SCSI_RESET_ERROR;
6443 break;
6446 * Ensure all requests completed by the microcode have
6447 * been processed by calling AdvISR().
6449 (void) AdvISR(adv_dvc_varp);
6450 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6451 } else {
6453 * Reset the specified device. If the device reset fails,
6454 * then reset the SCSI bus.
6457 ASC_DBG1(1,
6458 "advansys_reset: before AdvResetDevice(), target %d\n",
6459 scp->target);
6461 switch (AdvResetDevice(adv_dvc_varp, scp->target)) {
6462 case ASC_TRUE:
6463 ASC_DBG(1, "advansys_reset: AdvResetDevice() success\n");
6464 device_reset = ASC_TRUE;
6465 ret = SCSI_RESET_SUCCESS;
6466 break;
6467 case ASC_FALSE:
6468 default:
6469 ASC_DBG(1,
6470 "advansys_reset: AdvResetDevice() failed; Calling AdvResetChipAndSB()\n");
6472 switch (AdvResetChipAndSB(adv_dvc_varp)) {
6473 case ASC_TRUE:
6474 ASC_DBG(1,
6475 "advansys_reset: AdvResetChipAndSB() TRUE\n");
6476 ret = SCSI_RESET_SUCCESS;
6477 break;
6478 case ASC_FALSE:
6479 default:
6480 ASC_DBG(1,
6481 "advansys_reset: AdvResetChipAndSB() ERROR\n");
6482 ret = SCSI_RESET_ERROR;
6483 break;
6485 break;
6488 * Ensure all requests completed by the microcode have
6489 * been processed by calling AdvISR().
6491 (void) AdvISR(adv_dvc_varp);
6493 #endif /* version >= v1.3.89 */
6497 * Because the ASC_HOST_IN_RESET flag causes both
6498 * 'advansys_interrupt' and 'asc_isr_callback' to
6499 * queue requests to the board's 'done' queue and
6500 * prevents waiting commands from being executed,
6501 * these queued requests must be handled here.
6503 done_scp = asc_dequeue_list(&boardp->done, &last_scp,
6504 ASC_TID_ALL);
6507 * If a device reset was performed dequeue all waiting
6508 * and active requests for the device and set the request
6509 * status to DID_RESET.
6511 * If a SCSI bus reset was performed dequeue all waiting
6512 * and active requests for all devices and set the request
6513 * status to DID_RESET.
6515 if (device_reset == ASC_TRUE) {
6516 target = scp->target;
6517 } else {
6518 target = ASC_TID_ALL;
6522 * Add active requests to 'done_scp' and set the request status
6523 * to DID_RESET.
6525 if (done_scp == NULL) {
6526 done_scp = asc_dequeue_list(&boardp->active, &last_scp, target);
6527 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
6528 tscp->result = HOST_BYTE(DID_RESET);
6530 } else {
6531 ASC_ASSERT(last_scp != NULL);
6532 REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
6533 &new_last_scp, target);
6534 if (new_last_scp != NULL) {
6535 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6536 for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
6537 tscp->result = HOST_BYTE(DID_RESET);
6539 last_scp = new_last_scp;
6544 * Add waiting requests to 'done_scp' and set the request status
6545 * to DID_RESET.
6547 if (done_scp == NULL) {
6548 done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target);
6549 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
6550 tscp->result = HOST_BYTE(DID_RESET);
6552 } else {
6553 ASC_ASSERT(last_scp != NULL);
6554 REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
6555 &new_last_scp, target);
6556 if (new_last_scp != NULL) {
6557 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6558 for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
6559 tscp->result = HOST_BYTE(DID_RESET);
6561 last_scp = new_last_scp;
6565 /* Save the time of the most recently completed reset. */
6566 boardp->last_reset = jiffies;
6568 /* Clear reset flag. */
6569 boardp->flags &= ~ASC_HOST_IN_RESET;
6572 * Start any waiting commands for the board.
6574 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6575 ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6576 asc_execute_queue(&boardp->waiting);
6578 ret = SCSI_RESET_SUCCESS;
6581 /* Interrupts could be enabled here. */
6583 ASC_ASSERT(do_scsi_done != ASC_ERROR);
6584 ASC_ASSERT(scp_found != ASC_ERROR);
6585 if (do_scsi_done == ASC_TRUE) {
6586 if (scp->scsi_done == NULL) {
6587 ASC_PRINT1(
6588 "advansys_reset: reset request scsi_done() is NULL, %x\n",
6589 (unsigned) scp);
6590 } else {
6591 if (scp_found == ASC_FALSE) {
6592 ASC_PRINT1(
6593 "advansys_reset: reset request not active or waiting, completing anyway %x\n",
6594 (unsigned) scp);
6596 ASC_STATS(scp->host, done);
6597 scp->scsi_done(scp);
6602 * It is possible for the request done function to re-enable
6603 * interrupts without confusing the driver. But here interrupts
6604 * aren't enabled until requests have been completed.
6606 if (done_scp != NULL) {
6607 asc_scsi_done_list(done_scp);
6610 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
6612 /* Re-enable interrupts, if they were enabled on entry. */
6613 restore_flags(flags);
6615 ASC_ASSERT(ret != ASC_ERROR);
6616 return ret;
6620 * advansys_biosparam()
6622 * Translate disk drive geometry if the "BIOS greater than 1 GB"
6623 * support is enabled for a drive.
6625 * ip (information pointer) is an int array with the following definition:
6626 * ip[0]: heads
6627 * ip[1]: sectors
6628 * ip[2]: cylinders
6631 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
6632 advansys_biosparam(Disk *dp, int dep, int ip[])
6633 #else /* version >= v1.3.0 */
6634 advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
6635 #endif /* version >= v1.3.0 */
6637 asc_board_t *boardp;
6639 ASC_DBG(1, "advansys_biosparam: begin\n");
6640 ASC_STATS(dp->device->host, biosparam);
6641 boardp = ASC_BOARDP(dp->device->host);
6642 if (ASC_NARROW_BOARD(boardp)) {
6643 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
6644 ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
6645 ip[0] = 255;
6646 ip[1] = 63;
6647 } else {
6648 ip[0] = 64;
6649 ip[1] = 32;
6651 } else {
6652 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
6653 BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) {
6654 ip[0] = 255;
6655 ip[1] = 63;
6656 } else {
6657 ip[0] = 64;
6658 ip[1] = 32;
6661 ip[2] = dp->capacity / (ip[0] * ip[1]);
6662 ASC_DBG(1, "advansys_biosparam: end\n");
6663 return 0;
6667 * advansys_setup()
6669 * This function is called from init/main.c at boot time.
6670 * It it passed LILO parameters that can be set from the
6671 * LILO command line or in /etc/lilo.conf.
6673 * It is used by the AdvanSys driver to either disable I/O
6674 * port scanning or to limit scanning to 1 - 4 I/O ports.
6675 * Regardless of the option setting EISA and PCI boards
6676 * will still be searched for and detected. This option
6677 * only affects searching for ISA and VL boards.
6679 * If ADVANSYS_DEBUG is defined the driver debug level may
6680 * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
6682 * Examples:
6683 * 1. Eliminate I/O port scanning:
6684 * boot: linux advansys=
6685 * or
6686 * boot: linux advansys=0x0
6687 * 2. Limit I/O port scanning to one I/O port:
6688 * boot: linux advansys=0x110
6689 * 3. Limit I/O port scanning to four I/O ports:
6690 * boot: linux advansys=0x110,0x210,0x230,0x330
6691 * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
6692 * set the driver debug level to 2.
6693 * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
6695 * ints[0] - number of arguments
6696 * ints[1] - first argument
6697 * ints[2] - second argument
6698 * ...
6700 ASC_INITFUNC(
6701 void,
6702 advansys_setup(char *str, int *ints)
6705 int i;
6707 if (asc_iopflag == ASC_TRUE) {
6708 printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
6709 return;
6712 asc_iopflag = ASC_TRUE;
6714 if (ints[0] > ASC_NUM_IOPORT_PROBE) {
6715 #ifdef ADVANSYS_DEBUG
6716 if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
6717 (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
6718 asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
6719 } else {
6720 #endif /* ADVANSYS_DEBUG */
6721 printk("AdvanSys SCSI: only %d I/O ports accepted\n",
6722 ASC_NUM_IOPORT_PROBE);
6723 #ifdef ADVANSYS_DEBUG
6725 #endif /* ADVANSYS_DEBUG */
6728 #ifdef ADVANSYS_DEBUG
6729 ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
6730 for (i = 1; i < ints[0]; i++) {
6731 ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
6733 ASC_DBG(1, "\n");
6734 #endif /* ADVANSYS_DEBUG */
6736 for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
6737 asc_ioport[i-1] = ints[i];
6738 ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
6739 i - 1, asc_ioport[i-1]);
6745 * --- Loadable Driver Support
6748 #ifdef MODULE
6749 Scsi_Host_Template driver_template = ADVANSYS;
6750 # include "scsi_module.c"
6751 #endif /* MODULE */
6755 * --- Miscellaneous Driver Functions
6759 * First-level interrupt handler.
6761 * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting
6762 * adapter's asc_board_t. Because all boards are currently checked
6763 * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id'
6764 * could be used to identify an interrupt passed to the AdvanSys driver,
6765 * which is for a device sharing an interrupt with an AdvanSys adapter.
6767 STATIC void
6768 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
6769 advansys_interrupt(int irq, struct pt_regs *regs)
6770 #else /* version >= v1.3.70 */
6771 advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
6772 #endif /* version >= v1.3.70 */
6774 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6775 int flags;
6776 #else /* version >= v2.1.95 */
6777 unsigned long flags;
6778 #endif /* version >= v2.1.95 */
6779 int i;
6780 asc_board_t *boardp;
6781 Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
6782 Scsi_Cmnd *new_last_scp;
6784 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6785 /* Disable interrupts, if they aren't already disabled. */
6786 save_flags(flags);
6787 cli();
6788 #else /* version >= v2.1.95 */
6790 * Disable interrupts, if they aren't already disabled and acquire
6791 * the I/O spinlock.
6793 spin_lock_irqsave(&io_request_lock, flags);
6794 #endif /* version >= v2.1.95 */
6796 ASC_DBG(1, "advansys_interrupt: begin\n");
6799 * Check for interrupts on all boards.
6800 * AscISR() will call asc_isr_callback().
6802 for (i = 0; i < asc_board_count; i++) {
6803 boardp = ASC_BOARDP(asc_host[i]);
6804 ASC_DBG2(2, "advansys_interrupt: i %d, boardp %lx\n",
6805 i, (ulong) boardp)
6806 if (ASC_NARROW_BOARD(boardp)) {
6808 * Narrow Board
6810 if (AscIsIntPending(asc_host[i]->io_port)) {
6811 ASC_STATS(asc_host[i], interrupt);
6812 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
6813 AscISR(&boardp->dvc_var.asc_dvc_var);
6815 } else {
6817 * Wide Board
6819 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
6820 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
6821 ASC_STATS(asc_host[i], interrupt);
6826 * Start waiting requests and create a list of completed requests.
6828 * If a reset or abort request is being performed for the board,
6829 * the reset or abort handler will complete pending requests after
6830 * it has completed.
6832 if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) {
6833 ASC_DBG2(1, "advansys_interrupt: done_scp %lx, last_scp %lx\n",
6834 (ulong) done_scp, (ulong) last_scp);
6836 /* Start any waiting commands for the board. */
6837 if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6838 ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6839 asc_execute_queue(&boardp->waiting);
6843 * Add to the list of requests that must be completed.
6845 * 'done_scp' will always be NULL on the first iteration
6846 * of this loop. 'last_scp' is set at the same time as
6847 * 'done_scp'.
6849 if (done_scp == NULL) {
6850 done_scp = asc_dequeue_list(&boardp->done, &last_scp,
6851 ASC_TID_ALL);
6852 } else {
6853 ASC_ASSERT(last_scp != NULL);
6854 REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
6855 &new_last_scp, ASC_TID_ALL);
6856 if (new_last_scp != NULL) {
6857 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6858 last_scp = new_last_scp;
6864 /* Interrupts could be enabled here. */
6867 * It is possible for the request done function to re-enable
6868 * interrupts without confusing the driver. But here the
6869 * original flags aren't restored until all requests have been
6870 * completed.
6872 asc_scsi_done_list(done_scp);
6874 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6876 * Restore the original flags which will enable interrupts
6877 * if and only if they were enabled on entry.
6879 restore_flags(flags);
6880 #else /* version >= v2.1.95 */
6882 * Release the I/O spinlock and restore the original flags
6883 * which will enable interrupts if and only if they were
6884 * enabled on entry.
6886 spin_unlock_irqrestore(&io_request_lock, flags);
6887 #endif /* version >= v2.1.95 */
6889 ASC_DBG(1, "advansys_interrupt: end\n");
6890 return;
6893 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6895 * Set the number of commands to queue per device for the
6896 * specified host adapter.
6898 STATIC void
6899 advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
6901 Scsi_Device *device;
6902 asc_board_t *boardp;
6904 boardp = ASC_BOARDP(shp);
6905 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
6906 for (device = devicelist; device != NULL; device = device->next) {
6907 if (device->host != shp) {
6908 continue;
6911 * Save a pointer to the device and set its initial/maximum
6912 * queue depth.
6914 boardp->device[device->id] = device;
6915 if (ASC_NARROW_BOARD(boardp)) {
6916 device->queue_depth =
6917 boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id];
6918 } else {
6919 device->queue_depth =
6920 boardp->dvc_var.adv_dvc_var.max_dvc_qng;
6922 ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
6923 (unsigned) shp, device->id, device->queue_depth);
6926 #endif /* version >= v1.3.89 */
6929 * Function used only with polled I/O requests that are initiated by
6930 * advansys_command().
6932 STATIC void
6933 advansys_command_done(Scsi_Cmnd *scp)
6935 ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
6936 scp->SCp.Status = 1;
6940 * Complete all requests on the singly linked list pointed
6941 * to by 'scp'.
6943 * Interrupts can be enabled on entry.
6945 STATIC void
6946 asc_scsi_done_list(Scsi_Cmnd *scp)
6948 Scsi_Cmnd *tscp;
6950 ASC_DBG(2, "asc_scsi_done_list: begin\n");
6951 while (scp != NULL) {
6952 ASC_DBG1(3, "asc_scsi_done_list: scp %x\n", (unsigned) scp);
6953 tscp = REQPNEXT(scp);
6954 REQPNEXT(scp) = NULL;
6955 ASC_STATS(scp->host, done);
6956 ASC_ASSERT(scp->scsi_done != NULL);
6957 scp->scsi_done(scp);
6958 scp = tscp;
6960 ASC_DBG(2, "asc_scsi_done_list: done\n");
6961 return;
6965 * Execute a single 'Scsi_Cmnd'.
6967 * The function 'done' is called when the request has been completed.
6969 * Scsi_Cmnd:
6971 * host - board controlling device
6972 * device - device to send command
6973 * target - target of device
6974 * lun - lun of device
6975 * cmd_len - length of SCSI CDB
6976 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
6977 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
6979 * if (use_sg == 0) {
6980 * request_buffer - buffer address for request
6981 * request_bufflen - length of request buffer
6982 * } else {
6983 * request_buffer - pointer to scatterlist structure
6986 * sense_buffer - sense command buffer
6988 * result (4 bytes of an int):
6989 * Byte Meaning
6990 * 0 SCSI Status Byte Code
6991 * 1 SCSI One Byte Message Code
6992 * 2 Host Error Code
6993 * 3 Mid-Level Error Code
6995 * host driver fields:
6996 * SCp - Scsi_Pointer used for command processing status
6997 * scsi_done - used to save caller's done function
6998 * host_scribble - used for pointer to another Scsi_Cmnd
7000 * If this function returns ASC_NOERROR or ASC_ERROR the request
7001 * has been enqueued on the board's 'done' queue and must be
7002 * completed by the caller.
7004 * If ASC_BUSY is returned the request must be enqueued by the
7005 * caller and re-tried later.
7007 STATIC int
7008 asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
7010 asc_board_t *boardp;
7011 ASC_DVC_VAR *asc_dvc_varp;
7012 ADV_DVC_VAR *adv_dvc_varp;
7013 ADV_SCSI_REQ_Q *adv_scsiqp;
7014 Scsi_Device *device;
7015 int ret;
7017 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7018 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
7019 (unsigned) scp, (unsigned) scp->scsi_done);
7021 boardp = ASC_BOARDP(scp->host);
7022 device = boardp->device[scp->target];
7024 if (ASC_NARROW_BOARD(boardp)) {
7026 * Build and execute Narrow Board request.
7029 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
7032 * Build Asc Library request structure using the
7033 * global structures 'asc_scsi_req' and 'asc_sg_head'.
7035 * asc_build_req() can not return ASC_BUSY.
7037 if (asc_build_req(boardp, scp) == ASC_ERROR) {
7038 ASC_STATS(scp->host, build_error);
7039 return ASC_ERROR;
7043 * Execute the command. If there is no error, add the command
7044 * to the active queue.
7046 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
7047 case ASC_NOERROR:
7048 ASC_STATS(scp->host, exe_noerror);
7050 * Increment monotonically increasing per device successful
7051 * request counter. Wrapping doesn't matter.
7053 boardp->reqcnt[scp->target]++;
7055 asc_enqueue(&boardp->active, scp, ASC_BACK);
7056 ASC_DBG(1,
7057 "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
7058 break;
7059 case ASC_BUSY:
7060 /* Caller must enqueue request and retry later. */
7061 ASC_STATS(scp->host, exe_busy);
7062 break;
7063 case ASC_ERROR:
7064 ASC_PRINT2(
7065 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
7066 boardp->id, asc_dvc_varp->err_code);
7067 ASC_STATS(scp->host, exe_error);
7068 scp->result = HOST_BYTE(DID_ERROR);
7069 asc_enqueue(&boardp->done, scp, ASC_BACK);
7070 break;
7071 default:
7072 ASC_PRINT2(
7073 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
7074 boardp->id, asc_dvc_varp->err_code);
7075 ASC_STATS(scp->host, exe_unknown);
7076 scp->result = HOST_BYTE(DID_ERROR);
7077 asc_enqueue(&boardp->done, scp, ASC_BACK);
7078 break;
7080 } else {
7082 * Build and execute Wide Board request.
7084 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
7087 * Build and get a pointer to an Adv Library request structure.
7089 * If the request is successfully built then send it below,
7090 * otherwise return with an error.
7092 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
7093 case ASC_NOERROR:
7094 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
7095 break;
7096 case ASC_BUSY:
7097 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
7098 return ASC_BUSY;
7099 case ASC_ERROR:
7100 default:
7101 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
7102 ASC_STATS(scp->host, build_error);
7103 return ASC_ERROR;
7107 * Execute the command. If there is no error, add the command
7108 * to the active queue.
7110 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
7111 case ASC_NOERROR:
7112 ASC_STATS(scp->host, exe_noerror);
7114 * Increment monotonically increasing per device successful
7115 * request counter. Wrapping doesn't matter.
7117 boardp->reqcnt[scp->target]++;
7118 asc_enqueue(&boardp->active, scp, ASC_BACK);
7119 ASC_DBG(1,
7120 "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
7121 break;
7122 case ASC_BUSY:
7123 /* Caller must enqueue request and retry later. */
7124 ASC_STATS(scp->host, exe_busy);
7125 break;
7126 case ASC_ERROR:
7127 ASC_PRINT2(
7128 "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code %x\n",
7129 boardp->id, adv_dvc_varp->err_code);
7130 ASC_STATS(scp->host, exe_error);
7131 scp->result = HOST_BYTE(DID_ERROR);
7132 asc_enqueue(&boardp->done, scp, ASC_BACK);
7133 break;
7134 default:
7135 ASC_PRINT2(
7136 "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code %x\n",
7137 boardp->id, adv_dvc_varp->err_code);
7138 ASC_STATS(scp->host, exe_unknown);
7139 scp->result = HOST_BYTE(DID_ERROR);
7140 asc_enqueue(&boardp->done, scp, ASC_BACK);
7141 break;
7145 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
7146 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7147 return ret;
7151 * Build a request structure for the Asc Library (Narrow Board).
7153 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
7154 * used to build the request.
7156 * If an error occurs, then return ASC_ERROR.
7158 STATIC int
7159 asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp)
7162 * Mutually exclusive access is required to 'asc_scsi_q' and
7163 * 'asc_sg_head' until after the request is started.
7165 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
7168 * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
7170 asc_scsi_q.q2.srb_ptr = (ulong) scp;
7173 * Build the ASC_SCSI_Q request.
7175 ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
7176 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
7177 scp->cmd_len = ASC_MAX_CDB_LEN;
7179 asc_scsi_q.cdbptr = &scp->cmnd[0];
7180 asc_scsi_q.q2.cdb_len = scp->cmd_len;
7181 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
7182 asc_scsi_q.q1.target_lun = scp->lun;
7183 asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
7184 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7185 asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
7186 #else /* version >= v2.0.0 */
7187 asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
7188 #endif /* version >= v2.0.0 */
7189 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
7192 * If there are any outstanding requests for the current target,
7193 * then every 255th request send an ORDERED request. This heuristic
7194 * tries to retain the benefit of request sorting while preventing
7195 * request starvation. 255 is the max number of tags or pending commands
7196 * a device may have outstanding.
7198 * The request count is incremented below for every successfully
7199 * started request.
7202 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->target] > 0) &&
7203 (boardp->reqcnt[scp->target] % 255) == 0) {
7204 asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
7205 } else {
7206 asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
7210 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
7211 * buffer command.
7213 if (scp->use_sg == 0) {
7215 * CDB request of single contiguous buffer.
7217 ASC_STATS(scp->host, cont_cnt);
7218 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7219 asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
7220 #else /* version >= v2.0.0 */
7221 asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
7222 #endif /* version >= v2.0.0 */
7223 asc_scsi_q.q1.data_cnt = scp->request_bufflen;
7224 ASC_STATS_ADD(scp->host, cont_xfer,
7225 ASC_CEILING(scp->request_bufflen, 512));
7226 asc_scsi_q.q1.sg_queue_cnt = 0;
7227 asc_scsi_q.sg_head = NULL;
7228 } else {
7230 * CDB scatter-gather request list.
7232 int sgcnt;
7233 struct scatterlist *slp;
7235 if (scp->use_sg > scp->host->sg_tablesize) {
7236 ASC_PRINT3(
7237 "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
7238 boardp->id, scp->use_sg, scp->host->sg_tablesize);
7239 scp->result = HOST_BYTE(DID_ERROR);
7240 asc_enqueue(&boardp->done, scp, ASC_BACK);
7241 return ASC_ERROR;
7244 ASC_STATS(scp->host, sg_cnt);
7247 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
7248 * structure to point to it.
7250 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
7252 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
7253 asc_scsi_q.sg_head = &asc_sg_head;
7254 asc_scsi_q.q1.data_cnt = 0;
7255 asc_scsi_q.q1.data_addr = 0;
7256 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
7257 ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt);
7260 * Convert scatter-gather list into ASC_SG_HEAD list.
7262 slp = (struct scatterlist *) scp->request_buffer;
7263 for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
7264 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7265 asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
7266 #else /* version >= v2.0.0 */
7267 asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
7268 #endif /* version >= v2.0.0 */
7269 asc_sg_head.sg_list[sgcnt].bytes = slp->length;
7270 ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
7274 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
7275 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
7277 return ASC_NOERROR;
7281 * Build a request structure for the Adv Library (Wide Board).
7283 * If an adv_req_t can not be allocated to issue the request,
7284 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
7286 STATIC int
7287 adv_build_req(asc_board_t *boardp, Scsi_Cmnd *scp,
7288 ADV_SCSI_REQ_Q **adv_scsiqpp)
7290 adv_req_t *reqp;
7291 ADV_SCSI_REQ_Q *scsiqp;
7292 int i;
7295 * Allocate an adv_req_t structure from the board to execute
7296 * the command.
7298 if (boardp->adv_reqp == NULL) {
7299 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
7300 ASC_STATS(scp->host, adv_build_noreq);
7301 return ASC_BUSY;
7302 } else {
7303 reqp = boardp->adv_reqp;
7304 boardp->adv_reqp = reqp->next_reqp;
7305 reqp->next_reqp = NULL;
7309 * Get 4-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
7311 scsiqp = (ADV_SCSI_REQ_Q *) ADV_DWALIGN(&reqp->scsi_req_q);
7312 memset(scsiqp, 0, sizeof(ADV_SCSI_REQ_Q));
7315 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
7317 scsiqp->srb_ptr = (ulong) reqp;
7320 * Set the adv_req_t 'cmndp' to point to the Scsi_Cmnd structure.
7322 reqp->cmndp = scp;
7325 * Build the ADV_SCSI_REQ_Q request.
7329 * Set CDB length and copy it to the request structure.
7331 ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
7332 if (scp->cmd_len > ASC_MAX_CDB_LEN) {
7333 scp->cmd_len = ASC_MAX_CDB_LEN;
7335 scsiqp->cdb_len = scp->cmd_len;
7336 for (i = 0; i < scp->cmd_len; i++) {
7337 scsiqp->cdb[i] = scp->cmnd[i];
7340 scsiqp->target_id = scp->target;
7341 scsiqp->target_lun = scp->lun;
7343 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7344 scsiqp->sense_addr = (ulong) &scp->sense_buffer[0];
7345 #else /* version >= v2.0.0 */
7346 scsiqp->sense_addr = virt_to_bus(&scp->sense_buffer[0]);
7347 #endif /* version >= v2.0.0 */
7348 scsiqp->sense_len = sizeof(scp->sense_buffer);
7351 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
7352 * buffer command.
7354 scsiqp->data_cnt = scp->request_bufflen;
7355 scsiqp->vdata_addr = (ulong) scp->request_buffer;
7356 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7357 scsiqp->data_addr = (ulong) scp->request_buffer;
7358 #else /* version >= v2.0.0 */
7359 scsiqp->data_addr = virt_to_bus(scp->request_buffer);
7360 #endif /* version >= v2.0.0 */
7362 if (scp->use_sg == 0) {
7364 * CDB request of single contiguous buffer.
7366 reqp->sgblkp = NULL;
7367 scsiqp->sg_list_ptr = NULL;
7368 ASC_STATS(scp->host, cont_cnt);
7369 ASC_STATS_ADD(scp->host, cont_xfer,
7370 ASC_CEILING(scp->request_bufflen, 512));
7371 } else {
7373 * CDB scatter-gather request list.
7375 if (scp->use_sg > ADV_MAX_SG_LIST) {
7376 ASC_PRINT3(
7377 "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
7378 boardp->id, scp->use_sg, scp->host->sg_tablesize);
7379 scp->result = HOST_BYTE(DID_ERROR);
7380 asc_enqueue(&boardp->done, scp, ASC_BACK);
7383 * Free the 'adv_req_t' structure by adding it back to the
7384 * board free list.
7386 reqp->next_reqp = boardp->adv_reqp;
7387 boardp->adv_reqp = reqp;
7389 return ASC_ERROR;
7393 * Allocate an 'adv_sgblk_t' structure from the board to
7394 * execute the command.
7396 if (boardp->adv_sgblkp == NULL) {
7397 ASC_DBG(1, "adv_build_req: no free adv_sgblk_t\n");
7398 ASC_STATS(scp->host, adv_build_nosg);
7400 * Free the 'adv_req_t' structure by adding it back to the
7401 * board free list.
7403 reqp->next_reqp = boardp->adv_reqp;
7404 boardp->adv_reqp = reqp;
7405 return ASC_BUSY;
7406 } else {
7407 reqp->sgblkp = boardp->adv_sgblkp;
7408 boardp->adv_sgblkp = reqp->sgblkp->next_sgblkp;
7409 reqp->sgblkp->next_sgblkp = NULL;
7413 * Build scatter-gather list.
7415 scsiqp->sg_list_ptr = (ADV_SG_BLOCK *)
7416 ADV_DWALIGN(&reqp->sgblkp->sg_block[0]);
7418 memset(scsiqp->sg_list_ptr, 0, sizeof(ADV_SG_BLOCK) *
7419 (ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING));
7421 if (adv_get_sglist(&boardp->dvc_var.adv_dvc_var, scsiqp, scp) ==
7422 ADV_ERROR) {
7425 * Free the adv_sgblk_t structure, if any, by adding it back
7426 * to the board free list.
7428 ASC_ASSERT(reqp->sgblkp != NULL);
7429 reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
7430 boardp->adv_sgblkp = reqp->sgblkp;
7433 * Free the adv_req_t structure by adding it back to the
7434 * board free list.
7436 reqp->next_reqp = boardp->adv_reqp;
7437 boardp->adv_reqp = reqp;
7439 return ADV_ERROR;
7442 ASC_STATS(scp->host, sg_cnt);
7443 ASC_STATS_ADD(scp->host, sg_elem, scp->use_sg);
7446 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
7447 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
7449 *adv_scsiqpp = scsiqp;
7451 return ASC_NOERROR;
7455 * Build scatter-gather list for Adv Library (Wide Board).
7457 * Return:
7458 * ADV_SUCCESS(1) - SG List successfully created
7459 * ADV_ERROR(-1) - SG List creation failed
7461 STATIC int
7462 adv_get_sglist(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp,
7463 Scsi_Cmnd *scp)
7465 ADV_SG_BLOCK *sg_block; /* virtual address of a SG */
7466 ulong sg_block_next_addr; /* block and its next */
7467 ulong sg_block_physical_addr;
7468 int i;
7469 struct scatterlist *slp;
7470 int sg_elem_cnt;
7472 slp = (struct scatterlist *) scp->request_buffer;
7473 sg_elem_cnt = scp->use_sg;
7475 sg_block = scsiqp->sg_list_ptr;
7476 sg_block_next_addr = (ulong) sg_block; /* allow math operation */
7477 sg_block_physical_addr =
7478 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7479 (ulong) scsiqp->sg_list_ptr;
7480 #else /* version >= v2.0.0 */
7481 virt_to_bus(scsiqp->sg_list_ptr);
7482 #endif /* version >= v2.0.0 */
7483 ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7484 sg_block_physical_addr);
7485 scsiqp->sg_real_addr = sg_block_physical_addr;
7489 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
7491 sg_block->sg_list[i].sg_addr =
7492 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7493 (ulong) slp->address;
7494 #else /* version >= v2.0.0 */
7495 virt_to_bus(slp->address);
7496 #endif /* version >= v2.0.0 */
7497 sg_block->sg_list[i].sg_count = slp->length;
7498 ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
7500 if (--sg_elem_cnt == 0)
7501 { /* last entry, get out */
7502 sg_block->sg_cnt = i + 1;
7503 sg_block->sg_ptr = 0L; /* next link = NULL */
7504 return ADV_SUCCESS;
7506 slp++;
7508 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
7509 sg_block_next_addr += sizeof(ADV_SG_BLOCK);
7510 sg_block_physical_addr += sizeof(ADV_SG_BLOCK);
7511 ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7512 sg_block_physical_addr);
7514 sg_block->sg_ptr = (ADV_SG_BLOCK *) sg_block_physical_addr;
7515 sg_block = (ADV_SG_BLOCK *) sg_block_next_addr; /* virtual addr */
7517 while (1);
7518 /* NOTREACHED */
7522 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
7524 * Interrupt callback function for the Narrow SCSI Asc Library.
7526 STATIC void
7527 asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
7529 asc_board_t *boardp;
7530 Scsi_Cmnd *scp;
7531 struct Scsi_Host *shp;
7532 int underrun = ASC_FALSE;
7533 int i;
7535 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7536 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n",
7537 (unsigned) asc_dvc_varp, (unsigned) qdonep);
7538 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
7541 * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7542 * command that has been completed.
7544 scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
7545 ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
7547 if (scp == NULL) {
7548 ASC_PRINT("asc_isr_callback: scp is NULL\n");
7549 return;
7551 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7554 * If the request's host pointer is not valid, display a
7555 * message and return.
7557 shp = scp->host;
7558 for (i = 0; i < asc_board_count; i++) {
7559 if (asc_host[i] == shp) {
7560 break;
7563 if (i == asc_board_count) {
7564 ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n",
7565 (unsigned) scp, (unsigned) shp);
7566 return;
7569 ASC_STATS(shp, callback);
7570 ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
7573 * If the request isn't found on the active queue, it may
7574 * have been removed to handle a reset or abort request.
7575 * Display a message and return.
7577 boardp = ASC_BOARDP(shp);
7578 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
7579 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7580 ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
7581 boardp->id, (unsigned) scp);
7582 return;
7586 * Check for an underrun condition.
7588 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
7589 qdonep->remain_bytes <= scp->request_bufflen != 0) {
7590 ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
7591 (unsigned) qdonep->remain_bytes);
7592 underrun = ASC_TRUE;
7596 * 'qdonep' contains the command's ending status.
7598 switch (qdonep->d3.done_stat) {
7599 case QD_NO_ERROR:
7600 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
7601 switch (qdonep->d3.host_stat) {
7602 case QHSTA_NO_ERROR:
7603 scp->result = 0;
7604 break;
7605 default:
7606 /* QHSTA error occurred */
7607 scp->result = HOST_BYTE(DID_ERROR);
7608 break;
7612 * If an INQUIRY command completed successfully, then call
7613 * the AscInquiryHandling() function to set-up the device.
7615 if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 &&
7616 (scp->request_bufflen - qdonep->remain_bytes) >= 8)
7618 AscInquiryHandling(asc_dvc_varp, scp->target & 0x7,
7619 (ASC_SCSI_INQUIRY *) scp->request_buffer);
7623 * If there was an underrun without any other error,
7624 * set DID_ERROR to indicate the underrun error.
7626 * Note: There is no way yet to indicate the number
7627 * of underrun bytes.
7629 if (scp->result == 0 && underrun == ASC_TRUE) {
7630 scp->result = HOST_BYTE(DID_UNDERRUN);
7632 break;
7634 case QD_WITH_ERROR:
7635 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
7636 switch (qdonep->d3.host_stat) {
7637 case QHSTA_NO_ERROR:
7638 if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
7639 ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
7640 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7641 sizeof(scp->sense_buffer));
7643 * Note: The 'status_byte()' macro used by target drivers
7644 * defined in scsi.h shifts the status byte returned by
7645 * host drivers right by 1 bit. This is why target drivers
7646 * also use right shifted status byte definitions. For
7647 * instance target drivers use CHECK_CONDITION, defined to
7648 * 0x1, instead of the SCSI defined check condition value
7649 * of 0x2. Host drivers are supposed to return the status
7650 * byte as it is defined by SCSI.
7652 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7653 STATUS_BYTE(qdonep->d3.scsi_stat);
7654 } else {
7655 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
7657 break;
7659 default:
7660 /* QHSTA error occurred */
7661 ASC_DBG1(1, "asc_isr_callback: host_stat %x\n",
7662 qdonep->d3.host_stat);
7663 scp->result = HOST_BYTE(DID_BAD_TARGET);
7664 break;
7666 break;
7668 case QD_ABORTED_BY_HOST:
7669 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
7670 scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
7671 STATUS_BYTE(qdonep->d3.scsi_stat);
7672 break;
7674 default:
7675 ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
7676 scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
7677 STATUS_BYTE(qdonep->d3.scsi_stat);
7678 break;
7682 * If the 'init_tidmask' bit isn't already set for the target and the
7683 * current request finished normally, then set the bit for the target
7684 * to indicate that a device is present.
7686 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7687 qdonep->d3.done_stat == QD_NO_ERROR &&
7688 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
7689 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7693 * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7694 * function, add the command to the end of the board's done queue.
7695 * The done function for the command will be called from
7696 * advansys_interrupt().
7698 asc_enqueue(&boardp->done, scp, ASC_BACK);
7700 return;
7704 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
7706 * Callback function for the Wide SCSI Adv Library.
7708 STATIC void
7709 adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
7711 asc_board_t *boardp;
7712 adv_req_t *reqp;
7713 Scsi_Cmnd *scp;
7714 struct Scsi_Host *shp;
7715 int underrun = ASC_FALSE;
7716 int i;
7718 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7719 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %x, scsiqp %x\n",
7720 (unsigned) adv_dvc_varp, (unsigned) scsiqp);
7721 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
7724 * Get the adv_req_t structure for the command that has been
7725 * completed. The adv_req_t structure actually contains the
7726 * completed ADV_SCSI_REQ_Q structure.
7728 reqp = (adv_req_t *) scsiqp->srb_ptr;
7729 ASC_DBG1(1, "adv_isr_callback: reqp %x\n", (unsigned) reqp);
7730 if (reqp == NULL) {
7731 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
7732 return;
7736 * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7737 * command that has been completed.
7739 * Note: The adv_req_t request structure and adv_sgblk_t structure,
7740 * if any, are dropped, because a board structure pointer can not be
7741 * determined.
7743 scp = reqp->cmndp;
7744 ASC_DBG1(1, "adv_isr_callback: scp %x\n", (unsigned) scp);
7745 if (scp == NULL) {
7746 ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
7747 return;
7749 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7752 * If the request's host pointer is not valid, display a message
7753 * and return.
7755 shp = scp->host;
7756 for (i = 0; i < asc_board_count; i++) {
7757 if (asc_host[i] == shp) {
7758 break;
7762 * Note: If the host structure is not found, the adv_req_t request
7763 * structure and adv_sgblk_t structure, if any, is dropped.
7765 if (i == asc_board_count) {
7766 ASC_PRINT2("adv_isr_callback: scp %x has bad host pointer, host %x\n",
7767 (unsigned) scp, (unsigned) shp);
7768 return;
7771 ASC_STATS(shp, callback);
7772 ASC_DBG1(1, "adv_isr_callback: shp %x\n", (unsigned) shp);
7775 * If the request isn't found on the active queue, it may have been
7776 * removed to handle a reset or abort request. Display a message and
7777 * return.
7779 * Note: Because the structure may still be in use don't attempt
7780 * to free the adv_req_t and adv_sgblk_t, if any, structures.
7782 boardp = ASC_BOARDP(shp);
7783 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
7784 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7785 ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n",
7786 boardp->id, (unsigned) scp);
7787 return;
7791 * Check for an underrun condition.
7793 if (scp->request_bufflen != 0 && scsiqp->data_cnt != 0) {
7794 ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n",
7795 scsiqp->data_cnt);
7796 underrun = ASC_TRUE;
7800 * 'done_status' contains the command's ending status.
7802 switch (scsiqp->done_status) {
7803 case QD_NO_ERROR:
7804 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
7805 switch (scsiqp->host_status) {
7806 case QHSTA_NO_ERROR:
7807 scp->result = 0;
7808 break;
7809 default:
7810 /* QHSTA error occurred. */
7811 ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
7812 scsiqp->host_status);
7813 scp->result = HOST_BYTE(DID_ERROR);
7814 break;
7817 * If there was an underrun without any other error,
7818 * set DID_ERROR to indicate the underrun error.
7820 * Note: There is no way yet to indicate the number
7821 * of underrun bytes.
7823 if (scp->result == 0 && underrun == ASC_TRUE) {
7824 scp->result = HOST_BYTE(DID_UNDERRUN);
7826 break;
7828 case QD_WITH_ERROR:
7829 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
7830 switch (scsiqp->host_status) {
7831 case QHSTA_NO_ERROR:
7832 if (scsiqp->scsi_status == SS_CHK_CONDITION) {
7833 ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n");
7834 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7835 sizeof(scp->sense_buffer));
7837 * Note: The 'status_byte()' macro used by target drivers
7838 * defined in scsi.h shifts the status byte returned by
7839 * host drivers right by 1 bit. This is why target drivers
7840 * also use right shifted status byte definitions. For
7841 * instance target drivers use CHECK_CONDITION, defined to
7842 * 0x1, instead of the SCSI defined check condition value
7843 * of 0x2. Host drivers are supposed to return the status
7844 * byte as it is defined by SCSI.
7846 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7847 STATUS_BYTE(scsiqp->scsi_status);
7848 } else {
7849 scp->result = STATUS_BYTE(scsiqp->scsi_status);
7851 break;
7853 default:
7854 /* Some other QHSTA error occurred. */
7855 ASC_DBG1(1, "adv_isr_callback: host_status %x\n",
7856 scsiqp->host_status);
7857 scp->result = HOST_BYTE(DID_BAD_TARGET);
7858 break;
7860 break;
7862 case QD_ABORTED_BY_HOST:
7863 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
7864 scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
7865 break;
7867 default:
7868 ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status);
7869 scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
7870 break;
7874 * If the 'init_tidmask' bit isn't already set for the target and the
7875 * current request finished normally, then set the bit for the target
7876 * to indicate that a device is present.
7878 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7879 scsiqp->done_status == QD_NO_ERROR &&
7880 scsiqp->host_status == QHSTA_NO_ERROR) {
7881 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7885 * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7886 * function, add the command to the end of the board's done queue.
7887 * The done function for the command will be called from
7888 * advansys_interrupt().
7890 asc_enqueue(&boardp->done, scp, ASC_BACK);
7893 * Free the adv_sgblk_t structure, if any, by adding it back
7894 * to the board free list.
7896 if (reqp->sgblkp != NULL) {
7897 reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
7898 boardp->adv_sgblkp = reqp->sgblkp;
7902 * Free the adv_req_t structure used with the command by adding
7903 * it back to the board free list.
7905 reqp->next_reqp = boardp->adv_reqp;
7906 boardp->adv_reqp = reqp;
7908 ASC_DBG(1, "adv_isr_callback: done\n");
7910 return;
7914 * adv_async_callback() - Adv Library asynchronous event callback function.
7916 STATIC void
7917 adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
7919 switch (code)
7921 case ADV_ASYNC_SCSI_BUS_RESET_DET:
7923 * The firmware detected a SCSI Bus reset.
7925 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
7926 break;
7928 case ADV_ASYNC_RDMA_FAILURE:
7930 * Handle RDMA failure by resetting the SCSI Bus and
7931 * possibly the chip if it is unresponsive. Log the error
7932 * with a unique code.
7934 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
7935 AdvResetChipAndSB(adv_dvc_varp);
7936 break;
7938 case ADV_HOST_SCSI_BUS_RESET:
7940 * Host generated SCSI bus reset occurred.
7942 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
7943 break;
7945 default:
7946 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
7947 break;
7951 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
7952 #ifdef ASC_CONFIG_PCI
7954 * Search for an AdvanSys PCI device in the PCI configuration space.
7956 ASC_INITFUNC(
7957 STATIC int,
7958 asc_srch_pci_dev(PCI_DEVICE *pciDevice)
7961 int ret = PCI_DEVICE_NOT_FOUND;
7963 ASC_DBG(2, "asc_srch_pci_dev: begin\n");
7965 if (pci_scan_method == -1) {
7966 pci_scan_method = asc_scan_method();
7968 pciDevice->type = pci_scan_method;
7969 ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
7971 ret = asc_pci_find_dev(pciDevice);
7972 ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
7973 if (ret == PCI_DEVICE_FOUND) {
7974 pciDevice->slotNumber = pciDevice->slotFound + 1;
7975 pciDevice->startSlot = pciDevice->slotFound + 1;
7976 } else {
7977 if (pciDevice->bridge > pciDevice->busNumber) {
7978 ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
7979 pciDevice->bridge, pciDevice->busNumber);
7980 pciDevice->busNumber++;
7981 pciDevice->slotNumber = 0;
7982 pciDevice->startSlot = 0;
7983 pciDevice->endSlot = 0x0f;
7984 ret = asc_srch_pci_dev(pciDevice);
7985 ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
7989 ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
7990 return ret;
7994 * Determine the access method to be used for 'pciDevice'.
7996 ASC_INITFUNC(
7997 STATIC uchar,
7998 asc_scan_method(void)
8001 ushort data;
8002 PCI_DATA pciData;
8003 uchar type;
8004 uchar slot;
8006 ASC_DBG(2, "asc_scan_method: begin\n");
8007 memset(&pciData, 0, sizeof(pciData));
8008 for (type = 1; type < 3; type++) {
8009 pciData.type = type;
8010 for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
8011 pciData.slot = slot;
8012 data = asc_get_cfg_word(&pciData);
8013 if ((data != 0xFFFF) && (data != 0x0000)) {
8014 ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
8015 return (type);
8019 ASC_DBG1(4, "asc_scan_method: type %d\n", type);
8020 return (type);
8024 * Check for an AdvanSys PCI device in 'pciDevice'.
8026 * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
8028 ASC_INITFUNC(
8029 STATIC int,
8030 asc_pci_find_dev(PCI_DEVICE *pciDevice)
8033 PCI_DATA pciData;
8034 ushort vendorid, deviceid;
8035 uchar classcode, subclass;
8036 uchar lslot;
8038 ASC_DBG(3, "asc_pci_find_dev: begin\n");
8039 pciData.type = pciDevice->type;
8040 pciData.bus = pciDevice->busNumber;
8041 pciData.func = pciDevice->devFunc;
8042 lslot = pciDevice->startSlot;
8043 for (; lslot < pciDevice->endSlot; lslot++) {
8044 pciData.slot = lslot;
8045 pciData.offset = VENDORID_OFFSET;
8046 vendorid = asc_get_cfg_word(&pciData);
8047 ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
8048 if (vendorid != 0xffff) {
8049 pciData.offset = DEVICEID_OFFSET;
8050 deviceid = asc_get_cfg_word(&pciData);
8051 ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
8052 if ((vendorid == ASC_PCI_VENDORID) &&
8053 ((deviceid == ASC_PCI_DEVICE_ID_1100) ||
8054 (deviceid == ASC_PCI_DEVICE_ID_1200) ||
8055 (deviceid == ASC_PCI_DEVICE_ID_1300) ||
8056 (deviceid == ASC_PCI_DEVICE_ID_2300) ||
8057 (deviceid == ASC_PCI_DEVICE_ID_2500))) {
8058 pciDevice->slotFound = lslot;
8059 ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
8060 return PCI_DEVICE_FOUND;
8061 } else {
8062 pciData.offset = SUBCLASS_OFFSET;
8063 subclass = asc_get_cfg_byte(&pciData);
8064 pciData.offset = CLASSCODE_OFFSET;
8065 classcode = asc_get_cfg_byte(&pciData);
8066 if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
8067 (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
8068 pciDevice->bridge++;
8070 ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
8071 subclass, classcode);
8075 return PCI_DEVICE_NOT_FOUND;
8079 * Read PCI configuration data into 'pciConfig'.
8081 ASC_INITFUNC(
8082 STATIC void,
8083 asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
8086 PCI_DATA pciData;
8087 uchar counter;
8088 uchar *localConfig;
8090 ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ",
8091 pciDevice->slotFound);
8093 pciData.type = pciDevice->type;
8094 pciData.bus = pciDevice->busNumber;
8095 pciData.slot = pciDevice->slotFound;
8096 pciData.func = pciDevice->devFunc;
8097 localConfig = (uchar *) pciConfig;
8099 for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
8100 pciData.offset = counter;
8101 *localConfig = asc_get_cfg_byte(&pciData);
8102 ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
8103 localConfig++;
8105 ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
8109 * Read a word (16 bits) from the PCI configuration space.
8111 * The configuration mechanism is checked for the correct access method.
8113 ASC_INITFUNC(
8114 STATIC ushort,
8115 asc_get_cfg_word(PCI_DATA *pciData)
8118 ushort tmp;
8119 ulong address;
8120 ulong lbus = pciData->bus;
8121 ulong lslot = pciData->slot;
8122 ulong lfunc = pciData->func;
8123 uchar t2CFA, t2CF8;
8124 ulong t1CF8, t1CFC;
8126 ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
8127 pciData->type, lbus, lslot, lfunc);
8130 * Check type of configuration mechanism.
8132 if (pciData->type == 2) {
8134 * Save registers to be restored later.
8136 t2CFA = inp(0xCFA); /* save PCI bus register */
8137 t2CF8 = inp(0xCF8); /* save config space enable register */
8140 * Write the bus and enable registers.
8142 /* set for type 1 cycle, if needed */
8143 outp(0xCFA, pciData->bus);
8144 /* set the function number */
8145 outp(0xCF8, 0x10 | (pciData->func << 1));
8148 * Read the configuration space type 2 locations.
8150 tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
8152 outp(0xCFA, t2CFA); /* save PCI bus register */
8153 outp(0xCF8, t2CF8); /* save config space enable register */
8154 } else {
8156 * Type 1 or 3 configuration mechanism.
8158 * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
8160 t1CF8 = inpl(0xCF8);
8161 t1CFC = inpl(0xCFC);
8164 * enable <31>, bus = <23:16>, slot = <15:11>,
8165 * func = <10:8>, reg = <7:2>
8167 address = (ulong) ((lbus << 16) | (lslot << 11) |
8168 (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
8171 * Write out the address to CONFIG_ADDRESS.
8173 outpl(0xCF8, address);
8176 * Read in word from CONFIG_DATA.
8178 tmp = (ushort) ((inpl(0xCFC) >>
8179 ((pciData->offset & 2) * 8)) & 0xFFFF);
8182 * Restore registers.
8184 outpl(0xCF8, t1CF8);
8185 outpl(0xCFC, t1CFC);
8187 ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
8188 return tmp;
8192 * Reads a byte from the PCI configuration space.
8194 * The configuration mechanism is checked for the correct access method.
8196 ASC_INITFUNC(
8197 STATIC uchar,
8198 asc_get_cfg_byte(PCI_DATA *pciData)
8201 uchar tmp;
8202 ulong address;
8203 ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
8204 uchar t2CFA, t2CF8;
8205 ulong t1CF8, t1CFC;
8207 ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
8210 * Check type of configuration mechanism.
8212 if (pciData->type == 2) {
8214 * Save registers to be restored later.
8216 t2CFA = inp(0xCFA); /* save PCI bus register */
8217 t2CF8 = inp(0xCF8); /* save config space enable register */
8220 * Write the bus and enable registers.
8222 /* set for type 1 cycle, if needed */
8223 outp(0xCFA, pciData->bus);
8224 /* set the function number */
8225 outp(0xCF8, 0x10 | (pciData->func << 1));
8228 * Read configuration space type 2 locations.
8230 tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
8233 * Restore registers.
8235 outp(0xCF8, t2CF8); /* restore the enable register */
8236 outp(0xCFA, t2CFA); /* restore PCI bus register */
8237 } else {
8239 * Type 1 or 3 configuration mechanism.
8241 * Save CONFIG_ADDRESS and CONFIG_DATA register values.
8243 t1CF8 = inpl(0xCF8);
8244 t1CFC = inpl(0xCFC);
8247 * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
8248 * reg = <7:2>
8250 address = (ulong) ((lbus << 16) | (lslot << 11) |
8251 (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
8254 * Write out address to CONFIG_ADDRESS.
8256 outpl(0xCF8, address);
8259 * Read in word from CONFIG_DATA.
8261 tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
8264 * Restore registers.
8266 outpl(0xCF8, t1CF8);
8267 outpl(0xCFC, t1CFC);
8269 ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
8270 return tmp;
8274 * Write a byte to the PCI configuration space.
8276 ASC_INITFUNC(
8277 STATIC void,
8278 asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
8281 ulong tmpl;
8282 ulong address;
8283 ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
8284 uchar t2CFA, t2CF8;
8285 ulong t1CF8, t1CFC;
8287 ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n",
8288 pciData->type, byte_data);
8291 * Check type of configuration mechanism.
8293 if (pciData->type == 2) {
8296 * Save registers to be restored later.
8298 t2CFA = inp(0xCFA); /* save PCI bus register */
8299 t2CF8 = inp(0xCF8); /* save config space enable register */
8302 * Write bus and enable registers.
8304 outp(0xCFA, pciData->bus);
8307 * Set the function number.
8309 outp(0xCF8, 0x10 | (pciData->func << 1));
8312 * Write the configuration space type 2 locations.
8314 outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data);
8317 * Restore registers.
8319 outp(0xCF8, t2CF8); /* restore the enable register */
8320 outp(0xCFA, t2CFA); /* restore PCI bus register */
8321 } else {
8324 * Type 1 or 3 configuration mechanism.
8326 * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
8328 t1CF8 = inpl(0xCF8);
8329 t1CFC = inpl(0xCFC);
8332 * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
8333 * reg = <7:2>
8335 address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) |
8336 (pciData->offset & 0xFC) | 0x80000000L);
8338 * Write out address to CONFIG_ADDRESS.
8340 outpl(0xCF8, address);
8343 * Write double word to CONFIG_DATA preserving the bytes
8344 * in the double not written.
8346 tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8));
8347 outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8)));
8350 * Restore registers.
8352 outpl(0xCF8, t1CF8);
8353 outpl(0xCFC, t1CFC);
8355 ASC_DBG(4, "asc_put_cfg_byte: end\n");
8357 #endif /* ASC_CONFIG_PCI */
8358 #endif /* version < v2.1.93 */
8361 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
8362 * to indicate a command is queued for the device.
8364 * 'flag' may be either ASC_FRONT or ASC_BACK.
8366 * 'REQPNEXT(reqp)' returns reqp's next pointer.
8368 STATIC void
8369 asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
8371 int tid;
8373 ASC_DBG3(3, "asc_enqueue: ascq %x, reqp %x, flag %d\n",
8374 (unsigned) ascq, (unsigned) reqp, flag);
8375 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8376 ASC_ASSERT(reqp != NULL);
8377 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
8378 tid = REQPTID(reqp);
8379 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8380 if (flag == ASC_FRONT) {
8381 REQPNEXT(reqp) = ascq->q_first[tid];
8382 ascq->q_first[tid] = reqp;
8383 /* If the queue was empty, set the last pointer. */
8384 if (ascq->q_last[tid] == NULL) {
8385 ascq->q_last[tid] = reqp;
8387 } else { /* ASC_BACK */
8388 if (ascq->q_last[tid] != NULL) {
8389 REQPNEXT(ascq->q_last[tid]) = reqp;
8391 ascq->q_last[tid] = reqp;
8392 REQPNEXT(reqp) = NULL;
8393 /* If the queue was empty, set the first pointer. */
8394 if (ascq->q_first[tid] == NULL) {
8395 ascq->q_first[tid] = reqp;
8398 /* The queue has at least one entry, set its bit. */
8399 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
8400 #ifdef ADVANSYS_STATS
8401 /* Maintain request queue statistics. */
8402 ascq->q_tot_cnt[tid]++;
8403 ascq->q_cur_cnt[tid]++;
8404 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
8405 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
8406 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
8407 tid, ascq->q_max_cnt[tid]);
8409 REQPTIME(reqp) = REQTIMESTAMP();
8410 #endif /* ADVANSYS_STATS */
8411 ASC_DBG1(3, "asc_enqueue: reqp %x\n", (unsigned) reqp);
8412 return;
8416 * Return first queued 'REQP' on the specified queue for
8417 * the specified target device. Clear the 'tidmask' bit for
8418 * the device if no more commands are left queued for it.
8420 * 'REQPNEXT(reqp)' returns reqp's next pointer.
8422 STATIC REQP
8423 asc_dequeue(asc_queue_t *ascq, int tid)
8425 REQP reqp;
8427 ASC_DBG2(3, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid);
8428 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8429 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8430 if ((reqp = ascq->q_first[tid]) != NULL) {
8431 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
8432 ascq->q_first[tid] = REQPNEXT(reqp);
8433 /* If the queue is empty, clear its bit and the last pointer. */
8434 if (ascq->q_first[tid] == NULL) {
8435 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
8436 ASC_ASSERT(ascq->q_last[tid] == reqp);
8437 ascq->q_last[tid] = NULL;
8439 #ifdef ADVANSYS_STATS
8440 /* Maintain request queue statistics. */
8441 ascq->q_cur_cnt[tid]--;
8442 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
8443 REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
8444 #endif /* ADVANSYS_STATS */
8446 ASC_DBG1(3, "asc_dequeue: reqp %x\n", (unsigned) reqp);
8447 return reqp;
8451 * Return a pointer to a singly linked list of all the requests queued
8452 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
8454 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
8455 * the last request returned in the singly linked list.
8457 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
8458 * then all queued requests are concatenated into one list and
8459 * returned.
8461 * Note: If 'lastpp' is used to append a new list to the end of
8462 * an old list, only change the old list last pointer if '*lastpp'
8463 * (or the function return value) is not NULL, i.e. use a temporary
8464 * variable for 'lastpp' and check its value after the function return
8465 * before assigning it to the list last pointer.
8467 * Unfortunately collecting queuing time statistics adds overhead to
8468 * the function that isn't inherent to the function's algorithm.
8470 STATIC REQP
8471 asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
8473 REQP firstp, lastp;
8474 int i;
8476 ASC_DBG2(3, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid);
8477 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8478 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
8481 * If 'tid' is not ASC_TID_ALL, return requests only for
8482 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
8483 * requests for all tids.
8485 if (tid != ASC_TID_ALL) {
8486 /* Return all requests for the specified 'tid'. */
8487 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
8488 /* List is empty; Set first and last return pointers to NULL. */
8489 firstp = lastp = NULL;
8490 } else {
8491 firstp = ascq->q_first[tid];
8492 lastp = ascq->q_last[tid];
8493 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
8494 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
8495 #ifdef ADVANSYS_STATS
8497 REQP reqp;
8498 ascq->q_cur_cnt[tid] = 0;
8499 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
8500 REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
8503 #endif /* ADVANSYS_STATS */
8505 } else {
8506 /* Return all requests for all tids. */
8507 firstp = lastp = NULL;
8508 for (i = 0; i <= ADV_MAX_TID; i++) {
8509 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
8510 if (firstp == NULL) {
8511 firstp = ascq->q_first[i];
8512 lastp = ascq->q_last[i];
8513 } else {
8514 ASC_ASSERT(lastp != NULL);
8515 REQPNEXT(lastp) = ascq->q_first[i];
8516 lastp = ascq->q_last[i];
8518 ascq->q_first[i] = ascq->q_last[i] = NULL;
8519 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8520 #ifdef ADVANSYS_STATS
8521 ascq->q_cur_cnt[i] = 0;
8522 #endif /* ADVANSYS_STATS */
8525 #ifdef ADVANSYS_STATS
8527 REQP reqp;
8528 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
8529 REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
8532 #endif /* ADVANSYS_STATS */
8534 if (lastpp) {
8535 *lastpp = lastp;
8537 ASC_DBG1(3, "asc_dequeue_list: firstp %x\n", (unsigned) firstp);
8538 return firstp;
8542 * Remove the specified 'REQP' from the specified queue for
8543 * the specified target device. Clear the 'tidmask' bit for the
8544 * device if no more commands are left queued for it.
8546 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
8548 * Return ASC_TRUE if the command was found and removed,
8549 * otherwise return ASC_FALSE.
8551 STATIC int
8552 asc_rmqueue(asc_queue_t *ascq, REQP reqp)
8554 REQP currp, prevp;
8555 int tid;
8556 int ret = ASC_FALSE;
8558 ASC_DBG2(3, "asc_rmqueue: ascq %x, reqp %x\n",
8559 (unsigned) ascq, (unsigned) reqp);
8560 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8561 ASC_ASSERT(reqp != NULL);
8563 tid = REQPTID(reqp);
8564 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8567 * Handle the common case of 'reqp' being the first
8568 * entry on the queue.
8570 if (reqp == ascq->q_first[tid]) {
8571 ret = ASC_TRUE;
8572 ascq->q_first[tid] = REQPNEXT(reqp);
8573 /* If the queue is now empty, clear its bit and the last pointer. */
8574 if (ascq->q_first[tid] == NULL) {
8575 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
8576 ASC_ASSERT(ascq->q_last[tid] == reqp);
8577 ascq->q_last[tid] = NULL;
8579 } else if (ascq->q_first[tid] != NULL) {
8580 ASC_ASSERT(ascq->q_last[tid] != NULL);
8582 * Because the case of 'reqp' being the first entry has been
8583 * handled above and it is known the queue is not empty, if
8584 * 'reqp' is found on the queue it is guaranteed the queue will
8585 * not become empty and that 'q_first[tid]' will not be changed.
8587 * Set 'prevp' to the first entry, 'currp' to the second entry,
8588 * and search for 'reqp'.
8590 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
8591 currp; prevp = currp, currp = REQPNEXT(currp)) {
8592 if (currp == reqp) {
8593 ret = ASC_TRUE;
8594 REQPNEXT(prevp) = REQPNEXT(currp);
8595 REQPNEXT(reqp) = NULL;
8596 if (ascq->q_last[tid] == reqp) {
8597 ascq->q_last[tid] = prevp;
8599 break;
8603 #ifdef ADVANSYS_STATS
8604 /* Maintain request queue statistics. */
8605 if (ret == ASC_TRUE) {
8606 ascq->q_cur_cnt[tid]--;
8607 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
8609 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
8610 #endif /* ADVANSYS_STATS */
8611 ASC_DBG2(3, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret);
8612 return ret;
8616 * If the specified 'REQP' is queued on the specified queue for
8617 * the specified target device, return ASC_TRUE.
8619 STATIC int
8620 asc_isqueued(asc_queue_t *ascq, REQP reqp)
8622 REQP treqp;
8623 int tid;
8624 int ret = ASC_FALSE;
8626 ASC_DBG2(3, "asc_isqueued: ascq %x, reqp %x\n",
8627 (unsigned) ascq, (unsigned) reqp);
8628 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8629 ASC_ASSERT(reqp != NULL);
8631 tid = REQPTID(reqp);
8632 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8634 for (treqp = ascq->q_first[tid]; treqp; treqp = REQPNEXT(treqp)) {
8635 ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
8636 if (treqp == reqp) {
8637 ret = ASC_TRUE;
8638 break;
8641 ASC_DBG1(3, "asc_isqueued: ret %x\n", ret);
8642 return ret;
8646 * Execute as many queued requests as possible for the specified queue.
8648 * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd.
8650 STATIC void
8651 asc_execute_queue(asc_queue_t *ascq)
8653 ADV_SCSI_BIT_ID_TYPE scan_tidmask;
8654 REQP reqp;
8655 int i;
8657 ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq);
8658 ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8660 * Execute queued commands for devices attached to
8661 * the current board in round-robin fashion.
8663 scan_tidmask = ascq->q_tidmask;
8664 do {
8665 for (i = 0; i <= ADV_MAX_TID; i++) {
8666 if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
8667 if ((reqp = asc_dequeue(ascq, i)) == NULL) {
8668 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8669 } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp)
8670 == ASC_BUSY) {
8671 scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8672 /* Put the request back at front of the list. */
8673 asc_enqueue(ascq, reqp, ASC_FRONT);
8677 } while (scan_tidmask);
8678 return;
8681 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
8683 * asc_prt_board_devices()
8685 * Print driver information for devices attached to the board.
8687 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8688 * cf. asc_prt_line().
8690 * Return the number of characters copied into 'cp'. No more than
8691 * 'cplen' characters will be copied to 'cp'.
8693 STATIC int
8694 asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
8696 asc_board_t *boardp;
8697 int leftlen;
8698 int totlen;
8699 int len;
8700 int chip_scsi_id;
8701 int i;
8703 boardp = ASC_BOARDP(shp);
8704 leftlen = cplen;
8705 totlen = len = 0;
8707 len = asc_prt_line(cp, leftlen,
8708 "\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no);
8709 ASC_PRT_NEXT();
8711 if (ASC_NARROW_BOARD(boardp)) {
8712 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8713 } else {
8714 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8717 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
8718 ASC_PRT_NEXT();
8719 for (i = 0; i <= ADV_MAX_TID; i++) {
8720 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
8721 len = asc_prt_line(cp, leftlen, " %X,", i);
8722 ASC_PRT_NEXT();
8725 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
8726 ASC_PRT_NEXT();
8728 return totlen;
8732 * Display Wide Board BIOS Information.
8734 STATIC int
8735 asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen)
8737 asc_board_t *boardp;
8738 int leftlen;
8739 int totlen;
8740 int len;
8741 int upgrade = ASC_FALSE;
8742 ushort major, minor, letter;
8744 boardp = ASC_BOARDP(shp);
8745 leftlen = cplen;
8746 totlen = len = 0;
8748 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
8749 ASC_PRT_NEXT();
8752 * If the BIOS saved a valid signature, then fill in
8753 * the BIOS code segment base address.
8755 if (boardp->bios_signature != 0x55AA) {
8756 len = asc_prt_line(cp, leftlen, "Pre-3.1\n");
8757 ASC_PRT_NEXT();
8758 upgrade = ASC_TRUE;
8759 } else {
8760 major = (boardp->bios_version >> 12) & 0xF;
8761 minor = (boardp->bios_version >> 8) & 0xF;
8762 letter = (boardp->bios_version & 0xFF);
8764 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
8765 major, minor, letter >= 26 ? '?' : letter + 'A');
8766 ASC_PRT_NEXT();
8768 /* Current available ROM BIOS release is 3.1C. */
8769 if (major < 3 || (major <= 3 && minor < 1) ||
8770 (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) {
8771 upgrade = ASC_TRUE;
8774 if (upgrade == ASC_TRUE) {
8775 len = asc_prt_line(cp, leftlen,
8776 "Newer version of ROM BIOS available: ftp://ftp.advansys.com/pub\n");
8777 ASC_PRT_NEXT();
8780 return totlen;
8784 * Add serial number to information bar if signature AAh
8785 * is found in at bit 15-9 (7 bits) of word 1.
8787 * Serial Number consists fo 12 alpha-numeric digits.
8789 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
8790 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
8791 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
8792 * 5 - Product revision (A-J) Word0: " "
8794 * Signature Word1: 15-9 (7 bits)
8795 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
8796 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
8798 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
8800 * Note 1: Only production cards will have a serial number.
8802 * Note 2: Signature is most significant 7 bits (0xFE).
8804 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
8806 STATIC int
8807 asc_get_eeprom_string(ushort *serialnum, uchar *cp)
8809 ushort w, num;
8811 if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) {
8812 return ASC_FALSE;
8813 } else {
8815 * First word - 6 digits.
8817 w = serialnum[0];
8819 /* Product type - 1st digit. */
8820 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
8821 /* Product type is P=Prototype */
8822 *cp += 0x8;
8824 cp++;
8826 /* Manufacturing location - 2nd digit. */
8827 *cp++ = 'A' + ((w & 0x1C00) >> 10);
8829 /* Product ID - 3rd, 4th digits. */
8830 num = w & 0x3FF;
8831 *cp++ = '0' + (num / 100);
8832 num %= 100;
8833 *cp++ = '0' + (num / 10);
8835 /* Product revision - 5th digit. */
8836 *cp++ = 'A' + (num % 10);
8839 * Second word
8841 w = serialnum[1];
8844 * Year - 6th digit.
8846 * If bit 15 of third word is set, then the
8847 * last digit of the year is greater than 7.
8849 if (serialnum[2] & 0x8000) {
8850 *cp++ = '8' + ((w & 0x1C0) >> 6);
8851 } else {
8852 *cp++ = '0' + ((w & 0x1C0) >> 6);
8855 /* Week of year - 7th, 8th digits. */
8856 num = w & 0x003F;
8857 *cp++ = '0' + num / 10;
8858 num %= 10;
8859 *cp++ = '0' + num;
8862 * Third word
8864 w = serialnum[2] & 0x7FFF;
8866 /* Serial number - 9th digit. */
8867 *cp++ = 'A' + (w / 1000);
8869 /* 10th, 11th, 12th digits. */
8870 num = w % 1000;
8871 *cp++ = '0' + num / 100;
8872 num %= 100;
8873 *cp++ = '0' + num / 10;
8874 num %= 10;
8875 *cp++ = '0' + num;
8877 *cp = '\0'; /* Null Terminate the string. */
8878 return ASC_TRUE;
8883 * asc_prt_asc_board_eeprom()
8885 * Print board EEPROM configuration.
8887 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8888 * cf. asc_prt_line().
8890 * Return the number of characters copied into 'cp'. No more than
8891 * 'cplen' characters will be copied to 'cp'.
8893 STATIC int
8894 asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8896 asc_board_t *boardp;
8897 ASC_DVC_VAR *asc_dvc_varp;
8898 int leftlen;
8899 int totlen;
8900 int len;
8901 ASCEEP_CONFIG *ep;
8902 int i;
8903 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
8904 uchar serialstr[13];
8906 boardp = ASC_BOARDP(shp);
8907 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
8908 ep = &boardp->eep_config.asc_eep;
8910 leftlen = cplen;
8911 totlen = len = 0;
8913 len = asc_prt_line(cp, leftlen,
8914 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8915 ASC_PRT_NEXT();
8917 if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) ==
8918 ASC_TRUE) {
8919 len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8920 ASC_PRT_NEXT();
8921 } else {
8922 if (ep->adapter_info[5] == 0xBB) {
8923 len = asc_prt_line(cp, leftlen,
8924 " Default Settings Used for EEPROM-less Adapter.\n");
8925 ASC_PRT_NEXT();
8926 } else {
8927 len = asc_prt_line(cp, leftlen,
8928 " Serial Number Signature Not Present.\n");
8929 ASC_PRT_NEXT();
8933 len = asc_prt_line(cp, leftlen,
8934 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8935 ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng);
8936 ASC_PRT_NEXT();
8938 len = asc_prt_line(cp, leftlen,
8939 " cntl %x, no_scam %x\n",
8940 ep->cntl, ep->no_scam);
8941 ASC_PRT_NEXT();
8943 len = asc_prt_line(cp, leftlen,
8944 " Target ID: ");
8945 ASC_PRT_NEXT();
8946 for (i = 0; i <= ASC_MAX_TID; i++) {
8947 len = asc_prt_line(cp, leftlen, " %d", i);
8948 ASC_PRT_NEXT();
8950 len = asc_prt_line(cp, leftlen, "\n");
8951 ASC_PRT_NEXT();
8953 len = asc_prt_line(cp, leftlen,
8954 " Disconnects: ");
8955 ASC_PRT_NEXT();
8956 for (i = 0; i <= ASC_MAX_TID; i++) {
8957 len = asc_prt_line(cp, leftlen, " %c",
8958 (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8959 ASC_PRT_NEXT();
8961 len = asc_prt_line(cp, leftlen, "\n");
8962 ASC_PRT_NEXT();
8964 len = asc_prt_line(cp, leftlen,
8965 " Command Queuing: ");
8966 ASC_PRT_NEXT();
8967 for (i = 0; i <= ASC_MAX_TID; i++) {
8968 len = asc_prt_line(cp, leftlen, " %c",
8969 (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8970 ASC_PRT_NEXT();
8972 len = asc_prt_line(cp, leftlen, "\n");
8973 ASC_PRT_NEXT();
8975 len = asc_prt_line(cp, leftlen,
8976 " Start Motor: ");
8977 ASC_PRT_NEXT();
8978 for (i = 0; i <= ASC_MAX_TID; i++) {
8979 len = asc_prt_line(cp, leftlen, " %c",
8980 (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8981 ASC_PRT_NEXT();
8983 len = asc_prt_line(cp, leftlen, "\n");
8984 ASC_PRT_NEXT();
8986 len = asc_prt_line(cp, leftlen,
8987 " Synchronous Transfer:");
8988 ASC_PRT_NEXT();
8989 for (i = 0; i <= ASC_MAX_TID; i++) {
8990 len = asc_prt_line(cp, leftlen, " %c",
8991 (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8992 ASC_PRT_NEXT();
8994 len = asc_prt_line(cp, leftlen, "\n");
8995 ASC_PRT_NEXT();
8997 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
8998 len = asc_prt_line(cp, leftlen,
8999 " Host ISA DMA speed: %d MB/S\n",
9000 isa_dma_speed[ep->isa_dma_speed]);
9001 ASC_PRT_NEXT();
9004 return totlen;
9008 * asc_prt_adv_board_eeprom()
9010 * Print board EEPROM configuration.
9012 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9013 * cf. asc_prt_line().
9015 * Return the number of characters copied into 'cp'. No more than
9016 * 'cplen' characters will be copied to 'cp'.
9018 STATIC int
9019 asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
9021 asc_board_t *boardp;
9022 ADV_DVC_VAR *adv_dvc_varp;
9023 int leftlen;
9024 int totlen;
9025 int len;
9026 int i;
9027 char *termstr;
9028 uchar serialstr[13];
9029 ADVEEP_3550_CONFIG *ep_3550 = NULL;
9030 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
9031 ushort word;
9032 ushort *wordp;
9033 ushort sdtr_speed = 0;
9035 boardp = ASC_BOARDP(shp);
9036 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
9037 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9039 ep_3550 = &boardp->eep_config.adv_3550_eep;
9040 } else
9042 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
9045 leftlen = cplen;
9046 totlen = len = 0;
9048 len = asc_prt_line(cp, leftlen,
9049 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
9050 ASC_PRT_NEXT();
9052 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9054 wordp = &ep_3550->serial_number_word1;
9055 } else
9057 wordp = &ep_38C0800->serial_number_word1;
9060 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
9061 len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
9062 ASC_PRT_NEXT();
9063 } else {
9064 len = asc_prt_line(cp, leftlen,
9065 " Serial Number Signature Not Present.\n");
9066 ASC_PRT_NEXT();
9069 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9071 len = asc_prt_line(cp, leftlen,
9072 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
9073 ep_3550->adapter_scsi_id, ep_3550->max_host_qng,
9074 ep_3550->max_dvc_qng);
9075 ASC_PRT_NEXT();
9076 } else
9078 len = asc_prt_line(cp, leftlen,
9079 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
9080 ep_38C0800->adapter_scsi_id, ep_38C0800->max_host_qng,
9081 ep_38C0800->max_dvc_qng);
9082 ASC_PRT_NEXT();
9084 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9086 word = ep_3550->termination;
9087 } else
9089 word = ep_38C0800->termination_lvd;
9091 switch (word) {
9092 case 1:
9093 termstr = "Low Off/High Off";
9094 break;
9095 case 2:
9096 termstr = "Low Off/High On";
9097 break;
9098 case 3:
9099 termstr = "Low On/High On";
9100 break;
9101 default:
9102 case 0:
9103 termstr = "Automatic";
9104 break;
9107 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9109 len = asc_prt_line(cp, leftlen,
9110 " termination: %u (%s), bios_ctrl: %x\n",
9111 ep_3550->termination, termstr, ep_3550->bios_ctrl);
9112 ASC_PRT_NEXT();
9113 } else
9115 len = asc_prt_line(cp, leftlen,
9116 " termination: %u (%s), bios_ctrl: %x\n",
9117 ep_38C0800->termination_lvd, termstr, ep_38C0800->bios_ctrl);
9118 ASC_PRT_NEXT();
9121 len = asc_prt_line(cp, leftlen,
9122 " Target ID: ");
9123 ASC_PRT_NEXT();
9124 for (i = 0; i <= ADV_MAX_TID; i++) {
9125 len = asc_prt_line(cp, leftlen, " %X", i);
9126 ASC_PRT_NEXT();
9128 len = asc_prt_line(cp, leftlen, "\n");
9129 ASC_PRT_NEXT();
9131 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9133 word = ep_3550->disc_enable;
9134 } else
9136 word = ep_38C0800->disc_enable;
9138 len = asc_prt_line(cp, leftlen,
9139 " Disconnects: ");
9140 ASC_PRT_NEXT();
9141 for (i = 0; i <= ADV_MAX_TID; i++) {
9142 len = asc_prt_line(cp, leftlen, " %c",
9143 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9144 ASC_PRT_NEXT();
9146 len = asc_prt_line(cp, leftlen, "\n");
9147 ASC_PRT_NEXT();
9149 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9151 word = ep_3550->tagqng_able;
9152 } else
9154 word = ep_38C0800->tagqng_able;
9156 len = asc_prt_line(cp, leftlen,
9157 " Command Queuing: ");
9158 ASC_PRT_NEXT();
9159 for (i = 0; i <= ADV_MAX_TID; i++) {
9160 len = asc_prt_line(cp, leftlen, " %c",
9161 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9162 ASC_PRT_NEXT();
9164 len = asc_prt_line(cp, leftlen, "\n");
9165 ASC_PRT_NEXT();
9167 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9169 word = ep_3550->start_motor;
9170 } else
9172 word = ep_38C0800->start_motor;
9174 len = asc_prt_line(cp, leftlen,
9175 " Start Motor: ");
9176 ASC_PRT_NEXT();
9177 for (i = 0; i <= ADV_MAX_TID; i++) {
9178 len = asc_prt_line(cp, leftlen, " %c",
9179 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9180 ASC_PRT_NEXT();
9182 len = asc_prt_line(cp, leftlen, "\n");
9183 ASC_PRT_NEXT();
9185 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9187 len = asc_prt_line(cp, leftlen,
9188 " Synchronous Transfer:");
9189 ASC_PRT_NEXT();
9190 for (i = 0; i <= ADV_MAX_TID; i++) {
9191 len = asc_prt_line(cp, leftlen, " %c",
9192 (ep_3550->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9193 ASC_PRT_NEXT();
9195 len = asc_prt_line(cp, leftlen, "\n");
9196 ASC_PRT_NEXT();
9199 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9201 len = asc_prt_line(cp, leftlen,
9202 " Ultra Transfer: ");
9203 ASC_PRT_NEXT();
9204 for (i = 0; i <= ADV_MAX_TID; i++) {
9205 len = asc_prt_line(cp, leftlen, " %c",
9206 (ep_3550->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9207 ASC_PRT_NEXT();
9209 len = asc_prt_line(cp, leftlen, "\n");
9210 ASC_PRT_NEXT();
9213 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
9215 word = ep_3550->wdtr_able;
9216 } else
9218 word = ep_38C0800->wdtr_able;
9220 len = asc_prt_line(cp, leftlen,
9221 " Wide Transfer: ");
9222 ASC_PRT_NEXT();
9223 for (i = 0; i <= ADV_MAX_TID; i++) {
9224 len = asc_prt_line(cp, leftlen, " %c",
9225 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9226 ASC_PRT_NEXT();
9228 len = asc_prt_line(cp, leftlen, "\n");
9229 ASC_PRT_NEXT();
9231 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
9233 len = asc_prt_line(cp, leftlen,
9234 " Synchronous Transfer Speed (Mhz):\n ");
9235 ASC_PRT_NEXT();
9236 for (i = 0; i <= ADV_MAX_TID; i++) {
9237 char *speed_str;
9239 if (i == 0)
9241 sdtr_speed = adv_dvc_varp->sdtr_speed1;
9242 } else if (i == 4)
9244 sdtr_speed = adv_dvc_varp->sdtr_speed2;
9245 } else if (i == 8)
9247 sdtr_speed = adv_dvc_varp->sdtr_speed3;
9248 } else if (i == 12)
9250 sdtr_speed = adv_dvc_varp->sdtr_speed4;
9252 switch (sdtr_speed & ADV_MAX_TID)
9254 case 0: speed_str = "Off"; break;
9255 case 1: speed_str = " 5"; break;
9256 case 2: speed_str = " 10"; break;
9257 case 3: speed_str = " 20"; break;
9258 case 4: speed_str = " 40"; break;
9259 case 5: speed_str = " 80"; break;
9260 default: speed_str = "Unk"; break;
9262 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
9263 ASC_PRT_NEXT();
9264 if (i == 7)
9266 len = asc_prt_line(cp, leftlen, "\n ");
9267 ASC_PRT_NEXT();
9269 sdtr_speed >>= 4;
9271 len = asc_prt_line(cp, leftlen, "\n");
9272 ASC_PRT_NEXT();
9275 return totlen;
9279 * asc_prt_driver_conf()
9281 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9282 * cf. asc_prt_line().
9284 * Return the number of characters copied into 'cp'. No more than
9285 * 'cplen' characters will be copied to 'cp'.
9287 STATIC int
9288 asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
9290 asc_board_t *boardp;
9291 int leftlen;
9292 int totlen;
9293 int len;
9294 int chip_scsi_id;
9295 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
9296 int i;
9297 #endif /* version >= v1.3.89 */
9299 boardp = ASC_BOARDP(shp);
9301 leftlen = cplen;
9302 totlen = len = 0;
9304 len = asc_prt_line(cp, leftlen,
9305 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
9306 shp->host_no);
9307 ASC_PRT_NEXT();
9309 len = asc_prt_line(cp, leftlen,
9310 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
9311 " host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
9312 shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
9313 #else /* version >= v1.3.89 */
9314 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
9315 shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
9316 shp->max_channel);
9317 #endif /* version >= v1.3.89 */
9318 ASC_PRT_NEXT();
9320 len = asc_prt_line(cp, leftlen,
9321 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
9322 " can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
9323 shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
9324 #else /* version >= v1.3.57 */
9325 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
9326 shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
9327 shp->cmd_per_lun);
9328 #endif /* version >= v1.3.57 */
9329 ASC_PRT_NEXT();
9331 len = asc_prt_line(cp, leftlen,
9332 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
9333 " unchecked_isa_dma %d, loaded_as_module %d\n",
9334 shp->unchecked_isa_dma, shp->loaded_as_module);
9335 #else /* version >= v1.3.57 */
9336 " unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
9337 shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
9338 #endif /* version >= v1.3.57 */
9339 ASC_PRT_NEXT();
9341 len = asc_prt_line(cp, leftlen, " flags %x, last_reset %x, jiffies %x\n",
9342 boardp->flags, boardp->last_reset, jiffies);
9343 ASC_PRT_NEXT();
9345 if (ASC_NARROW_BOARD(boardp)) {
9346 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
9347 } else {
9348 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
9351 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
9352 if (boardp->flags & ASC_SELECT_QUEUE_DEPTHS) {
9353 len = asc_prt_line(cp, leftlen, " queue_depth:");
9354 ASC_PRT_NEXT();
9355 for (i = 0; i <= ADV_MAX_TID; i++) {
9356 if ((chip_scsi_id == i) ||
9357 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9358 continue;
9360 if (boardp->device[i] == NULL) {
9361 continue;
9363 len = asc_prt_line(cp, leftlen, " %X:%d",
9364 i, boardp->device[i]->queue_depth);
9365 ASC_PRT_NEXT();
9367 len = asc_prt_line(cp, leftlen, "\n");
9368 ASC_PRT_NEXT();
9370 #endif /* version >= v1.3.89 */
9372 return totlen;
9376 * asc_prt_asc_board_info()
9378 * Print dynamic board configuration information.
9380 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9381 * cf. asc_prt_line().
9383 * Return the number of characters copied into 'cp'. No more than
9384 * 'cplen' characters will be copied to 'cp'.
9386 STATIC int
9387 asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen)
9389 asc_board_t *boardp;
9390 int chip_scsi_id;
9391 int leftlen;
9392 int totlen;
9393 int len;
9394 ASC_DVC_VAR *v;
9395 ASC_DVC_CFG *c;
9396 int i;
9397 int renegotiate = 0;
9399 boardp = ASC_BOARDP(shp);
9400 v = &boardp->dvc_var.asc_dvc_var;
9401 c = &boardp->dvc_cfg.asc_dvc_cfg;
9402 chip_scsi_id = c->chip_scsi_id;
9404 leftlen = cplen;
9405 totlen = len = 0;
9407 len = asc_prt_line(cp, leftlen,
9408 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
9409 shp->host_no);
9410 ASC_PRT_NEXT();
9412 len = asc_prt_line(cp, leftlen,
9413 " chip_version %u, lib_version %x, lib_serial_no %u, mcode_date %x\n",
9414 c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date);
9415 ASC_PRT_NEXT();
9417 len = asc_prt_line(cp, leftlen,
9418 " mcode_version %x, err_code %u\n",
9419 c->mcode_version, v->err_code);
9420 ASC_PRT_NEXT();
9422 /* Current number of commands waiting for the host. */
9423 len = asc_prt_line(cp, leftlen,
9424 " Total Command Pending: %d\n", v->cur_total_qng);
9425 ASC_PRT_NEXT();
9427 len = asc_prt_line(cp, leftlen,
9428 " Command Queuing:");
9429 ASC_PRT_NEXT();
9430 for (i = 0; i <= ASC_MAX_TID; i++) {
9431 if ((chip_scsi_id == i) ||
9432 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9433 continue;
9435 len = asc_prt_line(cp, leftlen, " %X:%c",
9436 i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9437 ASC_PRT_NEXT();
9439 len = asc_prt_line(cp, leftlen, "\n");
9440 ASC_PRT_NEXT();
9442 /* Current number of commands waiting for a device. */
9443 len = asc_prt_line(cp, leftlen,
9444 " Command Queue Pending:");
9445 ASC_PRT_NEXT();
9446 for (i = 0; i <= ASC_MAX_TID; i++) {
9447 if ((chip_scsi_id == i) ||
9448 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9449 continue;
9451 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
9452 ASC_PRT_NEXT();
9454 len = asc_prt_line(cp, leftlen, "\n");
9455 ASC_PRT_NEXT();
9457 /* Current limit on number of commands that can be sent to a device. */
9458 len = asc_prt_line(cp, leftlen,
9459 " Command Queue Limit:");
9460 ASC_PRT_NEXT();
9461 for (i = 0; i <= ASC_MAX_TID; i++) {
9462 if ((chip_scsi_id == i) ||
9463 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9464 continue;
9466 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
9467 ASC_PRT_NEXT();
9469 len = asc_prt_line(cp, leftlen, "\n");
9470 ASC_PRT_NEXT();
9472 /* Indicate whether the device has returned queue full status. */
9473 len = asc_prt_line(cp, leftlen,
9474 " Command Queue Full:");
9475 ASC_PRT_NEXT();
9476 for (i = 0; i <= ASC_MAX_TID; i++) {
9477 if ((chip_scsi_id == i) ||
9478 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9479 continue;
9481 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
9482 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
9483 i, boardp->queue_full_cnt[i]);
9484 } else {
9485 len = asc_prt_line(cp, leftlen, " %X:N", i);
9487 ASC_PRT_NEXT();
9489 len = asc_prt_line(cp, leftlen, "\n");
9490 ASC_PRT_NEXT();
9492 len = asc_prt_line(cp, leftlen,
9493 " Synchronous Transfer:");
9494 ASC_PRT_NEXT();
9495 for (i = 0; i <= ASC_MAX_TID; i++) {
9496 if ((chip_scsi_id == i) ||
9497 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9498 continue;
9500 len = asc_prt_line(cp, leftlen, " %X:%c",
9501 i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9502 ASC_PRT_NEXT();
9504 len = asc_prt_line(cp, leftlen, "\n");
9505 ASC_PRT_NEXT();
9507 for (i = 0; i <= ASC_MAX_TID; i++) {
9508 uchar syn_period_ix;
9510 if ((chip_scsi_id == i) ||
9511 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
9512 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
9513 continue;
9516 len = asc_prt_line(cp, leftlen, " %X:", i);
9517 ASC_PRT_NEXT();
9519 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0)
9521 len = asc_prt_line(cp, leftlen, " Asynchronous");
9522 ASC_PRT_NEXT();
9523 } else
9525 syn_period_ix =
9526 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1);
9528 len = asc_prt_line(cp, leftlen,
9529 " Transfer Period Factor: %d (%d.%d Mhz),",
9530 v->sdtr_period_tbl[syn_period_ix],
9531 250 / v->sdtr_period_tbl[syn_period_ix],
9532 ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix]));
9533 ASC_PRT_NEXT();
9535 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
9536 boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
9537 ASC_PRT_NEXT();
9540 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
9541 len = asc_prt_line(cp, leftlen, "*\n");
9542 renegotiate = 1;
9543 } else
9545 len = asc_prt_line(cp, leftlen, "\n");
9547 ASC_PRT_NEXT();
9550 if (renegotiate)
9552 len = asc_prt_line(cp, leftlen,
9553 " * = Re-negotiation pending before next command.\n");
9554 ASC_PRT_NEXT();
9557 return totlen;
9561 * asc_prt_adv_board_info()
9563 * Print dynamic board configuration information.
9565 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9566 * cf. asc_prt_line().
9568 * Return the number of characters copied into 'cp'. No more than
9569 * 'cplen' characters will be copied to 'cp'.
9571 STATIC int
9572 asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen)
9574 asc_board_t *boardp;
9575 int leftlen;
9576 int totlen;
9577 int len;
9578 int i;
9579 ADV_DVC_VAR *v;
9580 ADV_DVC_CFG *c;
9581 AdvPortAddr iop_base;
9582 ushort chip_scsi_id;
9583 ushort lramword;
9584 uchar lrambyte;
9585 ushort tagqng_able;
9586 ushort sdtr_able, wdtr_able;
9587 ushort wdtr_done, sdtr_done;
9588 ushort period = 0;
9589 int renegotiate = 0;
9591 boardp = ASC_BOARDP(shp);
9592 v = &boardp->dvc_var.adv_dvc_var;
9593 c = &boardp->dvc_cfg.adv_dvc_cfg;
9594 iop_base = v->iop_base;
9595 chip_scsi_id = v->chip_scsi_id;
9597 leftlen = cplen;
9598 totlen = len = 0;
9600 len = asc_prt_line(cp, leftlen,
9601 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
9602 shp->host_no);
9603 ASC_PRT_NEXT();
9605 len = asc_prt_line(cp, leftlen,
9606 " iop_base %lx, cable_detect: %X, err_code %u\n",
9607 v->iop_base,
9608 AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT,
9609 v->err_code);
9610 ASC_PRT_NEXT();
9612 len = asc_prt_line(cp, leftlen,
9613 " chip_version %u, lib_version %x, mcode_date %x, mcode_version %x\n",
9614 c->chip_version, c->lib_version, c->mcode_date, c->mcode_version);
9615 ASC_PRT_NEXT();
9617 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
9618 len = asc_prt_line(cp, leftlen,
9619 " Queuing Enabled:");
9620 ASC_PRT_NEXT();
9621 for (i = 0; i <= ADV_MAX_TID; i++) {
9622 if ((chip_scsi_id == i) ||
9623 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9624 continue;
9627 len = asc_prt_line(cp, leftlen, " %X:%c",
9628 i, (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9629 ASC_PRT_NEXT();
9631 len = asc_prt_line(cp, leftlen, "\n");
9632 ASC_PRT_NEXT();
9634 len = asc_prt_line(cp, leftlen,
9635 " Queue Limit:");
9636 ASC_PRT_NEXT();
9637 for (i = 0; i <= ADV_MAX_TID; i++) {
9638 if ((chip_scsi_id == i) ||
9639 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9640 continue;
9643 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte);
9645 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9646 ASC_PRT_NEXT();
9648 len = asc_prt_line(cp, leftlen, "\n");
9649 ASC_PRT_NEXT();
9651 len = asc_prt_line(cp, leftlen,
9652 " Command Pending:");
9653 ASC_PRT_NEXT();
9654 for (i = 0; i <= ADV_MAX_TID; i++) {
9655 if ((chip_scsi_id == i) ||
9656 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9657 continue;
9660 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte);
9662 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9663 ASC_PRT_NEXT();
9665 len = asc_prt_line(cp, leftlen, "\n");
9666 ASC_PRT_NEXT();
9668 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
9669 len = asc_prt_line(cp, leftlen,
9670 " Wide Enabled:");
9671 ASC_PRT_NEXT();
9672 for (i = 0; i <= ADV_MAX_TID; i++) {
9673 if ((chip_scsi_id == i) ||
9674 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9675 continue;
9678 len = asc_prt_line(cp, leftlen, " %X:%c",
9679 i, (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9680 ASC_PRT_NEXT();
9682 len = asc_prt_line(cp, leftlen, "\n");
9683 ASC_PRT_NEXT();
9685 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
9686 len = asc_prt_line(cp, leftlen,
9687 " Transfer Bit Width:");
9688 ASC_PRT_NEXT();
9689 for (i = 0; i <= ADV_MAX_TID; i++) {
9690 if ((chip_scsi_id == i) ||
9691 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9692 continue;
9695 AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9696 lramword);
9698 len = asc_prt_line(cp, leftlen, " %X:%d",
9699 i, (lramword & 0x8000) ? 16 : 8);
9700 ASC_PRT_NEXT();
9702 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
9703 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
9704 len = asc_prt_line(cp, leftlen, "*");
9705 ASC_PRT_NEXT();
9706 renegotiate = 1;
9709 len = asc_prt_line(cp, leftlen, "\n");
9710 ASC_PRT_NEXT();
9712 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
9713 len = asc_prt_line(cp, leftlen,
9714 " Synchronous Enabled:");
9715 ASC_PRT_NEXT();
9716 for (i = 0; i <= ADV_MAX_TID; i++) {
9717 if ((chip_scsi_id == i) ||
9718 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9719 continue;
9722 len = asc_prt_line(cp, leftlen, " %X:%c",
9723 i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9724 ASC_PRT_NEXT();
9726 len = asc_prt_line(cp, leftlen, "\n");
9727 ASC_PRT_NEXT();
9729 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
9730 for (i = 0; i <= ADV_MAX_TID; i++) {
9732 AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9733 lramword);
9734 lramword &= ~0x8000;
9736 if ((chip_scsi_id == i) ||
9737 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
9738 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
9739 continue;
9742 len = asc_prt_line(cp, leftlen, " %X:", i);
9743 ASC_PRT_NEXT();
9745 if ((lramword & 0x1F) == 0) /* Check for REQ/ACK Offset 0. */
9747 len = asc_prt_line(cp, leftlen, " Asynchronous");
9748 ASC_PRT_NEXT();
9749 } else
9751 len = asc_prt_line(cp, leftlen, " Transfer Period Factor: ");
9752 ASC_PRT_NEXT();
9754 if ((lramword & 0x1F00) == 0x1100) /* 80 Mhz */
9756 len = asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
9757 ASC_PRT_NEXT();
9758 } else if ((lramword & 0x1F00) == 0x1000) /* 40 Mhz */
9760 len = asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
9761 ASC_PRT_NEXT();
9762 } else /* 20 Mhz or below. */
9764 period = (((lramword >> 8) * 25) + 50)/4;
9766 if (period == 0) /* Should never happen. */
9768 len = asc_prt_line(cp, leftlen, "%d (? Mhz), ");
9769 ASC_PRT_NEXT();
9770 } else
9772 len = asc_prt_line(cp, leftlen,
9773 "%d (%d.%d Mhz),",
9774 period, 250/period, ASC_TENTHS(250, period));
9775 ASC_PRT_NEXT();
9779 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
9780 lramword & 0x1F);
9781 ASC_PRT_NEXT();
9784 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
9785 len = asc_prt_line(cp, leftlen, "*\n");
9786 renegotiate = 1;
9787 } else
9789 len = asc_prt_line(cp, leftlen, "\n");
9791 ASC_PRT_NEXT();
9794 if (renegotiate)
9796 len = asc_prt_line(cp, leftlen,
9797 " * = Re-negotiation pending before next command.\n");
9798 ASC_PRT_NEXT();
9801 return totlen;
9805 * asc_proc_copy()
9807 * Copy proc information to a read buffer taking into account the current
9808 * read offset in the file and the remaining space in the read buffer.
9810 STATIC int
9811 asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
9812 char *cp, int cplen)
9814 int cnt = 0;
9816 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
9817 (unsigned) offset, (unsigned) advoffset, cplen);
9818 if (offset <= advoffset) {
9819 /* Read offset below current offset, copy everything. */
9820 cnt = ASC_MIN(cplen, leftlen);
9821 ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9822 (unsigned) curbuf, (unsigned) cp, cnt);
9823 memcpy(curbuf, cp, cnt);
9824 } else if (offset < advoffset + cplen) {
9825 /* Read offset within current range, partial copy. */
9826 cnt = (advoffset + cplen) - offset;
9827 cp = (cp + cplen) - cnt;
9828 cnt = ASC_MIN(cnt, leftlen);
9829 ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9830 (unsigned) curbuf, (unsigned) cp, cnt);
9831 memcpy(curbuf, cp, cnt);
9833 return cnt;
9837 * asc_prt_line()
9839 * If 'cp' is NULL print to the console, otherwise print to a buffer.
9841 * Return 0 if printing to the console, otherwise return the number of
9842 * bytes written to the buffer.
9844 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
9845 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
9847 STATIC int
9848 asc_prt_line(char *buf, int buflen, char *fmt, ...)
9850 va_list args;
9851 int ret;
9852 char s[ASC_PRTLINE_SIZE];
9854 va_start(args, fmt);
9855 ret = vsprintf(s, fmt, args);
9856 ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
9857 if (buf == NULL) {
9858 (void) printk(s);
9859 ret = 0;
9860 } else {
9861 ret = ASC_MIN(buflen, ret);
9862 memcpy(buf, s, ret);
9864 va_end(args);
9865 return ret;
9867 #endif /* version >= v1.3.0 */
9871 * --- Functions Required by the Asc Library
9875 * Delay for 'n' milliseconds. Don't use the 'jiffies'
9876 * global variable which is incremented once every 5 ms
9877 * from a timer interrupt, because this function may be
9878 * called when interrupts are disabled.
9880 STATIC void
9881 DvcSleepMilliSecond(ulong n)
9883 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
9884 ulong i;
9885 #endif /* version < v2.1.0 */
9887 ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
9888 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
9889 mdelay(n);
9890 #else /* version < v2.1.0 */
9891 for (i = 0; i < n; i++) {
9892 udelay(1000);
9894 #endif /* version < v2.1.0 */
9897 STATIC int
9898 DvcEnterCritical(void)
9900 int flags;
9902 save_flags(flags);
9903 cli();
9904 return flags;
9907 STATIC void
9908 DvcLeaveCritical(int flags)
9910 restore_flags(flags);
9913 STATIC ulong
9914 DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
9915 ASC_SG_HEAD *asc_sg_head_ptr)
9917 ulong buf_size;
9919 buf_size = buf_len;
9920 asc_sg_head_ptr->entry_cnt = 1;
9921 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9922 asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
9923 #else /* version >= v2.0.0 */
9924 asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
9925 #endif /* version >= v2.0.0 */
9926 asc_sg_head_ptr->sg_list[0].bytes = buf_size;
9927 return buf_size;
9931 * void
9932 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9934 * Calling/Exit State:
9935 * none
9937 * Description:
9938 * Output an ASC_SCSI_Q structure to the chip
9940 STATIC void
9941 DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9943 int i;
9945 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
9946 AscSetChipLramAddr(iop_base, s_addr);
9947 for (i = 0; i < words; i++, outbuf++) {
9948 if (i == 2 || i == 10) {
9949 continue;
9951 AscSetChipLramDataNoSwap(iop_base, *outbuf);
9956 * void
9957 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9959 * Calling/Exit State:
9960 * none
9962 * Description:
9963 * Input an ASC_QDONE_INFO structure from the chip
9965 STATIC void
9966 DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9968 int i;
9970 AscSetChipLramAddr(iop_base, s_addr);
9971 for (i = 0; i < words; i++, inbuf++) {
9972 if (i == 5) {
9973 continue;
9975 *inbuf = AscGetChipLramDataNoSwap(iop_base);
9977 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
9981 * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
9983 * Calling/Exit State:
9984 * none
9986 * Description:
9987 * output a buffer to an i/o port address
9989 STATIC void
9990 DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
9992 int i;
9994 for (i = 0; i < words; i++, outbuf++)
9995 outpw(iop_base, *outbuf);
9999 * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
10001 * Calling/Exit State:
10002 * none
10004 * Description:
10005 * input a buffer from an i/o port address
10007 STATIC void
10008 DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
10010 int i;
10012 for (i = 0; i < words; i++, inbuf++)
10013 *inbuf = inpw(iop_base);
10017 * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
10019 * Calling/Exit State:
10020 * none
10022 * Description:
10023 * output a buffer of 32-bit integers to an i/o port address in
10024 * 16 bit integer units
10026 STATIC void
10027 DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
10029 int i;
10030 int words;
10031 ushort *pw;
10033 pw = (ushort *) pdw;
10034 words = dwords << 1;
10035 for(i = 0; i < words; i++, pw++) {
10036 outpw(port, *pw);
10038 return;
10042 * Read a PCI configuration byte.
10044 ASC_INITFUNC(
10045 STATIC uchar,
10046 DvcReadPCIConfigByte(
10047 ASC_DVC_VAR asc_ptr_type *asc_dvc,
10048 ushort offset)
10051 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
10052 #ifdef ASC_CONFIG_PCI
10053 PCI_DATA pciData;
10055 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
10056 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
10057 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
10058 pciData.offset = offset;
10059 pciData.type = pci_scan_method;
10060 return asc_get_cfg_byte(&pciData);
10061 #else /* ASC_CONFIG_PCI */
10062 return 0;
10063 #endif /* ASC_CONFIG_PCI */
10064 #else /* version >= v2.1.93 */
10065 #ifdef CONFIG_PCI
10066 uchar byte_data;
10067 pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
10068 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
10069 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
10070 offset, &byte_data);
10071 return byte_data;
10072 #else /* CONFIG_PCI */
10073 return 0;
10074 #endif /* CONFIG_PCI */
10075 #endif /* version >= v2.1.93 */
10079 * Write a PCI configuration byte.
10081 ASC_INITFUNC(
10082 STATIC void,
10083 DvcWritePCIConfigByte(
10084 ASC_DVC_VAR asc_ptr_type *asc_dvc,
10085 ushort offset,
10086 uchar byte_data)
10089 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
10090 #ifdef ASC_CONFIG_PCI
10091 PCI_DATA pciData;
10093 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
10094 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
10095 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
10096 pciData.offset = offset;
10097 pciData.type = pci_scan_method;
10098 asc_put_cfg_byte(&pciData, byte_data);
10099 #endif /* ASC_CONFIG_PCI */
10100 #else /* version >= v2.1.93 */
10101 #ifdef CONFIG_PCI
10102 pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
10103 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
10104 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
10105 offset, byte_data);
10106 #endif /* CONFIG_PCI */
10107 #endif /* version >= v2.1.93 */
10111 * Return the BIOS address of the adapter at the specified
10112 * I/O port and with the specified bus type.
10114 ASC_INITFUNC(
10115 STATIC ushort,
10116 AscGetChipBiosAddress(
10117 PortAddr iop_base,
10118 ushort bus_type
10122 ushort cfg_lsw;
10123 ushort bios_addr;
10126 * The PCI BIOS is re-located by the motherboard BIOS. Because
10127 * of this the driver can not determine where a PCI BIOS is
10128 * loaded and executes.
10130 if (bus_type & ASC_IS_PCI)
10132 return(0);
10135 if((bus_type & ASC_IS_EISA) != 0)
10137 cfg_lsw = AscGetEisaChipCfg(iop_base);
10138 cfg_lsw &= 0x000F;
10139 bios_addr = (ushort)(ASC_BIOS_MIN_ADDR +
10140 (cfg_lsw * ASC_BIOS_BANK_SIZE));
10141 return(bios_addr);
10142 }/* if */
10144 cfg_lsw = AscGetChipCfgLsw(iop_base);
10147 * ISA PnP uses the top bit as the 32K BIOS flag
10149 if (bus_type == ASC_IS_ISAPNP)
10151 cfg_lsw &= 0x7FFF;
10152 }/* if */
10154 bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
10155 ASC_BIOS_MIN_ADDR);
10156 return(bios_addr);
10161 * --- Functions Required by the Adv Library
10165 * DvcGetPhyAddr()
10167 * Return the physical address of 'vaddr' and set '*lenp' to the
10168 * number of physically contiguous bytes that follow 'vaddr'.
10169 * 'flag' indicates the type of structure whose physical address
10170 * is being translated.
10172 * Note: Because Linux currently doesn't page the kernel and all
10173 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
10175 ulong
10176 DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
10177 uchar *vaddr, long *lenp, int flag)
10179 ulong paddr;
10181 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
10182 paddr = (ulong) vaddr;
10183 #else /* version >= v2.0.0 */
10184 paddr = virt_to_bus(vaddr);
10185 #endif /* version >= v2.0.0 */
10187 ASC_DBG4(4,
10188 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
10189 (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), paddr);
10191 return paddr;
10195 * Read a PCI configuration byte.
10197 ASC_INITFUNC(
10198 STATIC uchar,
10199 DvcAdvReadPCIConfigByte(
10200 ADV_DVC_VAR *asc_dvc,
10201 ushort offset)
10204 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
10205 #ifdef ASC_CONFIG_PCI
10206 PCI_DATA pciData;
10208 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
10209 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
10210 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
10211 pciData.offset = offset;
10212 pciData.type = pci_scan_method;
10213 return asc_get_cfg_byte(&pciData);
10214 #else /* ASC_CONFIG_PCI */
10215 return 0;
10216 #endif /* ASC_CONFIG_PCI */
10217 #else /* version >= v2.1.93 */
10218 #ifdef CONFIG_PCI
10219 uchar byte_data;
10220 pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
10221 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
10222 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
10223 offset, &byte_data);
10224 return byte_data;
10225 #else /* CONFIG_PCI */
10226 return 0;
10227 #endif /* CONFIG_PCI */
10228 #endif /* version >= v2.1.93 */
10232 * Write a PCI configuration byte.
10234 ASC_INITFUNC(
10235 STATIC void,
10236 DvcAdvWritePCIConfigByte(
10237 ADV_DVC_VAR *asc_dvc,
10238 ushort offset,
10239 uchar byte_data)
10242 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
10243 #ifdef ASC_CONFIG_PCI
10244 PCI_DATA pciData;
10246 pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
10247 pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
10248 pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
10249 pciData.offset = offset;
10250 pciData.type = pci_scan_method;
10251 asc_put_cfg_byte(&pciData, byte_data);
10252 #endif /* ASC_CONFIG_PCI */
10253 #else /* version >= v2.1.93 */
10254 #ifdef CONFIG_PCI
10255 pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
10256 PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
10257 ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
10258 offset, byte_data);
10259 #endif /* CONFIG_PCI */
10260 #endif /* version >= v2.1.93 */
10264 * --- Tracing and Debugging Functions
10267 #ifdef ADVANSYS_STATS
10269 * asc_prt_board_stats()
10271 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
10272 * cf. asc_prt_line().
10274 * Return the number of characters copied into 'cp'. No more than
10275 * 'cplen' characters will be copied to 'cp'.
10277 STATIC int
10278 asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
10280 int leftlen;
10281 int totlen;
10282 int len;
10283 struct asc_stats *s;
10284 int i;
10285 ushort chip_scsi_id;
10286 asc_board_t *boardp;
10287 asc_queue_t *active;
10288 asc_queue_t *waiting;
10290 leftlen = cplen;
10291 totlen = len = 0;
10293 boardp = ASC_BOARDP(shp);
10294 s = &boardp->asc_stats;
10296 len = asc_prt_line(cp, leftlen,
10297 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no);
10298 ASC_PRT_NEXT();
10300 len = asc_prt_line(cp, leftlen,
10301 " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n",
10302 s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
10303 ASC_PRT_NEXT();
10305 len = asc_prt_line(cp, leftlen,
10306 " interrupt %lu, callback %lu, done %lu\n",
10307 s->interrupt, s->callback, s->done);
10308 ASC_PRT_NEXT();
10310 len = asc_prt_line(cp, leftlen,
10311 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
10312 s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown);
10313 ASC_PRT_NEXT();
10315 if (ASC_NARROW_BOARD(boardp)) {
10316 len = asc_prt_line(cp, leftlen,
10317 " build_error %lu\n",
10318 s->build_error);
10319 } else {
10320 len = asc_prt_line(cp, leftlen,
10321 " build_error %lu, build_noreq %lu, build_nosg %lu\n",
10322 s->build_error, s->adv_build_noreq, s->adv_build_nosg);
10324 ASC_PRT_NEXT();
10327 * Display data transfer statistics.
10329 if (s->cont_cnt > 0) {
10330 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
10331 ASC_PRT_NEXT();
10333 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
10334 s->cont_xfer/2,
10335 ASC_TENTHS(s->cont_xfer, 2));
10336 ASC_PRT_NEXT();
10338 /* Contiguous transfer average size */
10339 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
10340 (s->cont_xfer/2)/s->cont_cnt,
10341 ASC_TENTHS((s->cont_xfer/2), s->cont_cnt));
10342 ASC_PRT_NEXT();
10345 if (s->sg_cnt > 0) {
10347 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
10348 s->sg_cnt, s->sg_elem);
10349 ASC_PRT_NEXT();
10351 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
10352 s->sg_xfer/2,
10353 ASC_TENTHS(s->sg_xfer, 2));
10354 ASC_PRT_NEXT();
10356 /* Scatter gather transfer statistics */
10357 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
10358 s->sg_elem/s->sg_cnt,
10359 ASC_TENTHS(s->sg_elem, s->sg_cnt));
10360 ASC_PRT_NEXT();
10362 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
10363 (s->sg_xfer/2)/s->sg_elem,
10364 ASC_TENTHS((s->sg_xfer/2), s->sg_elem));
10365 ASC_PRT_NEXT();
10367 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
10368 (s->sg_xfer/2)/s->sg_cnt,
10369 ASC_TENTHS((s->sg_xfer/2), s->sg_cnt));
10370 ASC_PRT_NEXT();
10374 * Display request queuing statistics.
10376 len = asc_prt_line(cp, leftlen,
10377 " Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ);
10378 ASC_PRT_NEXT();
10380 active = &ASC_BOARDP(shp)->active;
10381 waiting = &ASC_BOARDP(shp)->waiting;
10383 if (ASC_NARROW_BOARD(boardp)) {
10384 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
10385 } else {
10386 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
10389 for (i = 0; i <= ADV_MAX_TID; i++) {
10391 if ((chip_scsi_id == i) ||
10392 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
10393 continue;
10396 if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
10397 len = asc_prt_line(cp, leftlen, " target %d\n", i);
10398 ASC_PRT_NEXT();
10400 len = asc_prt_line(cp, leftlen,
10401 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
10402 active->q_cur_cnt[i], active->q_max_cnt[i],
10403 active->q_tot_cnt[i],
10404 active->q_min_tim[i], active->q_max_tim[i],
10405 (active->q_tot_cnt[i] == 0) ? 0 :
10406 (active->q_tot_tim[i]/active->q_tot_cnt[i]),
10407 (active->q_tot_cnt[i] == 0) ? 0 :
10408 ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
10409 ASC_PRT_NEXT();
10411 len = asc_prt_line(cp, leftlen,
10412 " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
10413 waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
10414 waiting->q_tot_cnt[i],
10415 waiting->q_min_tim[i], waiting->q_max_tim[i],
10416 (waiting->q_tot_cnt[i] == 0) ? 0 :
10417 (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
10418 (waiting->q_tot_cnt[i] == 0) ? 0 :
10419 ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
10420 ASC_PRT_NEXT();
10424 return totlen;
10426 #endif /* ADVANSYS_STATS */
10428 #ifdef ADVANSYS_DEBUG
10430 * asc_prt_scsi_host()
10432 STATIC void
10433 asc_prt_scsi_host(struct Scsi_Host *s)
10435 asc_board_t *boardp;
10437 boardp = ASC_BOARDP(s);
10439 printk("Scsi_Host at addr %x\n", (unsigned) s);
10440 printk(
10441 " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
10442 (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
10443 (unsigned) s->last_reset);
10445 printk(
10446 " host_queue %x, hostt %x, block %x,\n",
10447 (unsigned) s->host_queue, (unsigned) s->hostt, (unsigned) s->block);
10449 printk(
10450 " wish_block %d, base %lu, io_port %lu, n_io_port %u, irq %d,\n",
10451 s->wish_block, (ulong) s->base, (ulong) s->io_port, s->n_io_port,
10452 s->irq);
10454 printk(
10455 " dma_channel %d, this_id %d, can_queue %d,\n",
10456 s->dma_channel, s->this_id, s->can_queue);
10458 printk(
10459 " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
10460 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
10461 s->loaded_as_module);
10463 if (ASC_NARROW_BOARD(boardp)) {
10464 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
10465 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
10466 } else {
10467 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
10468 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
10473 * asc_prt_scsi_cmnd()
10475 STATIC void
10476 asc_prt_scsi_cmnd(Scsi_Cmnd *s)
10478 printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
10480 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
10481 printk(
10482 " host %x, device %x, target %u, lun %u\n",
10483 (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
10484 #else /* version >= v1.3.0 */
10485 printk(
10486 " host %x, device %x, target %u, lun %u, channel %u,\n",
10487 (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
10488 s->channel);
10489 #endif /* version >= v1.3.0 */
10491 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
10493 printk(
10494 " use_sg %u, sglist_len %u, abort_reason %x\n",
10495 s->use_sg, s->sglist_len, s->abort_reason);
10497 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
10498 printk(
10499 " retries %d, allowed %d\n",
10500 s->retries, s->allowed);
10501 #else /* version >= v1.3.89 */
10502 printk(
10503 " serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
10504 (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
10505 s->retries, s->allowed);
10506 #endif /* version >= v1.3.89 */
10508 printk(
10509 " timeout_per_command %d, timeout_total %d, timeout %d\n",
10510 s->timeout_per_command, s->timeout_total, s->timeout);
10512 printk(
10513 " internal_timeout %u, flags %u, this_count %d\n",
10514 s->internal_timeout, s->flags, s->this_count);
10516 printk(
10517 " scsi_done %x, done %x, host_scribble %x, result %x\n",
10518 (unsigned) s->scsi_done, (unsigned) s->done,
10519 (unsigned) s->host_scribble, s->result);
10521 printk(
10522 " tag %u, pid %u\n",
10523 (unsigned) s->tag, (unsigned) s->pid);
10527 * asc_prt_asc_dvc_var()
10529 STATIC void
10530 asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
10532 printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
10534 printk(
10535 " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
10536 h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
10538 printk(
10539 " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
10540 h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
10541 (unsigned) h->init_sdtr);
10543 printk(
10544 " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
10545 (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
10546 (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
10548 printk(
10549 " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
10550 (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
10551 (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
10553 printk(
10554 " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
10555 (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
10556 (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
10558 printk(
10559 " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
10560 (unsigned) h->last_q_shortage, (unsigned) h->init_state,
10561 (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
10563 printk(
10564 " cfg %x, saved_ptr2func %x\n",
10565 (unsigned) h->cfg, (unsigned) h->saved_ptr2func);
10569 * asc_prt_asc_dvc_cfg()
10571 STATIC void
10572 asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
10574 printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
10576 printk(
10577 " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n",
10578 h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable,
10579 h->sdtr_enable);
10581 printk(
10582 " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
10583 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
10584 h->chip_version);
10586 printk(
10587 " pci_device_id %d, lib_serial_no %x, lib_version %x, mcode_date %x,\n",
10588 h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
10590 printk(
10591 " mcode_version %d, overrun_buf %x\n",
10592 h->mcode_version, (unsigned) h->overrun_buf);
10596 * asc_prt_asc_scsi_q()
10598 STATIC void
10599 asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
10601 ASC_SG_HEAD *sgp;
10602 int i;
10604 printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
10606 printk(
10607 " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
10608 q->q2.target_ix, q->q1.target_lun,
10609 (unsigned) q->q2.srb_ptr, q->q2.tag_code);
10611 printk(
10612 " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
10613 (unsigned) q->q1.data_addr, q->q1.data_cnt,
10614 (unsigned) q->q1.sense_addr, q->q1.sense_len);
10616 printk(
10617 " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
10618 (unsigned) q->cdbptr, q->q2.cdb_len,
10619 (unsigned) q->sg_head, q->q1.sg_queue_cnt);
10621 if (q->sg_head) {
10622 sgp = q->sg_head;
10623 printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
10624 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
10625 for (i = 0; i < sgp->entry_cnt; i++) {
10626 printk(" [%u]: addr %x, bytes %lu\n",
10627 i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
10634 * asc_prt_asc_qdone_info()
10636 STATIC void
10637 asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
10639 printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
10640 printk(
10641 " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
10642 (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
10643 q->d2.tag_code, q->d3.done_stat);
10644 printk(
10645 " host_stat %x, scsi_stat %x, scsi_msg %x\n",
10646 q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
10650 * asc_prt_adv_dvc_var()
10652 * Display an ADV_DVC_VAR structure.
10654 STATIC void
10655 asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
10657 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h);
10659 printk(
10660 " iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
10661 (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able);
10663 printk(
10664 " isr_callback 0x%x, sdtr_able 0x%x, wdtr_able 0x%x\n",
10665 (unsigned) h->isr_callback, (unsigned) h->wdtr_able,
10666 (unsigned) h->sdtr_able);
10668 printk(
10669 " start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
10670 (unsigned) h->start_motor,
10671 (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
10673 printk(
10674 " max_host_qng %x, max_dvc_qng %x, carr_freelist %lxn\n",
10675 (unsigned) h->max_host_qng, (unsigned) h->max_dvc_qng,
10676 (ulong) h->carr_freelist);
10679 printk(
10680 " icq_sp %lx, irq_sp %lx\n",
10681 (ulong) h->icq_sp,
10682 (ulong) h->irq_sp);
10684 printk(
10685 " no_scam 0x%x, tagqng_able 0x%x\n",
10686 (unsigned) h->no_scam, (unsigned) h->tagqng_able);
10688 printk(
10689 " chip_scsi_id 0x%x, cfg %lx\n",
10690 (unsigned) h->chip_scsi_id, (ulong) h->cfg);
10694 * asc_prt_adv_dvc_cfg()
10696 * Display an ADV_DVC_CFG structure.
10698 STATIC void
10699 asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
10701 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h);
10703 printk(
10704 " disc_enable 0x%x, termination 0x%x\n",
10705 h->disc_enable, h->termination);
10707 printk(
10708 " chip_version 0x%x, mcode_date 0x%x\n",
10709 h->chip_version, h->mcode_date);
10711 printk(
10712 " mcode_version 0x%x, pci_device_id 0x%x, lib_version 0x%x\n",
10713 h->mcode_version, h->pci_device_id, h->lib_version);
10715 printk(
10716 " control_flag 0x%x, pci_slot_info 0x%x\n",
10717 h->control_flag, h->pci_slot_info);
10721 * asc_prt_adv_scsi_req_q()
10723 * Display an ADV_SCSI_REQ_Q structure.
10725 STATIC void
10726 asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
10728 int sg_blk_cnt;
10729 struct asc_sg_block *sg_ptr;
10731 printk("ADV_SCSI_REQ_Q at addr %x\n", (unsigned) q);
10733 printk(
10734 " target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
10735 q->target_id, q->target_lun, q->srb_ptr, q->a_flag);
10737 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
10738 q->cntl, q->data_addr, q->vdata_addr);
10740 printk(
10741 " cntl 0x%x, data_addr %lx, vdata_addr %lx\n",
10742 q->cntl, q->data_addr, q->vdata_addr);
10744 printk(
10745 " data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
10746 q->data_cnt, q->sense_addr, q->sense_len);
10748 printk(
10749 " cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
10750 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
10752 printk(
10753 " sg_working_ix %x, sg_working_data_cnt %lx, reserved %u\n",
10754 q->sg_working_ix, q->sg_working_data_cnt, q->reserved);
10756 printk(
10757 " scsiq_rptr %lx, sg_real_addr %lx, sg_list_ptr %lx\n",
10758 q->scsiq_rptr, q->sg_real_addr, (ulong) q->sg_list_ptr);
10760 /* Display the request's ADV_SG_BLOCK structures. */
10761 if (q->sg_list_ptr != NULL)
10763 sg_blk_cnt = 0;
10764 while (1) {
10766 * 'sg_ptr' is a physical address. Convert it to a virtual
10767 * address by indexing 'sg_blk_cnt' into the virtual address
10768 * array 'sg_list_ptr'.
10770 * XXX - Assumes all SG physical blocks are virtually contiguous.
10772 sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[sg_blk_cnt]);
10773 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
10774 if (sg_ptr->sg_ptr == NULL)
10776 break;
10778 sg_blk_cnt++;
10784 * asc_prt_adv_sgblock()
10786 * Display an ADV_SG_BLOCK structure.
10788 STATIC void
10789 asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
10791 int i;
10793 printk(" ASC_SG_BLOCK at addr %lx (sgblockno %d)\n",
10794 (ulong) b, sgblockno);
10795 printk(" sg_cnt %u, sg_ptr %lx\n",
10796 b->sg_cnt, (ulong) b->sg_ptr);
10797 ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
10798 if (b->sg_ptr != NULL)
10800 ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
10802 for (i = 0; i < b->sg_cnt; i++) {
10803 printk(" [%u]: sg_addr %lx, sg_count %lx\n",
10804 i, b->sg_list[i].sg_addr, b->sg_list[i].sg_count);
10809 * asc_prt_hex()
10811 * Print hexadecimal output in 4 byte groupings 32 bytes
10812 * or 8 double-words per line.
10814 STATIC void
10815 asc_prt_hex(char *f, uchar *s, int l)
10817 int i;
10818 int j;
10819 int k;
10820 int m;
10822 printk("%s: (%d bytes)\n", f, l);
10824 for (i = 0; i < l; i += 32) {
10826 /* Display a maximum of 8 double-words per line. */
10827 if ((k = (l - i) / 4) >= 8) {
10828 k = 8;
10829 m = 0;
10830 } else {
10831 m = (l - i) % 4;
10834 for (j = 0; j < k; j++) {
10835 printk(" %2.2X%2.2X%2.2X%2.2X",
10836 (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
10837 (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
10840 switch (m) {
10841 case 0:
10842 default:
10843 break;
10844 case 1:
10845 printk(" %2.2X",
10846 (unsigned) s[i+(j*4)]);
10847 break;
10848 case 2:
10849 printk(" %2.2X%2.2X",
10850 (unsigned) s[i+(j*4)],
10851 (unsigned) s[i+(j*4)+1]);
10852 break;
10853 case 3:
10854 printk(" %2.2X%2.2X%2.2X",
10855 (unsigned) s[i+(j*4)+1],
10856 (unsigned) s[i+(j*4)+2],
10857 (unsigned) s[i+(j*4)+3]);
10858 break;
10861 printk("\n");
10864 #endif /* ADVANSYS_DEBUG */
10866 #ifdef ADVANSYS_ASSERT
10868 * interrupts_enabled()
10870 * Return 1 if interrupts are enabled, otherwise return 0.
10872 STATIC int
10873 interrupts_enabled(void)
10875 int flags;
10877 save_flags(flags);
10878 if (flags & 0x0200) {
10879 return ASC_TRUE;
10880 } else {
10881 return ASC_FALSE;
10884 #endif /* ADVANSYS_ASSERT */
10888 * --- Asc Library Functions
10891 ASC_INITFUNC(
10892 STATIC ushort,
10893 AscGetEisaChipCfg(
10894 PortAddr iop_base
10898 PortAddr eisa_cfg_iop;
10900 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10901 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
10902 return (inpw(eisa_cfg_iop));
10905 ASC_INITFUNC(
10906 STATIC uchar,
10907 AscSetChipScsiID(
10908 PortAddr iop_base,
10909 uchar new_host_id
10913 ushort cfg_lsw;
10915 if (AscGetChipScsiID(iop_base) == new_host_id) {
10916 return (new_host_id);
10918 cfg_lsw = AscGetChipCfgLsw(iop_base);
10919 cfg_lsw &= 0xF8FF;
10920 cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
10921 AscSetChipCfgLsw(iop_base, cfg_lsw);
10922 return (AscGetChipScsiID(iop_base));
10925 ASC_INITFUNC(
10926 STATIC uchar,
10927 AscGetChipScsiCtrl(
10928 PortAddr iop_base
10932 uchar sc;
10934 AscSetBank(iop_base, 1);
10935 sc = inp(iop_base + IOP_REG_SC);
10936 AscSetBank(iop_base, 0);
10937 return (sc);
10940 ASC_INITFUNC(
10941 STATIC uchar,
10942 AscGetChipVersion(
10943 PortAddr iop_base,
10944 ushort bus_type
10948 if ((bus_type & ASC_IS_EISA) != 0) {
10949 PortAddr eisa_iop;
10950 uchar revision;
10951 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10952 (PortAddr) ASC_EISA_REV_IOP_MASK;
10953 revision = inp(eisa_iop);
10954 return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
10956 return (AscGetChipVerNo(iop_base));
10959 ASC_INITFUNC(
10960 STATIC ushort,
10961 AscGetChipBusType(
10962 PortAddr iop_base
10966 ushort chip_ver;
10968 chip_ver = AscGetChipVerNo(iop_base);
10969 if (
10970 (chip_ver >= ASC_CHIP_MIN_VER_VL)
10971 && (chip_ver <= ASC_CHIP_MAX_VER_VL)
10973 if (
10974 ((iop_base & 0x0C30) == 0x0C30)
10975 || ((iop_base & 0x0C50) == 0x0C50)
10977 return (ASC_IS_EISA);
10979 return (ASC_IS_VL);
10981 if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
10982 (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
10983 if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
10984 return (ASC_IS_ISAPNP);
10986 return (ASC_IS_ISA);
10987 } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
10988 (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
10989 return (ASC_IS_PCI);
10991 return (0);
10994 ASC_INITFUNC(
10995 STATIC ulong,
10996 AscLoadMicroCode(
10997 PortAddr iop_base,
10998 ushort s_addr,
10999 ushort *mcode_buf,
11000 ushort mcode_size
11004 ulong chksum;
11005 ushort mcode_word_size;
11006 ushort mcode_chksum;
11008 mcode_word_size = (ushort) (mcode_size >> 1);
11009 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
11010 AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
11011 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
11012 mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
11013 (ushort) ASC_CODE_SEC_BEG,
11014 (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
11015 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
11016 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
11017 return (chksum);
11020 ASC_INITFUNC(
11021 STATIC int,
11022 AscFindSignature(
11023 PortAddr iop_base
11027 ushort sig_word;
11029 if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
11030 sig_word = AscGetChipSignatureWord(iop_base);
11031 if ((sig_word == (ushort) ASC_1000_ID0W) ||
11032 (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
11033 return (1);
11036 return (0);
11039 STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
11040 STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
11042 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
11043 ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
11046 ASC_INITFUNC(
11047 STATIC PortAddr,
11048 AscSearchIOPortAddr(
11049 PortAddr iop_beg,
11050 ushort bus_type
11054 if (bus_type & ASC_IS_VL) {
11055 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
11056 if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
11057 return (iop_beg);
11060 return (0);
11062 if (bus_type & ASC_IS_ISA) {
11063 if (_isa_pnp_inited == 0) {
11064 AscSetISAPNPWaitForKey();
11065 _isa_pnp_inited++;
11067 while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
11068 if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
11069 return (iop_beg);
11072 return (0);
11074 if (bus_type & ASC_IS_EISA) {
11075 if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
11076 return (iop_beg);
11078 return (0);
11080 return (0);
11083 ASC_INITFUNC(
11084 STATIC PortAddr,
11085 AscSearchIOPortAddr11(
11086 PortAddr s_addr
11090 int i;
11091 PortAddr iop_base;
11093 for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
11094 if (_asc_def_iop_base[i] > s_addr) {
11095 break;
11098 for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
11099 iop_base = _asc_def_iop_base[i];
11100 if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
11101 ASC_DBG1(1,
11102 "AscSearchIOPortAddr11: check_region() failed I/O port %x\n",
11103 iop_base);
11104 continue;
11106 ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base);
11107 if (AscFindSignature(iop_base)) {
11108 return (iop_base);
11111 return (0);
11114 ASC_INITFUNC(
11115 STATIC void,
11116 AscToggleIRQAct(
11117 PortAddr iop_base
11121 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
11122 AscSetChipStatus(iop_base, 0);
11123 return;
11126 ASC_INITFUNC(
11127 STATIC void,
11128 AscSetISAPNPWaitForKey(
11129 void)
11132 outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
11133 outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
11134 return;
11137 ASC_INITFUNC(
11138 STATIC uchar,
11139 AscGetChipIRQ(
11140 PortAddr iop_base,
11141 ushort bus_type
11145 ushort cfg_lsw;
11146 uchar chip_irq;
11148 if ((bus_type & ASC_IS_EISA) != 0) {
11149 cfg_lsw = AscGetEisaChipCfg(iop_base);
11150 chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
11151 if ((chip_irq == 13) || (chip_irq > 15)) {
11152 return (0);
11154 return (chip_irq);
11156 if ((bus_type & ASC_IS_VL) != 0) {
11157 cfg_lsw = AscGetChipCfgLsw(iop_base);
11158 chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
11159 if ((chip_irq == 0) ||
11160 (chip_irq == 4) ||
11161 (chip_irq == 7)) {
11162 return (0);
11164 return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
11166 cfg_lsw = AscGetChipCfgLsw(iop_base);
11167 chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
11168 if (chip_irq == 3)
11169 chip_irq += (uchar) 2;
11170 return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
11173 ASC_INITFUNC(
11174 STATIC uchar,
11175 AscSetChipIRQ(
11176 PortAddr iop_base,
11177 uchar irq_no,
11178 ushort bus_type
11182 ushort cfg_lsw;
11184 if ((bus_type & ASC_IS_VL) != 0) {
11185 if (irq_no != 0) {
11186 if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
11187 irq_no = 0;
11188 } else {
11189 irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
11192 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
11193 cfg_lsw |= (ushort) 0x0010;
11194 AscSetChipCfgLsw(iop_base, cfg_lsw);
11195 AscToggleIRQAct(iop_base);
11196 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
11197 cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
11198 AscSetChipCfgLsw(iop_base, cfg_lsw);
11199 AscToggleIRQAct(iop_base);
11200 return (AscGetChipIRQ(iop_base, bus_type));
11202 if ((bus_type & (ASC_IS_ISA)) != 0) {
11203 if (irq_no == 15)
11204 irq_no -= (uchar) 2;
11205 irq_no -= (uchar) ASC_MIN_IRQ_NO;
11206 cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
11207 cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
11208 AscSetChipCfgLsw(iop_base, cfg_lsw);
11209 return (AscGetChipIRQ(iop_base, bus_type));
11211 return (0);
11214 ASC_INITFUNC(
11215 STATIC void,
11216 AscEnableIsaDma(
11217 uchar dma_channel
11221 if (dma_channel < 4) {
11222 outp(0x000B, (ushort) (0xC0 | dma_channel));
11223 outp(0x000A, dma_channel);
11224 } else if (dma_channel < 8) {
11225 outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
11226 outp(0x00D4, (ushort) (dma_channel - 4));
11228 return;
11231 STATIC int
11232 AscIsrChipHalted(
11233 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11236 EXT_MSG ext_msg;
11237 EXT_MSG out_msg;
11238 ushort halt_q_addr;
11239 int sdtr_accept;
11240 ushort int_halt_code;
11241 ASC_SCSI_BIT_ID_TYPE scsi_busy;
11242 ASC_SCSI_BIT_ID_TYPE target_id;
11243 PortAddr iop_base;
11244 uchar tag_code;
11245 uchar q_status;
11246 uchar halt_qp;
11247 uchar sdtr_data;
11248 uchar target_ix;
11249 uchar q_cntl, tid_no;
11250 uchar cur_dvc_qng;
11251 uchar asyn_sdtr;
11252 uchar scsi_status;
11253 asc_board_t *boardp;
11255 ASC_ASSERT(asc_dvc->drv_ptr != 0);
11256 boardp = (asc_board_t *) asc_dvc->drv_ptr;
11258 iop_base = asc_dvc->iop_base;
11259 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
11261 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
11262 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
11263 target_ix = AscReadLramByte(iop_base,
11264 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
11265 q_cntl = AscReadLramByte(iop_base,
11266 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
11267 tid_no = ASC_TIX_TO_TID(target_ix);
11268 target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
11269 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
11270 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
11271 } else {
11272 asyn_sdtr = 0;
11274 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
11275 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
11276 AscSetChipSDTR(iop_base, 0, tid_no);
11277 boardp->sdtr_data[tid_no] = 0;
11279 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11280 return (0);
11281 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
11282 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
11283 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
11284 boardp->sdtr_data[tid_no] = asyn_sdtr;
11286 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11287 return (0);
11288 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
11290 AscMemWordCopyFromLram(iop_base,
11291 ASCV_MSGIN_BEG,
11292 (ushort *) & ext_msg,
11293 (ushort) (sizeof (EXT_MSG) >> 1));
11295 if (ext_msg.msg_type == MS_EXTEND &&
11296 ext_msg.msg_req == MS_SDTR_CODE &&
11297 ext_msg.msg_len == MS_SDTR_LEN) {
11298 sdtr_accept = TRUE;
11299 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
11301 sdtr_accept = FALSE;
11302 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
11304 if ((ext_msg.xfer_period <
11305 asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) ||
11306 (ext_msg.xfer_period >
11307 asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) {
11308 sdtr_accept = FALSE;
11309 ext_msg.xfer_period =
11310 asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index];
11312 if (sdtr_accept) {
11313 sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
11314 ext_msg.req_ack_offset);
11315 if ((sdtr_data == 0xFF)) {
11317 q_cntl |= QC_MSG_OUT;
11318 asc_dvc->init_sdtr &= ~target_id;
11319 asc_dvc->sdtr_done &= ~target_id;
11320 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
11321 boardp->sdtr_data[tid_no] = asyn_sdtr;
11324 if (ext_msg.req_ack_offset == 0) {
11326 q_cntl &= ~QC_MSG_OUT;
11327 asc_dvc->init_sdtr &= ~target_id;
11328 asc_dvc->sdtr_done &= ~target_id;
11329 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
11330 } else {
11331 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
11333 q_cntl &= ~QC_MSG_OUT;
11334 asc_dvc->sdtr_done |= target_id;
11335 asc_dvc->init_sdtr |= target_id;
11336 asc_dvc->pci_fix_asyn_xfer &= ~target_id;
11337 sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
11338 ext_msg.req_ack_offset);
11339 AscSetChipSDTR(iop_base, sdtr_data, tid_no);
11340 boardp->sdtr_data[tid_no] = sdtr_data;
11341 } else {
11343 q_cntl |= QC_MSG_OUT;
11344 AscMsgOutSDTR(asc_dvc,
11345 ext_msg.xfer_period,
11346 ext_msg.req_ack_offset);
11347 asc_dvc->pci_fix_asyn_xfer &= ~target_id;
11348 sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
11349 ext_msg.req_ack_offset);
11350 AscSetChipSDTR(iop_base, sdtr_data, tid_no);
11351 boardp->sdtr_data[tid_no] = sdtr_data;
11352 asc_dvc->sdtr_done |= target_id;
11353 asc_dvc->init_sdtr |= target_id;
11357 AscWriteLramByte(iop_base,
11358 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
11359 q_cntl);
11360 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11361 return (0);
11362 } else if (ext_msg.msg_type == MS_EXTEND &&
11363 ext_msg.msg_req == MS_WDTR_CODE &&
11364 ext_msg.msg_len == MS_WDTR_LEN) {
11366 ext_msg.wdtr_width = 0;
11367 AscMemWordCopyToLram(iop_base,
11368 ASCV_MSGOUT_BEG,
11369 (ushort *) & ext_msg,
11370 (ushort) (sizeof (EXT_MSG) >> 1));
11371 q_cntl |= QC_MSG_OUT;
11372 AscWriteLramByte(iop_base,
11373 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
11374 q_cntl);
11375 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11376 return (0);
11377 } else {
11379 ext_msg.msg_type = M1_MSG_REJECT;
11380 AscMemWordCopyToLram(iop_base,
11381 ASCV_MSGOUT_BEG,
11382 (ushort *) & ext_msg,
11383 (ushort) (sizeof (EXT_MSG) >> 1));
11384 q_cntl |= QC_MSG_OUT;
11385 AscWriteLramByte(iop_base,
11386 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
11387 q_cntl);
11388 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11389 return (0);
11391 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
11393 q_cntl |= QC_REQ_SENSE;
11395 if ((asc_dvc->init_sdtr & target_id) != 0) {
11397 asc_dvc->sdtr_done &= ~target_id;
11399 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11400 q_cntl |= QC_MSG_OUT;
11401 AscMsgOutSDTR(asc_dvc,
11402 asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
11403 (uchar) (asc_dvc->max_sdtr_index - 1)],
11404 (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
11407 AscWriteLramByte(iop_base,
11408 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
11409 q_cntl);
11411 tag_code = AscReadLramByte(iop_base,
11412 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
11413 tag_code &= 0xDC;
11414 if (
11415 (asc_dvc->pci_fix_asyn_xfer & target_id)
11416 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
11419 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
11420 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
11423 AscWriteLramByte(iop_base,
11424 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
11425 tag_code);
11427 q_status = AscReadLramByte(iop_base,
11428 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
11429 q_status |= (QS_READY | QS_BUSY);
11430 AscWriteLramByte(iop_base,
11431 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
11432 q_status);
11434 scsi_busy = AscReadLramByte(iop_base,
11435 (ushort) ASCV_SCSIBUSY_B);
11436 scsi_busy &= ~target_id;
11437 AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
11439 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11440 return (0);
11441 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
11443 AscMemWordCopyFromLram(iop_base,
11444 ASCV_MSGOUT_BEG,
11445 (ushort *) & out_msg,
11446 (ushort) (sizeof (EXT_MSG) >> 1));
11448 if ((out_msg.msg_type == MS_EXTEND) &&
11449 (out_msg.msg_len == MS_SDTR_LEN) &&
11450 (out_msg.msg_req == MS_SDTR_CODE)) {
11452 asc_dvc->init_sdtr &= ~target_id;
11453 asc_dvc->sdtr_done &= ~target_id;
11454 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
11455 boardp->sdtr_data[tid_no] = asyn_sdtr;
11457 q_cntl &= ~QC_MSG_OUT;
11458 AscWriteLramByte(iop_base,
11459 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
11460 q_cntl);
11461 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11462 return (0);
11463 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
11465 scsi_status = AscReadLramByte(iop_base,
11466 (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
11467 cur_dvc_qng = AscReadLramByte(iop_base,
11468 (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
11469 if ((cur_dvc_qng > 0) &&
11470 (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
11472 scsi_busy = AscReadLramByte(iop_base,
11473 (ushort) ASCV_SCSIBUSY_B);
11474 scsi_busy |= target_id;
11475 AscWriteLramByte(iop_base,
11476 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
11477 asc_dvc->queue_full_or_busy |= target_id;
11479 if (scsi_status == SS_QUEUE_FULL) {
11480 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
11481 cur_dvc_qng -= 1;
11482 asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
11484 AscWriteLramByte(iop_base,
11485 (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG +
11486 (ushort) tid_no),
11487 cur_dvc_qng);
11490 * Set the device queue depth to the number of
11491 * active requests when the QUEUE FULL condition
11492 * was encountered.
11494 boardp->queue_full |= target_id;
11495 boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
11499 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11500 return (0);
11501 } else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC)
11503 uchar q_no;
11504 ushort q_addr;
11505 ulong srb_ptr;
11506 uchar sg_wk_q_no;
11507 uchar first_sg_wk_q_no;
11508 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
11509 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
11510 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
11511 ushort sg_list_dwords;
11512 ushort sg_entry_cnt;
11513 uchar next_qp;
11514 int i;
11516 q_no = AscReadLramByte(iop_base, (ushort) ASCV_REQ_SG_LIST_QP);
11517 if (q_no == ASC_QLINK_END)
11519 return(0);
11522 q_addr = ASC_QNO_TO_QADDR(q_no);
11524 /* Read request's SRB pointer. */
11525 srb_ptr = AscReadLramDWord(iop_base,
11526 (ushort) (q_addr + ASC_SCSIQ_D_SRBPTR));
11529 * Get request's first and working SG queue.
11531 sg_wk_q_no = AscReadLramByte(iop_base,
11532 (ushort) (q_addr + ASC_SCSIQ_B_SG_WK_QP));
11534 first_sg_wk_q_no = AscReadLramByte(iop_base,
11535 (ushort) (q_addr + ASC_SCSIQ_B_FIRST_SG_WK_QP));
11538 * Reset request's working SG queue back to the
11539 * first SG queue.
11541 AscWriteLramByte(iop_base,
11542 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SG_WK_QP),
11543 first_sg_wk_q_no);
11546 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
11547 * structure pointer using a macro provided by the driver.
11548 * The ASC_SCSI_REQ pointer provides a pointer to the
11549 * host ASC_SG_HEAD structure.
11551 scsiq = (ASC_SCSI_Q *) ASC_SRB2SCSIQ(srb_ptr);
11553 sg_head = scsiq->sg_head;
11556 * Set sg_entry_cnt to the number of SG elements
11557 * that will be completed on this interrupt.
11559 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
11560 * SG elements. The data_cnt and data_addr fields which
11561 * add 1 to the SG element capacity are not used when
11562 * restarting SG handling after a halt.
11564 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1))
11566 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
11569 * Keep track of remaining number of SG elements that will
11570 * need to be handled on the next interrupt.
11572 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
11573 } else
11575 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
11576 scsiq->remain_sg_entry_cnt = 0;
11580 * Copy SG elements into the list of allocated SG queues.
11582 * Last index completed is saved in scsiq->next_sg_index.
11584 next_qp = first_sg_wk_q_no;
11585 q_addr = ASC_QNO_TO_QADDR(next_qp);
11586 scsi_sg_q.sg_head_qp = q_no;
11587 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
11588 for( i = 0; i < sg_head->queue_cnt; i++)
11590 scsi_sg_q.seq_no = i + 1;
11591 if (sg_entry_cnt > ASC_SG_LIST_PER_Q)
11593 sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
11594 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
11596 * After very first SG queue RISC FW uses next
11597 * SG queue first element then checks sg_list_cnt
11598 * against zero and then decrements, so set
11599 * sg_list_cnt 1 less than number of SG elements
11600 * in each SG queue.
11602 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
11603 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
11604 } else {
11606 * This is the last SG queue in the list of
11607 * allocated SG queues. If there are more
11608 * SG elements than will fit in the allocated
11609 * queues, then set the QCSG_SG_XFER_MORE flag.
11611 if (scsiq->remain_sg_entry_cnt != 0)
11613 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
11614 } else
11616 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
11618 /* equals sg_entry_cnt * 2 */
11619 sg_list_dwords = sg_entry_cnt << 1;
11620 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
11621 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
11622 sg_entry_cnt = 0;
11625 scsi_sg_q.q_no = next_qp;
11626 AscMemWordCopyToLram(iop_base,
11627 (ushort) (q_addr+ASC_SCSIQ_SGHD_CPY_BEG),
11628 (ushort *) &scsi_sg_q,
11629 (ushort) (sizeof(ASC_SG_LIST_Q) >> 1));
11631 AscMemDWordCopyToLram( iop_base,
11632 (ushort) (q_addr+ASC_SGQ_LIST_BEG ),
11633 (ulong *) &sg_head->sg_list[scsiq->next_sg_index],
11634 (ushort) sg_list_dwords);
11636 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
11639 * If the just completed SG queue contained the
11640 * last SG element, then no more SG queues need
11641 * to be written.
11643 if (scsi_sg_q.cntl & QCSG_SG_XFER_END)
11645 break;
11648 next_qp = AscReadLramByte( iop_base,
11649 ( ushort )( q_addr+ASC_SCSIQ_B_FWD ) );
11650 q_addr = ASC_QNO_TO_QADDR( next_qp );
11654 * Clear the halt condition so the RISC will be restarted
11655 * after the return.
11657 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11658 return(0);
11660 return (0);
11663 STATIC uchar
11664 _AscCopyLramScsiDoneQ(
11665 PortAddr iop_base,
11666 ushort q_addr,
11667 REG ASC_QDONE_INFO * scsiq,
11668 ulong max_dma_count
11671 ushort _val;
11672 uchar sg_queue_cnt;
11674 DvcGetQinfo(iop_base,
11675 (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
11676 (ushort *) scsiq,
11677 (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
11678 _val = AscReadLramWord(iop_base,
11679 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
11680 scsiq->q_status = (uchar) _val;
11681 scsiq->q_no = (uchar) (_val >> 8);
11682 _val = AscReadLramWord(iop_base,
11683 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
11684 scsiq->cntl = (uchar) _val;
11685 sg_queue_cnt = (uchar) (_val >> 8);
11686 _val = AscReadLramWord(iop_base,
11687 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
11688 scsiq->sense_len = (uchar) _val;
11689 scsiq->extra_bytes = (uchar) (_val >> 8);
11692 * Read high word of remain bytes from alternate location.
11694 scsiq->remain_bytes = (((ulong) AscReadLramWord( iop_base,
11695 (ushort) (q_addr+ (ushort) ASC_SCSIQ_W_ALT_DC1))) << 16);
11697 * Read low word of remain bytes from original location.
11699 scsiq->remain_bytes += AscReadLramWord(iop_base,
11700 (ushort) (q_addr+ (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
11702 scsiq->remain_bytes &= max_dma_count;
11703 return (sg_queue_cnt);
11706 STATIC int
11707 AscIsrQDone(
11708 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11711 uchar next_qp;
11712 uchar n_q_used;
11713 uchar sg_list_qp;
11714 uchar sg_queue_cnt;
11715 uchar q_cnt;
11716 uchar done_q_tail;
11717 uchar tid_no;
11718 ASC_SCSI_BIT_ID_TYPE scsi_busy;
11719 ASC_SCSI_BIT_ID_TYPE target_id;
11720 PortAddr iop_base;
11721 ushort q_addr;
11722 ushort sg_q_addr;
11723 uchar cur_target_qng;
11724 ASC_QDONE_INFO scsiq_buf;
11725 REG ASC_QDONE_INFO *scsiq;
11726 int false_overrun;
11727 ASC_ISR_CALLBACK asc_isr_callback;
11729 iop_base = asc_dvc->iop_base;
11730 asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
11731 n_q_used = 1;
11732 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
11733 done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
11734 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
11735 next_qp = AscReadLramByte(iop_base,
11736 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
11737 if (next_qp != ASC_QLINK_END) {
11738 AscPutVarDoneQTail(iop_base, next_qp);
11739 q_addr = ASC_QNO_TO_QADDR(next_qp);
11740 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
11741 asc_dvc->max_dma_count);
11742 AscWriteLramByte(iop_base,
11743 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
11744 (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
11745 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
11746 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
11747 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
11748 sg_q_addr = q_addr;
11749 sg_list_qp = next_qp;
11750 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
11751 sg_list_qp = AscReadLramByte(iop_base,
11752 (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
11753 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
11754 if (sg_list_qp == ASC_QLINK_END) {
11755 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
11756 scsiq->d3.done_stat = QD_WITH_ERROR;
11757 scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
11758 goto FATAL_ERR_QDONE;
11760 AscWriteLramByte(iop_base,
11761 (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
11762 QS_FREE);
11764 n_q_used = sg_queue_cnt + 1;
11765 AscPutVarDoneQTail(iop_base, sg_list_qp);
11767 if (asc_dvc->queue_full_or_busy & target_id) {
11768 cur_target_qng = AscReadLramByte(iop_base,
11769 (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
11770 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
11771 scsi_busy = AscReadLramByte(iop_base,
11772 (ushort) ASCV_SCSIBUSY_B);
11773 scsi_busy &= ~target_id;
11774 AscWriteLramByte(iop_base,
11775 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
11776 asc_dvc->queue_full_or_busy &= ~target_id;
11779 if (asc_dvc->cur_total_qng >= n_q_used) {
11780 asc_dvc->cur_total_qng -= n_q_used;
11781 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
11782 asc_dvc->cur_dvc_qng[tid_no]--;
11784 } else {
11785 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
11786 scsiq->d3.done_stat = QD_WITH_ERROR;
11787 goto FATAL_ERR_QDONE;
11789 if ((scsiq->d2.srb_ptr == 0UL) ||
11790 ((scsiq->q_status & QS_ABORTED) != 0)) {
11791 return (0x11);
11792 } else if (scsiq->q_status == QS_DONE) {
11793 false_overrun = FALSE;
11794 if (scsiq->extra_bytes != 0) {
11795 scsiq->remain_bytes += (ulong) scsiq->extra_bytes;
11797 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
11798 if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) {
11799 if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
11800 scsiq->d3.done_stat = QD_NO_ERROR;
11801 scsiq->d3.host_stat = QHSTA_NO_ERROR;
11802 } else if (false_overrun) {
11803 scsiq->d3.done_stat = QD_NO_ERROR;
11804 scsiq->d3.host_stat = QHSTA_NO_ERROR;
11806 } else if (scsiq->d3.host_stat ==
11807 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
11808 AscStopChip(iop_base);
11809 AscSetChipControl(iop_base,
11810 (uchar) (CC_SCSI_RESET | CC_HALT));
11811 DvcDelayNanoSecond(asc_dvc, 60000);
11812 AscSetChipControl(iop_base, CC_HALT);
11813 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
11814 AscSetChipStatus(iop_base, 0);
11815 AscSetChipControl(iop_base, 0);
11818 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
11819 (*asc_isr_callback) (asc_dvc, scsiq);
11820 } else {
11821 if ((AscReadLramByte(iop_base,
11822 (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
11823 SCSICMD_StartStopUnit)) {
11824 asc_dvc->unit_not_ready &= ~target_id;
11825 if (scsiq->d3.done_stat != QD_NO_ERROR) {
11826 asc_dvc->start_motor &= ~target_id;
11830 return (1);
11831 } else {
11832 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
11833 FATAL_ERR_QDONE:
11834 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
11835 (*asc_isr_callback) (asc_dvc, scsiq);
11837 return (0x80);
11840 return (0);
11843 STATIC int
11844 AscISR(
11845 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11848 ASC_CS_TYPE chipstat;
11849 PortAddr iop_base;
11850 ushort saved_ram_addr;
11851 uchar ctrl_reg;
11852 uchar saved_ctrl_reg;
11853 int int_pending;
11854 int status;
11855 uchar host_flag;
11857 iop_base = asc_dvc->iop_base;
11858 int_pending = FALSE;
11860 if (AscIsIntPending(iop_base) == 0)
11862 return int_pending;
11865 if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
11866 || (asc_dvc->isr_callback == 0)
11868 return (ERR);
11870 if (asc_dvc->in_critical_cnt != 0) {
11871 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
11872 return (ERR);
11874 if (asc_dvc->is_in_int) {
11875 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
11876 return (ERR);
11878 asc_dvc->is_in_int = TRUE;
11879 ctrl_reg = AscGetChipControl(iop_base);
11880 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
11881 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
11882 chipstat = AscGetChipStatus(iop_base);
11883 if (chipstat & CSW_SCSI_RESET_LATCH) {
11884 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
11885 int i = 10;
11886 int_pending = TRUE;
11887 asc_dvc->sdtr_done = 0;
11888 saved_ctrl_reg &= (uchar) (~CC_HALT);
11889 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) &&
11890 (i-- > 0))
11892 DvcSleepMilliSecond(100);
11894 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
11895 AscSetChipControl(iop_base, CC_HALT);
11896 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
11897 AscSetChipStatus(iop_base, 0);
11898 chipstat = AscGetChipStatus(iop_base);
11901 saved_ram_addr = AscGetChipLramAddr(iop_base);
11902 host_flag = AscReadLramByte(iop_base,
11903 ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR);
11904 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
11905 (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
11906 if ((chipstat & CSW_INT_PENDING)
11907 || (int_pending)
11909 AscAckInterrupt(iop_base);
11910 int_pending = TRUE;
11911 if ((chipstat & CSW_HALTED) &&
11912 (ctrl_reg & CC_SINGLE_STEP)) {
11913 if (AscIsrChipHalted(asc_dvc) == ERR) {
11914 goto ISR_REPORT_QDONE_FATAL_ERROR;
11915 } else {
11916 saved_ctrl_reg &= (uchar) (~CC_HALT);
11918 } else {
11919 ISR_REPORT_QDONE_FATAL_ERROR:
11920 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
11921 while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
11923 } else {
11924 do {
11925 if ((status = AscIsrQDone(asc_dvc)) == 1) {
11926 break;
11928 } while (status == 0x11);
11930 if ((status & 0x80) != 0)
11931 int_pending = ERR;
11934 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
11935 AscSetChipLramAddr(iop_base, saved_ram_addr);
11936 AscSetChipControl(iop_base, saved_ctrl_reg);
11937 asc_dvc->is_in_int = FALSE;
11938 return (int_pending);
11941 STATIC uchar _asc_mcode_buf[] ASC_INITDATA =
11943 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11944 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11947 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
11948 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11949 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
11950 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00,
11951 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
11952 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80,
11953 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
11954 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
11955 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00,
11956 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1,
11957 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
11958 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00, 0x84, 0x97, 0x07, 0xA6,
11959 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00,
11960 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
11961 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x34, 0x01, 0x00, 0x33,
11962 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04,
11963 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
11964 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01, 0x00, 0x33, 0x0A, 0x00,
11965 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04,
11966 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
11967 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x3C, 0x01, 0x00, 0x05,
11968 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01,
11969 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
11970 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0xC2, 0x88, 0x06, 0x23,
11971 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0,
11972 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
11973 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97,
11974 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80,
11975 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
11976 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88, 0x04, 0x98, 0xF0, 0x80,
11977 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6,
11978 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
11979 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02, 0x07, 0xA6, 0x5A, 0x02,
11980 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96,
11981 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
11982 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01,
11983 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02,
11984 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
11985 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43,
11986 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01,
11987 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
11988 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8, 0x00, 0x33, 0x1F, 0x00,
11989 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6,
11990 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
11991 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xEE, 0x82,
11992 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8,
11993 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
11994 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6,
11995 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83,
11996 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
11997 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05, 0xFF, 0xA2, 0x7A, 0x03,
11998 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03,
11999 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
12000 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, 0xA4, 0x03, 0x00, 0xA6,
12001 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03,
12002 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
12003 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95, 0xC0, 0x83, 0x00, 0x33,
12004 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23,
12005 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
12006 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04, 0x06, 0xA6, 0x0A, 0x04,
12007 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84,
12008 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
12009 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33,
12010 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC,
12011 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
12012 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01,
12013 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00,
12014 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
12015 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3,
12016 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23,
12017 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
12018 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xE8, 0x81,
12019 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81,
12020 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
12021 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33,
12022 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01,
12023 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
12024 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04,
12025 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85,
12026 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
12027 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01,
12028 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01,
12029 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
12030 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05,
12031 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0,
12032 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
12033 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85,
12034 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0,
12035 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
12036 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63,
12037 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23,
12038 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
12039 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03,
12040 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6,
12041 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
12042 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61,
12043 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01,
12044 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
12045 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6,
12046 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20,
12047 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
12048 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
12049 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43,
12050 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
12051 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06,
12052 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6,
12053 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
12054 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01,
12055 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33,
12056 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
12057 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88, 0x00, 0x00, 0x80, 0x67,
12058 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61,
12059 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
12060 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05,
12061 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01,
12062 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
12063 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00,
12064 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00,
12065 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
12066 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33,
12067 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01,
12068 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
12069 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63,
12070 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02,
12071 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
12072 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04,
12073 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08,
12074 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
12075 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01,
12076 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08,
12077 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
12078 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B,
12079 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09,
12080 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
12081 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A,
12082 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3,
12083 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
12084 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01,
12085 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2,
12086 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
12089 STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf);
12090 STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012C453FUL;
12092 #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
12093 STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
12095 SCSICMD_Inquiry,
12096 SCSICMD_RequestSense,
12097 SCSICMD_ReadCapacity,
12098 SCSICMD_ReadTOC,
12099 SCSICMD_ModeSelect6,
12100 SCSICMD_ModeSense6,
12101 SCSICMD_ModeSelect10,
12102 SCSICMD_ModeSense10,
12103 0xFF,
12104 0xFF,
12105 0xFF,
12106 0xFF,
12107 0xFF,
12108 0xFF,
12109 0xFF,
12110 0xFF
12113 STATIC int
12114 AscExeScsiQueue(
12115 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12116 REG ASC_SCSI_Q * scsiq
12119 PortAddr iop_base;
12120 int last_int_level;
12121 int sta;
12122 int n_q_required;
12123 int disable_syn_offset_one_fix;
12124 int i;
12125 ulong addr;
12126 ASC_EXE_CALLBACK asc_exe_callback;
12127 ushort sg_entry_cnt = 0;
12128 ushort sg_entry_cnt_minus_one = 0;
12129 uchar target_ix;
12130 uchar tid_no;
12131 uchar sdtr_data;
12132 uchar extra_bytes;
12133 uchar scsi_cmd;
12134 uchar disable_cmd;
12135 ASC_SG_HEAD *sg_head;
12136 ulong data_cnt;
12138 iop_base = asc_dvc->iop_base;
12139 sg_head = scsiq->sg_head;
12140 asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
12141 if (asc_dvc->err_code != 0)
12142 return (ERR);
12143 if (scsiq == (ASC_SCSI_Q *) 0L) {
12144 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
12145 return (ERR);
12147 scsiq->q1.q_no = 0;
12148 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
12149 scsiq->q1.extra_bytes = 0;
12151 sta = 0;
12152 target_ix = scsiq->q2.target_ix;
12153 tid_no = ASC_TIX_TO_TID(target_ix);
12154 n_q_required = 1;
12155 if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
12156 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
12157 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
12158 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
12159 AscMsgOutSDTR(asc_dvc,
12160 asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
12161 (uchar) (asc_dvc->max_sdtr_index - 1)],
12162 (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
12163 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
12166 last_int_level = DvcEnterCritical();
12167 if (asc_dvc->in_critical_cnt != 0) {
12168 DvcLeaveCritical(last_int_level);
12169 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
12170 return (ERR);
12172 asc_dvc->in_critical_cnt++;
12173 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
12174 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
12175 asc_dvc->in_critical_cnt--;
12176 DvcLeaveCritical(last_int_level);
12177 return (ERR);
12179 #if !CC_VERY_LONG_SG_LIST
12180 if (sg_entry_cnt > ASC_MAX_SG_LIST)
12182 return(ERR);
12184 #endif /* !CC_VERY_LONG_SG_LIST */
12185 if (sg_entry_cnt == 1) {
12186 scsiq->q1.data_addr = (ulong) sg_head->sg_list[0].addr;
12187 scsiq->q1.data_cnt = (ulong) sg_head->sg_list[0].bytes;
12188 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
12190 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
12192 scsi_cmd = scsiq->cdbptr[0];
12193 disable_syn_offset_one_fix = FALSE;
12194 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
12195 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
12196 if (scsiq->q1.cntl & QC_SG_HEAD) {
12197 data_cnt = 0;
12198 for (i = 0; i < sg_entry_cnt; i++) {
12199 data_cnt += (ulong) sg_head->sg_list[i].bytes;
12201 } else {
12202 data_cnt = scsiq->q1.data_cnt;
12204 if (data_cnt != 0UL) {
12205 if (data_cnt < 512UL) {
12206 disable_syn_offset_one_fix = TRUE;
12207 } else {
12208 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) {
12209 disable_cmd = _syn_offset_one_disable_cmd[i];
12210 if (disable_cmd == 0xFF) {
12211 break;
12213 if (scsi_cmd == disable_cmd) {
12214 disable_syn_offset_one_fix = TRUE;
12215 break;
12221 if (disable_syn_offset_one_fix) {
12222 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
12223 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
12224 ASC_TAG_FLAG_DISABLE_DISCONNECT);
12225 } else {
12226 scsiq->q2.tag_code &= 0x23;
12228 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
12229 if (asc_dvc->bug_fix_cntl) {
12230 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
12231 if ((scsi_cmd == SCSICMD_Read6) ||
12232 (scsi_cmd == SCSICMD_Read10)) {
12233 addr =
12234 (ulong) sg_head->sg_list[sg_entry_cnt_minus_one].addr +
12235 (ulong) sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
12236 extra_bytes = (uchar) ((ushort) addr & 0x0003);
12237 if ((extra_bytes != 0) &&
12238 ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
12239 == 0)) {
12240 scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
12241 scsiq->q1.extra_bytes = extra_bytes;
12242 sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
12243 (ulong) extra_bytes;
12248 sg_head->entry_to_copy = sg_head->entry_cnt;
12250 * Set the sg_entry_cnt to the maximum possible. The rest of
12251 * the SG elements will be copied when the RISC completes the
12252 * SG elements that fit and halts.
12254 if (sg_entry_cnt > ASC_MAX_SG_LIST)
12256 sg_entry_cnt = ASC_MAX_SG_LIST;
12258 n_q_required = AscSgListToQueue(sg_entry_cnt);
12259 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
12260 (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
12261 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
12262 n_q_required)) == 1) {
12263 asc_dvc->in_critical_cnt--;
12264 if (asc_exe_callback != 0) {
12265 (*asc_exe_callback) (asc_dvc, scsiq);
12267 DvcLeaveCritical(last_int_level);
12268 return (sta);
12271 } else {
12272 if (asc_dvc->bug_fix_cntl) {
12273 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
12274 if ((scsi_cmd == SCSICMD_Read6) ||
12275 (scsi_cmd == SCSICMD_Read10)) {
12276 addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
12277 extra_bytes = (uchar) ((ushort) addr & 0x0003);
12278 if ((extra_bytes != 0) &&
12279 ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
12280 == 0)) {
12281 if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
12282 scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
12283 scsiq->q1.data_cnt -= (ulong) extra_bytes;
12284 scsiq->q1.extra_bytes = extra_bytes;
12290 n_q_required = 1;
12291 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
12292 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
12293 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
12294 n_q_required)) == 1) {
12295 asc_dvc->in_critical_cnt--;
12296 if (asc_exe_callback != 0) {
12297 (*asc_exe_callback) (asc_dvc, scsiq);
12299 DvcLeaveCritical(last_int_level);
12300 return (sta);
12304 asc_dvc->in_critical_cnt--;
12305 DvcLeaveCritical(last_int_level);
12306 return (sta);
12309 STATIC int
12310 AscSendScsiQueue(
12311 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12312 REG ASC_SCSI_Q * scsiq,
12313 uchar n_q_required
12316 PortAddr iop_base;
12317 uchar free_q_head;
12318 uchar next_qp;
12319 uchar tid_no;
12320 uchar target_ix;
12321 int sta;
12323 iop_base = asc_dvc->iop_base;
12324 target_ix = scsiq->q2.target_ix;
12325 tid_no = ASC_TIX_TO_TID(target_ix);
12326 sta = 0;
12327 free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
12328 if (n_q_required > 1) {
12329 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
12330 free_q_head, (uchar) (n_q_required)))
12331 != (uchar) ASC_QLINK_END) {
12332 asc_dvc->last_q_shortage = 0;
12333 scsiq->sg_head->queue_cnt = n_q_required - 1;
12334 scsiq->q1.q_no = free_q_head;
12335 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
12336 free_q_head)) == 1) {
12337 AscPutVarFreeQHead(iop_base, next_qp);
12338 asc_dvc->cur_total_qng += (uchar) (n_q_required);
12339 asc_dvc->cur_dvc_qng[tid_no]++;
12341 return (sta);
12343 } else if (n_q_required == 1) {
12344 if ((next_qp = AscAllocFreeQueue(iop_base,
12345 free_q_head)) != ASC_QLINK_END) {
12346 scsiq->q1.q_no = free_q_head;
12347 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
12348 free_q_head)) == 1) {
12349 AscPutVarFreeQHead(iop_base, next_qp);
12350 asc_dvc->cur_total_qng++;
12351 asc_dvc->cur_dvc_qng[tid_no]++;
12353 return (sta);
12356 return (sta);
12359 STATIC int
12360 AscSgListToQueue(
12361 int sg_list
12364 int n_sg_list_qs;
12366 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
12367 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
12368 n_sg_list_qs++;
12369 return (n_sg_list_qs + 1);
12373 STATIC uint
12374 AscGetNumOfFreeQueue(
12375 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12376 uchar target_ix,
12377 uchar n_qs
12380 uint cur_used_qs;
12381 uint cur_free_qs;
12382 ASC_SCSI_BIT_ID_TYPE target_id;
12383 uchar tid_no;
12385 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
12386 tid_no = ASC_TIX_TO_TID(target_ix);
12387 if ((asc_dvc->unit_not_ready & target_id) ||
12388 (asc_dvc->queue_full_or_busy & target_id)) {
12389 return (0);
12391 if (n_qs == 1) {
12392 cur_used_qs = (uint) asc_dvc->cur_total_qng +
12393 (uint) asc_dvc->last_q_shortage +
12394 (uint) ASC_MIN_FREE_Q;
12395 } else {
12396 cur_used_qs = (uint) asc_dvc->cur_total_qng +
12397 (uint) ASC_MIN_FREE_Q;
12399 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
12400 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
12401 if (asc_dvc->cur_dvc_qng[tid_no] >=
12402 asc_dvc->max_dvc_qng[tid_no]) {
12403 return (0);
12405 return (cur_free_qs);
12407 if (n_qs > 1) {
12408 if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
12409 asc_dvc->last_q_shortage = n_qs;
12412 return (0);
12415 STATIC int
12416 AscPutReadyQueue(
12417 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12418 REG ASC_SCSI_Q * scsiq,
12419 uchar q_no
12422 ushort q_addr;
12423 uchar tid_no;
12424 uchar sdtr_data;
12425 uchar syn_period_ix;
12426 uchar syn_offset;
12427 PortAddr iop_base;
12429 iop_base = asc_dvc->iop_base;
12430 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
12431 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
12432 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
12433 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
12434 syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
12435 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
12436 AscMsgOutSDTR(asc_dvc,
12437 asc_dvc->sdtr_period_tbl[syn_period_ix],
12438 syn_offset);
12439 scsiq->q1.cntl |= QC_MSG_OUT;
12441 q_addr = ASC_QNO_TO_QADDR(q_no);
12442 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
12443 scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
12445 scsiq->q1.status = QS_FREE;
12446 AscMemWordCopyToLram(iop_base,
12447 (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
12448 (ushort *) scsiq->cdbptr,
12449 (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
12450 DvcPutScsiQ(iop_base,
12451 (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
12452 (ushort *) & scsiq->q1.cntl,
12453 (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
12454 AscWriteLramWord(iop_base,
12455 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12456 (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
12457 return (1);
12460 STATIC int
12461 AscPutReadySgListQueue(
12462 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12463 REG ASC_SCSI_Q * scsiq,
12464 uchar q_no
12467 int sta;
12468 int i;
12469 ASC_SG_HEAD *sg_head;
12470 ASC_SG_LIST_Q scsi_sg_q;
12471 ulong saved_data_addr;
12472 ulong saved_data_cnt;
12473 PortAddr iop_base;
12474 ushort sg_list_dwords;
12475 ushort sg_index;
12476 ushort sg_entry_cnt;
12477 ushort q_addr;
12478 uchar next_qp;
12480 iop_base = asc_dvc->iop_base;
12481 sg_head = scsiq->sg_head;
12482 saved_data_addr = scsiq->q1.data_addr;
12483 saved_data_cnt = scsiq->q1.data_cnt;
12484 scsiq->q1.data_addr = (ulong) sg_head->sg_list[0].addr;
12485 scsiq->q1.data_cnt = (ulong) sg_head->sg_list[0].bytes;
12487 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
12488 * then not all SG elements will fit in the allocated queues.
12489 * The rest of the SG elements will be copied when the RISC
12490 * completes the SG elements that fit and halts.
12492 if (sg_head->entry_cnt > ASC_MAX_SG_LIST)
12495 * Set sg_entry_cnt to be the number of SG elements that
12496 * will fit in the allocated SG queues. It is minus 1 because
12497 * first SG element handled above. ASC_MAX_SG_LIST is already
12498 * inflated by 1 to account for this. For example it may
12499 * be 50 which is 1 + 7 queues * 7 SG elements.
12501 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
12504 * Keep track of remaining number of SG elements that will
12505 * need to be handled from a_isr.c.
12507 scsiq->remain_sg_entry_cnt = sg_head->entry_cnt - ASC_MAX_SG_LIST;
12508 } else
12511 * Set sg_entry_cnt to be the number of SG elements that
12512 * will fit in the allocated SG queues. Refer to comment
12513 * above regarding why it is - 1.
12515 sg_entry_cnt = sg_head->entry_cnt - 1;
12517 if (sg_entry_cnt != 0) {
12518 scsiq->q1.cntl |= QC_SG_HEAD;
12519 q_addr = ASC_QNO_TO_QADDR(q_no);
12520 sg_index = 1;
12521 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
12522 scsi_sg_q.sg_head_qp = q_no;
12523 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
12524 for (i = 0; i < sg_head->queue_cnt; i++) {
12525 scsi_sg_q.seq_no = i + 1;
12526 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
12527 sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
12528 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
12529 if (i == 0) {
12530 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
12531 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
12532 } else {
12533 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
12534 scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
12536 } else {
12538 * This is the last SG queue in the list of
12539 * allocated SG queues. If there are more
12540 * SG elements than will fit in the allocated
12541 * queues, then set the QCSG_SG_XFER_MORE flag.
12543 if (sg_head->entry_cnt > ASC_MAX_SG_LIST)
12545 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
12546 } else
12548 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
12550 sg_list_dwords = sg_entry_cnt << 1;
12551 if (i == 0) {
12552 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
12553 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
12554 } else {
12555 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
12556 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
12558 sg_entry_cnt = 0;
12560 next_qp = AscReadLramByte(iop_base,
12561 (ushort) (q_addr + ASC_SCSIQ_B_FWD));
12562 scsi_sg_q.q_no = next_qp;
12563 q_addr = ASC_QNO_TO_QADDR(next_qp);
12564 AscMemWordCopyToLram(iop_base,
12565 (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
12566 (ushort *) & scsi_sg_q,
12567 (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
12568 AscMemDWordCopyToLram(iop_base,
12569 (ushort) (q_addr + ASC_SGQ_LIST_BEG),
12570 (ulong *) & sg_head->sg_list[sg_index],
12571 (ushort) sg_list_dwords);
12572 sg_index += ASC_SG_LIST_PER_Q;
12573 scsiq->next_sg_index = sg_index;
12575 } else {
12576 scsiq->q1.cntl &= ~QC_SG_HEAD;
12578 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
12579 scsiq->q1.data_addr = saved_data_addr;
12580 scsiq->q1.data_cnt = saved_data_cnt;
12581 return (sta);
12584 STATIC int
12585 AscAbortSRB(
12586 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12587 ulong srb_ptr
12590 int sta;
12591 ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
12592 PortAddr iop_base;
12594 iop_base = asc_dvc->iop_base;
12595 sta = ERR;
12596 saved_unit_not_ready = asc_dvc->unit_not_ready;
12597 asc_dvc->unit_not_ready = 0xFF;
12598 AscWaitISRDone(asc_dvc);
12599 if (AscStopQueueExe(iop_base) == 1) {
12600 if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
12601 sta = 1;
12602 AscCleanUpBusyQueue(iop_base);
12603 AscStartQueueExe(iop_base);
12604 } else {
12605 sta = 0;
12606 AscStartQueueExe(iop_base);
12609 asc_dvc->unit_not_ready = saved_unit_not_ready;
12610 return (sta);
12613 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12614 STATIC int
12615 AscResetDevice(
12616 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12617 uchar target_ix
12620 PortAddr iop_base;
12621 int sta;
12622 uchar tid_no;
12624 ASC_SCSI_BIT_ID_TYPE target_id;
12625 int i;
12626 ASC_SCSI_REQ_Q scsiq_buf;
12627 ASC_SCSI_REQ_Q *scsiq;
12628 uchar *buf;
12629 ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
12630 iop_base = asc_dvc->iop_base;
12631 tid_no = ASC_TIX_TO_TID(target_ix);
12632 target_id = ASC_TID_TO_TARGET_ID(tid_no);
12633 saved_unit_not_ready = asc_dvc->unit_not_ready;
12634 asc_dvc->unit_not_ready = target_id;
12635 sta = ERR;
12636 AscWaitTixISRDone(asc_dvc, target_ix);
12637 if (AscStopQueueExe(iop_base) == 1) {
12638 if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
12639 AscCleanUpBusyQueue(iop_base);
12640 AscStartQueueExe(iop_base);
12641 AscWaitTixISRDone(asc_dvc, target_ix);
12642 sta = TRUE;
12643 scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
12644 buf = (uchar *) & scsiq_buf;
12645 for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
12646 *buf++ = 0x00;
12648 scsiq->r1.status = (uchar) QS_READY;
12649 scsiq->r2.cdb_len = 6;
12650 scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
12651 scsiq->r1.target_id = target_id;
12652 scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
12653 scsiq->cdbptr = (uchar *) scsiq->cdb;
12654 scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
12655 AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
12656 M1_BUS_DVC_RESET);
12657 asc_dvc->unit_not_ready &= ~target_id;
12658 asc_dvc->sdtr_done |= target_id;
12659 if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq)
12660 == 1) {
12661 asc_dvc->unit_not_ready = target_id;
12662 DvcSleepMilliSecond(1000);
12663 _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq);
12664 if (AscStopQueueExe(iop_base) == 1) {
12665 AscCleanUpDiscQueue(iop_base);
12666 AscStartQueueExe(iop_base);
12667 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
12668 AscSetRunChipSynRegAtID(iop_base, tid_no,
12669 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
12671 AscWaitTixISRDone(asc_dvc, target_ix);
12673 } else {
12674 sta = 0;
12676 asc_dvc->sdtr_done &= ~target_id;
12677 } else {
12678 sta = ERR;
12679 AscStartQueueExe(iop_base);
12682 asc_dvc->unit_not_ready = saved_unit_not_ready;
12683 return (sta);
12685 #endif /* version >= v1.3.89 */
12687 STATIC int
12688 AscResetSB(
12689 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12692 int sta;
12693 int i;
12694 PortAddr iop_base;
12696 iop_base = asc_dvc->iop_base;
12697 asc_dvc->unit_not_ready = 0xFF;
12698 sta = TRUE;
12699 AscWaitISRDone(asc_dvc);
12700 AscStopQueueExe(iop_base);
12701 asc_dvc->sdtr_done = 0;
12702 AscResetChipAndScsiBus(asc_dvc);
12703 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
12704 AscReInitLram(asc_dvc);
12705 for (i = 0; i <= ASC_MAX_TID; i++) {
12706 asc_dvc->cur_dvc_qng[i] = 0;
12707 if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) {
12708 AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
12711 asc_dvc->err_code = 0;
12712 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
12713 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
12714 sta = ERR;
12716 if (AscStartChip(iop_base) == 0) {
12717 sta = ERR;
12719 AscStartQueueExe(iop_base);
12720 asc_dvc->unit_not_ready = 0;
12721 asc_dvc->queue_full_or_busy = 0;
12722 return (sta);
12725 STATIC int
12726 AscSetRunChipSynRegAtID(
12727 PortAddr iop_base,
12728 uchar tid_no,
12729 uchar sdtr_data
12732 int sta = FALSE;
12734 if (AscHostReqRiscHalt(iop_base)) {
12735 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
12736 AscStartChip(iop_base);
12737 return (sta);
12739 return (sta);
12742 STATIC int
12743 AscSetChipSynRegAtID(
12744 PortAddr iop_base,
12745 uchar id,
12746 uchar sdtr_data
12749 ASC_SCSI_BIT_ID_TYPE org_id;
12750 int i;
12751 int sta = TRUE;
12753 AscSetBank(iop_base, 1);
12754 org_id = AscReadChipDvcID(iop_base);
12755 for (i = 0; i <= ASC_MAX_TID; i++) {
12756 if (org_id == (0x01 << i))
12757 break;
12759 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
12760 AscWriteChipDvcID(iop_base, id);
12761 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
12762 AscSetBank(iop_base, 0);
12763 AscSetChipSyn(iop_base, sdtr_data);
12764 if (AscGetChipSyn(iop_base) != sdtr_data) {
12765 sta = FALSE;
12767 } else {
12768 sta = FALSE;
12770 AscSetBank(iop_base, 1);
12771 AscWriteChipDvcID(iop_base, org_id);
12772 AscSetBank(iop_base, 0);
12773 return (sta);
12776 STATIC int
12777 AscReInitLram(
12778 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12781 AscInitLram(asc_dvc);
12782 AscInitQLinkVar(asc_dvc);
12783 return (0);
12786 STATIC ushort
12787 AscInitLram(
12788 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12791 uchar i;
12792 ushort s_addr;
12793 PortAddr iop_base;
12794 ushort warn_code;
12796 iop_base = asc_dvc->iop_base;
12797 warn_code = 0;
12798 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
12799 (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
12801 i = ASC_MIN_ACTIVE_QNO;
12802 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
12803 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
12804 (uchar) (i + 1));
12805 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
12806 (uchar) (asc_dvc->max_total_qng));
12807 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
12808 (uchar) i);
12809 i++;
12810 s_addr += ASC_QBLK_SIZE;
12811 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
12812 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
12813 (uchar) (i + 1));
12814 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
12815 (uchar) (i - 1));
12816 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
12817 (uchar) i);
12819 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
12820 (uchar) ASC_QLINK_END);
12821 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
12822 (uchar) (asc_dvc->max_total_qng - 1));
12823 AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
12824 (uchar) asc_dvc->max_total_qng);
12825 i++;
12826 s_addr += ASC_QBLK_SIZE;
12827 for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
12828 i++, s_addr += ASC_QBLK_SIZE) {
12829 AscWriteLramByte(iop_base,
12830 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
12831 AscWriteLramByte(iop_base,
12832 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
12833 AscWriteLramByte(iop_base,
12834 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
12836 return (warn_code);
12839 STATIC ushort
12840 AscInitQLinkVar(
12841 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12844 PortAddr iop_base;
12845 int i;
12846 ushort lram_addr;
12848 iop_base = asc_dvc->iop_base;
12849 AscPutRiscVarFreeQHead(iop_base, 1);
12850 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
12851 AscPutVarFreeQHead(iop_base, 1);
12852 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
12853 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
12854 (uchar) ((int) asc_dvc->max_total_qng + 1));
12855 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
12856 (uchar) ((int) asc_dvc->max_total_qng + 2));
12857 AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
12858 asc_dvc->max_total_qng);
12859 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
12860 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
12861 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
12862 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
12863 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
12864 AscPutQDoneInProgress(iop_base, 0);
12865 lram_addr = ASC_QADR_BEG;
12866 for (i = 0; i < 32; i++, lram_addr += 2) {
12867 AscWriteLramWord(iop_base, lram_addr, 0);
12869 return (0);
12872 STATIC int
12873 AscSetLibErrorCode(
12874 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12875 ushort err_code
12878 if (asc_dvc->err_code == 0) {
12879 asc_dvc->err_code = err_code;
12880 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
12881 err_code);
12883 return (err_code);
12887 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12888 STATIC int
12889 _AscWaitQDone(
12890 PortAddr iop_base,
12891 REG ASC_SCSI_Q * scsiq
12894 ushort q_addr;
12895 uchar q_status;
12896 int count = 0;
12898 while (scsiq->q1.q_no == 0);
12899 q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
12900 do {
12901 q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
12902 DvcSleepMilliSecond(100L);
12903 if (count++ > 30) {
12904 return (0);
12906 } while ((q_status & QS_READY) != 0);
12907 return (1);
12909 #endif /* version >= v1.3.89 */
12911 STATIC uchar
12912 AscMsgOutSDTR(
12913 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12914 uchar sdtr_period,
12915 uchar sdtr_offset
12918 EXT_MSG sdtr_buf;
12919 uchar sdtr_period_index;
12920 PortAddr iop_base;
12922 iop_base = asc_dvc->iop_base;
12923 sdtr_buf.msg_type = MS_EXTEND;
12924 sdtr_buf.msg_len = MS_SDTR_LEN;
12925 sdtr_buf.msg_req = MS_SDTR_CODE;
12926 sdtr_buf.xfer_period = sdtr_period;
12927 sdtr_offset &= ASC_SYN_MAX_OFFSET;
12928 sdtr_buf.req_ack_offset = sdtr_offset;
12929 if ((sdtr_period_index =
12930 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
12931 asc_dvc->max_sdtr_index) {
12932 AscMemWordCopyToLram(iop_base,
12933 ASCV_MSGOUT_BEG,
12934 (ushort *) & sdtr_buf,
12935 (ushort) (sizeof (EXT_MSG) >> 1));
12936 return ((sdtr_period_index << 4) | sdtr_offset);
12937 } else {
12939 sdtr_buf.req_ack_offset = 0;
12940 AscMemWordCopyToLram(iop_base,
12941 ASCV_MSGOUT_BEG,
12942 (ushort *) & sdtr_buf,
12943 (ushort) (sizeof (EXT_MSG) >> 1));
12944 return (0);
12948 STATIC uchar
12949 AscCalSDTRData(
12950 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12951 uchar sdtr_period,
12952 uchar syn_offset
12955 uchar byte;
12956 uchar sdtr_period_ix;
12958 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
12959 if (
12960 (sdtr_period_ix > asc_dvc->max_sdtr_index)
12962 return (0xFF);
12964 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
12965 return (byte);
12968 STATIC void
12969 AscSetChipSDTR(
12970 PortAddr iop_base,
12971 uchar sdtr_data,
12972 uchar tid_no
12975 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
12976 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
12977 return;
12980 STATIC uchar
12981 AscGetSynPeriodIndex(
12982 ASC_DVC_VAR asc_ptr_type * asc_dvc,
12983 ruchar syn_time
12986 ruchar *period_table;
12987 int max_index;
12988 int min_index;
12989 int i;
12991 period_table = asc_dvc->sdtr_period_tbl;
12992 max_index = (int) asc_dvc->max_sdtr_index;
12993 min_index = (int)asc_dvc->host_init_sdtr_index;
12994 if ((syn_time <= period_table[max_index])) {
12995 for (i = min_index; i < (max_index - 1); i++) {
12996 if (syn_time <= period_table[i]) {
12997 return ((uchar) i);
13000 return ((uchar) max_index);
13001 } else {
13002 return ((uchar) (max_index + 1));
13006 STATIC uchar
13007 AscAllocFreeQueue(
13008 PortAddr iop_base,
13009 uchar free_q_head
13012 ushort q_addr;
13013 uchar next_qp;
13014 uchar q_status;
13016 q_addr = ASC_QNO_TO_QADDR(free_q_head);
13017 q_status = (uchar) AscReadLramByte(iop_base,
13018 (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
13019 next_qp = AscReadLramByte(iop_base,
13020 (ushort) (q_addr + ASC_SCSIQ_B_FWD));
13021 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
13022 return (next_qp);
13024 return (ASC_QLINK_END);
13027 STATIC uchar
13028 AscAllocMultipleFreeQueue(
13029 PortAddr iop_base,
13030 uchar free_q_head,
13031 uchar n_free_q
13034 uchar i;
13036 for (i = 0; i < n_free_q; i++) {
13037 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
13038 == ASC_QLINK_END) {
13039 return (ASC_QLINK_END);
13042 return (free_q_head);
13045 STATIC int
13046 AscRiscHaltedAbortSRB(
13047 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
13048 ulong srb_ptr
13051 PortAddr iop_base;
13052 ushort q_addr;
13053 uchar q_no;
13054 ASC_QDONE_INFO scsiq_buf;
13055 ASC_QDONE_INFO *scsiq;
13056 ASC_ISR_CALLBACK asc_isr_callback;
13057 int last_int_level;
13059 iop_base = asc_dvc->iop_base;
13060 asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
13061 last_int_level = DvcEnterCritical();
13062 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
13063 for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
13064 q_no++) {
13065 q_addr = ASC_QNO_TO_QADDR(q_no);
13066 scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
13067 (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
13068 if (scsiq->d2.srb_ptr == srb_ptr) {
13069 _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
13070 if (((scsiq->q_status & QS_READY) != 0)
13071 && ((scsiq->q_status & QS_ABORTED) == 0)
13072 && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
13073 scsiq->q_status |= QS_ABORTED;
13074 scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
13075 AscWriteLramDWord(iop_base,
13076 (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
13077 0L);
13078 AscWriteLramByte(iop_base,
13079 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
13080 scsiq->q_status);
13081 (*asc_isr_callback) (asc_dvc, scsiq);
13082 return (1);
13086 DvcLeaveCritical(last_int_level);
13087 return (0);
13090 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
13091 STATIC int
13092 AscRiscHaltedAbortTIX(
13093 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
13094 uchar target_ix
13097 PortAddr iop_base;
13098 ushort q_addr;
13099 uchar q_no;
13100 ASC_QDONE_INFO scsiq_buf;
13101 ASC_QDONE_INFO *scsiq;
13102 ASC_ISR_CALLBACK asc_isr_callback;
13103 int last_int_level;
13105 iop_base = asc_dvc->iop_base;
13106 asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
13107 last_int_level = DvcEnterCritical();
13108 scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
13109 for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
13110 q_no++) {
13111 q_addr = ASC_QNO_TO_QADDR(q_no);
13112 _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
13113 if (((scsiq->q_status & QS_READY) != 0) &&
13114 ((scsiq->q_status & QS_ABORTED) == 0) &&
13115 ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
13116 if (scsiq->d2.target_ix == target_ix) {
13117 scsiq->q_status |= QS_ABORTED;
13118 scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
13119 AscWriteLramDWord(iop_base,
13120 (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
13121 0L);
13122 AscWriteLramByte(iop_base,
13123 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
13124 scsiq->q_status);
13125 (*asc_isr_callback) (asc_dvc, scsiq);
13129 DvcLeaveCritical(last_int_level);
13130 return (1);
13132 #endif /* version >= v1.3.89 */
13134 STATIC int
13135 AscHostReqRiscHalt(
13136 PortAddr iop_base
13139 int count = 0;
13140 int sta = 0;
13141 uchar saved_stop_code;
13143 if (AscIsChipHalted(iop_base))
13144 return (1);
13145 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
13146 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
13147 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
13149 do {
13150 if (AscIsChipHalted(iop_base)) {
13151 sta = 1;
13152 break;
13154 DvcSleepMilliSecond(100);
13155 } while (count++ < 20);
13156 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
13157 return (sta);
13160 STATIC int
13161 AscStopQueueExe(
13162 PortAddr iop_base
13165 int count = 0;
13167 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
13168 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
13169 ASC_STOP_REQ_RISC_STOP);
13170 do {
13171 if (
13172 AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
13173 ASC_STOP_ACK_RISC_STOP) {
13174 return (1);
13176 DvcSleepMilliSecond(100);
13177 } while (count++ < 20);
13179 return (0);
13182 STATIC int
13183 AscStartQueueExe(
13184 PortAddr iop_base
13187 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
13188 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
13190 return (1);
13193 STATIC int
13194 AscCleanUpBusyQueue(
13195 PortAddr iop_base
13198 int count;
13199 uchar stop_code;
13201 count = 0;
13202 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
13203 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
13204 ASC_STOP_CLEAN_UP_BUSY_Q);
13205 do {
13206 stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
13207 if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
13208 break;
13209 DvcSleepMilliSecond(100);
13210 } while (count++ < 20);
13212 return (1);
13215 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
13216 STATIC int
13217 AscCleanUpDiscQueue(
13218 PortAddr iop_base
13221 int count;
13222 uchar stop_code;
13224 count = 0;
13225 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
13226 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
13227 ASC_STOP_CLEAN_UP_DISC_Q);
13228 do {
13229 stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
13230 if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
13231 break;
13232 DvcSleepMilliSecond(100);
13233 } while (count++ < 20);
13235 return (1);
13237 #endif /* version >= v1.3.89 */
13239 STATIC int
13240 AscWaitTixISRDone(
13241 ASC_DVC_VAR asc_ptr_type * asc_dvc,
13242 uchar target_ix
13245 uchar cur_req;
13246 uchar tid_no;
13247 int i = 0;
13249 tid_no = ASC_TIX_TO_TID(target_ix);
13250 while (i++ < 10) {
13251 if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
13252 break;
13254 DvcSleepMilliSecond(1000L);
13255 if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
13256 break;
13259 return (1);
13262 STATIC int
13263 AscWaitISRDone(
13264 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
13267 int tid;
13269 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13270 AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
13272 return (1);
13275 STATIC ulong
13276 AscGetOnePhyAddr(
13277 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
13278 uchar * buf_addr,
13279 ulong buf_size
13282 ASC_MIN_SG_HEAD sg_head;
13284 sg_head.entry_cnt = ASC_MIN_SG_LIST;
13285 if (DvcGetSGList(asc_dvc, (uchar *) buf_addr,
13286 buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) {
13287 return (0L);
13289 if (sg_head.entry_cnt > 1) {
13290 return (0L);
13292 return ((ulong) sg_head.sg_list[0].addr);
13295 STATIC void
13296 DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
13298 udelay(micro_sec);
13301 STATIC void
13302 DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type * asc_dvc, ulong nano_sec)
13304 udelay((nano_sec + 999)/1000);
13307 ASC_INITFUNC(
13308 STATIC ulong,
13309 AscGetEisaProductID(
13310 PortAddr iop_base
13314 PortAddr eisa_iop;
13315 ushort product_id_high, product_id_low;
13316 ulong product_id;
13318 eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
13319 product_id_low = inpw(eisa_iop);
13320 product_id_high = inpw(eisa_iop + 2);
13321 product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
13322 return (product_id);
13325 ASC_INITFUNC(
13326 STATIC PortAddr,
13327 AscSearchIOPortAddrEISA(
13328 PortAddr iop_base
13332 ulong eisa_product_id;
13334 if (iop_base == 0) {
13335 iop_base = ASC_EISA_MIN_IOP_ADDR;
13336 } else {
13337 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
13338 return (0);
13339 if ((iop_base & 0x0050) == 0x0050) {
13340 iop_base += ASC_EISA_BIG_IOP_GAP;
13341 } else {
13342 iop_base += ASC_EISA_SMALL_IOP_GAP;
13345 while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
13346 eisa_product_id = AscGetEisaProductID(iop_base);
13347 if ((eisa_product_id == ASC_EISA_ID_740) ||
13348 (eisa_product_id == ASC_EISA_ID_750)) {
13349 if (AscFindSignature(iop_base)) {
13350 inpw(iop_base + 4);
13351 return (iop_base);
13354 if (iop_base == ASC_EISA_MAX_IOP_ADDR)
13355 return (0);
13356 if ((iop_base & 0x0050) == 0x0050) {
13357 iop_base += ASC_EISA_BIG_IOP_GAP;
13358 } else {
13359 iop_base += ASC_EISA_SMALL_IOP_GAP;
13362 return (0);
13365 STATIC int
13366 AscStartChip(
13367 PortAddr iop_base
13370 AscSetChipControl(iop_base, 0);
13371 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
13372 return (0);
13374 return (1);
13377 STATIC int
13378 AscStopChip(
13379 PortAddr iop_base
13382 uchar cc_val;
13384 cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
13385 AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
13386 AscSetChipIH(iop_base, INS_HALT);
13387 AscSetChipIH(iop_base, INS_RFLAG_WTM);
13388 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
13389 return (0);
13391 return (1);
13394 STATIC int
13395 AscIsChipHalted(
13396 PortAddr iop_base
13399 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
13400 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
13401 return (1);
13404 return (0);
13407 STATIC void
13408 AscSetChipIH(
13409 PortAddr iop_base,
13410 ushort ins_code
13413 AscSetBank(iop_base, 1);
13414 AscWriteChipIH(iop_base, ins_code);
13415 AscSetBank(iop_base, 0);
13416 return;
13419 STATIC void
13420 AscAckInterrupt(
13421 PortAddr iop_base
13424 uchar host_flag;
13425 uchar risc_flag;
13426 ushort loop;
13428 loop = 0;
13429 do {
13430 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
13431 if (loop++ > 0x7FFF) {
13432 break;
13434 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
13435 host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
13436 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
13437 (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
13438 AscSetChipStatus(iop_base, CIW_INT_ACK);
13439 loop = 0;
13440 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
13441 AscSetChipStatus(iop_base, CIW_INT_ACK);
13442 if (loop++ > 3) {
13443 break;
13446 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
13447 return;
13450 STATIC void
13451 AscDisableInterrupt(
13452 PortAddr iop_base
13455 ushort cfg;
13457 cfg = AscGetChipCfgLsw(iop_base);
13458 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
13459 return;
13462 STATIC void
13463 AscEnableInterrupt(
13464 PortAddr iop_base
13467 ushort cfg;
13469 cfg = AscGetChipCfgLsw(iop_base);
13470 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
13471 return;
13476 STATIC void
13477 AscSetBank(
13478 PortAddr iop_base,
13479 uchar bank
13482 uchar val;
13484 val = AscGetChipControl(iop_base) &
13485 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
13486 if (bank == 1) {
13487 val |= CC_BANK_ONE;
13488 } else if (bank == 2) {
13489 val |= CC_DIAG | CC_BANK_ONE;
13490 } else {
13491 val &= ~CC_BANK_ONE;
13493 AscSetChipControl(iop_base, val);
13494 return;
13497 STATIC int
13498 AscResetChipAndScsiBus(
13499 ASC_DVC_VAR *asc_dvc
13502 PortAddr iop_base;
13503 int i = 10;
13505 iop_base = asc_dvc->iop_base;
13506 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) && (i-- > 0))
13508 DvcSleepMilliSecond(100);
13510 AscStopChip(iop_base);
13511 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
13512 DvcDelayNanoSecond(asc_dvc, 60000);
13513 AscSetChipIH(iop_base, INS_RFLAG_WTM);
13514 AscSetChipIH(iop_base, INS_HALT);
13515 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
13516 AscSetChipControl(iop_base, CC_HALT);
13517 DvcSleepMilliSecond(200);
13518 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
13519 AscSetChipStatus(iop_base, 0);
13520 return (AscIsChipHalted(iop_base));
13523 ASC_INITFUNC(
13524 STATIC ulong,
13525 AscGetMaxDmaCount(
13526 ushort bus_type
13530 if (bus_type & ASC_IS_ISA)
13531 return (ASC_MAX_ISA_DMA_COUNT);
13532 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
13533 return (ASC_MAX_VL_DMA_COUNT);
13534 return (ASC_MAX_PCI_DMA_COUNT);
13537 ASC_INITFUNC(
13538 STATIC ushort,
13539 AscGetIsaDmaChannel(
13540 PortAddr iop_base
13544 ushort channel;
13546 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
13547 if (channel == 0x03)
13548 return (0);
13549 else if (channel == 0x00)
13550 return (7);
13551 return (channel + 4);
13554 ASC_INITFUNC(
13555 STATIC ushort,
13556 AscSetIsaDmaChannel(
13557 PortAddr iop_base,
13558 ushort dma_channel
13562 ushort cfg_lsw;
13563 uchar value;
13565 if ((dma_channel >= 5) && (dma_channel <= 7)) {
13566 if (dma_channel == 7)
13567 value = 0x00;
13568 else
13569 value = dma_channel - 4;
13570 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
13571 cfg_lsw |= value;
13572 AscSetChipCfgLsw(iop_base, cfg_lsw);
13573 return (AscGetIsaDmaChannel(iop_base));
13575 return (0);
13578 ASC_INITFUNC(
13579 STATIC uchar,
13580 AscSetIsaDmaSpeed(
13581 PortAddr iop_base,
13582 uchar speed_value
13586 speed_value &= 0x07;
13587 AscSetBank(iop_base, 1);
13588 AscWriteChipDmaSpeed(iop_base, speed_value);
13589 AscSetBank(iop_base, 0);
13590 return (AscGetIsaDmaSpeed(iop_base));
13593 ASC_INITFUNC(
13594 STATIC uchar,
13595 AscGetIsaDmaSpeed(
13596 PortAddr iop_base
13600 uchar speed_value;
13602 AscSetBank(iop_base, 1);
13603 speed_value = AscReadChipDmaSpeed(iop_base);
13604 speed_value &= 0x07;
13605 AscSetBank(iop_base, 0);
13606 return (speed_value);
13609 ASC_INITFUNC(
13610 STATIC ushort,
13611 AscReadPCIConfigWord(
13612 ASC_DVC_VAR asc_ptr_type *asc_dvc,
13613 ushort pci_config_offset)
13616 uchar lsb, msb;
13618 lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
13619 msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
13620 return ((ushort) ((msb << 8) | lsb));
13623 ASC_INITFUNC(
13624 STATIC ushort,
13625 AscInitGetConfig(
13626 ASC_DVC_VAR asc_ptr_type * asc_dvc
13630 ushort warn_code;
13631 PortAddr iop_base;
13632 ushort PCIDeviceID;
13633 ushort PCIVendorID;
13634 uchar PCIRevisionID;
13635 uchar prevCmdRegBits;
13637 warn_code = 0;
13638 iop_base = asc_dvc->iop_base;
13639 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
13640 if (asc_dvc->err_code != 0) {
13641 return (UW_ERR);
13643 if (asc_dvc->bus_type == ASC_IS_PCI) {
13644 PCIVendorID = AscReadPCIConfigWord(asc_dvc,
13645 AscPCIConfigVendorIDRegister);
13647 PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
13648 AscPCIConfigDeviceIDRegister);
13650 PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
13651 AscPCIConfigRevisionIDRegister);
13653 if (PCIVendorID != ASC_PCI_VENDORID) {
13654 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
13656 prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
13657 AscPCIConfigCommandRegister);
13659 if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
13660 AscPCICmdRegBits_IOMemBusMaster) {
13661 DvcWritePCIConfigByte(asc_dvc,
13662 AscPCIConfigCommandRegister,
13663 (prevCmdRegBits |
13664 AscPCICmdRegBits_IOMemBusMaster));
13666 if ((DvcReadPCIConfigByte(asc_dvc,
13667 AscPCIConfigCommandRegister)
13668 & AscPCICmdRegBits_IOMemBusMaster)
13669 != AscPCICmdRegBits_IOMemBusMaster) {
13670 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
13673 if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) ||
13674 (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) {
13675 DvcWritePCIConfigByte(asc_dvc,
13676 AscPCIConfigLatencyTimer, 0x00);
13677 if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer)
13678 != 0x00) {
13679 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
13681 } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) {
13682 if (DvcReadPCIConfigByte(asc_dvc,
13683 AscPCIConfigLatencyTimer) < 0x20) {
13684 DvcWritePCIConfigByte(asc_dvc,
13685 AscPCIConfigLatencyTimer, 0x20);
13687 if (DvcReadPCIConfigByte(asc_dvc,
13688 AscPCIConfigLatencyTimer) < 0x20) {
13689 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
13695 if (AscFindSignature(iop_base)) {
13696 warn_code |= AscInitAscDvcVar(asc_dvc);
13697 warn_code |= AscInitFromEEP(asc_dvc);
13698 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
13699 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
13700 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
13702 } else {
13703 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13705 return(warn_code);
13708 ASC_INITFUNC(
13709 STATIC ushort,
13710 AscInitSetConfig(
13711 ASC_DVC_VAR asc_ptr_type * asc_dvc
13715 ushort warn_code = 0;
13717 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
13718 if (asc_dvc->err_code != 0)
13719 return (UW_ERR);
13720 if (AscFindSignature(asc_dvc->iop_base)) {
13721 warn_code |= AscInitFromAscDvcVar(asc_dvc);
13722 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
13723 } else {
13724 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13726 return (warn_code);
13729 ASC_INITFUNC(
13730 STATIC ushort,
13731 AscInitFromAscDvcVar(
13732 ASC_DVC_VAR asc_ptr_type * asc_dvc
13736 PortAddr iop_base;
13737 ushort cfg_msw;
13738 ushort warn_code;
13739 ushort pci_device_id;
13741 iop_base = asc_dvc->iop_base;
13742 pci_device_id = asc_dvc->cfg->pci_device_id;
13743 warn_code = 0;
13744 cfg_msw = AscGetChipCfgMsw(iop_base);
13745 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
13746 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
13747 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
13748 AscSetChipCfgMsw(iop_base, cfg_msw);
13750 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
13751 asc_dvc->cfg->cmd_qng_enabled) {
13752 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
13753 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
13755 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
13756 warn_code |= ASC_WARN_AUTO_CONFIG;
13758 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
13759 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
13760 != asc_dvc->irq_no) {
13761 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
13764 if (asc_dvc->bus_type & ASC_IS_PCI) {
13765 cfg_msw &= 0xFFC0;
13766 AscSetChipCfgMsw(iop_base, cfg_msw);
13767 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
13768 } else {
13769 if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
13770 (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
13771 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
13772 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
13775 } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
13776 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
13777 == ASC_CHIP_VER_ASYN_BUG) {
13778 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
13781 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
13782 asc_dvc->cfg->chip_scsi_id) {
13783 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
13785 if (asc_dvc->bus_type & ASC_IS_ISA) {
13786 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
13787 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
13789 return (warn_code);
13792 ASC_INITFUNC(
13793 STATIC ushort,
13794 AscInitAsc1000Driver(
13795 ASC_DVC_VAR asc_ptr_type * asc_dvc
13799 ushort warn_code;
13800 PortAddr iop_base;
13802 iop_base = asc_dvc->iop_base;
13803 warn_code = 0;
13804 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
13805 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
13806 AscResetChipAndScsiBus(asc_dvc);
13807 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
13809 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
13810 if (asc_dvc->err_code != 0)
13811 return (UW_ERR);
13812 if (!AscFindSignature(asc_dvc->iop_base)) {
13813 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
13814 return (warn_code);
13816 AscDisableInterrupt(iop_base);
13817 warn_code |= AscInitLram(asc_dvc);
13818 if (asc_dvc->err_code != 0)
13819 return (UW_ERR);
13820 if (AscLoadMicroCode(iop_base, 0, (ushort *) _asc_mcode_buf,
13821 _asc_mcode_size) != _asc_mcode_chksum) {
13822 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
13823 return (warn_code);
13825 warn_code |= AscInitMicroCodeVar(asc_dvc);
13826 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
13827 AscEnableInterrupt(iop_base);
13828 return (warn_code);
13831 ASC_INITFUNC(
13832 STATIC ushort,
13833 AscInitAscDvcVar(
13834 ASC_DVC_VAR asc_ptr_type * asc_dvc
13838 int i;
13839 PortAddr iop_base;
13840 ushort warn_code;
13841 uchar chip_version;
13843 iop_base = asc_dvc->iop_base;
13844 warn_code = 0;
13845 asc_dvc->err_code = 0;
13846 if ((asc_dvc->bus_type &
13847 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
13848 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
13850 AscSetChipControl(iop_base, CC_HALT);
13851 AscSetChipStatus(iop_base, 0);
13852 asc_dvc->bug_fix_cntl = 0;
13853 asc_dvc->pci_fix_asyn_xfer = 0;
13854 asc_dvc->pci_fix_asyn_xfer_always = 0;
13855 asc_dvc->init_state = 0;
13856 asc_dvc->sdtr_done = 0;
13857 asc_dvc->cur_total_qng = 0;
13858 asc_dvc->is_in_int = 0;
13859 asc_dvc->in_critical_cnt = 0;
13860 asc_dvc->last_q_shortage = 0;
13861 asc_dvc->use_tagged_qng = 0;
13862 asc_dvc->no_scam = 0;
13863 asc_dvc->unit_not_ready = 0;
13864 asc_dvc->queue_full_or_busy = 0;
13865 asc_dvc->redo_scam = 0;
13866 asc_dvc->res2 = 0;
13867 asc_dvc->host_init_sdtr_index = 0;
13868 asc_dvc->res7 = 0;
13869 asc_dvc->res8 = 0;
13870 asc_dvc->cfg->can_tagged_qng = 0;
13871 asc_dvc->cfg->cmd_qng_enabled = 0;
13872 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
13873 asc_dvc->init_sdtr = 0;
13874 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
13875 asc_dvc->scsi_reset_wait = 3;
13876 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
13877 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
13878 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
13879 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
13880 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
13881 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
13882 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
13883 ASC_LIB_VERSION_MINOR;
13884 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
13885 asc_dvc->cfg->chip_version = chip_version;
13886 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
13887 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
13888 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
13889 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
13890 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
13891 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
13892 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
13893 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
13894 asc_dvc->max_sdtr_index = 7;
13895 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
13896 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
13897 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
13898 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
13899 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
13900 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
13901 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
13902 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
13903 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
13904 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
13905 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
13906 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
13907 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
13908 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
13909 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
13910 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
13911 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
13912 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
13913 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
13914 asc_dvc->max_sdtr_index = 15;
13915 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
13917 AscSetExtraControl(iop_base,
13918 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13919 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
13920 AscSetExtraControl(iop_base,
13921 (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
13924 if (asc_dvc->bus_type == ASC_IS_PCI) {
13925 AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13928 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
13929 if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
13930 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
13931 asc_dvc->bus_type = ASC_IS_ISAPNP;
13933 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
13934 asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
13936 for (i = 0; i <= ASC_MAX_TID; i++) {
13937 asc_dvc->cur_dvc_qng[i] = 0;
13938 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
13939 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L;
13940 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L;
13941 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
13943 return (warn_code);
13946 ASC_INITFUNC(
13947 STATIC ushort,
13948 AscInitFromEEP(
13949 ASC_DVC_VAR asc_ptr_type * asc_dvc
13953 ASCEEP_CONFIG eep_config_buf;
13954 ASCEEP_CONFIG *eep_config;
13955 PortAddr iop_base;
13956 ushort chksum;
13957 ushort warn_code;
13958 ushort cfg_msw, cfg_lsw;
13959 int i;
13960 int write_eep = 0;
13962 iop_base = asc_dvc->iop_base;
13963 warn_code = 0;
13964 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
13965 AscStopQueueExe(iop_base);
13966 if ((AscStopChip(iop_base) == FALSE) ||
13967 (AscGetChipScsiCtrl(iop_base) != 0)) {
13968 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
13969 AscResetChipAndScsiBus(asc_dvc);
13970 DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
13972 if (AscIsChipHalted(iop_base) == FALSE) {
13973 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13974 return (warn_code);
13976 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13977 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13978 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13979 return (warn_code);
13981 eep_config = (ASCEEP_CONFIG *) & eep_config_buf;
13982 cfg_msw = AscGetChipCfgMsw(iop_base);
13983 cfg_lsw = AscGetChipCfgLsw(iop_base);
13984 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
13985 cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
13986 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
13987 AscSetChipCfgMsw(iop_base, cfg_msw);
13989 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13990 if (chksum == 0) {
13991 chksum = 0xaa55;
13993 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
13994 warn_code |= ASC_WARN_AUTO_CONFIG;
13995 if (asc_dvc->cfg->chip_version == 3) {
13996 if (eep_config->cfg_lsw != cfg_lsw) {
13997 warn_code |= ASC_WARN_EEPROM_RECOVER;
13998 eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
14000 if (eep_config->cfg_msw != cfg_msw) {
14001 warn_code |= ASC_WARN_EEPROM_RECOVER;
14002 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
14006 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
14007 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
14008 if (chksum != eep_config->chksum) {
14009 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
14010 ASC_CHIP_VER_PCI_ULTRA_3050 )
14012 eep_config->init_sdtr = 0xFF;
14013 eep_config->disc_enable = 0xFF;
14014 eep_config->start_motor = 0xFF;
14015 eep_config->use_cmd_qng = 0;
14016 eep_config->max_total_qng = 0xF0;
14017 eep_config->max_tag_qng = 0x20;
14018 eep_config->cntl = 0xBFFF;
14019 eep_config->chip_scsi_id = 7;
14020 eep_config->no_scam = 0;
14021 eep_config->adapter_info[0] = 0;
14022 eep_config->adapter_info[1] = 0;
14023 eep_config->adapter_info[2] = 0;
14024 eep_config->adapter_info[3] = 0;
14025 eep_config->adapter_info[4] = 0;
14026 /* Indicate EEPROM-less board. */
14027 eep_config->adapter_info[5] = 0xBB;
14028 } else {
14029 write_eep = 1;
14030 warn_code |= ASC_WARN_EEPROM_CHKSUM;
14033 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
14034 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
14035 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
14036 asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
14037 asc_dvc->start_motor = eep_config->start_motor;
14038 asc_dvc->dvc_cntl = eep_config->cntl;
14039 asc_dvc->no_scam = eep_config->no_scam;
14040 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
14041 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
14042 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
14043 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
14044 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
14045 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
14046 if (!AscTestExternalLram(asc_dvc)) {
14047 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
14048 eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
14049 eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
14050 } else {
14051 eep_config->cfg_msw |= 0x0800;
14052 cfg_msw |= 0x0800;
14053 AscSetChipCfgMsw(iop_base, cfg_msw);
14054 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
14055 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
14057 } else {
14059 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
14060 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
14062 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
14063 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
14065 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
14066 eep_config->max_tag_qng = eep_config->max_total_qng;
14068 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
14069 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
14071 asc_dvc->max_total_qng = eep_config->max_total_qng;
14072 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
14073 eep_config->use_cmd_qng) {
14074 eep_config->disc_enable = eep_config->use_cmd_qng;
14075 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
14077 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
14078 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
14080 eep_config->chip_scsi_id &= ASC_MAX_TID;
14081 asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
14082 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
14083 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
14084 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
14087 for (i = 0; i <= ASC_MAX_TID; i++) {
14088 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
14089 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
14090 asc_dvc->cfg->sdtr_period_offset[i] =
14091 (uchar) (ASC_DEF_SDTR_OFFSET |
14092 (asc_dvc->host_init_sdtr_index << 4));
14094 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
14095 if (write_eep) {
14096 (void) AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
14098 return (warn_code);
14101 ASC_INITFUNC(
14102 STATIC ushort,
14103 AscInitMicroCodeVar(
14104 ASC_DVC_VAR asc_ptr_type * asc_dvc
14108 int i;
14109 ushort warn_code;
14110 PortAddr iop_base;
14111 ulong phy_addr;
14113 iop_base = asc_dvc->iop_base;
14114 warn_code = 0;
14115 for (i = 0; i <= ASC_MAX_TID; i++) {
14116 AscPutMCodeInitSDTRAtID(iop_base, i,
14117 asc_dvc->cfg->sdtr_period_offset[i]
14120 AscInitQLinkVar(asc_dvc);
14121 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
14122 asc_dvc->cfg->disc_enable);
14123 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
14124 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
14125 if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
14126 (uchar *) asc_dvc->cfg->overrun_buf,
14127 ASC_OVERRUN_BSIZE)) == 0L) {
14128 asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
14129 } else {
14130 phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
14131 AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
14132 AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
14133 ASC_OVERRUN_BSIZE - 8);
14135 asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
14136 (ushort) ASCV_MC_DATE_W);
14137 asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
14138 (ushort) ASCV_MC_VER_W);
14139 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
14140 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
14141 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
14142 return (warn_code);
14144 if (AscStartChip(iop_base) != 1) {
14145 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
14146 return (warn_code);
14148 return (warn_code);
14151 ASC_INITFUNC(
14152 STATIC int,
14153 AscTestExternalLram(
14154 ASC_DVC_VAR asc_ptr_type * asc_dvc
14158 PortAddr iop_base;
14159 ushort q_addr;
14160 ushort saved_word;
14161 int sta;
14163 iop_base = asc_dvc->iop_base;
14164 sta = 0;
14165 q_addr = ASC_QNO_TO_QADDR(241);
14166 saved_word = AscReadLramWord(iop_base, q_addr);
14167 AscSetChipLramAddr(iop_base, q_addr);
14168 AscSetChipLramData(iop_base, 0x55AA);
14169 DvcSleepMilliSecond(10);
14170 AscSetChipLramAddr(iop_base, q_addr);
14171 if (AscGetChipLramData(iop_base) == 0x55AA) {
14172 sta = 1;
14173 AscWriteLramWord(iop_base, q_addr, saved_word);
14175 return (sta);
14178 ASC_INITFUNC(
14179 STATIC int,
14180 AscWriteEEPCmdReg(
14181 PortAddr iop_base,
14182 uchar cmd_reg
14186 uchar read_back;
14187 int retry;
14189 retry = 0;
14190 while (TRUE) {
14191 AscSetChipEEPCmd(iop_base, cmd_reg);
14192 DvcSleepMilliSecond(1);
14193 read_back = AscGetChipEEPCmd(iop_base);
14194 if (read_back == cmd_reg) {
14195 return (1);
14197 if (retry++ > ASC_EEP_MAX_RETRY) {
14198 return (0);
14203 ASC_INITFUNC(
14204 STATIC int,
14205 AscWriteEEPDataReg(
14206 PortAddr iop_base,
14207 ushort data_reg
14211 ushort read_back;
14212 int retry;
14214 retry = 0;
14215 while (TRUE) {
14216 AscSetChipEEPData(iop_base, data_reg);
14217 DvcSleepMilliSecond(1);
14218 read_back = AscGetChipEEPData(iop_base);
14219 if (read_back == data_reg) {
14220 return (1);
14222 if (retry++ > ASC_EEP_MAX_RETRY) {
14223 return (0);
14228 ASC_INITFUNC(
14229 STATIC void,
14230 AscWaitEEPRead(
14231 void
14235 DvcSleepMilliSecond(1);
14236 return;
14239 ASC_INITFUNC(
14240 STATIC void,
14241 AscWaitEEPWrite(
14242 void
14246 DvcSleepMilliSecond(20);
14247 return;
14250 ASC_INITFUNC(
14251 STATIC ushort,
14252 AscReadEEPWord(
14253 PortAddr iop_base,
14254 uchar addr
14258 ushort read_wval;
14259 uchar cmd_reg;
14261 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
14262 AscWaitEEPRead();
14263 cmd_reg = addr | ASC_EEP_CMD_READ;
14264 AscWriteEEPCmdReg(iop_base, cmd_reg);
14265 AscWaitEEPRead();
14266 read_wval = AscGetChipEEPData(iop_base);
14267 AscWaitEEPRead();
14268 return (read_wval);
14271 ASC_INITFUNC(
14272 STATIC ushort,
14273 AscWriteEEPWord(
14274 PortAddr iop_base,
14275 uchar addr,
14276 ushort word_val
14280 ushort read_wval;
14282 read_wval = AscReadEEPWord(iop_base, addr);
14283 if (read_wval != word_val) {
14284 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
14285 AscWaitEEPRead();
14286 AscWriteEEPDataReg(iop_base, word_val);
14287 AscWaitEEPRead();
14288 AscWriteEEPCmdReg(iop_base,
14289 (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
14290 AscWaitEEPWrite();
14291 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
14292 AscWaitEEPRead();
14293 return (AscReadEEPWord(iop_base, addr));
14295 return (read_wval);
14298 ASC_INITFUNC(
14299 STATIC ushort,
14300 AscGetEEPConfig(
14301 PortAddr iop_base,
14302 ASCEEP_CONFIG * cfg_buf, ushort bus_type
14306 ushort wval;
14307 ushort sum;
14308 ushort *wbuf;
14309 int cfg_beg;
14310 int cfg_end;
14311 int s_addr;
14312 int isa_pnp_wsize;
14314 wbuf = (ushort *) cfg_buf;
14315 sum = 0;
14316 isa_pnp_wsize = 0;
14317 for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
14318 wval = AscReadEEPWord(iop_base, (uchar) s_addr);
14319 sum += wval;
14320 *wbuf = wval;
14322 if (bus_type & ASC_IS_VL) {
14323 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
14324 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
14325 } else {
14326 cfg_beg = ASC_EEP_DVC_CFG_BEG;
14327 cfg_end = ASC_EEP_MAX_DVC_ADDR;
14329 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
14330 s_addr++, wbuf++) {
14331 wval = AscReadEEPWord(iop_base, (uchar) s_addr);
14332 sum += wval;
14333 *wbuf = wval;
14335 *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
14336 return (sum);
14339 ASC_INITFUNC(
14340 STATIC int,
14341 AscSetEEPConfigOnce(
14342 PortAddr iop_base,
14343 ASCEEP_CONFIG * cfg_buf, ushort bus_type
14347 int n_error;
14348 ushort *wbuf;
14349 ushort sum;
14350 int s_addr;
14351 int cfg_beg;
14352 int cfg_end;
14354 wbuf = (ushort *) cfg_buf;
14355 n_error = 0;
14356 sum = 0;
14357 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
14358 sum += *wbuf;
14359 if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
14360 n_error++;
14363 if (bus_type & ASC_IS_VL) {
14364 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
14365 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
14366 } else {
14367 cfg_beg = ASC_EEP_DVC_CFG_BEG;
14368 cfg_end = ASC_EEP_MAX_DVC_ADDR;
14370 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
14371 s_addr++, wbuf++) {
14372 sum += *wbuf;
14373 if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
14374 n_error++;
14377 *wbuf = sum;
14378 if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
14379 n_error++;
14381 wbuf = (ushort *) cfg_buf;
14382 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
14383 if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
14384 n_error++;
14387 for (s_addr = cfg_beg; s_addr <= cfg_end;
14388 s_addr++, wbuf++) {
14389 if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
14390 n_error++;
14393 return (n_error);
14396 ASC_INITFUNC(
14397 STATIC int,
14398 AscSetEEPConfig(
14399 PortAddr iop_base,
14400 ASCEEP_CONFIG * cfg_buf, ushort bus_type
14404 int retry;
14405 int n_error;
14407 retry = 0;
14408 while (TRUE) {
14409 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
14410 bus_type)) == 0) {
14411 break;
14413 if (++retry > ASC_EEP_MAX_RETRY) {
14414 break;
14417 return (n_error);
14420 STATIC void
14421 AscAsyncFix(
14422 ASC_DVC_VAR asc_ptr_type *asc_dvc,
14423 uchar tid_no,
14424 ASC_SCSI_INQUIRY *inq)
14426 uchar dvc_type;
14427 ASC_SCSI_BIT_ID_TYPE tid_bits;
14429 dvc_type = inq->byte0.peri_dvc_type;
14430 tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
14432 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN)
14434 if (!(asc_dvc->init_sdtr & tid_bits))
14436 if ((dvc_type == SCSI_TYPE_CDROM) &&
14437 (AscCompareString((uchar *) inq->vendor_id,
14438 (uchar *) "HP ", 3) == 0))
14440 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
14442 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
14443 if ((dvc_type == SCSI_TYPE_PROC) ||
14444 (dvc_type == SCSI_TYPE_SCANNER) ||
14445 (dvc_type == SCSI_TYPE_CDROM) ||
14446 (dvc_type == SCSI_TYPE_SASD))
14448 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
14451 if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
14453 AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
14454 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
14458 return;
14461 STATIC int
14462 AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
14464 if ((inq->add_len >= 32) &&
14465 (AscCompareString((uchar *) inq->vendor_id,
14466 (uchar *) "QUANTUM XP34301", 15) == 0) &&
14467 (AscCompareString((uchar *) inq->product_rev_level,
14468 (uchar *) "1071", 4) == 0))
14470 return 0;
14472 return 1;
14475 STATIC void
14476 AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc,
14477 uchar tid_no, ASC_SCSI_INQUIRY *inq)
14479 ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
14480 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
14482 orig_init_sdtr = asc_dvc->init_sdtr;
14483 orig_use_tagged_qng = asc_dvc->use_tagged_qng;
14485 asc_dvc->init_sdtr &= ~tid_bit;
14486 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
14487 asc_dvc->use_tagged_qng &= ~tid_bit;
14489 if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) {
14490 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) {
14491 asc_dvc->init_sdtr |= tid_bit;
14493 if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) {
14494 if (AscTagQueuingSafe(inq)) {
14495 asc_dvc->use_tagged_qng |= tid_bit;
14496 asc_dvc->cfg->can_tagged_qng |= tid_bit;
14500 if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
14501 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
14502 asc_dvc->cfg->disc_enable);
14503 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
14504 asc_dvc->use_tagged_qng);
14505 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
14506 asc_dvc->cfg->can_tagged_qng);
14508 asc_dvc->max_dvc_qng[tid_no] =
14509 asc_dvc->cfg->max_tag_qng[tid_no];
14510 AscWriteLramByte(asc_dvc->iop_base,
14511 (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no),
14512 asc_dvc->max_dvc_qng[tid_no]);
14514 if (orig_init_sdtr != asc_dvc->init_sdtr) {
14515 AscAsyncFix(asc_dvc, tid_no, inq);
14517 return;
14520 STATIC int
14521 AscCompareString(
14522 ruchar * str1,
14523 ruchar * str2,
14524 int len
14527 int i;
14528 int diff;
14530 for (i = 0; i < len; i++) {
14531 diff = (int) (str1[i] - str2[i]);
14532 if (diff != 0)
14533 return (diff);
14535 return (0);
14538 STATIC uchar
14539 AscReadLramByte(
14540 PortAddr iop_base,
14541 ushort addr
14544 uchar byte_data;
14545 ushort word_data;
14547 if (isodd_word(addr)) {
14548 AscSetChipLramAddr(iop_base, addr - 1);
14549 word_data = AscGetChipLramData(iop_base);
14550 byte_data = (uchar) ((word_data >> 8) & 0xFF);
14551 } else {
14552 AscSetChipLramAddr(iop_base, addr);
14553 word_data = AscGetChipLramData(iop_base);
14554 byte_data = (uchar) (word_data & 0xFF);
14556 return (byte_data);
14559 STATIC ushort
14560 AscReadLramWord(
14561 PortAddr iop_base,
14562 ushort addr
14565 ushort word_data;
14567 AscSetChipLramAddr(iop_base, addr);
14568 word_data = AscGetChipLramData(iop_base);
14569 return (word_data);
14572 STATIC ulong
14573 AscReadLramDWord(
14574 PortAddr iop_base,
14575 ushort addr
14578 ushort val_low, val_high;
14579 ulong dword_data;
14581 AscSetChipLramAddr(iop_base, addr);
14582 val_low = AscGetChipLramData(iop_base);
14583 val_high = AscGetChipLramData(iop_base);
14584 dword_data = ((ulong) val_high << 16) | (ulong) val_low;
14585 return (dword_data);
14588 STATIC void
14589 AscWriteLramWord(
14590 PortAddr iop_base,
14591 ushort addr,
14592 ushort word_val
14595 AscSetChipLramAddr(iop_base, addr);
14596 AscSetChipLramData(iop_base, word_val);
14597 return;
14600 STATIC void
14601 AscWriteLramDWord(
14602 PortAddr iop_base,
14603 ushort addr,
14604 ulong dword_val
14607 ushort word_val;
14609 AscSetChipLramAddr(iop_base, addr);
14610 word_val = (ushort) dword_val;
14611 AscSetChipLramData(iop_base, word_val);
14612 word_val = (ushort) (dword_val >> 16);
14613 AscSetChipLramData(iop_base, word_val);
14614 return;
14617 STATIC void
14618 AscWriteLramByte(
14619 PortAddr iop_base,
14620 ushort addr,
14621 uchar byte_val
14624 ushort word_data;
14626 if (isodd_word(addr)) {
14627 addr--;
14628 word_data = AscReadLramWord(iop_base, addr);
14629 word_data &= 0x00FF;
14630 word_data |= (((ushort) byte_val << 8) & 0xFF00);
14631 } else {
14632 word_data = AscReadLramWord(iop_base, addr);
14633 word_data &= 0xFF00;
14634 word_data |= ((ushort) byte_val & 0x00FF);
14636 AscWriteLramWord(iop_base, addr, word_data);
14637 return;
14640 STATIC void
14641 AscMemWordCopyToLram(
14642 PortAddr iop_base,
14643 ushort s_addr,
14644 ushort * s_buffer,
14645 int words
14648 AscSetChipLramAddr(iop_base, s_addr);
14649 DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
14650 return;
14653 STATIC void
14654 AscMemDWordCopyToLram(
14655 PortAddr iop_base,
14656 ushort s_addr,
14657 ulong * s_buffer,
14658 int dwords
14661 AscSetChipLramAddr(iop_base, s_addr);
14662 DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
14663 return;
14666 STATIC void
14667 AscMemWordCopyFromLram(
14668 PortAddr iop_base,
14669 ushort s_addr,
14670 ushort * d_buffer,
14671 int words
14674 AscSetChipLramAddr(iop_base, s_addr);
14675 DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
14676 return;
14679 STATIC ulong
14680 AscMemSumLramWord(
14681 PortAddr iop_base,
14682 ushort s_addr,
14683 rint words
14686 ulong sum;
14687 int i;
14689 sum = 0L;
14690 for (i = 0; i < words; i++, s_addr += 2) {
14691 sum += AscReadLramWord(iop_base, s_addr);
14693 return (sum);
14696 STATIC void
14697 AscMemWordSetLram(
14698 PortAddr iop_base,
14699 ushort s_addr,
14700 ushort set_wval,
14701 rint words
14704 rint i;
14706 AscSetChipLramAddr(iop_base, s_addr);
14707 for (i = 0; i < words; i++) {
14708 AscSetChipLramData(iop_base, set_wval);
14710 return;
14715 * --- Adv Library Functions
14718 /* a_mcode.h */
14719 STATIC unsigned char _adv_asc3550_buf[] = {
14720 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x00, 0xfc, 0x48, 0xe4, 0x01, 0x00, 0x01, 0xf6,
14721 0x00, 0xf6, 0x18, 0xe4, 0x0a, 0x19, 0x18, 0x80, 0x02, 0x00, 0xff, 0xff, 0x03, 0xf6, 0x00, 0xfa,
14722 0xff, 0x00, 0x82, 0xe7, 0x9e, 0xe7, 0x01, 0xfa, 0x06, 0x0e, 0x09, 0xe7, 0x00, 0xea, 0x01, 0xe6,
14723 0x03, 0x00, 0x08, 0x00, 0x18, 0xf4, 0x55, 0xf0, 0x3e, 0x01, 0x3e, 0x57, 0x04, 0x00, 0x1e, 0xf0,
14724 0x85, 0xf0, 0x00, 0xe6, 0x00, 0xec, 0x32, 0xf0, 0x86, 0xf0, 0xa4, 0x0c, 0xd0, 0x01, 0xd5, 0xf0,
14725 0xf6, 0x18, 0x38, 0x54, 0x98, 0x57, 0xbc, 0x00, 0xb1, 0xf0, 0xb4, 0x00, 0x01, 0xfc, 0x02, 0x13,
14726 0x03, 0xfc, 0x9e, 0x0c, 0x00, 0x57, 0x01, 0xf0, 0x03, 0xe6, 0x0c, 0x1c, 0x10, 0x00, 0x18, 0x40,
14727 0x30, 0x12, 0x3e, 0x1c, 0xbd, 0x00, 0xe0, 0x00, 0x02, 0x48, 0x02, 0x80, 0x3c, 0x00, 0x4e, 0x01,
14728 0x66, 0x15, 0x6c, 0x01, 0x6e, 0x01, 0xbb, 0x00, 0xda, 0x12, 0x00, 0x4e, 0x01, 0x01, 0x01, 0xea,
14729 0x08, 0x12, 0x30, 0xe4, 0x6a, 0x0f, 0xa8, 0x0c, 0xae, 0x0f, 0xb6, 0x00, 0xb9, 0x54, 0x00, 0x80,
14730 0x04, 0x12, 0x06, 0xf7, 0x24, 0x01, 0x28, 0x01, 0x32, 0x00, 0x3c, 0x01, 0x3c, 0x56, 0x3e, 0x00,
14731 0x4b, 0xe4, 0x4c, 0x1c, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01,
14732 0x78, 0x01, 0x00, 0x01, 0x02, 0xee, 0x02, 0xfc, 0x03, 0x58, 0x03, 0xf7, 0x04, 0x80, 0x05, 0xfc,
14733 0x08, 0x44, 0x09, 0xf0, 0x0a, 0x15, 0x10, 0x44, 0x1b, 0x80, 0x20, 0x01, 0x38, 0x1c, 0x40, 0x00,
14734 0x4b, 0xf4, 0x4e, 0x1c, 0x5b, 0xf0, 0x5d, 0xf0, 0x80, 0x00, 0xaa, 0x00, 0xaa, 0x14, 0xb6, 0x08,
14735 0xb8, 0x0f, 0xbb, 0x55, 0xbd, 0x56, 0xbe, 0x00, 0xc0, 0x00, 0x00, 0x4c, 0x00, 0xdc, 0x02, 0x4a,
14736 0x05, 0xf0, 0x05, 0xf8, 0x06, 0x13, 0x08, 0x13, 0x0c, 0x00, 0x0e, 0x47, 0x0e, 0xf7, 0x0f, 0x00,
14737 0x19, 0x00, 0x20, 0x00, 0x2a, 0x01, 0x32, 0x1c, 0x36, 0x00, 0x38, 0x12, 0x3c, 0x0b, 0x45, 0x5a,
14738 0x56, 0x14, 0x59, 0xf0, 0x62, 0x0a, 0x69, 0x08, 0x83, 0x59, 0xae, 0x17, 0xb8, 0xf0, 0xba, 0x0f,
14739 0xba, 0x17, 0xf0, 0x00, 0xf6, 0x0d, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0x10, 0x04, 0xea, 0x04, 0xf6,
14740 0x04, 0xfc, 0x05, 0x00, 0x06, 0x00, 0x06, 0x12, 0x0a, 0x10, 0x0b, 0xf0, 0x0c, 0xf0, 0x12, 0x10,
14741 0x30, 0x1c, 0x33, 0x00, 0x34, 0x00, 0x38, 0x44, 0x40, 0x5c, 0x4a, 0xe4, 0x5a, 0x14, 0x62, 0x1a,
14742 0x64, 0x0a, 0x68, 0x08, 0x68, 0x54, 0x83, 0x55, 0x83, 0x5a, 0x91, 0x44, 0x98, 0x12, 0x9a, 0x16,
14743 0xa4, 0x00, 0xb0, 0x57, 0xb5, 0x00, 0xba, 0x00, 0xce, 0x45, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
14744 0xec, 0x0d, 0x00, 0x54, 0x01, 0x48, 0x01, 0x58, 0x02, 0x10, 0x02, 0xe6, 0x03, 0xa1, 0x04, 0x13,
14745 0x05, 0xe6, 0x06, 0x0b, 0x06, 0x83, 0x06, 0xf0, 0x07, 0x00, 0x0a, 0x00, 0x0a, 0x12, 0x0a, 0xf0,
14746 0x0c, 0x04, 0x0c, 0x10, 0x0c, 0x12, 0x0e, 0x13, 0x10, 0x10, 0x12, 0x1c, 0x17, 0x00, 0x18, 0x0e,
14747 0x19, 0xe4, 0x1a, 0x10, 0x1c, 0x00, 0x1c, 0x12, 0x1c, 0x14, 0x1d, 0xf7, 0x1e, 0x13, 0x20, 0x1c,
14748 0x20, 0xe7, 0x22, 0x01, 0x26, 0x01, 0x2a, 0x12, 0x30, 0xe7, 0x41, 0x58, 0x43, 0x48, 0x44, 0x55,
14749 0x46, 0x1c, 0x4e, 0xe4, 0x5c, 0xf0, 0x72, 0x02, 0x74, 0x03, 0x77, 0x57, 0x88, 0x12, 0x89, 0x48,
14750 0x92, 0x13, 0x99, 0x00, 0x9b, 0x00, 0x9c, 0x32, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x12, 0xb9, 0x00,
14751 0xba, 0x06, 0xbf, 0x57, 0xc0, 0x01, 0xc0, 0x08, 0xc2, 0x01, 0xfe, 0x9c, 0xf0, 0x26, 0x02, 0xfe,
14752 0xc6, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xfc, 0xfe, 0x18, 0x19, 0x00, 0xfa, 0xfe, 0x80, 0x01, 0xff,
14753 0x03, 0x00, 0x00, 0x2f, 0xfe, 0x01, 0x05, 0xff, 0x40, 0x00, 0x00, 0x0d, 0xff, 0x09, 0x00, 0x00,
14754 0xff, 0x08, 0x01, 0x01, 0xff, 0x10, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff,
14755 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04,
14756 0xf7, 0xfa, 0x35, 0x51, 0x0c, 0x01, 0xfe, 0xb6, 0x0e, 0xfe, 0x04, 0xf7, 0xfa, 0x51, 0x0c, 0x1d,
14757 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x20, 0xf0, 0xd0, 0x04, 0x55, 0x50, 0x02, 0xfe,
14758 0xe2, 0x0c, 0x01, 0xfe, 0x42, 0x0d, 0xfe, 0xe9, 0x12, 0x02, 0xfe, 0x04, 0x03, 0xfe, 0x28, 0x1c,
14759 0x04, 0xfe, 0xa6, 0x00, 0xfe, 0xdd, 0x12, 0x4e, 0x13, 0xfe, 0xa6, 0x00, 0xc3, 0xfe, 0x48, 0xf0,
14760 0xfe, 0x7c, 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0x96, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xb4, 0x02, 0xfe,
14761 0x46, 0xf0, 0xfe, 0x46, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x3a,
14762 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x3e, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x42, 0x02, 0x07, 0x0c, 0x9d,
14763 0x07, 0x06, 0x13, 0xb8, 0x02, 0x26, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02, 0x1c, 0xfe,
14764 0xed, 0x10, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x0e, 0x17, 0xfe, 0xe7, 0x10, 0xfe,
14765 0x06, 0xfc, 0xf5, 0x0e, 0x7b, 0x01, 0xc0, 0x02, 0x26, 0x17, 0x54, 0x47, 0xba, 0x01, 0xfe, 0x2c,
14766 0x0f, 0x0e, 0x7b, 0x01, 0x9a, 0xfe, 0xbd, 0x10, 0x0e, 0x7b, 0x01, 0x9a, 0xfe, 0xad, 0x10, 0xfe,
14767 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x07, 0x06, 0x13, 0xb8, 0x35, 0x1f, 0x26, 0xfe, 0x3d, 0xf0, 0xfe,
14768 0xf8, 0x01, 0x27, 0xfe, 0x8a, 0x02, 0xfe, 0x5a, 0x1c, 0xd5, 0xfe, 0x14, 0x1c, 0x17, 0xfe, 0x30,
14769 0x00, 0x47, 0xba, 0x01, 0xfe, 0x1c, 0x0f, 0x07, 0x06, 0x13, 0xb8, 0x02, 0xfc, 0x22, 0x2b, 0x05,
14770 0x10, 0x2f, 0xfe, 0x69, 0x10, 0x07, 0x06, 0x13, 0xb8, 0xfe, 0x04, 0xec, 0x2b, 0x08, 0x2b, 0x07,
14771 0x3a, 0x1d, 0x01, 0x40, 0x7f, 0xfe, 0x05, 0xf6, 0xf5, 0x01, 0xfe, 0x40, 0x16, 0x0b, 0x49, 0x89,
14772 0x37, 0x11, 0x43, 0x1d, 0xca, 0x08, 0x1c, 0x07, 0x3f, 0x01, 0x6a, 0x02, 0x26, 0x0e, 0x3b, 0x01,
14773 0x14, 0x05, 0x10, 0xd3, 0x08, 0x1c, 0x07, 0x3f, 0x01, 0x76, 0xfe, 0x28, 0x10, 0x0e, 0xbd, 0x01,
14774 0x14, 0xe5, 0x0e, 0x7c, 0x01, 0x14, 0xfe, 0x49, 0x54, 0x72, 0xfe, 0x12, 0x03, 0x08, 0x1c, 0x07,
14775 0x3f, 0x01, 0x6a, 0x02, 0x26, 0x35, 0x7f, 0xfe, 0x02, 0xe8, 0x2d, 0xf9, 0xfe, 0x9e, 0x43, 0xed,
14776 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xd0, 0xfe, 0x40, 0x1c, 0x1f, 0xec, 0xfe, 0x26, 0xf0, 0xfe,
14777 0x70, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x5e, 0x03, 0xfe, 0x11, 0xf0, 0xd0, 0xfe, 0x0e, 0x10, 0xfe,
14778 0x9f, 0xf0, 0xfe, 0x7e, 0x03, 0xe8, 0x12, 0xfe, 0x11, 0x00, 0x02, 0x4b, 0x35, 0xfe, 0x48, 0x1c,
14779 0xe8, 0x1f, 0xec, 0x33, 0xec, 0xfe, 0x82, 0xf0, 0xfe, 0x84, 0x03, 0x29, 0x22, 0xbb, 0x68, 0x16,
14780 0xbb, 0x0e, 0x7c, 0x01, 0x14, 0x68, 0x7d, 0x08, 0x1c, 0x07, 0x3f, 0x01, 0x40, 0x11, 0x3b, 0x08,
14781 0x3b, 0x07, 0x99, 0x01, 0x6a, 0xf3, 0x11, 0xfe, 0xe4, 0x00, 0x2c, 0xfe, 0xca, 0x03, 0x1f, 0x31,
14782 0x20, 0xfe, 0xda, 0x03, 0x01, 0x4a, 0xcb, 0xfe, 0xea, 0x03, 0x69, 0x8e, 0xcf, 0xfe, 0xaa, 0x06,
14783 0x02, 0x25, 0x04, 0x7b, 0x2a, 0x1b, 0xfe, 0x1c, 0x05, 0x17, 0x84, 0x01, 0x38, 0x01, 0x95, 0x01,
14784 0x98, 0x33, 0xfe, 0x5c, 0x02, 0x02, 0xeb, 0xe8, 0x35, 0x51, 0x18, 0xfe, 0x67, 0x1b, 0xf9, 0xed,
14785 0xfe, 0x48, 0x1c, 0x8b, 0x01, 0xee, 0xa8, 0xfe, 0x96, 0xf0, 0xfe, 0x24, 0x04, 0x2c, 0xfe, 0x28,
14786 0x04, 0x33, 0x26, 0x0e, 0x3b, 0x01, 0x14, 0x05, 0x10, 0x1b, 0xfe, 0x08, 0x05, 0x3c, 0x92, 0x9e,
14787 0x2d, 0x81, 0x6d, 0x1f, 0x31, 0x20, 0x25, 0x04, 0x7b, 0x2a, 0xfe, 0x10, 0x12, 0x17, 0x84, 0x01,
14788 0x38, 0x33, 0xfe, 0x5c, 0x02, 0x02, 0xeb, 0x30, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x5e,
14789 0x12, 0x0b, 0x09, 0x06, 0xfe, 0x56, 0x12, 0x23, 0x28, 0x93, 0x01, 0x0a, 0x81, 0x6d, 0x20, 0xfe,
14790 0xd8, 0x04, 0x23, 0x28, 0x93, 0x01, 0x0a, 0x20, 0x25, 0x23, 0x28, 0xb1, 0xfe, 0x4c, 0x44, 0xfe,
14791 0x32, 0x12, 0x56, 0xfe, 0x44, 0x48, 0x08, 0xd6, 0xfe, 0x4c, 0x54, 0x72, 0xfe, 0x08, 0x05, 0x7f,
14792 0x9e, 0x2d, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x48, 0x13, 0x3d, 0x05, 0xfe, 0xcc, 0x00,
14793 0xfe, 0x40, 0x13, 0x0b, 0x09, 0x06, 0x8d, 0xfe, 0x06, 0x10, 0x23, 0x28, 0xb1, 0x0b, 0x09, 0x36,
14794 0xdb, 0x17, 0xa2, 0x0b, 0x09, 0x06, 0x50, 0x17, 0xfe, 0x0d, 0x00, 0x01, 0x38, 0x33, 0xfe, 0x86,
14795 0x0c, 0x02, 0x25, 0x39, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xac, 0x03, 0x17, 0xa2, 0x01,
14796 0x38, 0x33, 0x26, 0x1f, 0x26, 0x02, 0xfe, 0x10, 0x05, 0xfe, 0x42, 0x5b, 0x51, 0x18, 0xfe, 0x46,
14797 0x59, 0xf9, 0xed, 0x17, 0x74, 0xfe, 0x07, 0x80, 0xfe, 0x31, 0x44, 0x0b, 0x09, 0x0c, 0xfe, 0x78,
14798 0x13, 0xfe, 0x20, 0x80, 0x05, 0x18, 0xfe, 0x70, 0x12, 0x6c, 0x09, 0x06, 0xfe, 0x60, 0x13, 0x04,
14799 0xfe, 0xa2, 0x00, 0x2a, 0x1b, 0xfe, 0xa8, 0x05, 0xfe, 0x31, 0xe4, 0x6f, 0x6c, 0x09, 0x0c, 0xfe,
14800 0x4a, 0x13, 0x04, 0xfe, 0xa0, 0x00, 0x2a, 0xfe, 0x42, 0x12, 0x59, 0x2c, 0xfe, 0x68, 0x05, 0x1f,
14801 0x31, 0xef, 0x01, 0x0a, 0x24, 0xfe, 0xc0, 0x05, 0x11, 0xfe, 0xe3, 0x00, 0x29, 0x6c, 0xfe, 0x4a,
14802 0xf0, 0xfe, 0x92, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0x8c, 0x05, 0xd1, 0x21, 0xfe, 0x21, 0x00, 0xa4,
14803 0x21, 0xfe, 0x22, 0x00, 0x9d, 0x21, 0x89, 0xfe, 0x09, 0x48, 0x01, 0x0a, 0x24, 0xfe, 0xc0, 0x05,
14804 0xfe, 0xe2, 0x08, 0x6c, 0x09, 0xda, 0x50, 0x01, 0xb6, 0x21, 0x06, 0x16, 0xe2, 0x47, 0xfe, 0x27,
14805 0x01, 0x0b, 0x09, 0x36, 0xe3, 0x4e, 0x01, 0xae, 0x17, 0xa2, 0x0b, 0x09, 0x06, 0x50, 0x17, 0xfe,
14806 0x0d, 0x00, 0x01, 0x38, 0x01, 0x95, 0x01, 0x98, 0x33, 0xfe, 0x86, 0x0c, 0x02, 0x25, 0x04, 0xfe,
14807 0x9c, 0x00, 0x2a, 0xfe, 0x3e, 0x12, 0x04, 0x52, 0x2a, 0xfe, 0x36, 0x13, 0x4e, 0x01, 0xae, 0x24,
14808 0xfe, 0x38, 0x06, 0x0e, 0x06, 0x6c, 0x09, 0x19, 0xfe, 0x02, 0x12, 0x79, 0x01, 0xfe, 0xf0, 0x13,
14809 0x20, 0xfe, 0x2e, 0x06, 0x11, 0xbe, 0x01, 0x4a, 0x11, 0xfe, 0xe5, 0x00, 0x04, 0x52, 0xb9, 0x0f,
14810 0x52, 0x04, 0xf4, 0x2a, 0xfe, 0x62, 0x12, 0x04, 0x4d, 0x2a, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x60,
14811 0x18, 0x01, 0xfe, 0xb2, 0x18, 0xe6, 0xc8, 0x19, 0x08, 0x61, 0xff, 0x02, 0x00, 0x57, 0x64, 0x7e,
14812 0x1a, 0x4f, 0xc7, 0xc8, 0x87, 0x4e, 0x01, 0xae, 0x24, 0xfe, 0xa2, 0x06, 0x6c, 0x09, 0x1e, 0xa3,
14813 0x7a, 0x0e, 0x54, 0x01, 0xfe, 0x1e, 0x14, 0x20, 0xfe, 0x98, 0x06, 0x11, 0xbe, 0x01, 0x4a, 0x11,
14814 0xfe, 0xe5, 0x00, 0x04, 0x4d, 0xb9, 0x0f, 0x4d, 0x07, 0x06, 0x01, 0xae, 0xf3, 0x71, 0x8b, 0x01,
14815 0xee, 0xa8, 0x11, 0xfe, 0xe2, 0x00, 0x2c, 0xf8, 0x1f, 0x31, 0xcf, 0xfe, 0xd6, 0x06, 0x80, 0xfe,
14816 0x74, 0x07, 0xcb, 0xfe, 0x7c, 0x07, 0x69, 0x8e, 0x02, 0x25, 0x0b, 0x09, 0x0c, 0xfe, 0x2e, 0x12,
14817 0x15, 0x18, 0x01, 0x0a, 0x15, 0x00, 0x01, 0x0a, 0x15, 0x00, 0x01, 0x0a, 0x15, 0x00, 0x01, 0x0a,
14818 0xfe, 0x99, 0xa4, 0x01, 0x0a, 0x15, 0x00, 0x02, 0xfe, 0x3a, 0x08, 0x66, 0x09, 0x1e, 0x8d, 0x0b,
14819 0x09, 0x1e, 0xfe, 0x30, 0x13, 0x15, 0xfe, 0x1b, 0x00, 0x01, 0x0a, 0x15, 0x00, 0x01, 0x0a, 0x15,
14820 0x00, 0x01, 0x0a, 0x15, 0x00, 0x01, 0x0a, 0x15, 0x06, 0x01, 0x0a, 0x15, 0x00, 0x02, 0xc9, 0x79,
14821 0xfe, 0x9a, 0x81, 0x65, 0x89, 0xfe, 0x09, 0x6f, 0xfe, 0x93, 0x45, 0x1b, 0xfe, 0x84, 0x07, 0x2c,
14822 0xfe, 0x5c, 0x07, 0x1f, 0x31, 0xcf, 0xfe, 0x54, 0x07, 0x69, 0x8e, 0x80, 0xfe, 0x74, 0x07, 0x02,
14823 0x25, 0x01, 0x4a, 0x02, 0xf8, 0x15, 0x19, 0x02, 0xf8, 0xfe, 0x9c, 0xf7, 0xfe, 0xf0, 0x07, 0xfe,
14824 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x73, 0xfe, 0xd2, 0x07, 0x0f, 0x5c, 0x13, 0x5d, 0x0b, 0x49, 0x6f,
14825 0x37, 0x01, 0xfe, 0xf6, 0x17, 0x05, 0x10, 0x82, 0xfe, 0x83, 0xe7, 0x88, 0xa4, 0xfe, 0x03, 0x40,
14826 0x0b, 0x49, 0x74, 0x37, 0x01, 0xb7, 0xab, 0xfe, 0x1f, 0x40, 0x16, 0x60, 0x01, 0xf6, 0xfe, 0x08,
14827 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x34, 0x51, 0xfe, 0xb6, 0x51, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
14828 0x0f, 0x5a, 0x13, 0x5b, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x28, 0x50, 0xfe, 0xaa, 0x50,
14829 0x0f, 0x41, 0x13, 0x42, 0xfe, 0x4a, 0x10, 0x0b, 0x09, 0x6f, 0xe3, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
14830 0x90, 0x0f, 0x5c, 0x13, 0x5d, 0x0b, 0x09, 0x74, 0xc7, 0x01, 0xb7, 0xfe, 0x1f, 0x80, 0x16, 0x60,
14831 0xfe, 0x34, 0x90, 0xfe, 0xb6, 0x90, 0x0f, 0x5e, 0x13, 0x5f, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
14832 0x0f, 0x5a, 0x13, 0x5b, 0xfe, 0x28, 0x90, 0xfe, 0xaa, 0x90, 0x0f, 0x41, 0x13, 0x42, 0x0f, 0x3e,
14833 0x13, 0x57, 0x0b, 0x49, 0x19, 0x37, 0x35, 0x08, 0xa1, 0x2c, 0xfe, 0x50, 0x08, 0xfe, 0x9e, 0xf0,
14834 0xfe, 0x64, 0x08, 0xc2, 0x1b, 0x31, 0x35, 0x6b, 0xfe, 0xed, 0x10, 0xa5, 0xfe, 0x88, 0x08, 0xa6,
14835 0xfe, 0xa4, 0x08, 0x80, 0xfe, 0x7c, 0x08, 0xcb, 0xfe, 0x82, 0x08, 0x69, 0x8e, 0x02, 0x25, 0x01,
14836 0x4a, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x66, 0x09, 0x06, 0xfe, 0x10, 0x12, 0x66,
14837 0x09, 0x0c, 0x48, 0x0b, 0x09, 0x0c, 0xfe, 0x66, 0x12, 0xfe, 0x2e, 0x1c, 0xa7, 0x66, 0x09, 0x06,
14838 0x48, 0x66, 0x09, 0x0c, 0xfe, 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x24, 0x09,
14839 0xfe, 0xac, 0xf0, 0xfe, 0xc4, 0x08, 0xfe, 0x92, 0x10, 0xfe, 0x34, 0x1c, 0xfe, 0xf3, 0x10, 0xfe,
14840 0xad, 0xf0, 0xfe, 0xd0, 0x08, 0x02, 0xfe, 0x32, 0x0a, 0xfe, 0x36, 0x1c, 0xfe, 0xe7, 0x10, 0xfe,
14841 0x2b, 0xf0, 0xb0, 0xfe, 0x6b, 0x18, 0x1a, 0xfe, 0x00, 0xfe, 0xdb, 0xc3, 0xfe, 0xd2, 0xf0, 0xb0,
14842 0xfe, 0x76, 0x18, 0x1a, 0x18, 0x1b, 0xb0, 0x04, 0xe1, 0x1a, 0x06, 0x1b, 0xb0, 0xa5, 0x77, 0xa6,
14843 0x77, 0xfe, 0x34, 0x1c, 0xfe, 0x36, 0x1c, 0xfe, 0xb1, 0x10, 0x8b, 0x59, 0x39, 0x17, 0xa2, 0x01,
14844 0x38, 0x12, 0xfe, 0x35, 0x00, 0x33, 0x4b, 0x12, 0x8c, 0x02, 0x4b, 0xfe, 0x74, 0x18, 0x1a, 0xfe,
14845 0x00, 0xf8, 0x1b, 0x77, 0x51, 0x1e, 0x01, 0xfe, 0x42, 0x0d, 0xd2, 0x08, 0x1c, 0x07, 0x3f, 0x01,
14846 0x6a, 0x22, 0x2d, 0x3c, 0x51, 0x18, 0x02, 0x77, 0xfe, 0x98, 0x80, 0xd8, 0x0c, 0x27, 0xfe, 0x14,
14847 0x0a, 0x0b, 0x09, 0x6f, 0xfe, 0x82, 0x12, 0x0b, 0x09, 0x19, 0xfe, 0x66, 0x13, 0x22, 0x60, 0x68,
14848 0xc6, 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91,
14849 0x62, 0x2d, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x73, 0xfb, 0x04, 0x5c, 0x2e, 0x5d, 0x0f, 0xaa,
14850 0x13, 0x8c, 0x9b, 0x5c, 0x9c, 0x5d, 0x01, 0xb7, 0xab, 0x62, 0x2d, 0x16, 0x60, 0xa0, 0x3e, 0x67,
14851 0x57, 0x63, 0x5e, 0x30, 0x5f, 0xe7, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x3e, 0xfe, 0x05, 0xfa,
14852 0x57, 0x01, 0xf6, 0xfe, 0x36, 0x10, 0x29, 0x0f, 0xaa, 0x0f, 0x8c, 0x63, 0x5e, 0x30, 0x5f, 0xa7,
14853 0x0b, 0x09, 0x19, 0x1b, 0xfb, 0x63, 0x41, 0x30, 0x42, 0x0b, 0x09, 0xfe, 0xf7, 0x00, 0x37, 0x04,
14854 0x5a, 0x2e, 0x5b, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02,
14855 0x77, 0x0b, 0x09, 0x19, 0x1b, 0xfb, 0x0b, 0x09, 0xfe, 0xf7, 0x00, 0x37, 0xfe, 0x3a, 0x55, 0xfe,
14856 0x19, 0x81, 0x79, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x3d, 0x05, 0xbf, 0x1b,
14857 0xfe, 0xcc, 0x08, 0x11, 0xbf, 0xfe, 0x98, 0x80, 0xd8, 0x0c, 0xfe, 0x14, 0x13, 0x04, 0x41, 0x2e,
14858 0x42, 0x73, 0xfe, 0xcc, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x77, 0x29, 0x4e, 0xfe,
14859 0x19, 0x80, 0xfe, 0xf1, 0x10, 0x0b, 0x09, 0x0c, 0xa3, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xfe,
14860 0x94, 0x10, 0xfe, 0x6c, 0x19, 0x9b, 0x41, 0xfe, 0xed, 0x19, 0x9c, 0x42, 0xfe, 0x0c, 0x51, 0xfe,
14861 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x1a, 0xfe, 0x00, 0xff, 0x2f, 0xfe, 0x7a, 0x10, 0xc3, 0xfe, 0xd2,
14862 0xf0, 0xfe, 0xac, 0x0a, 0xfe, 0x76, 0x18, 0x1a, 0x18, 0xce, 0x04, 0xe1, 0x1a, 0x06, 0x83, 0x12,
14863 0xfe, 0x16, 0x00, 0x02, 0x4b, 0xfe, 0xd1, 0xf0, 0xfe, 0xe2, 0x0a, 0x17, 0xa1, 0x01, 0x38, 0x12,
14864 0xd6, 0xfe, 0x48, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca, 0x0a, 0x12, 0xfe, 0x21, 0x00, 0x02, 0x4b,
14865 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x12, 0xfe, 0x22, 0x00, 0x02, 0x4b, 0xfe, 0xcb, 0xf0, 0xfe,
14866 0xe2, 0x0a, 0x12, 0xfe, 0x24, 0x00, 0x02, 0x4b, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x12, 0x88,
14867 0xd9, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x12, 0x89, 0xd4, 0xfe, 0xcc, 0xf0, 0xc9, 0xfe, 0x84,
14868 0x80, 0xd8, 0x19, 0xfe, 0xd5, 0x12, 0x12, 0xfe, 0x12, 0x00, 0x2c, 0xc9, 0x1f, 0x31, 0xa5, 0x25,
14869 0xa6, 0x25, 0x35, 0xf3, 0x2c, 0xfe, 0x1a, 0x0b, 0x1f, 0x31, 0x80, 0xfe, 0x36, 0x0b, 0x69, 0x8e,
14870 0xa5, 0xfe, 0xf0, 0x07, 0xa6, 0xfe, 0xf0, 0x07, 0x02, 0x25, 0x01, 0x4a, 0xfe, 0xdb, 0x10, 0x11,
14871 0xfe, 0xe8, 0x00, 0x8b, 0x81, 0x6d, 0xfe, 0x89, 0xf0, 0x25, 0x23, 0x28, 0xfe, 0xe9, 0x09, 0x01,
14872 0x0a, 0x81, 0x6d, 0x20, 0x25, 0x23, 0x28, 0x93, 0x33, 0xfe, 0x6e, 0x0b, 0x1f, 0x31, 0x02, 0xfe,
14873 0x62, 0x0b, 0xc2, 0x48, 0x12, 0xfe, 0x42, 0x00, 0x02, 0x4b, 0x9f, 0x06, 0xfe, 0x81, 0x49, 0xfe,
14874 0xcc, 0x12, 0x0b, 0x09, 0x0c, 0xfe, 0x5a, 0x13, 0x12, 0x00, 0x58, 0x0c, 0xfe, 0x6a, 0x12, 0x58,
14875 0xfe, 0x28, 0x00, 0x27, 0xfe, 0xb4, 0x0c, 0x0e, 0x7c, 0x01, 0x14, 0x05, 0x00, 0x83, 0x34, 0xfe,
14876 0x28, 0x00, 0x02, 0xfe, 0xb4, 0x0c, 0x01, 0x95, 0x01, 0x98, 0x0e, 0xbd, 0x01, 0xfe, 0x10, 0x0e,
14877 0xaf, 0x08, 0x3b, 0x07, 0x99, 0x01, 0x40, 0x11, 0x43, 0x08, 0x1c, 0x07, 0x3f, 0x01, 0x76, 0x02,
14878 0x26, 0x12, 0xfe, 0x44, 0x00, 0x58, 0x0c, 0xa3, 0x34, 0x0c, 0xfe, 0xc0, 0x10, 0x01, 0xb6, 0x34,
14879 0x0c, 0xfe, 0xb6, 0x10, 0x01, 0xb6, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xfe, 0x0a, 0x13, 0x34,
14880 0x0c, 0x12, 0xfe, 0x43, 0x00, 0xfe, 0xa2, 0x10, 0x0b, 0x49, 0x0c, 0x37, 0x01, 0x95, 0x01, 0x98,
14881 0xaf, 0x08, 0x3b, 0x07, 0x99, 0x01, 0x40, 0x11, 0x43, 0x08, 0x1c, 0x07, 0x3f, 0x01, 0x76, 0x51,
14882 0x0c, 0xaf, 0x1d, 0xca, 0x02, 0xfe, 0x48, 0x03, 0x0b, 0x09, 0x0c, 0xce, 0x34, 0x0c, 0x12, 0x00,
14883 0xfe, 0x54, 0x10, 0x66, 0x09, 0x1e, 0xfe, 0x50, 0x12, 0x0b, 0x09, 0x1e, 0xfe, 0x48, 0x13, 0xfe,
14884 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x72, 0x0c, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x78,
14885 0x0c, 0x0b, 0x49, 0x1e, 0x37, 0xfe, 0x95, 0x10, 0x12, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0c,
14886 0x79, 0xfe, 0x26, 0x10, 0x12, 0xfe, 0x13, 0x00, 0xd4, 0x12, 0xfe, 0x47, 0x00, 0xa4, 0x12, 0xfe,
14887 0x41, 0x00, 0x9d, 0x12, 0xfe, 0x24, 0x00, 0x04, 0x7b, 0x2a, 0x27, 0xeb, 0x79, 0xfe, 0x04, 0xe6,
14888 0x1e, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0xaf, 0x01, 0xd7, 0x02, 0x26, 0xd5, 0x17, 0x0c, 0x47,
14889 0xf2, 0xdf, 0x17, 0xfe, 0x31, 0x00, 0x47, 0xba, 0x01, 0xfe, 0x1c, 0x0f, 0x02, 0xfc, 0x1d, 0xfe,
14890 0x06, 0xec, 0xf7, 0x85, 0x34, 0x36, 0xbc, 0x2f, 0x1d, 0xfe, 0x06, 0xea, 0xf7, 0xfe, 0x47, 0x4b,
14891 0x7a, 0xfe, 0x75, 0x57, 0x04, 0x55, 0xfe, 0x98, 0x56, 0xfe, 0x28, 0x12, 0x0e, 0x7c, 0xfe, 0xfa,
14892 0x14, 0x4e, 0xe5, 0x0e, 0xbd, 0xfe, 0xf0, 0x14, 0xfe, 0x49, 0x54, 0x91, 0xfe, 0x28, 0x0d, 0x0e,
14893 0x1c, 0xfe, 0xe4, 0x14, 0xfe, 0x44, 0x48, 0x02, 0xfe, 0x48, 0x03, 0x0e, 0x55, 0xfe, 0xc8, 0x14,
14894 0x85, 0x34, 0x36, 0xbc, 0x2f, 0x1d, 0xfe, 0xce, 0x47, 0xfe, 0xbd, 0x13, 0x02, 0x26, 0x22, 0x2b,
14895 0x05, 0x10, 0xfe, 0x78, 0x12, 0x29, 0x16, 0x54, 0x16, 0xa9, 0x22, 0x43, 0x4e, 0x47, 0x43, 0xc2,
14896 0xfe, 0x0c, 0x13, 0xfe, 0xbc, 0xf0, 0xfe, 0xc4, 0x0d, 0x08, 0x06, 0x16, 0x54, 0x01, 0xfe, 0xd0,
14897 0x15, 0x04, 0xfe, 0x38, 0x01, 0x2e, 0xfe, 0x3a, 0x01, 0x73, 0xfe, 0xc8, 0x0d, 0x04, 0xfe, 0x38,
14898 0x01, 0x1a, 0xfe, 0xf0, 0xff, 0x0f, 0xfe, 0x60, 0x01, 0x04, 0xfe, 0x3a, 0x01, 0x0f, 0xfe, 0x62,
14899 0x01, 0x21, 0x06, 0x16, 0x43, 0xfe, 0x04, 0xec, 0x2b, 0x08, 0x2b, 0x07, 0x3a, 0x1d, 0x01, 0x40,
14900 0x7f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x40, 0x16, 0x11, 0x43, 0xca, 0x08, 0x06,
14901 0x03, 0x29, 0x03, 0x22, 0x54, 0xfe, 0xf7, 0x12, 0x22, 0xa9, 0x68, 0x16, 0xa9, 0x05, 0xa1, 0xfe,
14902 0x93, 0x13, 0xfe, 0x24, 0x1c, 0x17, 0x18, 0x47, 0xf2, 0xdf, 0xfe, 0xd9, 0x10, 0x94, 0xfe, 0x03,
14903 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0x94, 0xfe, 0x03, 0xdc, 0x29, 0xfe, 0x70, 0x57,
14904 0xfe, 0x33, 0x54, 0xfe, 0x3b, 0x54, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0x94, 0x29, 0xfe,
14905 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0x94, 0x7d, 0x03, 0x01, 0xfe, 0x70, 0x16, 0x3d, 0x05, 0x43,
14906 0xfe, 0x0a, 0x13, 0x08, 0x1c, 0x07, 0x3f, 0xd4, 0x01, 0x95, 0x01, 0x98, 0x08, 0x3b, 0x07, 0x99,
14907 0x01, 0x40, 0x11, 0xfe, 0xe9, 0x00, 0x0b, 0x09, 0x89, 0xfe, 0x52, 0x13, 0x01, 0xfe, 0x02, 0x16,
14908 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0x0f, 0xfe, 0x64, 0x01, 0xfe, 0x16, 0x90, 0x0f, 0xfe, 0x66,
14909 0x01, 0x0b, 0x09, 0x74, 0x8d, 0xfe, 0x03, 0x80, 0x6b, 0x3c, 0x11, 0x75, 0x08, 0x2b, 0x07, 0x3a,
14910 0x1d, 0x92, 0x01, 0x6a, 0xfe, 0x62, 0x08, 0x68, 0x3c, 0x11, 0x75, 0x08, 0x2b, 0x07, 0x3a, 0x1d,
14911 0x92, 0x01, 0x6a, 0x62, 0x2d, 0x11, 0x75, 0x08, 0x2b, 0x07, 0x3a, 0x1d, 0x92, 0x01, 0x76, 0x03,
14912 0xfe, 0x08, 0x1c, 0x04, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x04, 0xfe, 0xae, 0x00, 0xfe, 0x07,
14913 0x58, 0x04, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x04, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe,
14914 0x0a, 0x1c, 0x21, 0x87, 0x16, 0xf7, 0x29, 0x0f, 0x52, 0x0f, 0x4d, 0x21, 0x10, 0x16, 0x2b, 0x16,
14915 0x3a, 0x56, 0x9f, 0xd6, 0x08, 0x2b, 0x07, 0x3a, 0x1d, 0x01, 0x76, 0x7f, 0x11, 0x75, 0xfe, 0x14,
14916 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xf6, 0x0e, 0xd5, 0x8b, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
14917 0x18, 0x1c, 0x03, 0x1d, 0xfe, 0x0c, 0x14, 0x85, 0xfe, 0x07, 0xe6, 0x36, 0xfe, 0xce, 0x47, 0xfe,
14918 0xf5, 0x13, 0x03, 0x01, 0xb6, 0x0e, 0x3b, 0x01, 0x14, 0x05, 0x10, 0xd3, 0x0e, 0x1c, 0x01, 0x14,
14919 0x05, 0x10, 0xdb, 0xfe, 0x44, 0x58, 0x3c, 0xfe, 0x01, 0xec, 0xba, 0xfe, 0x9e, 0x40, 0xfe, 0x9d,
14920 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1e, 0x9e, 0x2d, 0x01, 0xd7, 0xfe, 0xc9, 0x10, 0x03, 0x35, 0x81,
14921 0x6d, 0x23, 0x28, 0xb1, 0x05, 0x1e, 0xfe, 0x48, 0x12, 0x05, 0x0c, 0xfe, 0x4c, 0x12, 0x05, 0x18,
14922 0x38, 0x05, 0xcc, 0x1b, 0xfe, 0xc0, 0x10, 0x05, 0xfe, 0x23, 0x00, 0x1b, 0xfe, 0xcc, 0x10, 0x05,
14923 0x06, 0x1b, 0xfe, 0x2a, 0x11, 0x05, 0x19, 0xfe, 0x12, 0x12, 0x05, 0x00, 0x1b, 0x25, 0x17, 0xcc,
14924 0x01, 0x38, 0xc4, 0x39, 0x01, 0x0a, 0x80, 0x4a, 0x03, 0x39, 0x11, 0xfe, 0xcc, 0x00, 0x02, 0x26,
14925 0x39, 0x3d, 0x05, 0xbf, 0xfe, 0xe3, 0x13, 0x63, 0x41, 0x30, 0x42, 0x73, 0xfe, 0x7e, 0x10, 0x0b,
14926 0x09, 0x6f, 0xfe, 0x72, 0x12, 0xa0, 0x3e, 0x67, 0x57, 0xe7, 0xfe, 0xe5, 0x55, 0x91, 0xfe, 0x48,
14927 0x10, 0x22, 0x60, 0xfe, 0x26, 0x13, 0x04, 0xaa, 0x2e, 0x8c, 0x73, 0xfe, 0x98, 0x0c, 0x0f, 0x5c,
14928 0x13, 0x5d, 0x29, 0x0f, 0xaa, 0x0f, 0x8c, 0x01, 0xb7, 0x21, 0x87, 0x6b, 0x16, 0x60, 0x01, 0xf6,
14929 0xa0, 0x3e, 0x67, 0x57, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x3e, 0xfe, 0x05,
14930 0xfa, 0x57, 0xfe, 0x91, 0x10, 0x04, 0x5e, 0x2e, 0x5f, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0f,
14931 0x5e, 0x13, 0x5f, 0xd1, 0xa0, 0x3e, 0x67, 0x57, 0xe7, 0xfe, 0xe5, 0x55, 0x04, 0x5a, 0x2e, 0x5b,
14932 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0f, 0x5a, 0x13, 0x5b, 0x0b, 0x09, 0x6f, 0xfe, 0x1e, 0x12,
14933 0x22, 0x60, 0xfe, 0x1f, 0x40, 0x04, 0x5c, 0x2e, 0x5d, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x04,
14934 0x5e, 0x2e, 0x5f, 0xfe, 0x34, 0x50, 0xfe, 0xb6, 0x50, 0x04, 0x5a, 0x2e, 0x5b, 0xfe, 0x08, 0x50,
14935 0xfe, 0x8a, 0x50, 0x04, 0x41, 0x2e, 0x42, 0xfe, 0x28, 0x50, 0xfe, 0xaa, 0x50, 0x02, 0x97, 0x21,
14936 0x06, 0x16, 0xf1, 0x02, 0x78, 0x39, 0x01, 0x0a, 0x20, 0x4c, 0x23, 0x28, 0xb1, 0x05, 0x06, 0x27,
14937 0x4c, 0x3d, 0x05, 0xbf, 0x27, 0x78, 0x01, 0xee, 0x1a, 0x4f, 0x1b, 0x4c, 0x0b, 0x09, 0x0c, 0xde,
14938 0x63, 0x41, 0x30, 0x42, 0xfe, 0x0a, 0x55, 0x2f, 0xfe, 0x8b, 0x55, 0x9b, 0x41, 0x9c, 0x42, 0xfe,
14939 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x78, 0xfe, 0x19, 0x81, 0xfe, 0x0a, 0x45, 0xfe, 0x19, 0x41,
14940 0x02, 0x78, 0x39, 0x01, 0x0a, 0x20, 0xfe, 0xc2, 0x0f, 0x23, 0x28, 0xfe, 0xe9, 0x09, 0x58, 0x18,
14941 0xfe, 0x94, 0x12, 0x58, 0x0c, 0x50, 0x02, 0x4c, 0x2c, 0xfe, 0x4a, 0x11, 0x1f, 0x31, 0x20, 0xfe,
14942 0xc2, 0x0f, 0x23, 0x28, 0x93, 0x05, 0x18, 0x27, 0x4c, 0x01, 0x0a, 0x20, 0xfe, 0xc2, 0x0f, 0x23,
14943 0x28, 0xfe, 0xe8, 0x09, 0x56, 0x04, 0xfe, 0x9c, 0x00, 0x2a, 0x2f, 0xfe, 0xbb, 0x45, 0x58, 0x00,
14944 0x48, 0x34, 0x06, 0x9f, 0x4f, 0xfe, 0xc0, 0x14, 0xfe, 0xf8, 0x14, 0xa8, 0x3d, 0x05, 0xbe, 0xfe,
14945 0x16, 0x13, 0x04, 0xf4, 0x2a, 0xce, 0x04, 0x4d, 0x2a, 0x2f, 0x59, 0x02, 0x78, 0xfe, 0xc0, 0x5d,
14946 0xfe, 0xe4, 0x14, 0xfe, 0x03, 0x17, 0x04, 0x52, 0xb9, 0x0f, 0x52, 0x59, 0x39, 0x01, 0x0a, 0x24,
14947 0x97, 0x01, 0xfe, 0xf0, 0x13, 0x02, 0x97, 0x2c, 0xfe, 0xd4, 0x11, 0x1f, 0x31, 0x20, 0x4c, 0x23,
14948 0x28, 0x93, 0x05, 0x06, 0x27, 0x4c, 0xfe, 0xf6, 0x14, 0xfe, 0x42, 0x58, 0xfe, 0x70, 0x14, 0xfe,
14949 0x92, 0x14, 0xa8, 0xfe, 0x4a, 0xf4, 0x0c, 0x1b, 0x4c, 0xfe, 0x4a, 0xf4, 0x06, 0xd2, 0x3d, 0x05,
14950 0xbe, 0xc7, 0x02, 0x78, 0x04, 0x4d, 0xb9, 0x0f, 0x4d, 0x59, 0x39, 0x01, 0x0a, 0x24, 0x97, 0x01,
14951 0xfe, 0x1e, 0x14, 0x02, 0x97, 0x24, 0xfe, 0x3c, 0x12, 0x71, 0xef, 0x71, 0x03, 0x33, 0x8d, 0x69,
14952 0x8d, 0x59, 0x39, 0x01, 0x0a, 0xfe, 0xe3, 0x10, 0x08, 0x61, 0xff, 0x02, 0x00, 0x57, 0x64, 0x7e,
14953 0x1a, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x08, 0x61, 0xff, 0x02, 0x00,
14954 0x57, 0x64, 0x7e, 0x1a, 0x4f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x08, 0x61, 0xff, 0x02,
14955 0x00, 0x57, 0x64, 0x7e, 0x03, 0x08, 0x61, 0xff, 0x02, 0x00, 0x57, 0x64, 0x7e, 0xfe, 0x0b, 0x58,
14956 0x03, 0x0e, 0x52, 0x01, 0x9a, 0x0e, 0x4d, 0x01, 0x9a, 0x03, 0xc6, 0x1a, 0x10, 0xff, 0x03, 0x00,
14957 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x64, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe,
14958 0x03, 0x7c, 0x62, 0x2d, 0x0f, 0x5a, 0x13, 0x5b, 0x9b, 0x5e, 0x9c, 0x5f, 0x03, 0xfe, 0x62, 0x18,
14959 0xfe, 0x82, 0x5a, 0xfe, 0xe1, 0x1a, 0xb4, 0xfe, 0x02, 0x58, 0x03, 0x01, 0xfe, 0x60, 0x18, 0xfe,
14960 0x42, 0x48, 0x79, 0x56, 0x7a, 0x01, 0x0a, 0x20, 0xfe, 0xe8, 0x13, 0x23, 0x28, 0xfe, 0xe9, 0x09,
14961 0xfe, 0xc1, 0x59, 0x01, 0x0a, 0x20, 0xfe, 0xe8, 0x13, 0x23, 0x28, 0xfe, 0xe8, 0x0a, 0x04, 0xf4,
14962 0x2a, 0xfe, 0xc2, 0x12, 0x29, 0xad, 0x1e, 0xde, 0x58, 0xcd, 0x72, 0xfe, 0x38, 0x13, 0x50, 0x08,
14963 0x06, 0x07, 0xcd, 0x9f, 0xfe, 0x00, 0x10, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa4, 0xff,
14964 0x02, 0x83, 0x55, 0xad, 0x18, 0xfe, 0x12, 0x13, 0x70, 0xfe, 0x30, 0x00, 0x91, 0xf0, 0x07, 0x84,
14965 0x08, 0x06, 0xfe, 0x56, 0x10, 0xad, 0x0c, 0xfe, 0x16, 0x13, 0x70, 0xfe, 0x64, 0x00, 0x91, 0xf0,
14966 0x0e, 0xfe, 0x64, 0x00, 0x07, 0x88, 0x08, 0x06, 0xfe, 0x28, 0x10, 0xad, 0x06, 0xfe, 0x5e, 0x13,
14967 0x70, 0xfe, 0xc8, 0x00, 0x91, 0xf0, 0x0e, 0xfe, 0xc8, 0x00, 0x07, 0x54, 0x08, 0x06, 0xd1, 0x70,
14968 0xfe, 0x90, 0x01, 0xea, 0xfe, 0x9e, 0x13, 0x7a, 0xa7, 0xfe, 0x43, 0xf4, 0xa9, 0xfe, 0x56, 0xf0,
14969 0xfe, 0xb0, 0x13, 0xfe, 0x04, 0xf4, 0x61, 0xfe, 0x43, 0xf4, 0x88, 0xfe, 0xf3, 0x10, 0xac, 0x01,
14970 0xfe, 0x7a, 0x12, 0x1a, 0x4f, 0xd3, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x87, 0xea, 0xfe, 0xe2,
14971 0x13, 0x7a, 0xfe, 0x14, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xea, 0xfe, 0xe2, 0x13,
14972 0xc8, 0x19, 0x9d, 0x56, 0x7a, 0x08, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x03, 0x56, 0x08,
14973 0x0c, 0x03, 0x15, 0x06, 0x01, 0x0a, 0x24, 0xdc, 0x15, 0x0c, 0x01, 0x0a, 0x24, 0xdc, 0x15, 0x18,
14974 0x01, 0x0a, 0x24, 0xdc, 0x71, 0xfe, 0x89, 0x49, 0x01, 0x0a, 0x03, 0x15, 0x06, 0x01, 0x0a, 0x24,
14975 0x90, 0x15, 0x18, 0x01, 0x0a, 0x24, 0x90, 0x15, 0x06, 0x01, 0x0a, 0x24, 0x90, 0xfe, 0x89, 0x49,
14976 0x01, 0x0a, 0x24, 0x90, 0x71, 0xfe, 0x89, 0x4a, 0x01, 0x0a, 0x03, 0x56, 0x03, 0x22, 0xe2, 0x05,
14977 0x06, 0xfe, 0x44, 0x13, 0xab, 0x16, 0xe2, 0xfe, 0x49, 0xf4, 0x00, 0x50, 0x71, 0xc4, 0x59, 0xfe,
14978 0x01, 0xec, 0xfe, 0x27, 0x01, 0xef, 0x01, 0x0a, 0x3d, 0x05, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13,
14979 0x20, 0xfe, 0xa0, 0x14, 0x29, 0x16, 0xf1, 0x01, 0x4a, 0x22, 0xf1, 0x05, 0x06, 0x48, 0x0b, 0x49,
14980 0x06, 0x37, 0x03, 0x0f, 0x53, 0x13, 0x8a, 0xfe, 0x43, 0x58, 0x01, 0x14, 0x05, 0x10, 0xfe, 0x1e,
14981 0x12, 0x45, 0xe6, 0x8f, 0x01, 0x44, 0xfe, 0x90, 0x4d, 0xe0, 0x10, 0xfe, 0xc5, 0x59, 0x01, 0x44,
14982 0xfe, 0x8d, 0x56, 0xb4, 0x45, 0x03, 0x45, 0x30, 0x8a, 0x01, 0x14, 0x45, 0x8f, 0x01, 0x44, 0xe4,
14983 0x10, 0xe0, 0x10, 0x30, 0x53, 0x70, 0x1c, 0x83, 0x0e, 0x55, 0x01, 0xc0, 0x03, 0x0f, 0x53, 0x13,
14984 0x8a, 0xfe, 0xc3, 0x58, 0x01, 0x14, 0x05, 0x10, 0xfe, 0x1a, 0x12, 0x45, 0xe6, 0x8f, 0x01, 0x44,
14985 0xe4, 0x10, 0xfe, 0x80, 0x4d, 0xfe, 0xc5, 0x59, 0x01, 0x44, 0x45, 0x03, 0x45, 0x30, 0x53, 0x01,
14986 0x14, 0x45, 0x8f, 0x01, 0x44, 0xe4, 0x10, 0xe0, 0x10, 0x30, 0x53, 0x70, 0x1c, 0x83, 0x0e, 0x55,
14987 0x01, 0xc0, 0x03, 0x0f, 0x53, 0x13, 0x8a, 0xfe, 0x43, 0x58, 0x01, 0x14, 0xfe, 0x42, 0x48, 0x8f,
14988 0x01, 0x44, 0xfe, 0xc0, 0x5a, 0xac, 0xfe, 0x00, 0xcd, 0xfe, 0x01, 0xcc, 0xfe, 0x4a, 0x46, 0xde,
14989 0x94, 0x7d, 0x05, 0x10, 0xfe, 0x2e, 0x13, 0x67, 0x53, 0xfe, 0x4d, 0xf4, 0x1c, 0xfe, 0x1c, 0x13,
14990 0x0e, 0x55, 0x01, 0x9a, 0xa7, 0xfe, 0x40, 0x4c, 0xfe, 0xc5, 0x58, 0x01, 0x44, 0xfe, 0x00, 0x07,
14991 0x7d, 0x05, 0x10, 0x83, 0x67, 0x8a, 0xfe, 0x05, 0x57, 0xfe, 0x08, 0x10, 0xfe, 0x45, 0x58, 0x01,
14992 0x44, 0xfe, 0x8d, 0x56, 0xb4, 0xfe, 0x80, 0x4c, 0xfe, 0x05, 0x17, 0x03, 0x07, 0x10, 0x6e, 0x65,
14993 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xdd, 0x36, 0x96, 0xfe,
14994 0xe4, 0x15, 0x01, 0xfe, 0xea, 0x16, 0xfe, 0x0c, 0x13, 0x86, 0x36, 0x65, 0xfe, 0x2c, 0x01, 0xfe,
14995 0x2f, 0x19, 0x03, 0xb5, 0x27, 0xfe, 0xd4, 0x15, 0xfe, 0xda, 0x10, 0x07, 0x10, 0x6e, 0x04, 0xfe,
14996 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58, 0x04, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58,
14997 0x86, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x65, 0xfe, 0x38, 0x00,
14998 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x96, 0xfe, 0x2e, 0x16, 0xfe, 0xb6, 0x14, 0x2f, 0x03,
14999 0xb5, 0x27, 0xfe, 0x06, 0x16, 0xfe, 0x9c, 0x10, 0x07, 0x10, 0x6e, 0xb4, 0xfe, 0x18, 0xdf, 0xfe,
15000 0x19, 0xdf, 0xdd, 0x3e, 0x96, 0xfe, 0x50, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10, 0x13, 0x86, 0x3e,
15001 0x65, 0x1e, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x03, 0xb5, 0x27, 0xfe, 0x44, 0x16, 0xfe,
15002 0x6c, 0x10, 0x07, 0x10, 0x6e, 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x86, 0xda, 0x65, 0x1e, 0xfe,
15003 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0xda, 0x96, 0xfe, 0x88, 0x16, 0xfe, 0x5c, 0x14, 0x2f, 0x03, 0xb5,
15004 0x27, 0xfe, 0x74, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x10, 0x6e, 0xfe, 0x18, 0xfe, 0x5c,
15005 0xfe, 0x19, 0xfe, 0x5d, 0xc6, 0xdd, 0x74, 0x96, 0xfe, 0xae, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c,
15006 0x13, 0x86, 0x74, 0x4e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81,
15007 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x62, 0x2d, 0x03, 0x62, 0x2d, 0xfe, 0x12, 0x45, 0x27, 0xfe,
15008 0x9e, 0x16, 0x17, 0x06, 0x47, 0xf2, 0xdf, 0x02, 0x26, 0xfe, 0x39, 0xf0, 0xfe, 0xf2, 0x16, 0x29,
15009 0x03, 0xfe, 0x7e, 0x18, 0x1a, 0x18, 0x82, 0x08, 0x0d, 0x03, 0x6e, 0x04, 0xe1, 0x1a, 0x06, 0xfe,
15010 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x1d, 0x0e, 0x1c, 0x01, 0x14, 0x05, 0x10, 0x48, 0x3c, 0xfe, 0x78,
15011 0x14, 0xfe, 0x34, 0x12, 0x4f, 0x85, 0x34, 0x36, 0xbc, 0xfe, 0xe9, 0x13, 0x1d, 0x0e, 0x3b, 0x01,
15012 0x14, 0x05, 0x10, 0x48, 0x3c, 0x90, 0xe3, 0x4f, 0x85, 0x34, 0x36, 0xbc, 0xfe, 0xe9, 0x13, 0x07,
15013 0x0c, 0x03, 0xfe, 0x9c, 0xe7, 0x0c, 0x12, 0xfe, 0x15, 0x00, 0x92, 0x9e, 0x2d, 0x01, 0xd7, 0x07,
15014 0x06, 0x03, 0x0b, 0x49, 0x36, 0x37, 0x08, 0x3b, 0x07, 0x99, 0x01, 0x40, 0x11, 0x43, 0x08, 0x1c,
15015 0x07, 0x3f, 0x01, 0x76, 0x07, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x63, 0xf5, 0x30,
15016 0x75, 0xfe, 0x48, 0x55, 0x2f, 0xfe, 0xc9, 0x55, 0x03, 0x22, 0xbb, 0x6b, 0x16, 0xbb, 0x03, 0x0e,
15017 0xbd, 0x01, 0x14, 0xe5, 0x0e, 0x7c, 0x01, 0x14, 0xfe, 0x49, 0x44, 0x27, 0xfe, 0xe8, 0x17, 0x0e,
15018 0x1c, 0x01, 0x14, 0x05, 0x10, 0x48, 0x0e, 0x55, 0x01, 0xc0, 0x0e, 0x7c, 0x01, 0x14, 0x6b, 0x7d,
15019 0x03, 0xfe, 0x40, 0x5e, 0xfe, 0xe2, 0x08, 0xfe, 0xc0, 0x4c, 0x22, 0x3a, 0x05, 0x10, 0xfe, 0x52,
15020 0x12, 0x3c, 0x05, 0x00, 0xfe, 0x18, 0x12, 0xfe, 0xe1, 0x18, 0xfe, 0x19, 0xf4, 0xfe, 0x7f, 0x00,
15021 0xfe, 0x10, 0x13, 0xfe, 0xe2, 0x08, 0x6b, 0x3c, 0x3d, 0x05, 0x75, 0xa3, 0xfe, 0x82, 0x48, 0xfe,
15022 0x01, 0x80, 0xfe, 0xd7, 0x10, 0xfe, 0xc4, 0x48, 0x08, 0x2b, 0x07, 0x3a, 0xfe, 0x40, 0x5f, 0x1d,
15023 0x01, 0x40, 0x11, 0xfe, 0xdd, 0x00, 0xfe, 0x14, 0x46, 0x08, 0x2b, 0x07, 0x3a, 0x01, 0x40, 0x11,
15024 0xfe, 0xdd, 0x00, 0xfe, 0x40, 0x4a, 0x68, 0xfe, 0x06, 0x17, 0xfe, 0x01, 0x07, 0xfe, 0x82, 0x48,
15025 0xfe, 0x04, 0x17, 0x03, 0xe9, 0x18, 0x72, 0xfe, 0x70, 0x18, 0x04, 0xfe, 0x90, 0x00, 0xfe, 0x3a,
15026 0x45, 0xfe, 0x2c, 0x10, 0xe9, 0xcc, 0x72, 0xfe, 0x82, 0x18, 0x04, 0xfe, 0x92, 0x00, 0xc5, 0x1e,
15027 0xd9, 0xe9, 0xfe, 0x0b, 0x00, 0x72, 0xfe, 0x94, 0x18, 0x04, 0xfe, 0x94, 0x00, 0xc5, 0x19, 0xfe,
15028 0x08, 0x10, 0x04, 0xfe, 0x96, 0x00, 0xc5, 0x84, 0xfe, 0x4e, 0x45, 0xd2, 0xfe, 0x0a, 0x45, 0xff,
15029 0x04, 0x68, 0x54, 0xfe, 0xf1, 0x10, 0x1a, 0x87, 0x03, 0x05, 0xa1, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0,
15030 0x18, 0x21, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, 0x05, 0x1e, 0xfe, 0x5a, 0xf0, 0xfe, 0xce, 0x18,
15031 0x21, 0xcd, 0xfe, 0x26, 0x10, 0x05, 0x18, 0x82, 0x21, 0x84, 0xd9, 0x05, 0x0c, 0x82, 0x21, 0x88,
15032 0xfe, 0x0e, 0x10, 0x05, 0x06, 0x82, 0x21, 0x54, 0xc4, 0xab, 0x03, 0x17, 0xfe, 0x09, 0x00, 0x01,
15033 0x38, 0x2c, 0xfe, 0xfe, 0x18, 0x04, 0x6d, 0xac, 0x03, 0x1f, 0xfe, 0x16, 0x19, 0xfe, 0x14, 0xf0,
15034 0x0a, 0x2c, 0xfe, 0x12, 0x19, 0x03, 0xff, 0x34, 0x00, 0x00,};
15036 STATIC unsigned short _adv_asc3550_size =
15037 sizeof(_adv_asc3550_buf); /* 0x13AA */
15038 STATIC unsigned long _adv_asc3550_chksum =
15039 0x04F4788EUL; /* Expanded checksum. */
15041 STATIC unsigned char _adv_asc38C0800_buf[] = {
15042 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x00, 0xfc, 0x48, 0xe4, 0x01, 0x00, 0x00, 0xf6,
15043 0x18, 0xe4, 0x01, 0xf6, 0x18, 0x80, 0x02, 0x00, 0x02, 0x1a, 0xff, 0xff, 0x00, 0xfa, 0x03, 0xf6,
15044 0xff, 0x00, 0x82, 0xe7, 0x01, 0xfa, 0x9e, 0xe7, 0x09, 0xe7, 0xe6, 0x0e, 0x00, 0xea, 0x01, 0xe6,
15045 0x03, 0x00, 0x1e, 0xf0, 0x55, 0xf0, 0x18, 0xf4, 0x3e, 0x57, 0x04, 0x00, 0x3e, 0x01, 0x85, 0xf0,
15046 0x00, 0xe6, 0x03, 0xfc, 0x08, 0x00, 0x32, 0xf0, 0x38, 0x54, 0x84, 0x0d, 0x86, 0xf0, 0xd4, 0x01,
15047 0xd5, 0xf0, 0xee, 0x19, 0x00, 0xec, 0x01, 0xfc, 0x98, 0x57, 0xbc, 0x00, 0x10, 0x13, 0xb1, 0xf0,
15048 0x02, 0x13, 0x3c, 0x00, 0x7e, 0x0d, 0xb4, 0x00, 0x00, 0x57, 0x01, 0xf0, 0x02, 0xfc, 0x03, 0xe6,
15049 0x0c, 0x1c, 0x10, 0x00, 0x18, 0x40, 0x3e, 0x1c, 0xbd, 0x00, 0xe0, 0x00, 0x02, 0x80, 0x3e, 0x00,
15050 0x46, 0x16, 0x4a, 0x10, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54, 0xba, 0x13,
15051 0xbb, 0x00, 0x00, 0x4e, 0x01, 0x01, 0x01, 0xea, 0x02, 0x48, 0x02, 0xfa, 0x08, 0x12, 0x30, 0xe4,
15052 0x3c, 0x56, 0x4e, 0x01, 0x5d, 0xf0, 0x7a, 0x01, 0x88, 0x0d, 0x8e, 0x10, 0xb6, 0x00, 0xc4, 0x08,
15053 0x00, 0x80, 0x04, 0x12, 0x05, 0xfc, 0x24, 0x01, 0x28, 0x01, 0x32, 0x00, 0x3c, 0x01, 0x40, 0x00,
15054 0x4b, 0xe4, 0x4b, 0xf4, 0x4c, 0x1c, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x78, 0x01,
15055 0x7c, 0x01, 0xbb, 0x55, 0x00, 0x01, 0x02, 0xee, 0x03, 0x58, 0x03, 0xf7, 0x03, 0xfa, 0x04, 0x80,
15056 0x08, 0x44, 0x09, 0xf0, 0x10, 0x44, 0x1b, 0x80, 0x20, 0x01, 0x38, 0x1c, 0x4e, 0x1c, 0x5b, 0xf0,
15057 0x80, 0x00, 0x8a, 0x15, 0x98, 0x10, 0xaa, 0x00, 0xbd, 0x56, 0xbe, 0x00, 0xc0, 0x00, 0x00, 0x4c,
15058 0x00, 0xdc, 0x02, 0x4a, 0x04, 0xfc, 0x05, 0xf0, 0x05, 0xf8, 0x06, 0x13, 0x06, 0xf7, 0x08, 0x13,
15059 0x0c, 0x00, 0x0e, 0x47, 0x0e, 0xf7, 0x0f, 0x00, 0x1c, 0x0c, 0x20, 0x00, 0x2a, 0x01, 0x32, 0x1c,
15060 0x36, 0x00, 0x42, 0x54, 0x44, 0x0b, 0x44, 0x55, 0x45, 0x5a, 0x59, 0xf0, 0x5c, 0xf0, 0x62, 0x0a,
15061 0x69, 0x08, 0x78, 0x13, 0x83, 0x59, 0x8e, 0x18, 0x9a, 0x10, 0x9a, 0x18, 0xb8, 0xf0, 0xd6, 0x0e,
15062 0xea, 0x15, 0xf0, 0x00, 0x04, 0x10, 0x04, 0xea, 0x04, 0xf6, 0x05, 0x00, 0x06, 0x00, 0x06, 0x12,
15063 0x0a, 0x10, 0x0a, 0x12, 0x0b, 0xf0, 0x0c, 0x10, 0x0c, 0xf0, 0x12, 0x10, 0x19, 0x00, 0x19, 0xe4,
15064 0x2a, 0x12, 0x30, 0x1c, 0x33, 0x00, 0x34, 0x00, 0x36, 0x15, 0x38, 0x44, 0x3a, 0x15, 0x40, 0x5c,
15065 0x4a, 0xe4, 0x62, 0x1a, 0x68, 0x08, 0x68, 0x54, 0x7a, 0x17, 0x83, 0x55, 0x83, 0x5a, 0x91, 0x44,
15066 0xa2, 0x10, 0xa4, 0x00, 0xb0, 0x57, 0xb5, 0x00, 0xba, 0x00, 0xcc, 0x0e, 0xce, 0x45, 0xd0, 0x00,
15067 0xe1, 0x00, 0xe5, 0x55, 0xe7, 0x00, 0x00, 0x54, 0x01, 0x48, 0x01, 0x58, 0x02, 0x10, 0x02, 0xe6,
15068 0x03, 0xa1, 0x04, 0x13, 0x05, 0xe6, 0x06, 0x83, 0x06, 0xf0, 0x07, 0x00, 0x0a, 0x00, 0x0a, 0xf0,
15069 0x0c, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x04, 0x10, 0x10, 0x12, 0x1c, 0x19, 0x81, 0x1a, 0x10,
15070 0x1c, 0x00, 0x1c, 0x12, 0x1c, 0x13, 0x1d, 0xf7, 0x1e, 0x13, 0x20, 0x1c, 0x20, 0xe7, 0x22, 0x01,
15071 0x26, 0x01, 0x30, 0xe7, 0x38, 0x12, 0x3a, 0x55, 0x3f, 0x00, 0x41, 0x58, 0x43, 0x48, 0x46, 0x1c,
15072 0x4e, 0xe4, 0x5a, 0x13, 0x68, 0x13, 0x72, 0x14, 0x76, 0x02, 0x77, 0x57, 0x78, 0x03, 0x89, 0x48,
15073 0x8a, 0x13, 0x98, 0x80, 0x99, 0x00, 0x9b, 0x00, 0x9c, 0x32, 0xfe, 0x9c, 0xf0, 0x27, 0x02, 0xfe,
15074 0xa6, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xfe, 0xc6, 0x01, 0xfe, 0x18, 0x1a, 0x00, 0xfe, 0xc4, 0x01,
15075 0xfe, 0x84, 0x01, 0xff, 0x03, 0x00, 0x00, 0x30, 0xfe, 0x01, 0x05, 0xff, 0x40, 0x00, 0x00, 0x0d,
15076 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x10, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
15077 0xff, 0x10, 0xff, 0xff, 0xff, 0x11, 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21,
15078 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xfe, 0xc4, 0x01, 0x38, 0x86, 0x0b, 0x01, 0xfe, 0x96, 0x0f, 0xfe,
15079 0x04, 0xf7, 0xfe, 0xc4, 0x01, 0x86, 0x0b, 0x1c, 0x38, 0xfe, 0x3d, 0xf0, 0xfe, 0xfc, 0x01, 0xfe,
15080 0x20, 0xf0, 0xdb, 0x04, 0x5e, 0x59, 0x02, 0xfe, 0xc2, 0x0d, 0x01, 0xfe, 0x22, 0x0e, 0xfe, 0xe9,
15081 0x12, 0x02, 0xfe, 0x08, 0x03, 0xfe, 0x28, 0x1c, 0x04, 0xfe, 0xa6, 0x00, 0xfe, 0xdd, 0x12, 0x46,
15082 0x12, 0xfe, 0xa6, 0x00, 0xcd, 0xfe, 0x48, 0xf0, 0xfe, 0x80, 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0x9a,
15083 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xb8, 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x4a, 0x02, 0xfe, 0x47, 0xf0,
15084 0xfe, 0x50, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x3e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x42, 0x02, 0xfe,
15085 0x45, 0xf0, 0xfe, 0x46, 0x02, 0x09, 0x0b, 0xa2, 0x09, 0x06, 0x12, 0xc1, 0x02, 0x27, 0xfe, 0x00,
15086 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02, 0x1c, 0xfe, 0xed, 0x10, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10,
15087 0x01, 0xfe, 0xee, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xfe, 0xa8, 0x00, 0x0f, 0x7d, 0x01,
15088 0xc5, 0x02, 0x27, 0x17, 0x5d, 0x4b, 0xc3, 0x01, 0xab, 0x0f, 0x7d, 0x01, 0x9f, 0xfe, 0xbd, 0x10,
15089 0x0f, 0x7d, 0x01, 0x9f, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x09, 0x06, 0x12,
15090 0xc1, 0x38, 0x19, 0x27, 0xfe, 0x3d, 0xf0, 0xfe, 0xfc, 0x01, 0x28, 0xfe, 0x8e, 0x02, 0xfe, 0x5a,
15091 0x1c, 0xdd, 0xfe, 0x14, 0x1c, 0x17, 0xfe, 0x30, 0x00, 0x4b, 0xc3, 0x01, 0xfe, 0xfc, 0x0f, 0x09,
15092 0x06, 0x12, 0xc1, 0x02, 0xfe, 0xc6, 0x01, 0x2a, 0x2d, 0x05, 0x10, 0x30, 0xfe, 0x69, 0x10, 0x09,
15093 0x06, 0x12, 0xc1, 0xfe, 0x04, 0xec, 0x2d, 0x07, 0x2d, 0x09, 0x3c, 0x1c, 0x01, 0x40, 0x81, 0xfe,
15094 0x05, 0xf6, 0xfe, 0xa8, 0x00, 0x01, 0xfe, 0x20, 0x17, 0x0a, 0x4f, 0x8d, 0x3a, 0x11, 0x48, 0x1c,
15095 0xd3, 0x07, 0x1e, 0x09, 0x51, 0x01, 0xa0, 0x02, 0x27, 0x0f, 0x3d, 0x01, 0x15, 0x05, 0x10, 0xda,
15096 0x07, 0x1e, 0x09, 0x51, 0x01, 0x79, 0xfe, 0x28, 0x10, 0x0f, 0xc7, 0x01, 0x15, 0xed, 0x0f, 0x7e,
15097 0x01, 0x15, 0xfe, 0x49, 0x54, 0x77, 0xfe, 0x16, 0x03, 0x07, 0x1e, 0x09, 0x51, 0x01, 0xa0, 0x02,
15098 0x27, 0x38, 0x81, 0xfe, 0x02, 0xe8, 0x33, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xf5, 0xfe, 0x07,
15099 0x4b, 0xfe, 0x20, 0xf0, 0xdb, 0xfe, 0x40, 0x1c, 0x19, 0xf6, 0xfe, 0x26, 0xf0, 0xfe, 0x74, 0x03,
15100 0xfe, 0xa0, 0xf0, 0xfe, 0x62, 0x03, 0xfe, 0x11, 0xf0, 0xdb, 0xfe, 0x0e, 0x10, 0xfe, 0x9f, 0xf0,
15101 0xfe, 0x82, 0x03, 0xef, 0x13, 0xfe, 0x11, 0x00, 0x02, 0x54, 0x38, 0xfe, 0x48, 0x1c, 0xef, 0x19,
15102 0xf6, 0x35, 0xf6, 0xfe, 0x82, 0xf0, 0xfe, 0x88, 0x03, 0x24, 0x2a, 0xc4, 0x70, 0x16, 0xc4, 0x0f,
15103 0x7e, 0x01, 0x15, 0x70, 0x7f, 0x07, 0x1e, 0x09, 0x51, 0x01, 0x40, 0x11, 0x3d, 0x07, 0x3d, 0x09,
15104 0xa1, 0x01, 0xa0, 0xfc, 0x11, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xce, 0x03, 0x19, 0x32, 0x1f, 0xfe,
15105 0xde, 0x03, 0x01, 0x41, 0xd4, 0xfe, 0xee, 0x03, 0x71, 0x8c, 0xd7, 0xfe, 0xae, 0x06, 0x02, 0x25,
15106 0x04, 0x7d, 0x2c, 0x1a, 0xfe, 0x20, 0x05, 0x17, 0x88, 0x01, 0x2e, 0x01, 0x9b, 0x01, 0x9d, 0x35,
15107 0xfe, 0x60, 0x02, 0x02, 0xf4, 0xef, 0x38, 0x86, 0x18, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xf5,
15108 0xfe, 0x48, 0x1c, 0x8f, 0x01, 0xf2, 0xb1, 0xfe, 0x96, 0xf0, 0xfe, 0x28, 0x04, 0x2f, 0xfe, 0x2c,
15109 0x04, 0x35, 0x27, 0x0f, 0x3d, 0x01, 0x15, 0x05, 0x10, 0x1a, 0xfe, 0x0c, 0x05, 0x4c, 0x97, 0xa3,
15110 0x33, 0x84, 0x74, 0x19, 0x32, 0x1f, 0x25, 0x04, 0x7d, 0x2c, 0xfe, 0x10, 0x12, 0x17, 0x88, 0x01,
15111 0x2e, 0x35, 0xfe, 0x60, 0x02, 0x02, 0xf4, 0x21, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x5e,
15112 0x12, 0x0a, 0x08, 0x06, 0xfe, 0x56, 0x12, 0x23, 0x29, 0x98, 0x01, 0x0c, 0x84, 0x74, 0x1f, 0xfe,
15113 0xdc, 0x04, 0x23, 0x29, 0x98, 0x01, 0x0c, 0x1f, 0x25, 0x23, 0x29, 0xba, 0xfe, 0x4c, 0x44, 0xfe,
15114 0x32, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x07, 0xfe, 0x93, 0x00, 0xfe, 0x4c, 0x54, 0x77, 0xfe, 0x0c,
15115 0x05, 0x81, 0xa3, 0x33, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x48, 0x13, 0x3e, 0x05, 0xfe,
15116 0xcc, 0x00, 0xfe, 0x40, 0x13, 0x0a, 0x08, 0x06, 0xea, 0xfe, 0x06, 0x10, 0x23, 0x29, 0xba, 0x0a,
15117 0x08, 0x39, 0xe1, 0x17, 0xa6, 0x0a, 0x08, 0x06, 0x59, 0x17, 0xfe, 0x0d, 0x00, 0x01, 0x2e, 0x35,
15118 0xfe, 0x66, 0x0d, 0x02, 0x25, 0x3b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xb7, 0x03, 0x17,
15119 0xa6, 0x01, 0x2e, 0x35, 0x27, 0x19, 0x27, 0x02, 0xfe, 0x14, 0x05, 0xfe, 0x42, 0x5b, 0x86, 0x18,
15120 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xf5, 0x17, 0x78, 0xfe, 0x07, 0x80, 0xfe, 0x31, 0x44, 0x0a,
15121 0x08, 0x0b, 0x99, 0xfe, 0x20, 0x80, 0x05, 0x18, 0xfe, 0x70, 0x12, 0x73, 0x08, 0x06, 0xfe, 0x60,
15122 0x13, 0x04, 0xfe, 0xa2, 0x00, 0x2c, 0x1a, 0xfe, 0xac, 0x05, 0xfe, 0x31, 0xe4, 0x5f, 0x73, 0x08,
15123 0x0b, 0xfe, 0x4a, 0x13, 0x04, 0xfe, 0xa0, 0x00, 0x2c, 0xfe, 0x42, 0x12, 0x62, 0x2f, 0xfe, 0x6c,
15124 0x05, 0x19, 0x32, 0xf7, 0x01, 0x0c, 0x26, 0xfe, 0xc4, 0x05, 0x11, 0xfe, 0xe3, 0x00, 0x24, 0x73,
15125 0xfe, 0x4a, 0xf0, 0xfe, 0x96, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0x90, 0x05, 0xab, 0x20, 0xfe, 0x21,
15126 0x00, 0xa8, 0x20, 0xfe, 0x22, 0x00, 0xa2, 0x20, 0x8d, 0xfe, 0x09, 0x48, 0x01, 0x0c, 0x26, 0xfe,
15127 0xc4, 0x05, 0xfe, 0xe2, 0x08, 0x73, 0x08, 0xe0, 0x59, 0x01, 0x99, 0x20, 0x06, 0x16, 0xe8, 0x4b,
15128 0xfe, 0x27, 0x01, 0x0a, 0x08, 0x39, 0xb0, 0x46, 0x01, 0xb6, 0x17, 0xa6, 0x0a, 0x08, 0x06, 0x59,
15129 0x17, 0xfe, 0x0d, 0x00, 0x01, 0x2e, 0x01, 0x9b, 0x01, 0x9d, 0x35, 0xfe, 0x66, 0x0d, 0x02, 0x25,
15130 0x04, 0xfe, 0x9c, 0x00, 0x2c, 0xfe, 0x3e, 0x12, 0x04, 0x5b, 0x2c, 0xfe, 0x36, 0x13, 0x46, 0x01,
15131 0xb6, 0x26, 0xfe, 0x3c, 0x06, 0x0f, 0x06, 0x73, 0x08, 0x22, 0xfe, 0x02, 0x12, 0x69, 0x01, 0xfe,
15132 0xd0, 0x14, 0x1f, 0xfe, 0x32, 0x06, 0x11, 0xc8, 0x01, 0x41, 0x11, 0xfe, 0xe5, 0x00, 0x04, 0x5b,
15133 0xc2, 0x0e, 0x5b, 0x04, 0xfe, 0x9e, 0x00, 0x2c, 0xfe, 0x62, 0x12, 0x04, 0x56, 0x2c, 0xf1, 0x01,
15134 0xfe, 0x40, 0x19, 0x01, 0xfe, 0xaa, 0x19, 0xee, 0xd2, 0xec, 0x07, 0x6a, 0xff, 0x02, 0x00, 0x57,
15135 0x6c, 0x80, 0x1b, 0x58, 0xd1, 0xd2, 0x8b, 0x46, 0x01, 0xb6, 0x26, 0xfe, 0xa6, 0x06, 0x73, 0x08,
15136 0x1d, 0xa7, 0x7c, 0x0f, 0x5d, 0x01, 0xfe, 0xfe, 0x14, 0x1f, 0xfe, 0x9c, 0x06, 0x11, 0xc8, 0x01,
15137 0x41, 0x11, 0xfe, 0xe5, 0x00, 0x04, 0x56, 0xc2, 0x0e, 0x56, 0x09, 0x06, 0x01, 0xb6, 0xfc, 0x76,
15138 0x8f, 0x01, 0xf2, 0xb1, 0x11, 0xfe, 0xe2, 0x00, 0x2f, 0xfe, 0xbe, 0x06, 0x19, 0x32, 0xd7, 0xfe,
15139 0xda, 0x06, 0x83, 0xfe, 0x78, 0x07, 0xd4, 0xfe, 0x80, 0x07, 0x71, 0x8c, 0x02, 0x25, 0x0a, 0x08,
15140 0x0b, 0xfe, 0x2e, 0x12, 0x14, 0x18, 0x01, 0x0c, 0x14, 0x00, 0x01, 0x0c, 0x14, 0x00, 0x01, 0x0c,
15141 0x14, 0x00, 0x01, 0x0c, 0xfe, 0x99, 0xa4, 0x01, 0x0c, 0x14, 0x00, 0x02, 0xfe, 0x3e, 0x08, 0x6f,
15142 0x08, 0x1d, 0xea, 0x0a, 0x08, 0x1d, 0xfe, 0x30, 0x13, 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x0c, 0x14,
15143 0x00, 0x01, 0x0c, 0x14, 0x00, 0x01, 0x0c, 0x14, 0x00, 0x01, 0x0c, 0x14, 0x06, 0x01, 0x0c, 0x14,
15144 0x00, 0x02, 0xfe, 0xe6, 0x0b, 0x69, 0xfe, 0x9a, 0x81, 0x6d, 0x8d, 0xfe, 0x09, 0x6f, 0xfe, 0x93,
15145 0x45, 0x1a, 0xfe, 0x88, 0x07, 0x2f, 0xfe, 0x60, 0x07, 0x19, 0x32, 0xd7, 0xfe, 0x58, 0x07, 0x71,
15146 0x8c, 0x83, 0xfe, 0x78, 0x07, 0x02, 0x25, 0x01, 0x41, 0x02, 0xfe, 0xbe, 0x06, 0x14, 0x22, 0x02,
15147 0xfe, 0xbe, 0x06, 0xfe, 0x9c, 0xf7, 0xfe, 0xf4, 0x07, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x52,
15148 0xfe, 0xd6, 0x07, 0x0e, 0x65, 0x12, 0x66, 0x0a, 0x4f, 0x5f, 0x3a, 0x01, 0xfe, 0xd6, 0x18, 0x05,
15149 0x10, 0x85, 0xfe, 0x83, 0xe7, 0xfe, 0x95, 0x00, 0xa8, 0xfe, 0x03, 0x40, 0x0a, 0x4f, 0x78, 0x3a,
15150 0x01, 0xbc, 0xb5, 0xfe, 0x1f, 0x40, 0x16, 0x67, 0x01, 0xf8, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50,
15151 0xfe, 0x34, 0x51, 0xfe, 0xb6, 0x51, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0e, 0x63, 0x12, 0x64,
15152 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x28, 0x50, 0xfe, 0xaa, 0x50, 0x0e, 0x42, 0x12, 0x43,
15153 0x41, 0x0a, 0x08, 0x5f, 0xb0, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0e, 0x65, 0x12, 0x66, 0x0a,
15154 0x08, 0x78, 0xd1, 0x01, 0xbc, 0xfe, 0x1f, 0x80, 0x16, 0x67, 0xfe, 0x34, 0x90, 0xfe, 0xb6, 0x90,
15155 0x0e, 0x44, 0x12, 0x45, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0e, 0x63, 0x12, 0x64, 0xfe, 0x28,
15156 0x90, 0xfe, 0xaa, 0x90, 0x0e, 0x42, 0x12, 0x43, 0x0e, 0x31, 0x12, 0x3f, 0x24, 0x0e, 0x53, 0x0e,
15157 0x68, 0x0a, 0x4f, 0x22, 0x3a, 0x38, 0x07, 0xa5, 0x2f, 0xfe, 0x5e, 0x08, 0xfe, 0x9e, 0xf0, 0xfe,
15158 0x72, 0x08, 0xcc, 0x1a, 0x32, 0x38, 0x72, 0xfe, 0xed, 0x10, 0xaa, 0xfe, 0x96, 0x08, 0xac, 0xfe,
15159 0xb2, 0x08, 0x83, 0xfe, 0x8a, 0x08, 0xd4, 0xfe, 0x90, 0x08, 0x71, 0x8c, 0x02, 0x25, 0x01, 0x41,
15160 0xfe, 0xc9, 0x10, 0x14, 0x22, 0xfe, 0xc9, 0x10, 0x6f, 0x08, 0x06, 0xfe, 0x10, 0x12, 0x6f, 0x08,
15161 0x0b, 0x4e, 0x0a, 0x08, 0x0b, 0xfe, 0x8e, 0x12, 0xfe, 0x2e, 0x1c, 0xad, 0x6f, 0x08, 0x06, 0x4e,
15162 0x6f, 0x08, 0x0b, 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xcc, 0x09, 0xfe,
15163 0xac, 0xf0, 0xfe, 0xfa, 0x08, 0x02, 0xfe, 0xd8, 0x09, 0xfe, 0xb7, 0xf0, 0xfe, 0xf6, 0x08, 0xfe,
15164 0x02, 0xf6, 0x1d, 0x69, 0xfe, 0x70, 0x18, 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55,
15165 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x19, 0x92, 0xfe, 0x8c,
15166 0xf0, 0xfe, 0xf6, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xea, 0x08, 0xfe, 0x34, 0x1c, 0xfe, 0xcb, 0x10,
15167 0xfe, 0xad, 0xf0, 0xfe, 0x06, 0x09, 0x02, 0xfe, 0x12, 0x0b, 0xfe, 0x36, 0x1c, 0xfe, 0xbf, 0x10,
15168 0xfe, 0x2b, 0xf0, 0x92, 0xfe, 0x6b, 0x18, 0x1b, 0xfe, 0x00, 0xfe, 0xe1, 0xcd, 0xfe, 0xd2, 0xf0,
15169 0x92, 0xfe, 0x76, 0x18, 0x1b, 0x18, 0x1a, 0x92, 0x04, 0xe7, 0x1b, 0x06, 0x1a, 0x92, 0xaa, 0x57,
15170 0xac, 0x57, 0xfe, 0x34, 0x1c, 0xfe, 0x36, 0x1c, 0xfe, 0x89, 0x10, 0x8f, 0x62, 0x3b, 0x17, 0xa6,
15171 0x01, 0x2e, 0x13, 0xfe, 0x35, 0x00, 0x35, 0x54, 0x13, 0x90, 0x02, 0x54, 0xf9, 0xaf, 0x0b, 0xfe,
15172 0x1a, 0x12, 0x50, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xeb, 0xde, 0xfe, 0x74,
15173 0x18, 0x91, 0x93, 0x1a, 0xfe, 0xc8, 0x08, 0x02, 0x57, 0x0a, 0x08, 0x5f, 0x2e, 0x04, 0x31, 0x2b,
15174 0x3f, 0x0e, 0x44, 0x12, 0x45, 0x82, 0x31, 0x5a, 0x3f, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18, 0xfe,
15175 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x36, 0x44, 0x21, 0x45, 0x04, 0x53, 0x2b, 0x68, 0x91, 0xfe, 0xe3,
15176 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18, 0x91, 0xfe, 0xe3, 0x54, 0x93, 0xc9, 0x52, 0xfe, 0xc8,
15177 0x08, 0x02, 0x57, 0xfe, 0x37, 0xf0, 0xfe, 0xd4, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x5a, 0x09, 0x02,
15178 0x57, 0xf9, 0xaf, 0x0b, 0x28, 0xfe, 0xf4, 0x0a, 0x36, 0x53, 0x21, 0x68, 0x52, 0xfe, 0x38, 0x0a,
15179 0x07, 0xfe, 0xc0, 0x07, 0x46, 0x61, 0x00, 0xd9, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x06,
15180 0x0a, 0x91, 0x96, 0xfe, 0x1e, 0x0a, 0x36, 0x53, 0x91, 0xfe, 0xe3, 0x54, 0x4d, 0x53, 0x6e, 0x68,
15181 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x57, 0x36, 0x53, 0x21, 0x68, 0xfe, 0x14, 0x59, 0xfe,
15182 0x95, 0x59, 0xeb, 0x4d, 0x53, 0x4d, 0x68, 0x02, 0x57, 0x0a, 0x08, 0x5f, 0xfe, 0x82, 0x12, 0x0a,
15183 0x08, 0x22, 0xfe, 0x66, 0x13, 0x2a, 0x67, 0x70, 0xd0, 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe,
15184 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6b, 0x33, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59,
15185 0x52, 0xfe, 0xd0, 0x08, 0x04, 0x65, 0x2b, 0x66, 0x0e, 0xb3, 0x12, 0x90, 0x4d, 0x65, 0x6e, 0x66,
15186 0x01, 0xbc, 0xb5, 0x6b, 0x33, 0x16, 0x67, 0x82, 0x31, 0x5a, 0x3f, 0x36, 0x44, 0x21, 0x45, 0x93,
15187 0xc9, 0xfe, 0x04, 0xfa, 0x31, 0xfe, 0x05, 0xfa, 0x3f, 0x01, 0xf8, 0xfe, 0x36, 0x10, 0x24, 0x0e,
15188 0xb3, 0x0e, 0x90, 0x36, 0x44, 0x21, 0x45, 0xad, 0x0a, 0x08, 0x22, 0x1a, 0xfe, 0xd0, 0x08, 0x36,
15189 0x42, 0x21, 0x43, 0x0a, 0x08, 0xfe, 0xf7, 0x00, 0x3a, 0x04, 0x63, 0x2b, 0x64, 0xfe, 0x10, 0x58,
15190 0xfe, 0x91, 0x58, 0x4d, 0x53, 0x6e, 0x68, 0x02, 0xfe, 0xee, 0x09, 0x0a, 0x08, 0x22, 0x1a, 0xfe,
15191 0xd0, 0x08, 0x0a, 0x08, 0xfe, 0xf7, 0x00, 0x3a, 0xeb, 0xde, 0x69, 0xfe, 0x10, 0x90, 0xfe, 0x92,
15192 0x90, 0xfe, 0xd3, 0x10, 0x3e, 0x05, 0xca, 0x1a, 0xfe, 0x02, 0x09, 0x11, 0xca, 0xf9, 0xaf, 0x0b,
15193 0xfe, 0x14, 0x13, 0x04, 0x42, 0x2b, 0x43, 0x52, 0xfe, 0x02, 0x09, 0xfe, 0x0c, 0x58, 0xfe, 0x8d,
15194 0x58, 0x02, 0x57, 0x24, 0x46, 0xfe, 0x19, 0x80, 0xfe, 0xf1, 0x10, 0x0a, 0x08, 0x0b, 0xa7, 0xfe,
15195 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x94, 0x10, 0xfe, 0x6c, 0x19, 0x4d, 0x42, 0xfe, 0xed, 0x19,
15196 0x6e, 0x43, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x1b, 0xfe, 0x00, 0xff, 0x30,
15197 0xfe, 0x7a, 0x10, 0xcd, 0xfe, 0xd2, 0xf0, 0xfe, 0x8c, 0x0b, 0xfe, 0x76, 0x18, 0x1b, 0x18, 0xa9,
15198 0x04, 0xe7, 0x1b, 0x06, 0x87, 0x13, 0xfe, 0x16, 0x00, 0x02, 0x54, 0xfe, 0xd1, 0xf0, 0xfe, 0xc2,
15199 0x0b, 0x17, 0xa5, 0x01, 0x2e, 0x13, 0xfe, 0x17, 0x00, 0xfe, 0x48, 0x10, 0xfe, 0xce, 0xf0, 0xfe,
15200 0xaa, 0x0b, 0x13, 0xfe, 0x21, 0x00, 0x02, 0x54, 0xfe, 0xcd, 0xf0, 0xfe, 0xb6, 0x0b, 0x13, 0xfe,
15201 0x22, 0x00, 0x02, 0x54, 0xfe, 0xcb, 0xf0, 0xfe, 0xc2, 0x0b, 0x13, 0xfe, 0x24, 0x00, 0x02, 0x54,
15202 0xfe, 0xd0, 0xf0, 0xfe, 0xcc, 0x0b, 0x13, 0xae, 0xdf, 0xfe, 0xcf, 0xf0, 0xfe, 0xd6, 0x0b, 0x13,
15203 0x8d, 0xdc, 0xfe, 0xcc, 0xf0, 0xfe, 0xe6, 0x0b, 0xfe, 0x84, 0x80, 0xaf, 0x22, 0xfe, 0xd5, 0x12,
15204 0x13, 0xfe, 0x12, 0x00, 0x2f, 0xfe, 0xe6, 0x0b, 0x19, 0x32, 0xaa, 0x25, 0xac, 0x25, 0x38, 0xfc,
15205 0x2f, 0xfe, 0xfa, 0x0b, 0x19, 0x32, 0x83, 0xfe, 0x16, 0x0c, 0x71, 0x8c, 0xaa, 0xfe, 0xf4, 0x07,
15206 0xac, 0xfe, 0xf4, 0x07, 0x02, 0x25, 0x01, 0x41, 0xfe, 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0x8f,
15207 0x84, 0x74, 0xfe, 0x89, 0xf0, 0x25, 0x23, 0x29, 0xfe, 0xe9, 0x09, 0x01, 0x0c, 0x84, 0x74, 0x1f,
15208 0x25, 0x23, 0x29, 0x98, 0x35, 0xfe, 0x4e, 0x0c, 0x19, 0x32, 0x02, 0xfe, 0x42, 0x0c, 0xcc, 0x4e,
15209 0x13, 0xfe, 0x42, 0x00, 0x02, 0x54, 0xa4, 0x06, 0xfe, 0x81, 0x49, 0xfe, 0xcc, 0x12, 0x0a, 0x08,
15210 0x0b, 0xf1, 0x13, 0x00, 0x60, 0x0b, 0xfe, 0x6a, 0x12, 0x60, 0xfe, 0x28, 0x00, 0x28, 0xfe, 0x94,
15211 0x0d, 0x0f, 0x7e, 0x01, 0x15, 0x05, 0x00, 0x87, 0x37, 0xfe, 0x28, 0x00, 0x02, 0xfe, 0x94, 0x0d,
15212 0x01, 0x9b, 0x01, 0x9d, 0x0f, 0xc7, 0x01, 0xfe, 0xf0, 0x0e, 0xb9, 0x07, 0x3d, 0x09, 0xa1, 0x01,
15213 0x40, 0x11, 0x48, 0x07, 0x1e, 0x09, 0x51, 0x01, 0x79, 0x02, 0x27, 0x13, 0xfe, 0x44, 0x00, 0x60,
15214 0x0b, 0xa7, 0x37, 0x0b, 0xfe, 0xc0, 0x10, 0x01, 0x99, 0x37, 0x0b, 0xfe, 0xb6, 0x10, 0x01, 0x99,
15215 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xfe, 0x0a, 0x13, 0x37, 0x0b, 0x13, 0xfe, 0x43, 0x00, 0xc0,
15216 0x0a, 0x4f, 0x0b, 0x3a, 0x01, 0x9b, 0x01, 0x9d, 0xb9, 0x07, 0x3d, 0x09, 0xa1, 0x01, 0x40, 0x11,
15217 0x48, 0x07, 0x1e, 0x09, 0x51, 0x01, 0x79, 0x86, 0x0b, 0xb9, 0x1c, 0xd3, 0x02, 0xfe, 0x4c, 0x03,
15218 0x0a, 0x08, 0x0b, 0xa9, 0x37, 0x0b, 0x13, 0x00, 0xfe, 0x54, 0x10, 0x6f, 0x08, 0x1d, 0xfe, 0x50,
15219 0x12, 0x0a, 0x08, 0x1d, 0xfe, 0x48, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x52, 0x0d,
15220 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x58, 0x0d, 0x0a, 0x4f, 0x1d, 0x3a, 0xfe, 0x95, 0x10,
15221 0x13, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x69, 0xfe, 0x26, 0x10, 0x13, 0xfe, 0x13, 0x00,
15222 0xdc, 0x13, 0xfe, 0x47, 0x00, 0xa8, 0x13, 0xfe, 0x41, 0x00, 0xa2, 0x13, 0xfe, 0x24, 0x00, 0x04,
15223 0x7d, 0x2c, 0x28, 0xf4, 0x69, 0xfe, 0x04, 0xe6, 0x1d, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0xb9,
15224 0x01, 0xfe, 0xf8, 0x0e, 0x02, 0x27, 0xdd, 0x17, 0x0b, 0x4b, 0xfb, 0xe5, 0x17, 0xfe, 0x31, 0x00,
15225 0x4b, 0xc3, 0x01, 0xfe, 0xfc, 0x0f, 0x02, 0xfe, 0xc6, 0x01, 0x1c, 0xfe, 0x06, 0xec, 0xfe, 0xb9,
15226 0x00, 0x89, 0x37, 0x39, 0xc6, 0x30, 0x1c, 0xfe, 0x06, 0xea, 0xfe, 0xb9, 0x00, 0xfe, 0x47, 0x4b,
15227 0x7c, 0xfe, 0x75, 0x57, 0x04, 0x5e, 0xfe, 0x98, 0x56, 0xfe, 0x28, 0x12, 0x0f, 0x7e, 0xfe, 0xfa,
15228 0x14, 0x46, 0xed, 0x0f, 0xc7, 0xfe, 0xf0, 0x14, 0xfe, 0x49, 0x54, 0x95, 0xfe, 0x08, 0x0e, 0x0f,
15229 0x1e, 0xfe, 0xe4, 0x14, 0xfe, 0x44, 0x48, 0x02, 0xfe, 0x4c, 0x03, 0x0f, 0x5e, 0xfe, 0xc8, 0x14,
15230 0x89, 0x37, 0x39, 0xc6, 0x30, 0x1c, 0xfe, 0xce, 0x47, 0xfe, 0xbd, 0x13, 0x02, 0x27, 0x2a, 0x2d,
15231 0x05, 0x10, 0xfe, 0x78, 0x12, 0x24, 0x16, 0x5d, 0x16, 0xb2, 0x2a, 0x48, 0x46, 0x4b, 0x48, 0xcc,
15232 0xd9, 0xfe, 0xbc, 0xf0, 0xfe, 0xa4, 0x0e, 0x07, 0x06, 0x16, 0x5d, 0x01, 0xfe, 0xb0, 0x16, 0x04,
15233 0xfe, 0x38, 0x01, 0x2b, 0xfe, 0x3a, 0x01, 0x52, 0xfe, 0xa8, 0x0e, 0x04, 0xfe, 0x38, 0x01, 0x1b,
15234 0xfe, 0xf0, 0xff, 0x0e, 0xfe, 0x60, 0x01, 0x04, 0xfe, 0x3a, 0x01, 0x0e, 0xfe, 0x62, 0x01, 0x20,
15235 0x06, 0x16, 0x48, 0xfe, 0x04, 0xec, 0x2d, 0x07, 0x2d, 0x09, 0x3c, 0x1c, 0x01, 0x40, 0x81, 0xfe,
15236 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x20, 0x17, 0x11, 0x48, 0xd3, 0x07, 0x06, 0x03, 0x24,
15237 0x03, 0x2a, 0x5d, 0xfe, 0xf7, 0x12, 0x2a, 0xb2, 0x70, 0x16, 0xb2, 0x05, 0xa5, 0xfe, 0x93, 0x13,
15238 0xfe, 0x24, 0x1c, 0x17, 0x18, 0x4b, 0xfb, 0xe5, 0xfe, 0xd9, 0x10, 0x9a, 0xfe, 0x03, 0xdc, 0xfe,
15239 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0x9a, 0xfe, 0x03, 0xdc, 0x24, 0xfe, 0x70, 0x57, 0xfe, 0x33,
15240 0x54, 0xfe, 0x3b, 0x54, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0x9a, 0x24, 0xfe, 0x00, 0xcc,
15241 0x03, 0xfe, 0x03, 0x57, 0x9a, 0x7f, 0x03, 0x01, 0xfe, 0x50, 0x17, 0x3e, 0x05, 0x48, 0xfe, 0x0a,
15242 0x13, 0x07, 0x1e, 0x09, 0x51, 0xdc, 0x01, 0x9b, 0x01, 0x9d, 0x07, 0x3d, 0x09, 0xa1, 0x01, 0x40,
15243 0x11, 0xfe, 0xe9, 0x00, 0x0a, 0x08, 0x8d, 0xfe, 0x52, 0x13, 0x01, 0xfe, 0xe2, 0x16, 0xfe, 0x1e,
15244 0x1c, 0xfe, 0x14, 0x90, 0x0e, 0xfe, 0x64, 0x01, 0xfe, 0x16, 0x90, 0x0e, 0xfe, 0x66, 0x01, 0x0a,
15245 0x08, 0x78, 0xea, 0xfe, 0x03, 0x80, 0x72, 0x4c, 0x11, 0x7b, 0x07, 0x2d, 0x09, 0x3c, 0x1c, 0x97,
15246 0x01, 0xa0, 0xfe, 0x62, 0x08, 0x70, 0x4c, 0x11, 0x7b, 0x07, 0x2d, 0x09, 0x3c, 0x1c, 0x97, 0x01,
15247 0xa0, 0x6b, 0x33, 0x11, 0x7b, 0x07, 0x2d, 0x09, 0x3c, 0x1c, 0x97, 0x01, 0x79, 0x03, 0xfe, 0x08,
15248 0x1c, 0x04, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x04, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x04,
15249 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x04, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
15250 0x20, 0x8b, 0x16, 0xfe, 0xb9, 0x00, 0x24, 0x0e, 0x5b, 0x0e, 0x56, 0x20, 0x10, 0x16, 0x2d, 0x16,
15251 0x3c, 0x50, 0xa4, 0xfe, 0x93, 0x00, 0x07, 0x2d, 0x09, 0x3c, 0x1c, 0x01, 0x79, 0x81, 0x11, 0x7b,
15252 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xd6, 0x0f, 0xdd, 0x8f, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
15253 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x1c, 0xfe, 0x0c, 0x14, 0x89, 0xfe, 0x07, 0xe6, 0x39, 0xfe, 0xce,
15254 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x99, 0x0f, 0x3d, 0x01, 0x15, 0x05, 0x10, 0xda, 0x0f, 0x1e,
15255 0x01, 0x15, 0x05, 0x10, 0xe1, 0xfe, 0x44, 0x58, 0x4c, 0xfe, 0x01, 0xec, 0xc3, 0xfe, 0x9e, 0x40,
15256 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1d, 0xa3, 0x33, 0x01, 0xfe, 0xf8, 0x0e, 0xfe, 0xc9,
15257 0x10, 0x03, 0x38, 0x84, 0x74, 0x23, 0x29, 0xba, 0x05, 0x1d, 0xfe, 0x48, 0x12, 0x05, 0x0b, 0xfe,
15258 0x4c, 0x12, 0x05, 0x18, 0xfe, 0x30, 0x12, 0x05, 0xd5, 0x1a, 0xfe, 0xa0, 0x11, 0x05, 0xfe, 0x23,
15259 0x00, 0x1a, 0xfe, 0xac, 0x11, 0x05, 0x06, 0x1a, 0xa9, 0x05, 0x22, 0xfe, 0x12, 0x12, 0x05, 0x00,
15260 0x1a, 0x25, 0x17, 0xd5, 0x01, 0x2e, 0xce, 0x3b, 0x01, 0x0c, 0x83, 0x41, 0x03, 0x3b, 0x11, 0xfe,
15261 0xcc, 0x00, 0x02, 0x27, 0x3b, 0x3e, 0x05, 0xca, 0xfe, 0xe3, 0x13, 0x36, 0x42, 0x21, 0x43, 0x52,
15262 0xfe, 0x5e, 0x11, 0x0a, 0x08, 0x5f, 0xfe, 0x72, 0x12, 0x82, 0x31, 0x5a, 0x3f, 0x93, 0xc9, 0x95,
15263 0xfe, 0x28, 0x11, 0x2a, 0x67, 0xfe, 0x26, 0x13, 0x04, 0xb3, 0x2b, 0x90, 0x52, 0xfe, 0x78, 0x0d,
15264 0x0e, 0x65, 0x12, 0x66, 0x24, 0x0e, 0xb3, 0x0e, 0x90, 0x01, 0xbc, 0x20, 0x8b, 0x72, 0x16, 0x67,
15265 0x01, 0xf8, 0x82, 0x31, 0x5a, 0x3f, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x31,
15266 0xfe, 0x05, 0xfa, 0x3f, 0xfe, 0x91, 0x10, 0x04, 0x44, 0x2b, 0x45, 0xfe, 0x40, 0x56, 0xfe, 0xe1,
15267 0x56, 0x0e, 0x44, 0x12, 0x45, 0xab, 0x82, 0x31, 0x5a, 0x3f, 0x93, 0xc9, 0x04, 0x63, 0x2b, 0x64,
15268 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0e, 0x63, 0x12, 0x64, 0x0a, 0x08, 0x5f, 0xfe, 0x1e, 0x12,
15269 0x2a, 0x67, 0xfe, 0x1f, 0x40, 0x04, 0x65, 0x2b, 0x66, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x04,
15270 0x44, 0x2b, 0x45, 0xfe, 0x34, 0x50, 0xfe, 0xb6, 0x50, 0x04, 0x63, 0x2b, 0x64, 0xfe, 0x08, 0x50,
15271 0xfe, 0x8a, 0x50, 0x04, 0x42, 0x2b, 0x43, 0xfe, 0x28, 0x50, 0xfe, 0xaa, 0x50, 0x02, 0x9c, 0x20,
15272 0x06, 0x16, 0xfa, 0x02, 0x7a, 0x3b, 0x01, 0x0c, 0x1f, 0x55, 0x23, 0x29, 0xba, 0x05, 0x06, 0x28,
15273 0x55, 0x3e, 0x05, 0xca, 0x28, 0x7a, 0x01, 0xf2, 0x1b, 0x58, 0x1a, 0x55, 0x0a, 0x08, 0x0b, 0xe4,
15274 0x36, 0x42, 0x21, 0x43, 0xfe, 0x0a, 0x55, 0x30, 0xfe, 0x8b, 0x55, 0x4d, 0x42, 0x6e, 0x43, 0xfe,
15275 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x7a, 0xde, 0xfe, 0x0a, 0x45, 0xfe, 0x19, 0x41, 0x02, 0x7a,
15276 0x3b, 0x01, 0x0c, 0x1f, 0xc0, 0x23, 0x29, 0xfe, 0xe9, 0x09, 0x60, 0x18, 0xfe, 0x94, 0x12, 0x60,
15277 0x0b, 0x59, 0x02, 0x55, 0x2f, 0xb0, 0x19, 0x32, 0x1f, 0xc0, 0x23, 0x29, 0x98, 0x05, 0x18, 0x28,
15278 0x55, 0x01, 0x0c, 0x1f, 0xc0, 0x23, 0x29, 0xfe, 0xe8, 0x09, 0x50, 0x04, 0xfe, 0x9c, 0x00, 0x2c,
15279 0x30, 0xfe, 0xbb, 0x45, 0x60, 0x00, 0x4e, 0x37, 0x06, 0xa4, 0x58, 0xfe, 0xc0, 0x14, 0xfe, 0xf8,
15280 0x14, 0xb1, 0x3e, 0x05, 0xc8, 0xfe, 0x16, 0x13, 0x04, 0xfe, 0x9e, 0x00, 0x2c, 0xa9, 0x04, 0x56,
15281 0x2c, 0x30, 0x62, 0x02, 0x7a, 0xfe, 0xc0, 0x5d, 0xfe, 0xe4, 0x14, 0xfe, 0x03, 0x17, 0x04, 0x5b,
15282 0xc2, 0x0e, 0x5b, 0x62, 0x3b, 0x01, 0x0c, 0x26, 0x9c, 0x01, 0xfe, 0xd0, 0x14, 0x02, 0x9c, 0x2f,
15283 0xfe, 0xb4, 0x12, 0x19, 0x32, 0x1f, 0x55, 0x23, 0x29, 0x98, 0x05, 0x06, 0x28, 0x55, 0xfe, 0xf6,
15284 0x14, 0xfe, 0x42, 0x58, 0xfe, 0x70, 0x14, 0xfe, 0x92, 0x14, 0xb1, 0xfe, 0x4a, 0xf4, 0x0b, 0x1a,
15285 0x55, 0xfe, 0x4a, 0xf4, 0x06, 0xd8, 0x3e, 0x05, 0xc8, 0xd1, 0x02, 0x7a, 0x04, 0x56, 0xc2, 0x0e,
15286 0x56, 0x62, 0x3b, 0x01, 0x0c, 0x26, 0x9c, 0x01, 0xfe, 0xfe, 0x14, 0x02, 0x9c, 0x26, 0xe2, 0x76,
15287 0xf7, 0x76, 0x03, 0x35, 0xfe, 0x18, 0x13, 0x71, 0xfe, 0x18, 0x13, 0x62, 0x3b, 0x01, 0x0c, 0xfe,
15288 0xe3, 0x10, 0x07, 0x6a, 0xff, 0x02, 0x00, 0x57, 0x6c, 0x80, 0x1b, 0xfe, 0xff, 0x7f, 0xfe, 0x30,
15289 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x07, 0x6a, 0xff, 0x02, 0x00, 0x57, 0x6c, 0x80, 0x1b, 0x58, 0xfe,
15290 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x07, 0x6a, 0xff, 0x02, 0x00, 0x57, 0x6c, 0x80, 0x03, 0x07,
15291 0x6a, 0xff, 0x02, 0x00, 0x57, 0x6c, 0x80, 0xfe, 0x0b, 0x58, 0x03, 0x0f, 0x5b, 0x01, 0x9f, 0x0f,
15292 0x56, 0x01, 0x9f, 0x03, 0xd0, 0x1b, 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x22, 0x6c,
15293 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6b, 0x33, 0x0e, 0x63,
15294 0x12, 0x64, 0x4d, 0x44, 0x6e, 0x45, 0x03, 0xfe, 0x62, 0x18, 0xfe, 0x82, 0x5a, 0xfe, 0xe1, 0x1a,
15295 0xbe, 0xfe, 0x02, 0x58, 0x03, 0x01, 0xfe, 0x40, 0x19, 0xfe, 0x42, 0x48, 0x69, 0x50, 0x7c, 0x01,
15296 0x0c, 0x1f, 0xfe, 0xc8, 0x14, 0x23, 0x29, 0xfe, 0xe9, 0x09, 0xfe, 0xc1, 0x59, 0x01, 0x0c, 0x1f,
15297 0xfe, 0xc8, 0x14, 0x23, 0x29, 0xfe, 0xe8, 0x0a, 0x04, 0xfe, 0x9e, 0x00, 0x2c, 0xfe, 0xc2, 0x12,
15298 0x24, 0xb8, 0x1d, 0xe4, 0x60, 0xd6, 0x77, 0xfe, 0x18, 0x14, 0x59, 0x07, 0x06, 0x09, 0xd6, 0xa4,
15299 0xfe, 0x00, 0x10, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa8, 0xff, 0x02, 0x83, 0x55, 0xb8,
15300 0x18, 0xfe, 0x12, 0x13, 0x61, 0xfe, 0x30, 0x00, 0x95, 0xf3, 0x09, 0x88, 0x07, 0x06, 0xfe, 0x56,
15301 0x10, 0xb8, 0x0b, 0xfe, 0x16, 0x13, 0x61, 0xfe, 0x64, 0x00, 0x95, 0xf3, 0x0f, 0xfe, 0x64, 0x00,
15302 0x09, 0xae, 0x07, 0x06, 0xfe, 0x28, 0x10, 0xb8, 0x06, 0xfe, 0x5e, 0x13, 0x61, 0xfe, 0xc8, 0x00,
15303 0x95, 0xf3, 0x0f, 0xfe, 0xc8, 0x00, 0x09, 0x5d, 0x07, 0x06, 0xab, 0x61, 0xfe, 0x90, 0x01, 0x96,
15304 0xfe, 0x7e, 0x14, 0x7c, 0xad, 0xfe, 0x43, 0xf4, 0xb2, 0xfe, 0x56, 0xf0, 0xfe, 0x90, 0x14, 0xfe,
15305 0x04, 0xf4, 0x6a, 0xfe, 0x43, 0xf4, 0xae, 0xfe, 0xf3, 0x10, 0xb7, 0x01, 0xf1, 0x1b, 0x58, 0xda,
15306 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x8b, 0x96, 0xfe, 0xc2, 0x14, 0x7c, 0xfe, 0x14, 0x10, 0xfe,
15307 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0xec, 0x96, 0xfe, 0xc2, 0x14, 0xd2, 0xec, 0xa2, 0x50, 0x7c, 0x07,
15308 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x03, 0x50, 0x07, 0x0b, 0x03, 0x14, 0x06, 0x01, 0x0c,
15309 0x26, 0xfe, 0xfc, 0x14, 0x14, 0x0b, 0x01, 0x0c, 0x26, 0xfe, 0xfc, 0x14, 0x14, 0x18, 0x01, 0x0c,
15310 0x26, 0xfe, 0xfc, 0x14, 0x76, 0xfe, 0x89, 0x49, 0x01, 0x0c, 0x03, 0x14, 0x06, 0x01, 0x0c, 0x26,
15311 0xb4, 0x14, 0x18, 0x01, 0x0c, 0x26, 0xb4, 0x14, 0x06, 0x01, 0x0c, 0x26, 0xb4, 0xfe, 0x89, 0x49,
15312 0x01, 0x0c, 0x26, 0xb4, 0x76, 0xfe, 0x89, 0x4a, 0x01, 0x0c, 0x03, 0x50, 0x03, 0x2a, 0xe8, 0x05,
15313 0x06, 0xfe, 0x44, 0x13, 0xb5, 0x16, 0xe8, 0xfe, 0x49, 0xf4, 0x00, 0x59, 0x76, 0xce, 0x62, 0xfe,
15314 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf7, 0x01, 0x0c, 0x3e, 0x05, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13,
15315 0x1f, 0xfe, 0x80, 0x15, 0x24, 0x16, 0xfa, 0x01, 0x41, 0x2a, 0xfa, 0x05, 0x06, 0x4e, 0x0a, 0x4f,
15316 0x06, 0x3a, 0x03, 0x0e, 0x5c, 0x12, 0x8e, 0xfe, 0x43, 0x58, 0x01, 0x15, 0x05, 0x10, 0xfe, 0x1e,
15317 0x12, 0x49, 0xee, 0x94, 0x01, 0x47, 0xfe, 0x90, 0x4d, 0xe6, 0x10, 0xfe, 0xc5, 0x59, 0x01, 0x47,
15318 0xfe, 0x8d, 0x56, 0xbe, 0x49, 0x03, 0x49, 0x21, 0x8e, 0x01, 0x15, 0x49, 0x94, 0x01, 0x47, 0xe9,
15319 0x10, 0xe6, 0x10, 0x21, 0x5c, 0x61, 0x1e, 0x87, 0x0f, 0x5e, 0x01, 0xc5, 0x03, 0x0e, 0x5c, 0x12,
15320 0x8e, 0xfe, 0xc3, 0x58, 0x01, 0x15, 0x05, 0x10, 0xfe, 0x1a, 0x12, 0x49, 0xee, 0x94, 0x01, 0x47,
15321 0xe9, 0x10, 0xfe, 0x80, 0x4d, 0xfe, 0xc5, 0x59, 0x01, 0x47, 0x49, 0x03, 0x49, 0x21, 0x5c, 0x01,
15322 0x15, 0x49, 0x94, 0x01, 0x47, 0xe9, 0x10, 0xe6, 0x10, 0x21, 0x5c, 0x61, 0x1e, 0x87, 0x0f, 0x5e,
15323 0x01, 0xc5, 0x03, 0x0e, 0x5c, 0x12, 0x8e, 0xfe, 0x43, 0x58, 0x01, 0x15, 0xfe, 0x42, 0x48, 0x94,
15324 0x01, 0x47, 0xfe, 0xc0, 0x5a, 0xb7, 0xfe, 0x00, 0xcd, 0xfe, 0x01, 0xcc, 0xfe, 0x4a, 0x46, 0xe4,
15325 0x9a, 0x7f, 0x05, 0x10, 0xfe, 0x2e, 0x13, 0x5a, 0x5c, 0xfe, 0x4d, 0xf4, 0x1e, 0xe2, 0x0f, 0x5e,
15326 0x01, 0x9f, 0xad, 0xfe, 0x40, 0x4c, 0xfe, 0xc5, 0x58, 0x01, 0x47, 0xfe, 0x00, 0x07, 0x7f, 0x05,
15327 0x10, 0x87, 0x5a, 0x8e, 0xfe, 0x05, 0x57, 0xfe, 0x08, 0x10, 0xfe, 0x45, 0x58, 0x01, 0x47, 0xfe,
15328 0x8d, 0x56, 0xbe, 0xfe, 0x80, 0x4c, 0xfe, 0x05, 0x17, 0x03, 0x09, 0x10, 0x75, 0x6d, 0xfe, 0x60,
15329 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xe3, 0x39, 0x9e, 0xfe, 0xc4, 0x16,
15330 0x01, 0xfe, 0xca, 0x17, 0xd9, 0x8a, 0x39, 0x6d, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xbf,
15331 0x28, 0xfe, 0xb4, 0x16, 0xfe, 0xda, 0x10, 0x09, 0x10, 0x75, 0x04, 0xfe, 0x64, 0x01, 0xfe, 0x00,
15332 0xf4, 0x22, 0xfe, 0x18, 0x58, 0x04, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x8a, 0x22, 0xfe, 0x3c,
15333 0x90, 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6d, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe,
15334 0x1c, 0xf7, 0x22, 0x9e, 0xfe, 0x0e, 0x17, 0xfe, 0xb6, 0x14, 0x30, 0x03, 0xbf, 0x28, 0xfe, 0xe6,
15335 0x16, 0xfe, 0x9c, 0x10, 0x09, 0x10, 0x75, 0xbe, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xdf, 0xe3, 0x31,
15336 0x9e, 0xfe, 0x30, 0x17, 0xfe, 0x94, 0x14, 0x2e, 0x8a, 0x31, 0x6d, 0x1d, 0xfe, 0xaf, 0x19, 0xfe,
15337 0x98, 0xe7, 0x00, 0x03, 0xbf, 0x28, 0xfe, 0x24, 0x17, 0xfe, 0x6c, 0x10, 0x09, 0x10, 0x75, 0xfe,
15338 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x8a, 0xe0, 0x6d, 0x1d, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0xe0,
15339 0x9e, 0xfe, 0x68, 0x17, 0xfe, 0x5c, 0x14, 0x30, 0x03, 0xbf, 0x28, 0xfe, 0x54, 0x17, 0xfe, 0x42,
15340 0x10, 0xfe, 0x02, 0xf6, 0x10, 0x75, 0xfe, 0x18, 0xfe, 0x65, 0xfe, 0x19, 0xfe, 0x66, 0xd0, 0xe3,
15341 0x78, 0x9e, 0xfe, 0x8e, 0x17, 0xfe, 0x36, 0x14, 0xe2, 0x8a, 0x78, 0x46, 0xfe, 0x83, 0x58, 0xfe,
15342 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x6b, 0x33,
15343 0x03, 0x6b, 0x33, 0xfe, 0x12, 0x45, 0x28, 0xfe, 0x7e, 0x17, 0x17, 0x06, 0x4b, 0xfb, 0xe5, 0x02,
15344 0x27, 0xfe, 0x39, 0xf0, 0xfe, 0xd2, 0x17, 0x24, 0x03, 0xfe, 0x7e, 0x18, 0x1b, 0x18, 0x85, 0x07,
15345 0x0d, 0x03, 0x75, 0x04, 0xe7, 0x1b, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x1c, 0x0f, 0x1e,
15346 0x01, 0x15, 0x05, 0x10, 0x4e, 0x4c, 0xfe, 0x78, 0x14, 0xfe, 0x34, 0x12, 0x58, 0x89, 0x37, 0x39,
15347 0xc6, 0xfe, 0xe9, 0x13, 0x1c, 0x0f, 0x3d, 0x01, 0x15, 0x05, 0x10, 0x4e, 0x4c, 0xfe, 0x56, 0x14,
15348 0xb0, 0x58, 0x89, 0x37, 0x39, 0xc6, 0xfe, 0xe9, 0x13, 0x09, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b,
15349 0x13, 0xfe, 0x15, 0x00, 0x97, 0xa3, 0x33, 0x01, 0xfe, 0xf8, 0x0e, 0x09, 0x06, 0x03, 0x0a, 0x4f,
15350 0x39, 0x3a, 0x07, 0x3d, 0x09, 0xa1, 0x01, 0x40, 0x11, 0x48, 0x07, 0x1e, 0x09, 0x51, 0x01, 0x79,
15351 0x09, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x36, 0xfe, 0xa8, 0x00, 0x21, 0x7b, 0xfe,
15352 0x48, 0x55, 0x30, 0xfe, 0xc9, 0x55, 0x03, 0x2a, 0xc4, 0x72, 0x16, 0xc4, 0x03, 0x0f, 0xc7, 0x01,
15353 0x15, 0xed, 0x0f, 0x7e, 0x01, 0x15, 0xfe, 0x49, 0x44, 0x28, 0xfe, 0xc8, 0x18, 0x0f, 0x1e, 0x01,
15354 0x15, 0x05, 0x10, 0x4e, 0x0f, 0x5e, 0x01, 0xc5, 0x0f, 0x7e, 0x01, 0x15, 0x72, 0x7f, 0x03, 0xfe,
15355 0x40, 0x5e, 0xfe, 0xe2, 0x08, 0xfe, 0xc0, 0x4c, 0x2a, 0x3c, 0x05, 0x10, 0xfe, 0x52, 0x12, 0x4c,
15356 0x05, 0x00, 0xfe, 0x18, 0x12, 0xfe, 0xe1, 0x18, 0xfe, 0x19, 0xf4, 0xfe, 0x7f, 0x00, 0x2e, 0xfe,
15357 0xe2, 0x08, 0x72, 0x4c, 0x3e, 0x05, 0x7b, 0xa7, 0xfe, 0x82, 0x48, 0xfe, 0x01, 0x80, 0xfe, 0xd7,
15358 0x10, 0xfe, 0xc4, 0x48, 0x07, 0x2d, 0x09, 0x3c, 0xfe, 0x40, 0x5f, 0x1c, 0x01, 0x40, 0x11, 0xfe,
15359 0xdd, 0x00, 0xfe, 0x14, 0x46, 0x07, 0x2d, 0x09, 0x3c, 0x01, 0x40, 0x11, 0xfe, 0xdd, 0x00, 0xfe,
15360 0x40, 0x4a, 0x70, 0xfe, 0x06, 0x17, 0xfe, 0x01, 0x07, 0xfe, 0x82, 0x48, 0xfe, 0x04, 0x17, 0x03,
15361 0xf0, 0x18, 0x77, 0xfe, 0x50, 0x19, 0x04, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
15362 0xf0, 0xd5, 0x77, 0xfe, 0x62, 0x19, 0x04, 0xfe, 0x92, 0x00, 0xcf, 0x1d, 0xdf, 0xf0, 0xfe, 0x0b,
15363 0x00, 0x77, 0xfe, 0x74, 0x19, 0x04, 0xfe, 0x94, 0x00, 0xcf, 0x22, 0xfe, 0x08, 0x10, 0x04, 0xfe,
15364 0x96, 0x00, 0xcf, 0x88, 0xfe, 0x4e, 0x45, 0xd8, 0xfe, 0x0a, 0x45, 0xff, 0x04, 0x68, 0x54, 0xfe,
15365 0xf1, 0x10, 0x1b, 0x8b, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4,
15366 0xfe, 0x00, 0x04, 0xd8, 0xfe, 0x48, 0xf4, 0x18, 0x96, 0xfe, 0xa8, 0x19, 0x07, 0x18, 0x03, 0x05,
15367 0xa5, 0xfe, 0x5a, 0xf0, 0xfe, 0xb8, 0x19, 0x20, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, 0x05, 0x1d,
15368 0xfe, 0x5a, 0xf0, 0xfe, 0xc6, 0x19, 0x20, 0xd6, 0xfe, 0x26, 0x10, 0x05, 0x18, 0x85, 0x20, 0x88,
15369 0xdf, 0x05, 0x0b, 0x85, 0x20, 0xae, 0xfe, 0x0e, 0x10, 0x05, 0x06, 0x85, 0x20, 0x5d, 0xce, 0xb5,
15370 0x03, 0x17, 0xfe, 0x09, 0x00, 0x01, 0x2e, 0x2f, 0xfe, 0xf6, 0x19, 0x04, 0x74, 0xb7, 0x03, 0x19,
15371 0xfe, 0x16, 0x1a, 0xfe, 0x14, 0xf0, 0x0c, 0x2f, 0xfe, 0x0a, 0x1a, 0x19, 0xfe, 0x16, 0x1a, 0xfe,
15372 0x82, 0xf0, 0xfe, 0x0e, 0x1a, 0x03, 0xff, 0x34, 0x00, 0x00,};
15374 STATIC unsigned short _adv_asc38C0800_size =
15375 sizeof(_adv_asc38C0800_buf); /* 0x14AA */
15376 STATIC unsigned long _adv_asc38C0800_chksum =
15377 0x05297A65UL; /* Expanded checksum. */
15379 /* a_init.c */
15381 * EEPROM Configuration.
15383 * All drivers should use this structure to set the default EEPROM
15384 * configuration. The BIOS now uses this structure when it is built.
15385 * Additional structure information can be found in a_condor.h where
15386 * the structure is defined.
15388 STATIC ADVEEP_3550_CONFIG
15389 Default_3550_EEPROM_Config ASC_INITDATA = {
15390 ADV_EEPROM_BIOS_ENABLE, /* cfg_msw */
15391 0x0000, /* cfg_lsw */
15392 0xFFFF, /* disc_enable */
15393 0xFFFF, /* wdtr_able */
15394 0xFFFF, /* sdtr_able */
15395 0xFFFF, /* start_motor */
15396 0xFFFF, /* tagqng_able */
15397 0xFFFF, /* bios_scan */
15398 0, /* scam_tolerant */
15399 7, /* adapter_scsi_id */
15400 0, /* bios_boot_delay */
15401 3, /* scsi_reset_delay */
15402 0, /* bios_id_lun */
15403 0, /* termination */
15404 0, /* reserved1 */
15405 0xFFE7, /* bios_ctrl */
15406 0xFFFF, /* ultra_able */
15407 0, /* reserved2 */
15408 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
15409 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
15410 0, /* dvc_cntl */
15411 0, /* bug_fix */
15412 0, /* serial_number_word1 */
15413 0, /* serial_number_word2 */
15414 0, /* serial_number_word3 */
15415 0, /* check_sum */
15416 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */
15417 0, /* dvc_err_code */
15418 0, /* adv_err_code */
15419 0, /* adv_err_addr */
15420 0, /* saved_dvc_err_code */
15421 0, /* saved_adv_err_code */
15422 0, /* saved_adv_err_addr */
15423 0 /* num_of_err */
15426 STATIC ADVEEP_38C0800_CONFIG
15427 Default_38C0800_EEPROM_Config ASC_INITDATA = {
15428 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_msw */
15429 0x0000, /* 01 cfg_lsw */
15430 0xFFFF, /* 02 disc_enable */
15431 0xFFFF, /* 03 wdtr_able */
15432 0x4444, /* 04 sdtr_speed1 */
15433 0xFFFF, /* 05 start_motor */
15434 0xFFFF, /* 06 tagqng_able */
15435 0xFFFF, /* 07 bios_scan */
15436 0, /* 08 scam_tolerant */
15437 7, /* 09 adapter_scsi_id */
15438 0, /* bios_boot_delay */
15439 3, /* 10 scsi_reset_delay */
15440 0, /* bios_id_lun */
15441 0, /* 11 termination_se */
15442 0, /* termination_lvd */
15443 0xFFE7, /* 12 bios_ctrl */
15444 0x4444, /* 13 sdtr_speed2 */
15445 0x4444, /* 14 sdtr_speed3 */
15446 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
15447 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
15448 0, /* 16 dvc_cntl */
15449 0x4444, /* 17 sdtr_speed4 */
15450 0, /* 18 serial_number_word1 */
15451 0, /* 19 serial_number_word2 */
15452 0, /* 20 serial_number_word3 */
15453 0, /* 21 check_sum */
15454 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 22-29 oem_name[16] */
15455 0, /* 30 dvc_err_code */
15456 0, /* 31 adv_err_code */
15457 0, /* 32 adv_err_addr */
15458 0, /* 33 saved_dvc_err_code */
15459 0, /* 34 saved_adv_err_code */
15460 0, /* 35 saved_adv_err_addr */
15461 0, /* 36 reserved */
15462 0, /* 37 reserved */
15463 0, /* 38 reserved */
15464 0, /* 39 reserved */
15465 0, /* 40 reserved */
15466 0, /* 41 reserved */
15467 0, /* 42 reserved */
15468 0, /* 43 reserved */
15469 0, /* 44 reserved */
15470 0, /* 45 reserved */
15471 0, /* 46 reserved */
15472 0, /* 47 reserved */
15473 0, /* 48 reserved */
15474 0, /* 49 reserved */
15475 0, /* 50 reserved */
15476 0, /* 51 reserved */
15477 0, /* 52 reserved */
15478 0, /* 53 reserved */
15479 0, /* 54 reserved */
15480 0, /* 55 reserved */
15481 0, /* 56 cisptr_lsw */
15482 0, /* 57 cisprt_msw */
15483 ADV_PCI_VENDOR_ID, /* 58 subsysvid */
15484 ADV_PCI_DEVID_38C0800_REV1, /* 59 subsysid */
15485 0, /* 60 reserved */
15486 0, /* 61 reserved */
15487 0, /* 62 reserved */
15488 0 /* 63 reserved */
15492 * Initialize the ADV_DVC_VAR structure.
15494 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
15496 * For a non-fatal error return a warning code. If there are no warnings
15497 * then 0 is returned.
15499 ASC_INITFUNC(
15500 STATIC int,
15501 AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
15504 ushort warn_code;
15505 AdvPortAddr iop_base;
15506 uchar pci_cmd_reg;
15507 int status;
15509 warn_code = 0;
15510 asc_dvc->err_code = 0;
15511 iop_base = asc_dvc->iop_base;
15514 * PCI Command Register
15517 if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
15518 AscPCIConfigCommandRegister))
15519 & AscPCICmdRegBits_BusMastering)
15520 != AscPCICmdRegBits_BusMastering)
15522 pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
15524 DvcAdvWritePCIConfigByte(asc_dvc,
15525 AscPCIConfigCommandRegister, pci_cmd_reg);
15527 if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister))
15528 & AscPCICmdRegBits_BusMastering)
15529 != AscPCICmdRegBits_BusMastering)
15531 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
15536 * PCI Latency Timer
15538 * If the "latency timer" register is 0x20 or above, then we don't need
15539 * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
15540 * comes up less than 0x20).
15542 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
15543 DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20);
15544 if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20)
15546 warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
15551 * Save the state of the PCI Configuration Command Register
15552 * "Parity Error Response Control" Bit. If the bit is clear (0),
15553 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
15554 * DMA parity errors.
15556 asc_dvc->cfg->control_flag = 0;
15557 if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
15558 & AscPCICmdRegBits_ParErrRespCtrl)) == 0)
15560 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
15563 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
15564 ADV_LIB_VERSION_MINOR;
15565 asc_dvc->cfg->chip_version =
15566 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
15568 ASC_DBG2(1, "iopb_chip_id_1: %x %x\n",
15569 (ushort) AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
15570 (ushort) ADV_CHIP_ID_BYTE);
15572 ASC_DBG2(1, "iopw_chip_id_0: %x %x\n",
15573 (ushort) AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
15574 (ushort) ADV_CHIP_ID_WORD);
15577 * Reset the chip to start and allow register writes.
15579 if (AdvFindSignature(iop_base) == 0)
15581 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
15582 return ADV_ERROR;
15584 else {
15586 * The caller must set 'chip_type' to a valid setting.
15588 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
15589 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
15590 asc_dvc->chip_type != ADV_CHIP_ASC38C1600)
15592 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
15593 return ADV_ERROR;
15597 * Reset Chip.
15599 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
15600 ADV_CTRL_REG_CMD_RESET);
15601 DvcSleepMilliSecond(100);
15602 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
15603 ADV_CTRL_REG_CMD_WR_IO_REG);
15605 if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800)
15607 if ((status = AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR)
15609 return ADV_ERROR;
15611 } else
15613 if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR)
15615 return ADV_ERROR;
15618 warn_code |= status;
15621 return warn_code;
15625 * Initialize the ASC-3550.
15627 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
15629 * For a non-fatal error return a warning code. If there are no warnings
15630 * then 0 is returned.
15632 STATIC int
15633 AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
15635 AdvPortAddr iop_base;
15636 ushort warn_code;
15637 ulong sum;
15638 int begin_addr;
15639 int end_addr;
15640 ushort code_sum;
15641 int word;
15642 int j;
15643 int adv_asc3550_expanded_size;
15644 ADV_CARR_T *carrp;
15645 ulong contig_len;
15646 long buf_size;
15647 ulong carr_paddr;
15648 int i;
15649 ushort scsi_cfg1;
15650 uchar tid;
15651 ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */
15652 ushort wdtr_able = 0, sdtr_able, tagqng_able;
15653 uchar max_cmd[ADV_MAX_TID + 1];
15655 /* If there is already an error, don't continue. */
15656 if (asc_dvc->err_code != 0)
15658 return ADV_ERROR;
15662 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
15664 if (asc_dvc->chip_type != ADV_CHIP_ASC3550)
15666 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
15667 return ADV_ERROR;
15670 warn_code = 0;
15671 iop_base = asc_dvc->iop_base;
15674 * Save the RISC memory BIOS region before writing the microcode.
15675 * The BIOS may already be loaded and using its RISC LRAM region
15676 * so its region must be saved and restored.
15678 * Note: This code makes the assumption, which is currently true,
15679 * that a chip reset does not clear RISC LRAM.
15681 for (i = 0; i < ASC_MC_BIOSLEN/2; i++)
15683 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]);
15687 * Save current per TID negotiated values.
15689 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA)
15691 ushort bios_version, major, minor;
15693 bios_version = bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM)/2];
15694 major = (bios_version >> 12) & 0xF;
15695 minor = (bios_version >> 8) & 0xF;
15696 if (major <= 3 || (major == 3 && minor == 1))
15698 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
15699 AdvReadWordLram(iop_base, 0x120, wdtr_able);
15700 } else
15702 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
15705 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
15706 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
15707 for (tid = 0; tid <= ADV_MAX_TID; tid++)
15709 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
15710 max_cmd[tid]);
15714 * Load the Microcode
15716 * Write the microcode image to RISC memory starting at address 0.
15718 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
15719 /* Assume the following compressed format of the microcode buffer:
15721 * 254 word (508 byte) table indexed by byte code followed
15722 * by the following byte codes:
15724 * 1-Byte Code:
15725 * 00: Emit word 0 in table.
15726 * 01: Emit word 1 in table.
15728 * FD: Emit word 253 in table.
15730 * Multi-Byte Code:
15731 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
15732 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
15734 word = 0;
15735 for (i = 253 * 2; i < _adv_asc3550_size; i++)
15737 if (_adv_asc3550_buf[i] == 0xff)
15739 for (j = 0; j < _adv_asc3550_buf[i + 1]; j++)
15741 AdvWriteWordAutoIncLram(iop_base,
15742 *((ushort *) (&_adv_asc3550_buf[i + 2])));
15743 word++;
15745 i += 3;
15746 } else if (_adv_asc3550_buf[i] == 0xfe)
15748 AdvWriteWordAutoIncLram(iop_base,
15749 *((ushort *) (&_adv_asc3550_buf[i + 1])));
15750 i += 2;
15751 word++;
15752 } else
15754 AdvWriteWordAutoIncLram(iop_base,
15755 *((ushort *) &_adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
15756 word++;
15761 * Set 'word' for later use to clear the rest of memory and save
15762 * the expanded mcode size.
15764 word *= 2;
15765 adv_asc3550_expanded_size = word;
15768 * Clear the rest of ASC-3550 Internal RAM (8KB).
15770 for (; word < ADV_3550_MEMSIZE; word += 2)
15772 AdvWriteWordAutoIncLram(iop_base, 0);
15776 * Verify the microcode checksum.
15778 sum = 0;
15779 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
15781 for (word = 0; word < adv_asc3550_expanded_size; word += 2)
15783 sum += AdvReadWordAutoIncLram(iop_base);
15786 if (sum != _adv_asc3550_chksum)
15788 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
15789 return ADV_ERROR;
15793 * Restore the RISC memory BIOS region.
15795 for (i = 0; i < ASC_MC_BIOSLEN/2; i++)
15797 AdvWriteByteLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]);
15801 * Calculate and write the microcode code checksum to the microcode
15802 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
15804 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
15805 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
15806 code_sum = 0;
15807 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
15808 for (word = begin_addr; word < end_addr; word += 2)
15810 code_sum += AdvReadWordAutoIncLram(iop_base);
15812 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
15815 * Read and save microcode version and date.
15817 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date);
15818 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version);
15821 * Set the chip type to indicate the ASC3550.
15823 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
15826 * If the PCI Configuration Command Register "Parity Error Response
15827 * Control" Bit was clear (0), then set the microcode variable
15828 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
15829 * to ignore DMA parity errors.
15831 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR)
15834 * Note: Don't remove the use of a temporary variable in
15835 * the following code, otherwise the Microsoft C compiler
15836 * will turn the following lines into a no-op.
15838 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15839 word |= CONTROL_FLAG_IGNORE_PERR;
15840 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
15844 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
15845 * threshold of 128 bytes. This register is only accessible to the host.
15847 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
15848 START_CTL_EMFU | READ_CMD_MRM);
15851 * Microcode operating variables for WDTR, SDTR, and command tag
15852 * queuing will be set in AdvInquiryHandling() based on what a
15853 * device reports it is capable of in Inquiry byte 7.
15855 * If SCSI Bus Resets haev been disabled, then directly set
15856 * SDTR and WDTR from the EEPROM configuration. This will allow
15857 * the BIOS and warm boot to work without a SCSI bus hang on
15858 * the Inquiry caused by host and target mismatched DTR values.
15859 * Without the SCSI Bus Reset, before an Inquiry a device can't
15860 * be assumed to be in Asynchronous, Narrow mode.
15862 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0)
15864 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able);
15865 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able);
15869 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
15870 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
15871 * bitmask. These values determine the maximum SDTR speed negotiated
15872 * with a device.
15874 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
15875 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
15876 * without determining here whether the device supports SDTR.
15878 * 4-bit speed SDTR speed name
15879 * =========== ===============
15880 * 0000b (0x0) SDTR disabled
15881 * 0001b (0x1) 5 Mhz
15882 * 0010b (0x2) 10 Mhz
15883 * 0011b (0x3) 20 Mhz (Ultra)
15884 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
15885 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
15886 * 0110b (0x6) Undefined
15888 * 1111b (0xF) Undefined
15890 word = 0;
15891 for (tid = 0; tid <= ADV_MAX_TID; tid++)
15893 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able)
15895 /* Set Ultra speed for TID 'tid'. */
15896 word |= (0x3 << (4 * (tid % 4)));
15897 } else
15899 /* Set Fast speed for TID 'tid'. */
15900 word |= (0x2 << (4 * (tid % 4)));
15902 if (tid == 3) /* Check if done with sdtr_speed1. */
15904 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
15905 word = 0;
15906 } else if (tid == 7) /* Check if done with sdtr_speed2. */
15908 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
15909 word = 0;
15910 } else if (tid == 11) /* Check if done with sdtr_speed3. */
15912 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
15913 word = 0;
15914 } else if (tid == 15) /* Check if done with sdtr_speed4. */
15916 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
15917 /* End of loop. */
15922 * Set microcode operating variable for the disconnect per TID bitmask.
15924 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable);
15928 * Set SCSI_CFG0 Microcode Default Value.
15930 * The microcode will set the SCSI_CFG0 register using this value
15931 * after it is started below.
15933 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
15934 PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id);
15937 * Determine SCSI_CFG1 Microcode Default Value.
15939 * The microcode will set the SCSI_CFG1 register using this value
15940 * after it is started below.
15943 /* Read current SCSI_CFG1 Register value. */
15944 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
15947 * If all three connectors are in use, return an error.
15949 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
15950 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0)
15952 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
15953 return ADV_ERROR;
15957 * If the internal narrow cable is reversed all of the SCSI_CTRL
15958 * register signals will be set. Check for and return an error if
15959 * this condition is found.
15961 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07)
15963 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
15964 return ADV_ERROR;
15968 * If this is a differential board and a single-ended device
15969 * is attached to one of the connectors, return an error.
15971 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0)
15973 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
15974 return ADV_ERROR;
15978 * If automatic termination control is enabled, then set the
15979 * termination value based on a table listed in a_condor.h.
15981 * If manual termination was specified with an EEPROM setting
15982 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
15983 * is ready to be 'ored' into SCSI_CFG1.
15985 if (asc_dvc->cfg->termination == 0)
15988 * The software always controls termination by setting TERM_CTL_SEL.
15989 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
15991 asc_dvc->cfg->termination |= TERM_CTL_SEL;
15993 switch(scsi_cfg1 & CABLE_DETECT)
15995 /* TERM_CTL_H: on, TERM_CTL_L: on */
15996 case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF:
15997 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
15998 break;
16000 /* TERM_CTL_H: on, TERM_CTL_L: off */
16001 case 0x1: case 0x5: case 0x9: case 0xA: case 0xC:
16002 asc_dvc->cfg->termination |= TERM_CTL_H;
16003 break;
16005 /* TERM_CTL_H: off, TERM_CTL_L: off */
16006 case 0x2: case 0x6:
16007 break;
16012 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
16014 scsi_cfg1 &= ~TERM_CTL;
16017 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
16018 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
16019 * referenced, because the hardware internally inverts
16020 * the Termination High and Low bits if TERM_POL is set.
16022 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
16025 * Set SCSI_CFG1 Microcode Default Value
16027 * Set filter value and possibly modified termination control
16028 * bits in the Microcode SCSI_CFG1 Register Value.
16030 * The microcode will set the SCSI_CFG1 register using this value
16031 * after it is started below.
16033 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
16034 FLTR_11_TO_20NS | scsi_cfg1);
16037 * Set MEM_CFG Microcode Default Value
16039 * The microcode will set the MEM_CFG register using this value
16040 * after it is started below.
16042 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
16043 * are defined.
16045 * ASC-3550 has 8KB internal memory.
16047 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
16048 BIOS_EN | RAM_SZ_8KB);
16051 * Set SEL_MASK Microcode Default Value
16053 * The microcode will set the SEL_MASK register using this value
16054 * after it is started below.
16056 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
16057 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
16060 * Build carrier freelist.
16062 * Driver must have already allocated memory and set 'carrier_buf'.
16064 ADV_ASSERT(asc_dvc->carrier_buf != NULL);
16066 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
16067 asc_dvc->carr_freelist = NULL;
16068 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf)
16070 buf_size = ADV_CARRIER_BUFSIZE;
16071 } else
16073 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
16076 do {
16078 * Get physical address of the carrier 'carrp'.
16080 contig_len = sizeof(ADV_CARR_T);
16081 carr_paddr = DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp,
16082 (long *) &contig_len, ADV_IS_CARRIER_FLAG);
16084 buf_size -= sizeof(ADV_CARR_T);
16087 * If the current carrier is not physically contiguous, then
16088 * maybe there was a page crossing. Try the next carrier aligned
16089 * start address.
16091 if (contig_len < sizeof(ADV_CARR_T))
16093 carrp++;
16094 continue;
16097 carrp->carr_pa = carr_paddr;
16098 carrp->carr_va = (ulong) carrp;
16101 * Insert the carrier at the beginning of the freelist.
16103 carrp->next_vpa = (ulong) asc_dvc->carr_freelist;
16104 asc_dvc->carr_freelist = carrp;
16106 carrp++;
16108 while (buf_size > 0);
16111 * Set-up the Host->RISC Initiator Command Queue (ICQ).
16114 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL)
16116 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
16117 return ADV_ERROR;
16119 asc_dvc->carr_freelist = (ADV_CARR_T *) asc_dvc->icq_sp->next_vpa;
16122 * The first command issued will be placed in the stopper carrier.
16124 asc_dvc->icq_sp->next_vpa = ASC_CQ_STOPPER;
16127 * Set RISC ICQ physical address start value.
16129 AdvWriteDWordLram(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
16132 * Set-up the RISC->Host Initiator Response Queue (IRQ).
16134 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL)
16136 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
16137 return ADV_ERROR;
16139 asc_dvc->carr_freelist = (ADV_CARR_T *) asc_dvc->irq_sp->next_vpa;
16142 * The first command completed by the RISC will be placed in
16143 * the stopper.
16145 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
16146 * completed the RISC will set the ASC_RQ_STOPPER bit.
16148 asc_dvc->irq_sp->next_vpa = ASC_CQ_STOPPER;
16151 * Set RISC IRQ physical address start value.
16153 AdvWriteDWordLram(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
16154 asc_dvc->carr_pending_cnt = 0;
16156 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
16157 (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR));
16160 * Note: Don't remove the use of a temporary variable in
16161 * the following code, otherwise the Microsoft C compiler
16162 * will turn the following lines into a no-op.
16164 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
16165 AdvWriteWordRegister(iop_base, IOPW_PC, word);
16167 /* finally, finally, gentlemen, start your engine */
16168 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
16171 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
16172 * Resets should be performed. The RISC has to be running
16173 * to issue a SCSI Bus Reset.
16175 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
16178 * If the BIOS Signature is present in memory, restore the
16179 * BIOS Handshake Configuration Table and do not perform
16180 * a SCSI Bus Reset.
16182 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA)
16185 * Restore per TID negotiated values.
16187 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16188 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16189 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
16190 for (tid = 0; tid <= ADV_MAX_TID; tid++)
16192 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
16193 max_cmd[tid]);
16195 } else
16197 if (AdvResetSB(asc_dvc) != ADV_TRUE)
16199 warn_code = ASC_WARN_BUSRESET_ERROR;
16204 return warn_code;
16208 * Initialize the ASC-38C0800.
16210 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
16212 * For a non-fatal error return a warning code. If there are no warnings
16213 * then 0 is returned.
16215 STATIC int
16216 AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
16218 AdvPortAddr iop_base;
16219 ushort warn_code;
16220 ulong sum;
16221 int begin_addr;
16222 int end_addr;
16223 ushort code_sum;
16224 int word;
16225 int j;
16226 int adv_asc38C0800_expanded_size;
16227 ADV_CARR_T *carrp;
16228 ulong contig_len;
16229 long buf_size;
16230 ulong carr_paddr;
16231 int i;
16232 ushort scsi_cfg1;
16233 uchar byte;
16234 uchar tid;
16235 ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */
16236 ushort wdtr_able, sdtr_able, tagqng_able;
16237 uchar max_cmd[ADV_MAX_TID + 1];
16239 /* If there is already an error, don't continue. */
16240 if (asc_dvc->err_code != 0)
16242 return ADV_ERROR;
16246 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
16248 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800)
16250 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
16251 return ADV_ERROR;
16254 warn_code = 0;
16255 iop_base = asc_dvc->iop_base;
16258 * Save the RISC memory BIOS region before writing the microcode.
16259 * The BIOS may already be loaded and using its RISC LRAM region
16260 * so its region must be saved and restored.
16262 * Note: This code makes the assumption, which is currently true,
16263 * that a chip reset does not clear RISC LRAM.
16265 for (i = 0; i < ASC_MC_BIOSLEN/2; i++)
16267 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]);
16271 * Save current per TID negotiated values.
16273 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16274 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16275 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
16276 for (tid = 0; tid <= ADV_MAX_TID; tid++)
16278 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
16279 max_cmd[tid]);
16283 * RAM BIST (RAM Built-In Self Test)
16285 * Address : I/O base + offset 0x38h register (byte).
16286 * Function: Bit 7-6(RW) : RAM mode
16287 * Normal Mode : 0x00
16288 * Pre-test Mode : 0x40
16289 * RAM Test Mode : 0x80
16290 * Bit 5 : unused
16291 * Bit 4(RO) : Done bit
16292 * Bit 3-0(RO) : Status
16293 * Host Error : 0x08
16294 * Int_RAM Error : 0x04
16295 * RISC Error : 0x02
16296 * SCSI Error : 0x01
16297 * No Error : 0x00
16299 * Note: RAM BIST code should be put right here, before loading the
16300 * microcode and after saving the RISC memory BIOS region.
16304 * LRAM Pre-test
16306 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
16307 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
16308 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
16309 * to NORMAL_MODE, return an error too.
16311 for (i = 0; i < 2; i++)
16313 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
16314 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
16315 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
16316 if ((byte & RAM_TEST_DONE) == 0 || (byte & 0x0F) != PRE_TEST_VALUE)
16318 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
16319 return ADV_ERROR;
16322 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
16323 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
16324 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
16325 != NORMAL_VALUE)
16327 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
16328 return ADV_ERROR;
16333 * LRAM Test - It takes about 1.5 ms to run through the test.
16335 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
16336 * If Done bit not set or Status not 0, save register byte, set the
16337 * err_code, and return an error.
16339 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
16340 DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */
16342 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
16343 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0)
16345 /* Get here if Done bit not set or Status not 0. */
16346 asc_dvc->bist_err_code = byte; /* for BIOS display message */
16347 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
16348 return ADV_ERROR;
16351 /* We need to reset back to normal mode after LRAM test passes. */
16352 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
16355 * Load the Microcode
16357 * Write the microcode image to RISC memory starting at address 0.
16360 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
16362 /* Assume the following compressed format of the microcode buffer:
16364 * 254 word (508 byte) table indexed by byte code followed
16365 * by the following byte codes:
16367 * 1-Byte Code:
16368 * 00: Emit word 0 in table.
16369 * 01: Emit word 1 in table.
16371 * FD: Emit word 253 in table.
16373 * Multi-Byte Code:
16374 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
16375 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
16377 word = 0;
16378 for (i = 253 * 2; i < _adv_asc38C0800_size; i++)
16380 if (_adv_asc38C0800_buf[i] == 0xff)
16382 for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++)
16384 AdvWriteWordAutoIncLram(iop_base,
16385 *((ushort *) (&_adv_asc38C0800_buf[i + 2])));
16386 word++;
16388 i += 3;
16389 } else if (_adv_asc38C0800_buf[i] == 0xfe)
16391 AdvWriteWordAutoIncLram(iop_base,
16392 *((ushort *) (&_adv_asc38C0800_buf[i + 1])));
16393 i += 2;
16394 word++;
16395 } else
16397 AdvWriteWordAutoIncLram(iop_base, *((ushort *)
16398 &_adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
16399 word++;
16404 * Set 'word' for later use to clear the rest of memory and save
16405 * the expanded mcode size.
16407 word *= 2;
16408 adv_asc38C0800_expanded_size = word;
16411 * Clear the rest of ASC-38C0800 Internal RAM (16KB).
16413 for (; word < ADV_38C0800_MEMSIZE; word += 2)
16415 AdvWriteWordAutoIncLram(iop_base, 0);
16419 * Verify the microcode checksum.
16421 sum = 0;
16422 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
16424 for (word = 0; word < adv_asc38C0800_expanded_size; word += 2)
16426 sum += AdvReadWordAutoIncLram(iop_base);
16429 if (sum != _adv_asc38C0800_chksum)
16431 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
16432 return ADV_ERROR;
16436 * Restore the RISC memory BIOS region.
16438 for (i = 0; i < ASC_MC_BIOSLEN/2; i++)
16440 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]);
16444 * Calculate and write the microcode code checksum to the microcode
16445 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
16447 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
16448 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
16449 code_sum = 0;
16450 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
16451 for (word = begin_addr; word < end_addr; word += 2)
16453 code_sum += AdvReadWordAutoIncLram(iop_base);
16455 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
16458 * Read microcode version and date.
16460 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date);
16461 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version);
16464 * Set the chip type to indicate the ASC38C0800.
16466 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
16469 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
16470 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
16471 * cable detection and then we are able to read C_DET[3:0].
16473 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
16474 * Microcode Default Value' section below.
16476 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
16477 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, scsi_cfg1 | DIS_TERM_DRV);
16480 * If the PCI Configuration Command Register "Parity Error Response
16481 * Control" Bit was clear (0), then set the microcode variable
16482 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
16483 * to ignore DMA parity errors.
16485 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR)
16488 * Note: Don't remove the use of a temporary variable in
16489 * the following code, otherwise the Microsoft C compiler
16490 * will turn the following lines into a no-op.
16492 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
16493 word |= CONTROL_FLAG_IGNORE_PERR;
16494 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
16498 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
16499 * bits for the default FIFO threshold.
16501 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
16503 * For DMA Errata #4 set the BC_THRESH_ENB bit.
16505 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
16506 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
16509 * Microcode operating variables for WDTR, SDTR, and command tag
16510 * queuing will be set in AdvInquiryHandling() based on what a
16511 * device reports it is capable of in Inquiry byte 7.
16513 * If SCSI Bus Resets have been disabled, then directly set
16514 * SDTR and WDTR from the EEPROM configuration. This will allow
16515 * the BIOS and warm boot to work without a SCSI bus hang on
16516 * the Inquiry caused by host and target mismatched DTR values.
16517 * Without the SCSI Bus Reset, before an Inquiry a device can't
16518 * be assumed to be in Asynchronous, Narrow mode.
16520 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0)
16522 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able);
16523 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able);
16527 * Set microcode operating variables for DISC and SDTR_SPEED1,
16528 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
16529 * configuration values.
16531 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
16532 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
16533 * without determining here whether the device supports SDTR.
16535 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable);
16536 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
16537 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
16538 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
16539 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
16542 * Set SCSI_CFG0 Microcode Default Value.
16544 * The microcode will set the SCSI_CFG0 register using this value
16545 * after it is started below.
16547 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
16548 PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id);
16551 * Determine SCSI_CFG1 Microcode Default Value.
16553 * The microcode will set the SCSI_CFG1 register using this value
16554 * after it is started below.
16557 /* Read current SCSI_CFG1 Register value. */
16558 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
16561 * If the internal narrow cable is reversed all of the SCSI_CTRL
16562 * register signals will be set. Check for and return an error if
16563 * this condition is found.
16565 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07)
16567 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
16568 return ADV_ERROR;
16572 * All kind of combinations of devices attached to one of four connectors
16573 * are acceptable except HVD device attached. For example, LVD device can
16574 * be attached to SE connector while SE device attached to LVD connector.
16575 * If LVD device attached to SE connector, it only runs up to Ultra speed.
16577 * If an HVD device is attached to one of LVD connectors, return an error.
16578 * However, there is no way to detect HVD device attached to SE connectors.
16580 if (scsi_cfg1 & HVD)
16582 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
16583 return ADV_ERROR;
16587 * If either SE or LVD automatic termination control is enabled, then
16588 * set the termination value based on a table listed in a_condor.h.
16590 * If manual termination was specified with an EEPROM setting then
16591 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to
16592 * be 'ored' into SCSI_CFG1.
16594 if ((asc_dvc->cfg->termination & TERM_SE) == 0)
16596 /* SE automatic termination control is enabled. */
16597 switch(scsi_cfg1 & C_DET_SE)
16599 /* TERM_SE_HI: on, TERM_SE_LO: on */
16600 case 0x1: case 0x2: case 0x3:
16601 asc_dvc->cfg->termination |= TERM_SE;
16602 break;
16604 /* TERM_SE_HI: on, TERM_SE_LO: off */
16605 case 0x0:
16606 asc_dvc->cfg->termination |= TERM_SE_HI;
16607 break;
16611 if ((asc_dvc->cfg->termination & TERM_LVD) == 0)
16613 /* LVD automatic termination control is enabled. */
16614 switch(scsi_cfg1 & C_DET_LVD)
16616 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
16617 case 0x4: case 0x8: case 0xC:
16618 asc_dvc->cfg->termination |= TERM_LVD;
16619 break;
16621 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
16622 case 0x0:
16623 break;
16628 * Clear any set TERM_SE and TERM_LVD bits.
16630 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
16633 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
16635 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
16638 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits
16639 * and set possibly modified termination control bits in the Microcode
16640 * SCSI_CFG1 Register Value.
16642 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
16645 * Set SCSI_CFG1 Microcode Default Value
16647 * Set possibly modified termination control and reset DIS_TERM_DRV
16648 * bits in the Microcode SCSI_CFG1 Register Value.
16650 * The microcode will set the SCSI_CFG1 register using this value
16651 * after it is started below.
16653 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
16656 * Set MEM_CFG Microcode Default Value
16658 * The microcode will set the MEM_CFG register using this value
16659 * after it is started below.
16661 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
16662 * are defined.
16664 * ASC-38C0800 has 16KB internal memory.
16666 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
16667 BIOS_EN | RAM_SZ_16KB);
16670 * Set SEL_MASK Microcode Default Value
16672 * The microcode will set the SEL_MASK register using this value
16673 * after it is started below.
16675 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
16676 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
16679 * Build the carrier freelist.
16681 * Driver must have already allocated memory and set 'carrier_buf'.
16684 ADV_ASSERT(asc_dvc->carrier_buf != NULL);
16686 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
16687 asc_dvc->carr_freelist = NULL;
16688 if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf)
16690 buf_size = ADV_CARRIER_BUFSIZE;
16691 } else
16693 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
16696 do {
16698 * Get physical address for the carrier 'carrp'.
16700 contig_len = sizeof(ADV_CARR_T);
16701 carr_paddr = DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp,
16702 (long *) &contig_len, ADV_IS_CARRIER_FLAG);
16704 buf_size -= sizeof(ADV_CARR_T);
16707 * If the current carrier is not physically contiguous, then
16708 * maybe there was a page crossing. Try the next carrier aligned
16709 * start address.
16711 if (contig_len < sizeof(ADV_CARR_T))
16713 carrp++;
16714 continue;
16717 carrp->carr_pa = carr_paddr;
16718 carrp->carr_va = (ulong) carrp;
16721 * Insert the carrier at the beginning of the freelist.
16723 carrp->next_vpa = (ulong) asc_dvc->carr_freelist;
16724 asc_dvc->carr_freelist = carrp;
16726 carrp++;
16728 while (buf_size > 0);
16731 * Set-up the Host->RISC Initiator Command Queue (ICQ).
16734 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL)
16736 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
16737 return ADV_ERROR;
16739 asc_dvc->carr_freelist = (ADV_CARR_T *) asc_dvc->icq_sp->next_vpa;
16742 * The first command issued will be placed in the stopper carrier.
16744 asc_dvc->icq_sp->next_vpa = ASC_CQ_STOPPER;
16747 * Set RISC ICQ physical address start value.
16749 AdvWriteDWordLram(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
16752 * Set-up the RISC->Host Initiator Response Queue (IRQ).
16754 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL)
16756 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
16757 return ADV_ERROR;
16759 asc_dvc->carr_freelist = (ADV_CARR_T *) asc_dvc->irq_sp->next_vpa;
16762 * The first command completed by the RISC will be placed in
16763 * the stopper.
16765 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
16766 * completed the RISC will set the ASC_RQ_STOPPER bit.
16768 asc_dvc->irq_sp->next_vpa = ASC_CQ_STOPPER;
16771 * Set RISC IRQ physical address start value.
16773 AdvWriteDWordLram(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
16774 asc_dvc->carr_pending_cnt = 0;
16776 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
16777 (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR));
16779 * Note: Don't remove the use of a temporary variable in
16780 * the following code, otherwise the Microsoft C compiler
16781 * will turn the following lines into a no-op.
16783 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
16784 AdvWriteWordRegister(iop_base, IOPW_PC, word);
16786 /* finally, finally, gentlemen, start your engine */
16787 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
16790 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
16791 * Resets should be performed. The RISC has to be running
16792 * to issue a SCSI Bus Reset.
16794 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
16797 * If the BIOS Signature is present in memory, restore the
16798 * BIOS Handshake Configuration Table and do not perform
16799 * a SCSI Bus Reset.
16801 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA)
16804 * Restore per TID negotiated values.
16806 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
16807 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
16808 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
16809 for (tid = 0; tid <= ADV_MAX_TID; tid++)
16811 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
16812 max_cmd[tid]);
16814 } else
16816 if (AdvResetSB(asc_dvc) != ADV_TRUE)
16818 warn_code = ASC_WARN_BUSRESET_ERROR;
16823 return warn_code;
16827 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
16828 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
16829 * all of this is done.
16831 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
16833 * For a non-fatal error return a warning code. If there are no warnings
16834 * then 0 is returned.
16836 * Note: Chip is stopped on entry.
16838 ASC_INITFUNC(
16839 STATIC int,
16840 AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
16843 AdvPortAddr iop_base;
16844 ushort warn_code;
16845 ADVEEP_38C0800_CONFIG eep_config;
16846 int i;
16847 uchar tid, termination;
16848 ushort sdtr_speed = 0;
16850 iop_base = asc_dvc->iop_base;
16852 warn_code = 0;
16855 * Read the board's EEPROM configuration.
16857 * Set default values if a bad checksum is found.
16859 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != eep_config.check_sum)
16861 warn_code |= ASC_WARN_EEPROM_CHKSUM;
16864 * Set EEPROM default values.
16866 for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++)
16868 *((uchar *) &eep_config + i) =
16869 *((uchar *) &Default_38C0800_EEPROM_Config + i);
16873 * Assume the 6 byte board serial number that was read
16874 * from EEPROM is correct even if the EEPROM checksum
16875 * failed.
16877 eep_config.serial_number_word3 =
16878 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1);
16880 eep_config.serial_number_word2 =
16881 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2);
16883 eep_config.serial_number_word1 =
16884 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3);
16886 AdvSet38C0800EEPConfig(iop_base, &eep_config);
16889 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
16890 * EEPROM configuration that was read.
16892 * This is the mapping of EEPROM fields to Adv Library fields.
16894 asc_dvc->wdtr_able = eep_config.wdtr_able;
16895 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
16896 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
16897 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
16898 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
16899 asc_dvc->tagqng_able = eep_config.tagqng_able;
16900 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
16901 asc_dvc->max_host_qng = eep_config.max_host_qng;
16902 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16903 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
16904 asc_dvc->start_motor = eep_config.start_motor;
16905 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
16906 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
16907 asc_dvc->no_scam = eep_config.scam_tolerant;
16908 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
16909 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
16910 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
16913 * For every Target ID if any of its 'sdtr_speed[1234]' bits
16914 * are set, then set an 'sdtr_able' bit for it.
16916 asc_dvc->sdtr_able = 0;
16917 for (tid = 0; tid <= ADV_MAX_TID; tid++)
16919 if (tid == 0)
16921 sdtr_speed = asc_dvc->sdtr_speed1;
16922 } else if (tid == 4)
16924 sdtr_speed = asc_dvc->sdtr_speed2;
16925 } else if (tid == 8)
16927 sdtr_speed = asc_dvc->sdtr_speed3;
16928 } else if (tid == 12)
16930 sdtr_speed = asc_dvc->sdtr_speed4;
16932 if (sdtr_speed & ADV_MAX_TID)
16934 asc_dvc->sdtr_able |= (1 << tid);
16936 sdtr_speed >>= 4;
16940 * Set the host maximum queuing (max. 253, min. 16) and the per device
16941 * maximum queuing (max. 63, min. 4).
16943 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG)
16945 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16946 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG)
16948 /* If the value is zero, assume it is uninitialized. */
16949 if (eep_config.max_host_qng == 0)
16951 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
16952 } else
16954 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
16958 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG)
16960 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16961 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG)
16963 /* If the value is zero, assume it is uninitialized. */
16964 if (eep_config.max_dvc_qng == 0)
16966 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
16967 } else
16969 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
16974 * If 'max_dvc_qng' is greater than 'max_host_qng', then
16975 * set 'max_dvc_qng' to 'max_host_qng'.
16977 if (eep_config.max_dvc_qng > eep_config.max_host_qng)
16979 eep_config.max_dvc_qng = eep_config.max_host_qng;
16983 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
16984 * values based on possibly adjusted EEPROM values.
16986 asc_dvc->max_host_qng = eep_config.max_host_qng;
16987 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
16990 * If the EEPROM 'termination' field is set to automatic (0), then set
16991 * the ADV_DVC_CFG 'termination' field to automatic also.
16993 * If the termination is specified with a non-zero 'termination'
16994 * value check that a legal value is set and set the ADV_DVC_CFG
16995 * 'termination' field appropriately.
16997 if (eep_config.termination_se == 0)
16999 termination = 0; /* auto termination for SE */
17000 } else
17002 /* Enable manual control with low off / high off. */
17003 if (eep_config.termination_se == 1)
17005 termination = 0;
17007 /* Enable manual control with low off / high on. */
17008 } else if (eep_config.termination_se == 2)
17010 termination = TERM_SE_HI;
17012 /* Enable manual control with low on / high on. */
17013 } else if (eep_config.termination_se == 3)
17015 termination = TERM_SE;
17016 } else
17019 * The EEPROM 'termination_se' field contains a bad value.
17020 * Use automatic termination instead.
17022 termination = 0;
17023 warn_code |= ASC_WARN_EEPROM_TERMINATION;
17027 if (eep_config.termination_lvd == 0)
17029 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
17030 } else
17032 /* Enable manual control with low off / high off. */
17033 if (eep_config.termination_lvd == 1)
17035 asc_dvc->cfg->termination = termination;
17037 /* Enable manual control with low off / high on. */
17038 } else if (eep_config.termination_lvd == 2)
17040 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
17042 /* Enable manual control with low on / high on. */
17043 } else if (eep_config.termination_lvd == 3)
17045 asc_dvc->cfg->termination =
17046 termination | TERM_LVD;
17047 } else
17050 * The EEPROM 'termination_lvd' field contains a bad value.
17051 * Use automatic termination instead.
17053 asc_dvc->cfg->termination = termination;
17054 warn_code |= ASC_WARN_EEPROM_TERMINATION;
17058 return warn_code;
17062 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
17063 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
17064 * all of this is done.
17066 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
17068 * For a non-fatal error return a warning code. If there are no warnings
17069 * then 0 is returned.
17071 * Note: Chip is stopped on entry.
17073 ASC_INITFUNC(
17074 STATIC int,
17075 AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
17078 AdvPortAddr iop_base;
17079 ushort warn_code;
17080 ADVEEP_3550_CONFIG eep_config;
17081 int i;
17083 iop_base = asc_dvc->iop_base;
17085 warn_code = 0;
17088 * Read the board's EEPROM configuration.
17090 * Set default values if a bad checksum is found.
17092 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum)
17094 warn_code |= ASC_WARN_EEPROM_CHKSUM;
17097 * Set EEPROM default values.
17099 for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++)
17101 *((uchar *) &eep_config + i) =
17102 *((uchar *) &Default_3550_EEPROM_Config + i);
17106 * Assume the 6 byte board serial number that was read
17107 * from EEPROM is correct even if the EEPROM checksum
17108 * failed.
17110 eep_config.serial_number_word3 =
17111 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1);
17113 eep_config.serial_number_word2 =
17114 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2);
17116 eep_config.serial_number_word1 =
17117 AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3);
17119 AdvSet3550EEPConfig(iop_base, &eep_config);
17122 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
17123 * EEPROM configuration that was read.
17125 * This is the mapping of EEPROM fields to Adv Library fields.
17127 asc_dvc->wdtr_able = eep_config.wdtr_able;
17128 asc_dvc->sdtr_able = eep_config.sdtr_able;
17129 asc_dvc->ultra_able = eep_config.ultra_able;
17130 asc_dvc->tagqng_able = eep_config.tagqng_able;
17131 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
17132 asc_dvc->max_host_qng = eep_config.max_host_qng;
17133 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
17134 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
17135 asc_dvc->start_motor = eep_config.start_motor;
17136 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
17137 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
17138 asc_dvc->no_scam = eep_config.scam_tolerant;
17139 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
17140 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
17141 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
17144 * Set the host maximum queuing (max. 253, min. 16) and the per device
17145 * maximum queuing (max. 63, min. 4).
17147 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG)
17149 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
17150 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG)
17152 /* If the value is zero, assume it is uninitialized. */
17153 if (eep_config.max_host_qng == 0)
17155 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
17156 } else
17158 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
17162 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG)
17164 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
17165 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG)
17167 /* If the value is zero, assume it is uninitialized. */
17168 if (eep_config.max_dvc_qng == 0)
17170 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
17171 } else
17173 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
17178 * If 'max_dvc_qng' is greater than 'max_host_qng', then
17179 * set 'max_dvc_qng' to 'max_host_qng'.
17181 if (eep_config.max_dvc_qng > eep_config.max_host_qng)
17183 eep_config.max_dvc_qng = eep_config.max_host_qng;
17187 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
17188 * values based on possibly adjusted EEPROM values.
17190 asc_dvc->max_host_qng = eep_config.max_host_qng;
17191 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
17195 * If the EEPROM 'termination' field is set to automatic (0), then set
17196 * the ADV_DVC_CFG 'termination' field to automatic also.
17198 * If the termination is specified with a non-zero 'termination'
17199 * value check that a legal value is set and set the ADV_DVC_CFG
17200 * 'termination' field appropriately.
17202 if (eep_config.termination == 0)
17204 asc_dvc->cfg->termination = 0; /* auto termination */
17205 } else
17207 /* Enable manual control with low off / high off. */
17208 if (eep_config.termination == 1)
17210 asc_dvc->cfg->termination = TERM_CTL_SEL;
17212 /* Enable manual control with low off / high on. */
17213 } else if (eep_config.termination == 2)
17215 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
17217 /* Enable manual control with low on / high on. */
17218 } else if (eep_config.termination == 3)
17220 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
17221 } else
17224 * The EEPROM 'termination' field contains a bad value. Use
17225 * automatic termination instead.
17227 asc_dvc->cfg->termination = 0;
17228 warn_code |= ASC_WARN_EEPROM_TERMINATION;
17232 return warn_code;
17236 * Read EEPROM configuration into the specified buffer.
17238 * Return a checksum based on the EEPROM configuration read.
17240 ASC_INITFUNC(
17241 STATIC ushort,
17242 AdvGet38C0800EEPConfig(AdvPortAddr iop_base,
17243 ADVEEP_38C0800_CONFIG *cfg_buf)
17246 ushort wval, chksum;
17247 ushort *wbuf;
17248 int eep_addr;
17250 wbuf = (ushort *) cfg_buf;
17251 chksum = 0;
17253 for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
17254 eep_addr < ASC_EEP_DVC_CFG_END;
17255 eep_addr++, wbuf++)
17257 wval = AdvReadEEPWord(iop_base, eep_addr);
17258 chksum += wval;
17259 *wbuf = wval;
17261 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
17262 wbuf++;
17263 for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
17264 eep_addr < ASC_EEP_MAX_WORD_ADDR;
17265 eep_addr++, wbuf++)
17267 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
17269 return chksum;
17274 * Read EEPROM configuration into the specified buffer.
17276 * Return a checksum based on the EEPROM configuration read.
17278 ASC_INITFUNC(
17279 STATIC ushort,
17280 AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
17283 ushort wval, chksum;
17284 ushort *wbuf;
17285 int eep_addr;
17287 wbuf = (ushort *) cfg_buf;
17288 chksum = 0;
17290 for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
17291 eep_addr < ASC_EEP_DVC_CFG_END;
17292 eep_addr++, wbuf++)
17294 wval = AdvReadEEPWord(iop_base, eep_addr);
17295 chksum += wval;
17296 *wbuf = wval;
17298 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
17299 wbuf++;
17300 for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
17301 eep_addr < ASC_EEP_MAX_WORD_ADDR;
17302 eep_addr++, wbuf++)
17304 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
17306 return chksum;
17310 * Read the EEPROM from specified location
17312 ASC_INITFUNC(
17313 STATIC ushort,
17314 AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
17317 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
17318 ASC_EEP_CMD_READ | eep_word_addr);
17319 AdvWaitEEPCmd(iop_base);
17320 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
17324 * Wait for EEPROM command to complete
17326 ASC_INITFUNC(
17327 STATIC void,
17328 AdvWaitEEPCmd(AdvPortAddr iop_base)
17331 int eep_delay_ms;
17333 for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++)
17335 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE)
17337 break;
17339 DvcSleepMilliSecond(1);
17341 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0)
17343 ADV_ASSERT(0);
17345 return;
17349 * Write the EEPROM from 'cfg_buf'.
17351 void
17352 AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
17354 ushort *wbuf;
17355 ushort addr, chksum;
17357 wbuf = (ushort *) cfg_buf;
17358 chksum = 0;
17360 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
17361 AdvWaitEEPCmd(iop_base);
17364 * Write EEPROM from word 0 to word 20
17366 for (addr = ASC_EEP_DVC_CFG_BEGIN;
17367 addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++)
17369 chksum += *wbuf;
17370 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
17371 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17372 AdvWaitEEPCmd(iop_base);
17373 DvcSleepMilliSecond(ASC_EEP_DELAY_MS);
17377 * Write EEPROM checksum at word 21
17379 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
17380 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17381 AdvWaitEEPCmd(iop_base);
17382 wbuf++; /* skip over check_sum */
17385 * Write EEPROM OEM name at words 22 to 29
17387 for (addr = ASC_EEP_DVC_CTL_BEGIN;
17388 addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++)
17390 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
17391 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17392 AdvWaitEEPCmd(iop_base);
17394 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
17395 AdvWaitEEPCmd(iop_base);
17396 return;
17400 * Write the EEPROM from 'cfg_buf'.
17402 void
17403 AdvSet38C0800EEPConfig(AdvPortAddr iop_base,
17404 ADVEEP_38C0800_CONFIG *cfg_buf)
17406 ushort *wbuf;
17407 ushort addr, chksum;
17409 wbuf = (ushort *) cfg_buf;
17410 chksum = 0;
17412 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
17413 AdvWaitEEPCmd(iop_base);
17416 * Write EEPROM from word 0 to word 20
17418 for (addr = ASC_EEP_DVC_CFG_BEGIN;
17419 addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++)
17421 chksum += *wbuf;
17422 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
17423 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17424 AdvWaitEEPCmd(iop_base);
17425 DvcSleepMilliSecond(ASC_EEP_DELAY_MS);
17429 * Write EEPROM checksum at word 21
17431 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
17432 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17433 AdvWaitEEPCmd(iop_base);
17434 wbuf++; /* skip over check_sum */
17437 * Write EEPROM OEM name at words 22 to 29
17439 for (addr = ASC_EEP_DVC_CTL_BEGIN;
17440 addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++)
17442 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
17443 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
17444 AdvWaitEEPCmd(iop_base);
17446 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
17447 AdvWaitEEPCmd(iop_base);
17448 return;
17451 /* a_advlib.c */
17453 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
17455 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
17456 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
17457 * RISC to notify it a new command is ready to be executed.
17459 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
17460 * set to SCSI_MAX_RETRY.
17462 * Return:
17463 * ADV_SUCCESS(1) - The request was successfully queued.
17464 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
17465 * request completes.
17466 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
17467 * host IC error.
17469 STATIC int
17470 AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc,
17471 ADV_SCSI_REQ_Q *scsiq)
17473 int last_int_level;
17474 AdvPortAddr iop_base;
17475 long req_size;
17476 ulong req_paddr;
17477 ADV_CARR_T *new_carrp;
17479 ADV_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */
17482 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
17484 if (scsiq->target_id > ADV_MAX_TID)
17486 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
17487 scsiq->done_status = QD_WITH_ERROR;
17488 return ADV_ERROR;
17491 iop_base = asc_dvc->iop_base;
17493 last_int_level = DvcEnterCritical();
17496 * Allocate a carrier ensuring at least one carrier always
17497 * remains on the freelist and initialize fields.
17499 if ((new_carrp = asc_dvc->carr_freelist) == NULL)
17501 return ADV_BUSY;
17503 asc_dvc->carr_freelist = (ADV_CARR_T *) new_carrp->next_vpa;
17504 asc_dvc->carr_pending_cnt++;
17507 * Set the carrier to be a stopper by setting 'next_vpa'
17508 * to the stopper value. The current stopper will be changed
17509 * below to point to the new stopper.
17511 new_carrp->next_vpa = ASC_CQ_STOPPER;
17514 * Clear the ADV_SCSI_REQ_Q done flag.
17516 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
17518 req_size = sizeof(ADV_SCSI_REQ_Q);
17519 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *) scsiq,
17520 (long *) &req_size, ADV_IS_SCSIQ_FLAG);
17522 ADV_ASSERT(ADV_DWALIGN(req_paddr) == req_paddr);
17523 ADV_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
17525 /* Save virtual and physical address of ADV_SCSI_REQ_Q and Carrier. */
17526 scsiq->scsiq_ptr = (ADV_SCSI_REQ_Q *) scsiq;
17527 scsiq->scsiq_rptr = req_paddr;
17529 /* XXX - Could have the RISC set these values. */
17530 scsiq->carr_va = (ulong) asc_dvc->icq_sp;
17531 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
17534 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
17535 * the microcode. The newly allocated stopper will become the new
17536 * stopper.
17538 asc_dvc->icq_sp->areq_vpa = (ulong) req_paddr;
17541 * Set the 'next_vpa' pointer for the old stopper to be the
17542 * physical address of the new stopper. The RISC can only
17543 * follow physical addresses.
17545 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
17548 * Set the host adapter stopper pointer to point to the new carrier.
17550 asc_dvc->icq_sp = new_carrp;
17553 * Tickle the RISC to tell it to read its Command Queue Head pointer.
17555 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
17556 if (asc_dvc->chip_type == ADV_CHIP_ASC3550)
17559 * Clear the tickle value. In the ASC-3550 the RISC flag
17560 * command 'clr_tickle_a' does not work unless the host
17561 * value is cleared.
17563 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
17566 DvcLeaveCritical(last_int_level);
17568 return ADV_SUCCESS;
17572 * Reset SCSI Bus and purge all outstanding requests.
17574 * Return Value:
17575 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
17576 * ADV_FALSE(0) - Microcode command failed.
17577 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
17578 * may be hung which requires driver recovery.
17580 STATIC int
17581 AdvResetSB(ADV_DVC_VAR *asc_dvc)
17583 int status;
17586 * Send the SCSI Bus Reset idle start idle command which asserts
17587 * the SCSI Bus Reset signal.
17589 status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET_START, 0L);
17590 if (status != ADV_TRUE)
17592 return status;
17596 * Delay for the specified SCSI Bus Reset hold time.
17598 * The hold time delay is done on the host because the RISC has no
17599 * microsecond accurate timer.
17601 DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US);
17604 * Send the SCSI Bus Reset end idle command which de-asserts
17605 * the SCSI Bus Reset signal and purges any pending requests.
17607 status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET_END, 0L);
17608 if (status != ADV_TRUE)
17610 return status;
17613 DvcSleepMilliSecond((ulong) asc_dvc->scsi_reset_wait * 1000);
17615 return status;
17619 * Reset chip and SCSI Bus.
17621 * Return Value:
17622 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
17623 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
17625 STATIC int
17626 AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
17628 int status;
17629 ushort wdtr_able, sdtr_able, tagqng_able;
17630 uchar tid, max_cmd[ADV_MAX_TID + 1];
17631 AdvPortAddr iop_base;
17632 ushort bios_sig;
17634 iop_base = asc_dvc->iop_base;
17637 * Save current per TID negotiated values.
17639 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
17640 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
17641 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
17642 for (tid = 0; tid <= ADV_MAX_TID; tid++)
17644 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
17645 max_cmd[tid]);
17649 * Force the AdvInitAsc3550/38C0800Driver() function to
17650 * perform a SCSI Bus Reset by clearing the BIOS signature word.
17651 * The initialization functions assumes a SCSI Bus Reset is not
17652 * needed if the BIOS signature word is present.
17654 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
17655 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
17658 * Stop chip and reset it.
17660 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
17661 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
17662 DvcSleepMilliSecond(100);
17663 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG);
17666 * Reset Adv Library error code, if any, and try
17667 * re-initializing the chip.
17669 asc_dvc->err_code = 0;
17670 if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800)
17672 status = AdvInitAsc38C0800Driver(asc_dvc);
17673 } else
17675 status = AdvInitAsc3550Driver(asc_dvc);
17678 /* Translate initialization return value to status value. */
17679 if (status == 0)
17681 status = ADV_TRUE;
17682 } else
17684 status = ADV_FALSE;
17688 * Restore the BIOS signature word.
17690 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
17693 * Restore per TID negotiated values.
17695 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
17696 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
17697 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
17698 for (tid = 0; tid <= ADV_MAX_TID; tid++)
17700 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
17701 max_cmd[tid]);
17704 return status;
17708 * Adv Library Interrupt Service Routine
17710 * This function is called by a driver's interrupt service routine.
17711 * The function disables and re-enables interrupts.
17713 * When a microcode idle command is completed, the ADV_DVC_VAR
17714 * 'idle_cmd_done' field is set to ADV_TRUE.
17716 * Note: AdvISR() can be called when interrupts are disabled or even
17717 * when there is no hardware interrupt condition present. It will
17718 * always check for completed idle commands and microcode requests.
17719 * This is an important feature that shouldn't be changed because it
17720 * allows commands to be completed from polling mode loops.
17722 * Return:
17723 * ADV_TRUE(1) - interrupt was pending
17724 * ADV_FALSE(0) - no interrupt was pending
17726 STATIC int
17727 AdvISR(ADV_DVC_VAR *asc_dvc)
17729 AdvPortAddr iop_base;
17730 uchar int_stat;
17731 ushort target_bit;
17732 ADV_CARR_T *free_carrp;
17733 ulong irq_next_vpa;
17734 int flags;
17735 ADV_SCSI_REQ_Q *scsiq;
17737 flags = DvcEnterCritical();
17739 iop_base = asc_dvc->iop_base;
17741 /* Reading the register clears the interrupt. */
17742 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
17744 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
17745 ADV_INTR_STATUS_INTRC)) == 0)
17747 return ADV_FALSE;
17751 * Notify the driver of an asynchronous microcode condition by
17752 * calling the ADV_DVC_VAR.async_callback function. The function
17753 * is passed the microcode ASC_MC_INTRB_CODE byte value.
17755 if (int_stat & ADV_INTR_STATUS_INTRB)
17757 uchar intrb_code;
17759 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
17760 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
17761 asc_dvc->carr_pending_cnt != 0)
17763 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
17764 if (asc_dvc->chip_type == ADV_CHIP_ASC3550)
17766 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
17770 if (asc_dvc->async_callback != 0)
17772 (*asc_dvc->async_callback)(asc_dvc, intrb_code);
17777 * Check if the IRQ stopper carrier contains a completed request.
17779 while (((irq_next_vpa = asc_dvc->irq_sp->next_vpa) & ASC_RQ_DONE) != 0)
17782 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
17783 * The RISC will have set 'areq_vpa' to a virtual address.
17785 scsiq = (ADV_SCSI_REQ_Q *) asc_dvc->irq_sp->areq_vpa;
17788 * Advance the stopper pointer to the next carrier
17789 * ignoring the lower four bits. Free the previous
17790 * stopper carrier.
17792 free_carrp = asc_dvc->irq_sp;
17793 asc_dvc->irq_sp = ASC_GET_CARRP(irq_next_vpa);
17795 free_carrp->next_vpa = (ulong) asc_dvc->carr_freelist;
17796 asc_dvc->carr_freelist = (ADV_CARR_T *) free_carrp;
17797 asc_dvc->carr_pending_cnt--;
17800 ADV_ASSERT(scsiq != NULL);
17801 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
17804 * Clear request microcode control flag.
17806 scsiq->cntl = 0;
17809 * Check Condition handling
17811 if ((scsiq->done_status == QD_WITH_ERROR) &&
17812 (scsiq->scsi_status == SS_CHK_CONDITION)
17817 * If the command that completed was a SCSI INQUIRY and
17818 * LUN 0 was sent the command, then process the INQUIRY
17819 * command information for the device.
17821 else if (scsiq->done_status == QD_NO_ERROR &&
17822 scsiq->cdb[0] == SCSICMD_Inquiry &&
17823 scsiq->target_lun == 0)
17825 AdvInquiryHandling(asc_dvc, scsiq);
17829 * Notify the driver of the completed request by passing
17830 * the ADV_SCSI_REQ_Q pointer to its callback function.
17832 scsiq->a_flag |= ADV_SCSIQ_DONE;
17833 (*asc_dvc->isr_callback)(asc_dvc, scsiq);
17835 * Note: After the driver callback function is called, 'scsiq'
17836 * can no longer be referenced.
17838 * Fall through and continue processing other completed
17839 * requests...
17843 * Disable interrupts again in case the driver inadvertently
17844 * enabled interrupts in its callback function.
17846 * The DvcEnterCritical() return value is ignored, because
17847 * the 'flags' saved when AdvISR() was first entered will be
17848 * used to restore the interrupt flag on exit.
17850 (void) DvcEnterCritical();
17852 DvcLeaveCritical(flags);
17853 return ADV_TRUE;
17857 * Send an idle command to the chip and wait for completion.
17859 * Command completion is polled for once per microsecond.
17861 * The function can be called from anywhere including an interrupt handler.
17862 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
17863 * functions to prevent reentrancy.
17865 * Return Values:
17866 * ADV_TRUE - command completed successfully
17867 * ADV_FALSE - command failed
17868 * ADV_ERROR - command timed out
17870 STATIC int
17871 AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
17872 ushort idle_cmd,
17873 ulong idle_cmd_parameter)
17875 int last_int_level;
17876 int result;
17877 ulong i, j;
17878 AdvPortAddr iop_base;
17880 last_int_level = DvcEnterCritical();
17882 iop_base = asc_dvc->iop_base;
17885 * Clear the idle command status which is set by the microcode
17886 * to a non-zero value to indicate when the command is completed.
17887 * The non-zero result is one of the IDLE_CMD_STATUS_* values
17888 * defined in a_advlib.h.
17890 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort) 0);
17893 * Write the idle command value after the idle command parameter
17894 * has been written to avoid a race condition. If the order is not
17895 * followed, the microcode may process the idle command before the
17896 * parameters have been written to LRAM.
17898 AdvWriteDWordLram(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
17899 idle_cmd_parameter);
17900 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
17903 * Tickle the RISC to tell it to process the idle command.
17905 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
17906 if (asc_dvc->chip_type == ADV_CHIP_ASC3550)
17909 * Clear the tickle value. In the ASC-3550 the RISC flag
17910 * command 'clr_tickle_b' does not work unless the host
17911 * value is cleared.
17913 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
17916 /* Wait for up to 100 millisecond for the idle command to timeout. */
17917 for (i = 0; i < SCSI_WAIT_100_MSEC; i++)
17919 /* Poll once each microsecond for command completion. */
17920 for (j = 0; j < SCSI_US_PER_MSEC; j++)
17922 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, result);
17923 if (result != 0)
17925 DvcLeaveCritical(last_int_level);
17926 return result;
17928 DvcDelayMicroSecond(asc_dvc, (ushort) 1);
17932 ADV_ASSERT(0); /* The idle command should never timeout. */
17933 DvcLeaveCritical(last_int_level);
17934 return ADV_ERROR;
17938 * Inquiry Information Byte 7 Handling
17940 * Handle SCSI Inquiry Command information for a device by setting
17941 * microcode operating variables that affect WDTR, SDTR, and Tag
17942 * Queuing.
17944 STATIC void
17945 AdvInquiryHandling(
17946 ADV_DVC_VAR *asc_dvc,
17947 ADV_SCSI_REQ_Q *scsiq)
17949 AdvPortAddr iop_base;
17950 uchar tid;
17951 ADV_SCSI_INQUIRY *inq;
17952 ushort tidmask;
17953 ushort cfg_word;
17956 * AdvInquiryHandling() requires up to INQUIRY information Byte 7
17957 * to be available.
17959 * If less than 8 bytes of INQUIRY information were requested or less
17960 * than 8 bytes were transferred, then return. cdb[4] is the request
17961 * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
17962 * microcode to the transfer residual count.
17965 if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8)
17967 return;
17970 iop_base = asc_dvc->iop_base;
17971 tid = scsiq->target_id;
17973 inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr;
17976 * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
17978 if (inq->rsp_data_fmt < 2 && inq->ansi_apr_ver < 2)
17980 return;
17981 } else
17984 * INQUIRY Byte 7 Handling
17986 * Use a device's INQUIRY byte 7 to determine whether it
17987 * supports WDTR, SDTR, and Tag Queuing. If the feature
17988 * is enabled in the EEPROM and the device supports the
17989 * feature, then enable it in the microcode.
17992 tidmask = ADV_TID_TO_TIDMASK(tid);
17995 * Wide Transfers
17997 * If the EEPROM enabled WDTR for the device and the device
17998 * supports wide bus (16 bit) transfers, then turn on the
17999 * device's 'wdtr_able' bit and write the new value to the
18000 * microcode.
18002 if ((asc_dvc->wdtr_able & tidmask) && inq->WBus16)
18004 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
18005 if ((cfg_word & tidmask) == 0)
18007 cfg_word |= tidmask;
18008 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
18011 * Clear the microcode "SDTR negotiation" and "WDTR
18012 * negotiation" done indicators for the target to cause
18013 * it to negotiate with the new setting set above.
18014 * WDTR when accepted causes the target to enter
18015 * asynchronous mode, so SDTR must be negotiated.
18017 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
18018 cfg_word &= ~tidmask;
18019 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
18020 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
18021 cfg_word &= ~tidmask;
18022 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
18027 * Synchronous Transfers
18029 * If the EEPROM enabled SDTR for the device and the device
18030 * supports synchronous transfers, then turn on the device's
18031 * 'sdtr_able' bit. Write the new value to the microcode.
18033 if ((asc_dvc->sdtr_able & tidmask) && inq->Sync)
18035 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
18036 if ((cfg_word & tidmask) == 0)
18038 cfg_word |= tidmask;
18039 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
18042 * Clear the microcode "SDTR negotiation" done indicator
18043 * for the target to cause it to negotiate with the new
18044 * setting set above.
18046 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
18047 cfg_word &= ~tidmask;
18048 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
18053 * If the EEPROM enabled Tag Queuing for the device and the
18054 * device supports Tag Queueing, then turn on the device's
18055 * 'tagqng_enable' bit in the microcode and set the microcode
18056 * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
18057 * value.
18059 * Tag Queuing is disabled for the BIOS which runs in polled
18060 * mode and would see no benefit from Tag Queuing. Also by
18061 * disabling Tag Queuing in the BIOS devices with Tag Queuing
18062 * bugs will at least work with the BIOS.
18064 if ((asc_dvc->tagqng_able & tidmask) && inq->CmdQue)
18066 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
18067 cfg_word |= tidmask;
18068 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
18070 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
18071 asc_dvc->max_dvc_qng);