|
|
1.1 root 1: /* $Id: advansys.c,v 1.1 1999/04/26 05:54:04 tb Exp $ */
2: #define ASC_VERSION "3.1E" /* AdvanSys Driver Version */
3:
4: /*
5: * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
6: *
7: * Copyright (c) 1995-1998 Advanced System Products, Inc.
8: * All Rights Reserved.
9: *
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.
14: *
15: * There is an AdvanSys Linux WWW page at:
16: * http://www.advansys.com/linux.html
17: *
18: * The latest version of the AdvanSys driver is available at:
19: * ftp://ftp.advansys.com/pub/linux/linux.tgz
20: *
21: * Please send questions, comments, bug reports to:
22: * [email protected] (Bob Frey)
23: */
24:
25: /*
26:
27: Documentation for the AdvanSys Driver
28:
29: A. Linux Kernel Testing
30: B. Adapters Supported by this Driver
31: C. Linux v1.2.X - Directions for Adding the AdvanSys Driver
32: D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver
33: E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver
34: F. Source Comments
35: G. Driver Compile Time Options and Debugging
36: H. Driver LILO Option
37: I. Release History
38: J. Known Problems or Issues
39: K. Credits
40: L. AdvanSys Contact Information
41:
42: A. Linux Kernel Testing
43:
44: This driver has been tested in the following Linux kernels: v1.2.13,
45: v1.3.57, v2.0.33, v2.1.77. These kernel versions are major releases
46: of Linux or the latest Linux kernel versions available when this version
47: of the driver was released. The driver should also work in earlier
48: versions of the Linux kernel. Beginning with v1.3.58 the AdvanSys driver
49: is included with all Linux kernels. Please refer to sections C, D, and
50: E for instructions on adding or upgrading the AdvanSys driver.
51:
52: B. Adapters Supported by this Driver
53:
54: AdvanSys (Advanced System Products, Inc.) manufactures the following
55: RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
56: (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
57: buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
58: transfer) SCSI Host Adapters for the PCI bus.
59:
60: The CDB counts below indicate the number of SCSI CDB (Command
61: Descriptor Block) requests that can be stored in the RISC chip
62: cache and board LRAM. A CDB is a single SCSI command. The driver
63: detect routine will display the number of CDBs available for each
64: adapter detected. The number of CDBs used by the driver can be
65: lowered in the BIOS by changing the 'Host Queue Size' adapter setting.
66:
67: Connectivity Products:
68: ABP510/5150 - Bus-Master ISA (240 CDB) (Footnote 1)
69: ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1, 3)
70: ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) (Footnote 4)
71: ABP920 - Bus-Master PCI (16 CDB)
72: ABP930 - Bus-Master PCI (16 CDB) (Footnote 5)
73: ABP930U - Bus-Master PCI Ultra (16 CDB)
74: ABP930UA - Bus-Master PCI Ultra (16 CDB)
75: ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2)
76: ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) (Footnote 2)
77:
78: Single Channel Products:
79: ABP542 - Bus-Master ISA with floppy (240 CDB)
80: ABP742 - Bus-Master EISA (240 CDB)
81: ABP842 - Bus-Master VL (240 CDB)
82: ABP940 - Bus-Master PCI (240 CDB)
83: ABP940U - Bus-Master PCI Ultra (240 CDB)
84: ABP970 - Bus-Master PCI MAC/PC (240 CDB)
85: ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
86: ABP940UW - Bus-Master PCI Ultra-Wide (240 CDB)
87:
88: Multi Channel Products:
89: ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
90: ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
91: ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
92: ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
93: ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
94:
95: Footnotes:
96: 1. This board has been shipped by HP with the 4020i CD-R drive.
97: The board has no BIOS so it cannot control a boot device, but
98: it can control any secondary SCSI device.
99: 2. This board has been sold by Iomega as a Jaz Jet PCI adapter.
100: 3. This board has been sold by SIIG as the i540 SpeedMaster.
101: 4. This board has been sold by SIIG as the i542 SpeedMaster.
102: 5. This board has been sold by SIIG as the Fast SCSI Pro PCI.
103:
104: C. Linux v1.2.X - Directions for Adding the AdvanSys Driver
105:
106: These directions apply to v1.2.13. For versions that follow v1.2.13.
107: but precede v1.3.57 some of the changes for Linux v1.3.X listed
108: below may need to be modified or included. A patch is available
109: for v1.2.13 from the AdvanSys WWW and FTP sites.
110:
111: There are two source files: advansys.h and advansys.c. Copy
112: both of these files to the directory /usr/src/linux/drivers/scsi.
113:
114: 1. Add the following line to /usr/src/linux/arch/i386/config.in
115: after "comment 'SCSI low-level drivers'":
116:
117: bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
118:
119: 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
120: after "#include "hosts.h"":
121:
122: #ifdef CONFIG_SCSI_ADVANSYS
123: #include "advansys.h"
124: #endif
125:
126: and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
127:
128: #ifdef CONFIG_SCSI_ADVANSYS
129: ADVANSYS,
130: #endif
131:
132: 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
133:
134: ifdef CONFIG_SCSI_ADVANSYS
135: SCSI_SRCS := $(SCSI_SRCS) advansys.c
136: SCSI_OBJS := $(SCSI_OBJS) advansys.o
137: else
138: SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
139: endif
140:
141: 4. (Optional) If you would like to enable the LILO command line
142: and /etc/lilo.conf 'advansys' option, make the following changes.
143: This option can be used to disable I/O port scanning or to limit
144: I/O port scanning to specific addresses. Refer to the 'Driver
145: LILO Option' section below. Add the following lines to
146: /usr/src/linux/init/main.c in the prototype section:
147:
148: extern void advansys_setup(char *str, int *ints);
149:
150: and add the following lines to the bootsetups[] array.
151:
152: #ifdef CONFIG_SCSI_ADVANSYS
153: { "advansys=", advansys_setup },
154: #endif
155:
156: 5. If you have the HP 4020i CD-R driver and Linux v1.2.X you should
157: add a fix to the CD-ROM target driver. This fix will allow
158: you to mount CDs with the iso9660 file system. Linux v1.3.X
159: already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
160: and function get_sectorsize() after the line:
161:
162: if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
163:
164: add the following line:
165:
166: if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
167:
168: 6. In the directory /usr/src/linux run 'make config' to configure
169: the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
170: make the kernel. If the AdvanSys driver is not configured, then
171: a loadable module can be built by running 'make modules' and
172: 'make modules_install'. Use 'insmod' and 'rmmod' to install
173: and remove advansys.o.
174:
175: D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver
176:
177: These directions apply to v1.3.57. For versions that precede v1.3.57
178: some of these changes may need to be modified or eliminated. A patch
179: is available for v1.3.57 from the AdvanSys WWW and FTP sites.
180: Beginning with v1.3.58 this driver is included with the Linux
181: distribution eliminating the need for making any changes.
182:
183: There are two source files: advansys.h and advansys.c. Copy
184: both of these files to the directory /usr/src/linux/drivers/scsi.
185:
186: 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
187: after "comment 'SCSI low-level drivers'":
188:
189: dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
190:
191: 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
192: after "#include "hosts.h"":
193:
194: #ifdef CONFIG_SCSI_ADVANSYS
195: #include "advansys.h"
196: #endif
197:
198: and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
199:
200: #ifdef CONFIG_SCSI_ADVANSYS
201: ADVANSYS,
202: #endif
203:
204: 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
205:
206: ifeq ($(CONFIG_SCSI_ADVANSYS),y)
207: L_OBJS += advansys.o
208: else
209: ifeq ($(CONFIG_SCSI_ADVANSYS),m)
210: M_OBJS += advansys.o
211: endif
212: endif
213:
214: 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
215: in the enum scsi_directory_inos array:
216:
217: PROC_SCSI_ADVANSYS,
218:
219: 5. (Optional) If you would like to enable the LILO command line
220: and /etc/lilo.conf 'advansys' option, make the following changes.
221: This option can be used to disable I/O port scanning or to limit
222: I/O port scanning to specific addresses. Refer to the 'Driver
223: LILO Option' section below. Add the following lines to
224: /usr/src/linux/init/main.c in the prototype section:
225:
226: extern void advansys_setup(char *str, int *ints);
227:
228: and add the following lines to the bootsetups[] array.
229:
230: #ifdef CONFIG_SCSI_ADVANSYS
231: { "advansys=", advansys_setup },
232: #endif
233:
234: 6. In the directory /usr/src/linux run 'make config' to configure
235: the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
236: make the kernel. If the AdvanSys driver is not configured, then
237: a loadable module can be built by running 'make modules' and
238: 'make modules_install'. Use 'insmod' and 'rmmod' to install
239: and remove advansys.o.
240:
241: E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver
242:
243: To upgrade the AdvanSys driver in a Linux v1.3.58 and newer
244: kernel, first check the version of the current driver. The
245: version is defined by the manifest constant ASC_VERSION at
246: the beginning of advansys.c. The new driver should have a
247: ASC_VERSION value greater than the current version. To install
248: the new driver rename advansys.c and advansys.h in the Linux
249: kernel source tree drivers/scsi directory to different names
250: or save them to a different directory in case you want to revert
251: to the old version of the driver. After the old driver is saved
252: copy the new advansys.c and advansys.h to drivers/scsi, rebuild
253: the kernel, and install the new kernel. No other changes are needed.
254:
255: F. Source Comments
256:
257: 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
258:
259: 2. This driver should be maintained in multiple files. But to make
260: it easier to include with Linux and to follow Linux conventions,
261: the whole driver is maintained in the source files advansys.h and
262: advansys.c. In this file logical sections of the driver begin with
263: a comment that contains '---'. The following are the logical sections
264: of the driver below.
265:
266: --- Linux Version
267: --- Linux Include Files
268: --- Driver Options
269: --- Debugging Header
270: --- Asc Library Constants and Macros
271: --- Adv Library Constants and Macros
272: --- Driver Constants and Macros
273: --- Driver Structures
274: --- Driver Data
275: --- Driver Function Prototypes
276: --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
277: --- Loadable Driver Support
278: --- Miscellaneous Driver Functions
279: --- Functions Required by the Asc Library
280: --- Functions Required by the Adv Library
281: --- Tracing and Debugging Functions
282: --- Asc Library Functions
283: --- Adv Library Functions
284:
285: 3. The string 'XXX' is used to flag code that needs to be re-written
286: or that contains a problem that needs to be addressed.
287:
288: 4. I have stripped comments from and reformatted the source for the
289: Asc Library and Adv Library to reduce the size of this file. This
290: source can be found under the following headings. The Asc Library
291: is used to support Narrow Boards. The Adv Library is used to
292: support Wide Boards.
293:
294: --- Asc Library Constants and Macros
295: --- Adv Library Constants and Macros
296: --- Asc Library Functions
297: --- Adv Library Functions
298:
299: G. Driver Compile Time Options and Debugging
300:
301: In this source file the following constants can be defined. They are
302: defined in the source below. Both of these options are enabled by
303: default.
304:
305: 1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled)
306:
307: Enabling this option adds assertion logic statements to the
308: driver. If an assertion fails a message will be displayed to
309: the console, but the system will continue to operate. Any
310: assertions encountered should be reported to the person
311: responsible for the driver. Assertion statements may proactively
312: detect problems with the driver and facilitate fixing these
313: problems. Enabling assertions will add a small overhead to the
314: execution of the driver.
315:
316: 2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled)
317:
318: Enabling this option adds tracing functions to the driver and
319: the ability to set a driver tracing level at boot time. This
320: option will also export symbols not required outside the driver to
321: the kernel name space. This option is very useful for debugging
322: the driver, but it will add to the size of the driver execution
323: image and add overhead to the execution of the driver.
324:
325: The amount of debugging output can be controlled with the global
326: variable 'asc_dbglvl'. The higher the number the more output. By
327: default the debug level is 0.
328:
329: If the driver is loaded at boot time and the LILO Driver Option
330: is included in the system, the debug level can be changed by
331: specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The
332: first three hex digits of the pseudo I/O Port must be set to
333: 'deb' and the fourth hex digit specifies the debug level: 0 - F.
334: The following command line will look for an adapter at 0x330
335: and set the debug level to 2.
336:
337: linux advansys=0x330,0,0,0,0xdeb2
338:
339: If the driver is built as a loadable module this variable can be
340: defined when the driver is loaded. The following insmod command
341: will set the debug level to one.
342:
343: insmod advansys.o asc_dbglvl=1
344:
345: Debugging Message Levels:
346: 0: Errors Only
347: 1: High-Level Tracing
348: 2-N: Verbose Tracing
349:
350: I don't know the approved way for turning on printk()s to the
351: console. Here's a program I use to do this. Debug output is
352: logged in /var/adm/messages.
353:
354: main()
355: {
356: syscall(103, 7, 0, 0);
357: }
358:
359: I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
360: prevents most level 1 debug messages from being lost.
361:
362: 3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0)
363:
364: Enabling this option adds statistics collection and display
365: through /proc to the driver. The information is useful for
366: monitoring driver and device performance. It will add to the
367: size of the driver execution image and add minor overhead to
368: the execution of the driver.
369:
370: Statistics are maintained on a per adapter basis. Driver entry
371: point call counts and transfer size counts are maintained.
372: Statistics are only available for kernels greater than or equal
373: to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured.
374:
375: AdvanSys SCSI adapter files have the following path name format:
376:
377: /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
378:
379: This information can be displayed with cat. For example:
380:
381: cat /proc/scsi/advansys/0
382:
383: When ADVANSYS_STATS is not defined the AdvanSys /proc files only
384: contain adapter and device configuration information.
385:
386: H. Driver LILO Option
387:
388: If init/main.c is modified as described in the 'Directions for Adding
389: the AdvanSys Driver to Linux' section (B.4.) above, the driver will
390: recognize the 'advansys' LILO command line and /etc/lilo.conf option.
391: This option can be used to either disable I/O port scanning or to limit
392: scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
393: PCI boards will still be searched for and detected. This option only
394: affects searching for ISA and VL boards.
395:
396: Examples:
397: 1. Eliminate I/O port scanning:
398: boot: linux advansys=
399: or
400: boot: linux advansys=0x0
401: 2. Limit I/O port scanning to one I/O port:
402: boot: linux advansys=0x110
403: 3. Limit I/O port scanning to four I/O ports:
404: boot: linux advansys=0x110,0x210,0x230,0x330
405:
406: For a loadable module the same effect can be achieved by setting
407: the 'asc_iopflag' variable and 'asc_ioport' array when loading
408: the driver, e.g.
409:
410: insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
411:
412: If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1)
413: I/O Port may be added to specify the driver debug level. Refer to
414: the 'Driver Compile Time Options and Debugging' section above for
415: more information.
416:
417: I. Release History
418:
419: BETA-1.0 (12/23/95):
420: First Release
421:
422: BETA-1.1 (12/28/95):
423: 1. Prevent advansys_detect() from being called twice.
424: 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
425:
426: 1.2 (1/12/96):
427: 1. Prevent re-entrancy in the interrupt handler which
428: resulted in the driver hanging Linux.
429: 2. Fix problem that prevented ABP-940 cards from being
430: recognized on some PCI motherboards.
431: 3. Add support for the ABP-5140 PnP ISA card.
432: 4. Fix check condition return status.
433: 5. Add conditionally compiled code for Linux v1.3.X.
434:
435: 1.3 (2/23/96):
436: 1. Fix problem in advansys_biosparam() that resulted in the
437: wrong drive geometry being returned for drives > 1GB with
438: extended translation enabled.
439: 2. Add additional tracing during device initialization.
440: 3. Change code that only applies to ISA PnP adapter.
441: 4. Eliminate 'make dep' warning.
442: 5. Try to fix problem with handling resets by increasing their
443: timeout value.
444:
445: 1.4 (5/8/96):
446: 1. Change definitions to eliminate conflicts with other subsystems.
447: 2. Add versioning code for the shared interrupt changes.
448: 3. Eliminate problem in asc_rmqueue() with iterating after removing
449: a request.
450: 4. Remove reset request loop problem from the "Known Problems or
451: Issues" section. This problem was isolated and fixed in the
452: mid-level SCSI driver.
453:
454: 1.5 (8/8/96):
455: 1. Add support for ABP-940U (PCI Ultra) adapter.
456: 2. Add support for IRQ sharing by setting the SA_SHIRQ flag for
457: request_irq and supplying a dev_id pointer to both request_irq()
458: and free_irq().
459: 3. In AscSearchIOPortAddr11() restore a call to check_region() which
460: should be used before I/O port probing.
461: 4. Fix bug in asc_prt_hex() which resulted in the displaying
462: the wrong data.
463: 5. Incorporate miscellaneous Asc Library bug fixes and new microcode.
464: 6. Change driver versioning to be specific to each Linux sub-level.
465: 7. Change statistics gathering to be per adapter instead of global
466: to the driver.
467: 8. Add more information and statistics to the adapter /proc file:
468: /proc/scsi/advansys[0...].
469: 9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list.
470: This problem has been addressed with the SCSI mid-level changes
471: made in v1.3.89. The advansys_select_queue_depths() function
472: was added for the v1.3.89 changes.
473:
474: 1.6 (9/10/96):
475: 1. Incorporate miscellaneous Asc Library bug fixes and new microcode.
476:
477: 1.7 (9/25/96):
478: 1. Enable clustering and optimize the setting of the maximum number
479: of scatter gather elements for any particular board. Clustering
480: increases CPU utilization, but results in a relatively larger
481: increase in I/O throughput.
482: 2. Improve the performance of the request queuing functions by
483: adding a last pointer to the queue structure.
484: 3. Correct problems with reset and abort request handling that
485: could have hung or crashed Linux.
486: 4. Add more information to the adapter /proc file:
487: /proc/scsi/advansys[0...].
488: 5. Remove the request timeout issue form the driver issues list.
489: 6. Miscellaneous documentation additions and changes.
490:
491: 1.8 (10/4/96):
492: 1. Make changes to handle the new v2.1.0 kernel memory mapping
493: in which a kernel virtual address may not be equivalent to its
494: bus or DMA memory address.
495: 2. Change abort and reset request handling to make it yet even
496: more robust.
497: 3. Try to mitigate request starvation by sending ordered requests
498: to heavily loaded, tag queuing enabled devices.
499: 4. Maintain statistics on request response time.
500: 5. Add request response time statistics and other information to
501: the adapter /proc file: /proc/scsi/advansys[0...].
502:
503: 1.9 (10/21/96):
504: 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
505: make use of mid-level SCSI driver device queue depth flow
506: control mechanism. This will eliminate aborts caused by a
507: device being unable to keep up with requests and eliminate
508: repeat busy or QUEUE FULL status returned by a device.
509: 2. Incorporate miscellaneous Asc Library bug fixes.
510: 3. To allow the driver to work in kernels with broken module
511: support set 'cmd_per_lun' if the driver is compiled as a
512: module. This change affects kernels v1.3.89 to present.
513: 4. Remove PCI BIOS address from the driver banner. The PCI BIOS
514: is relocated by the motherboard BIOS and its new address can
515: not be determined by the driver.
516: 5. Add mid-level SCSI queue depth information to the adapter
517: /proc file: /proc/scsi/advansys[0...].
518:
519: 2.0 (11/14/96):
520: 1. Change allocation of global structures used for device
521: initialization to guarantee they are in DMA-able memory.
522: Previously when the driver was loaded as a module these
523: structures might not have been in DMA-able memory, causing
524: device initialization to fail.
525:
526: 2.1 (12/30/96):
527: 1. In advansys_reset(), if the request is a synchronous reset
528: request, even if the request serial number has changed, then
529: complete the request.
530: 2. Add Asc Library bug fixes including new microcode.
531: 3. Clear inquiry buffer before using it.
532: 4. Correct ifdef typo.
533:
534: 2.2 (1/15/97):
535: 1. Add Asc Library bug fixes including new microcode.
536: 2. Add synchronous data transfer rate information to the
537: adapter /proc file: /proc/scsi/advansys[0...].
538: 3. Change ADVANSYS_DEBUG to be disabled by default. This
539: will reduce the size of the driver image, eliminate execution
540: overhead, and remove unneeded symbols from the kernel symbol
541: space that were previously added by the driver.
542: 4. Add new compile-time option ADVANSYS_ASSERT for assertion
543: code that used to be defined within ADVANSYS_DEBUG. This
544: option is enabled by default.
545:
546: 2.8 (5/26/97):
547: 1. Change version number to 2.8 to synchronize the Linux driver
548: version numbering with other AdvanSys drivers.
549: 2. Reformat source files without tabs to present the same view
550: of the file to everyone regardless of the editor tab setting
551: being used.
552: 3. Add Asc Library bug fixes.
553:
554: 3.1A (1/8/98):
555: 1. Change version number to 3.1 to indicate that support for
556: Ultra-Wide adapters (ABP-940UW) is included in this release.
557: 2. Add Asc Library (Narrow Board) bug fixes.
558: 3. Report an underrun condition with the host status byte set
559: to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which
560: causes the underrun condition to be ignored. When Linux defines
561: its own DID_UNDERRUN the constant defined in this file can be
562: removed.
563: 4. Add patch to AscWaitTixISRDone().
564: 5. Add support for up to 16 different AdvanSys host adapter SCSI
565: channels in one system. This allows four cards with four channels
566: to be used in one system.
567:
568: 3.1B (1/9/98):
569: 1. Handle that PCI register base addresses are not always page
570: aligned even though ioremap() requires that the address argument
571: be page aligned.
572:
573: 3.1C (1/10/98):
574: 1. Update latest BIOS version checked for from the /proc file.
575: 2. Don't set microcode SDTR variable at initialization. Instead
576: wait until device capabilities have been detected from an Inquiry
577: command.
578:
579: 3.1D (1/21/98):
580: 1. Improve performance when the driver is compiled as module by
581: allowing up to 64 scatter-gather elements instead of 8.
582:
583: 3.1E (5/1/98):
584: 1. Set time delay in AscWaitTixISRDone() to 1000 ms.
585: 2. Include SMP locking changes.
586: 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS
587: access functions.
588: 4. Update board serial number printing.
589: 5. Try allocating an IRQ both with and without the SA_INTERRUPT
590: flag set to allow IRQ sharing with drivers that do not set
591: the SA_INTERRUPT flag. Also display a more descriptive error
592: message if request_irq() fails.
593: 5. Update to latest Asc and Adv Libraries.
594:
595: J. Known Problems or Issues
596:
597: 1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around
598: the queue depth flow control code when mid-level SCSI changes
599: are included in Linux.
600:
601: K. Credits
602:
603: Nathan Hartwell <[email protected]> provided the directions and
604: basis for the Linux v1.3.X changes which were included in the
605: 1.2 release.
606:
607: Thomas E Zerucha <[email protected]> pointed out a bug
608: in advansys_biosparam() which was fixed in the 1.3 release.
609:
610: Erik Ratcliffe <[email protected]> has done testing of the
611: AdvanSys driver in the Caldera releases.
612:
613: Rik van Riel <[email protected]> provided a patch to
614: AscWaitTixISRDone() which he found necessary to make the
615: driver work with a SCSI-1 disk.
616:
617: Mark Moran <[email protected]> has helped test Ultra-Wide
618: support in the 3.1A driver.
619:
620: L. AdvanSys Contact Information
621:
622: Mail: Advanced System Products, Inc.
623: 1150 Ringwood Court
624: San Jose, CA 95131
625: Operator: 1-408-383-9400
626: FAX: 1-408-383-9612
627: Tech Support: 1-800-525-7440/1-408-467-2930
628: BBS: 1-408-383-9540 (14400,N,8,1)
629: Interactive FAX: 1-408-383-9753
630: Customer Direct Sales: 1-800-525-7443/1-408-383-5777
631: Tech Support E-Mail: [email protected]
632: FTP Site: ftp.advansys.com (login: anonymous)
633: Web Site: http://www.advansys.com
634:
635: */
636:
637:
638: /*
639: * --- Linux Version
640: */
641:
642: /* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
643: #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
644:
645: #ifndef LINUX_VERSION_CODE
646: #include <linux/version.h>
647: #endif /* LINUX_VERSION_CODE */
648:
649:
650: /*
651: * --- Linux Include Files
652: */
653:
654: #include <linux/config.h>
655: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
656: #ifdef MODULE
657: #include <linux/module.h>
658: #endif /* MODULE */
659: #endif /* version >= v1.3.0 */
660: #include <linux/string.h>
661: #include <linux/sched.h>
662: #include <linux/kernel.h>
663: #include <linux/head.h>
664: #include <linux/types.h>
665: #include <linux/ioport.h>
666: #include <linux/delay.h>
667: #include <linux/malloc.h>
668: #include <linux/mm.h>
669: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
670: #include <linux/proc_fs.h>
671: #endif /* version >= v1.3.0 */
672: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,23)
673: #include <linux/init.h>
674: #endif /* version >= v2.1.23 */
675: #include <asm/io.h>
676: #include <asm/system.h>
677: #include <asm/dma.h>
678: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
679: #include "../block/blk.h"
680: #else /* version >= v1.3.0 */
681: #include <linux/blk.h>
682: #include <linux/stat.h>
683: #endif /* version >= v1.3.0 */
684: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95)
685: #include <asm/spinlock.h>
686: #endif /* version >= 2.1.95 */
687: #include "scsi.h"
688: #include "hosts.h"
689: #include "sd.h"
690: #include "advansys.h"
691: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,93)
692: #ifdef CONFIG_PCI
693: #include <linux/pci.h>
694: #endif /* CONFIG_PCI */
695: #else /* version < v2.1.93 */
696: /*
697: * For earlier than v2.1.93 the driver has its own PCI configuration.
698: * If PCI is not needed in a kernel before v2.1.93 this define can be
699: * turned-off to make the driver object smaller.
700: */
701: #define ASC_CONFIG_PCI
702: #endif /* version < v2.1.93 */
703:
704: /*
705: * If Linux eventually defines a DID_UNDERRUN, the constant here can be
706: * removed. The current value of zero for DID_UNDERRUN results in underrun
707: * conditions being ignored.
708: */
709: #define DID_UNDERRUN 0
710:
711:
712: /*
713: * --- Driver Options
714: */
715:
716: /* Enable driver assertions. */
717: #define ADVANSYS_ASSERT
718:
719: /* Enable driver tracing. */
720: /* #define ADVANSYS_DEBUG */
721:
722: /*
723: * Because of no /proc to display them, statistics are disabled
724: * for versions prior to v1.3.0.
725: */
726: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
727: #undef ADVANSYS_STATS /* Disable statistics */
728: #else /* version >= v1.3.0 */
729: #define ADVANSYS_STATS /* Enable statistics. */
730: #endif /* version >= v1.3.0 */
731:
732:
733: /*
734: * --- Debugging Header
735: */
736:
737: #ifdef ADVANSYS_DEBUG
738: #define STATIC
739: #else /* ADVANSYS_DEBUG */
740: #define STATIC static
741: #endif /* ADVANSYS_DEBUG */
742:
743:
744: /*
745: * --- Asc Library Constants and Macros
746: */
747:
748: #define ASC_LIB_VERSION_MAJOR 1
749: #define ASC_LIB_VERSION_MINOR 22
750: #define ASC_LIB_SERIAL_NUMBER 113
751:
752: typedef unsigned char uchar;
753:
754: #ifndef NULL
755: #define NULL (0)
756: #endif
757: #ifndef TRUE
758: #define TRUE (1)
759: #endif
760: #ifndef FALSE
761: #define FALSE (0)
762: #endif
763: #define REG register
764: #define rchar REG __s8
765: #define rshort REG __s16
766: #define rint REG __s32
767: #define rlong REG __s32
768: #define ruchar REG __u8
769: #define rushort REG __u16
770: #define ruint REG __u32
771: #define rulong REG __u32
772: #define NULLPTR (void *)0
773: #define FNULLPTR (void *)0UL
774: #define EOF (-1)
775: #define EOS '\0'
776: #define ERR (-1)
777: #define UB_ERR (uchar)(0xFF)
778: #define UW_ERR (uint)(0xFFFF)
779: #define UL_ERR (ulong)(0xFFFFFFFFUL)
780: #define iseven_word(val) ((((uint)val) & (uint)0x0001) == 0)
781: #define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
782: #define toeven_word(val) (((uint)val) & (uint)0xFFFE)
783: #define biton(val, bits) (((uint)(val >> bits) & (uint)0x0001) != 0)
784: #define bitoff(val, bits) (((uint)(val >> bits) & (uint)0x0001) == 0)
785: #define lbiton(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) != 0)
786: #define lbitoff(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) == 0)
787: #define absh(val) ((val) < 0 ? -(val) : (val))
788: #define swapbyte(ch) ((((ch) << 4) | ((ch) >> 4)))
789: #ifndef GBYTE
790: #define GBYTE (0x40000000UL)
791: #endif
792: #ifndef MBYTE
793: #define MBYTE (0x100000UL)
794: #endif
795: #ifndef KBYTE
796: #define KBYTE (0x400)
797: #endif
798: #define HI_BYTE(x) (*((__u8 *)(&x)+1))
799: #define LO_BYTE(x) (*((__u8 *)&x))
800: #define HI_WORD(x) (*((__u16 *)(&x)+1))
801: #define LO_WORD(x) (*((__u16 *)&x))
802: #ifndef MAKEWORD
803: #define MAKEWORD(lo, hi) ((__u16) (((__u16) lo) | ((__u16) hi << 8)))
804: #endif
805: #ifndef MAKELONG
806: #define MAKELONG(lo, hi) ((__u32) (((__u32) lo) | ((__u32) hi << 16)))
807: #endif
808: #define SwapWords(dWord) ((__u32) ((dWord >> 16) | (dWord << 16)))
809: #define SwapBytes(word) ((__u16) ((word >> 8) | (word << 8)))
810: #define BigToLittle(dWord) ((__u32) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
811: #define LittleToBig(dWord) BigToLittle(dWord)
812: #define AscPCIConfigVendorIDRegister 0x0000
813: #define AscPCIConfigDeviceIDRegister 0x0002
814: #define AscPCIConfigCommandRegister 0x0004
815: #define AscPCIConfigStatusRegister 0x0006
816: #define AscPCIConfigRevisionIDRegister 0x0008
817: #define AscPCIConfigCacheSize 0x000C
818: #define AscPCIConfigLatencyTimer 0x000D
819: #define AscPCIIOBaseRegister 0x0010
820: #define AscPCICmdRegBits_IOMemBusMaster 0x0007
821: #define ASC_PCI_ID2BUS(id) ((id) & 0xFF)
822: #define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F)
823: #define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7)
824: #define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
825: #define ASC_PCI_VENDORID 0x10CD
826: #define ASC_PCI_DEVICEID_1200A 0x1100
827: #define ASC_PCI_DEVICEID_1200B 0x1200
828: #define ASC_PCI_DEVICEID_ULTRA 0x1300
829: #define ASC_PCI_REVISION_3150 0x02
830: #define ASC_PCI_REVISION_3050 0x03
831:
832: #define ASC_DVCLIB_CALL_DONE (1)
833: #define ASC_DVCLIB_CALL_FAILED (0)
834: #define ASC_DVCLIB_CALL_ERROR (-1)
835:
836: #define PortAddr unsigned short /* port address size */
837: #define Ptr2Func ulong
838: #define inp(port) inb(port)
839: #define inpw(port) inw(port)
840: #define inpl(port) inl(port)
841: #define outp(port, byte) outb((byte), (port))
842: #define outpw(port, word) outw((word), (port))
843: #define outpl(port, long) outl((long), (port))
844: #define ASC_MAX_SG_QUEUE 7
845: #define ASC_MAX_SG_LIST SG_ALL
846:
847: #define ASC_CS_TYPE unsigned short
848: #ifndef asc_ptr_type
849: #define asc_ptr_type
850: #endif
851:
852: #ifndef ASC_GET_PTR2FUNC
853: #define ASC_GET_PTR2FUNC(fun) (Ptr2Func)(fun)
854: #endif
855: #define FLIP_BYTE_NIBBLE(x) (((x<<4)& 0xFF) | (x>>4))
856: #define ASC_IS_ISA (0x0001)
857: #define ASC_IS_ISAPNP (0x0081)
858: #define ASC_IS_EISA (0x0002)
859: #define ASC_IS_PCI (0x0004)
860: #define ASC_IS_PCI_ULTRA (0x0104)
861: #define ASC_IS_PCMCIA (0x0008)
862: #define ASC_IS_MCA (0x0020)
863: #define ASC_IS_VL (0x0040)
864: #define ASC_ISA_PNP_PORT_ADDR (0x279)
865: #define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
866: #define ASC_IS_WIDESCSI_16 (0x0100)
867: #define ASC_IS_WIDESCSI_32 (0x0200)
868: #define ASC_IS_BIG_ENDIAN (0x8000)
869: #define ASC_CHIP_MIN_VER_VL (0x01)
870: #define ASC_CHIP_MAX_VER_VL (0x07)
871: #define ASC_CHIP_MIN_VER_PCI (0x09)
872: #define ASC_CHIP_MAX_VER_PCI (0x0F)
873: #define ASC_CHIP_VER_PCI_BIT (0x08)
874: #define ASC_CHIP_MIN_VER_ISA (0x11)
875: #define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
876: #define ASC_CHIP_MAX_VER_ISA (0x27)
877: #define ASC_CHIP_VER_ISA_BIT (0x30)
878: #define ASC_CHIP_VER_ISAPNP_BIT (0x20)
879: #define ASC_CHIP_VER_ASYN_BUG (0x21)
880: #define ASC_CHIP_VER_PCI 0x08
881: #define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
882: #define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
883: #define ASC_CHIP_MIN_VER_EISA (0x41)
884: #define ASC_CHIP_MAX_VER_EISA (0x47)
885: #define ASC_CHIP_VER_EISA_BIT (0x40)
886: #define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
887: #define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
888: #define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
889: #define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
890: #define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
891: #define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
892: #define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
893: #define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
894: #define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
895: #define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
896: #define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
897: #ifndef inpw_noswap
898: #define inpw_noswap(port) inpw(port)
899: #endif
900: #ifndef outpw_noswap
901: #define outpw_noswap(port, data) outpw(port, data)
902: #endif
903: #define ASC_SCSI_ID_BITS 3
904: #define ASC_SCSI_TIX_TYPE uchar
905: #define ASC_ALL_DEVICE_BIT_SET 0xFF
906: #ifdef ASC_WIDESCSI_16
907: #undef ASC_SCSI_ID_BITS
908: #define ASC_SCSI_ID_BITS 4
909: #define ASC_ALL_DEVICE_BIT_SET 0xFFFF
910: #endif
911: #ifdef ASC_WIDESCSI_32
912: #undef ASC_SCSI_ID_BITS
913: #define ASC_SCSI_ID_BITS 5
914: #define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL
915: #endif
916: #if ASC_SCSI_ID_BITS == 3
917: #define ASC_SCSI_BIT_ID_TYPE uchar
918: #define ASC_MAX_TID 7
919: #define ASC_MAX_LUN 7
920: #define ASC_SCSI_WIDTH_BIT_SET 0xFF
921: #elif ASC_SCSI_ID_BITS == 4
922: #define ASC_SCSI_BIT_ID_TYPE ushort
923: #define ASC_MAX_TID 15
924: #define ASC_MAX_LUN 7
925: #define ASC_SCSI_WIDTH_BIT_SET 0xFFFF
926: #elif ASC_SCSI_ID_BITS == 5
927: #define ASC_SCSI_BIT_ID_TYPE ulong
928: #define ASC_MAX_TID 31
929: #define ASC_MAX_LUN 7
930: #define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF
931: #else
932: #error ASC_SCSI_ID_BITS definition is wrong
933: #endif
934: #define ASC_MAX_SENSE_LEN 32
935: #define ASC_MIN_SENSE_LEN 14
936: #define ASC_MAX_CDB_LEN 12
937: #define ASC_SCSI_RESET_HOLD_TIME_US 60
938: #define SCSICMD_TestUnitReady 0x00
939: #define SCSICMD_Rewind 0x01
940: #define SCSICMD_Rezero 0x01
941: #define SCSICMD_RequestSense 0x03
942: #define SCSICMD_Format 0x04
943: #define SCSICMD_FormatUnit 0x04
944: #define SCSICMD_Read6 0x08
945: #define SCSICMD_Write6 0x0A
946: #define SCSICMD_Seek6 0x0B
947: #define SCSICMD_Inquiry 0x12
948: #define SCSICMD_Verify6 0x13
949: #define SCSICMD_ModeSelect6 0x15
950: #define SCSICMD_ModeSense6 0x1A
951: #define SCSICMD_StartStopUnit 0x1B
952: #define SCSICMD_LoadUnloadTape 0x1B
953: #define SCSICMD_ReadCapacity 0x25
954: #define SCSICMD_Read10 0x28
955: #define SCSICMD_Write10 0x2A
956: #define SCSICMD_Seek10 0x2B
957: #define SCSICMD_Erase10 0x2C
958: #define SCSICMD_WriteAndVerify10 0x2E
959: #define SCSICMD_Verify10 0x2F
960: #define SCSICMD_WriteBuffer 0x3B
961: #define SCSICMD_ReadBuffer 0x3C
962: #define SCSICMD_ReadLong 0x3E
963: #define SCSICMD_WriteLong 0x3F
964: #define SCSICMD_ReadTOC 0x43
965: #define SCSICMD_ReadHeader 0x44
966: #define SCSICMD_ModeSelect10 0x55
967: #define SCSICMD_ModeSense10 0x5A
968: #define SCSI_TYPE_DASD 0x00
969: #define SCSI_TYPE_SASD 0x01
970: #define SCSI_TYPE_PRN 0x02
971: #define SCSI_TYPE_PROC 0x03
972: #define SCSI_TYPE_WORM 0x04
973: #define SCSI_TYPE_CDROM 0x05
974: #define SCSI_TYPE_SCANNER 0x06
975: #define SCSI_TYPE_OPTMEM 0x07
976: #define SCSI_TYPE_MED_CHG 0x08
977: #define SCSI_TYPE_COMM 0x09
978: #define SCSI_TYPE_UNKNOWN 0x1F
979: #define SCSI_TYPE_NO_DVC 0xFF
980: #define ASC_SCSIDIR_NOCHK 0x00
981: #define ASC_SCSIDIR_T2H 0x08
982: #define ASC_SCSIDIR_H2T 0x10
983: #define ASC_SCSIDIR_NODATA 0x18
984: #define SCSI_SENKEY_NO_SENSE 0x00
985: #define SCSI_SENKEY_UNDEFINED 0x01
986: #define SCSI_SENKEY_NOT_READY 0x02
987: #define SCSI_SENKEY_MEDIUM_ERR 0x03
988: #define SCSI_SENKEY_HW_ERR 0x04
989: #define SCSI_SENKEY_ILLEGAL 0x05
990: #define SCSI_SENKEY_ATTENTION 0x06
991: #define SCSI_SENKEY_PROTECTED 0x07
992: #define SCSI_SENKEY_BLANK 0x08
993: #define SCSI_SENKEY_V_UNIQUE 0x09
994: #define SCSI_SENKEY_CPY_ABORT 0x0A
995: #define SCSI_SENKEY_ABORT 0x0B
996: #define SCSI_SENKEY_EQUAL 0x0C
997: #define SCSI_SENKEY_VOL_OVERFLOW 0x0D
998: #define SCSI_SENKEY_MISCOMP 0x0E
999: #define SCSI_SENKEY_RESERVED 0x0F
1000: #define SCSI_ASC_NOMEDIA 0x3A
1001: #define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
1002: #define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
1003: #define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
1004: #define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
1005: #define SS_GOOD 0x00
1006: #define SS_CHK_CONDITION 0x02
1007: #define SS_CONDITION_MET 0x04
1008: #define SS_TARGET_BUSY 0x08
1009: #define SS_INTERMID 0x10
1010: #define SS_INTERMID_COND_MET 0x14
1011: #define SS_RSERV_CONFLICT 0x18
1012: #define SS_CMD_TERMINATED 0x22
1013: #define SS_QUEUE_FULL 0x28
1014: #define MS_CMD_DONE 0x00
1015: #define MS_EXTEND 0x01
1016: #define MS_SDTR_LEN 0x03
1017: #define MS_SDTR_CODE 0x01
1018: #define MS_WDTR_LEN 0x02
1019: #define MS_WDTR_CODE 0x03
1020: #define MS_MDP_LEN 0x05
1021: #define MS_MDP_CODE 0x00
1022: #define M1_SAVE_DATA_PTR 0x02
1023: #define M1_RESTORE_PTRS 0x03
1024: #define M1_DISCONNECT 0x04
1025: #define M1_INIT_DETECTED_ERR 0x05
1026: #define M1_ABORT 0x06
1027: #define M1_MSG_REJECT 0x07
1028: #define M1_NO_OP 0x08
1029: #define M1_MSG_PARITY_ERR 0x09
1030: #define M1_LINK_CMD_DONE 0x0A
1031: #define M1_LINK_CMD_DONE_WFLAG 0x0B
1032: #define M1_BUS_DVC_RESET 0x0C
1033: #define M1_ABORT_TAG 0x0D
1034: #define M1_CLR_QUEUE 0x0E
1035: #define M1_INIT_RECOVERY 0x0F
1036: #define M1_RELEASE_RECOVERY 0x10
1037: #define M1_KILL_IO_PROC 0x11
1038: #define M2_QTAG_MSG_SIMPLE 0x20
1039: #define M2_QTAG_MSG_HEAD 0x21
1040: #define M2_QTAG_MSG_ORDERED 0x22
1041: #define M2_IGNORE_WIDE_RESIDUE 0x23
1042:
1043: typedef struct {
1044: uchar peri_dvc_type:5;
1045: uchar peri_qualifier:3;
1046: } ASC_SCSI_INQ0;
1047:
1048: typedef struct {
1049: uchar dvc_type_modifier:7;
1050: uchar rmb:1;
1051: } ASC_SCSI_INQ1;
1052:
1053: typedef struct {
1054: uchar ansi_apr_ver:3;
1055: uchar ecma_ver:3;
1056: uchar iso_ver:2;
1057: } ASC_SCSI_INQ2;
1058:
1059: typedef struct {
1060: uchar rsp_data_fmt:4;
1061: uchar res:2;
1062: uchar TemIOP:1;
1063: uchar aenc:1;
1064: } ASC_SCSI_INQ3;
1065:
1066: typedef struct {
1067: uchar StfRe:1;
1068: uchar CmdQue:1;
1069: uchar Reserved:1;
1070: uchar Linked:1;
1071: uchar Sync:1;
1072: uchar WBus16:1;
1073: uchar WBus32:1;
1074: uchar RelAdr:1;
1075: } ASC_SCSI_INQ7;
1076:
1077: typedef struct {
1078: ASC_SCSI_INQ0 byte0;
1079: ASC_SCSI_INQ1 byte1;
1080: ASC_SCSI_INQ2 byte2;
1081: ASC_SCSI_INQ3 byte3;
1082: uchar add_len;
1083: uchar res1;
1084: uchar res2;
1085: ASC_SCSI_INQ7 byte7;
1086: uchar vendor_id[8];
1087: uchar product_id[16];
1088: uchar product_rev_level[4];
1089: } ASC_SCSI_INQUIRY;
1090:
1091: typedef struct asc_req_sense {
1092: uchar err_code:7;
1093: uchar info_valid:1;
1094: uchar segment_no;
1095: uchar sense_key:4;
1096: uchar reserved_bit:1;
1097: uchar sense_ILI:1;
1098: uchar sense_EOM:1;
1099: uchar file_mark:1;
1100: uchar info1[4];
1101: uchar add_sense_len;
1102: uchar cmd_sp_info[4];
1103: uchar asc;
1104: uchar ascq;
1105: uchar fruc;
1106: uchar sks_byte0:7;
1107: uchar sks_valid:1;
1108: uchar sks_bytes[2];
1109: uchar notused[2];
1110: uchar ex_sense_code;
1111: uchar info2[4];
1112: } ASC_REQ_SENSE;
1113:
1114: #define ASC_SG_LIST_PER_Q 7
1115: #define QS_FREE 0x00
1116: #define QS_READY 0x01
1117: #define QS_DISC1 0x02
1118: #define QS_DISC2 0x04
1119: #define QS_BUSY 0x08
1120: #define QS_ABORTED 0x40
1121: #define QS_DONE 0x80
1122: #define QC_NO_CALLBACK 0x01
1123: #define QC_SG_SWAP_QUEUE 0x02
1124: #define QC_SG_HEAD 0x04
1125: #define QC_DATA_IN 0x08
1126: #define QC_DATA_OUT 0x10
1127: #define QC_URGENT 0x20
1128: #define QC_MSG_OUT 0x40
1129: #define QC_REQ_SENSE 0x80
1130: #define QCSG_SG_XFER_LIST 0x02
1131: #define QCSG_SG_XFER_MORE 0x04
1132: #define QCSG_SG_XFER_END 0x08
1133: #define QD_IN_PROGRESS 0x00
1134: #define QD_NO_ERROR 0x01
1135: #define QD_ABORTED_BY_HOST 0x02
1136: #define QD_WITH_ERROR 0x04
1137: #define QD_INVALID_REQUEST 0x80
1138: #define QD_INVALID_HOST_NUM 0x81
1139: #define QD_INVALID_DEVICE 0x82
1140: #define QD_ERR_INTERNAL 0xFF
1141: #define QHSTA_NO_ERROR 0x00
1142: #define QHSTA_M_SEL_TIMEOUT 0x11
1143: #define QHSTA_M_DATA_OVER_RUN 0x12
1144: #define QHSTA_M_DATA_UNDER_RUN 0x12
1145: #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
1146: #define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
1147: #define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
1148: #define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
1149: #define QHSTA_D_HOST_ABORT_FAILED 0x23
1150: #define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
1151: #define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
1152: #define QHSTA_D_ASPI_NO_BUF_POOL 0x26
1153: #define QHSTA_M_WTM_TIMEOUT 0x41
1154: #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
1155: #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
1156: #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
1157: #define QHSTA_M_TARGET_STATUS_BUSY 0x45
1158: #define QHSTA_M_BAD_TAG_CODE 0x46
1159: #define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
1160: #define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
1161: #define QHSTA_D_LRAM_CMP_ERROR 0x81
1162: #define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1163: #define ASC_FLAG_SCSIQ_REQ 0x01
1164: #define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1165: #define ASC_FLAG_BIOS_ASYNC_IO 0x04
1166: #define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1167: #define ASC_FLAG_WIN16 0x10
1168: #define ASC_FLAG_WIN32 0x20
1169: #define ASC_FLAG_ISA_OVER_16MB 0x40
1170: #define ASC_FLAG_DOS_VM_CALLBACK 0x80
1171: #define ASC_TAG_FLAG_EXTRA_BYTES 0x10
1172: #define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
1173: #define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
1174: #define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
1175: #define ASC_SCSIQ_CPY_BEG 4
1176: #define ASC_SCSIQ_SGHD_CPY_BEG 2
1177: #define ASC_SCSIQ_B_FWD 0
1178: #define ASC_SCSIQ_B_BWD 1
1179: #define ASC_SCSIQ_B_STATUS 2
1180: #define ASC_SCSIQ_B_QNO 3
1181: #define ASC_SCSIQ_B_CNTL 4
1182: #define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1183: #define ASC_SCSIQ_D_DATA_ADDR 8
1184: #define ASC_SCSIQ_D_DATA_CNT 12
1185: #define ASC_SCSIQ_B_SENSE_LEN 20
1186: #define ASC_SCSIQ_DONE_INFO_BEG 22
1187: #define ASC_SCSIQ_D_SRBPTR 22
1188: #define ASC_SCSIQ_B_TARGET_IX 26
1189: #define ASC_SCSIQ_B_CDB_LEN 28
1190: #define ASC_SCSIQ_B_TAG_CODE 29
1191: #define ASC_SCSIQ_W_VM_ID 30
1192: #define ASC_SCSIQ_DONE_STATUS 32
1193: #define ASC_SCSIQ_HOST_STATUS 33
1194: #define ASC_SCSIQ_SCSI_STATUS 34
1195: #define ASC_SCSIQ_CDB_BEG 36
1196: #define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1197: #define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1198: #define ASC_SCSIQ_B_SG_WK_QP 49
1199: #define ASC_SCSIQ_B_SG_WK_IX 50
1200: #define ASC_SCSIQ_W_REQ_COUNT 52
1201: #define ASC_SCSIQ_B_LIST_CNT 6
1202: #define ASC_SCSIQ_B_CUR_LIST_CNT 7
1203: #define ASC_SGQ_B_SG_CNTL 4
1204: #define ASC_SGQ_B_SG_HEAD_QP 5
1205: #define ASC_SGQ_B_SG_LIST_CNT 6
1206: #define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1207: #define ASC_SGQ_LIST_BEG 8
1208: #define ASC_DEF_SCSI1_QNG 4
1209: #define ASC_MAX_SCSI1_QNG 4
1210: #define ASC_DEF_SCSI2_QNG 16
1211: #define ASC_MAX_SCSI2_QNG 32
1212: #define ASC_TAG_CODE_MASK 0x23
1213: #define ASC_STOP_REQ_RISC_STOP 0x01
1214: #define ASC_STOP_ACK_RISC_STOP 0x03
1215: #define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1216: #define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1217: #define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1218: #define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
1219: #define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
1220: #define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
1221: #define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
1222: #define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
1223: #define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
1224: #define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
1225:
1226: typedef struct asc_scisq_1 {
1227: uchar status;
1228: uchar q_no;
1229: uchar cntl;
1230: uchar sg_queue_cnt;
1231: uchar target_id;
1232: uchar target_lun;
1233: ulong data_addr;
1234: ulong data_cnt;
1235: ulong sense_addr;
1236: uchar sense_len;
1237: uchar extra_bytes;
1238: } ASC_SCSIQ_1;
1239:
1240: typedef struct asc_scisq_2 {
1241: ulong srb_ptr;
1242: uchar target_ix;
1243: uchar flag;
1244: uchar cdb_len;
1245: uchar tag_code;
1246: ushort vm_id;
1247: } ASC_SCSIQ_2;
1248:
1249: typedef struct asc_scsiq_3 {
1250: uchar done_stat;
1251: uchar host_stat;
1252: uchar scsi_stat;
1253: uchar scsi_msg;
1254: } ASC_SCSIQ_3;
1255:
1256: typedef struct asc_scsiq_4 {
1257: uchar cdb[ASC_MAX_CDB_LEN];
1258: uchar y_first_sg_list_qp;
1259: uchar y_working_sg_qp;
1260: uchar y_working_sg_ix;
1261: uchar y_res;
1262: ushort x_req_count;
1263: ushort x_reconnect_rtn;
1264: ulong x_saved_data_addr;
1265: ulong x_saved_data_cnt;
1266: } ASC_SCSIQ_4;
1267:
1268: typedef struct asc_q_done_info {
1269: ASC_SCSIQ_2 d2;
1270: ASC_SCSIQ_3 d3;
1271: uchar q_status;
1272: uchar q_no;
1273: uchar cntl;
1274: uchar sense_len;
1275: uchar extra_bytes;
1276: uchar res;
1277: ulong remain_bytes;
1278: } ASC_QDONE_INFO;
1279:
1280: typedef struct asc_sg_list {
1281: ulong addr;
1282: ulong bytes;
1283: } ASC_SG_LIST;
1284:
1285: typedef struct asc_sg_head {
1286: ushort entry_cnt;
1287: ushort queue_cnt;
1288: ushort entry_to_copy;
1289: ushort res;
1290: ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
1291: } ASC_SG_HEAD;
1292:
1293: #define ASC_MIN_SG_LIST 2
1294:
1295: typedef struct asc_min_sg_head {
1296: ushort entry_cnt;
1297: ushort queue_cnt;
1298: ushort entry_to_copy;
1299: ushort res;
1300: ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
1301: } ASC_MIN_SG_HEAD;
1302:
1303: #define QCX_SORT (0x0001)
1304: #define QCX_COALEASE (0x0002)
1305:
1306: typedef struct asc_scsi_q {
1307: ASC_SCSIQ_1 q1;
1308: ASC_SCSIQ_2 q2;
1309: uchar *cdbptr;
1310: ASC_SG_HEAD *sg_head;
1311: } ASC_SCSI_Q;
1312:
1313: typedef struct asc_scsi_req_q {
1314: ASC_SCSIQ_1 r1;
1315: ASC_SCSIQ_2 r2;
1316: uchar *cdbptr;
1317: ASC_SG_HEAD *sg_head;
1318: uchar *sense_ptr;
1319: ASC_SCSIQ_3 r3;
1320: uchar cdb[ASC_MAX_CDB_LEN];
1321: uchar sense[ASC_MIN_SENSE_LEN];
1322: } ASC_SCSI_REQ_Q;
1323:
1324: typedef struct asc_scsi_bios_req_q {
1325: ASC_SCSIQ_1 r1;
1326: ASC_SCSIQ_2 r2;
1327: uchar *cdbptr;
1328: ASC_SG_HEAD *sg_head;
1329: uchar *sense_ptr;
1330: ASC_SCSIQ_3 r3;
1331: uchar cdb[ASC_MAX_CDB_LEN];
1332: uchar sense[ASC_MIN_SENSE_LEN];
1333: } ASC_SCSI_BIOS_REQ_Q;
1334:
1335: typedef struct asc_risc_q {
1336: uchar fwd;
1337: uchar bwd;
1338: ASC_SCSIQ_1 i1;
1339: ASC_SCSIQ_2 i2;
1340: ASC_SCSIQ_3 i3;
1341: ASC_SCSIQ_4 i4;
1342: } ASC_RISC_Q;
1343:
1344: typedef struct asc_sg_list_q {
1345: uchar seq_no;
1346: uchar q_no;
1347: uchar cntl;
1348: uchar sg_head_qp;
1349: uchar sg_list_cnt;
1350: uchar sg_cur_list_cnt;
1351: } ASC_SG_LIST_Q;
1352:
1353: typedef struct asc_risc_sg_list_q {
1354: uchar fwd;
1355: uchar bwd;
1356: ASC_SG_LIST_Q sg;
1357: ASC_SG_LIST sg_list[7];
1358: } ASC_RISC_SG_LIST_Q;
1359:
1360: #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1361: #define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1362: #define ASCQ_ERR_NO_ERROR 0
1363: #define ASCQ_ERR_IO_NOT_FOUND 1
1364: #define ASCQ_ERR_LOCAL_MEM 2
1365: #define ASCQ_ERR_CHKSUM 3
1366: #define ASCQ_ERR_START_CHIP 4
1367: #define ASCQ_ERR_INT_TARGET_ID 5
1368: #define ASCQ_ERR_INT_LOCAL_MEM 6
1369: #define ASCQ_ERR_HALT_RISC 7
1370: #define ASCQ_ERR_GET_ASPI_ENTRY 8
1371: #define ASCQ_ERR_CLOSE_ASPI 9
1372: #define ASCQ_ERR_HOST_INQUIRY 0x0A
1373: #define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1374: #define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1375: #define ASCQ_ERR_Q_STATUS 0x0D
1376: #define ASCQ_ERR_WR_SCSIQ 0x0E
1377: #define ASCQ_ERR_PC_ADDR 0x0F
1378: #define ASCQ_ERR_SYN_OFFSET 0x10
1379: #define ASCQ_ERR_SYN_XFER_TIME 0x11
1380: #define ASCQ_ERR_LOCK_DMA 0x12
1381: #define ASCQ_ERR_UNLOCK_DMA 0x13
1382: #define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1383: #define ASCQ_ERR_MICRO_CODE_HALT 0x15
1384: #define ASCQ_ERR_SET_LRAM_ADDR 0x16
1385: #define ASCQ_ERR_CUR_QNG 0x17
1386: #define ASCQ_ERR_SG_Q_LINKS 0x18
1387: #define ASCQ_ERR_SCSIQ_PTR 0x19
1388: #define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1389: #define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1390: #define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1391: #define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1392: #define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1393: #define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1394: #define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1395: #define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1396: #define ASCQ_ERR_SEND_SCSI_Q 0x22
1397: #define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1398: #define ASCQ_ERR_RESET_SDTR 0x24
1399: #define ASC_WARN_NO_ERROR 0x0000
1400: #define ASC_WARN_IO_PORT_ROTATE 0x0001
1401: #define ASC_WARN_EEPROM_CHKSUM 0x0002
1402: #define ASC_WARN_IRQ_MODIFIED 0x0004
1403: #define ASC_WARN_AUTO_CONFIG 0x0008
1404: #define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1405: #define ASC_WARN_EEPROM_RECOVER 0x0020
1406: #define ASC_WARN_CFG_MSW_RECOVER 0x0040
1407: #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
1408: #define ASC_IERR_WRITE_EEPROM 0x0001
1409: #define ASC_IERR_MCODE_CHKSUM 0x0002
1410: #define ASC_IERR_SET_PC_ADDR 0x0004
1411: #define ASC_IERR_START_STOP_CHIP 0x0008
1412: #define ASC_IERR_IRQ_NO 0x0010
1413: #define ASC_IERR_SET_IRQ_NO 0x0020
1414: #define ASC_IERR_CHIP_VERSION 0x0040
1415: #define ASC_IERR_SET_SCSI_ID 0x0080
1416: #define ASC_IERR_GET_PHY_ADDR 0x0100
1417: #define ASC_IERR_BAD_SIGNATURE 0x0200
1418: #define ASC_IERR_NO_BUS_TYPE 0x0400
1419: #define ASC_IERR_SCAM 0x0800
1420: #define ASC_IERR_SET_SDTR 0x1000
1421: #define ASC_IERR_RW_LRAM 0x8000
1422: #define ASC_DEF_IRQ_NO 10
1423: #define ASC_MAX_IRQ_NO 15
1424: #define ASC_MIN_IRQ_NO 10
1425: #define ASC_MIN_REMAIN_Q (0x02)
1426: #define ASC_DEF_MAX_TOTAL_QNG (0xF0)
1427: #define ASC_MIN_TAG_Q_PER_DVC (0x04)
1428: #define ASC_DEF_TAG_Q_PER_DVC (0x04)
1429: #define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1430: #define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
1431: #define ASC_MAX_TOTAL_QNG 240
1432: #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
1433: #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
1434: #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1435: #define ASC_MAX_INRAM_TAG_QNG 16
1436: #define ASC_IOADR_TABLE_MAX_IX 11
1437: #define ASC_IOADR_GAP 0x10
1438: #define ASC_SEARCH_IOP_GAP 0x10
1439: #define ASC_MIN_IOP_ADDR (PortAddr)0x0100
1440: #define ASC_MAX_IOP_ADDR (PortAddr)0x3F0
1441: #define ASC_IOADR_1 (PortAddr)0x0110
1442: #define ASC_IOADR_2 (PortAddr)0x0130
1443: #define ASC_IOADR_3 (PortAddr)0x0150
1444: #define ASC_IOADR_4 (PortAddr)0x0190
1445: #define ASC_IOADR_5 (PortAddr)0x0210
1446: #define ASC_IOADR_6 (PortAddr)0x0230
1447: #define ASC_IOADR_7 (PortAddr)0x0250
1448: #define ASC_IOADR_8 (PortAddr)0x0330
1449: #define ASC_IOADR_DEF ASC_IOADR_8
1450: #define ASC_LIB_SCSIQ_WK_SP 256
1451: #define ASC_MAX_SYN_XFER_NO 16
1452: #define ASC_SYN_MAX_OFFSET 0x0F
1453: #define ASC_DEF_SDTR_OFFSET 0x0F
1454: #define ASC_DEF_SDTR_INDEX 0x00
1455: #define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
1456: #define SYN_XFER_NS_0 25
1457: #define SYN_XFER_NS_1 30
1458: #define SYN_XFER_NS_2 35
1459: #define SYN_XFER_NS_3 40
1460: #define SYN_XFER_NS_4 50
1461: #define SYN_XFER_NS_5 60
1462: #define SYN_XFER_NS_6 70
1463: #define SYN_XFER_NS_7 85
1464: #define SYN_ULTRA_XFER_NS_0 12
1465: #define SYN_ULTRA_XFER_NS_1 19
1466: #define SYN_ULTRA_XFER_NS_2 25
1467: #define SYN_ULTRA_XFER_NS_3 32
1468: #define SYN_ULTRA_XFER_NS_4 38
1469: #define SYN_ULTRA_XFER_NS_5 44
1470: #define SYN_ULTRA_XFER_NS_6 50
1471: #define SYN_ULTRA_XFER_NS_7 57
1472: #define SYN_ULTRA_XFER_NS_8 63
1473: #define SYN_ULTRA_XFER_NS_9 69
1474: #define SYN_ULTRA_XFER_NS_10 75
1475: #define SYN_ULTRA_XFER_NS_11 82
1476: #define SYN_ULTRA_XFER_NS_12 88
1477: #define SYN_ULTRA_XFER_NS_13 94
1478: #define SYN_ULTRA_XFER_NS_14 100
1479: #define SYN_ULTRA_XFER_NS_15 107
1480:
1481: typedef struct ext_msg {
1482: uchar msg_type;
1483: uchar msg_len;
1484: uchar msg_req;
1485: union {
1486: struct {
1487: uchar sdtr_xfer_period;
1488: uchar sdtr_req_ack_offset;
1489: } sdtr;
1490: struct {
1491: uchar wdtr_width;
1492: } wdtr;
1493: struct {
1494: uchar mdp_b3;
1495: uchar mdp_b2;
1496: uchar mdp_b1;
1497: uchar mdp_b0;
1498: } mdp;
1499: } u_ext_msg;
1500: uchar res;
1501: } EXT_MSG;
1502:
1503: #define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
1504: #define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
1505: #define wdtr_width u_ext_msg.wdtr.wdtr_width
1506: #define mdp_b3 u_ext_msg.mdp_b3
1507: #define mdp_b2 u_ext_msg.mdp_b2
1508: #define mdp_b1 u_ext_msg.mdp_b1
1509: #define mdp_b0 u_ext_msg.mdp_b0
1510:
1511: typedef struct asc_dvc_cfg {
1512: ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1513: ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1514: ASC_SCSI_BIT_ID_TYPE disc_enable;
1515: ASC_SCSI_BIT_ID_TYPE sdtr_enable;
1516: uchar chip_scsi_id:4;
1517: uchar isa_dma_speed:4;
1518: uchar isa_dma_channel;
1519: uchar chip_version;
1520: ushort pci_device_id;
1521: ushort lib_serial_no;
1522: ushort lib_version;
1523: ushort mcode_date;
1524: ushort mcode_version;
1525: uchar max_tag_qng[ASC_MAX_TID + 1];
1526: uchar *overrun_buf;
1527: uchar sdtr_period_offset[ASC_MAX_TID + 1];
1528: ushort pci_slot_info;
1529: uchar adapter_info[6];
1530: } ASC_DVC_CFG;
1531:
1532: #define ASC_DEF_DVC_CNTL 0xFFFF
1533: #define ASC_DEF_CHIP_SCSI_ID 7
1534: #define ASC_DEF_ISA_DMA_SPEED 4
1535: #define ASC_INIT_STATE_NULL 0x0000
1536: #define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1537: #define ASC_INIT_STATE_END_GET_CFG 0x0002
1538: #define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1539: #define ASC_INIT_STATE_END_SET_CFG 0x0008
1540: #define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1541: #define ASC_INIT_STATE_END_LOAD_MC 0x0020
1542: #define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1543: #define ASC_INIT_STATE_END_INQUIRY 0x0080
1544: #define ASC_INIT_RESET_SCSI_DONE 0x0100
1545: #define ASC_INIT_STATE_WITHOUT_EEP 0x8000
1546: #define ASC_PCI_DEVICE_ID_REV_A 0x1100
1547: #define ASC_PCI_DEVICE_ID_REV_B 0x1200
1548: #define ASC_BUG_FIX_IF_NOT_DWB 0x0001
1549: #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
1550: #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1551: #define ASC_MIN_TAGGED_CMD 7
1552: #define ASC_MAX_SCSI_RESET_WAIT 30
1553:
1554: typedef struct asc_dvc_var {
1555: PortAddr iop_base;
1556: ushort err_code;
1557: ushort dvc_cntl;
1558: ushort bug_fix_cntl;
1559: ushort bus_type;
1560: Ptr2Func isr_callback;
1561: Ptr2Func exe_callback;
1562: ASC_SCSI_BIT_ID_TYPE init_sdtr;
1563: ASC_SCSI_BIT_ID_TYPE sdtr_done;
1564: ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1565: ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1566: ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1567: ASC_SCSI_BIT_ID_TYPE start_motor;
1568: uchar scsi_reset_wait;
1569: uchar chip_no;
1570: char is_in_int;
1571: uchar max_total_qng;
1572: uchar cur_total_qng;
1573: uchar in_critical_cnt;
1574: uchar irq_no;
1575: uchar last_q_shortage;
1576: ushort init_state;
1577: uchar cur_dvc_qng[ASC_MAX_TID + 1];
1578: uchar max_dvc_qng[ASC_MAX_TID + 1];
1579: ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
1580: ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
1581: uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
1582: ASC_DVC_CFG *cfg;
1583: Ptr2Func saved_ptr2func;
1584: ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
1585: char redo_scam;
1586: ushort res2;
1587: uchar dos_int13_table[ASC_MAX_TID + 1];
1588: ulong max_dma_count;
1589: ASC_SCSI_BIT_ID_TYPE no_scam;
1590: ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1591: uchar max_sdtr_index;
1592: uchar host_init_sdtr_index;
1593: ulong drv_ptr;
1594: ulong uc_break;
1595: ulong res7;
1596: ulong res8;
1597: } ASC_DVC_VAR;
1598:
1599: typedef int (* ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO *);
1600: typedef int (* ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
1601:
1602: typedef struct asc_dvc_inq_info {
1603: uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1604: } ASC_DVC_INQ_INFO;
1605:
1606: typedef struct asc_cap_info {
1607: ulong lba;
1608: ulong blk_size;
1609: } ASC_CAP_INFO;
1610:
1611: typedef struct asc_cap_info_array {
1612: ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1613: } ASC_CAP_INFO_ARRAY;
1614:
1615: #define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
1616: #define ASC_MCNTL_NULL_TARGET (ushort)0x0002
1617: #define ASC_CNTL_INITIATOR (ushort)0x0001
1618: #define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
1619: #define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
1620: #define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
1621: #define ASC_CNTL_NO_SCAM (ushort)0x0010
1622: #define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
1623: #define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
1624: #define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
1625: #define ASC_CNTL_RESET_SCSI (ushort)0x0200
1626: #define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
1627: #define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
1628: #define ASC_CNTL_SCSI_PARITY (ushort)0x1000
1629: #define ASC_CNTL_BURST_MODE (ushort)0x2000
1630: #define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
1631: #define ASC_EEP_DVC_CFG_BEG_VL 2
1632: #define ASC_EEP_MAX_DVC_ADDR_VL 15
1633: #define ASC_EEP_DVC_CFG_BEG 32
1634: #define ASC_EEP_MAX_DVC_ADDR 45
1635: #define ASC_EEP_DEFINED_WORDS 10
1636: #define ASC_EEP_MAX_ADDR 63
1637: #define ASC_EEP_RES_WORDS 0
1638: #define ASC_EEP_MAX_RETRY 20
1639: #define ASC_MAX_INIT_BUSY_RETRY 8
1640: #define ASC_EEP_ISA_PNP_WSIZE 16
1641:
1642: typedef struct asceep_config {
1643: ushort cfg_lsw;
1644: ushort cfg_msw;
1645: uchar init_sdtr;
1646: uchar disc_enable;
1647: uchar use_cmd_qng;
1648: uchar start_motor;
1649: uchar max_total_qng;
1650: uchar max_tag_qng;
1651: uchar bios_scan;
1652: uchar power_up_wait;
1653: uchar no_scam;
1654: uchar chip_scsi_id:4;
1655: uchar isa_dma_speed:4;
1656: uchar dos_int13_table[ASC_MAX_TID + 1];
1657: uchar adapter_info[6];
1658: ushort cntl;
1659: ushort chksum;
1660: } ASCEEP_CONFIG;
1661:
1662: #define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
1663: #define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
1664: #define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
1665:
1666: #define ASC_EEP_CMD_READ 0x80
1667: #define ASC_EEP_CMD_WRITE 0x40
1668: #define ASC_EEP_CMD_WRITE_ABLE 0x30
1669: #define ASC_EEP_CMD_WRITE_DISABLE 0x00
1670: #define ASC_OVERRUN_BSIZE 0x00000048UL
1671: #define ASC_CTRL_BREAK_ONCE 0x0001
1672: #define ASC_CTRL_BREAK_STAY_IDLE 0x0002
1673: #define ASCV_MSGOUT_BEG 0x0000
1674: #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1675: #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1676: #define ASCV_BREAK_SAVED_CODE (ushort)0x0006
1677: #define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1678: #define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1679: #define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1680: #define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1681: #define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1682: #define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
1683: #define ASCV_BREAK_ADDR (ushort)0x0028
1684: #define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
1685: #define ASCV_BREAK_CONTROL (ushort)0x002C
1686: #define ASCV_BREAK_HIT_COUNT (ushort)0x002E
1687:
1688: #define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
1689: #define ASCV_MCODE_CHKSUM_W (ushort)0x0032
1690: #define ASCV_MCODE_SIZE_W (ushort)0x0034
1691: #define ASCV_STOP_CODE_B (ushort)0x0036
1692: #define ASCV_DVC_ERR_CODE_B (ushort)0x0037
1693: #define ASCV_OVERRUN_PADDR_D (ushort)0x0038
1694: #define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
1695: #define ASCV_HALTCODE_W (ushort)0x0040
1696: #define ASCV_CHKSUM_W (ushort)0x0042
1697: #define ASCV_MC_DATE_W (ushort)0x0044
1698: #define ASCV_MC_VER_W (ushort)0x0046
1699: #define ASCV_NEXTRDY_B (ushort)0x0048
1700: #define ASCV_DONENEXT_B (ushort)0x0049
1701: #define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
1702: #define ASCV_SCSIBUSY_B (ushort)0x004B
1703: #define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
1704: #define ASCV_CURCDB_B (ushort)0x004D
1705: #define ASCV_RCLUN_B (ushort)0x004E
1706: #define ASCV_BUSY_QHEAD_B (ushort)0x004F
1707: #define ASCV_DISC1_QHEAD_B (ushort)0x0050
1708: #define ASCV_DISC_ENABLE_B (ushort)0x0052
1709: #define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
1710: #define ASCV_HOSTSCSI_ID_B (ushort)0x0055
1711: #define ASCV_MCODE_CNTL_B (ushort)0x0056
1712: #define ASCV_NULL_TARGET_B (ushort)0x0057
1713: #define ASCV_FREE_Q_HEAD_W (ushort)0x0058
1714: #define ASCV_DONE_Q_TAIL_W (ushort)0x005A
1715: #define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
1716: #define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
1717: #define ASCV_HOST_FLAG_B (ushort)0x005D
1718: #define ASCV_TOTAL_READY_Q_B (ushort)0x0064
1719: #define ASCV_VER_SERIAL_B (ushort)0x0065
1720: #define ASCV_HALTCODE_SAVED_W (ushort)0x0066
1721: #define ASCV_WTM_FLAG_B (ushort)0x0068
1722: #define ASCV_RISC_FLAG_B (ushort)0x006A
1723: #define ASCV_REQ_SG_LIST_QP (ushort)0x006B
1724: #define ASC_HOST_FLAG_IN_ISR 0x01
1725: #define ASC_HOST_FLAG_ACK_INT 0x02
1726: #define ASC_RISC_FLAG_GEN_INT 0x01
1727: #define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1728: #define IOP_CTRL (0x0F)
1729: #define IOP_STATUS (0x0E)
1730: #define IOP_INT_ACK IOP_STATUS
1731: #define IOP_REG_IFC (0x0D)
1732: #define IOP_SYN_OFFSET (0x0B)
1733: #define IOP_EXTRA_CONTROL (0x0D)
1734: #define IOP_REG_PC (0x0C)
1735: #define IOP_RAM_ADDR (0x0A)
1736: #define IOP_RAM_DATA (0x08)
1737: #define IOP_EEP_DATA (0x06)
1738: #define IOP_EEP_CMD (0x07)
1739: #define IOP_VERSION (0x03)
1740: #define IOP_CONFIG_HIGH (0x04)
1741: #define IOP_CONFIG_LOW (0x02)
1742: #define IOP_SIG_BYTE (0x01)
1743: #define IOP_SIG_WORD (0x00)
1744: #define IOP_REG_DC1 (0x0E)
1745: #define IOP_REG_DC0 (0x0C)
1746: #define IOP_REG_SB (0x0B)
1747: #define IOP_REG_DA1 (0x0A)
1748: #define IOP_REG_DA0 (0x08)
1749: #define IOP_REG_SC (0x09)
1750: #define IOP_DMA_SPEED (0x07)
1751: #define IOP_REG_FLAG (0x07)
1752: #define IOP_FIFO_H (0x06)
1753: #define IOP_FIFO_L (0x04)
1754: #define IOP_REG_ID (0x05)
1755: #define IOP_REG_QP (0x03)
1756: #define IOP_REG_IH (0x02)
1757: #define IOP_REG_IX (0x01)
1758: #define IOP_REG_AX (0x00)
1759: #define IFC_REG_LOCK (0x00)
1760: #define IFC_REG_UNLOCK (0x09)
1761: #define IFC_WR_EN_FILTER (0x10)
1762: #define IFC_RD_NO_EEPROM (0x10)
1763: #define IFC_SLEW_RATE (0x20)
1764: #define IFC_ACT_NEG (0x40)
1765: #define IFC_INP_FILTER (0x80)
1766: #define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
1767: #define SC_SEL (uchar)(0x80)
1768: #define SC_BSY (uchar)(0x40)
1769: #define SC_ACK (uchar)(0x20)
1770: #define SC_REQ (uchar)(0x10)
1771: #define SC_ATN (uchar)(0x08)
1772: #define SC_IO (uchar)(0x04)
1773: #define SC_CD (uchar)(0x02)
1774: #define SC_MSG (uchar)(0x01)
1775: #define SEC_SCSI_CTL (uchar)(0x80)
1776: #define SEC_ACTIVE_NEGATE (uchar)(0x40)
1777: #define SEC_SLEW_RATE (uchar)(0x20)
1778: #define SEC_ENABLE_FILTER (uchar)(0x10)
1779: #define ASC_HALT_EXTMSG_IN (ushort)0x8000
1780: #define ASC_HALT_CHK_CONDITION (ushort)0x8100
1781: #define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
1782: #define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
1783: #define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
1784: #define ASC_HALT_SDTR_REJECTED (ushort)0x4000
1785: #define ASC_MAX_QNO 0xF8
1786: #define ASC_DATA_SEC_BEG (ushort)0x0080
1787: #define ASC_DATA_SEC_END (ushort)0x0080
1788: #define ASC_CODE_SEC_BEG (ushort)0x0080
1789: #define ASC_CODE_SEC_END (ushort)0x0080
1790: #define ASC_QADR_BEG (0x4000)
1791: #define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
1792: #define ASC_QADR_END (ushort)0x7FFF
1793: #define ASC_QLAST_ADR (ushort)0x7FC0
1794: #define ASC_QBLK_SIZE 0x40
1795: #define ASC_BIOS_DATA_QBEG 0xF8
1796: #define ASC_MIN_ACTIVE_QNO 0x01
1797: #define ASC_QLINK_END 0xFF
1798: #define ASC_EEPROM_WORDS 0x10
1799: #define ASC_MAX_MGS_LEN 0x10
1800: #define ASC_BIOS_ADDR_DEF 0xDC00
1801: #define ASC_BIOS_SIZE 0x3800
1802: #define ASC_BIOS_RAM_OFF 0x3800
1803: #define ASC_BIOS_RAM_SIZE 0x800
1804: #define ASC_BIOS_MIN_ADDR 0xC000
1805: #define ASC_BIOS_MAX_ADDR 0xEC00
1806: #define ASC_BIOS_BANK_SIZE 0x0400
1807: #define ASC_MCODE_START_ADDR 0x0080
1808: #define ASC_CFG0_HOST_INT_ON 0x0020
1809: #define ASC_CFG0_BIOS_ON 0x0040
1810: #define ASC_CFG0_VERA_BURST_ON 0x0080
1811: #define ASC_CFG0_SCSI_PARITY_ON 0x0800
1812: #define ASC_CFG1_SCSI_TARGET_ON 0x0080
1813: #define ASC_CFG1_LRAM_8BITS_ON 0x0800
1814: #define ASC_CFG_MSW_CLR_MASK 0x3080
1815: #define CSW_TEST1 (ASC_CS_TYPE)0x8000
1816: #define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
1817: #define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
1818: #define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
1819: #define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
1820: #define CSW_TEST2 (ASC_CS_TYPE)0x0400
1821: #define CSW_TEST3 (ASC_CS_TYPE)0x0200
1822: #define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
1823: #define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
1824: #define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
1825: #define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
1826: #define CSW_HALTED (ASC_CS_TYPE)0x0010
1827: #define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
1828: #define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
1829: #define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
1830: #define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
1831: #define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
1832: #define CIW_INT_ACK (ASC_CS_TYPE)0x0100
1833: #define CIW_TEST1 (ASC_CS_TYPE)0x0200
1834: #define CIW_TEST2 (ASC_CS_TYPE)0x0400
1835: #define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
1836: #define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
1837: #define CC_CHIP_RESET (uchar)0x80
1838: #define CC_SCSI_RESET (uchar)0x40
1839: #define CC_HALT (uchar)0x20
1840: #define CC_SINGLE_STEP (uchar)0x10
1841: #define CC_DMA_ABLE (uchar)0x08
1842: #define CC_TEST (uchar)0x04
1843: #define CC_BANK_ONE (uchar)0x02
1844: #define CC_DIAG (uchar)0x01
1845: #define ASC_1000_ID0W 0x04C1
1846: #define ASC_1000_ID0W_FIX 0x00C1
1847: #define ASC_1000_ID1B 0x25
1848: #define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50)
1849: #define ASC_EISA_SMALL_IOP_GAP (0x0020)
1850: #define ASC_EISA_MIN_IOP_ADDR (0x0C30)
1851: #define ASC_EISA_MAX_IOP_ADDR (0xFC50)
1852: #define ASC_EISA_REV_IOP_MASK (0x0C83)
1853: #define ASC_EISA_PID_IOP_MASK (0x0C80)
1854: #define ASC_EISA_CFG_IOP_MASK (0x0C86)
1855: #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
1856: #define ASC_EISA_ID_740 0x01745004UL
1857: #define ASC_EISA_ID_750 0x01755004UL
1858: #define INS_HALTINT (ushort)0x6281
1859: #define INS_HALT (ushort)0x6280
1860: #define INS_SINT (ushort)0x6200
1861: #define INS_RFLAG_WTM (ushort)0x7380
1862: #define ASC_MC_SAVE_CODE_WSIZE 0x500
1863: #define ASC_MC_SAVE_DATA_WSIZE 0x40
1864:
1865: typedef struct asc_mc_saved {
1866: ushort data[ASC_MC_SAVE_DATA_WSIZE];
1867: ushort code[ASC_MC_SAVE_CODE_WSIZE];
1868: } ASC_MC_SAVED;
1869:
1870: #define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
1871: #define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
1872: #define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
1873: #define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
1874: #define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
1875: #define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
1876: #define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
1877: #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
1878: #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
1879: #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
1880: #define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)) ;
1881: #define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)) ;
1882: #define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data) ;
1883: #define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)) ;
1884: #define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1885: #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1886: #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1887: #define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1888: #define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1889: #define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1890: #define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1891: #define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1892: #define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1893: #define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1894: #define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1895: #define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1896: #define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1897: #define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1898: #define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1899: #define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1900: #define AscGetChipLramDataNoSwap(port) (ushort)inpw_noswap((port)+IOP_RAM_DATA)
1901: #define AscSetChipLramDataNoSwap(port, data) outpw_noswap((port)+IOP_RAM_DATA, data)
1902: #define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1903: #define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1904: #define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1905: #define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1906: #define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1907: #define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1908: #define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1909: #define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1910: #define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1911: #define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1912: #define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1913: #define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1914: #define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1915: #define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1916: #define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1917: #define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1918: #define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1919: #define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1920: #define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1921: #define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1922: #define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1923: #define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1924: #define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1925: #define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1926: #define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1927: #define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1928: #define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1929: #define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1930: #define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1931: #define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1932: #define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1933: #define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1934: #define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1935: #define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1936: #define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1937: #define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1938: #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1939: #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1940:
1941: STATIC int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1942: STATIC int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1943: STATIC void AscWaitEEPRead(void);
1944: STATIC void AscWaitEEPWrite(void);
1945: STATIC ushort AscReadEEPWord(PortAddr, uchar);
1946: STATIC ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1947: STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1948: STATIC int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1949: STATIC int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1950: STATIC int AscStartChip(PortAddr);
1951: STATIC int AscStopChip(PortAddr);
1952: STATIC void AscSetChipIH(PortAddr, ushort);
1953: STATIC int AscIsChipHalted(PortAddr);
1954: STATIC void AscAckInterrupt(PortAddr);
1955: STATIC void AscDisableInterrupt(PortAddr);
1956: STATIC void AscEnableInterrupt(PortAddr);
1957: STATIC void AscSetBank(PortAddr, uchar);
1958: STATIC int AscResetChipAndScsiBus(ASC_DVC_VAR *);
1959: STATIC ushort AscGetIsaDmaChannel(PortAddr);
1960: STATIC ushort AscSetIsaDmaChannel(PortAddr, ushort);
1961: STATIC uchar AscSetIsaDmaSpeed(PortAddr, uchar);
1962: STATIC uchar AscGetIsaDmaSpeed(PortAddr);
1963: STATIC uchar AscReadLramByte(PortAddr, ushort);
1964: STATIC ushort AscReadLramWord(PortAddr, ushort);
1965: STATIC ulong AscReadLramDWord(PortAddr, ushort);
1966: STATIC void AscWriteLramWord(PortAddr, ushort, ushort);
1967: STATIC void AscWriteLramDWord(PortAddr, ushort, ulong);
1968: STATIC void AscWriteLramByte(PortAddr, ushort, uchar);
1969: STATIC ulong AscMemSumLramWord(PortAddr, ushort, rint);
1970: STATIC void AscMemWordSetLram(PortAddr, ushort, ushort, rint);
1971: STATIC void AscMemWordCopyToLram(PortAddr, ushort, ushort *, int);
1972: STATIC void AscMemDWordCopyToLram(PortAddr, ushort, ulong *, int);
1973: STATIC void AscMemWordCopyFromLram(PortAddr, ushort, ushort *, int);
1974: STATIC ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1975: STATIC ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
1976: STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1977: STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
1978: STATIC int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
1979: STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
1980: STATIC uchar AscCalSDTRData(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
1981: STATIC void AscSetChipSDTR(PortAddr, uchar, uchar);
1982: STATIC uchar AscGetSynPeriodIndex(ASC_DVC_VAR asc_ptr_type *, ruchar);
1983: STATIC uchar AscAllocFreeQueue(PortAddr, uchar);
1984: STATIC uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1985: STATIC int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
1986: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
1987: STATIC int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
1988: #endif /* version >= v1.3.89 */
1989: STATIC int AscHostReqRiscHalt(PortAddr);
1990: STATIC int AscStopQueueExe(PortAddr);
1991: STATIC int AscStartQueueExe(PortAddr);
1992: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
1993: STATIC int AscCleanUpDiscQueue(PortAddr);
1994: #endif /* version >= v1.3.89 */
1995: STATIC int AscCleanUpBusyQueue(PortAddr);
1996: STATIC int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
1997: STATIC int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
1998: STATIC ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar *,
1999: ulong);
2000: STATIC int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
2001: ASC_SCSI_Q * scsiq,
2002: uchar n_q_required);
2003: STATIC int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *,
2004: ASC_SCSI_Q *, uchar);
2005: STATIC int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
2006: ASC_SCSI_Q *, uchar);
2007: STATIC int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
2008: STATIC int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
2009: STATIC ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *);
2010: STATIC int AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
2011: STATIC ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
2012: STATIC int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
2013: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2014: STATIC int _AscWaitQDone(PortAddr, ASC_SCSI_Q *);
2015: #endif /* version >= v1.3.89 */
2016: STATIC int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
2017: STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
2018: ASC_QDONE_INFO *, ulong);
2019: STATIC int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
2020: STATIC int AscCompareString(uchar *, uchar *, int);
2021: STATIC ushort AscGetEisaChipCfg(PortAddr);
2022: STATIC ulong AscGetEisaProductID(PortAddr);
2023: STATIC PortAddr AscSearchIOPortAddrEISA(PortAddr);
2024: STATIC uchar AscGetChipScsiCtrl(PortAddr);
2025: STATIC uchar AscSetChipScsiID(PortAddr, uchar);
2026: STATIC uchar AscGetChipVersion(PortAddr, ushort);
2027: STATIC ushort AscGetChipBusType(PortAddr);
2028: STATIC ulong AscLoadMicroCode(PortAddr, ushort, ushort *, ushort);
2029: STATIC int AscFindSignature(PortAddr);
2030: STATIC PortAddr AscSearchIOPortAddr11(PortAddr);
2031: STATIC void AscToggleIRQAct(PortAddr);
2032: STATIC void AscSetISAPNPWaitForKey(void);
2033: STATIC uchar AscGetChipIRQ(PortAddr, ushort);
2034: STATIC uchar AscSetChipIRQ(PortAddr, uchar, ushort);
2035: STATIC ushort AscGetChipBiosAddress(PortAddr, ushort);
2036: STATIC int DvcEnterCritical(void);
2037: STATIC void DvcLeaveCritical(int);
2038: STATIC void DvcInPortWords(PortAddr, ushort *, int);
2039: STATIC void DvcOutPortWords(PortAddr, ushort *, int);
2040: STATIC void DvcOutPortDWords(PortAddr, ulong *, int);
2041: STATIC uchar DvcReadPCIConfigByte(ASC_DVC_VAR asc_ptr_type *, ushort);
2042: STATIC void DvcWritePCIConfigByte(ASC_DVC_VAR asc_ptr_type *,
2043: ushort, uchar);
2044: STATIC ushort AscGetChipBiosAddress(PortAddr, ushort);
2045: STATIC void DvcSleepMilliSecond(ulong);
2046: STATIC void DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type *, ulong);
2047: STATIC ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar *,
2048: ulong, ASC_SG_HEAD *);
2049: STATIC void DvcPutScsiQ(PortAddr, ushort, ushort *, int);
2050: STATIC void DvcGetQinfo(PortAddr, ushort, ushort *, int);
2051: STATIC PortAddr AscSearchIOPortAddr(PortAddr, ushort);
2052: STATIC ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
2053: STATIC ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
2054: STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
2055: STATIC void AscAsyncFix(ASC_DVC_VAR asc_ptr_type *, uchar,
2056: ASC_SCSI_INQUIRY *);
2057: STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
2058: STATIC void AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *,
2059: uchar, ASC_SCSI_INQUIRY *);
2060: STATIC int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
2061: STATIC int AscISR(ASC_DVC_VAR asc_ptr_type *);
2062: STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar,
2063: uchar);
2064: STATIC int AscSgListToQueue(int);
2065: STATIC int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
2066: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
2067: STATIC int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
2068: #endif /* version >= v1.3.89 */
2069: STATIC int AscResetSB(ASC_DVC_VAR asc_ptr_type *);
2070: STATIC void AscEnableIsaDma(uchar);
2071: STATIC ulong AscGetMaxDmaCount(ushort);
2072:
2073:
2074: /*
2075: * --- Adv Library Constants and Macros
2076: */
2077:
2078: #define ADV_LIB_VERSION_MAJOR 3
2079: #define ADV_LIB_VERSION_MINOR 45
2080:
2081: /* d_os_dep.h */
2082: #define ADV_OS_LINUX
2083:
2084: /*
2085: * Define Adv Library required special types.
2086: */
2087: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
2088: #define AdvPortAddr unsigned short /* I/O Port address size */
2089: #else /* version >= v1,3,0 */
2090: #define AdvPortAddr unsigned long /* Virtual memory address size */
2091: #endif /* version >= v1,3,0 */
2092:
2093: /*
2094: * Define Adv Library required memory access macros.
2095: */
2096: #define ADV_MEM_READB(addr) readb(addr)
2097: #define ADV_MEM_READW(addr) readw(addr)
2098: #define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
2099: #define ADV_MEM_WRITEW(addr, word) writew(word, addr)
2100:
2101: /*
2102: * The I/O memory mapping function names changed in 2.1.X.
2103: */
2104: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
2105: #define ioremap vremap
2106: #define iounmap vfree
2107: #endif /* version < v2.1.0 */
2108:
2109: /*
2110: * Define total number of simultaneous maximum element scatter-gather
2111: * requests, i.e. ADV_TOT_SG_LIST * ADV_MAX_SG_LIST is the total number
2112: * of simultaneous scatter-gather elements supported per wide adapter.
2113: */
2114: #define ADV_TOT_SG_LIST 64
2115:
2116: /*
2117: * Define Adv Library required per request scatter-gather element limit.
2118: */
2119: #define ADV_MAX_SG_LIST 64
2120:
2121: /*
2122: * Scatter-Gather Definitions per request.
2123: *
2124: * Because SG block memory is allocated in virtual memory but is
2125: * referenced by the microcode as physical memory, we need to do
2126: * calculations to insure there will be enough physically contiguous
2127: * memory to support ADV_MAX_SG_LIST SG entries.
2128: */
2129:
2130: /* Number of SG blocks needed. */
2131: #define ADV_NUM_SG_BLOCK \
2132: ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
2133:
2134: /* Total contiguous memory needed for SG blocks. */
2135: #define ADV_SG_TOTAL_MEM_SIZE \
2136: (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
2137:
2138: #define ASC_PAGE_SIZE PAGE_SIZE
2139:
2140: /*
2141: * Number of page crossings possible for the total contiguous virtual memory
2142: * needed for SG blocks.
2143: *
2144: * We need to allocate this many additional SG blocks in virtual memory to
2145: * insure there will be space for ADV_NUM_SG_BLOCK physically contiguous
2146: * scatter-gather blocks.
2147: */
2148: #define ADV_NUM_PAGE_CROSSING \
2149: ((ADV_SG_TOTAL_MEM_SIZE + (ASC_PAGE_SIZE - 1))/ASC_PAGE_SIZE)
2150:
2151: /*
2152: * Define Adv Library Assertion Macro.
2153: */
2154:
2155: #define ADV_ASSERT(a) ASC_ASSERT(a)
2156:
2157: /* a_condor.h */
2158: #define ADV_PCI_VENDOR_ID 0x10CD
2159: #define ADV_PCI_DEVICE_ID_REV_A 0x2300
2160:
2161: #define ASC_EEP_DVC_CFG_BEGIN (0x00)
2162: #define ASC_EEP_DVC_CFG_END (0x15)
2163: #define ASC_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
2164: #define ASC_EEP_MAX_WORD_ADDR (0x1E)
2165:
2166: #define ASC_EEP_DELAY_MS 100
2167:
2168: /*
2169: * EEPROM bits reference by the RISC after initialization.
2170: */
2171: #define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
2172: #define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
2173: #define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
2174:
2175: /*
2176: * EEPROM configuration format
2177: *
2178: * Field naming convention:
2179: *
2180: * *_enable indicates the field enables or disables the feature. The
2181: * value is never reset.
2182: *
2183: * *_able indicates both whether a feature should be enabled or disabled
2184: * and whether a device isi capable of the feature. At initialization
2185: * this field may be set, but later if a device is found to be incapable
2186: * of the feature, the field is cleared.
2187: *
2188: * Default values are maintained in a_init.c in the structure
2189: * Default_EEPROM_Config.
2190: */
2191: typedef struct adveep_config
2192: {
2193: /* Word Offset, Description */
2194:
2195: ushort cfg_lsw; /* 00 power up initialization */
2196: /* bit 13 set - Term Polarity Control */
2197: /* bit 14 set - BIOS Enable */
2198: /* bit 15 set - Big Endian Mode */
2199: ushort cfg_msw; /* 01 unused */
2200: ushort disc_enable; /* 02 disconnect enable */
2201: ushort wdtr_able; /* 03 Wide DTR able */
2202: ushort sdtr_able; /* 04 Synchronous DTR able */
2203: ushort start_motor; /* 05 send start up motor */
2204: ushort tagqng_able; /* 06 tag queuing able */
2205: ushort bios_scan; /* 07 BIOS device control */
2206: ushort scam_tolerant; /* 08 no scam */
2207:
2208: uchar adapter_scsi_id; /* 09 Host Adapter ID */
2209: uchar bios_boot_delay; /* power up wait */
2210:
2211: uchar scsi_reset_delay; /* 10 reset delay */
2212: uchar bios_id_lun; /* first boot device scsi id & lun */
2213: /* high nibble is lun */
2214: /* low nibble is scsi id */
2215:
2216: uchar termination; /* 11 0 - automatic */
2217: /* 1 - low off / high off */
2218: /* 2 - low off / high on */
2219: /* 3 - low on / high on */
2220: /* There is no low on / high off */
2221:
2222: uchar reserved1; /* reserved byte (not used) */
2223:
2224: ushort bios_ctrl; /* 12 BIOS control bits */
2225: /* bit 0 set: BIOS don't act as initiator. */
2226: /* bit 1 set: BIOS > 1 GB support */
2227: /* bit 2 set: BIOS > 2 Disk Support */
2228: /* bit 3 set: BIOS don't support removables */
2229: /* bit 4 set: BIOS support bootable CD */
2230: /* bit 5 set: */
2231: /* bit 6 set: BIOS support multiple LUNs */
2232: /* bit 7 set: BIOS display of message */
2233: /* bit 8 set: */
2234: /* bit 9 set: Reset SCSI bus during init. */
2235: /* bit 10 set: */
2236: /* bit 11 set: No verbose initialization. */
2237: /* bit 12 set: SCSI parity enabled */
2238: /* bit 13 set: */
2239: /* bit 14 set: */
2240: /* bit 15 set: */
2241: ushort ultra_able; /* 13 ULTRA speed able */
2242: ushort reserved2; /* 14 reserved */
2243: uchar max_host_qng; /* 15 maximum host queuing */
2244: uchar max_dvc_qng; /* maximum per device queuing */
2245: ushort dvc_cntl; /* 16 control bit for driver */
2246: ushort bug_fix; /* 17 control bit for bug fix */
2247: ushort serial_number_word1; /* 18 Board serial number word 1 */
2248: ushort serial_number_word2; /* 19 Board serial number word 2 */
2249: ushort serial_number_word3; /* 20 Board serial number word 3 */
2250: ushort check_sum; /* 21 EEP check sum */
2251: uchar oem_name[16]; /* 22 OEM name */
2252: ushort dvc_err_code; /* 30 last device driver error code */
2253: ushort adv_err_code; /* 31 last uc and Adv Lib error code */
2254: ushort adv_err_addr; /* 32 last uc error address */
2255: ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
2256: ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
2257: ushort saved_adv_err_addr; /* 35 saved last uc error address */
2258: ushort num_of_err; /* 36 number of error */
2259: } ADVEEP_CONFIG;
2260:
2261: /*
2262: * EEPROM Commands
2263: */
2264: #define ASC_EEP_CMD_DONE 0x0200
2265: #define ASC_EEP_CMD_DONE_ERR 0x0001
2266:
2267: /* cfg_word */
2268: #define EEP_CFG_WORD_BIG_ENDIAN 0x8000
2269:
2270: /* bios_ctrl */
2271: #define BIOS_CTRL_BIOS 0x0001
2272: #define BIOS_CTRL_EXTENDED_XLAT 0x0002
2273: #define BIOS_CTRL_GT_2_DISK 0x0004
2274: #define BIOS_CTRL_BIOS_REMOVABLE 0x0008
2275: #define BIOS_CTRL_BOOTABLE_CD 0x0010
2276: #define BIOS_CTRL_MULTIPLE_LUN 0x0040
2277: #define BIOS_CTRL_DISPLAY_MSG 0x0080
2278: #define BIOS_CTRL_NO_SCAM 0x0100
2279: #define BIOS_CTRL_RESET_SCSI_BUS 0x0200
2280: #define BIOS_CTRL_INIT_VERBOSE 0x0800
2281: #define BIOS_CTRL_SCSI_PARITY 0x1000
2282:
2283: /*
2284: * ASC 3550 Internal Memory Size - 8KB
2285: */
2286: #define ADV_CONDOR_MEMSIZE 0x2000 /* 8 KB Internal Memory */
2287:
2288: /*
2289: * ASC 3550 I/O Length - 64 bytes
2290: */
2291: #define ADV_CONDOR_IOLEN 0x40 /* I/O Port Range in bytes */
2292:
2293: /*
2294: * Byte I/O register address from base of 'iop_base'.
2295: */
2296: #define IOPB_INTR_STATUS_REG 0x00
2297: #define IOPB_CHIP_ID_1 0x01
2298: #define IOPB_INTR_ENABLES 0x02
2299: #define IOPB_CHIP_TYPE_REV 0x03
2300: #define IOPB_RES_ADDR_4 0x04
2301: #define IOPB_RES_ADDR_5 0x05
2302: #define IOPB_RAM_DATA 0x06
2303: #define IOPB_RES_ADDR_7 0x07
2304: #define IOPB_FLAG_REG 0x08
2305: #define IOPB_RES_ADDR_9 0x09
2306: #define IOPB_RISC_CSR 0x0A
2307: #define IOPB_RES_ADDR_B 0x0B
2308: #define IOPB_RES_ADDR_C 0x0C
2309: #define IOPB_RES_ADDR_D 0x0D
2310: #define IOPB_RES_ADDR_E 0x0E
2311: #define IOPB_RES_ADDR_F 0x0F
2312: #define IOPB_MEM_CFG 0x10
2313: #define IOPB_RES_ADDR_11 0x11
2314: #define IOPB_RES_ADDR_12 0x12
2315: #define IOPB_RES_ADDR_13 0x13
2316: #define IOPB_FLASH_PAGE 0x14
2317: #define IOPB_RES_ADDR_15 0x15
2318: #define IOPB_RES_ADDR_16 0x16
2319: #define IOPB_RES_ADDR_17 0x17
2320: #define IOPB_FLASH_DATA 0x18
2321: #define IOPB_RES_ADDR_19 0x19
2322: #define IOPB_RES_ADDR_1A 0x1A
2323: #define IOPB_RES_ADDR_1B 0x1B
2324: #define IOPB_RES_ADDR_1C 0x1C
2325: #define IOPB_RES_ADDR_1D 0x1D
2326: #define IOPB_RES_ADDR_1E 0x1E
2327: #define IOPB_RES_ADDR_1F 0x1F
2328: #define IOPB_DMA_CFG0 0x20
2329: #define IOPB_DMA_CFG1 0x21
2330: #define IOPB_TICKLE 0x22
2331: #define IOPB_DMA_REG_WR 0x23
2332: #define IOPB_SDMA_STATUS 0x24
2333: #define IOPB_SCSI_BYTE_CNT 0x25
2334: #define IOPB_HOST_BYTE_CNT 0x26
2335: #define IOPB_BYTE_LEFT_TO_XFER 0x27
2336: #define IOPB_BYTE_TO_XFER_0 0x28
2337: #define IOPB_BYTE_TO_XFER_1 0x29
2338: #define IOPB_BYTE_TO_XFER_2 0x2A
2339: #define IOPB_BYTE_TO_XFER_3 0x2B
2340: #define IOPB_ACC_GRP 0x2C
2341: #define IOPB_RES_ADDR_2D 0x2D
2342: #define IOPB_DEV_ID 0x2E
2343: #define IOPB_RES_ADDR_2F 0x2F
2344: #define IOPB_SCSI_DATA 0x30
2345: #define IOPB_RES_ADDR_31 0x31
2346: #define IOPB_RES_ADDR_32 0x32
2347: #define IOPB_SCSI_DATA_HSHK 0x33
2348: #define IOPB_SCSI_CTRL 0x34
2349: #define IOPB_RES_ADDR_35 0x35
2350: #define IOPB_RES_ADDR_36 0x36
2351: #define IOPB_RES_ADDR_37 0x37
2352: #define IOPB_RES_ADDR_38 0x38
2353: #define IOPB_RES_ADDR_39 0x39
2354: #define IOPB_RES_ADDR_3A 0x3A
2355: #define IOPB_RES_ADDR_3B 0x3B
2356: #define IOPB_RFIFO_CNT 0x3C
2357: #define IOPB_RES_ADDR_3D 0x3D
2358: #define IOPB_RES_ADDR_3E 0x3E
2359: #define IOPB_RES_ADDR_3F 0x3F
2360:
2361: /*
2362: * Word I/O register address from base of 'iop_base'.
2363: */
2364: #define IOPW_CHIP_ID_0 0x00 /* CID0 */
2365: #define IOPW_CTRL_REG 0x02 /* CC */
2366: #define IOPW_RAM_ADDR 0x04 /* LA */
2367: #define IOPW_RAM_DATA 0x06 /* LD */
2368: #define IOPW_RES_ADDR_08 0x08
2369: #define IOPW_RISC_CSR 0x0A /* CSR */
2370: #define IOPW_SCSI_CFG0 0x0C /* CFG0 */
2371: #define IOPW_SCSI_CFG1 0x0E /* CFG1 */
2372: #define IOPW_RES_ADDR_10 0x10
2373: #define IOPW_SEL_MASK 0x12 /* SM */
2374: #define IOPW_RES_ADDR_14 0x14
2375: #define IOPW_FLASH_ADDR 0x16 /* FA */
2376: #define IOPW_RES_ADDR_18 0x18
2377: #define IOPW_EE_CMD 0x1A /* EC */
2378: #define IOPW_EE_DATA 0x1C /* ED */
2379: #define IOPW_SFIFO_CNT 0x1E /* SFC */
2380: #define IOPW_RES_ADDR_20 0x20
2381: #define IOPW_Q_BASE 0x22 /* QB */
2382: #define IOPW_QP 0x24 /* QP */
2383: #define IOPW_IX 0x26 /* IX */
2384: #define IOPW_SP 0x28 /* SP */
2385: #define IOPW_PC 0x2A /* PC */
2386: #define IOPW_RES_ADDR_2C 0x2C
2387: #define IOPW_RES_ADDR_2E 0x2E
2388: #define IOPW_SCSI_DATA 0x30 /* SD */
2389: #define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
2390: #define IOPW_SCSI_CTRL 0x34 /* SC */
2391: #define IOPW_HSHK_CFG 0x36 /* HCFG */
2392: #define IOPW_SXFR_STATUS 0x36 /* SXS */
2393: #define IOPW_SXFR_CNTL 0x38 /* SXL */
2394: #define IOPW_SXFR_CNTH 0x3A /* SXH */
2395: #define IOPW_RES_ADDR_3C 0x3C
2396: #define IOPW_RFIFO_DATA 0x3E /* RFD */
2397:
2398: /*
2399: * Doubleword I/O register address from base of 'iop_base'.
2400: */
2401: #define IOPDW_RES_ADDR_0 0x00
2402: #define IOPDW_RAM_DATA 0x04
2403: #define IOPDW_RES_ADDR_8 0x08
2404: #define IOPDW_RES_ADDR_C 0x0C
2405: #define IOPDW_RES_ADDR_10 0x10
2406: #define IOPDW_RES_ADDR_14 0x14
2407: #define IOPDW_RES_ADDR_18 0x18
2408: #define IOPDW_RES_ADDR_1C 0x1C
2409: #define IOPDW_SDMA_ADDR0 0x20
2410: #define IOPDW_SDMA_ADDR1 0x24
2411: #define IOPDW_SDMA_COUNT 0x28
2412: #define IOPDW_SDMA_ERROR 0x2C
2413: #define IOPDW_RDMA_ADDR0 0x30
2414: #define IOPDW_RDMA_ADDR1 0x34
2415: #define IOPDW_RDMA_COUNT 0x38
2416: #define IOPDW_RDMA_ERROR 0x3C
2417:
2418: #define ADV_CHIP_ID_BYTE 0x25
2419: #define ADV_CHIP_ID_WORD 0x04C1
2420:
2421: #define ADV_SC_SCSI_BUS_RESET 0x2000
2422:
2423: #define ADV_INTR_ENABLE_HOST_INTR 0x01
2424: #define ADV_INTR_ENABLE_SEL_INTR 0x02
2425: #define ADV_INTR_ENABLE_DPR_INTR 0x04
2426: #define ADV_INTR_ENABLE_RTA_INTR 0x08
2427: #define ADV_INTR_ENABLE_RMA_INTR 0x10
2428: #define ADV_INTR_ENABLE_RST_INTR 0x20
2429: #define ADV_INTR_ENABLE_DPE_INTR 0x40
2430: #define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
2431:
2432: #define ADV_INTR_STATUS_INTRA 0x01
2433: #define ADV_INTR_STATUS_INTRB 0x02
2434: #define ADV_INTR_STATUS_INTRC 0x04
2435:
2436: #define ADV_RISC_CSR_STOP (0x0000)
2437: #define ADV_RISC_TEST_COND (0x2000)
2438: #define ADV_RISC_CSR_RUN (0x4000)
2439: #define ADV_RISC_CSR_SINGLE_STEP (0x8000)
2440:
2441: #define ADV_CTRL_REG_HOST_INTR 0x0100
2442: #define ADV_CTRL_REG_SEL_INTR 0x0200
2443: #define ADV_CTRL_REG_DPR_INTR 0x0400
2444: #define ADV_CTRL_REG_RTA_INTR 0x0800
2445: #define ADV_CTRL_REG_RMA_INTR 0x1000
2446: #define ADV_CTRL_REG_RES_BIT14 0x2000
2447: #define ADV_CTRL_REG_DPE_INTR 0x4000
2448: #define ADV_CTRL_REG_POWER_DONE 0x8000
2449: #define ADV_CTRL_REG_ANY_INTR 0xFF00
2450:
2451: #define ADV_CTRL_REG_CMD_RESET 0x00C6
2452: #define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
2453: #define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
2454: #define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
2455: #define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
2456:
2457: #define ADV_SCSI_CTRL_RSTOUT 0x2000
2458:
2459: #define AdvIsIntPending(port) \
2460: (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
2461:
2462: /*
2463: * SCSI_CFG0 Register bit definitions
2464: */
2465: #define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
2466: #define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
2467: #define EVEN_PARITY 0x1000 /* Select Even Parity */
2468: #define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
2469: #define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
2470: #define PRIM_MODE 0x0100 /* Primitive SCSI mode */
2471: #define SCAM_EN 0x0080 /* Enable SCAM selection */
2472: #define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
2473: #define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
2474: #define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
2475: #define OUR_ID 0x000F /* SCSI ID */
2476:
2477: /*
2478: * SCSI_CFG1 Register bit definitions
2479: */
2480: #define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
2481: #define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
2482: #define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
2483: #define FILTER_SEL 0x0C00 /* Filter Period Selection */
2484: #define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
2485: #define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
2486: #define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
2487: #define ACTIVE_DBL 0x0200 /* Disable Active Negation */
2488: #define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
2489: #define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
2490: #define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
2491: #define TERM_CTL 0x0030 /* External SCSI Termination Bits */
2492: #define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
2493: #define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
2494: #define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
2495:
2496: #define CABLE_ILLEGAL_A 0x7
2497: /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
2498:
2499: #define CABLE_ILLEGAL_B 0xB
2500: /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
2501:
2502: /*
2503: The following table details the SCSI_CFG1 Termination Polarity,
2504: Termination Control and Cable Detect bits.
2505:
2506: Cable Detect | Termination
2507: Bit 3 2 1 0 | 5 4 | Notes
2508: _____________|________|____________________
2509: 1 1 1 0 | on on | Internal wide only
2510: 1 1 0 1 | on on | Internal narrow only
2511: 1 0 1 1 | on on | External narrow only
2512: 0 x 1 1 | on on | External wide only
2513: 1 1 0 0 | on off| Internal wide and internal narrow
2514: 1 0 1 0 | on off| Internal wide and external narrow
2515: 0 x 1 0 | off off| Internal wide and external wide
2516: 1 0 0 1 | on off| Internal narrow and external narrow
2517: 0 x 0 1 | on off| Internal narrow and external wide
2518: 1 1 1 1 | on on | No devices are attached
2519: x 0 0 0 | on on | Illegal (all 3 connectors are used)
2520: 0 x 0 0 | on on | Illegal (all 3 connectors are used)
2521:
2522: x means don't-care (either '0' or '1')
2523:
2524: If term_pol (bit 13) is '0' (active-low terminator enable), then:
2525: 'on' is '0' and 'off' is '1'.
2526:
2527: If term_pol bit is '1' (meaning active-hi terminator enable), then:
2528: 'on' is '1' and 'off' is '0'.
2529: */
2530:
2531: /*
2532: * MEM_CFG Register bit definitions
2533: */
2534: #define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
2535: #define FAST_EE_CLK 0x20 /* Diagnostic Bit */
2536: #define RAM_SZ 0x1C /* Specify size of RAM to RISC */
2537: #define RAM_SZ_2KB 0x00 /* 2 KB */
2538: #define RAM_SZ_4KB 0x04 /* 4 KB */
2539: #define RAM_SZ_8KB 0x08 /* 8 KB */
2540: #define RAM_SZ_16KB 0x0C /* 16 KB */
2541: #define RAM_SZ_32KB 0x10 /* 32 KB */
2542: #define RAM_SZ_64KB 0x14 /* 64 KB */
2543:
2544: /*
2545: * DMA_CFG0 Register bit definitions
2546: *
2547: * This register is only accessible to the host.
2548: */
2549: #define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
2550: #define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
2551: #define FIFO_THRESH_16B 0x00 /* 16 bytes */
2552: #define FIFO_THRESH_32B 0x20 /* 32 bytes */
2553: #define FIFO_THRESH_48B 0x30 /* 48 bytes */
2554: #define FIFO_THRESH_64B 0x40 /* 64 bytes */
2555: #define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
2556: #define FIFO_THRESH_96B 0x60 /* 96 bytes */
2557: #define FIFO_THRESH_112B 0x70 /* 112 bytes */
2558: #define START_CTL 0x0C /* DMA start conditions */
2559: #define START_CTL_TH 0x00 /* Wait threshold level (default) */
2560: #define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
2561: #define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
2562: #define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
2563: #define READ_CMD 0x03 /* Memory Read Method */
2564: #define READ_CMD_MR 0x00 /* Memory Read */
2565: #define READ_CMD_MRL 0x02 /* Memory Read Long */
2566: #define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
2567:
2568: /* a_advlib.h */
2569:
2570: /*
2571: * Adv Library Status Definitions
2572: */
2573: #define ADV_TRUE 1
2574: #define ADV_FALSE 0
2575: #define ADV_NOERROR 1
2576: #define ADV_SUCCESS 1
2577: #define ADV_BUSY 0
2578: #define ADV_ERROR (-1)
2579:
2580:
2581: /*
2582: * ASC_DVC_VAR 'warn_code' values
2583: */
2584: #define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
2585: #define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
2586: #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
2587: #define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
2588:
2589: #define ADV_MAX_TID 15 /* max. target identifier */
2590: #define ADV_MAX_LUN 7 /* max. logical unit number */
2591:
2592:
2593: /*
2594: * AscInitGetConfig() and AscInitAsc1000Driver() Definitions
2595: *
2596: * Error code values are set in ASC_DVC_VAR 'err_code'.
2597: */
2598: #define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
2599: #define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
2600: #define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
2601: #define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
2602: #define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
2603: #define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
2604: #define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
2605: #define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
2606: #define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
2607: #define ASC_IERR_RW_LRAM 0x8000 /* read/write local RAM error */
2608:
2609: /*
2610: * Fixed locations of microcode operating variables.
2611: */
2612: #define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
2613: #define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
2614: #define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
2615: #define ASC_MC_STACK_BEGIN 0x002E /* microcode stack begin */
2616: #define ASC_MC_STACK_END 0x0030 /* microcode stack end */
2617: #define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
2618: #define ASC_MC_VERSION_NUM 0x003A /* microcode number */
2619: #define ASCV_VER_SERIAL_W 0x003C /* used in dos_init */
2620: #define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
2621: #define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
2622: #define ASC_MC_HALTCODE 0x0094 /* microcode halt code */
2623: #define ASC_MC_CALLERPC 0x0096 /* microcode halt caller PC */
2624: #define ASC_MC_ADAPTER_SCSI_ID 0x0098 /* one ID byte + reserved */
2625: #define ASC_MC_ULTRA_ABLE 0x009C
2626: #define ASC_MC_SDTR_ABLE 0x009E
2627: #define ASC_MC_TAGQNG_ABLE 0x00A0
2628: #define ASC_MC_DISC_ENABLE 0x00A2
2629: #define ASC_MC_IDLE_CMD 0x00A6
2630: #define ASC_MC_IDLE_PARA_STAT 0x00A8
2631: #define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
2632: #define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
2633: #define ASC_MC_DEFAULT_MEM_CFG 0x00B0
2634: #define ASC_MC_DEFAULT_SEL_MASK 0x00B2
2635: #define ASC_MC_RISC_NEXT_READY 0x00B4
2636: #define ASC_MC_RISC_NEXT_DONE 0x00B5
2637: #define ASC_MC_SDTR_DONE 0x00B6
2638: #define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
2639: #define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
2640: #define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
2641: #define ASC_MC_WDTR_ABLE 0x0120 /* Wide Transfer TID bitmask. */
2642: #define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
2643: #define ASC_MC_WDTR_DONE 0x0124
2644: #define ASC_MC_HOST_NEXT_READY 0x0128 /* Host Next Ready RQL Entry. */
2645: #define ASC_MC_HOST_NEXT_DONE 0x0129 /* Host Next Done RQL Entry. */
2646:
2647: /*
2648: * BIOS LRAM variable absolute offsets.
2649: */
2650: #define BIOS_CODESEG 0x54
2651: #define BIOS_CODELEN 0x56
2652: #define BIOS_SIGNATURE 0x58
2653: #define BIOS_VERSION 0x5A
2654: #define BIOS_SIGNATURE 0x58
2655:
2656: /*
2657: * Microcode Control Flags
2658: *
2659: * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
2660: * and handled by the microcode.
2661: */
2662: #define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
2663:
2664: /*
2665: * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
2666: */
2667: #define HSHK_CFG_WIDE_XFR 0x8000
2668: #define HSHK_CFG_RATE 0x0F00
2669: #define HSHK_CFG_OFFSET 0x001F
2670:
2671: /*
2672: * LRAM RISC Queue Lists (LRAM addresses 0x1200 - 0x19FF)
2673: *
2674: * Each of the 255 Adv Library/Microcode RISC queue lists or mailboxes
2675: * starting at LRAM address 0x1200 is 8 bytes and has the following
2676: * structure. Only 253 of these are actually used for command queues.
2677: */
2678:
2679: #define ASC_MC_RISC_Q_LIST_BASE 0x1200
2680: #define ASC_MC_RISC_Q_LIST_SIZE 0x0008
2681: #define ASC_MC_RISC_Q_TOTAL_CNT 0x00FF /* Num. queue slots in LRAM. */
2682: #define ASC_MC_RISC_Q_FIRST 0x0001
2683: #define ASC_MC_RISC_Q_LAST 0x00FF
2684:
2685: #define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
2686: #define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
2687: #define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
2688: #define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
2689:
2690: /* RISC Queue List structure - 8 bytes */
2691: #define RQL_FWD 0 /* forward pointer (1 byte) */
2692: #define RQL_BWD 1 /* backward pointer (1 byte) */
2693: #define RQL_STATE 2 /* state byte - free, ready, done, aborted (1 byte) */
2694: #define RQL_TID 3 /* request target id (1 byte) */
2695: #define RQL_PHYADDR 4 /* request physical pointer (4 bytes) */
2696:
2697: /* RISC Queue List state values */
2698: #define ASC_MC_QS_FREE 0x00
2699: #define ASC_MC_QS_READY 0x01
2700: #define ASC_MC_QS_DONE 0x40
2701: #define ASC_MC_QS_ABORTED 0x80
2702:
2703: /* RISC Queue List pointer values */
2704: #define ASC_MC_NULL_Q 0x00 /* NULL_Q == 0 */
2705: #define ASC_MC_BIOS_Q 0xFF /* BIOS_Q = 255 */
2706:
2707: /* ASC_SCSI_REQ_Q 'cntl' field values */
2708: #define ASC_MC_QC_START_MOTOR 0x02 /* Issue start motor. */
2709: #define ASC_MC_QC_NO_OVERRUN 0x04 /* Don't report overrun. */
2710: #define ASC_MC_QC_FIRST_DMA 0x08 /* Internal microcode flag. */
2711: #define ASC_MC_QC_ABORTED 0x10 /* Request aborted by host. */
2712: #define ASC_MC_QC_REQ_SENSE 0x20 /* Auto-Request Sense. */
2713: #define ASC_MC_QC_DOS_REQ 0x80 /* Request issued by DOS. */
2714:
2715:
2716: /*
2717: * ASC_SCSI_REQ_Q 'a_flag' definitions
2718: *
2719: * The Adv Library should limit use to the lower nibble (4 bits) of
2720: * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2721: */
2722: #define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2723: #define ADV_SCSIQ_DONE 0x02 /* request done */
2724:
2725: /*
2726: * Adapter temporary configuration structure
2727: *
2728: * This structure can be discarded after initialization. Don't add
2729: * fields here needed after initialization.
2730: *
2731: * Field naming convention:
2732: *
2733: * *_enable indicates the field enables or disables a feature. The
2734: * value of the field is never reset.
2735: */
2736: typedef struct adv_dvc_cfg {
2737: ushort disc_enable; /* enable disconnection */
2738: uchar chip_version; /* chip version */
2739: uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2740: ushort pci_device_id; /* PCI device code number */
2741: ushort lib_version; /* Adv Library version number */
2742: ushort control_flag; /* Microcode Control Flag */
2743: ushort mcode_date; /* Microcode date */
2744: ushort mcode_version; /* Microcode version */
2745: ushort pci_slot_info; /* high byte device/function number */
2746: /* bits 7-3 device num., bits 2-0 function num. */
2747: /* low byte bus num. */
2748: ushort bios_boot_wait; /* BIOS boot time delay */
2749: ushort serial1; /* EEPROM serial number word 1 */
2750: ushort serial2; /* EEPROM serial number word 2 */
2751: ushort serial3; /* EEPROM serial number word 3 */
2752: } ADV_DVC_CFG;
2753:
2754: /*
2755: * Adapter operation variable structure.
2756: *
2757: * One structure is required per host adapter.
2758: *
2759: * Field naming convention:
2760: *
2761: * *_able indicates both whether a feature should be enabled or disabled
2762: * and whether a device isi capable of the feature. At initialization
2763: * this field may be set, but later if a device is found to be incapable
2764: * of the feature, the field is cleared.
2765: */
2766: typedef struct adv_dvc_var {
2767: AdvPortAddr iop_base; /* I/O port address */
2768: ushort err_code; /* fatal error code */
2769: ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
2770: Ptr2Func isr_callback; /* pointer to function, called in AdvISR() */
2771: Ptr2Func sbreset_callback; /* pointer to function, called in AdvISR() */
2772: ushort wdtr_able; /* try WDTR for a device */
2773: ushort sdtr_able; /* try SDTR for a device */
2774: ushort ultra_able; /* try SDTR Ultra speed for a device */
2775: ushort tagqng_able; /* try tagged queuing with a device */
2776: uchar max_dvc_qng; /* maximum number of tagged commands per device */
2777: ushort start_motor; /* start motor command allowed */
2778: uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2779: uchar chip_no; /* should be assigned by caller */
2780: uchar max_host_qng; /* maximum number of Q'ed command allowed */
2781: uchar cur_host_qng; /* total number of queue command */
2782: uchar irq_no; /* IRQ number */
2783: ushort no_scam; /* scam_tolerant of EEPROM */
2784: ushort idle_cmd_done; /* microcode idle command done set by AdvISR() */
2785: ulong drv_ptr; /* driver pointer to private structure */
2786: uchar chip_scsi_id; /* chip SCSI target ID */
2787: /*
2788: * Note: The following fields will not be used after initialization. The
2789: * driver may discard the buffer after initialization is done.
2790: */
2791: ADV_DVC_CFG *cfg; /* temporary configuration structure */
2792: } ADV_DVC_VAR;
2793:
2794: #define NO_OF_SG_PER_BLOCK 15
2795:
2796: typedef struct asc_sg_block {
2797: uchar reserved1;
2798: uchar reserved2;
2799: uchar first_entry_no; /* starting entry number */
2800: uchar last_entry_no; /* last entry number */
2801: struct asc_sg_block *sg_ptr; /* links to the next sg block */
2802: struct {
2803: ulong sg_addr; /* SG element address */
2804: ulong sg_count; /* SG element count */
2805: } sg_list[NO_OF_SG_PER_BLOCK];
2806: } ADV_SG_BLOCK;
2807:
2808: /*
2809: * ASC_SCSI_REQ_Q - microcode request structure
2810: *
2811: * All fields in this structure up to byte 60 are used by the microcode.
2812: * The microcode makes assumptions about the size and ordering of fields
2813: * in this structure. Do not change the structure definition here without
2814: * coordinating the change with the microcode.
2815: */
2816: typedef struct adv_scsi_req_q {
2817: uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2818: uchar sg_entry_cnt; /* SG element count. Zero for no SG. */
2819: uchar target_id; /* Device target identifier. */
2820: uchar target_lun; /* Device target logical unit number. */
2821: ulong data_addr; /* Data buffer physical address. */
2822: ulong data_cnt; /* Data count. Ucode sets to residual. */
2823: ulong sense_addr; /* Sense buffer physical address. */
2824: ulong srb_ptr; /* Driver request pointer. */
2825: uchar a_flag; /* Adv Library flag field. */
2826: uchar sense_len; /* Auto-sense length. Ucode sets to residual. */
2827: uchar cdb_len; /* SCSI CDB length. */
2828: uchar tag_code; /* SCSI-2 Tag Queue Code: 00, 20-22. */
2829: uchar done_status; /* Completion status. */
2830: uchar scsi_status; /* SCSI status byte. */
2831: uchar host_status; /* Ucode host status. */
2832: uchar ux_sg_ix; /* Ucode working SG variable. */
2833: uchar cdb[12]; /* SCSI command block. */
2834: ulong sg_real_addr; /* SG list physical address. */
2835: struct adv_scsi_req_q *free_scsiq_link;
2836: ulong ux_wk_data_cnt; /* Saved data count at disconnection. */
2837: struct adv_scsi_req_q *scsiq_ptr;
2838: ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2839: /*
2840: * End of microcode structure - 60 bytes. The rest of the structure
2841: * is used by the Adv Library and ignored by the microcode.
2842: */
2843: ulong vsense_addr; /* Sense buffer virtual address. */
2844: ulong vdata_addr; /* Data buffer virtual address. */
2845: uchar orig_sense_len; /* Original length of sense buffer. */
2846: } ADV_SCSI_REQ_Q; /* BIOS - 70 bytes, DOS - 76 bytes, W95, WNT - 69 bytes */
2847:
2848: /*
2849: * Microcode idle loop commands
2850: */
2851: #define IDLE_CMD_COMPLETED 0
2852: #define IDLE_CMD_STOP_CHIP 0x0001
2853: #define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2854: #define IDLE_CMD_SEND_INT 0x0004
2855: #define IDLE_CMD_ABORT 0x0008
2856: #define IDLE_CMD_DEVICE_RESET 0x0010
2857: #define IDLE_CMD_SCSI_RESET 0x0020
2858:
2859: /*
2860: * AdvSendIdleCmd() flag definitions.
2861: */
2862: #define ADV_NOWAIT 0x01
2863:
2864: /*
2865: * Wait loop time out values.
2866: */
2867: #define SCSI_WAIT_10_SEC 10 /* 10 seconds */
2868: #define SCSI_MS_PER_SEC 1000 /* milliseconds per second */
2869:
2870: /*
2871: * Device drivers must define the following functions.
2872: */
2873: STATIC int DvcEnterCritical(void);
2874: STATIC void DvcLeaveCritical(int);
2875: STATIC void DvcSleepMilliSecond(ulong);
2876: STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
2877: STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
2878: STATIC ulong DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2879: uchar *, long *, int);
2880: STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
2881:
2882: /*
2883: * Adv Library functions available to drivers.
2884: */
2885: STATIC int AdvExeScsiQueue(ADV_DVC_VAR *,
2886: ADV_SCSI_REQ_Q *);
2887: STATIC int AdvISR(ADV_DVC_VAR *);
2888: STATIC int AdvInitGetConfig(ADV_DVC_VAR *);
2889: STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2890: STATIC int AdvResetSB(ADV_DVC_VAR *);
2891:
2892: /*
2893: * Internal Adv Library functions.
2894: */
2895: STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ulong, int);
2896: STATIC void AdvResetChip(ADV_DVC_VAR *);
2897: STATIC int AdvSendScsiCmd(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2898: STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2899: STATIC int AdvInitFromEEP(ADV_DVC_VAR *);
2900: STATIC ushort AdvGetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *);
2901: STATIC void AdvSetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *);
2902: STATIC void AdvWaitEEPCmd(AdvPortAddr);
2903: STATIC ushort AdvReadEEPWord(AdvPortAddr, int);
2904: STATIC void AdvResetSCSIBus(ADV_DVC_VAR *);
2905:
2906: /*
2907: * PCI Bus Definitions
2908: */
2909: #define AscPCICmdRegBits_BusMastering 0x0007
2910: #define AscPCICmdRegBits_ParErrRespCtrl 0x0040
2911:
2912: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
2913:
2914: /* Read byte from a register. */
2915: #define AdvReadByteRegister(iop_base, reg_off) \
2916: (inp((iop_base) + (reg_off)))
2917:
2918: /* Write byte to a register. */
2919: #define AdvWriteByteRegister(iop_base, reg_off, byte) \
2920: (outp((iop_base) + (reg_off), (byte)))
2921:
2922: /* Read word (2 bytes) from a register. */
2923: #define AdvReadWordRegister(iop_base, reg_off) \
2924: (inpw((iop_base) + (reg_off)))
2925:
2926: /* Write word (2 bytes) to a register. */
2927: #define AdvWriteWordRegister(iop_base, reg_off, word) \
2928: (outpw((iop_base) + (reg_off), (word)))
2929:
2930: /* Read byte from LRAM. */
2931: #define AdvReadByteLram(iop_base, addr, byte) \
2932: do { \
2933: outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
2934: (byte) = inp((iop_base) + IOPB_RAM_DATA); \
2935: } while (0)
2936:
2937: /* Write byte to LRAM. */
2938: #define AdvWriteByteLram(iop_base, addr, byte) \
2939: (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
2940: outp((iop_base) + IOPB_RAM_DATA, (byte)))
2941:
2942: /* Read word (2 bytes) from LRAM. */
2943: #define AdvReadWordLram(iop_base, addr, word) \
2944: do { \
2945: outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
2946: (word) = inpw((iop_base) + IOPW_RAM_DATA); \
2947: } while (0)
2948:
2949: /* Write word (2 bytes) to LRAM. */
2950: #define AdvWriteWordLram(iop_base, addr, word) \
2951: (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
2952: outpw((iop_base) + IOPW_RAM_DATA, (word)))
2953:
2954: /* Write double word (4 bytes) to LRAM */
2955: /* Because of unspecified C language ordering don't use auto-increment. */
2956: #define AdvWriteDWordLram(iop_base, addr, dword) \
2957: ((outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
2958: outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword) & 0xFFFF))), \
2959: (outpw((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2960: outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword >> 16) & 0xFFFF))))
2961:
2962: /* Read word (2 bytes) from LRAM assuming that the address is already set. */
2963: #define AdvReadWordAutoIncLram(iop_base) \
2964: (inpw((iop_base) + IOPW_RAM_DATA))
2965:
2966: /* Write word (2 bytes) to LRAM assuming that the address is already set. */
2967: #define AdvWriteWordAutoIncLram(iop_base, word) \
2968: (outpw((iop_base) + IOPW_RAM_DATA, (word)))
2969:
2970: #else /* version >= v1,3,0 */
2971:
2972: /* Read byte from a register. */
2973: #define AdvReadByteRegister(iop_base, reg_off) \
2974: (ADV_MEM_READB((iop_base) + (reg_off)))
2975:
2976: /* Write byte to a register. */
2977: #define AdvWriteByteRegister(iop_base, reg_off, byte) \
2978: (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2979:
2980: /* Read word (2 bytes) from a register. */
2981: #define AdvReadWordRegister(iop_base, reg_off) \
2982: (ADV_MEM_READW((iop_base) + (reg_off)))
2983:
2984: /* Write word (2 bytes) to a register. */
2985: #define AdvWriteWordRegister(iop_base, reg_off, word) \
2986: (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2987:
2988: /* Read byte from LRAM. */
2989: #define AdvReadByteLram(iop_base, addr, byte) \
2990: do { \
2991: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2992: (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2993: } while (0)
2994:
2995: /* Write byte to LRAM. */
2996: #define AdvWriteByteLram(iop_base, addr, byte) \
2997: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2998: ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2999:
3000: /* Read word (2 bytes) from LRAM. */
3001: #define AdvReadWordLram(iop_base, addr, word) \
3002: do { \
3003: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
3004: (word) = ADV_MEM_READW((iop_base) + IOPW_RAM_DATA); \
3005: } while (0)
3006:
3007: /* Write word (2 bytes) to LRAM. */
3008: #define AdvWriteWordLram(iop_base, addr, word) \
3009: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3010: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3011:
3012: /* Write double word (4 bytes) to LRAM */
3013: /* Because of unspecified C language ordering don't use auto-increment. */
3014: #define AdvWriteDWordLram(iop_base, addr, dword) \
3015: ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
3016: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3017: (ushort) ((dword) & 0xFFFF))), \
3018: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
3019: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
3020: (ushort) ((dword >> 16) & 0xFFFF))))
3021:
3022: /* Read word (2 bytes) from LRAM assuming that the address is already set. */
3023: #define AdvReadWordAutoIncLram(iop_base) \
3024: (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
3025:
3026: /* Write word (2 bytes) to LRAM assuming that the address is already set. */
3027: #define AdvWriteWordAutoIncLram(iop_base, word) \
3028: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
3029:
3030: #endif /* version >= v1,3,0 */
3031:
3032: /*
3033: * Define macro to check for Condor signature.
3034: *
3035: * Evaluate to ADV_TRUE if a Condor chip is found the specified port
3036: * address 'iop_base'. Otherwise evalue to ADV_FALSE.
3037: */
3038: #define AdvFindSignature(iop_base) \
3039: (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
3040: ADV_CHIP_ID_BYTE) && \
3041: (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
3042: ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
3043:
3044: /*
3045: * Define macro to Return the version number of the chip at 'iop_base'.
3046: *
3047: * The second parameter 'bus_type' is currently unused.
3048: */
3049: #define AdvGetChipVersion(iop_base, bus_type) \
3050: AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
3051:
3052: /*
3053: * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
3054: * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
3055: *
3056: * If the request has not yet been sent to the device it will simply be
3057: * aborted from RISC memory. If the request is disconnected it will be
3058: * aborted on reselection by sending an Abort Message to the target ID.
3059: *
3060: * Return value:
3061: * ADV_TRUE(1) - Queue was successfully aborted.
3062: * ADV_FALSE(0) - Queue was not found on the active queue list.
3063: */
3064: #define AdvAbortSRB(asc_dvc, srb_ptr) \
3065: AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
3066: (ulong) (srb_ptr), 0)
3067:
3068: /*
3069: * Send a Bus Device Reset Message to the specified target ID.
3070: *
3071: * All outstanding commands will be purged if sending the
3072: * Bus Device Reset Message is successful.
3073: *
3074: * Return Value:
3075: * ADV_TRUE(1) - All requests on the target are purged.
3076: * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
3077: * are not purged.
3078: */
3079: #define AdvResetDevice(asc_dvc, target_id) \
3080: AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
3081: (ulong) (target_id), 0)
3082:
3083: /*
3084: * SCSI Wide Type definition.
3085: */
3086: #define ADV_SCSI_BIT_ID_TYPE ushort
3087:
3088: /*
3089: * AdvInitScsiTarget() 'cntl_flag' options.
3090: */
3091: #define ADV_SCAN_LUN 0x01
3092: #define ADV_CAPINFO_NOLUN 0x02
3093:
3094: /*
3095: * Convert target id to target id bit mask.
3096: */
3097: #define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
3098:
3099: /*
3100: * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
3101: */
3102:
3103: #define QD_NO_STATUS 0x00 /* Request not completed yet. */
3104: #define QD_NO_ERROR 0x01
3105: #define QD_ABORTED_BY_HOST 0x02
3106: #define QD_WITH_ERROR 0x04
3107:
3108: #define QHSTA_NO_ERROR 0x00
3109: #define QHSTA_M_SEL_TIMEOUT 0x11
3110: #define QHSTA_M_DATA_OVER_RUN 0x12
3111: #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
3112: #define QHSTA_M_QUEUE_ABORTED 0x15
3113: #define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
3114: #define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
3115: #define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
3116: #define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
3117: #define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
3118: #define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
3119: #define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
3120: /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
3121: #define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
3122: #define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
3123: #define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
3124: #define QHSTA_M_WTM_TIMEOUT 0x41
3125: #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
3126: #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
3127: #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
3128: #define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
3129:
3130: typedef int (* ADV_ISR_CALLBACK)
3131: (ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3132:
3133: typedef int (* ADV_SBRESET_CALLBACK)
3134: (ADV_DVC_VAR *);
3135:
3136: /*
3137: * Default EEPROM Configuration structure defined in a_init.c.
3138: */
3139: extern ADVEEP_CONFIG Default_EEPROM_Config;
3140:
3141: /*
3142: * DvcGetPhyAddr() flag arguments
3143: */
3144: #define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
3145: #define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
3146: #define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
3147: #define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
3148: #define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
3149:
3150: /* Return the address that is aligned at the next doubleword >= to 'addr'. */
3151: #define ADV_DWALIGN(addr) (((ulong) (addr) + 0x3) & ~0x3)
3152:
3153: /*
3154: * Total contiguous memory needed for driver SG blocks.
3155: *
3156: * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
3157: * number of scatter-gather elements the driver supports in a
3158: * single request.
3159: */
3160:
3161: #ifndef ADV_MAX_SG_LIST
3162: Forced Error: Driver must define ADV_MAX_SG_LIST.
3163: #endif /* ADV_MAX_SG_LIST */
3164:
3165: #define ADV_SG_LIST_MAX_BYTE_SIZE \
3166: (sizeof(ADV_SG_BLOCK) * \
3167: ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
3168:
3169: /*
3170: * A driver may optionally define the assertion macro ADV_ASSERT() in
3171: * its d_os_dep.h file. If the macro has not already been defined,
3172: * then define the macro to a no-op.
3173: */
3174: #ifndef ADV_ASSERT
3175: #define ADV_ASSERT(a)
3176: #endif /* ADV_ASSERT */
3177:
3178:
3179: /*
3180: * --- Driver Constants and Macros
3181: */
3182:
3183: #define ASC_NUM_BOARD_SUPPORTED 16
3184: #define ASC_NUM_IOPORT_PROBE 4
3185: #define ASC_NUM_BUS 4
3186:
3187: /* Reference Scsi_Host hostdata */
3188: #define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
3189:
3190: /* asc_board_t flags */
3191: #define ASC_HOST_IN_RESET 0x01
3192: #define ASC_HOST_IN_ABORT 0x02
3193: #define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
3194: #define ASC_SELECT_QUEUE_DEPTHS 0x08
3195:
3196: #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
3197: #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
3198:
3199: #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
3200:
3201: /*
3202: * If the Linux kernel version supports freeing initialization code
3203: * and data after loading, define macros for this purpose. These macros
3204: * are not used when the driver is built as a module, cf. linux/init.h.
3205: */
3206: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,23)
3207: #define ASC_INITFUNC(func) func
3208: #define ASC_INITDATA
3209: #define ASC_INIT
3210: #else /* version >= v2.1.23 */
3211: #define ASC_INITFUNC(func) __initfunc(func)
3212: #define ASC_INITDATA __initdata
3213: #define ASC_INIT __init
3214: #endif /* version >= v2.1.23 */
3215:
3216: #define ASC_INFO_SIZE 128 /* advansys_info() line size */
3217:
3218: /* /proc/scsi/advansys/[0...] related definitions */
3219: #define ASC_PRTBUF_SIZE 2048
3220: #define ASC_PRTLINE_SIZE 160
3221:
3222: #define ASC_PRT_NEXT() \
3223: if (cp) { \
3224: totlen += len; \
3225: leftlen -= len; \
3226: if (leftlen == 0) { \
3227: return totlen; \
3228: } \
3229: cp += len; \
3230: }
3231:
3232: #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
3233:
3234: /* Asc Library return codes */
3235: #define ASC_TRUE 1
3236: #define ASC_FALSE 0
3237: #define ASC_NOERROR 1
3238: #define ASC_BUSY 0
3239: #define ASC_ERROR (-1)
3240:
3241: /* Scsi_Cmnd function return codes */
3242: #define STATUS_BYTE(byte) (byte)
3243: #define MSG_BYTE(byte) ((byte) << 8)
3244: #define HOST_BYTE(byte) ((byte) << 16)
3245: #define DRIVER_BYTE(byte) ((byte) << 24)
3246:
3247: /*
3248: * The following definitions and macros are OS independent interfaces to
3249: * the queue functions:
3250: * REQ - SCSI request structure
3251: * REQP - pointer to SCSI request structure
3252: * REQPTID(reqp) - reqp's target id
3253: * REQPNEXT(reqp) - reqp's next pointer
3254: * REQPNEXTP(reqp) - pointer to reqp's next pointer
3255: * REQPTIME(reqp) - reqp's time stamp value
3256: * REQTIMESTAMP() - system time stamp value
3257: */
3258: typedef Scsi_Cmnd REQ, *REQP;
3259: #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
3260: #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
3261: #define REQPTID(reqp) ((reqp)->target)
3262: #define REQPTIME(reqp) ((reqp)->SCp.this_residual)
3263: #define REQTIMESTAMP() (jiffies)
3264:
3265: #define REQTIMESTAT(function, ascq, reqp, tid) \
3266: { \
3267: /*
3268: * If the request time stamp is less than the system time stamp, then \
3269: * maybe the system time stamp wrapped. Set the request time to zero.\
3270: */ \
3271: if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
3272: REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
3273: } else { \
3274: /* Indicate an error occurred with the assertion. */ \
3275: ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
3276: REQPTIME(reqp) = 0; \
3277: } \
3278: /* Handle first minimum time case without external initialization. */ \
3279: if (((ascq)->q_tot_cnt[tid] == 1) || \
3280: (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
3281: (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
3282: ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
3283: (function), (tid), (ascq)->q_min_tim[tid]); \
3284: } \
3285: if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
3286: (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
3287: ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
3288: (function), tid, (ascq)->q_max_tim[tid]); \
3289: } \
3290: (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
3291: /* Reset the time stamp field. */ \
3292: REQPTIME(reqp) = 0; \
3293: }
3294:
3295: /* asc_enqueue() flags */
3296: #define ASC_FRONT 1
3297: #define ASC_BACK 2
3298:
3299: /* asc_dequeue_list() argument */
3300: #define ASC_TID_ALL (-1)
3301:
3302: /* Return non-zero, if the queue is empty. */
3303: #define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
3304:
3305: /* PCI configuration declarations */
3306:
3307: #define PCI_BASE_CLASS_PREDEFINED 0x00
3308: #define PCI_BASE_CLASS_MASS_STORAGE 0x01
3309: #define PCI_BASE_CLASS_NETWORK 0x02
3310: #define PCI_BASE_CLASS_DISPLAY 0x03
3311: #define PCI_BASE_CLASS_MULTIMEDIA 0x04
3312: #define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05
3313: #define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06
3314:
3315: /* MASS STORAGE */
3316: #define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00
3317: #define PCI_SUB_CLASS_IDE_CONTROLLER 0x01
3318: #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02
3319: #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03
3320: #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80
3321:
3322: /* NETWORK CONTROLLER */
3323: #define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00
3324: #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01
3325: #define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02
3326: #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80
3327:
3328: /* DISPLAY CONTROLLER */
3329: #define PCI_SUB_CLASS_VGA_CONTROLLER 0x00
3330: #define PCI_SUB_CLASS_XGA_CONTROLLER 0x01
3331: #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80
3332:
3333: /* MULTIMEDIA CONTROLLER */
3334: #define PCI_SUB_CLASS_VIDEO_DEVICE 0x00
3335: #define PCI_SUB_CLASS_AUDIO_DEVICE 0x01
3336: #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80
3337:
3338: /* MEMORY CONTROLLER */
3339: #define PCI_SUB_CLASS_RAM_CONTROLLER 0x00
3340: #define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01
3341: #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80
3342:
3343: /* BRIDGE CONTROLLER */
3344: #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00
3345: #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01
3346: #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02
3347: #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03
3348: #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04
3349: #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05
3350: #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80
3351:
3352: #define PCI_MAX_SLOT 0x1F
3353: #define PCI_MAX_BUS 0xFF
3354: #define PCI_IOADDRESS_MASK 0xFFFE
3355: #define ASC_PCI_VENDORID 0x10CD
3356: #define ASC_PCI_DEVICE_ID_CNT 4 /* PCI Device ID count. */
3357: #define ASC_PCI_DEVICE_ID_1100 0x1100
3358: #define ASC_PCI_DEVICE_ID_1200 0x1200
3359: #define ASC_PCI_DEVICE_ID_1300 0x1300
3360: #define ASC_PCI_DEVICE_ID_2300 0x2300
3361:
3362: /* PCI IO Port Addresses to generate special cycle */
3363:
3364: #define PCI_CONFIG_ADDRESS_MECH1 0x0CF8
3365: #define PCI_CONFIG_DATA_MECH1 0x0CFC
3366:
3367: #define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */
3368:
3369: #define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000
3370: #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00
3371: #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8
3372:
3373: #define PCI_DEVICE_FOUND 0x0000
3374: #define PCI_DEVICE_NOT_FOUND 0xffff
3375:
3376: #define SUBCLASS_OFFSET 0x0A
3377: #define CLASSCODE_OFFSET 0x0B
3378: #define VENDORID_OFFSET 0x00
3379: #define DEVICEID_OFFSET 0x02
3380:
3381: #ifndef ADVANSYS_STATS
3382: #define ASC_STATS(shp, counter)
3383: #define ASC_STATS_ADD(shp, counter, count)
3384: #else /* ADVANSYS_STATS */
3385: #define ASC_STATS(shp, counter) \
3386: (ASC_BOARDP(shp)->asc_stats.counter++)
3387:
3388: #define ASC_STATS_ADD(shp, counter, count) \
3389: (ASC_BOARDP(shp)->asc_stats.counter += (count))
3390: #endif /* ADVANSYS_STATS */
3391:
3392: #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
3393:
3394: /* If the result wraps when calculating tenths, return 0. */
3395: #define ASC_TENTHS(num, den) \
3396: (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
3397: 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
3398:
3399: /*
3400: * Display a message to the console.
3401: */
3402: #define ASC_PRINT(s) \
3403: { \
3404: printk("advansys: "); \
3405: printk(s); \
3406: }
3407:
3408: #define ASC_PRINT1(s, a1) \
3409: { \
3410: printk("advansys: "); \
3411: printk((s), (a1)); \
3412: }
3413:
3414: #define ASC_PRINT2(s, a1, a2) \
3415: { \
3416: printk("advansys: "); \
3417: printk((s), (a1), (a2)); \
3418: }
3419:
3420: #define ASC_PRINT3(s, a1, a2, a3) \
3421: { \
3422: printk("advansys: "); \
3423: printk((s), (a1), (a2), (a3)); \
3424: }
3425:
3426: #define ASC_PRINT4(s, a1, a2, a3, a4) \
3427: { \
3428: printk("advansys: "); \
3429: printk((s), (a1), (a2), (a3), (a4)); \
3430: }
3431:
3432:
3433: #ifndef ADVANSYS_DEBUG
3434:
3435: #define ASC_DBG(lvl, s)
3436: #define ASC_DBG1(lvl, s, a1)
3437: #define ASC_DBG2(lvl, s, a1, a2)
3438: #define ASC_DBG3(lvl, s, a1, a2, a3)
3439: #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
3440: #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
3441: #define ASC_DBG_PRT_SCSI_CMND(lvl, s)
3442: #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
3443: #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3444: #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
3445: #define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
3446: #define ASC_DBG_PRT_HEX(lvl, name, start, length)
3447: #define ASC_DBG_PRT_CDB(lvl, cdb, len)
3448: #define ASC_DBG_PRT_SENSE(lvl, sense, len)
3449: #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
3450:
3451: #else /* ADVANSYS_DEBUG */
3452:
3453: /*
3454: * Debugging Message Levels:
3455: * 0: Errors Only
3456: * 1: High-Level Tracing
3457: * 2-N: Verbose Tracing
3458: */
3459:
3460: #define ASC_DBG(lvl, s) \
3461: { \
3462: if (asc_dbglvl >= (lvl)) { \
3463: printk(s); \
3464: } \
3465: }
3466:
3467: #define ASC_DBG1(lvl, s, a1) \
3468: { \
3469: if (asc_dbglvl >= (lvl)) { \
3470: printk((s), (a1)); \
3471: } \
3472: }
3473:
3474: #define ASC_DBG2(lvl, s, a1, a2) \
3475: { \
3476: if (asc_dbglvl >= (lvl)) { \
3477: printk((s), (a1), (a2)); \
3478: } \
3479: }
3480:
3481: #define ASC_DBG3(lvl, s, a1, a2, a3) \
3482: { \
3483: if (asc_dbglvl >= (lvl)) { \
3484: printk((s), (a1), (a2), (a3)); \
3485: } \
3486: }
3487:
3488: #define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
3489: { \
3490: if (asc_dbglvl >= (lvl)) { \
3491: printk((s), (a1), (a2), (a3), (a4)); \
3492: } \
3493: }
3494:
3495: #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
3496: { \
3497: if (asc_dbglvl >= (lvl)) { \
3498: asc_prt_scsi_host(s); \
3499: } \
3500: }
3501:
3502: #define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
3503: { \
3504: if (asc_dbglvl >= (lvl)) { \
3505: asc_prt_scsi_cmnd(s); \
3506: } \
3507: }
3508:
3509: #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
3510: { \
3511: if (asc_dbglvl >= (lvl)) { \
3512: asc_prt_asc_scsi_q(scsiqp); \
3513: } \
3514: }
3515:
3516: #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
3517: { \
3518: if (asc_dbglvl >= (lvl)) { \
3519: asc_prt_asc_qdone_info(qdone); \
3520: } \
3521: }
3522:
3523: #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
3524: { \
3525: if (asc_dbglvl >= (lvl)) { \
3526: asc_prt_adv_scsi_req_q(scsiqp); \
3527: } \
3528: }
3529:
3530: #define ASC_DBG_PRT_HEX(lvl, name, start, length) \
3531: { \
3532: if (asc_dbglvl >= (lvl)) { \
3533: asc_prt_hex((name), (start), (length)); \
3534: } \
3535: }
3536:
3537: #define ASC_DBG_PRT_CDB(lvl, cdb, len) \
3538: ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
3539:
3540: #define ASC_DBG_PRT_SENSE(lvl, sense, len) \
3541: ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
3542:
3543: #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
3544: ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
3545: #endif /* ADVANSYS_DEBUG */
3546:
3547: #ifndef ADVANSYS_ASSERT
3548: #define ASC_ASSERT(a)
3549: #else /* ADVANSYS_ASSERT */
3550:
3551: #define ASC_ASSERT(a) \
3552: { \
3553: if (!(a)) { \
3554: printk("ASC_ASSERT() Failure: file %s, line %d\n", \
3555: __FILE__, __LINE__); \
3556: } \
3557: }
3558:
3559: #endif /* ADVANSYS_ASSERT */
3560:
3561:
3562: /*
3563: * --- Driver Structures
3564: */
3565:
3566: #ifdef ADVANSYS_STATS
3567:
3568: /* Per board statistics structure */
3569: struct asc_stats {
3570: /* Driver Entrypoint Statistics */
3571: ulong command; /* # calls to advansys_command() */
3572: ulong queuecommand; /* # calls to advansys_queuecommand() */
3573: ulong abort; /* # calls to advansys_abort() */
3574: ulong reset; /* # calls to advansys_reset() */
3575: ulong biosparam; /* # calls to advansys_biosparam() */
3576: ulong interrupt; /* # advansys_interrupt() calls */
3577: ulong callback; /* # calls to asc/adv_isr_callback() */
3578: ulong done; /* # calls to request's scsi_done function */
3579: ulong build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
3580: ulong adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
3581: ulong adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
3582: /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
3583: ulong exe_noerror; /* # ASC_NOERROR returns. */
3584: ulong exe_busy; /* # ASC_BUSY returns. */
3585: ulong exe_error; /* # ASC_ERROR returns. */
3586: ulong exe_unknown; /* # unknown returns. */
3587: /* Data Transfer Statistics */
3588: ulong cont_cnt; /* # non-scatter-gather I/O requests received */
3589: ulong cont_xfer; /* # contiguous transfer 512-bytes */
3590: ulong sg_cnt; /* # scatter-gather I/O requests received */
3591: ulong sg_elem; /* # scatter-gather elements */
3592: ulong sg_xfer; /* # scatter-gather transfer 512-bytes */
3593: };
3594: #endif /* ADVANSYS_STATS */
3595:
3596: /*
3597: * Request queuing structure
3598: */
3599: typedef struct asc_queue {
3600: ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
3601: REQP q_first[ADV_MAX_TID+1]; /* first queued request */
3602: REQP q_last[ADV_MAX_TID+1]; /* last queued request */
3603: #ifdef ADVANSYS_STATS
3604: short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */
3605: short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */
3606: ulong q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */
3607: ulong q_tot_tim[ADV_MAX_TID+1]; /* total time queued */
3608: ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */
3609: ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */
3610: #endif /* ADVANSYS_STATS */
3611: } asc_queue_t;
3612:
3613: /*
3614: * Adv Library Request Structures
3615: *
3616: * The following two se structures are used to process Wide Board requests.
3617: * One structure is needed for each command received from the Mid-Level SCSI
3618: * driver.
3619: *
3620: * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
3621: * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
3622: * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
3623: * Mid-Level SCSI request structure.
3624: *
3625: * The adv_sgblk_t structure is used to handle requests that include
3626: * scatter-gather elements.
3627: */
3628: typedef struct adv_sgblk {
3629: ADV_SG_BLOCK sg_block[ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING];
3630: uchar align2[4]; /* Sgblock structure padding. */
3631: struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
3632: } adv_sgblk_t;
3633:
3634: typedef struct adv_req {
3635: ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
3636: uchar align1[4]; /* Request structure padding. */
3637: Scsi_Cmnd *cmndp; /* Mid-Level SCSI command pointer. */
3638: adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
3639: struct adv_req *next_reqp; /* Next Request Structure. */
3640: } adv_req_t;
3641:
3642: /*
3643: * Structure allocated for each board.
3644: *
3645: * This structure is allocated by scsi_register() at the end
3646: * of the 'Scsi_Host' structure starting at the 'hostdata'
3647: * field. It is guaranteed to be allocated from DMA-able memory.
3648: */
3649: typedef struct asc_board {
3650: int id; /* Board Id */
3651: uint flags; /* Board flags */
3652: union {
3653: ASC_DVC_VAR asc_dvc_var; /* Narrow board */
3654: ADV_DVC_VAR adv_dvc_var; /* Wide board */
3655: } dvc_var;
3656: union {
3657: ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
3658: ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
3659: } dvc_cfg;
3660: asc_queue_t active; /* Active command queue */
3661: asc_queue_t waiting; /* Waiting command queue */
3662: asc_queue_t done; /* Done command queue */
3663: ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
3664: Scsi_Device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */
3665: ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */
3666: #if ASC_QUEUE_FLOW_CONTROL
3667: ushort nerrcnt[ADV_MAX_TID+1]; /* No error request count */
3668: #endif /* ASC_QUEUE_FLOW_CONTROL */
3669: ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
3670: ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */
3671: union {
3672: ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
3673: ADVEEP_CONFIG adv_eep; /* Wide EEPROM config. */
3674: } eep_config;
3675: ulong last_reset; /* Saved last reset time */
3676: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3677: /* /proc/scsi/advansys/[0...] */
3678: char *prtbuf; /* Statistics Print Buffer */
3679: #endif /* version >= v1.3.0 */
3680: #ifdef ADVANSYS_STATS
3681: struct asc_stats asc_stats; /* Board statistics */
3682: #endif /* ADVANSYS_STATS */
3683: /*
3684: * The following fields are used only for Narrow Boards.
3685: */
3686: /* The following three structures must be in DMA-able memory. */
3687: ASC_SCSI_REQ_Q scsireqq;
3688: ASC_CAP_INFO cap_info;
3689: ASC_SCSI_INQUIRY inquiry;
3690: uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */
3691: /*
3692: * The following fields are used only for Wide Boards.
3693: */
3694: void *ioremap_addr; /* I/O Memory remap address. */
3695: ushort ioport; /* I/O Port address. */
3696: adv_req_t *orig_reqp; /* adv_req_t memory block. */
3697: adv_req_t *adv_reqp; /* Request structures. */
3698: adv_sgblk_t *orig_sgblkp; /* adv_sgblk_t memory block. */
3699: adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
3700: ushort bios_signature; /* BIOS Signature. */
3701: ushort bios_version; /* BIOS Version. */
3702: ushort bios_codeseg; /* BIOS Code Segment. */
3703: ushort bios_codelen; /* BIOS Code Segment Length. */
3704: } asc_board_t;
3705:
3706: /*
3707: * PCI configuration structures
3708: */
3709: typedef struct _PCI_DATA_
3710: {
3711: uchar type;
3712: uchar bus;
3713: uchar slot;
3714: uchar func;
3715: uchar offset;
3716: } PCI_DATA;
3717:
3718: typedef struct _PCI_DEVICE_
3719: {
3720: ushort vendorID;
3721: ushort deviceID;
3722: ushort slotNumber;
3723: ushort slotFound;
3724: uchar busNumber;
3725: uchar maxBusNumber;
3726: uchar devFunc;
3727: ushort startSlot;
3728: ushort endSlot;
3729: uchar bridge;
3730: uchar type;
3731: } PCI_DEVICE;
3732:
3733: typedef struct _PCI_CONFIG_SPACE_
3734: {
3735: ushort vendorID;
3736: ushort deviceID;
3737: ushort command;
3738: ushort status;
3739: uchar revision;
3740: uchar classCode[3];
3741: uchar cacheSize;
3742: uchar latencyTimer;
3743: uchar headerType;
3744: uchar bist;
3745: ulong baseAddress[6];
3746: ushort reserved[4];
3747: ulong optionRomAddr;
3748: ushort reserved2[4];
3749: uchar irqLine;
3750: uchar irqPin;
3751: uchar minGnt;
3752: uchar maxLatency;
3753: } PCI_CONFIG_SPACE;
3754:
3755:
3756: /*
3757: * --- Driver Data
3758: */
3759:
3760: /* Note: All driver global data should be initialized. */
3761:
3762: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3763: struct proc_dir_entry proc_scsi_advansys =
3764: {
3765: PROC_SCSI_ADVANSYS, /* unsigned short low_ino */
3766: 8, /* unsigned short namelen */
3767: "advansys", /* const char *name */
3768: S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */
3769: 2 /* nlink_t nlink */
3770: };
3771: #endif /* version >= v1.3.0 */
3772:
3773: /* Number of boards detected in system. */
3774: STATIC int asc_board_count = 0;
3775: STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
3776:
3777: /* Overrun buffer shared between all boards. */
3778: STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
3779:
3780: /*
3781: * Global structures required to issue a command.
3782: */
3783: STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
3784: STATIC ASC_SG_HEAD asc_sg_head = { 0 };
3785:
3786: /* List of supported bus types. */
3787: STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
3788: ASC_IS_ISA,
3789: ASC_IS_VL,
3790: ASC_IS_EISA,
3791: ASC_IS_PCI,
3792: };
3793:
3794: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
3795: #ifdef ASC_CONFIG_PCI
3796: STATIC int pci_scan_method ASC_INITDATA = -1;
3797: #endif /* ASC_CONFIG_PCI */
3798: #endif /* version < v2.1.93 */
3799:
3800: /*
3801: * Used with the LILO 'advansys' option to eliminate or
3802: * limit I/O port probing at boot time, cf. advansys_setup().
3803: */
3804: STATIC int asc_iopflag = ASC_FALSE;
3805: STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
3806:
3807: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
3808: /*
3809: * In kernels earlier than v1.3.0, kmalloc() does not work
3810: * during driver initialization. Therefore statically declare
3811: * 16 elements of each structure. v1.3.0 kernels will probably
3812: * not need any more than this number.
3813: */
3814: uchar adv_req_buf[16 * sizeof(adv_req_t)] = { 0 };
3815: uchar adv_sgblk_buf[16 * sizeof(adv_sgblk_t)] = { 0 };
3816: #endif /* version >= v1,3,0 */
3817:
3818: #ifdef ADVANSYS_DEBUG
3819: STATIC char *
3820: asc_bus_name[ASC_NUM_BUS] = {
3821: "ASC_IS_ISA",
3822: "ASC_IS_VL",
3823: "ASC_IS_EISA",
3824: "ASC_IS_PCI",
3825: };
3826:
3827: STATIC int asc_dbglvl = 0;
3828: #endif /* ADVANSYS_DEBUG */
3829:
3830: /* Declaration for Asc Library internal data referenced by driver. */
3831: STATIC PortAddr _asc_def_iop_base[];
3832:
3833:
3834: /*
3835: * --- Driver Function Prototypes
3836: *
3837: * advansys.h contains function prototypes for functions global to Linux.
3838: */
3839:
3840: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3841: STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int);
3842: #endif /* version >= v1.3.0 */
3843: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
3844: STATIC void advansys_interrupt(int, struct pt_regs *);
3845: #else /* version >= v1.3.70 */
3846: STATIC void advansys_interrupt(int, void *, struct pt_regs *);
3847: #endif /* version >= v1.3.70 */
3848: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
3849: STATIC void advansys_select_queue_depths(struct Scsi_Host *,
3850: Scsi_Device *);
3851: #endif /* version >= v1.3.89 */
3852: STATIC void advansys_command_done(Scsi_Cmnd *);
3853: STATIC void asc_scsi_done_list(Scsi_Cmnd *);
3854: STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
3855: STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *);
3856: STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
3857: STATIC int adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *);
3858: STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
3859: STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
3860: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
3861: #ifdef ASC_CONFIG_PCI
3862: STATIC int asc_srch_pci_dev(PCI_DEVICE *);
3863: STATIC uchar asc_scan_method(void);
3864: STATIC int asc_pci_find_dev(PCI_DEVICE *);
3865: STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
3866: STATIC ushort asc_get_cfg_word(PCI_DATA *);
3867: STATIC uchar asc_get_cfg_byte(PCI_DATA *);
3868: STATIC void asc_put_cfg_byte(PCI_DATA *, uchar);
3869: #endif /* ASC_CONFIG_PCI */
3870: #endif /* version < v2.1.93 */
3871: STATIC void asc_enqueue(asc_queue_t *, REQP, int);
3872: STATIC REQP asc_dequeue(asc_queue_t *, int);
3873: STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
3874: STATIC int asc_rmqueue(asc_queue_t *, REQP);
3875: STATIC int asc_isqueued(asc_queue_t *, REQP);
3876: STATIC void asc_execute_queue(asc_queue_t *);
3877: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3878: STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int);
3879: STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
3880: STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
3881: STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
3882: STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
3883: STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
3884: STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
3885: STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
3886: STATIC int asc_prt_line(char *, int, char *fmt, ...);
3887: #endif /* version >= v1.3.0 */
3888:
3889: /* Declaration for Asc Library internal functions reference by driver. */
3890: STATIC int AscFindSignature(PortAddr);
3891: STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
3892:
3893: #ifdef ADVANSYS_STATS
3894: STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int);
3895: #endif /* ADVANSYS_STATS */
3896:
3897: #ifdef ADVANSYS_DEBUG
3898: STATIC void asc_prt_scsi_host(struct Scsi_Host *);
3899: STATIC void asc_prt_scsi_cmnd(Scsi_Cmnd *);
3900: STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
3901: STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
3902: STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
3903: STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
3904: STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
3905: STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
3906: STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
3907: STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
3908: STATIC void asc_prt_hex(char *f, uchar *, int);
3909: #endif /* ADVANSYS_DEBUG */
3910:
3911: #ifdef ADVANSYS_ASSERT
3912: STATIC int interrupts_enabled(void);
3913: #endif /* ADVANSYS_ASSERT */
3914:
3915:
3916: /*
3917: * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
3918: */
3919:
3920: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
3921: /*
3922: * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
3923: *
3924: * *buffer: I/O buffer
3925: * **start: if inout == FALSE pointer into buffer where user read should start
3926: * offset: current offset into a /proc/scsi/advansys/[0...] file
3927: * length: length of buffer
3928: * hostno: Scsi_Host host_no
3929: * inout: TRUE - user is writing; FALSE - user is reading
3930: *
3931: * Return the number of bytes read from or written to a
3932: * /proc/scsi/advansys/[0...] file.
3933: *
3934: * Note: This function uses the per board buffer 'prtbuf' which is
3935: * allocated when the board is initialized in advansys_detect(). The
3936: * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
3937: * used to write to the buffer. The way asc_proc_copy() is written
3938: * if 'prtbuf' is too small it will not be overwritten. Instead the
3939: * user just won't get all the available statistics.
3940: */
3941: int
3942: advansys_proc_info(char *buffer, char **start, off_t offset, int length,
3943: int hostno, int inout)
3944: {
3945: struct Scsi_Host *shp;
3946: asc_board_t *boardp;
3947: int i;
3948: char *cp;
3949: int cplen;
3950: int cnt;
3951: int totcnt;
3952: int leftlen;
3953: char *curbuf;
3954: off_t advoffset;
3955: Scsi_Device *scd;
3956:
3957: ASC_DBG(1, "advansys_proc_info: begin\n");
3958:
3959: /*
3960: * User write not supported.
3961: */
3962: if (inout == TRUE) {
3963: return(-ENOSYS);
3964: }
3965:
3966: /*
3967: * User read of /proc/scsi/advansys/[0...] file.
3968: */
3969:
3970: /* Find the specified board. */
3971: for (i = 0; i < asc_board_count; i++) {
3972: if (asc_host[i]->host_no == hostno) {
3973: break;
3974: }
3975: }
3976: if (i == asc_board_count) {
3977: return(-ENOENT);
3978: }
3979:
3980: shp = asc_host[i];
3981: boardp = ASC_BOARDP(shp);
3982:
3983: /* Copy read data starting at the beginning of the buffer. */
3984: *start = buffer;
3985: curbuf = buffer;
3986: advoffset = 0;
3987: totcnt = 0;
3988: leftlen = length;
3989:
3990: /*
3991: * Get board configuration information.
3992: *
3993: * advansys_info() returns the board string from its own static buffer.
3994: */
3995: cp = (char *) advansys_info(shp);
3996: strcat(cp, "\n");
3997: cplen = strlen(cp);
3998: /* Copy board information. */
3999: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4000: totcnt += cnt;
4001: leftlen -= cnt;
4002: if (leftlen == 0) {
4003: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4004: return totcnt;
4005: }
4006: advoffset += cplen;
4007: curbuf += cnt;
4008:
4009: /*
4010: * Display Wide Board BIOS Information.
4011: */
4012: if (ASC_WIDE_BOARD(boardp)) {
4013: cp = boardp->prtbuf;
4014: cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
4015: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4016: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4017: totcnt += cnt;
4018: leftlen -= cnt;
4019: if (leftlen == 0) {
4020: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4021: return totcnt;
4022: }
4023: advoffset += cplen;
4024: curbuf += cnt;
4025: }
4026:
4027: /*
4028: * Display driver information for each device attached to the board.
4029: */
4030: cp = boardp->prtbuf;
4031: cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
4032: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4033: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4034: totcnt += cnt;
4035: leftlen -= cnt;
4036: if (leftlen == 0) {
4037: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4038: return totcnt;
4039: }
4040: advoffset += cplen;
4041: curbuf += cnt;
4042:
4043: /*
4044: * Display target driver information for each device attached
4045: * to the board.
4046: */
4047: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75)
4048: for (scd = scsi_devices; scd; scd = scd->next)
4049: #else /* version >= v2.1.75 */
4050: for (scd = shp->host_queue; scd; scd = scd->next)
4051: #endif /* version >= v2.1.75 */
4052: {
4053: if (scd->host == shp) {
4054: cp = boardp->prtbuf;
4055: /*
4056: * Note: If proc_print_scsidevice() writes more than
4057: * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'.
4058: */
4059: proc_print_scsidevice(scd, cp, &cplen, 0);
4060: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4061: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4062: totcnt += cnt;
4063: leftlen -= cnt;
4064: if (leftlen == 0) {
4065: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4066: return totcnt;
4067: }
4068: advoffset += cplen;
4069: curbuf += cnt;
4070: }
4071: }
4072:
4073: /*
4074: * Display EEPROM configuration for the board.
4075: */
4076: cp = boardp->prtbuf;
4077: if (ASC_NARROW_BOARD(boardp)) {
4078: cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4079: } else {
4080: cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
4081: }
4082: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4083: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4084: totcnt += cnt;
4085: leftlen -= cnt;
4086: if (leftlen == 0) {
4087: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4088: return totcnt;
4089: }
4090: advoffset += cplen;
4091: curbuf += cnt;
4092:
4093: /*
4094: * Display driver configuration and information for the board.
4095: */
4096: cp = boardp->prtbuf;
4097: cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
4098: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4099: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4100: totcnt += cnt;
4101: leftlen -= cnt;
4102: if (leftlen == 0) {
4103: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4104: return totcnt;
4105: }
4106: advoffset += cplen;
4107: curbuf += cnt;
4108:
4109: #ifdef ADVANSYS_STATS
4110: /*
4111: * Display driver statistics for the board.
4112: */
4113: cp = boardp->prtbuf;
4114: cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
4115: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4116: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4117: totcnt += cnt;
4118: leftlen -= cnt;
4119: if (leftlen == 0) {
4120: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4121: return totcnt;
4122: }
4123: advoffset += cplen;
4124: curbuf += cnt;
4125: #endif /* ADVANSYS_STATS */
4126:
4127: /*
4128: * Display Asc Library dynamic configuration information
4129: * for the board.
4130: */
4131: cp = boardp->prtbuf;
4132: if (ASC_NARROW_BOARD(boardp)) {
4133: cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
4134: } else {
4135: cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
4136: }
4137: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
4138: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
4139: totcnt += cnt;
4140: leftlen -= cnt;
4141: if (leftlen == 0) {
4142: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4143: return totcnt;
4144: }
4145: advoffset += cplen;
4146: curbuf += cnt;
4147:
4148: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
4149:
4150: return totcnt;
4151: }
4152: #endif /* version >= v1.3.0 */
4153:
4154: /*
4155: * advansys_detect()
4156: *
4157: * Detect function for AdvanSys adapters.
4158: *
4159: * Argument is a pointer to the host driver's scsi_hosts entry.
4160: *
4161: * Return number of adapters found.
4162: *
4163: * Note: Because this function is called during system initialization
4164: * it must not call SCSI mid-level functions including scsi_malloc()
4165: * and scsi_free().
4166: */
4167: ASC_INITFUNC(
4168: int
4169: advansys_detect(Scsi_Host_Template *tpnt)
4170: )
4171: {
4172: static int detect_called = ASC_FALSE;
4173: int iop;
4174: int bus;
4175: struct Scsi_Host *shp;
4176: asc_board_t *boardp;
4177: ASC_DVC_VAR *asc_dvc_varp = NULL;
4178: ADV_DVC_VAR *adv_dvc_varp = NULL;
4179: int ioport = 0;
4180: int share_irq = FALSE;
4181: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4182: #ifdef ASC_CONFIG_PCI
4183: PCI_DEVICE pciDevice;
4184: PCI_CONFIG_SPACE pciConfig;
4185: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4186: unsigned long pci_memory_address;
4187: #endif /* version >= v1,3,0 */
4188: #endif /* ASC_CONFIG_PCI */
4189: #else /* version >= v2.1.93 */
4190: #ifdef CONFIG_PCI
4191: struct pci_dev *pci_devp = NULL;
4192: int pci_device_id_cnt = 0;
4193: unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
4194: ASC_PCI_DEVICE_ID_1100,
4195: ASC_PCI_DEVICE_ID_1200,
4196: ASC_PCI_DEVICE_ID_1300,
4197: ASC_PCI_DEVICE_ID_2300
4198: };
4199: unsigned long pci_memory_address;
4200: #endif /* CONFIG_PCI */
4201: #endif /* version >= v2.1.93 */
4202: int warn_code, err_code;
4203: int ret;
4204:
4205: if (detect_called == ASC_FALSE) {
4206: detect_called = ASC_TRUE;
4207: } else {
4208: printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n");
4209: return 0;
4210: }
4211:
4212: ASC_DBG(1, "advansys_detect: begin\n");
4213:
4214: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4215: tpnt->proc_dir = &proc_scsi_advansys;
4216: #endif /* version >= v1.3.0 */
4217:
4218: asc_board_count = 0;
4219:
4220: /*
4221: * If I/O port probing has been modified, then verify and
4222: * clean-up the 'asc_ioport' list.
4223: */
4224: if (asc_iopflag == ASC_TRUE) {
4225: for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
4226: ASC_DBG2(1, "advansys_detect: asc_ioport[%d] %x\n",
4227: ioport, asc_ioport[ioport]);
4228: if (asc_ioport[ioport] != 0) {
4229: for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
4230: if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
4231: break;
4232: }
4233: }
4234: if (iop == ASC_IOADR_TABLE_MAX_IX) {
4235: printk(
4236: "AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
4237: asc_ioport[ioport]);
4238: asc_ioport[ioport] = 0;
4239: }
4240: }
4241: }
4242: ioport = 0;
4243: }
4244:
4245: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4246: #ifdef ASC_CONFIG_PCI
4247: memset(&pciDevice, 0, sizeof(PCI_DEVICE));
4248: memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
4249: pciDevice.maxBusNumber = PCI_MAX_BUS;
4250: pciDevice.endSlot = PCI_MAX_SLOT;
4251: #endif /* ASC_CONFIG_PCI */
4252: #endif /* version < v2.1.93 */
4253:
4254: for (bus = 0; bus < ASC_NUM_BUS; bus++) {
4255:
4256: ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
4257: bus, asc_bus_name[bus]);
4258: iop = 0;
4259:
4260: while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
4261:
4262: ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
4263: asc_board_count);
4264:
4265: switch (asc_bus[bus]) {
4266: case ASC_IS_ISA:
4267: case ASC_IS_VL:
4268: if (asc_iopflag == ASC_FALSE) {
4269: iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
4270: } else {
4271: /*
4272: * ISA and VL I/O port scanning has either been
4273: * eliminated or limited to selected ports on
4274: * the LILO command line, /etc/lilo.conf, or
4275: * by setting variables when the module was loaded.
4276: */
4277: ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
4278: ioport_try_again:
4279: iop = 0;
4280: for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
4281: if ((iop = asc_ioport[ioport]) != 0) {
4282: break;
4283: }
4284: }
4285: if (iop) {
4286: ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
4287: iop);
4288: if (check_region(iop, ASC_IOADR_GAP) != 0) {
4289: printk(
4290: "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
4291: /* Don't try this I/O port twice. */
4292: asc_ioport[ioport] = 0;
4293: goto ioport_try_again;
4294: } else if (AscFindSignature(iop) == ASC_FALSE) {
4295: printk(
4296: "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
4297: /* Don't try this I/O port twice. */
4298: asc_ioport[ioport] = 0;
4299: goto ioport_try_again;
4300: } else {
4301: /*
4302: * If this isn't an ISA board, then it must be
4303: * a VL board. If currently looking an ISA
4304: * board is being looked for then try for
4305: * another ISA board in 'asc_ioport'.
4306: */
4307: if (asc_bus[bus] == ASC_IS_ISA &&
4308: (AscGetChipVersion(iop, ASC_IS_ISA) &
4309: ASC_CHIP_VER_ISA_BIT) == 0) {
4310: /*
4311: * Don't clear 'asc_ioport[ioport]'. Try
4312: * this board again for VL. Increment
4313: * 'ioport' past this board.
4314: */
4315: ioport++;
4316: goto ioport_try_again;
4317: }
4318: }
4319: /*
4320: * This board appears good, don't try the I/O port
4321: * again by clearing its value. Increment 'ioport'
4322: * for the next iteration.
4323: */
4324: asc_ioport[ioport++] = 0;
4325: }
4326: }
4327: break;
4328:
4329: case ASC_IS_EISA:
4330: iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
4331: break;
4332:
4333: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4334: #ifdef ASC_CONFIG_PCI
4335: case ASC_IS_PCI:
4336: if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
4337: iop = 0;
4338: } else {
4339: ASC_DBG2(2,
4340: "advansys_detect: slotFound %d, busNumber %d\n",
4341: pciDevice.slotFound, pciDevice.busNumber);
4342: asc_get_pci_cfg(&pciDevice, &pciConfig);
4343: iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
4344: ASC_DBG2(1,
4345: "advansys_detect: vendorID %X, deviceID %X\n",
4346: pciConfig.vendorID, pciConfig.deviceID);
4347: ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
4348: iop, pciConfig.irqLine);
4349: }
4350: break;
4351: #endif /* ASC_CONFIG_PCI */
4352: #else /* version >= v2.1.93 */
4353: #ifdef CONFIG_PCI
4354: case ASC_IS_PCI:
4355: while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) {
4356: if ((pci_devp = pci_find_device(ASC_PCI_VENDORID,
4357: pci_device_id[pci_device_id_cnt], pci_devp)) == NULL) {
4358: pci_device_id_cnt++;
4359: } else {
4360: break;
4361: }
4362: }
4363: if (pci_devp == NULL) {
4364: iop = 0;
4365: } else {
4366: ASC_DBG2(2,
4367: "advansys_detect: devfn %d, bus number %d\n",
4368: pci_devp->devfn, pci_devp->bus->number);
4369: iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK;
4370: ASC_DBG2(1,
4371: "advansys_detect: vendorID %X, deviceID %X\n",
4372: pci_devp->vendor, pci_devp->device);
4373: ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
4374: iop, pci_devp->irq);
4375: }
4376: break;
4377: #endif /* CONFIG_PCI */
4378: #endif /* version >= v2.1.93 */
4379:
4380: default:
4381: ASC_PRINT1("advansys_detect: unknown bus type: %d\n",
4382: asc_bus[bus]);
4383: break;
4384: }
4385: ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
4386:
4387: /*
4388: * Adapter not found, try next bus type.
4389: */
4390: if (iop == 0) {
4391: break;
4392: }
4393:
4394: /*
4395: * Adapter found.
4396: *
4397: * Register the adapter, get its configuration, and
4398: * initialize it.
4399: */
4400: ASC_DBG(2, "advansys_detect: scsi_register()\n");
4401: shp = scsi_register(tpnt, sizeof(asc_board_t));
4402:
4403: /* Save a pointer to the Scsi_host of each board found. */
4404: asc_host[asc_board_count++] = shp;
4405:
4406: /* Initialize private per board data */
4407: boardp = ASC_BOARDP(shp);
4408: memset(boardp, 0, sizeof(asc_board_t));
4409: boardp->id = asc_board_count - 1;
4410:
4411: /*
4412: * Handle both narrow and wide boards.
4413: *
4414: * If a Wide board was detected, set the board structure
4415: * wide board flag. Set-up the board structure based on
4416: * the board type.
4417: */
4418: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4419: #ifdef ASC_CONFIG_PCI
4420: if (asc_bus[bus] == ASC_IS_PCI &&
4421: pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) {
4422: boardp->flags |= ASC_IS_WIDE_BOARD;
4423: }
4424: #endif /* ASC_CONFIG_PCI */
4425: #else /* version >= v2.1.93 */
4426: #ifdef CONFIG_PCI
4427: if (asc_bus[bus] == ASC_IS_PCI &&
4428: pci_devp->device == ASC_PCI_DEVICE_ID_2300) {
4429: boardp->flags |= ASC_IS_WIDE_BOARD;
4430: }
4431: #endif /* CONFIG_PCI */
4432: #endif /* version >= v2.1.93 */
4433:
4434: if (ASC_NARROW_BOARD(boardp)) {
4435: ASC_DBG(1, "advansys_detect: narrow board\n");
4436: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4437: asc_dvc_varp->bus_type = asc_bus[bus];
4438: asc_dvc_varp->drv_ptr = (ulong) boardp;
4439: asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
4440: asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
4441: asc_dvc_varp->iop_base = iop;
4442: asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback;
4443: } else {
4444: ASC_DBG(1, "advansys_detect: wide board\n");
4445: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4446: adv_dvc_varp->drv_ptr = (ulong) boardp;
4447: adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
4448: adv_dvc_varp->isr_callback = (Ptr2Func) adv_isr_callback;
4449:
4450: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
4451: adv_dvc_varp->iop_base = iop;
4452: #else /* version >= v1,3,0 */
4453: /*
4454: * Map the board's registers into virtual memory for
4455: * PCI slave access. Only memory accesses are used to
4456: * access the board's registers.
4457: *
4458: * Note: The PCI register base address is not always
4459: * page aligned, but the address passed to ioremap()
4460: * must be page aligned. It is guaranteed that the
4461: * PCI register base address will not cross a page
4462: * boundary.
4463: */
4464: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4465: #ifdef ASC_CONFIG_PCI
4466: pci_memory_address = pciConfig.baseAddress[1];
4467: if ((boardp->ioremap_addr =
4468: ioremap(pci_memory_address & PAGE_MASK,
4469: PAGE_SIZE)) == 0) {
4470: ASC_PRINT3(
4471: "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
4472: boardp->id, pci_memory_address, ADV_CONDOR_IOLEN);
4473: scsi_unregister(shp);
4474: asc_board_count--;
4475: continue;
4476: }
4477: adv_dvc_varp->iop_base = (AdvPortAddr)
4478: (boardp->ioremap_addr +
4479: (pci_memory_address - (pci_memory_address & PAGE_MASK)));
4480: #endif /* ASC_CONFIG_PCI */
4481: #else /* version >= v2.1.93 */
4482: #ifdef CONFIG_PCI
4483: pci_memory_address = pci_devp->base_address[1];
4484: if ((boardp->ioremap_addr =
4485: ioremap(pci_memory_address & PAGE_MASK,
4486: PAGE_SIZE)) == 0) {
4487: ASC_PRINT3(
4488: "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
4489: boardp->id, pci_memory_address, ADV_CONDOR_IOLEN);
4490: scsi_unregister(shp);
4491: asc_board_count--;
4492: continue;
4493: }
4494: adv_dvc_varp->iop_base = (AdvPortAddr)
4495: (boardp->ioremap_addr +
4496: (pci_memory_address - (pci_memory_address & PAGE_MASK)));
4497: #endif /* CONFIG_PCI */
4498: #endif /* version >= v2.1.93 */
4499: #endif /* version >= v1,3,0 */
4500:
4501: /*
4502: * Even though it isn't used to access the board in
4503: * kernels greater than or equal to v1.3.0, save
4504: * the I/O Port address so that it can be reported and
4505: * displayed.
4506: */
4507: boardp->ioport = iop;
4508: }
4509:
4510: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4511: /*
4512: * Allocate buffer for printing information from
4513: * /proc/scsi/advansys/[0...].
4514: */
4515: if ((boardp->prtbuf =
4516: kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
4517: ASC_PRINT3(
4518: "advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n",
4519: boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
4520: scsi_unregister(shp);
4521: asc_board_count--;
4522: continue;
4523: }
4524: #endif /* version >= v1.3.0 */
4525:
4526: if (ASC_NARROW_BOARD(boardp)) {
4527: /*
4528: * Set the board bus type and PCI IRQ before
4529: * calling AscInitGetConfig().
4530: */
4531: switch (asc_dvc_varp->bus_type) {
4532: case ASC_IS_ISA:
4533: shp->unchecked_isa_dma = TRUE;
4534: share_irq = FALSE;
4535: break;
4536: case ASC_IS_VL:
4537: shp->unchecked_isa_dma = FALSE;
4538: share_irq = FALSE;
4539: break;
4540: case ASC_IS_EISA:
4541: shp->unchecked_isa_dma = FALSE;
4542: share_irq = TRUE;
4543: break;
4544: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4545: #ifdef ASC_CONFIG_PCI
4546: case ASC_IS_PCI:
4547: shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine;
4548: asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
4549: asc_dvc_varp->cfg->pci_slot_info =
4550: ASC_PCI_MKID(pciDevice.busNumber,
4551: pciDevice.slotFound,
4552: pciDevice.devFunc);
4553: shp->unchecked_isa_dma = FALSE;
4554: share_irq = TRUE;
4555: break;
4556: #endif /* ASC_CONFIG_PCI */
4557: #else /* version >= v2.1.93 */
4558: #ifdef CONFIG_PCI
4559: case ASC_IS_PCI:
4560: shp->irq = asc_dvc_varp->irq_no = pci_devp->irq;
4561: asc_dvc_varp->cfg->pci_device_id = pci_devp->device;
4562: asc_dvc_varp->cfg->pci_slot_info =
4563: ASC_PCI_MKID(pci_devp->bus->number,
4564: PCI_SLOT(pci_devp->devfn),
4565: PCI_FUNC(pci_devp->devfn));
4566: shp->unchecked_isa_dma = FALSE;
4567: share_irq = TRUE;
4568: break;
4569: #endif /* CONFIG_PCI */
4570: #endif /* version >= v2.1.93 */
4571: default:
4572: ASC_PRINT2(
4573: "advansys_detect: board %d: unknown adapter type: %d\n",
4574: boardp->id, asc_dvc_varp->bus_type);
4575: shp->unchecked_isa_dma = TRUE;
4576: share_irq = FALSE;
4577: break;
4578: }
4579: } else {
4580: /*
4581: * For Wide boards set PCI information before calling
4582: * AdvInitGetConfig().
4583: */
4584: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
4585: #ifdef ASC_CONFIG_PCI
4586: shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine;
4587: adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
4588: adv_dvc_varp->cfg->pci_slot_info =
4589: ASC_PCI_MKID(pciDevice.busNumber,
4590: pciDevice.slotFound,
4591: pciDevice.devFunc);
4592: shp->unchecked_isa_dma = FALSE;
4593: share_irq = TRUE;
4594: #endif /* ASC_CONFIG_PCI */
4595: #else /* version >= v2.1.93 */
4596: #ifdef CONFIG_PCI
4597: shp->irq = adv_dvc_varp->irq_no = pci_devp->irq;
4598: adv_dvc_varp->cfg->pci_device_id = pci_devp->device;
4599: adv_dvc_varp->cfg->pci_slot_info =
4600: ASC_PCI_MKID(pci_devp->bus->number,
4601: PCI_SLOT(pci_devp->devfn),
4602: PCI_FUNC(pci_devp->devfn));
4603: shp->unchecked_isa_dma = FALSE;
4604: share_irq = TRUE;
4605: #endif /* CONFIG_PCI */
4606: #endif /* version >= v2.1.93 */
4607: }
4608:
4609: /*
4610: * Read the board configuration.
4611: */
4612: if (ASC_NARROW_BOARD(boardp)) {
4613: /*
4614: * NOTE: AscInitGetConfig() may change the board's
4615: * bus_type value. The asc_bus[bus] value should no
4616: * longer be used. If the bus_type field must be
4617: * referenced only use the bit-wise AND operator "&".
4618: */
4619: ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
4620: switch(ret = AscInitGetConfig(asc_dvc_varp)) {
4621: case 0: /* No error */
4622: break;
4623: case ASC_WARN_IO_PORT_ROTATE:
4624: ASC_PRINT1(
4625: "AscInitGetConfig: board %d: I/O port address modified\n",
4626: boardp->id);
4627: break;
4628: case ASC_WARN_AUTO_CONFIG:
4629: ASC_PRINT1(
4630: "AscInitGetConfig: board %d: I/O port increment switch enabled\n",
4631: boardp->id);
4632: break;
4633: case ASC_WARN_EEPROM_CHKSUM:
4634: ASC_PRINT1(
4635: "AscInitGetConfig: board %d: EEPROM checksum error\n",
4636: boardp->id);
4637: break;
4638: case ASC_WARN_IRQ_MODIFIED:
4639: ASC_PRINT1(
4640: "AscInitGetConfig: board %d: IRQ modified\n",
4641: boardp->id);
4642: break;
4643: case ASC_WARN_CMD_QNG_CONFLICT:
4644: ASC_PRINT1(
4645: "AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
4646: boardp->id);
4647: break;
4648: default:
4649: ASC_PRINT2(
4650: "AscInitGetConfig: board %d: unknown warning: %x\n",
4651: boardp->id, ret);
4652: break;
4653: }
4654: if ((err_code = asc_dvc_varp->err_code) != 0) {
4655: ASC_PRINT3(
4656: "AscInitGetConfig: board %d error: init_state %x, err_code %x\n",
4657: boardp->id, asc_dvc_varp->init_state,
4658: asc_dvc_varp->err_code);
4659: }
4660: } else {
4661: ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n");
4662: if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
4663: ASC_PRINT2("AdvInitGetConfig: board %d: warning: %x\n",
4664: boardp->id, ret);
4665: }
4666: if ((err_code = adv_dvc_varp->err_code) != 0) {
4667: ASC_PRINT2(
4668: "AdvInitGetConfig: board %d error: err_code %x\n",
4669: boardp->id, adv_dvc_varp->err_code);
4670: }
4671: }
4672:
4673: if (err_code != 0) {
4674: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4675: kfree(boardp->prtbuf);
4676: #endif /* version >= v1.3.0 */
4677: scsi_unregister(shp);
4678: asc_board_count--;
4679: continue;
4680: }
4681:
4682: /*
4683: * Save the EEPROM configuration so that it can be displayed
4684: * from /proc/scsi/advansys/[0...].
4685: */
4686: if (ASC_NARROW_BOARD(boardp)) {
4687:
4688: ASCEEP_CONFIG *ep;
4689:
4690: /*
4691: * Set the adapter's target id bit in the 'init_tidmask' field.
4692: */
4693: boardp->init_tidmask |=
4694: ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
4695:
4696: /*
4697: * Save EEPROM settings for the board.
4698: */
4699: ep = &boardp->eep_config.asc_eep;
4700:
4701: ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
4702: ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
4703: ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
4704: ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed;
4705: ep->start_motor = asc_dvc_varp->start_motor;
4706: ep->cntl = asc_dvc_varp->dvc_cntl;
4707: ep->no_scam = asc_dvc_varp->no_scam;
4708: ep->max_total_qng = asc_dvc_varp->max_total_qng;
4709: ep->chip_scsi_id = asc_dvc_varp->cfg->chip_scsi_id;
4710: /* 'max_tag_qng' is set to the same value for every device. */
4711: ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
4712: ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
4713: ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
4714: ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
4715: ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
4716: ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
4717: ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
4718: ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6];
4719:
4720: /*
4721: * Modify board configuration.
4722: */
4723: ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
4724: switch (ret = AscInitSetConfig(asc_dvc_varp)) {
4725: case 0: /* No error. */
4726: break;
4727: case ASC_WARN_IO_PORT_ROTATE:
4728: ASC_PRINT1(
4729: "AscInitSetConfig: board %d: I/O port address modified\n",
4730: boardp->id);
4731: break;
4732: case ASC_WARN_AUTO_CONFIG:
4733: ASC_PRINT1(
4734: "AscInitSetConfig: board %d: I/O port increment switch enabled\n",
4735: boardp->id);
4736: break;
4737: case ASC_WARN_EEPROM_CHKSUM:
4738: ASC_PRINT1(
4739: "AscInitSetConfig: board %d: EEPROM checksum error\n",
4740: boardp->id);
4741: break;
4742: case ASC_WARN_IRQ_MODIFIED:
4743: ASC_PRINT1(
4744: "AscInitSetConfig: board %d: IRQ modified\n",
4745: boardp->id);
4746: break;
4747: case ASC_WARN_CMD_QNG_CONFLICT:
4748: ASC_PRINT1(
4749: "AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
4750: boardp->id);
4751: break;
4752: default:
4753: ASC_PRINT2(
4754: "AscInitSetConfig: board %d: unknown warning: %x\n",
4755: boardp->id, ret);
4756: break;
4757: }
4758: if (asc_dvc_varp->err_code != 0) {
4759: ASC_PRINT3(
4760: "AscInitSetConfig: board %d error: init_state %x, err_code %x\n",
4761: boardp->id, asc_dvc_varp->init_state,
4762: asc_dvc_varp->err_code);
4763: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4764: kfree(boardp->prtbuf);
4765: #endif /* version >= v1.3.0 */
4766: scsi_unregister(shp);
4767: asc_board_count--;
4768: continue;
4769: }
4770:
4771: /*
4772: * Finish initializing the 'Scsi_Host' structure.
4773: */
4774: /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
4775: if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
4776: shp->irq = asc_dvc_varp->irq_no;
4777: }
4778: } else {
4779:
4780: ADVEEP_CONFIG *ep;
4781:
4782: /*
4783: * Save Wide EEP Configuration Information.
4784: */
4785: ep = &boardp->eep_config.adv_eep;
4786:
4787: ep->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
4788: ep->max_host_qng = adv_dvc_varp->max_host_qng;
4789: ep->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
4790: ep->termination = adv_dvc_varp->cfg->termination;
4791: ep->disc_enable = adv_dvc_varp->cfg->disc_enable;
4792: ep->bios_ctrl = adv_dvc_varp->bios_ctrl;
4793: ep->wdtr_able = adv_dvc_varp->wdtr_able;
4794: ep->sdtr_able = adv_dvc_varp->sdtr_able;
4795: ep->ultra_able = adv_dvc_varp->ultra_able;
4796: ep->tagqng_able = adv_dvc_varp->tagqng_able;
4797: ep->start_motor = adv_dvc_varp->start_motor;
4798: ep->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait;
4799: ep->bios_boot_delay = adv_dvc_varp->cfg->bios_boot_wait;
4800: ep->serial_number_word1 = adv_dvc_varp->cfg->serial1;
4801: ep->serial_number_word2 = adv_dvc_varp->cfg->serial2;
4802: ep->serial_number_word3 = adv_dvc_varp->cfg->serial3;
4803:
4804: /*
4805: * Set the adapter's target id bit in the 'init_tidmask' field.
4806: */
4807: boardp->init_tidmask |=
4808: ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
4809:
4810: /*
4811: * Finish initializing the 'Scsi_Host' structure.
4812: */
4813: shp->irq = adv_dvc_varp->irq_no;
4814: }
4815:
4816: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
4817: /*
4818: * Channels are numbered beginning with 0. For AdvanSys One host
4819: * structure supports one channel. Multi-channel boards have a
4820: * separate host structure for each channel.
4821: */
4822: shp->max_channel = 0;
4823: #endif /* version >= v1.3.89 */
4824: if (ASC_NARROW_BOARD(boardp)) {
4825: shp->max_id = ASC_MAX_TID + 1;
4826: shp->max_lun = ASC_MAX_LUN + 1;
4827:
4828: shp->io_port = asc_dvc_varp->iop_base;
4829: shp->n_io_port = ASC_IOADR_GAP;
4830: shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
4831:
4832: /* Set maximum number of queues the adapter can handle. */
4833: shp->can_queue = asc_dvc_varp->max_total_qng;
4834: } else {
4835: shp->max_id = ADV_MAX_TID + 1;
4836: shp->max_lun = ADV_MAX_LUN + 1;
4837:
4838: /*
4839: * Save the I/O Port address and length even though the
4840: * in v1.3.0 and greater kernels the region is not used
4841: * by a Wide board. Instead the board is accessed with
4842: * Memory Mapped I/O.
4843: */
4844: shp->io_port = iop;
4845: shp->n_io_port = ADV_CONDOR_IOLEN;
4846:
4847: shp->this_id = adv_dvc_varp->chip_scsi_id;
4848:
4849: /* Set maximum number of queues the adapter can handle. */
4850: shp->can_queue = adv_dvc_varp->max_host_qng;
4851: }
4852:
4853: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
4854: /*
4855: * In old kernels without tag queuing support and with memory
4856: * allocation problems set a conservative 'cmd_per_lun' value.
4857: */
4858: #ifdef MODULE
4859: shp->cmd_per_lun = 1;
4860: #else /* MODULE */
4861: shp->cmd_per_lun = 4;
4862: #endif /* MODULE */
4863: ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
4864: #else /* version >= v1.3.89 */
4865: /*
4866: * Following v1.3.89, 'cmd_per_lun' is no longer needed
4867: * and should be set to zero.
4868: *
4869: * But because of a bug introduced in v1.3.89 if the driver is
4870: * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
4871: * SCSI function 'allocate_device' will panic. To allow the driver
4872: * to work as a module in these kernels set 'cmd_per_lun' to 1.
4873: */
4874: #ifdef MODULE
4875: shp->cmd_per_lun = 1;
4876: #else /* MODULE */
4877: shp->cmd_per_lun = 0;
4878: #endif /* MODULE */
4879: /*
4880: * Use the host 'select_queue_depths' function to determine
4881: * the number of commands to queue per device.
4882: */
4883: shp->select_queue_depths = advansys_select_queue_depths;
4884: #endif /* version >= v1.3.89 */
4885:
4886: /*
4887: * Set the maximum number of scatter-gather elements the
4888: * adapter can handle.
4889: */
4890: if (ASC_NARROW_BOARD(boardp)) {
4891: /*
4892: * Allow two commands with 'sg_tablesize' scatter-gather
4893: * elements to be executed simultaneously. This value is
4894: * the theoretical hardware limit. It may be decreased
4895: * below.
4896: */
4897: shp->sg_tablesize =
4898: (((asc_dvc_varp->max_total_qng - 2) / 2) *
4899: ASC_SG_LIST_PER_Q) + 1;
4900: } else {
4901: shp->sg_tablesize = ADV_MAX_SG_LIST;
4902: }
4903:
4904: #ifdef MODULE
4905: /*
4906: * If the driver is compiled as a module, set a limit on the
4907: * 'sg_tablesize' value to prevent memory allocation failures.
4908: * Memory allocation errors are more likely to occur at module
4909: * load time, then at driver initialization time.
4910: */
4911: if (shp->sg_tablesize > 64) {
4912: shp->sg_tablesize = 64;
4913: }
4914: #endif /* MODULE */
4915:
4916: /*
4917: * The value of 'sg_tablesize' can not exceed the SCSI
4918: * mid-level driver definition of SG_ALL. SG_ALL also
4919: * must not be exceeded, because it is used to define the
4920: * size of the scatter-gather table in 'struct asc_sg_head'.
4921: */
4922: if (shp->sg_tablesize > SG_ALL) {
4923: shp->sg_tablesize = SG_ALL;
4924: }
4925:
4926: ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
4927: shp->sg_tablesize);
4928:
4929: /* BIOS start address. */
4930: if (ASC_NARROW_BOARD(boardp)) {
4931: shp->base = (char *) ((ulong) AscGetChipBiosAddress(
4932: asc_dvc_varp->iop_base,
4933: asc_dvc_varp->bus_type));
4934: } else {
4935: /*
4936: * Fill-in BIOS board variables. The Wide BIOS saves
4937: * information in LRAM that is used by the driver.
4938: */
4939: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE,
4940: boardp->bios_signature);
4941: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION,
4942: boardp->bios_version);
4943: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG,
4944: boardp->bios_codeseg);
4945: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN,
4946: boardp->bios_codelen);
4947:
4948: ASC_DBG2(1,
4949: "advansys_detect: bios_signature %x, bios_version %x\n",
4950: boardp->bios_signature, boardp->bios_version);
4951:
4952: ASC_DBG2(1,
4953: "advansys_detect: bios_codeseg %x, bios_codelen %x\n",
4954: boardp->bios_codeseg, boardp->bios_codelen);
4955:
4956: /*
4957: * If the BIOS saved a valid signature, then fill in
4958: * the BIOS code segment base address.
4959: */
4960: if (boardp->bios_signature == 0x55AA) {
4961: /*
4962: * Convert x86 realmode code segment to a linear
4963: * address by shifting left 4.
4964: */
4965: shp->base = (uchar *) (boardp->bios_codeseg << 4);
4966: } else {
4967: shp->base = 0;
4968: }
4969: }
4970:
4971: /*
4972: * Register Board Resources - I/O Port, DMA, IRQ
4973: */
4974:
4975: /* Register I/O port range. */
4976: ASC_DBG(2, "advansys_detect: request_region()\n");
4977: request_region(shp->io_port, shp->n_io_port, "advansys");
4978:
4979: /* Register DMA Channel for Narrow boards. */
4980: shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
4981: if (ASC_NARROW_BOARD(boardp)) {
4982: /* Register DMA channel for ISA bus. */
4983: if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4984: shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
4985: if ((ret =
4986: request_dma(shp->dma_channel, "advansys")) != 0) {
4987: ASC_PRINT3(
4988: "advansys_detect: board %d: request_dma() %d failed %d\n",
4989: boardp->id, shp->dma_channel, ret);
4990: release_region(shp->io_port, shp->n_io_port);
4991: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4992: kfree(boardp->prtbuf);
4993: #endif /* version >= v1.3.0 */
4994: scsi_unregister(shp);
4995: asc_board_count--;
4996: continue;
4997: }
4998: AscEnableIsaDma(shp->dma_channel);
4999: }
5000: }
5001:
5002: /* Register IRQ Number. */
5003: ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
5004: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5005: if ((ret = request_irq(shp->irq, advansys_interrupt,
5006: SA_INTERRUPT, "advansys")) != 0)
5007: #else /* version >= v1.3.70 */
5008: /*
5009: * If request_irq() fails with the SA_INTERRUPT flag set,
5010: * then try again without the SA_INTERRUPT flag set. This
5011: * allows IRQ sharing to work even with other drivers that
5012: * do not set the SA_INTERRUPT flag.
5013: *
5014: * If SA_INTERRUPT is not set, then interrupts are enabled
5015: * before the driver interrupt function is called.
5016: */
5017: if (((ret = request_irq(shp->irq, advansys_interrupt,
5018: SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
5019: "advansys", boardp)) != 0) &&
5020: ((ret = request_irq(shp->irq, advansys_interrupt,
5021: (share_irq == TRUE ? SA_SHIRQ : 0),
5022: "advansys", boardp)) != 0))
5023: #endif /* version >= v1.3.70 */
5024: {
5025: if (ret == -EBUSY) {
5026: ASC_PRINT2(
5027: "advansys_detect: board %d: request_irq(): IRQ %d already in use.\n",
5028: boardp->id, shp->irq);
5029: } else if (ret == -EINVAL) {
5030: ASC_PRINT2(
5031: "advansys_detect: board %d: request_irq(): IRQ %d not valid.\n",
5032: boardp->id, shp->irq);
5033: } else {
5034: ASC_PRINT3(
5035: "advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n",
5036: boardp->id, shp->irq, ret);
5037: }
5038: release_region(shp->io_port, shp->n_io_port);
5039: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5040: iounmap(boardp->ioremap_addr);
5041: #endif /* version >= v1,3,0 */
5042: if (shp->dma_channel != NO_ISA_DMA) {
5043: free_dma(shp->dma_channel);
5044: }
5045: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5046: kfree(boardp->prtbuf);
5047: #endif /* version >= v1.3.0 */
5048: scsi_unregister(shp);
5049: asc_board_count--;
5050: continue;
5051: }
5052:
5053: /*
5054: * Initialize board RISC chip and enable interrupts.
5055: */
5056: if (ASC_NARROW_BOARD(boardp)) {
5057: ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
5058: warn_code = AscInitAsc1000Driver(asc_dvc_varp);
5059: err_code = asc_dvc_varp->err_code;
5060:
5061: if (warn_code || err_code) {
5062: ASC_PRINT4(
5063: "AscInitAsc1000Driver: board %d: error: init_state %x, warn %x error %x\n",
5064: boardp->id, asc_dvc_varp->init_state,
5065: warn_code, err_code);
5066: }
5067: } else {
5068: int req_cnt;
5069: adv_req_t *reqp = NULL;
5070: int sg_cnt;
5071: adv_sgblk_t *sgp = NULL;
5072:
5073: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
5074: req_cnt = sizeof(adv_req_buf)/sizeof(adv_req_t);
5075: sg_cnt = sizeof(adv_sgblk_buf)/sizeof(adv_sgblk_t);
5076: reqp = (adv_req_t *) &adv_req_buf[0];
5077: sgp = (adv_sgblk_t *) &adv_sgblk_buf[0];
5078: #else /* version >= v1.3.0 */
5079: /*
5080: * Allocate up to 'max_host_qng' request structures for
5081: * the Wide board.
5082: */
5083: for (req_cnt = adv_dvc_varp->max_host_qng;
5084: req_cnt > 0; req_cnt--) {
5085:
5086: reqp = (adv_req_t *)
5087: kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
5088:
5089: ASC_DBG3(1,
5090: "advansys_detect: reqp %x, req_cnt %d, bytes %d\n",
5091: (unsigned) reqp, req_cnt, sizeof(adv_req_t) * req_cnt);
5092:
5093: if (reqp != NULL) {
5094: break;
5095: }
5096: }
5097:
5098: /*
5099: * Allocate up to ADV_TOT_SG_LIST request structures for
5100: * the Wide board.
5101: */
5102: for (sg_cnt = ADV_TOT_SG_LIST; sg_cnt > 0; sg_cnt--) {
5103:
5104: sgp = (adv_sgblk_t *)
5105: kmalloc(sizeof(adv_sgblk_t) * sg_cnt, GFP_ATOMIC);
5106:
5107: ASC_DBG3(1,
5108: "advansys_detect: sgp %x, sg_cnt %d, bytes %d\n",
5109: (unsigned) sgp, sg_cnt, sizeof(adv_sgblk_t) * sg_cnt);
5110:
5111: if (sgp != NULL) {
5112: break;
5113: }
5114: }
5115: #endif /* version >= v1.3.0 */
5116:
5117: /*
5118: * If no request structures or scatter-gather structures could
5119: * be allocated, then return an error. Otherwise continue with
5120: * initialization.
5121: */
5122: if (reqp == NULL) {
5123: ASC_PRINT1(
5124: "advansys_detect: board %d: error: failed to kmalloc() adv_req_t buffer.\n",
5125: boardp->id);
5126: err_code = ADV_ERROR;
5127: } else if (sgp == NULL) {
5128: kfree(reqp);
5129: ASC_PRINT1(
5130: "advansys_detect: board %d: error: failed to kmalloc() adv_sgblk_t buffer.\n",
5131: boardp->id);
5132: err_code = ADV_ERROR;
5133: } else {
5134:
5135: /*
5136: * Save original pointer for kfree() in case the
5137: * driver is built as a module and can be unloaded.
5138: */
5139: boardp->orig_reqp = reqp;
5140:
5141: /*
5142: * Point 'adv_reqp' to the request structures and
5143: * link them together.
5144: */
5145: req_cnt--;
5146: reqp[req_cnt].next_reqp = NULL;
5147: for (; req_cnt > 0; req_cnt--) {
5148: reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
5149: }
5150: boardp->adv_reqp = &reqp[0];
5151:
5152: /*
5153: * Save original pointer for kfree() in case the
5154: * driver is built as a module and can be unloaded.
5155: */
5156: boardp->orig_sgblkp = sgp;
5157:
5158: /*
5159: * Point 'adv_sgblkp' to the request structures and
5160: * link them together.
5161: */
5162: sg_cnt--;
5163: sgp[sg_cnt].next_sgblkp = NULL;
5164: for (; sg_cnt > 0; sg_cnt--) {
5165: sgp[sg_cnt - 1].next_sgblkp = &sgp[sg_cnt];
5166: }
5167: boardp->adv_sgblkp = &sgp[0];
5168:
5169: ASC_DBG(2, "advansys_detect: AdvInitAsc3550Driver()\n");
5170: warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
5171: err_code = adv_dvc_varp->err_code;
5172:
5173: if (warn_code || err_code) {
5174: ASC_PRINT3(
5175: "AdvInitAsc3550Driver: board %d: error: warn %x, error %x\n",
5176: boardp->id, warn_code, adv_dvc_varp->err_code);
5177: }
5178: }
5179: }
5180:
5181: if (err_code != 0) {
5182: release_region(shp->io_port, shp->n_io_port);
5183: if (ASC_WIDE_BOARD(boardp)) {
5184: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5185: iounmap(boardp->ioremap_addr);
5186: #endif /* version >= v1,3,0 */
5187: if (boardp->orig_reqp) {
5188: kfree(boardp->orig_reqp);
5189: boardp->orig_reqp = boardp->adv_reqp = NULL;
5190: }
5191: if (boardp->orig_sgblkp) {
5192: kfree(boardp->orig_sgblkp);
5193: boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5194: }
5195: }
5196: if (shp->dma_channel != NO_ISA_DMA) {
5197: free_dma(shp->dma_channel);
5198: }
5199: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5200: kfree(boardp->prtbuf);
5201: #endif /* version >= v1.3.0 */
5202: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5203: free_irq(shp->irq);
5204: #else /* version >= v1.3.70 */
5205: free_irq(shp->irq, boardp);
5206: #endif /* version >= v1.3.70 */
5207: scsi_unregister(shp);
5208: asc_board_count--;
5209: continue;
5210: }
5211: ASC_DBG_PRT_SCSI_HOST(2, shp);
5212: }
5213: }
5214: ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
5215: return asc_board_count;
5216: }
5217:
5218: /*
5219: * advansys_release()
5220: *
5221: * Release resources allocated for a single AdvanSys adapter.
5222: */
5223: int
5224: advansys_release(struct Scsi_Host *shp)
5225: {
5226: asc_board_t *boardp;
5227:
5228: ASC_DBG(1, "advansys_release: begin\n");
5229: boardp = ASC_BOARDP(shp);
5230: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5231: free_irq(shp->irq);
5232: #else /* version >= v1.3.70 */
5233: free_irq(shp->irq, boardp);
5234: #endif /* version >= v1.3.70 */
5235: if (shp->dma_channel != NO_ISA_DMA) {
5236: ASC_DBG(1, "advansys_release: free_dma()\n");
5237: free_dma(shp->dma_channel);
5238: }
5239: release_region(shp->io_port, shp->n_io_port);
5240: if (ASC_WIDE_BOARD(boardp)) {
5241: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5242: iounmap(boardp->ioremap_addr);
5243: #endif /* version >= v1,3,0 */
5244: if (boardp->orig_reqp) {
5245: kfree(boardp->orig_reqp);
5246: boardp->orig_reqp = boardp->adv_reqp = NULL;
5247: }
5248: if (boardp->orig_sgblkp) {
5249: kfree(boardp->orig_sgblkp);
5250: boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5251: }
5252: }
5253: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5254: ASC_ASSERT(boardp->prtbuf != NULL);
5255: kfree(boardp->prtbuf);
5256: #endif /* version >= v1.3.0 */
5257: scsi_unregister(shp);
5258: ASC_DBG(1, "advansys_release: end\n");
5259: return 0;
5260: }
5261:
5262: /*
5263: * advansys_info()
5264: *
5265: * Return suitable for printing on the console with the argument
5266: * adapter's configuration information.
5267: *
5268: * Note: The information line should not exceed ASC_INFO_SIZE bytes,
5269: * otherwise the static 'info' array will be overrun.
5270: */
5271: const char *
5272: advansys_info(struct Scsi_Host *shp)
5273: {
5274: static char info[ASC_INFO_SIZE];
5275: asc_board_t *boardp;
5276: ASC_DVC_VAR *asc_dvc_varp;
5277: ADV_DVC_VAR *adv_dvc_varp;
5278: char *busname;
5279:
5280: boardp = ASC_BOARDP(shp);
5281: if (ASC_NARROW_BOARD(boardp)) {
5282: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5283: ASC_DBG(1, "advansys_info: begin\n");
5284: if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
5285: if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
5286: busname = "ISA PnP";
5287: } else {
5288: busname = "ISA";
5289: }
5290: sprintf(info,
5291: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5292: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u",
5293: #else /* version >= v2.1.92 */
5294: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u",
5295: #endif /* version >= v2.1.92 */
5296: ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5297: (unsigned) shp->base,
5298: shp->io_port, shp->n_io_port - 1,
5299: shp->irq, shp->dma_channel);
5300: } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
5301: if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
5302: == ASC_IS_PCI_ULTRA) {
5303: busname = "PCI Ultra";
5304: } else {
5305: busname = "PCI";
5306: }
5307: sprintf(info,
5308: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5309: "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u",
5310: #else /* version >= v2.1.92 */
5311: "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u",
5312: #endif /* version >= v2.1.92 */
5313: ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5314: shp->io_port, shp->n_io_port - 1, shp->irq);
5315: } else {
5316: if (asc_dvc_varp->bus_type & ASC_IS_VL) {
5317: busname = "VL";
5318: } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
5319: busname = "EISA";
5320: } else {
5321: busname = "?";
5322: ASC_PRINT2(
5323: "advansys_info: board %d: unknown bus type %d\n",
5324: boardp->id, asc_dvc_varp->bus_type);
5325: }
5326: sprintf(info,
5327: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5328: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u",
5329: #else /* version >= v2.1.92 */
5330: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u",
5331: #endif /* version >= v2.1.92 */
5332: ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5333: (unsigned) shp->base, shp->io_port - 1,
5334: shp->n_io_port, shp->irq);
5335: }
5336: } else {
5337: /*
5338: * Wide Adapter Information
5339: *
5340: * Memory-mapped I/O is used instead of I/O space to access
5341: * the adapter, but display the I/O Port range. The Memory
5342: * I/O address is displayed through the driver /proc file.
5343: */
5344: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5345: if (boardp->bios_signature == 0x55AA) {
5346: sprintf(info,
5347: "AdvanSys SCSI %s: PCI Ultra-Wide: BIOS %X/%X, IO %X/%X, IRQ %u",
5348: ASC_VERSION,
5349: boardp->bios_codeseg << 4,
5350: boardp->bios_codelen > 0 ?
5351: (boardp->bios_codelen << 9) - 1 : 0,
5352: (unsigned) boardp->ioport, ADV_CONDOR_IOLEN - 1,
5353: shp->irq);
5354: } else {
5355: sprintf(info,
5356: "AdvanSys SCSI %s: PCI Ultra-Wide: IO %X/%X, IRQ %u",
5357: ASC_VERSION,
5358: (unsigned) boardp->ioport,
5359: (ADV_CONDOR_IOLEN - 1),
5360: shp->irq);
5361: }
5362: }
5363: ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
5364: ASC_DBG(1, "advansys_info: end\n");
5365: return info;
5366: }
5367:
5368: /*
5369: * advansys_command() - polled I/O entrypoint.
5370: *
5371: * Apparently host drivers shouldn't return until the command
5372: * is finished.
5373: *
5374: * Note: This is an old interface that is no longer used by the SCSI
5375: * mid-level driver. The new interface, advansys_queuecommand(),
5376: * currently handles all requests.
5377: */
5378: int
5379: advansys_command(Scsi_Cmnd *scp)
5380: {
5381: ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
5382: ASC_STATS(scp->host, command);
5383: scp->SCp.Status = 0; /* Set to a known state */
5384: advansys_queuecommand(scp, advansys_command_done);
5385: while (scp->SCp.Status == 0) {
5386: continue;
5387: }
5388: ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
5389: return scp->result;
5390: }
5391:
5392: /*
5393: * advansys_queuecommand() - interrupt-driven I/O entrypoint.
5394: *
5395: * This function always returns 0. Command return status is saved
5396: * in the 'scp' result field.
5397: */
5398: int
5399: advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
5400: {
5401: struct Scsi_Host *shp;
5402: asc_board_t *boardp;
5403: int flags;
5404: Scsi_Cmnd *done_scp;
5405:
5406: shp = scp->host;
5407: boardp = ASC_BOARDP(shp);
5408: ASC_STATS(shp, queuecommand);
5409:
5410: /*
5411: * Disable interrupts to preserve request ordering and provide
5412: * mutually exclusive access to global structures used to initiate
5413: * a request.
5414: */
5415: save_flags(flags);
5416: cli();
5417:
5418: /*
5419: * Block new commands while handling a reset or abort request.
5420: */
5421: if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5422: if (boardp->flags & ASC_HOST_IN_RESET) {
5423: ASC_DBG1(1,
5424: "advansys_queuecommand: scp %x blocked for reset request\n",
5425: (unsigned) scp);
5426: scp->result = HOST_BYTE(DID_RESET);
5427: } else {
5428: ASC_DBG1(1,
5429: "advansys_queuecommand: scp %x blocked for abort request\n",
5430: (unsigned) scp);
5431: scp->result = HOST_BYTE(DID_ABORT);
5432: }
5433:
5434: /*
5435: * Add blocked requests to the board's 'done' queue. The queued
5436: * requests will be completed at the end of the abort or reset
5437: * handling.
5438: */
5439: asc_enqueue(&boardp->done, scp, ASC_BACK);
5440: restore_flags(flags);
5441: return 0;
5442: }
5443:
5444: /*
5445: * Attempt to execute any waiting commands for the board.
5446: */
5447: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5448: ASC_DBG(1,
5449: "advansys_queuecommand: before asc_execute_queue() waiting\n");
5450: asc_execute_queue(&boardp->waiting);
5451: }
5452:
5453: /*
5454: * Save the function pointer to Linux mid-level 'done' function
5455: * and attempt to execute the command.
5456: *
5457: * If ASC_ERROR is returned the request has been added to the
5458: * board's 'active' queue and will be completed by the interrupt
5459: * handler.
5460: *
5461: * If ASC_BUSY is returned add the request to the board's per
5462: * target waiting list.
5463: *
5464: * If an error occurred, the request will have been placed on the
5465: * board's 'done' queue and must be completed before returning.
5466: */
5467: scp->scsi_done = done;
5468: switch (asc_execute_scsi_cmnd(scp)) {
5469: case ASC_NOERROR:
5470: break;
5471: case ASC_BUSY:
5472: asc_enqueue(&boardp->waiting, scp, ASC_BACK);
5473: break;
5474: case ASC_ERROR:
5475: default:
5476: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5477: /* Interrupts could be enabled here. */
5478: asc_scsi_done_list(done_scp);
5479: break;
5480: }
5481:
5482: restore_flags(flags);
5483: return 0;
5484: }
5485:
5486: /*
5487: * advansys_abort()
5488: *
5489: * Abort the command specified by 'scp'.
5490: */
5491: int
5492: advansys_abort(Scsi_Cmnd *scp)
5493: {
5494: struct Scsi_Host *shp;
5495: asc_board_t *boardp;
5496: ASC_DVC_VAR *asc_dvc_varp;
5497: ADV_DVC_VAR *adv_dvc_varp;
5498: int flags;
5499: int do_scsi_done;
5500: int scp_found;
5501: Scsi_Cmnd *done_scp = NULL;
5502: int ret;
5503:
5504: /* Save current flags and disable interrupts. */
5505: save_flags(flags);
5506: cli();
5507:
5508: ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
5509:
5510: #ifdef ADVANSYS_STATS
5511: if (scp->host != NULL) {
5512: ASC_STATS(scp->host, abort);
5513: }
5514: #endif /* ADVANSYS_STATS */
5515:
5516: #ifdef ADVANSYS_ASSERT
5517: do_scsi_done = ASC_ERROR;
5518: scp_found = ASC_ERROR;
5519: ret = ASC_ERROR;
5520: #endif /* ADVANSYS_ASSERT */
5521:
5522: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5523: if (scp->serial_number != scp->serial_number_at_timeout) {
5524: ASC_PRINT1(
5525: "advansys_abort: timeout serial number changed for request %x\n",
5526: (unsigned) scp);
5527: do_scsi_done = ASC_FALSE;
5528: scp_found = ASC_FALSE;
5529: ret = SCSI_ABORT_NOT_RUNNING;
5530: } else
5531: #endif /* version >= v1.3.89 */
5532: if ((shp = scp->host) == NULL) {
5533: scp->result = HOST_BYTE(DID_ERROR);
5534: do_scsi_done = ASC_TRUE;
5535: scp_found = ASC_FALSE;
5536: ret = SCSI_ABORT_ERROR;
5537: } else if ((boardp = ASC_BOARDP(shp))->flags &
5538: (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5539: ASC_PRINT2(
5540: "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
5541: boardp->id, boardp->flags);
5542: do_scsi_done = ASC_TRUE;
5543: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5544: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5545: scp_found = ASC_TRUE;
5546: } else {
5547: scp_found = ASC_FALSE;
5548: }
5549: scp->result = HOST_BYTE(DID_ERROR);
5550: ret = SCSI_ABORT_ERROR;
5551: } else {
5552: /* Set abort flag to avoid nested reset or abort requests. */
5553: boardp->flags |= ASC_HOST_IN_ABORT;
5554:
5555: do_scsi_done = ASC_TRUE;
5556: if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
5557: /*
5558: * If asc_rmqueue() found the command on the waiting
5559: * queue, it had not been sent to the device. After
5560: * the queue is removed, no other handling is required.
5561: */
5562: ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
5563: (unsigned) scp);
5564: scp_found = ASC_TRUE;
5565: scp->result = HOST_BYTE(DID_ABORT);
5566: ret = SCSI_ABORT_SUCCESS;
5567: } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
5568: /*
5569: * If asc_isqueued() found the command on the active
5570: * queue, it has been sent to the device. The command
5571: * will be returned through the interrupt handler after
5572: * it has been aborted.
5573: */
5574:
5575: if (ASC_NARROW_BOARD(boardp)) {
5576: /*
5577: * Narrow Board
5578: */
5579: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5580: scp->result = HOST_BYTE(DID_ABORT);
5581:
5582: sti(); /* Enable interrupts for AscAbortSRB(). */
5583: ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
5584: (unsigned) scp);
5585: switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
5586: case ASC_TRUE:
5587: /* asc_isr_callback() will be called */
5588: ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
5589: ret = SCSI_ABORT_PENDING;
5590: break;
5591: case ASC_FALSE:
5592: /* Request has apparently already completed. */
5593: ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
5594: ret = SCSI_ABORT_NOT_RUNNING;
5595: break;
5596: case ASC_ERROR:
5597: default:
5598: ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
5599: ret = SCSI_ABORT_ERROR;
5600: break;
5601: }
5602: cli();
5603: } else {
5604: /*
5605: * Wide Board
5606: */
5607: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5608: scp->result = HOST_BYTE(DID_ABORT);
5609:
5610: ASC_DBG1(1, "advansys_abort: before AdvAbortSRB(), scp %x\n",
5611: (unsigned) scp);
5612: switch (AdvAbortSRB(adv_dvc_varp, (ulong) scp)) {
5613: case ASC_TRUE:
5614: /* asc_isr_callback() will be called */
5615: ASC_DBG(1, "advansys_abort: AdvAbortSRB() TRUE\n");
5616: ret = SCSI_ABORT_PENDING;
5617: break;
5618: case ASC_FALSE:
5619: /* Request has apparently already completed. */
5620: ASC_DBG(1, "advansys_abort: AdvAbortSRB() FALSE\n");
5621: ret = SCSI_ABORT_NOT_RUNNING;
5622: break;
5623: case ASC_ERROR:
5624: default:
5625: ASC_DBG(1, "advansys_abort: AdvAbortSRB() ERROR\n");
5626: ret = SCSI_ABORT_ERROR;
5627: break;
5628: }
5629: /*
5630: * Ensure all requests completed by the microcode have
5631: * been processed by calling AdvISR().
5632: */
5633: (void) AdvISR(adv_dvc_varp);
5634: }
5635:
5636: /*
5637: * The request will either still be on the active queue
5638: * or have been added to the board's done queue.
5639: */
5640: if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
5641: scp->result = HOST_BYTE(DID_ABORT);
5642: scp_found = ASC_TRUE;
5643: } else {
5644: scp_found = asc_rmqueue(&boardp->done, scp);
5645: ASC_ASSERT(scp_found == ASC_TRUE);
5646: }
5647:
5648: } else {
5649: /*
5650: * The command was not found on the active or waiting queues.
5651: */
5652: do_scsi_done = ASC_TRUE;
5653: scp_found = ASC_FALSE;
5654: ret = SCSI_ABORT_NOT_RUNNING;
5655: }
5656:
5657: /* Clear abort flag. */
5658: boardp->flags &= ~ASC_HOST_IN_ABORT;
5659:
5660: /*
5661: * Because the ASC_HOST_IN_ABORT flag causes both
5662: * 'advansys_interrupt' and 'asc_isr_callback' to
5663: * queue requests to the board's 'done' queue and
5664: * prevents waiting commands from being executed,
5665: * these queued requests must be handled here.
5666: */
5667: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5668:
5669: /*
5670: * Start any waiting commands for the board.
5671: */
5672: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5673: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
5674: asc_execute_queue(&boardp->waiting);
5675: }
5676: }
5677:
5678: /* Interrupts could be enabled here. */
5679:
5680: /*
5681: * Complete the request to be aborted, unless it has been
5682: * restarted as detected above, even if it was not found on
5683: * the device active or waiting queues.
5684: */
5685: ASC_ASSERT(do_scsi_done != ASC_ERROR);
5686: ASC_ASSERT(scp_found != ASC_ERROR);
5687: if (do_scsi_done == ASC_TRUE) {
5688: if (scp->scsi_done == NULL) {
5689: ASC_PRINT1(
5690: "advansys_abort: aborted request scsi_done() is NULL, %x\n",
5691: (unsigned) scp);
5692: } else {
5693: if (scp_found == ASC_FALSE) {
5694: ASC_PRINT1(
5695: "advansys_abort: abort request not active or waiting, completing anyway %x\n",
5696: (unsigned) scp);
5697: }
5698: ASC_STATS(scp->host, done);
5699: scp->scsi_done(scp);
5700: }
5701: }
5702:
5703: /*
5704: * It is possible for the request done function to re-enable
5705: * interrupts without confusing the driver. But here interrupts
5706: * aren't enabled until all requests have been completed.
5707: */
5708: if (done_scp != NULL) {
5709: asc_scsi_done_list(done_scp);
5710: }
5711:
5712: ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
5713:
5714: /* Re-enable interrupts, if they were enabled on entry. */
5715: restore_flags(flags);
5716:
5717: ASC_ASSERT(ret != ASC_ERROR);
5718: return ret;
5719: }
5720:
5721: /*
5722: * advansys_reset()
5723: *
5724: * Reset the device associated with the command 'scp'.
5725: */
5726: int
5727: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
5728: advansys_reset(Scsi_Cmnd *scp)
5729: #else /* version >= v1.3.89 */
5730: advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
5731: #endif /* version >= v1.3.89 */
5732: {
5733: struct Scsi_Host *shp;
5734: asc_board_t *boardp;
5735: ASC_DVC_VAR *asc_dvc_varp;
5736: ADV_DVC_VAR *adv_dvc_varp;
5737: int flags;
5738: Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
5739: Scsi_Cmnd *tscp, *new_last_scp;
5740: int do_scsi_done;
5741: int scp_found;
5742: int status;
5743: int target;
5744: int ret;
5745: int device_reset = ASC_FALSE;
5746:
5747: /* Save current flags and disable interrupts. */
5748: save_flags(flags);
5749: cli();
5750:
5751: ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
5752:
5753: #ifdef ADVANSYS_STATS
5754: if (scp->host != NULL) {
5755: ASC_STATS(scp->host, reset);
5756: }
5757: #endif /* ADVANSYS_STATS */
5758:
5759: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5760: if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) &&
5761: (scp->serial_number != scp->serial_number_at_timeout)) {
5762: ASC_PRINT1(
5763: "advansys_reset: timeout serial number changed for request %x\n",
5764: (unsigned) scp);
5765: do_scsi_done = ASC_FALSE;
5766: scp_found = ASC_FALSE;
5767: ret = SCSI_RESET_NOT_RUNNING;
5768: } else
5769: #endif /* version >= v1.3.89 */
5770: if ((shp = scp->host) == NULL) {
5771: scp->result = HOST_BYTE(DID_ERROR);
5772: do_scsi_done = ASC_TRUE;
5773: scp_found = ASC_FALSE;
5774: ret = SCSI_RESET_ERROR;
5775: } else if ((boardp = ASC_BOARDP(shp))->flags &
5776: (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5777: ASC_PRINT2(
5778: "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
5779: boardp->id, boardp->flags);
5780: do_scsi_done = ASC_TRUE;
5781: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5782: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5783: scp_found = ASC_TRUE;
5784: } else {
5785: scp_found = ASC_FALSE;
5786: }
5787: scp->result = HOST_BYTE(DID_ERROR);
5788: ret = SCSI_RESET_ERROR;
5789: } else if (jiffies >= boardp->last_reset &&
5790: jiffies < (boardp->last_reset + (10 * HZ))) {
5791: /*
5792: * Don't allow a reset to be attempted within 10 seconds
5793: * of the last reset.
5794: *
5795: * If 'jiffies' wrapping occurs, the reset request will go
5796: * through, because a wrapped 'jiffies' would not pass the
5797: * test above.
5798: */
5799: ASC_DBG(1,
5800: "advansys_reset: reset within 10 sec of last reset ignored\n");
5801: do_scsi_done = ASC_TRUE;
5802: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5803: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5804: scp_found = ASC_TRUE;
5805: } else {
5806: scp_found = ASC_FALSE;
5807: }
5808: scp->result = HOST_BYTE(DID_ERROR);
5809: ret = SCSI_RESET_ERROR;
5810: } else {
5811: do_scsi_done = ASC_TRUE;
5812:
5813: /* Set reset flag to avoid nested reset or abort requests. */
5814: boardp->flags |= ASC_HOST_IN_RESET;
5815:
5816: /*
5817: * If the request is on the target waiting or active queue
5818: * or the board done queue, then remove it and note that it
5819: * was found.
5820: */
5821: if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
5822: ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
5823: scp_found = ASC_TRUE;
5824: } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
5825: ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
5826: scp_found = ASC_TRUE;
5827: } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
5828: scp_found = ASC_TRUE;
5829: } else {
5830: scp_found = ASC_FALSE;
5831: }
5832:
5833:
5834: if (ASC_NARROW_BOARD(boardp)) {
5835: /*
5836: * Narrow Board
5837: *
5838: * If the suggest reset bus flags are set, then reset the bus.
5839: * Otherwise only reset the device.
5840: */
5841: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5842: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5843: if (reset_flags &
5844: (SCSI_RESET_SUGGEST_BUS_RESET |
5845: SCSI_RESET_SUGGEST_HOST_RESET)) {
5846: #endif /* version >= v1.3.89 */
5847:
5848: /*
5849: * Reset the target's SCSI bus.
5850: */
5851: ASC_DBG(1, "advansys_reset: before AscResetSB()\n");
5852: sti(); /* Enable interrupts for AscResetSB(). */
5853: status = AscResetSB(asc_dvc_varp);
5854: cli();
5855: switch (status) {
5856: case ASC_TRUE:
5857: ASC_DBG(1, "advansys_reset: AscResetSB() success\n");
5858: ret = SCSI_RESET_SUCCESS;
5859: break;
5860: case ASC_ERROR:
5861: default:
5862: ASC_DBG(1, "advansys_reset: AscResetSB() failed\n");
5863: ret = SCSI_RESET_ERROR;
5864: break;
5865: }
5866:
5867: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5868: } else {
5869: /*
5870: * Reset the specified device. If the device reset fails,
5871: * then reset the SCSI bus.
5872: */
5873:
5874: ASC_DBG1(1,
5875: "advansys_reset: before AscResetDevice(), target %d\n",
5876: scp->target);
5877: sti(); /* Enable interrupts for AscResetDevice(). */
5878: status = AscResetDevice(asc_dvc_varp, scp->target);
5879: cli();
5880:
5881: switch (status) {
5882: case ASC_TRUE:
5883: ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
5884: device_reset = ASC_TRUE;
5885: ret = SCSI_RESET_SUCCESS;
5886: break;
5887: case ASC_ERROR:
5888: default:
5889: ASC_DBG(1,
5890: "advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n");
5891: sti(); /* Enable interrupts for AscResetSB(). */
5892: status = AscResetSB(asc_dvc_varp);
5893: cli();
5894: switch (status) {
5895: case ASC_TRUE:
5896: ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
5897: ret = SCSI_RESET_SUCCESS;
5898: break;
5899: case ASC_ERROR:
5900: default:
5901: ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
5902: ret = SCSI_RESET_ERROR;
5903: break;
5904: }
5905: break;
5906: }
5907: }
5908: #endif /* version >= v1.3.89 */
5909: } else {
5910: /*
5911: * Wide Board
5912: *
5913: * If the suggest reset bus flags are set, then reset the bus.
5914: * Otherwise only reset the device.
5915: */
5916: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5917: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5918: if (reset_flags &
5919: (SCSI_RESET_SUGGEST_BUS_RESET |
5920: SCSI_RESET_SUGGEST_HOST_RESET)) {
5921: #endif /* version >= v1.3.89 */
5922:
5923: /*
5924: * Reset the target's SCSI bus.
5925: */
5926: ASC_DBG(1, "advansys_reset: before AdvResetSB()\n");
5927: switch (AdvResetSB(adv_dvc_varp)) {
5928: case ASC_TRUE:
5929: ASC_DBG(1, "advansys_reset: AdvResetSB() success\n");
5930: ret = SCSI_RESET_SUCCESS;
5931: break;
5932: case ASC_FALSE:
5933: default:
5934: ASC_DBG(1, "advansys_reset: AdvResetSB() failed\n");
5935: ret = SCSI_RESET_ERROR;
5936: break;
5937: }
5938: /*
5939: * Ensure all requests completed by the microcode have
5940: * been processed by calling AdvISR().
5941: */
5942: (void) AdvISR(adv_dvc_varp);
5943: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5944: } else {
5945: /*
5946: * Reset the specified device. If the device reset fails,
5947: * then reset the SCSI bus.
5948: */
5949:
5950: ASC_DBG1(1,
5951: "advansys_reset: before AdvResetDevice(), target %d\n",
5952: scp->target);
5953:
5954: switch (AdvResetDevice(adv_dvc_varp, scp->target)) {
5955: case ASC_TRUE:
5956: ASC_DBG(1, "advansys_reset: AdvResetDevice() success\n");
5957: device_reset = ASC_TRUE;
5958: ret = SCSI_RESET_SUCCESS;
5959: break;
5960: case ASC_FALSE:
5961: default:
5962: ASC_DBG(1,
5963: "advansys_reset: AdvResetDevice() failed; Calling AdvResetSB()\n");
5964:
5965: switch (AdvResetSB(adv_dvc_varp)) {
5966: case ASC_TRUE:
5967: ASC_DBG(1, "advansys_reset: AdvResetSB() TRUE\n");
5968: ret = SCSI_RESET_SUCCESS;
5969: break;
5970: case ASC_FALSE:
5971: default:
5972: ASC_DBG(1, "advansys_reset: AdvResetSB() ERROR\n");
5973: ret = SCSI_RESET_ERROR;
5974: break;
5975: }
5976: break;
5977: }
5978: /*
5979: * Ensure all requests completed by the microcode have
5980: * been processed by calling AdvISR().
5981: */
5982: (void) AdvISR(adv_dvc_varp);
5983: }
5984: #endif /* version >= v1.3.89 */
5985: }
5986:
5987: /*
5988: * Because the ASC_HOST_IN_RESET flag causes both
5989: * 'advansys_interrupt' and 'asc_isr_callback' to
5990: * queue requests to the board's 'done' queue and
5991: * prevents waiting commands from being executed,
5992: * these queued requests must be handled here.
5993: */
5994: done_scp = asc_dequeue_list(&boardp->done, &last_scp,
5995: ASC_TID_ALL);
5996:
5997: /*
5998: * If a device reset was performed dequeue all waiting
5999: * and active requests for the device and set the request
6000: * status to DID_RESET.
6001: *
6002: * If a SCSI bus reset was performed dequeue all waiting
6003: * and active requests for all devices and set the request
6004: * status to DID_RESET.
6005: */
6006: if (device_reset == ASC_TRUE) {
6007: target = scp->target;
6008: } else {
6009: target = ASC_TID_ALL;
6010: }
6011:
6012: /*
6013: * Add active requests to 'done_scp' and set the request status
6014: * to DID_RESET.
6015: */
6016: if (done_scp == NULL) {
6017: done_scp = asc_dequeue_list(&boardp->active, &last_scp, target);
6018: for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
6019: tscp->result = HOST_BYTE(DID_RESET);
6020: }
6021: } else {
6022: ASC_ASSERT(last_scp != NULL);
6023: REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
6024: &new_last_scp, target);
6025: if (new_last_scp != NULL) {
6026: ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6027: for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
6028: tscp->result = HOST_BYTE(DID_RESET);
6029: }
6030: last_scp = new_last_scp;
6031: }
6032: }
6033:
6034: /*
6035: * Add waiting requests to 'done_scp' and set the request status
6036: * to DID_RESET.
6037: */
6038: if (done_scp == NULL) {
6039: done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target);
6040: for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
6041: tscp->result = HOST_BYTE(DID_RESET);
6042: }
6043: } else {
6044: ASC_ASSERT(last_scp != NULL);
6045: REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
6046: &new_last_scp, target);
6047: if (new_last_scp != NULL) {
6048: ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6049: for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
6050: tscp->result = HOST_BYTE(DID_RESET);
6051: }
6052: last_scp = new_last_scp;
6053: }
6054: }
6055:
6056: /* Save the time of the most recently completed reset. */
6057: boardp->last_reset = jiffies;
6058:
6059: /* Clear reset flag. */
6060: boardp->flags &= ~ASC_HOST_IN_RESET;
6061:
6062: /*
6063: * Start any waiting commands for the board.
6064: */
6065: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6066: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6067: asc_execute_queue(&boardp->waiting);
6068: }
6069: ret = SCSI_RESET_SUCCESS;
6070: }
6071:
6072: /* Interrupts could be enabled here. */
6073:
6074: ASC_ASSERT(do_scsi_done != ASC_ERROR);
6075: ASC_ASSERT(scp_found != ASC_ERROR);
6076: if (do_scsi_done == ASC_TRUE) {
6077: if (scp->scsi_done == NULL) {
6078: ASC_PRINT1(
6079: "advansys_reset: reset request scsi_done() is NULL, %x\n",
6080: (unsigned) scp);
6081: } else {
6082: if (scp_found == ASC_FALSE) {
6083: ASC_PRINT1(
6084: "advansys_reset: reset request not active or waiting, completing anyway %x\n",
6085: (unsigned) scp);
6086: }
6087: ASC_STATS(scp->host, done);
6088: scp->scsi_done(scp);
6089: }
6090: }
6091:
6092: /*
6093: * It is possible for the request done function to re-enable
6094: * interrupts without confusing the driver. But here interrupts
6095: * aren't enabled until requests have been completed.
6096: */
6097: if (done_scp != NULL) {
6098: asc_scsi_done_list(done_scp);
6099: }
6100:
6101: ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
6102:
6103: /* Re-enable interrupts, if they were enabled on entry. */
6104: restore_flags(flags);
6105:
6106: ASC_ASSERT(ret != ASC_ERROR);
6107: return ret;
6108: }
6109:
6110: /*
6111: * advansys_biosparam()
6112: *
6113: * Translate disk drive geometry if the "BIOS greater than 1 GB"
6114: * support is enabled for a drive.
6115: *
6116: * ip (information pointer) is an int array with the following definition:
6117: * ip[0]: heads
6118: * ip[1]: sectors
6119: * ip[2]: cylinders
6120: */
6121: int
6122: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
6123: advansys_biosparam(Disk *dp, int dep, int ip[])
6124: #else /* version >= v1.3.0 */
6125: advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
6126: #endif /* version >= v1.3.0 */
6127: {
6128: asc_board_t *boardp;
6129:
6130: ASC_DBG(1, "advansys_biosparam: begin\n");
6131: ASC_STATS(dp->device->host, biosparam);
6132: boardp = ASC_BOARDP(dp->device->host);
6133: if (ASC_NARROW_BOARD(boardp)) {
6134: if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
6135: ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
6136: ip[0] = 255;
6137: ip[1] = 63;
6138: } else {
6139: ip[0] = 64;
6140: ip[1] = 32;
6141: }
6142: } else {
6143: if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
6144: BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) {
6145: ip[0] = 255;
6146: ip[1] = 63;
6147: } else {
6148: ip[0] = 64;
6149: ip[1] = 32;
6150: }
6151: }
6152: ip[2] = dp->capacity / (ip[0] * ip[1]);
6153: ASC_DBG(1, "advansys_biosparam: end\n");
6154: return 0;
6155: }
6156:
6157: /*
6158: * advansys_setup()
6159: *
6160: * This function is called from init/main.c at boot time.
6161: * It it passed LILO parameters that can be set from the
6162: * LILO command line or in /etc/lilo.conf.
6163: *
6164: * It is used by the AdvanSys driver to either disable I/O
6165: * port scanning or to limit scanning to 1 - 4 I/O ports.
6166: * Regardless of the option setting EISA and PCI boards
6167: * will still be searched for and detected. This option
6168: * only affects searching for ISA and VL boards.
6169: *
6170: * If ADVANSYS_DEBUG is defined the driver debug level may
6171: * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
6172: *
6173: * Examples:
6174: * 1. Eliminate I/O port scanning:
6175: * boot: linux advansys=
6176: * or
6177: * boot: linux advansys=0x0
6178: * 2. Limit I/O port scanning to one I/O port:
6179: * boot: linux advansys=0x110
6180: * 3. Limit I/O port scanning to four I/O ports:
6181: * boot: linux advansys=0x110,0x210,0x230,0x330
6182: * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
6183: * set the driver debug level to 2.
6184: * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
6185: *
6186: * ints[0] - number of arguments
6187: * ints[1] - first argument
6188: * ints[2] - second argument
6189: * ...
6190: */
6191: ASC_INITFUNC(
6192: void
6193: advansys_setup(char *str, int *ints)
6194: )
6195: {
6196: int i;
6197:
6198: if (asc_iopflag == ASC_TRUE) {
6199: printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
6200: return;
6201: }
6202:
6203: asc_iopflag = ASC_TRUE;
6204:
6205: if (ints[0] > ASC_NUM_IOPORT_PROBE) {
6206: #ifdef ADVANSYS_DEBUG
6207: if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
6208: (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
6209: asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
6210: } else {
6211: #endif /* ADVANSYS_DEBUG */
6212: printk("AdvanSys SCSI: only %d I/O ports accepted\n",
6213: ASC_NUM_IOPORT_PROBE);
6214: #ifdef ADVANSYS_DEBUG
6215: }
6216: #endif /* ADVANSYS_DEBUG */
6217: }
6218:
6219: #ifdef ADVANSYS_DEBUG
6220: ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
6221: for (i = 1; i < ints[0]; i++) {
6222: ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
6223: }
6224: ASC_DBG(1, "\n");
6225: #endif /* ADVANSYS_DEBUG */
6226:
6227: for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
6228: asc_ioport[i-1] = ints[i];
6229: ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
6230: i - 1, asc_ioport[i-1]);
6231: }
6232: }
6233:
6234:
6235: /*
6236: * --- Loadable Driver Support
6237: */
6238:
6239: #ifdef MODULE
6240: Scsi_Host_Template driver_template = ADVANSYS;
6241: # include "scsi_module.c"
6242: #endif /* MODULE */
6243:
6244:
6245: /*
6246: * --- Miscellaneous Driver Functions
6247: */
6248:
6249: /*
6250: * First-level interrupt handler.
6251: *
6252: * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting
6253: * adapter's asc_board_t. Because all boards are currently checked
6254: * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id'
6255: * could be used to identify an interrupt passed to the AdvanSys driver,
6256: * which is for a device sharing an interrupt with an AdvanSys adapter.
6257: */
6258: STATIC void
6259: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
6260: advansys_interrupt(int irq, struct pt_regs *regs)
6261: #else /* version >= v1.3.70 */
6262: advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
6263: #endif /* version >= v1.3.70 */
6264: {
6265: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6266: int flags;
6267: #else /* version >= v2.1.95 */
6268: unsigned long flags;
6269: #endif /* version >= v2.1.95 */
6270: int i;
6271: asc_board_t *boardp;
6272: Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
6273: Scsi_Cmnd *new_last_scp;
6274:
6275: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6276: /* Disable interrupts, if they aren't already disabled. */
6277: save_flags(flags);
6278: cli();
6279: #else /* version >= v2.1.95 */
6280: /*
6281: * Disable interrupts, if they aren't already disabled and acquire
6282: * the I/O spinlock.
6283: */
6284: spin_lock_irqsave(&io_request_lock, flags);
6285: #endif /* version >= v2.1.95 */
6286:
6287: ASC_DBG(1, "advansys_interrupt: begin\n");
6288:
6289: /*
6290: * Check for interrupts on all boards.
6291: * AscISR() will call asc_isr_callback().
6292: */
6293: for (i = 0; i < asc_board_count; i++) {
6294: boardp = ASC_BOARDP(asc_host[i]);
6295: ASC_DBG2(2, "advansys_interrupt: i %d, boardp %lx\n",
6296: i, (ulong) boardp)
6297: if (ASC_NARROW_BOARD(boardp)) {
6298: /*
6299: * Narrow Board
6300: */
6301: if (AscIsIntPending(asc_host[i]->io_port)) {
6302: ASC_STATS(asc_host[i], interrupt);
6303: ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
6304: AscISR(&boardp->dvc_var.asc_dvc_var);
6305: }
6306: } else {
6307: /*
6308: * Wide Board
6309: */
6310: ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
6311: if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
6312: ASC_STATS(asc_host[i], interrupt);
6313: }
6314: }
6315:
6316: /*
6317: * Start waiting requests and create a list of completed requests.
6318: *
6319: * If a reset or abort request is being performed for the board,
6320: * the reset or abort handler will complete pending requests after
6321: * it has completed.
6322: */
6323: if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) {
6324: ASC_DBG2(1, "advansys_interrupt: done_scp %lx, last_scp %lx\n",
6325: (ulong) done_scp, (ulong) last_scp);
6326:
6327: /* Start any waiting commands for the board. */
6328: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6329: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6330: asc_execute_queue(&boardp->waiting);
6331: }
6332:
6333: /*
6334: * Add to the list of requests that must be completed.
6335: *
6336: * 'done_scp' will always be NULL on the first iteration
6337: * of this loop. 'last_scp' is set at the same time as
6338: * 'done_scp'.
6339: */
6340: if (done_scp == NULL) {
6341: done_scp = asc_dequeue_list(&boardp->done, &last_scp,
6342: ASC_TID_ALL);
6343: } else {
6344: ASC_ASSERT(last_scp != NULL);
6345: REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
6346: &new_last_scp, ASC_TID_ALL);
6347: if (new_last_scp != NULL) {
6348: ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6349: last_scp = new_last_scp;
6350: }
6351: }
6352: }
6353: }
6354:
6355: /* Interrupts could be enabled here. */
6356:
6357: /*
6358: * It is possible for the request done function to re-enable
6359: * interrupts without confusing the driver. But here the
6360: * original flags aren't restored until all requests have been
6361: * completed.
6362: */
6363: asc_scsi_done_list(done_scp);
6364:
6365: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6366: /*
6367: * Restore the original flags which will enable interrupts
6368: * if and only if they were enabled on entry.
6369: */
6370: restore_flags(flags);
6371: #else /* version >= v2.1.95 */
6372: /*
6373: * Release the I/O spinlock and restore the original flags
6374: * which will enable interrupts if and only if they were
6375: * enabled on entry.
6376: */
6377: spin_unlock_irqrestore(&io_request_lock, flags);
6378: #endif /* version >= v2.1.95 */
6379:
6380: ASC_DBG(1, "advansys_interrupt: end\n");
6381: return;
6382: }
6383:
6384: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6385: /*
6386: * Set the number of commands to queue per device for the
6387: * specified host adapter.
6388: */
6389: STATIC void
6390: advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
6391: {
6392: Scsi_Device *device;
6393: asc_board_t *boardp;
6394:
6395: boardp = ASC_BOARDP(shp);
6396: boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
6397: for (device = devicelist; device != NULL; device = device->next) {
6398: if (device->host != shp) {
6399: continue;
6400: }
6401: /*
6402: * Save a pointer to the device and set its initial/maximum
6403: * queue depth.
6404: */
6405: boardp->device[device->id] = device;
6406: if (ASC_NARROW_BOARD(boardp)) {
6407: device->queue_depth =
6408: boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id];
6409: } else {
6410: device->queue_depth =
6411: boardp->dvc_var.adv_dvc_var.max_dvc_qng;
6412: }
6413: ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
6414: (unsigned) shp, device->id, device->queue_depth);
6415: }
6416: }
6417: #endif /* version >= v1.3.89 */
6418:
6419: /*
6420: * Function used only with polled I/O requests that are initiated by
6421: * advansys_command().
6422: */
6423: STATIC void
6424: advansys_command_done(Scsi_Cmnd *scp)
6425: {
6426: ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
6427: scp->SCp.Status = 1;
6428: }
6429:
6430: /*
6431: * Complete all requests on the singly linked list pointed
6432: * to by 'scp'.
6433: *
6434: * Interrupts can be enabled on entry.
6435: */
6436: STATIC void
6437: asc_scsi_done_list(Scsi_Cmnd *scp)
6438: {
6439: Scsi_Cmnd *tscp;
6440:
6441: ASC_DBG(2, "asc_scsi_done_list: begin\n");
6442: while (scp != NULL) {
6443: ASC_DBG1(3, "asc_scsi_done_list: scp %x\n", (unsigned) scp);
6444: tscp = REQPNEXT(scp);
6445: REQPNEXT(scp) = NULL;
6446: ASC_STATS(scp->host, done);
6447: ASC_ASSERT(scp->scsi_done != NULL);
6448: scp->scsi_done(scp);
6449: scp = tscp;
6450: }
6451: ASC_DBG(2, "asc_scsi_done_list: done\n");
6452: return;
6453: }
6454:
6455: /*
6456: * Execute a single 'Scsi_Cmnd'.
6457: *
6458: * The function 'done' is called when the request has been completed.
6459: *
6460: * Scsi_Cmnd:
6461: *
6462: * host - board controlling device
6463: * device - device to send command
6464: * target - target of device
6465: * lun - lun of device
6466: * cmd_len - length of SCSI CDB
6467: * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
6468: * use_sg - if non-zero indicates scatter-gather request with use_sg elements
6469: *
6470: * if (use_sg == 0) {
6471: * request_buffer - buffer address for request
6472: * request_bufflen - length of request buffer
6473: * } else {
6474: * request_buffer - pointer to scatterlist structure
6475: * }
6476: *
6477: * sense_buffer - sense command buffer
6478: *
6479: * result (4 bytes of an int):
6480: * Byte Meaning
6481: * 0 SCSI Status Byte Code
6482: * 1 SCSI One Byte Message Code
6483: * 2 Host Error Code
6484: * 3 Mid-Level Error Code
6485: *
6486: * host driver fields:
6487: * SCp - Scsi_Pointer used for command processing status
6488: * scsi_done - used to save caller's done function
6489: * host_scribble - used for pointer to another Scsi_Cmnd
6490: *
6491: * If this function returns ASC_NOERROR or ASC_ERROR the request
6492: * has been enqueued on the board's 'done' queue and must be
6493: * completed by the caller.
6494: *
6495: * If ASC_BUSY is returned the request must be enqueued by the
6496: * caller and re-tried later.
6497: */
6498: STATIC int
6499: asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
6500: {
6501: asc_board_t *boardp;
6502: ASC_DVC_VAR *asc_dvc_varp;
6503: ADV_DVC_VAR *adv_dvc_varp;
6504: ADV_SCSI_REQ_Q *adv_scsiqp;
6505: Scsi_Device *device;
6506: int ret;
6507:
6508: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
6509: ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
6510: (unsigned) scp, (unsigned) scp->scsi_done);
6511:
6512: boardp = ASC_BOARDP(scp->host);
6513: device = boardp->device[scp->target];
6514:
6515: if (ASC_NARROW_BOARD(boardp)) {
6516: /*
6517: * Build and execute Narrow Board request.
6518: */
6519:
6520: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6521:
6522: /*
6523: * Build Asc Library request structure using the
6524: * global structures 'asc_scsi_req' and 'asc_sg_head'.
6525: *
6526: * asc_build_req() can not return ASC_BUSY.
6527: */
6528: if (asc_build_req(boardp, scp) == ASC_ERROR) {
6529: ASC_STATS(scp->host, build_error);
6530: return ASC_ERROR;
6531: }
6532:
6533: /*
6534: * Execute the command. If there is no error, add the command
6535: * to the active queue.
6536: */
6537: switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
6538: case ASC_NOERROR:
6539: ASC_STATS(scp->host, exe_noerror);
6540: /*
6541: * Increment monotonically increasing per device successful
6542: * request counter. Wrapping doesn't matter.
6543: */
6544: boardp->reqcnt[scp->target]++;
6545:
6546: #if ASC_QUEUE_FLOW_CONTROL
6547: /*
6548: * Conditionally increment the device queue depth.
6549: *
6550: * If no error occurred and there have been 100 consecutive
6551: * successful requests and the current queue depth is less
6552: * than the maximum queue depth, then increment the current
6553: * queue depth.
6554: */
6555: if (boardp->nerrcnt[scp->target]++ > 100) {
6556: boardp->nerrcnt[scp->target] = 0;
6557: if (device != NULL &&
6558: (device->queue_curr_depth < device->queue_depth) &&
6559: (!(boardp->queue_full &
6560: ADV_TID_TO_TIDMASK(scp->target)) ||
6561: (boardp->queue_full_cnt[scp->target] >
6562: device->queue_curr_depth))) {
6563: device->queue_curr_depth++;
6564: }
6565: }
6566: #endif /* ASC_QUEUE_FLOW_CONTROL */
6567: asc_enqueue(&boardp->active, scp, ASC_BACK);
6568: ASC_DBG(1,
6569: "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
6570: break;
6571: case ASC_BUSY:
6572: /* Caller must enqueue request and retry later. */
6573: ASC_STATS(scp->host, exe_busy);
6574: #if ASC_QUEUE_FLOW_CONTROL
6575: /*
6576: * Clear consecutive no error counter and if possible decrement
6577: * queue depth.
6578: */
6579: boardp->nerrcnt[scp->target] = 0;
6580: if (device != NULL && device->queue_curr_depth > 1) {
6581: device->queue_curr_depth--;
6582: }
6583: #endif /* ASC_QUEUE_FLOW_CONTROL */
6584: break;
6585: case ASC_ERROR:
6586: ASC_PRINT2(
6587: "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
6588: boardp->id, asc_dvc_varp->err_code);
6589: ASC_STATS(scp->host, exe_error);
6590: #if ASC_QUEUE_FLOW_CONTROL
6591: /* Clear consecutive no error counter. */
6592: boardp->nerrcnt[scp->target] = 0;
6593: #endif /* ASC_QUEUE_FLOW_CONTROL */
6594: scp->result = HOST_BYTE(DID_ERROR);
6595: asc_enqueue(&boardp->done, scp, ASC_BACK);
6596: break;
6597: default:
6598: ASC_PRINT2(
6599: "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
6600: boardp->id, asc_dvc_varp->err_code);
6601: ASC_STATS(scp->host, exe_unknown);
6602: #if ASC_QUEUE_FLOW_CONTROL
6603: /* Clear consecutive no error counter. */
6604: boardp->nerrcnt[scp->target] = 0;
6605: #endif /* ASC_QUEUE_FLOW_CONTROL */
6606: scp->result = HOST_BYTE(DID_ERROR);
6607: asc_enqueue(&boardp->done, scp, ASC_BACK);
6608: break;
6609: }
6610: } else {
6611: /*
6612: * Build and execute Wide Board request.
6613: */
6614: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6615:
6616: /*
6617: * Build and get a pointer to an Adv Library request structure.
6618: *
6619: * If the request is successfully built then send it below,
6620: * otherwise return with an error.
6621: */
6622: switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
6623: case ASC_NOERROR:
6624: ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
6625: break;
6626: case ASC_BUSY:
6627: ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
6628: return ASC_BUSY;
6629: case ASC_ERROR:
6630: default:
6631: ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
6632: ASC_STATS(scp->host, build_error);
6633: return ASC_ERROR;
6634: }
6635:
6636: /*
6637: * Execute the command. If there is no error, add the command
6638: * to the active queue.
6639: */
6640: switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
6641: case ASC_NOERROR:
6642: ASC_STATS(scp->host, exe_noerror);
6643: /*
6644: * Increment monotonically increasing per device successful
6645: * request counter. Wrapping doesn't matter.
6646: */
6647: boardp->reqcnt[scp->target]++;
6648: asc_enqueue(&boardp->active, scp, ASC_BACK);
6649: ASC_DBG(1,
6650: "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
6651: break;
6652: case ASC_BUSY:
6653: /* Caller must enqueue request and retry later. */
6654: ASC_STATS(scp->host, exe_busy);
6655: break;
6656: case ASC_ERROR:
6657: ASC_PRINT2(
6658: "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code %x\n",
6659: boardp->id, adv_dvc_varp->err_code);
6660: ASC_STATS(scp->host, exe_error);
6661: scp->result = HOST_BYTE(DID_ERROR);
6662: asc_enqueue(&boardp->done, scp, ASC_BACK);
6663: break;
6664: default:
6665: ASC_PRINT2(
6666: "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code %x\n",
6667: boardp->id, adv_dvc_varp->err_code);
6668: ASC_STATS(scp->host, exe_unknown);
6669: scp->result = HOST_BYTE(DID_ERROR);
6670: asc_enqueue(&boardp->done, scp, ASC_BACK);
6671: break;
6672: }
6673: }
6674:
6675: ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
6676: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
6677: return ret;
6678: }
6679:
6680: /*
6681: * Build a request structure for the Asc Library (Narrow Board).
6682: *
6683: * The global structures 'asc_scsi_q' and 'asc_sg_head' are
6684: * used to build the request.
6685: *
6686: * If an error occurs, then return ASC_ERROR.
6687: */
6688: STATIC int
6689: asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp)
6690: {
6691: /*
6692: * Mutually exclusive access is required to 'asc_scsi_q' and
6693: * 'asc_sg_head' until after the request is started.
6694: */
6695: memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
6696:
6697: /*
6698: * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
6699: */
6700: asc_scsi_q.q2.srb_ptr = (ulong) scp;
6701:
6702: /*
6703: * Build the ASC_SCSI_Q request.
6704: */
6705: ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
6706: if (scp->cmd_len > ASC_MAX_CDB_LEN) {
6707: scp->cmd_len = ASC_MAX_CDB_LEN;
6708: }
6709: asc_scsi_q.cdbptr = &scp->cmnd[0];
6710: asc_scsi_q.q2.cdb_len = scp->cmd_len;
6711: asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
6712: asc_scsi_q.q1.target_lun = scp->lun;
6713: asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
6714: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6715: asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
6716: #else /* version >= v2.0.0 */
6717: asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
6718: #endif /* version >= v2.0.0 */
6719: asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
6720:
6721: /*
6722: * If there are any outstanding requests for the current target,
6723: * then every 255th request send an ORDERED request. This heuristic
6724: * tries to retain the benefit of request sorting while preventing
6725: * request starvation. 255 is the max number of tags or pending commands
6726: * a device may have outstanding.
6727: *
6728: * The request count is incremented below for every successfully
6729: * started request.
6730: *
6731: */
6732: if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->target] > 0) &&
6733: (boardp->reqcnt[scp->target] % 255) == 0) {
6734: asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
6735: } else {
6736: asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
6737: }
6738:
6739: /*
6740: * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
6741: * buffer command.
6742: */
6743: if (scp->use_sg == 0) {
6744: /*
6745: * CDB request of single contiguous buffer.
6746: */
6747: ASC_STATS(scp->host, cont_cnt);
6748: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6749: asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
6750: #else /* version >= v2.0.0 */
6751: asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
6752: #endif /* version >= v2.0.0 */
6753: asc_scsi_q.q1.data_cnt = scp->request_bufflen;
6754: ASC_STATS_ADD(scp->host, cont_xfer,
6755: ASC_CEILING(scp->request_bufflen, 512));
6756: asc_scsi_q.q1.sg_queue_cnt = 0;
6757: asc_scsi_q.sg_head = NULL;
6758: } else {
6759: /*
6760: * CDB scatter-gather request list.
6761: */
6762: int sgcnt;
6763: struct scatterlist *slp;
6764:
6765: if (scp->use_sg > scp->host->sg_tablesize) {
6766: ASC_PRINT3(
6767: "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
6768: boardp->id, scp->use_sg, scp->host->sg_tablesize);
6769: scp->result = HOST_BYTE(DID_ERROR);
6770: asc_enqueue(&boardp->done, scp, ASC_BACK);
6771: return ASC_ERROR;
6772: }
6773:
6774: ASC_STATS(scp->host, sg_cnt);
6775:
6776: /*
6777: * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
6778: * structure to point to it.
6779: */
6780: memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
6781:
6782: asc_scsi_q.q1.cntl |= QC_SG_HEAD;
6783: asc_scsi_q.sg_head = &asc_sg_head;
6784: asc_scsi_q.q1.data_cnt = 0;
6785: asc_scsi_q.q1.data_addr = 0;
6786: asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
6787: ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt);
6788:
6789: /*
6790: * Convert scatter-gather list into ASC_SG_HEAD list.
6791: */
6792: slp = (struct scatterlist *) scp->request_buffer;
6793: for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
6794: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6795: asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
6796: #else /* version >= v2.0.0 */
6797: asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
6798: #endif /* version >= v2.0.0 */
6799: asc_sg_head.sg_list[sgcnt].bytes = slp->length;
6800: ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
6801: }
6802: }
6803:
6804: ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
6805: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
6806:
6807: return ASC_NOERROR;
6808: }
6809:
6810: /*
6811: * Build a request structure for the Adv Library (Wide Board).
6812: *
6813: * If an adv_req_t can not be allocated to issue the request,
6814: * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
6815: */
6816: STATIC int
6817: adv_build_req(asc_board_t *boardp, Scsi_Cmnd *scp,
6818: ADV_SCSI_REQ_Q **adv_scsiqpp)
6819: {
6820: adv_req_t *reqp;
6821: ADV_SCSI_REQ_Q *scsiqp;
6822: int i;
6823:
6824: /*
6825: * Allocate an adv_req_t structure from the board to execute
6826: * the command.
6827: */
6828: if (boardp->adv_reqp == NULL) {
6829: ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
6830: ASC_STATS(scp->host, adv_build_noreq);
6831: return ASC_BUSY;
6832: } else {
6833: reqp = boardp->adv_reqp;
6834: boardp->adv_reqp = reqp->next_reqp;
6835: reqp->next_reqp = NULL;
6836: }
6837:
6838: /*
6839: * Get 4-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
6840: */
6841: scsiqp = (ADV_SCSI_REQ_Q *) ADV_DWALIGN(&reqp->scsi_req_q);
6842: memset(scsiqp, 0, sizeof(ADV_SCSI_REQ_Q));
6843:
6844: /*
6845: * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
6846: */
6847: scsiqp->srb_ptr = (ulong) reqp;
6848:
6849: /*
6850: * Set the adv_req_t 'cmndp' to point to the Scsi_Cmnd structure.
6851: */
6852: reqp->cmndp = scp;
6853:
6854: /*
6855: * Build the ADV_SCSI_REQ_Q request.
6856: */
6857:
6858: /*
6859: * Set CDB length and copy it to the request structure.
6860: */
6861: ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
6862: if (scp->cmd_len > ASC_MAX_CDB_LEN) {
6863: scp->cmd_len = ASC_MAX_CDB_LEN;
6864: }
6865: scsiqp->cdb_len = scp->cmd_len;
6866: for (i = 0; i < scp->cmd_len; i++) {
6867: scsiqp->cdb[i] = scp->cmnd[i];
6868: }
6869:
6870: scsiqp->target_id = scp->target;
6871: scsiqp->target_lun = scp->lun;
6872:
6873: scsiqp->vsense_addr = (ulong) &scp->sense_buffer[0];
6874: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6875: scsiqp->sense_addr = (ulong) &scp->sense_buffer[0];
6876: #else /* version >= v2.0.0 */
6877: scsiqp->sense_addr = virt_to_bus(&scp->sense_buffer[0]);
6878: #endif /* version >= v2.0.0 */
6879: scsiqp->sense_len = sizeof(scp->sense_buffer);
6880:
6881: /*
6882: * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
6883: * buffer command.
6884: */
6885: scsiqp->data_cnt = scp->request_bufflen;
6886: scsiqp->vdata_addr = (ulong) scp->request_buffer;
6887: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6888: scsiqp->data_addr = (ulong) scp->request_buffer;
6889: #else /* version >= v2.0.0 */
6890: scsiqp->data_addr = virt_to_bus(scp->request_buffer);
6891: #endif /* version >= v2.0.0 */
6892:
6893: if (scp->use_sg == 0) {
6894: /*
6895: * CDB request of single contiguous buffer.
6896: */
6897: reqp->sgblkp = NULL;
6898: scsiqp->sg_list_ptr = NULL;
6899: ASC_STATS(scp->host, cont_cnt);
6900: ASC_STATS_ADD(scp->host, cont_xfer,
6901: ASC_CEILING(scp->request_bufflen, 512));
6902: } else {
6903: /*
6904: * CDB scatter-gather request list.
6905: */
6906: if (scp->use_sg > ADV_MAX_SG_LIST) {
6907: ASC_PRINT3(
6908: "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
6909: boardp->id, scp->use_sg, scp->host->sg_tablesize);
6910: scp->result = HOST_BYTE(DID_ERROR);
6911: asc_enqueue(&boardp->done, scp, ASC_BACK);
6912:
6913: /*
6914: * Free the 'adv_req_t' structure by adding it back to the
6915: * board free list.
6916: */
6917: reqp->next_reqp = boardp->adv_reqp;
6918: boardp->adv_reqp = reqp;
6919:
6920: return ASC_ERROR;
6921: }
6922:
6923: /*
6924: * Allocate an 'adv_sgblk_t' structure from the board to
6925: * execute the command.
6926: */
6927: if (boardp->adv_sgblkp == NULL) {
6928: ASC_DBG(1, "adv_build_req: no free adv_sgblk_t\n");
6929: ASC_STATS(scp->host, adv_build_nosg);
6930: /*
6931: * Free the 'adv_req_t' structure by adding it back to the
6932: * board free list.
6933: */
6934: reqp->next_reqp = boardp->adv_reqp;
6935: boardp->adv_reqp = reqp;
6936: return ASC_BUSY;
6937: } else {
6938: reqp->sgblkp = boardp->adv_sgblkp;
6939: boardp->adv_sgblkp = reqp->sgblkp->next_sgblkp;
6940: reqp->sgblkp->next_sgblkp = NULL;
6941: }
6942:
6943: /*
6944: * Build scatter-gather list.
6945: */
6946: scsiqp->sg_list_ptr = (ADV_SG_BLOCK *)
6947: ADV_DWALIGN(&reqp->sgblkp->sg_block[0]);
6948:
6949: memset(scsiqp->sg_list_ptr, 0, sizeof(ADV_SG_BLOCK) *
6950: (ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING));
6951:
6952: if (adv_get_sglist(&boardp->dvc_var.adv_dvc_var, scsiqp, scp) ==
6953: ADV_ERROR) {
6954:
6955: /*
6956: * Free the adv_sgblk_t structure, if any, by adding it back
6957: * to the board free list.
6958: */
6959: ASC_ASSERT(reqp->sgblkp != NULL);
6960: reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
6961: boardp->adv_sgblkp = reqp->sgblkp;
6962:
6963: /*
6964: * Free the adv_req_t structure by adding it back to the
6965: * board free list.
6966: */
6967: reqp->next_reqp = boardp->adv_reqp;
6968: boardp->adv_reqp = reqp;
6969:
6970: return ADV_ERROR;
6971: }
6972:
6973: ASC_STATS(scp->host, sg_cnt);
6974: ASC_STATS_ADD(scp->host, sg_elem, scp->use_sg);
6975: }
6976:
6977: ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
6978: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
6979:
6980: *adv_scsiqpp = scsiqp;
6981:
6982: return ASC_NOERROR;
6983: }
6984:
6985: /*
6986: * Build scatter-gather list for Adv Library (Wide Board).
6987: *
6988: * Return:
6989: * ADV_SUCCESS(1) - SG List successfully created
6990: * ADV_ERROR(-1) - SG List creation failed
6991: */
6992: STATIC int
6993: adv_get_sglist(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp,
6994: Scsi_Cmnd *scp)
6995: {
6996: ADV_SG_BLOCK *sg_block; /* virtual address of a SG */
6997: ulong sg_block_next_addr; /* block and its next */
6998: ulong sg_block_physical_addr;
6999: int sg_block_index, i; /* how many SG entries */
7000: struct scatterlist *slp;
7001: int sg_elem_cnt;
7002:
7003: slp = (struct scatterlist *) scp->request_buffer;
7004: sg_elem_cnt = scp->use_sg;
7005:
7006: sg_block = scsiqp->sg_list_ptr;
7007: sg_block_next_addr = (ulong) sg_block; /* allow math operation */
7008: sg_block_physical_addr =
7009: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7010: (ulong) scsiqp->sg_list_ptr;
7011: #else /* version >= v2.0.0 */
7012: virt_to_bus(scsiqp->sg_list_ptr);
7013: #endif /* version >= v2.0.0 */
7014: ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7015: sg_block_physical_addr);
7016: scsiqp->sg_real_addr = sg_block_physical_addr;
7017:
7018: sg_block_index = 0;
7019: do
7020: {
7021: sg_block->first_entry_no = sg_block_index;
7022: for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
7023: {
7024: sg_block->sg_list[i].sg_addr =
7025: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7026: (ulong) slp->address;
7027: #else /* version >= v2.0.0 */
7028: virt_to_bus(slp->address);
7029: #endif /* version >= v2.0.0 */
7030: sg_block->sg_list[i].sg_count = slp->length;
7031: ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
7032:
7033: if (--sg_elem_cnt == 0)
7034: { /* last entry, get out */
7035: scsiqp->sg_entry_cnt = sg_block_index + i + 1;
7036: sg_block->last_entry_no = sg_block_index + i;
7037: sg_block->sg_ptr = 0L; /* next link = NULL */
7038: return ADV_SUCCESS;
7039: }
7040: slp++;
7041: }
7042: sg_block_next_addr += sizeof(ADV_SG_BLOCK);
7043: sg_block_physical_addr += sizeof(ADV_SG_BLOCK);
7044: ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7045: sg_block_physical_addr);
7046:
7047: sg_block_index += NO_OF_SG_PER_BLOCK;
7048: sg_block->sg_ptr = (ADV_SG_BLOCK *) sg_block_physical_addr;
7049: sg_block->last_entry_no = sg_block_index - 1;
7050: sg_block = (ADV_SG_BLOCK *) sg_block_next_addr; /* virtual addr */
7051: }
7052: while (1);
7053: /* NOTREACHED */
7054: }
7055:
7056: /*
7057: * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
7058: *
7059: * Interrupt callback function for the Narrow SCSI Asc Library.
7060: */
7061: STATIC void
7062: asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
7063: {
7064: asc_board_t *boardp;
7065: Scsi_Cmnd *scp;
7066: struct Scsi_Host *shp;
7067: int underrun = ASC_FALSE;
7068: int i;
7069:
7070: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7071: ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n",
7072: (unsigned) asc_dvc_varp, (unsigned) qdonep);
7073: ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
7074:
7075: /*
7076: * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7077: * command that has been completed.
7078: */
7079: scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
7080: ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
7081:
7082: if (scp == NULL) {
7083: ASC_PRINT("asc_isr_callback: scp is NULL\n");
7084: return;
7085: }
7086: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7087:
7088: /*
7089: * If the request's host pointer is not valid, display a
7090: * message and return.
7091: */
7092: shp = scp->host;
7093: for (i = 0; i < asc_board_count; i++) {
7094: if (asc_host[i] == shp) {
7095: break;
7096: }
7097: }
7098: if (i == asc_board_count) {
7099: ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n",
7100: (unsigned) scp, (unsigned) shp);
7101: return;
7102: }
7103:
7104: ASC_STATS(shp, callback);
7105: ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
7106:
7107: /*
7108: * If the request isn't found on the active queue, it may
7109: * have been removed to handle a reset or abort request.
7110: * Display a message and return.
7111: */
7112: boardp = ASC_BOARDP(shp);
7113: ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
7114: if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7115: ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
7116: boardp->id, (unsigned) scp);
7117: return;
7118: }
7119:
7120: /*
7121: * Check for an underrun condition.
7122: */
7123: if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
7124: qdonep->remain_bytes <= scp->request_bufflen != 0) {
7125: ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
7126: (unsigned) qdonep->remain_bytes);
7127: underrun = ASC_TRUE;
7128: }
7129:
7130: /*
7131: * 'qdonep' contains the command's ending status.
7132: */
7133: switch (qdonep->d3.done_stat) {
7134: case QD_NO_ERROR:
7135: ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
7136: switch (qdonep->d3.host_stat) {
7137: case QHSTA_NO_ERROR:
7138: scp->result = 0;
7139: break;
7140: default:
7141: /* QHSTA error occurred */
7142: scp->result = HOST_BYTE(DID_ERROR);
7143: break;
7144: }
7145:
7146: /*
7147: * If an INQUIRY command completed successfully, then call
7148: * the AscInquiryHandling() function to set-up the device.
7149: */
7150: if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 &&
7151: (scp->request_bufflen - qdonep->remain_bytes) >= 8)
7152: {
7153: AscInquiryHandling(asc_dvc_varp, scp->target & 0x7,
7154: (ASC_SCSI_INQUIRY *) scp->request_buffer);
7155: }
7156:
7157: /*
7158: * If there was an underrun without any other error,
7159: * set DID_ERROR to indicate the underrun error.
7160: *
7161: * Note: There is no way yet to indicate the number
7162: * of underrun bytes.
7163: */
7164: if (scp->result == 0 && underrun == ASC_TRUE) {
7165: scp->result = HOST_BYTE(DID_UNDERRUN);
7166: }
7167: break;
7168:
7169: case QD_WITH_ERROR:
7170: ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
7171: switch (qdonep->d3.host_stat) {
7172: case QHSTA_NO_ERROR:
7173: if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
7174: ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
7175: ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7176: sizeof(scp->sense_buffer));
7177: /*
7178: * Note: The 'status_byte()' macro used by target drivers
7179: * defined in scsi.h shifts the status byte returned by
7180: * host drivers right by 1 bit. This is why target drivers
7181: * also use right shifted status byte definitions. For
7182: * instance target drivers use CHECK_CONDITION, defined to
7183: * 0x1, instead of the SCSI defined check condition value
7184: * of 0x2. Host drivers are supposed to return the status
7185: * byte as it is defined by SCSI.
7186: */
7187: scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7188: STATUS_BYTE(qdonep->d3.scsi_stat);
7189: } else {
7190: scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
7191: }
7192: break;
7193:
7194: default:
7195: /* QHSTA error occurred */
7196: ASC_DBG1(1, "asc_isr_callback: host_stat %x\n",
7197: qdonep->d3.host_stat);
7198: scp->result = HOST_BYTE(DID_BAD_TARGET);
7199: break;
7200: }
7201: break;
7202:
7203: case QD_ABORTED_BY_HOST:
7204: ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
7205: scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
7206: STATUS_BYTE(qdonep->d3.scsi_stat);
7207: break;
7208:
7209: default:
7210: ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
7211: scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
7212: STATUS_BYTE(qdonep->d3.scsi_stat);
7213: break;
7214: }
7215:
7216: /*
7217: * If the 'init_tidmask' bit isn't already set for the target and the
7218: * current request finished normally, then set the bit for the target
7219: * to indicate that a device is present.
7220: */
7221: if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7222: qdonep->d3.done_stat == QD_NO_ERROR &&
7223: qdonep->d3.host_stat == QHSTA_NO_ERROR) {
7224: boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7225: }
7226:
7227: /*
7228: * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7229: * function, add the command to the end of the board's done queue.
7230: * The done function for the command will be called from
7231: * advansys_interrupt().
7232: */
7233: asc_enqueue(&boardp->done, scp, ASC_BACK);
7234:
7235: return;
7236: }
7237:
7238: /*
7239: * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
7240: *
7241: * Callback function for the Wide SCSI Adv Library.
7242: */
7243: STATIC void
7244: adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
7245: {
7246: asc_board_t *boardp;
7247: adv_req_t *reqp;
7248: Scsi_Cmnd *scp;
7249: struct Scsi_Host *shp;
7250: int underrun = ASC_FALSE;
7251: int i;
7252:
7253: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7254: ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %x, scsiqp %x\n",
7255: (unsigned) adv_dvc_varp, (unsigned) scsiqp);
7256: ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
7257:
7258: /*
7259: * Get the adv_req_t structure for the command that has been
7260: * completed. The adv_req_t structure actually contains the
7261: * completed ADV_SCSI_REQ_Q structure.
7262: */
7263: reqp = (adv_req_t *) scsiqp->srb_ptr;
7264: ASC_DBG1(1, "adv_isr_callback: reqp %x\n", (unsigned) reqp);
7265: if (reqp == NULL) {
7266: ASC_PRINT("adv_isr_callback: reqp is NULL\n");
7267: return;
7268: }
7269:
7270: /*
7271: * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7272: * command that has been completed.
7273: *
7274: * Note: The adv_req_t request structure and adv_sgblk_t structure,
7275: * if any, * dropped, because a board structure pointer can not be
7276: * determined.
7277: */
7278: scp = reqp->cmndp;
7279: ASC_DBG1(1, "adv_isr_callback: scp %x\n", (unsigned) scp);
7280: if (scp == NULL) {
7281: ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
7282: return;
7283: }
7284: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7285:
7286: /*
7287: * If the request's host pointer is not valid, display a message
7288: * and return.
7289: */
7290: shp = scp->host;
7291: for (i = 0; i < asc_board_count; i++) {
7292: if (asc_host[i] == shp) {
7293: break;
7294: }
7295: }
7296: /*
7297: * Note: If the host structure is not found, the adv_req_t request
7298: * structure and adv_sgblk_t structure, if any, is dropped.
7299: */
7300: if (i == asc_board_count) {
7301: ASC_PRINT2("adv_isr_callback: scp %x has bad host pointer, host %x\n",
7302: (unsigned) scp, (unsigned) shp);
7303: return;
7304: }
7305:
7306: ASC_STATS(shp, callback);
7307: ASC_DBG1(1, "adv_isr_callback: shp %x\n", (unsigned) shp);
7308:
7309: /*
7310: * If the request isn't found on the active queue, it may have been
7311: * removed to handle a reset or abort request. Display a message and
7312: * return.
7313: *
7314: * Note: Because the structure may still be in use don't attempt
7315: * to free the adv_req_t and adv_sgblk_t, if any, structures.
7316: */
7317: boardp = ASC_BOARDP(shp);
7318: ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
7319: if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7320: ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n",
7321: boardp->id, (unsigned) scp);
7322: return;
7323: }
7324:
7325: /*
7326: * Check for an underrun condition.
7327: */
7328: if (scp->request_bufflen != 0 && scsiqp->data_cnt != 0) {
7329: ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n",
7330: scsiqp->data_cnt);
7331: underrun = ASC_TRUE;
7332: }
7333:
7334: /*
7335: * 'done_status' contains the command's ending status.
7336: */
7337: switch (scsiqp->done_status) {
7338: case QD_NO_ERROR:
7339: ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
7340: switch (scsiqp->host_status) {
7341: case QHSTA_NO_ERROR:
7342: scp->result = 0;
7343: break;
7344: default:
7345: /* QHSTA error occurred. */
7346: ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
7347: scsiqp->host_status);
7348: scp->result = HOST_BYTE(DID_ERROR);
7349: break;
7350: }
7351: /*
7352: * If there was an underrun without any other error,
7353: * set DID_ERROR to indicate the underrun error.
7354: *
7355: * Note: There is no way yet to indicate the number
7356: * of underrun bytes.
7357: */
7358: if (scp->result == 0 && underrun == ASC_TRUE) {
7359: scp->result = HOST_BYTE(DID_UNDERRUN);
7360: }
7361: break;
7362:
7363: case QD_WITH_ERROR:
7364: ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
7365: switch (scsiqp->host_status) {
7366: case QHSTA_NO_ERROR:
7367: if (scsiqp->scsi_status == SS_CHK_CONDITION) {
7368: ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n");
7369: ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7370: sizeof(scp->sense_buffer));
7371: /*
7372: * Note: The 'status_byte()' macro used by target drivers
7373: * defined in scsi.h shifts the status byte returned by
7374: * host drivers right by 1 bit. This is why target drivers
7375: * also use right shifted status byte definitions. For
7376: * instance target drivers use CHECK_CONDITION, defined to
7377: * 0x1, instead of the SCSI defined check condition value
7378: * of 0x2. Host drivers are supposed to return the status
7379: * byte as it is defined by SCSI.
7380: */
7381: scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7382: STATUS_BYTE(scsiqp->scsi_status);
7383: } else {
7384: scp->result = STATUS_BYTE(scsiqp->scsi_status);
7385: }
7386: break;
7387:
7388: default:
7389: /* Some other QHSTA error occurred. */
7390: ASC_DBG1(1, "adv_isr_callback: host_status %x\n",
7391: scsiqp->host_status);
7392: scp->result = HOST_BYTE(DID_BAD_TARGET);
7393: break;
7394: }
7395: break;
7396:
7397: case QD_ABORTED_BY_HOST:
7398: ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
7399: scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
7400: break;
7401:
7402: default:
7403: ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status);
7404: scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
7405: break;
7406: }
7407:
7408: /*
7409: * If the 'init_tidmask' bit isn't already set for the target and the
7410: * current request finished normally, then set the bit for the target
7411: * to indicate that a device is present.
7412: */
7413: if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7414: scsiqp->done_status == QD_NO_ERROR &&
7415: scsiqp->host_status == QHSTA_NO_ERROR) {
7416: boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7417: }
7418:
7419: /*
7420: * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7421: * function, add the command to the end of the board's done queue.
7422: * The done function for the command will be called from
7423: * advansys_interrupt().
7424: */
7425: asc_enqueue(&boardp->done, scp, ASC_BACK);
7426:
7427: /*
7428: * Free the adv_sgblk_t structure, if any, by adding it back
7429: * to the board free list.
7430: */
7431: if (reqp->sgblkp != NULL) {
7432: reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
7433: boardp->adv_sgblkp = reqp->sgblkp;
7434: }
7435:
7436: /*
7437: * Free the adv_req_t structure used with the command by adding
7438: * it back to the board free list.
7439: */
7440: reqp->next_reqp = boardp->adv_reqp;
7441: boardp->adv_reqp = reqp;
7442:
7443: ASC_DBG(1, "adv_isr_callback: done\n");
7444:
7445: return;
7446: }
7447:
7448: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
7449: #ifdef ASC_CONFIG_PCI
7450: /*
7451: * Search for an AdvanSys PCI device in the PCI configuration space.
7452: */
7453: ASC_INITFUNC(
7454: STATIC int
7455: asc_srch_pci_dev(PCI_DEVICE *pciDevice)
7456: )
7457: {
7458: int ret = PCI_DEVICE_NOT_FOUND;
7459:
7460: ASC_DBG(2, "asc_srch_pci_dev: begin\n");
7461:
7462: if (pci_scan_method == -1) {
7463: pci_scan_method = asc_scan_method();
7464: }
7465: pciDevice->type = pci_scan_method;
7466: ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
7467:
7468: ret = asc_pci_find_dev(pciDevice);
7469: ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
7470: if (ret == PCI_DEVICE_FOUND) {
7471: pciDevice->slotNumber = pciDevice->slotFound + 1;
7472: pciDevice->startSlot = pciDevice->slotFound + 1;
7473: } else {
7474: if (pciDevice->bridge > pciDevice->busNumber) {
7475: ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
7476: pciDevice->bridge, pciDevice->busNumber);
7477: pciDevice->busNumber++;
7478: pciDevice->slotNumber = 0;
7479: pciDevice->startSlot = 0;
7480: pciDevice->endSlot = 0x0f;
7481: ret = asc_srch_pci_dev(pciDevice);
7482: ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
7483: }
7484: }
7485:
7486: ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
7487: return ret;
7488: }
7489:
7490: /*
7491: * Determine the access method to be used for 'pciDevice'.
7492: */
7493: ASC_INITFUNC(
7494: STATIC uchar
7495: asc_scan_method(void)
7496: )
7497: {
7498: ushort data;
7499: PCI_DATA pciData;
7500: uchar type;
7501: uchar slot;
7502:
7503: ASC_DBG(2, "asc_scan_method: begin\n");
7504: memset(&pciData, 0, sizeof(pciData));
7505: for (type = 1; type < 3; type++) {
7506: pciData.type = type;
7507: for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
7508: pciData.slot = slot;
7509: data = asc_get_cfg_word(&pciData);
7510: if ((data != 0xFFFF) && (data != 0x0000)) {
7511: ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
7512: return (type);
7513: }
7514: }
7515: }
7516: ASC_DBG1(4, "asc_scan_method: type %d\n", type);
7517: return (type);
7518: }
7519:
7520: /*
7521: * Check for an AdvanSys PCI device in 'pciDevice'.
7522: *
7523: * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
7524: */
7525: ASC_INITFUNC(
7526: STATIC int
7527: asc_pci_find_dev(PCI_DEVICE *pciDevice)
7528: )
7529: {
7530: PCI_DATA pciData;
7531: ushort vendorid, deviceid;
7532: uchar classcode, subclass;
7533: uchar lslot;
7534:
7535: ASC_DBG(3, "asc_pci_find_dev: begin\n");
7536: pciData.type = pciDevice->type;
7537: pciData.bus = pciDevice->busNumber;
7538: pciData.func = pciDevice->devFunc;
7539: lslot = pciDevice->startSlot;
7540: for (; lslot < pciDevice->endSlot; lslot++) {
7541: pciData.slot = lslot;
7542: pciData.offset = VENDORID_OFFSET;
7543: vendorid = asc_get_cfg_word(&pciData);
7544: ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
7545: if (vendorid != 0xffff) {
7546: pciData.offset = DEVICEID_OFFSET;
7547: deviceid = asc_get_cfg_word(&pciData);
7548: ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
7549: if ((vendorid == ASC_PCI_VENDORID) &&
7550: ((deviceid == ASC_PCI_DEVICE_ID_1100) ||
7551: (deviceid == ASC_PCI_DEVICE_ID_1200) ||
7552: (deviceid == ASC_PCI_DEVICE_ID_1300) ||
7553: (deviceid == ASC_PCI_DEVICE_ID_2300))) {
7554: pciDevice->slotFound = lslot;
7555: ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
7556: return PCI_DEVICE_FOUND;
7557: } else {
7558: pciData.offset = SUBCLASS_OFFSET;
7559: subclass = asc_get_cfg_byte(&pciData);
7560: pciData.offset = CLASSCODE_OFFSET;
7561: classcode = asc_get_cfg_byte(&pciData);
7562: if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
7563: (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
7564: pciDevice->bridge++;
7565: }
7566: ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
7567: subclass, classcode);
7568: }
7569: }
7570: }
7571: return PCI_DEVICE_NOT_FOUND;
7572: }
7573:
7574: /*
7575: * Read PCI configuration data into 'pciConfig'.
7576: */
7577: ASC_INITFUNC(
7578: STATIC void
7579: asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
7580: )
7581: {
7582: PCI_DATA pciData;
7583: uchar counter;
7584: uchar *localConfig;
7585:
7586: ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ",
7587: pciDevice->slotFound);
7588:
7589: pciData.type = pciDevice->type;
7590: pciData.bus = pciDevice->busNumber;
7591: pciData.slot = pciDevice->slotFound;
7592: pciData.func = pciDevice->devFunc;
7593: localConfig = (uchar *) pciConfig;
7594:
7595: for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
7596: pciData.offset = counter;
7597: *localConfig = asc_get_cfg_byte(&pciData);
7598: ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
7599: localConfig++;
7600: }
7601: ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
7602: }
7603:
7604: /*
7605: * Read a word (16 bits) from the PCI configuration space.
7606: *
7607: * The configuration mechanism is checked for the correct access method.
7608: */
7609: ASC_INITFUNC(
7610: STATIC ushort
7611: asc_get_cfg_word(PCI_DATA *pciData)
7612: )
7613: {
7614: ushort tmp;
7615: ulong address;
7616: ulong lbus = pciData->bus;
7617: ulong lslot = pciData->slot;
7618: ulong lfunc = pciData->func;
7619: uchar t2CFA, t2CF8;
7620: ulong t1CF8, t1CFC;
7621:
7622: ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
7623: pciData->type, lbus, lslot, lfunc);
7624:
7625: /*
7626: * Check type of configuration mechanism.
7627: */
7628: if (pciData->type == 2) {
7629: /*
7630: * Save registers to be restored later.
7631: */
7632: t2CFA = inp(0xCFA); /* save PCI bus register */
7633: t2CF8 = inp(0xCF8); /* save config space enable register */
7634:
7635: /*
7636: * Write the bus and enable registers.
7637: */
7638: /* set for type 1 cycle, if needed */
7639: outp(0xCFA, pciData->bus);
7640: /* set the function number */
7641: outp(0xCF8, 0x10 | (pciData->func << 1)) ;
7642:
7643: /*
7644: * Read the configuration space type 2 locations.
7645: */
7646: tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
7647:
7648: outp(0xCFA, t2CFA); /* save PCI bus register */
7649: outp(0xCF8, t2CF8); /* save config space enable register */
7650: } else {
7651: /*
7652: * Type 1 or 3 configuration mechanism.
7653: *
7654: * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
7655: */
7656: t1CF8 = inpl(0xCF8);
7657: t1CFC = inpl(0xCFC);
7658:
7659: /*
7660: * enable <31>, bus = <23:16>, slot = <15:11>,
7661: * func = <10:8>, reg = <7:2>
7662: */
7663: address = (ulong) ((lbus << 16) | (lslot << 11) |
7664: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
7665:
7666: /*
7667: * Write out the address to CONFIG_ADDRESS.
7668: */
7669: outpl(0xCF8, address);
7670:
7671: /*
7672: * Read in word from CONFIG_DATA.
7673: */
7674: tmp = (ushort) ((inpl(0xCFC) >>
7675: ((pciData->offset & 2) * 8)) & 0xFFFF);
7676:
7677: /*
7678: * Restore registers.
7679: */
7680: outpl(0xCF8, t1CF8);
7681: outpl(0xCFC, t1CFC);
7682: }
7683: ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
7684: return tmp;
7685: }
7686:
7687: /*
7688: * Reads a byte from the PCI configuration space.
7689: *
7690: * The configuration mechanism is checked for the correct access method.
7691: */
7692: ASC_INITFUNC(
7693: STATIC uchar
7694: asc_get_cfg_byte(PCI_DATA *pciData)
7695: )
7696: {
7697: uchar tmp;
7698: ulong address;
7699: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
7700: uchar t2CFA, t2CF8;
7701: ulong t1CF8, t1CFC;
7702:
7703: ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
7704:
7705: /*
7706: * Check type of configuration mechanism.
7707: */
7708: if (pciData->type == 2) {
7709: /*
7710: * Save registers to be restored later.
7711: */
7712: t2CFA = inp(0xCFA); /* save PCI bus register */
7713: t2CF8 = inp(0xCF8); /* save config space enable register */
7714:
7715: /*
7716: * Write the bus and enable registers.
7717: */
7718: /* set for type 1 cycle, if needed */
7719: outp(0xCFA, pciData->bus);
7720: /* set the function number */
7721: outp(0xCF8, 0x10 | (pciData->func << 1));
7722:
7723: /*
7724: * Read configuration space type 2 locations.
7725: */
7726: tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
7727:
7728: /*
7729: * Restore registers.
7730: */
7731: outp(0xCF8, t2CF8); /* restore the enable register */
7732: outp(0xCFA, t2CFA); /* restore PCI bus register */
7733: } else {
7734: /*
7735: * Type 1 or 3 configuration mechanism.
7736: *
7737: * Save CONFIG_ADDRESS and CONFIG_DATA register values.
7738: */
7739: t1CF8 = inpl(0xCF8);
7740: t1CFC = inpl(0xCFC);
7741:
7742: /*
7743: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
7744: * reg = <7:2>
7745: */
7746: address = (ulong) ((lbus << 16) | (lslot << 11) |
7747: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
7748:
7749: /*
7750: * Write out address to CONFIG_ADDRESS.
7751: */
7752: outpl(0xCF8, address);
7753:
7754: /*
7755: * Read in word from CONFIG_DATA.
7756: */
7757: tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
7758:
7759: /*
7760: * Restore registers.
7761: */
7762: outpl(0xCF8, t1CF8);
7763: outpl(0xCFC, t1CFC);
7764: }
7765: ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
7766: return tmp;
7767: }
7768:
7769: /*
7770: * Write a byte to the PCI configuration space.
7771: */
7772: ASC_INITFUNC(
7773: STATIC void
7774: asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
7775: )
7776: {
7777: ulong tmpl;
7778: ulong address;
7779: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
7780: uchar t2CFA, t2CF8;
7781: ulong t1CF8, t1CFC;
7782:
7783: ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n",
7784: pciData->type, byte_data);
7785:
7786: /*
7787: * Check type of configuration mechanism.
7788: */
7789: if (pciData->type == 2) {
7790:
7791: /*
7792: * Save registers to be restored later.
7793: */
7794: t2CFA = inp(0xCFA); /* save PCI bus register */
7795: t2CF8 = inp(0xCF8); /* save config space enable register */
7796:
7797: /*
7798: * Write bus and enable registers.
7799: */
7800: outp(0xCFA, pciData->bus);
7801:
7802: /*
7803: * Set the function number.
7804: */
7805: outp(0xCF8, 0x10 | (pciData->func << 1));
7806:
7807: /*
7808: * Write the configuration space type 2 locations.
7809: */
7810: outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data);
7811:
7812: /*
7813: * Restore registers.
7814: */
7815: outp(0xCF8, t2CF8); /* restore the enable register */
7816: outp(0xCFA, t2CFA); /* restore PCI bus register */
7817: } else {
7818:
7819: /*
7820: * Type 1 or 3 configuration mechanism.
7821: *
7822: * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
7823: */
7824: t1CF8 = inpl(0xCF8);
7825: t1CFC = inpl(0xCFC);
7826:
7827: /*
7828: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
7829: * reg = <7:2>
7830: */
7831: address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) |
7832: (pciData->offset & 0xFC) | 0x80000000L);
7833: /*
7834: * Write out address to CONFIG_ADDRESS.
7835: */
7836: outpl(0xCF8, address);
7837:
7838: /*
7839: * Write double word to CONFIG_DATA preserving the bytes
7840: * in the double not written.
7841: */
7842: tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8));
7843: outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8)));
7844:
7845: /*
7846: * Restore registers.
7847: */
7848: outpl(0xCF8, t1CF8);
7849: outpl(0xCFC, t1CFC);
7850: }
7851: ASC_DBG(4, "asc_put_cfg_byte: end\n");
7852: }
7853: #endif /* ASC_CONFIG_PCI */
7854: #endif /* version < v2.1.93 */
7855:
7856: /*
7857: * Add a 'REQP' to the end of specified queue. Set 'tidmask'
7858: * to indicate a command is queued for the device.
7859: *
7860: * 'flag' may be either ASC_FRONT or ASC_BACK.
7861: *
7862: * 'REQPNEXT(reqp)' returns reqp's next pointer.
7863: */
7864: STATIC void
7865: asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
7866: {
7867: int tid;
7868:
7869: ASC_DBG3(3, "asc_enqueue: ascq %x, reqp %x, flag %d\n",
7870: (unsigned) ascq, (unsigned) reqp, flag);
7871: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7872: ASC_ASSERT(reqp != NULL);
7873: ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
7874: tid = REQPTID(reqp);
7875: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
7876: if (flag == ASC_FRONT) {
7877: REQPNEXT(reqp) = ascq->q_first[tid];
7878: ascq->q_first[tid] = reqp;
7879: /* If the queue was empty, set the last pointer. */
7880: if (ascq->q_last[tid] == NULL) {
7881: ascq->q_last[tid] = reqp;
7882: }
7883: } else { /* ASC_BACK */
7884: if (ascq->q_last[tid] != NULL) {
7885: REQPNEXT(ascq->q_last[tid]) = reqp;
7886: }
7887: ascq->q_last[tid] = reqp;
7888: REQPNEXT(reqp) = NULL;
7889: /* If the queue was empty, set the first pointer. */
7890: if (ascq->q_first[tid] == NULL) {
7891: ascq->q_first[tid] = reqp;
7892: }
7893: }
7894: /* The queue has at least one entry, set its bit. */
7895: ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
7896: #ifdef ADVANSYS_STATS
7897: /* Maintain request queue statistics. */
7898: ascq->q_tot_cnt[tid]++;
7899: ascq->q_cur_cnt[tid]++;
7900: if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
7901: ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
7902: ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
7903: tid, ascq->q_max_cnt[tid]);
7904: }
7905: REQPTIME(reqp) = REQTIMESTAMP();
7906: #endif /* ADVANSYS_STATS */
7907: ASC_DBG1(3, "asc_enqueue: reqp %x\n", (unsigned) reqp);
7908: return;
7909: }
7910:
7911: /*
7912: * Return first queued 'REQP' on the specified queue for
7913: * the specified target device. Clear the 'tidmask' bit for
7914: * the device if no more commands are left queued for it.
7915: *
7916: * 'REQPNEXT(reqp)' returns reqp's next pointer.
7917: */
7918: STATIC REQP
7919: asc_dequeue(asc_queue_t *ascq, int tid)
7920: {
7921: REQP reqp;
7922:
7923: ASC_DBG2(3, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid);
7924: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7925: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
7926: if ((reqp = ascq->q_first[tid]) != NULL) {
7927: ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
7928: ascq->q_first[tid] = REQPNEXT(reqp);
7929: /* If the queue is empty, clear its bit and the last pointer. */
7930: if (ascq->q_first[tid] == NULL) {
7931: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
7932: ASC_ASSERT(ascq->q_last[tid] == reqp);
7933: ascq->q_last[tid] = NULL;
7934: }
7935: #ifdef ADVANSYS_STATS
7936: /* Maintain request queue statistics. */
7937: ascq->q_cur_cnt[tid]--;
7938: ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
7939: REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
7940: #endif /* ADVANSYS_STATS */
7941: }
7942: ASC_DBG1(3, "asc_dequeue: reqp %x\n", (unsigned) reqp);
7943: return reqp;
7944: }
7945:
7946: /*
7947: * Return a pointer to a singly linked list of all the requests queued
7948: * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
7949: *
7950: * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
7951: * the last request returned in the singly linked list.
7952: *
7953: * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
7954: * then all queued requests are concatenated into one list and
7955: * returned.
7956: *
7957: * Note: If 'lastpp' is used to append a new list to the end of
7958: * an old list, only change the old list last pointer if '*lastpp'
7959: * (or the function return value) is not NULL, i.e. use a temporary
7960: * variable for 'lastpp' and check its value after the function return
7961: * before assigning it to the list last pointer.
7962: *
7963: * Unfortunately collecting queuing time statistics adds overhead to
7964: * the function that isn't inherent to the function's algorithm.
7965: */
7966: STATIC REQP
7967: asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
7968: {
7969: REQP firstp, lastp;
7970: int i;
7971:
7972: ASC_DBG2(3, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid);
7973: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7974: ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
7975:
7976: /*
7977: * If 'tid' is not ASC_TID_ALL, return requests only for
7978: * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
7979: * requests for all tids.
7980: */
7981: if (tid != ASC_TID_ALL) {
7982: /* Return all requests for the specified 'tid'. */
7983: if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
7984: /* List is empty; Set first and last return pointers to NULL. */
7985: firstp = lastp = NULL;
7986: } else {
7987: firstp = ascq->q_first[tid];
7988: lastp = ascq->q_last[tid];
7989: ascq->q_first[tid] = ascq->q_last[tid] = NULL;
7990: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
7991: #ifdef ADVANSYS_STATS
7992: {
7993: REQP reqp;
7994: ascq->q_cur_cnt[tid] = 0;
7995: for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
7996: REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
7997: }
7998: }
7999: #endif /* ADVANSYS_STATS */
8000: }
8001: } else {
8002: /* Return all requests for all tids. */
8003: firstp = lastp = NULL;
8004: for (i = 0; i <= ADV_MAX_TID; i++) {
8005: if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
8006: if (firstp == NULL) {
8007: firstp = ascq->q_first[i];
8008: lastp = ascq->q_last[i];
8009: } else {
8010: ASC_ASSERT(lastp != NULL);
8011: REQPNEXT(lastp) = ascq->q_first[i];
8012: lastp = ascq->q_last[i];
8013: }
8014: ascq->q_first[i] = ascq->q_last[i] = NULL;
8015: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8016: #ifdef ADVANSYS_STATS
8017: ascq->q_cur_cnt[i] = 0;
8018: #endif /* ADVANSYS_STATS */
8019: }
8020: }
8021: #ifdef ADVANSYS_STATS
8022: {
8023: REQP reqp;
8024: for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
8025: REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
8026: }
8027: }
8028: #endif /* ADVANSYS_STATS */
8029: }
8030: if (lastpp) {
8031: *lastpp = lastp;
8032: }
8033: ASC_DBG1(3, "asc_dequeue_list: firstp %x\n", (unsigned) firstp);
8034: return firstp;
8035: }
8036:
8037: /*
8038: * Remove the specified 'REQP' from the specified queue for
8039: * the specified target device. Clear the 'tidmask' bit for the
8040: * device if no more commands are left queued for it.
8041: *
8042: * 'REQPNEXT(reqp)' returns reqp's the next pointer.
8043: *
8044: * Return ASC_TRUE if the command was found and removed,
8045: * otherwise return ASC_FALSE.
8046: */
8047: STATIC int
8048: asc_rmqueue(asc_queue_t *ascq, REQP reqp)
8049: {
8050: REQP currp, prevp;
8051: int tid;
8052: int ret = ASC_FALSE;
8053:
8054: ASC_DBG2(3, "asc_rmqueue: ascq %x, reqp %x\n",
8055: (unsigned) ascq, (unsigned) reqp);
8056: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8057: ASC_ASSERT(reqp != NULL);
8058:
8059: tid = REQPTID(reqp);
8060: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8061:
8062: /*
8063: * Handle the common case of 'reqp' being the first
8064: * entry on the queue.
8065: */
8066: if (reqp == ascq->q_first[tid]) {
8067: ret = ASC_TRUE;
8068: ascq->q_first[tid] = REQPNEXT(reqp);
8069: /* If the queue is now empty, clear its bit and the last pointer. */
8070: if (ascq->q_first[tid] == NULL) {
8071: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
8072: ASC_ASSERT(ascq->q_last[tid] == reqp);
8073: ascq->q_last[tid] = NULL;
8074: }
8075: } else if (ascq->q_first[tid] != NULL) {
8076: ASC_ASSERT(ascq->q_last[tid] != NULL);
8077: /*
8078: * Because the case of 'reqp' being the first entry has been
8079: * handled above and it is known the queue is not empty, if
8080: * 'reqp' is found on the queue it is guaranteed the queue will
8081: * not become empty and that 'q_first[tid]' will not be changed.
8082: *
8083: * Set 'prevp' to the first entry, 'currp' to the second entry,
8084: * and search for 'reqp'.
8085: */
8086: for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
8087: currp; prevp = currp, currp = REQPNEXT(currp)) {
8088: if (currp == reqp) {
8089: ret = ASC_TRUE;
8090: REQPNEXT(prevp) = REQPNEXT(currp);
8091: REQPNEXT(reqp) = NULL;
8092: if (ascq->q_last[tid] == reqp) {
8093: ascq->q_last[tid] = prevp;
8094: }
8095: break;
8096: }
8097: }
8098: }
8099: #ifdef ADVANSYS_STATS
8100: /* Maintain request queue statistics. */
8101: if (ret == ASC_TRUE) {
8102: ascq->q_cur_cnt[tid]--;
8103: REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
8104: }
8105: ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
8106: #endif /* ADVANSYS_STATS */
8107: ASC_DBG2(3, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret);
8108: return ret;
8109: }
8110:
8111: /*
8112: * If the specified 'REQP' is queued on the specified queue for
8113: * the specified target device, return ASC_TRUE.
8114: */
8115: STATIC int
8116: asc_isqueued(asc_queue_t *ascq, REQP reqp)
8117: {
8118: REQP treqp;
8119: int tid;
8120: int ret = ASC_FALSE;
8121:
8122: ASC_DBG2(3, "asc_isqueued: ascq %x, reqp %x\n",
8123: (unsigned) ascq, (unsigned) reqp);
8124: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8125: ASC_ASSERT(reqp != NULL);
8126:
8127: tid = REQPTID(reqp);
8128: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8129:
8130: for (treqp = ascq->q_first[tid]; treqp; treqp = REQPNEXT(treqp)) {
8131: ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
8132: if (treqp == reqp) {
8133: ret = ASC_TRUE;
8134: break;
8135: }
8136: }
8137: ASC_DBG1(3, "asc_isqueued: ret %x\n", ret);
8138: return ret;
8139: }
8140:
8141: /*
8142: * Execute as many queued requests as possible for the specified queue.
8143: *
8144: * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd.
8145: */
8146: STATIC void
8147: asc_execute_queue(asc_queue_t *ascq)
8148: {
8149: ADV_SCSI_BIT_ID_TYPE scan_tidmask;
8150: REQP reqp;
8151: int i;
8152:
8153: ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq);
8154: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8155: /*
8156: * Execute queued commands for devices attached to
8157: * the current board in round-robin fashion.
8158: */
8159: scan_tidmask = ascq->q_tidmask;
8160: do {
8161: for (i = 0; i <= ADV_MAX_TID; i++) {
8162: if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
8163: if ((reqp = asc_dequeue(ascq, i)) == NULL) {
8164: scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8165: } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp)
8166: == ASC_BUSY) {
8167: scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8168: /* Put the request back at front of the list. */
8169: asc_enqueue(ascq, reqp, ASC_FRONT);
8170: }
8171: }
8172: }
8173: } while (scan_tidmask);
8174: return;
8175: }
8176:
8177: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
8178: /*
8179: * asc_prt_board_devices()
8180: *
8181: * Print driver information for devices attached to the board.
8182: *
8183: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8184: * cf. asc_prt_line().
8185: *
8186: * Return the number of characters copied into 'cp'. No more than
8187: * 'cplen' characters will be copied to 'cp'.
8188: */
8189: STATIC int
8190: asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
8191: {
8192: asc_board_t *boardp;
8193: int leftlen;
8194: int totlen;
8195: int len;
8196: int chip_scsi_id;
8197: int i;
8198:
8199: boardp = ASC_BOARDP(shp);
8200: leftlen = cplen;
8201: totlen = len = 0;
8202:
8203: len = asc_prt_line(cp, leftlen,
8204: "\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no);
8205: ASC_PRT_NEXT();
8206:
8207: if (ASC_NARROW_BOARD(boardp)) {
8208: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8209: } else {
8210: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8211: }
8212:
8213: len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
8214: ASC_PRT_NEXT();
8215: for (i = 0; i <= ADV_MAX_TID; i++) {
8216: if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
8217: len = asc_prt_line(cp, leftlen, " %X,", i);
8218: ASC_PRT_NEXT();
8219: }
8220: }
8221: len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
8222: ASC_PRT_NEXT();
8223:
8224: return totlen;
8225: }
8226:
8227: /*
8228: * Display Wide Board BIOS Information.
8229: */
8230: STATIC int
8231: asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen)
8232: {
8233: asc_board_t *boardp;
8234: int leftlen;
8235: int totlen;
8236: int len;
8237: int upgrade = ASC_FALSE;
8238: ushort major, minor, letter;
8239:
8240: boardp = ASC_BOARDP(shp);
8241: leftlen = cplen;
8242: totlen = len = 0;
8243:
8244: len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
8245: ASC_PRT_NEXT();
8246:
8247: /*
8248: * If the BIOS saved a valid signature, then fill in
8249: * the BIOS code segment base address.
8250: */
8251: if (boardp->bios_signature != 0x55AA) {
8252: len = asc_prt_line(cp, leftlen, "Pre-3.1\n");
8253: ASC_PRT_NEXT();
8254: upgrade = ASC_TRUE;
8255: } else {
8256: major = (boardp->bios_version >> 12) & 0xF;
8257: minor = (boardp->bios_version >> 8) & 0xF;
8258: letter = (boardp->bios_version & 0xFF);
8259:
8260: len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
8261: major, minor, letter >= 26 ? '?' : letter + 'A');
8262: ASC_PRT_NEXT();
8263:
8264: /* Current available ROM BIOS release is 3.1C. */
8265: if (major < 3 || (major <= 3 && minor < 1) ||
8266: (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) {
8267: upgrade = ASC_TRUE;
8268: }
8269: }
8270: if (upgrade == ASC_TRUE) {
8271: len = asc_prt_line(cp, leftlen,
8272: "Newer version of ROM BIOS available: ftp://ftp.advansys.com/pub\n");
8273: ASC_PRT_NEXT();
8274: }
8275:
8276: return totlen;
8277: }
8278:
8279: /*
8280: * Add serial number to information bar if signature AAh
8281: * is found in at bit 15-9 (7 bits) of word 1.
8282: *
8283: * Serial Number consists fo 12 alpha-numeric digits.
8284: *
8285: * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
8286: * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
8287: * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
8288: * 5 - Product revision (A-J) Word0: " "
8289: *
8290: * Signature Word1: 15-9 (7 bits)
8291: * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
8292: * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
8293: *
8294: * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
8295: *
8296: * Note 1: Only production cards will have a serial number.
8297: *
8298: * Note 2: Signature is most significant 7 bits (0xFE).
8299: *
8300: * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
8301: */
8302: STATIC int
8303: asc_get_eeprom_string(ushort *serialnum, uchar *cp)
8304: {
8305: ushort w, num;
8306:
8307: if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) {
8308: return ASC_FALSE;
8309: } else {
8310: /*
8311: * First word - 6 digits.
8312: */
8313: w = serialnum[0];
8314:
8315: /* Product type - 1st digit. */
8316: if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
8317: /* Product type is P=Prototype */
8318: *cp += 0x8;
8319: }
8320: cp++;
8321:
8322: /* Manufacturing location - 2nd digit. */
8323: *cp++ = 'A' + ((w & 0x1C00) >> 10);
8324:
8325: /* Product ID - 3rd, 4th digits. */
8326: num = w & 0x3FF;
8327: *cp++ = '0' + (num / 100);
8328: num %= 100;
8329: *cp++ = '0' + (num / 10);
8330:
8331: /* Product revision - 5th digit. */
8332: *cp++ = 'A' + (num % 10);
8333:
8334: /*
8335: * Second word
8336: */
8337: w = serialnum[1];
8338:
8339: /*
8340: * Year - 6th digit.
8341: *
8342: * If bit 15 of third word is set, then the
8343: * last digit of the year is greater than 7.
8344: */
8345: if (serialnum[2] & 0x8000) {
8346: *cp++ = '8' + ((w & 0x1C0) >> 6);
8347: } else {
8348: *cp++ = '0' + ((w & 0x1C0) >> 6);
8349: }
8350:
8351: /* Week of year - 7th, 8th digits. */
8352: num = w & 0x003F;
8353: *cp++ = '0' + num / 10;
8354: num %= 10;
8355: *cp++ = '0' + num;
8356:
8357: /*
8358: * Third word
8359: */
8360: w = serialnum[2] & 0x7FFF;
8361:
8362: /* Serial number - 9th digit. */
8363: *cp++ = 'A' + (w / 1000);
8364:
8365: /* 10th, 11th, 12th digits. */
8366: num = w % 1000;
8367: *cp++ = '0' + num / 100;
8368: num %= 100;
8369: *cp++ = '0' + num / 10;
8370: num %= 10;
8371: *cp++ = '0' + num;
8372:
8373: *cp = '\0'; /* Null Terminate the string. */
8374: return ASC_TRUE;
8375: }
8376: }
8377:
8378: /*
8379: * asc_prt_asc_board_eeprom()
8380: *
8381: * Print board EEPROM configuration.
8382: *
8383: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8384: * cf. asc_prt_line().
8385: *
8386: * Return the number of characters copied into 'cp'. No more than
8387: * 'cplen' characters will be copied to 'cp'.
8388: */
8389: STATIC int
8390: asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8391: {
8392: asc_board_t *boardp;
8393: ASC_DVC_VAR *asc_dvc_varp;
8394: int leftlen;
8395: int totlen;
8396: int len;
8397: ASCEEP_CONFIG *ep;
8398: int i;
8399: int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
8400: uchar serialstr[13];
8401:
8402: boardp = ASC_BOARDP(shp);
8403: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
8404: ep = &boardp->eep_config.asc_eep;
8405:
8406: leftlen = cplen;
8407: totlen = len = 0;
8408:
8409: len = asc_prt_line(cp, leftlen,
8410: "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8411: ASC_PRT_NEXT();
8412:
8413: if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) ==
8414: ASC_TRUE) {
8415: len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8416: ASC_PRT_NEXT();
8417: } else {
8418: if (ep->adapter_info[5] == 0xBB) {
8419: len = asc_prt_line(cp, leftlen,
8420: " Default Settings Used for EEPROM-less Adapter.\n");
8421: ASC_PRT_NEXT();
8422: } else {
8423: len = asc_prt_line(cp, leftlen,
8424: " Serial Number Signature Not Present.\n");
8425: ASC_PRT_NEXT();
8426: }
8427: }
8428:
8429: len = asc_prt_line(cp, leftlen,
8430: " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8431: ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng);
8432: ASC_PRT_NEXT();
8433:
8434: len = asc_prt_line(cp, leftlen,
8435: " cntl %x, no_scam %x\n",
8436: ep->cntl, ep->no_scam);
8437: ASC_PRT_NEXT();
8438:
8439: len = asc_prt_line(cp, leftlen,
8440: " Target ID: ");
8441: ASC_PRT_NEXT();
8442: for (i = 0; i <= ASC_MAX_TID; i++) {
8443: len = asc_prt_line(cp, leftlen, " %d", i);
8444: ASC_PRT_NEXT();
8445: }
8446: len = asc_prt_line(cp, leftlen, "\n");
8447: ASC_PRT_NEXT();
8448:
8449: len = asc_prt_line(cp, leftlen,
8450: " Disconnects: ");
8451: ASC_PRT_NEXT();
8452: for (i = 0; i <= ASC_MAX_TID; i++) {
8453: len = asc_prt_line(cp, leftlen, " %c",
8454: (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8455: ASC_PRT_NEXT();
8456: }
8457: len = asc_prt_line(cp, leftlen, "\n");
8458: ASC_PRT_NEXT();
8459:
8460: len = asc_prt_line(cp, leftlen,
8461: " Command Queuing: ");
8462: ASC_PRT_NEXT();
8463: for (i = 0; i <= ASC_MAX_TID; i++) {
8464: len = asc_prt_line(cp, leftlen, " %c",
8465: (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8466: ASC_PRT_NEXT();
8467: }
8468: len = asc_prt_line(cp, leftlen, "\n");
8469: ASC_PRT_NEXT();
8470:
8471: len = asc_prt_line(cp, leftlen,
8472: " Start Motor: ");
8473: ASC_PRT_NEXT();
8474: for (i = 0; i <= ASC_MAX_TID; i++) {
8475: len = asc_prt_line(cp, leftlen, " %c",
8476: (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8477: ASC_PRT_NEXT();
8478: }
8479: len = asc_prt_line(cp, leftlen, "\n");
8480: ASC_PRT_NEXT();
8481:
8482: len = asc_prt_line(cp, leftlen,
8483: " Synchronous Transfer:");
8484: ASC_PRT_NEXT();
8485: for (i = 0; i <= ASC_MAX_TID; i++) {
8486: len = asc_prt_line(cp, leftlen, " %c",
8487: (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8488: ASC_PRT_NEXT();
8489: }
8490: len = asc_prt_line(cp, leftlen, "\n");
8491: ASC_PRT_NEXT();
8492:
8493: if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
8494: len = asc_prt_line(cp, leftlen,
8495: " Host ISA DMA speed: %d MB/S\n",
8496: isa_dma_speed[ep->isa_dma_speed]);
8497: ASC_PRT_NEXT();
8498: }
8499:
8500: return totlen;
8501: }
8502:
8503: /*
8504: * asc_prt_adv_board_eeprom()
8505: *
8506: * Print board EEPROM configuration.
8507: *
8508: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8509: * cf. asc_prt_line().
8510: *
8511: * Return the number of characters copied into 'cp'. No more than
8512: * 'cplen' characters will be copied to 'cp'.
8513: */
8514: STATIC int
8515: asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8516: {
8517: asc_board_t *boardp;
8518: ADV_DVC_VAR *adv_dvc_varp;
8519: int leftlen;
8520: int totlen;
8521: int len;
8522: int i;
8523: char *termstr;
8524: uchar serialstr[13];
8525: ADVEEP_CONFIG *ep;
8526:
8527: boardp = ASC_BOARDP(shp);
8528: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
8529: ep = &boardp->eep_config.adv_eep;
8530:
8531: leftlen = cplen;
8532: totlen = len = 0;
8533:
8534: len = asc_prt_line(cp, leftlen,
8535: "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8536: ASC_PRT_NEXT();
8537:
8538: if (asc_get_eeprom_string(&ep->serial_number_word1, serialstr) ==
8539: ASC_TRUE) {
8540: len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8541: ASC_PRT_NEXT();
8542: } else {
8543: len = asc_prt_line(cp, leftlen,
8544: " Serial Number Signature Not Present.\n");
8545: ASC_PRT_NEXT();
8546: }
8547:
8548: len = asc_prt_line(cp, leftlen,
8549: " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8550: ep->adapter_scsi_id, ep->max_host_qng, ep->max_dvc_qng);
8551: ASC_PRT_NEXT();
8552:
8553: switch (ep->termination) {
8554: case 1:
8555: termstr = "Low Off/High Off";
8556: break;
8557: case 2:
8558: termstr = "Low Off/High On";
8559: break;
8560: case 3:
8561: termstr = "Low On/High On";
8562: break;
8563: default:
8564: case 0:
8565: termstr = "Automatic";
8566: break;
8567: }
8568:
8569: len = asc_prt_line(cp, leftlen,
8570: " termination: %u (%s), bios_ctrl: %x\n",
8571: ep->termination, termstr, ep->bios_ctrl);
8572: ASC_PRT_NEXT();
8573:
8574: len = asc_prt_line(cp, leftlen,
8575: " Target ID: ");
8576: ASC_PRT_NEXT();
8577: for (i = 0; i <= ADV_MAX_TID; i++) {
8578: len = asc_prt_line(cp, leftlen, " %X", i);
8579: ASC_PRT_NEXT();
8580: }
8581: len = asc_prt_line(cp, leftlen, "\n");
8582: ASC_PRT_NEXT();
8583:
8584: len = asc_prt_line(cp, leftlen,
8585: " Disconnects: ");
8586: ASC_PRT_NEXT();
8587: for (i = 0; i <= ADV_MAX_TID; i++) {
8588: len = asc_prt_line(cp, leftlen, " %c",
8589: (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8590: ASC_PRT_NEXT();
8591: }
8592: len = asc_prt_line(cp, leftlen, "\n");
8593: ASC_PRT_NEXT();
8594:
8595: len = asc_prt_line(cp, leftlen,
8596: " Command Queuing: ");
8597: ASC_PRT_NEXT();
8598: for (i = 0; i <= ADV_MAX_TID; i++) {
8599: len = asc_prt_line(cp, leftlen, " %c",
8600: (ep->tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8601: ASC_PRT_NEXT();
8602: }
8603: len = asc_prt_line(cp, leftlen, "\n");
8604: ASC_PRT_NEXT();
8605:
8606: len = asc_prt_line(cp, leftlen,
8607: " Start Motor: ");
8608: ASC_PRT_NEXT();
8609: for (i = 0; i <= ADV_MAX_TID; i++) {
8610: len = asc_prt_line(cp, leftlen, " %c",
8611: (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8612: ASC_PRT_NEXT();
8613: }
8614: len = asc_prt_line(cp, leftlen, "\n");
8615: ASC_PRT_NEXT();
8616:
8617: len = asc_prt_line(cp, leftlen,
8618: " Synchronous Transfer:");
8619: ASC_PRT_NEXT();
8620: for (i = 0; i <= ADV_MAX_TID; i++) {
8621: len = asc_prt_line(cp, leftlen, " %c",
8622: (ep->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8623: ASC_PRT_NEXT();
8624: }
8625: len = asc_prt_line(cp, leftlen, "\n");
8626: ASC_PRT_NEXT();
8627:
8628: len = asc_prt_line(cp, leftlen,
8629: " Ultra Transfer: ");
8630: ASC_PRT_NEXT();
8631: for (i = 0; i <= ADV_MAX_TID; i++) {
8632: len = asc_prt_line(cp, leftlen, " %c",
8633: (ep->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8634: ASC_PRT_NEXT();
8635: }
8636: len = asc_prt_line(cp, leftlen, "\n");
8637: ASC_PRT_NEXT();
8638:
8639: len = asc_prt_line(cp, leftlen,
8640: " Wide Transfer: ");
8641: ASC_PRT_NEXT();
8642: for (i = 0; i <= ADV_MAX_TID; i++) {
8643: len = asc_prt_line(cp, leftlen, " %c",
8644: (ep->wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8645: ASC_PRT_NEXT();
8646: }
8647: len = asc_prt_line(cp, leftlen, "\n");
8648: ASC_PRT_NEXT();
8649:
8650: return totlen;
8651: }
8652:
8653: /*
8654: * asc_prt_driver_conf()
8655: *
8656: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8657: * cf. asc_prt_line().
8658: *
8659: * Return the number of characters copied into 'cp'. No more than
8660: * 'cplen' characters will be copied to 'cp'.
8661: */
8662: STATIC int
8663: asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
8664: {
8665: asc_board_t *boardp;
8666: int leftlen;
8667: int totlen;
8668: int len;
8669: int chip_scsi_id;
8670: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
8671: int i;
8672: #endif /* version >= v1.3.89 */
8673:
8674: boardp = ASC_BOARDP(shp);
8675:
8676: leftlen = cplen;
8677: totlen = len = 0;
8678:
8679: len = asc_prt_line(cp, leftlen,
8680: "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
8681: shp->host_no);
8682: ASC_PRT_NEXT();
8683:
8684: len = asc_prt_line(cp, leftlen,
8685: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
8686: " host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
8687: shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
8688: #else /* version >= v1.3.89 */
8689: " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
8690: shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
8691: shp->max_channel);
8692: #endif /* version >= v1.3.89 */
8693: ASC_PRT_NEXT();
8694:
8695: len = asc_prt_line(cp, leftlen,
8696: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
8697: " can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
8698: shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
8699: #else /* version >= v1.3.57 */
8700: " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
8701: shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
8702: shp->cmd_per_lun);
8703: #endif /* version >= v1.3.57 */
8704: ASC_PRT_NEXT();
8705:
8706: len = asc_prt_line(cp, leftlen,
8707: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
8708: " unchecked_isa_dma %d, loaded_as_module %d\n",
8709: shp->unchecked_isa_dma, shp->loaded_as_module);
8710: #else /* version >= v1.3.57 */
8711: " unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
8712: shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
8713: #endif /* version >= v1.3.57 */
8714: ASC_PRT_NEXT();
8715:
8716: len = asc_prt_line(cp, leftlen, " flags %x, last_reset %x, jiffies %x\n",
8717: boardp->flags, boardp->last_reset, jiffies);
8718: ASC_PRT_NEXT();
8719:
8720: if (ASC_NARROW_BOARD(boardp)) {
8721: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8722: } else {
8723: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8724: }
8725:
8726: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
8727: if (boardp->flags & ASC_SELECT_QUEUE_DEPTHS) {
8728: len = asc_prt_line(cp, leftlen, " queue_depth:");
8729: ASC_PRT_NEXT();
8730: for (i = 0; i <= ADV_MAX_TID; i++) {
8731: if ((chip_scsi_id == i) ||
8732: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8733: continue;
8734: }
8735: if (boardp->device[i] == NULL) {
8736: continue;
8737: }
8738: len = asc_prt_line(cp, leftlen, " %X:%d",
8739: i, boardp->device[i]->queue_depth);
8740: ASC_PRT_NEXT();
8741: }
8742: len = asc_prt_line(cp, leftlen, "\n");
8743: ASC_PRT_NEXT();
8744: }
8745: #endif /* version >= v1.3.89 */
8746:
8747: #if ASC_QUEUE_FLOW_CONTROL
8748: if (ASC_NARROW_BOARD(boardp)) {
8749: len = asc_prt_line(cp, leftlen, " queue_curr_depth:");
8750: ASC_PRT_NEXT();
8751: /* Use ASC_MAX_TID for Narrow Board. */
8752: for (i = 0; i <= ASC_MAX_TID; i++) {
8753: if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
8754: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8755: continue;
8756: }
8757: if (boardp->device[i] == NULL) {
8758: continue;
8759: }
8760: len = asc_prt_line(cp, leftlen, " %d:%d",
8761: i, boardp->device[i]->queue_curr_depth);
8762: ASC_PRT_NEXT();
8763: }
8764: len = asc_prt_line(cp, leftlen, "\n");
8765: ASC_PRT_NEXT();
8766:
8767: len = asc_prt_line(cp, leftlen, " queue_count:");
8768: ASC_PRT_NEXT();
8769: /* Use ASC_MAX_TID for Narrow Board. */
8770: for (i = 0; i <= ASC_MAX_TID; i++) {
8771: if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
8772: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8773: continue;
8774: }
8775: if (boardp->device[i] == NULL) {
8776: continue;
8777: }
8778: len = asc_prt_line(cp, leftlen, " %d:%d",
8779: i, boardp->device[i]->queue_count);
8780: ASC_PRT_NEXT();
8781: }
8782: len = asc_prt_line(cp, leftlen, "\n");
8783: ASC_PRT_NEXT();
8784: }
8785: #endif /* ASC_QUEUE_FLOW_CONTROL */
8786:
8787: return totlen;
8788: }
8789:
8790: /*
8791: * asc_prt_asc_board_info()
8792: *
8793: * Print dynamic board configuration information.
8794: *
8795: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8796: * cf. asc_prt_line().
8797: *
8798: * Return the number of characters copied into 'cp'. No more than
8799: * 'cplen' characters will be copied to 'cp'.
8800: */
8801: STATIC int
8802: asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen)
8803: {
8804: asc_board_t *boardp;
8805: int leftlen;
8806: int totlen;
8807: int len;
8808: ASC_DVC_VAR *v;
8809: ASC_DVC_CFG *c;
8810: int i;
8811:
8812: boardp = ASC_BOARDP(shp);
8813: v = &boardp->dvc_var.asc_dvc_var;
8814: c = &boardp->dvc_cfg.asc_dvc_cfg;
8815:
8816: leftlen = cplen;
8817: totlen = len = 0;
8818:
8819: len = asc_prt_line(cp, leftlen,
8820: "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
8821: shp->host_no);
8822: ASC_PRT_NEXT();
8823:
8824: len = asc_prt_line(cp, leftlen,
8825: " chip_version %u, lib_version %x, lib_serial_no %u, mcode_date %x\n",
8826: c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date);
8827: ASC_PRT_NEXT();
8828:
8829: len = asc_prt_line(cp, leftlen,
8830: " mcode_version %x, err_code %u\n",
8831: c->mcode_version, v->err_code);
8832: ASC_PRT_NEXT();
8833:
8834: /* Current number of commands waiting for the host. */
8835: len = asc_prt_line(cp, leftlen,
8836: " Total Command Pending: %d\n", v->cur_total_qng);
8837: ASC_PRT_NEXT();
8838:
8839: len = asc_prt_line(cp, leftlen,
8840: " Command Queuing:");
8841: ASC_PRT_NEXT();
8842: for (i = 0; i <= ASC_MAX_TID; i++) {
8843: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8844: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8845: continue;
8846: }
8847: len = asc_prt_line(cp, leftlen, " %d:%c",
8848: i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8849: ASC_PRT_NEXT();
8850: }
8851: len = asc_prt_line(cp, leftlen, "\n");
8852: ASC_PRT_NEXT();
8853:
8854: /* Current number of commands waiting for a device. */
8855: len = asc_prt_line(cp, leftlen,
8856: " Command Queue Pending:");
8857: ASC_PRT_NEXT();
8858: for (i = 0; i <= ASC_MAX_TID; i++) {
8859: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8860: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8861: continue;
8862: }
8863: len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
8864: ASC_PRT_NEXT();
8865: }
8866: len = asc_prt_line(cp, leftlen, "\n");
8867: ASC_PRT_NEXT();
8868:
8869: /* Current limit on number of commands that can be sent to a device. */
8870: len = asc_prt_line(cp, leftlen,
8871: " Command Queue Limit:");
8872: ASC_PRT_NEXT();
8873: for (i = 0; i <= ASC_MAX_TID; i++) {
8874: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8875: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8876: continue;
8877: }
8878: len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
8879: ASC_PRT_NEXT();
8880: }
8881: len = asc_prt_line(cp, leftlen, "\n");
8882: ASC_PRT_NEXT();
8883:
8884: /* Indicate whether the device has returned queue full status. */
8885: len = asc_prt_line(cp, leftlen,
8886: " Command Queue Full:");
8887: ASC_PRT_NEXT();
8888: for (i = 0; i <= ASC_MAX_TID; i++) {
8889: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8890: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8891: continue;
8892: }
8893: if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
8894: len = asc_prt_line(cp, leftlen, " %d:Y-%d",
8895: i, boardp->queue_full_cnt[i]);
8896: } else {
8897: len = asc_prt_line(cp, leftlen, " %d:N", i);
8898: }
8899: ASC_PRT_NEXT();
8900: }
8901: len = asc_prt_line(cp, leftlen, "\n");
8902: ASC_PRT_NEXT();
8903:
8904: len = asc_prt_line(cp, leftlen,
8905: " Synchronous Transfer:");
8906: ASC_PRT_NEXT();
8907: for (i = 0; i <= ASC_MAX_TID; i++) {
8908: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8909: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8910: continue;
8911: }
8912: len = asc_prt_line(cp, leftlen, " %d:%c",
8913: i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8914: ASC_PRT_NEXT();
8915: }
8916: len = asc_prt_line(cp, leftlen, "\n");
8917: ASC_PRT_NEXT();
8918:
8919: for (i = 0; i <= ASC_MAX_TID; i++) {
8920: uchar syn_period_ix;
8921:
8922: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8923: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8924: continue;
8925: }
8926: if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
8927: continue;
8928: }
8929: syn_period_ix = (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1);
8930: len = asc_prt_line(cp, leftlen, " %d:", i);
8931: ASC_PRT_NEXT();
8932:
8933: len = asc_prt_line(cp, leftlen,
8934: " Transfer Period Factor: %d (%d.%d Mhz),",
8935: v->sdtr_period_tbl[syn_period_ix],
8936: 250 / v->sdtr_period_tbl[syn_period_ix],
8937: ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix]));
8938: ASC_PRT_NEXT();
8939:
8940: len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
8941: boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
8942: ASC_PRT_NEXT();
8943: }
8944:
8945: return totlen;
8946: }
8947:
8948: /*
8949: * asc_prt_adv_board_info()
8950: *
8951: * Print dynamic board configuration information.
8952: *
8953: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8954: * cf. asc_prt_line().
8955: *
8956: * Return the number of characters copied into 'cp'. No more than
8957: * 'cplen' characters will be copied to 'cp'.
8958: */
8959: STATIC int
8960: asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen)
8961: {
8962: asc_board_t *boardp;
8963: int leftlen;
8964: int totlen;
8965: int len;
8966: int i;
8967: ADV_DVC_VAR *v;
8968: ADV_DVC_CFG *c;
8969: AdvPortAddr iop_base;
8970: ushort chip_scsi_id;
8971: ushort lramword;
8972: uchar lrambyte;
8973: ushort sdtr_able;
8974: ushort period;
8975:
8976: boardp = ASC_BOARDP(shp);
8977: v = &boardp->dvc_var.adv_dvc_var;
8978: c = &boardp->dvc_cfg.adv_dvc_cfg;
8979: iop_base = v->iop_base;
8980: chip_scsi_id = v->chip_scsi_id;
8981:
8982: leftlen = cplen;
8983: totlen = len = 0;
8984:
8985: len = asc_prt_line(cp, leftlen,
8986: "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
8987: shp->host_no);
8988: ASC_PRT_NEXT();
8989:
8990: len = asc_prt_line(cp, leftlen,
8991: " iop_base %lx, cable_detect: %X, err_code %u, idle_cmd_done %u\n",
8992: v->iop_base,
8993: AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT,
8994: v->err_code, v->idle_cmd_done);
8995: ASC_PRT_NEXT();
8996:
8997: len = asc_prt_line(cp, leftlen,
8998: " chip_version %u, lib_version %x, mcode_date %x, mcode_version %x\n",
8999: c->chip_version, c->lib_version, c->mcode_date, c->mcode_version);
9000: ASC_PRT_NEXT();
9001:
9002: AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, lramword);
9003: len = asc_prt_line(cp, leftlen,
9004: " Queuing Enabled:");
9005: ASC_PRT_NEXT();
9006: for (i = 0; i <= ADV_MAX_TID; i++) {
9007: if ((chip_scsi_id == i) ||
9008: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9009: continue;
9010: }
9011:
9012: len = asc_prt_line(cp, leftlen, " %X:%c",
9013: i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9014: ASC_PRT_NEXT();
9015: }
9016: len = asc_prt_line(cp, leftlen, "\n");
9017: ASC_PRT_NEXT();
9018:
9019: len = asc_prt_line(cp, leftlen,
9020: " Queue Limit:");
9021: ASC_PRT_NEXT();
9022: for (i = 0; i <= ADV_MAX_TID; i++) {
9023: if ((chip_scsi_id == i) ||
9024: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9025: continue;
9026: }
9027:
9028: AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte);
9029:
9030: len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9031: ASC_PRT_NEXT();
9032: }
9033: len = asc_prt_line(cp, leftlen, "\n");
9034: ASC_PRT_NEXT();
9035:
9036: len = asc_prt_line(cp, leftlen,
9037: " Command Pending:");
9038: ASC_PRT_NEXT();
9039: for (i = 0; i <= ADV_MAX_TID; i++) {
9040: if ((chip_scsi_id == i) ||
9041: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9042: continue;
9043: }
9044:
9045: AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte);
9046:
9047: len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9048: ASC_PRT_NEXT();
9049: }
9050: len = asc_prt_line(cp, leftlen, "\n");
9051: ASC_PRT_NEXT();
9052:
9053: AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, lramword);
9054: len = asc_prt_line(cp, leftlen,
9055: " Wide Enabled:");
9056: ASC_PRT_NEXT();
9057: for (i = 0; i <= ADV_MAX_TID; i++) {
9058: if ((chip_scsi_id == i) ||
9059: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9060: continue;
9061: }
9062:
9063: len = asc_prt_line(cp, leftlen, " %X:%c",
9064: i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9065: ASC_PRT_NEXT();
9066: }
9067: len = asc_prt_line(cp, leftlen, "\n");
9068: ASC_PRT_NEXT();
9069:
9070: len = asc_prt_line(cp, leftlen,
9071: " Transfer Bit Width:");
9072: ASC_PRT_NEXT();
9073: for (i = 0; i <= ADV_MAX_TID; i++) {
9074: if ((chip_scsi_id == i) ||
9075: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9076: continue;
9077: }
9078:
9079: AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9080: lramword);
9081: len = asc_prt_line(cp, leftlen, " %X:%d",
9082: i, (lramword & 0x8000) ? 16 : 8);
9083: ASC_PRT_NEXT();
9084: }
9085: len = asc_prt_line(cp, leftlen, "\n");
9086: ASC_PRT_NEXT();
9087:
9088: AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
9089: len = asc_prt_line(cp, leftlen,
9090: " Synchronous Enabled:");
9091: ASC_PRT_NEXT();
9092: for (i = 0; i <= ADV_MAX_TID; i++) {
9093: if ((chip_scsi_id == i) ||
9094: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9095: continue;
9096: }
9097:
9098: len = asc_prt_line(cp, leftlen, " %X:%c",
9099: i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9100: ASC_PRT_NEXT();
9101: }
9102: len = asc_prt_line(cp, leftlen, "\n");
9103: ASC_PRT_NEXT();
9104:
9105: for (i = 0; i <= ADV_MAX_TID; i++) {
9106:
9107: AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9108: lramword);
9109: lramword &= ~0x8000;
9110:
9111: if ((chip_scsi_id == i) ||
9112: ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0) ||
9113: (lramword == 0)) {
9114: continue;
9115: }
9116:
9117: len = asc_prt_line(cp, leftlen, " %X:", i);
9118: ASC_PRT_NEXT();
9119:
9120: period = (((lramword >> 8) * 25) + 50)/4;
9121:
9122: len = asc_prt_line(cp, leftlen,
9123: " Transfer Period Factor: %d (%d.%d Mhz),",
9124: period, 250/period, ASC_TENTHS(250, period));
9125: ASC_PRT_NEXT();
9126:
9127: len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
9128: lramword & 0x1F);
9129: ASC_PRT_NEXT();
9130: }
9131:
9132: return totlen;
9133: }
9134:
9135: /*
9136: * asc_proc_copy()
9137: *
9138: * Copy proc information to a read buffer taking into account the current
9139: * read offset in the file and the remaining space in the read buffer.
9140: */
9141: STATIC int
9142: asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
9143: char *cp, int cplen)
9144: {
9145: int cnt = 0;
9146:
9147: ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
9148: (unsigned) offset, (unsigned) advoffset, cplen);
9149: if (offset <= advoffset) {
9150: /* Read offset below current offset, copy everything. */
9151: cnt = ASC_MIN(cplen, leftlen);
9152: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9153: (unsigned) curbuf, (unsigned) cp, cnt);
9154: memcpy(curbuf, cp, cnt);
9155: } else if (offset < advoffset + cplen) {
9156: /* Read offset within current range, partial copy. */
9157: cnt = (advoffset + cplen) - offset;
9158: cp = (cp + cplen) - cnt;
9159: cnt = ASC_MIN(cnt, leftlen);
9160: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9161: (unsigned) curbuf, (unsigned) cp, cnt);
9162: memcpy(curbuf, cp, cnt);
9163: }
9164: return cnt;
9165: }
9166:
9167: /*
9168: * asc_prt_line()
9169: *
9170: * If 'cp' is NULL print to the console, otherwise print to a buffer.
9171: *
9172: * Return 0 if printing to the console, otherwise return the number of
9173: * bytes written to the buffer.
9174: *
9175: * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
9176: * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
9177: */
9178: STATIC int
9179: asc_prt_line(char *buf, int buflen, char *fmt, ...)
9180: {
9181: va_list args;
9182: int ret;
9183: char s[ASC_PRTLINE_SIZE];
9184:
9185: va_start(args, fmt);
9186: ret = vsprintf(s, fmt, args);
9187: ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
9188: if (buf == NULL) {
9189: (void) printk(s);
9190: ret = 0;
9191: } else {
9192: ret = ASC_MIN(buflen, ret);
9193: memcpy(buf, s, ret);
9194: }
9195: va_end(args);
9196: return ret;
9197: }
9198: #endif /* version >= v1.3.0 */
9199:
9200:
9201: /*
9202: * --- Functions Required by the Asc Library
9203: */
9204:
9205: /*
9206: * Delay for 'n' milliseconds. Don't use the 'jiffies'
9207: * global variable which is incremented once every 5 ms
9208: * from a timer interrupt, because this function may be
9209: * called when interrupts are disabled.
9210: */
9211: STATIC void
9212: DvcSleepMilliSecond(ulong n)
9213: {
9214: ulong i;
9215:
9216: ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
9217: for (i = 0; i < n; i++) {
9218: udelay(1000);
9219: }
9220: }
9221:
9222: STATIC int
9223: DvcEnterCritical(void)
9224: {
9225: int flags;
9226:
9227: save_flags(flags);
9228: cli();
9229: return flags;
9230: }
9231:
9232: STATIC void
9233: DvcLeaveCritical(int flags)
9234: {
9235: restore_flags(flags);
9236: }
9237:
9238: STATIC ulong
9239: DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
9240: ASC_SG_HEAD *asc_sg_head_ptr)
9241: {
9242: ulong buf_size;
9243:
9244: buf_size = buf_len;
9245: asc_sg_head_ptr->entry_cnt = 1;
9246: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9247: asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
9248: #else /* version >= v2.0.0 */
9249: asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
9250: #endif /* version >= v2.0.0 */
9251: asc_sg_head_ptr->sg_list[0].bytes = buf_size;
9252: return buf_size;
9253: }
9254:
9255: /*
9256: * void
9257: * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9258: *
9259: * Calling/Exit State:
9260: * none
9261: *
9262: * Description:
9263: * Output an ASC_SCSI_Q structure to the chip
9264: */
9265: STATIC void
9266: DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9267: {
9268: int i;
9269:
9270: ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
9271: AscSetChipLramAddr(iop_base, s_addr);
9272: for (i = 0; i < words; i++, outbuf++) {
9273: if (i == 2 || i == 10) {
9274: continue;
9275: }
9276: AscSetChipLramDataNoSwap(iop_base, *outbuf);
9277: }
9278: }
9279:
9280: /*
9281: * void
9282: * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9283: *
9284: * Calling/Exit State:
9285: * none
9286: *
9287: * Description:
9288: * Input an ASC_QDONE_INFO structure from the chip
9289: */
9290: STATIC void
9291: DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9292: {
9293: int i;
9294:
9295: AscSetChipLramAddr(iop_base, s_addr);
9296: for (i = 0; i < words; i++, inbuf++) {
9297: if (i == 5) {
9298: continue;
9299: }
9300: *inbuf = AscGetChipLramDataNoSwap(iop_base);
9301: }
9302: ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
9303: }
9304:
9305: /*
9306: * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
9307: *
9308: * Calling/Exit State:
9309: * none
9310: *
9311: * Description:
9312: * output a buffer to an i/o port address
9313: */
9314: STATIC void
9315: DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
9316: {
9317: int i;
9318:
9319: for (i = 0; i < words; i++, outbuf++)
9320: outpw(iop_base, *outbuf);
9321: }
9322:
9323: /*
9324: * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
9325: *
9326: * Calling/Exit State:
9327: * none
9328: *
9329: * Description:
9330: * input a buffer from an i/o port address
9331: */
9332: STATIC void
9333: DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
9334: {
9335: int i;
9336:
9337: for (i = 0; i < words; i++, inbuf++)
9338: *inbuf = inpw(iop_base);
9339: }
9340:
9341: /*
9342: * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
9343: *
9344: * Calling/Exit State:
9345: * none
9346: *
9347: * Description:
9348: * output a buffer of 32-bit integers to an i/o port address in
9349: * 16 bit integer units
9350: */
9351: STATIC void
9352: DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
9353: {
9354: int i;
9355: int words;
9356: ushort *pw;
9357:
9358: pw = (ushort *) pdw;
9359: words = dwords << 1;
9360: for(i = 0; i < words; i++, pw++) {
9361: outpw(port, *pw);
9362: }
9363: return;
9364: }
9365:
9366: /*
9367: * Read a PCI configuration byte.
9368: */
9369: ASC_INITFUNC(
9370: STATIC uchar
9371: DvcReadPCIConfigByte(
9372: ASC_DVC_VAR asc_ptr_type *asc_dvc,
9373: ushort offset)
9374: )
9375: {
9376: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9377: #ifdef ASC_CONFIG_PCI
9378: PCI_DATA pciData;
9379:
9380: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9381: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9382: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9383: pciData.offset = offset;
9384: pciData.type = pci_scan_method;
9385: return asc_get_cfg_byte(&pciData);
9386: #else /* ASC_CONFIG_PCI */
9387: return 0;
9388: #endif /* ASC_CONFIG_PCI */
9389: #else /* version >= v2.1.93 */
9390: #ifdef CONFIG_PCI
9391: uchar byte_data;
9392: pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9393: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9394: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9395: offset, &byte_data);
9396: return byte_data;
9397: #else /* CONFIG_PCI */
9398: return 0;
9399: #endif /* CONFIG_PCI */
9400: #endif /* version >= v2.1.93 */
9401: }
9402:
9403: /*
9404: * Write a PCI configuration byte.
9405: */
9406: ASC_INITFUNC(
9407: STATIC void
9408: DvcWritePCIConfigByte(
9409: ASC_DVC_VAR asc_ptr_type *asc_dvc,
9410: ushort offset,
9411: uchar byte_data)
9412: )
9413: {
9414: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9415: #ifdef ASC_CONFIG_PCI
9416: PCI_DATA pciData;
9417:
9418: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9419: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9420: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9421: pciData.offset = offset;
9422: pciData.type = pci_scan_method;
9423: asc_put_cfg_byte(&pciData, byte_data);
9424: #endif /* ASC_CONFIG_PCI */
9425: #else /* version >= v2.1.93 */
9426: #ifdef CONFIG_PCI
9427: pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9428: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9429: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9430: offset, byte_data);
9431: #endif /* CONFIG_PCI */
9432: #endif /* version >= v2.1.93 */
9433: }
9434:
9435: /*
9436: * Return the BIOS address of the adapter at the specified
9437: * I/O port and with the specified bus type.
9438: */
9439: ASC_INITFUNC(
9440: STATIC ushort
9441: AscGetChipBiosAddress(
9442: PortAddr iop_base,
9443: ushort bus_type
9444: )
9445: )
9446: {
9447: ushort cfg_lsw ;
9448: ushort bios_addr ;
9449:
9450: /*
9451: * The PCI BIOS is re-located by the motherboard BIOS. Because
9452: * of this the driver can not determine where a PCI BIOS is
9453: * loaded and executes.
9454: */
9455: if (bus_type & ASC_IS_PCI)
9456: {
9457: return(0);
9458: }
9459:
9460: if((bus_type & ASC_IS_EISA) != 0)
9461: {
9462: cfg_lsw = AscGetEisaChipCfg(iop_base) ;
9463: cfg_lsw &= 0x000F ;
9464: bios_addr = (ushort)(ASC_BIOS_MIN_ADDR +
9465: (cfg_lsw * ASC_BIOS_BANK_SIZE)) ;
9466: return(bios_addr) ;
9467: }/* if */
9468:
9469: cfg_lsw = AscGetChipCfgLsw(iop_base) ;
9470:
9471: /*
9472: * ISA PnP uses the top bit as the 32K BIOS flag
9473: */
9474: if (bus_type == ASC_IS_ISAPNP)
9475: {
9476: cfg_lsw &= 0x7FFF;
9477: }/* if */
9478:
9479: bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
9480: ASC_BIOS_MIN_ADDR) ;
9481: return(bios_addr) ;
9482: }
9483:
9484:
9485: /*
9486: * --- Functions Required by the Adv Library
9487: */
9488:
9489: /*
9490: * DvcGetPhyAddr()
9491: *
9492: * Return the physical address of 'vaddr' and set '*lenp' to the
9493: * number of physically contiguous bytes that follow 'vaddr'.
9494: * 'flag' indicates the type of structure whose physical address
9495: * is being translated.
9496: *
9497: * Note: Because Linux currently doesn't page the kernel and all
9498: * kernel buffers are physically contiguous, leave '*lenp' unchanged.
9499: */
9500: ulong
9501: DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
9502: uchar *vaddr, long *lenp, int flag)
9503: {
9504: ulong paddr;
9505:
9506: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9507: paddr = (ulong) vaddr;
9508: #else /* version >= v2.0.0 */
9509: paddr = virt_to_bus(vaddr);
9510: #endif /* version >= v2.0.0 */
9511:
9512: ASC_DBG4(4,
9513: "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
9514: (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), paddr);
9515:
9516: return paddr;
9517: }
9518:
9519: /*
9520: * Read a PCI configuration byte.
9521: */
9522: ASC_INITFUNC(
9523: STATIC uchar
9524: DvcAdvReadPCIConfigByte(
9525: ADV_DVC_VAR *asc_dvc,
9526: ushort offset)
9527: )
9528: {
9529: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9530: #ifdef ASC_CONFIG_PCI
9531: PCI_DATA pciData;
9532:
9533: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9534: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9535: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9536: pciData.offset = offset;
9537: pciData.type = pci_scan_method;
9538: return asc_get_cfg_byte(&pciData);
9539: #else /* ASC_CONFIG_PCI */
9540: return 0;
9541: #endif /* ASC_CONFIG_PCI */
9542: #else /* version >= v2.1.93 */
9543: #ifdef CONFIG_PCI
9544: uchar byte_data;
9545: pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9546: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9547: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9548: offset, &byte_data);
9549: return byte_data;
9550: #else /* CONFIG_PCI */
9551: return 0;
9552: #endif /* CONFIG_PCI */
9553: #endif /* version >= v2.1.93 */
9554: }
9555:
9556: /*
9557: * Write a PCI configuration byte.
9558: */
9559: ASC_INITFUNC(
9560: STATIC void
9561: DvcAdvWritePCIConfigByte(
9562: ADV_DVC_VAR *asc_dvc,
9563: ushort offset,
9564: uchar byte_data)
9565: )
9566: {
9567: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9568: #ifdef ASC_CONFIG_PCI
9569: PCI_DATA pciData;
9570:
9571: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9572: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9573: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9574: pciData.offset = offset;
9575: pciData.type = pci_scan_method;
9576: asc_put_cfg_byte(&pciData, byte_data);
9577: #endif /* ASC_CONFIG_PCI */
9578: #else /* version >= v2.1.93 */
9579: #ifdef CONFIG_PCI
9580: pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9581: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9582: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9583: offset, byte_data);
9584: #endif /* CONFIG_PCI */
9585: #endif /* version >= v2.1.93 */
9586: }
9587:
9588: /*
9589: * --- Tracing and Debugging Functions
9590: */
9591:
9592: #ifdef ADVANSYS_STATS
9593: /*
9594: * asc_prt_board_stats()
9595: *
9596: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9597: * cf. asc_prt_line().
9598: *
9599: * Return the number of characters copied into 'cp'. No more than
9600: * 'cplen' characters will be copied to 'cp'.
9601: */
9602: STATIC int
9603: asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
9604: {
9605: int leftlen;
9606: int totlen;
9607: int len;
9608: struct asc_stats *s;
9609: int i;
9610: ushort chip_scsi_id;
9611: asc_board_t *boardp;
9612: asc_queue_t *active;
9613: asc_queue_t *waiting;
9614:
9615: leftlen = cplen;
9616: totlen = len = 0;
9617:
9618: boardp = ASC_BOARDP(shp);
9619: s = &boardp->asc_stats;
9620:
9621: len = asc_prt_line(cp, leftlen,
9622: "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no);
9623: ASC_PRT_NEXT();
9624:
9625: len = asc_prt_line(cp, leftlen,
9626: " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n",
9627: s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
9628: ASC_PRT_NEXT();
9629:
9630: len = asc_prt_line(cp, leftlen,
9631: " interrupt %lu, callback %lu, done %lu\n",
9632: s->interrupt, s->callback, s->done);
9633: ASC_PRT_NEXT();
9634:
9635: len = asc_prt_line(cp, leftlen,
9636: " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
9637: s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown);
9638: ASC_PRT_NEXT();
9639:
9640: if (ASC_NARROW_BOARD(boardp)) {
9641: len = asc_prt_line(cp, leftlen,
9642: " build_error %lu\n",
9643: s->build_error);
9644: } else {
9645: len = asc_prt_line(cp, leftlen,
9646: " build_error %lu, build_noreq %lu, build_nosg %lu\n",
9647: s->build_error, s->adv_build_noreq, s->adv_build_nosg);
9648: }
9649: ASC_PRT_NEXT();
9650:
9651: /*
9652: * Display data transfer statistics.
9653: */
9654: if (s->cont_cnt > 0) {
9655: len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
9656: ASC_PRT_NEXT();
9657:
9658: len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
9659: s->cont_xfer/2,
9660: ASC_TENTHS(s->cont_xfer, 2));
9661: ASC_PRT_NEXT();
9662:
9663: /* Contiguous transfer average size */
9664: len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
9665: (s->cont_xfer/2)/s->cont_cnt,
9666: ASC_TENTHS((s->cont_xfer/2), s->cont_cnt));
9667: ASC_PRT_NEXT();
9668: }
9669:
9670: if (s->sg_cnt > 0) {
9671:
9672: len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
9673: s->sg_cnt, s->sg_elem);
9674: ASC_PRT_NEXT();
9675:
9676: len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
9677: s->sg_xfer/2,
9678: ASC_TENTHS(s->sg_xfer, 2));
9679: ASC_PRT_NEXT();
9680:
9681: /* Scatter gather transfer statistics */
9682: len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
9683: s->sg_elem/s->sg_cnt,
9684: ASC_TENTHS(s->sg_elem, s->sg_cnt));
9685: ASC_PRT_NEXT();
9686:
9687: len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
9688: (s->sg_xfer/2)/s->sg_elem,
9689: ASC_TENTHS((s->sg_xfer/2), s->sg_elem));
9690: ASC_PRT_NEXT();
9691:
9692: len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
9693: (s->sg_xfer/2)/s->sg_cnt,
9694: ASC_TENTHS((s->sg_xfer/2), s->sg_cnt));
9695: ASC_PRT_NEXT();
9696: }
9697:
9698: /*
9699: * Display request queuing statistics.
9700: */
9701: len = asc_prt_line(cp, leftlen,
9702: " Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ);
9703: ASC_PRT_NEXT();
9704:
9705: active = &ASC_BOARDP(shp)->active;
9706: waiting = &ASC_BOARDP(shp)->waiting;
9707:
9708: if (ASC_NARROW_BOARD(boardp)) {
9709: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
9710: } else {
9711: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
9712: }
9713:
9714: for (i = 0; i <= ADV_MAX_TID; i++) {
9715:
9716: if ((chip_scsi_id == i) ||
9717: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9718: continue;
9719: }
9720:
9721: if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
9722: len = asc_prt_line(cp, leftlen, " target %d\n", i);
9723: ASC_PRT_NEXT();
9724:
9725: len = asc_prt_line(cp, leftlen,
9726: " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
9727: active->q_cur_cnt[i], active->q_max_cnt[i],
9728: active->q_tot_cnt[i],
9729: active->q_min_tim[i], active->q_max_tim[i],
9730: (active->q_tot_cnt[i] == 0) ? 0 :
9731: (active->q_tot_tim[i]/active->q_tot_cnt[i]),
9732: (active->q_tot_cnt[i] == 0) ? 0 :
9733: ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
9734: ASC_PRT_NEXT();
9735:
9736: len = asc_prt_line(cp, leftlen,
9737: " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
9738: waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
9739: waiting->q_tot_cnt[i],
9740: waiting->q_min_tim[i], waiting->q_max_tim[i],
9741: (waiting->q_tot_cnt[i] == 0) ? 0 :
9742: (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
9743: (waiting->q_tot_cnt[i] == 0) ? 0 :
9744: ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
9745: ASC_PRT_NEXT();
9746: }
9747: }
9748:
9749: return totlen;
9750: }
9751: #endif /* ADVANSYS_STATS */
9752:
9753: #ifdef ADVANSYS_DEBUG
9754: /*
9755: * asc_prt_scsi_host()
9756: */
9757: STATIC void
9758: asc_prt_scsi_host(struct Scsi_Host *s)
9759: {
9760: asc_board_t *boardp;
9761:
9762: boardp = ASC_BOARDP(s);
9763:
9764: printk("Scsi_Host at addr %x\n", (unsigned) s);
9765: printk(
9766: " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
9767: (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
9768: (unsigned) s->last_reset);
9769:
9770: printk(
9771: " host_wait %x, host_queue %x, hostt %x, block %x,\n",
9772: (unsigned) s->host_wait, (unsigned) s->host_queue,
9773: (unsigned) s->hostt, (unsigned) s->block);
9774:
9775: printk(
9776: " wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
9777: s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
9778: s->irq, s->dma_channel);
9779:
9780: printk(
9781: " this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
9782:
9783: printk(
9784: " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
9785: s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
9786: s->loaded_as_module);
9787:
9788: if (ASC_NARROW_BOARD(boardp)) {
9789: asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
9790: asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
9791: } else {
9792: asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
9793: asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
9794: }
9795: }
9796:
9797: /*
9798: * asc_prt_scsi_cmnd()
9799: */
9800: STATIC void
9801: asc_prt_scsi_cmnd(Scsi_Cmnd *s)
9802: {
9803: printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
9804:
9805: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
9806: printk(
9807: " host %x, device %x, target %u, lun %u\n",
9808: (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
9809: #else /* version >= v1.3.0 */
9810: printk(
9811: " host %x, device %x, target %u, lun %u, channel %u,\n",
9812: (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
9813: s->channel);
9814: #endif /* version >= v1.3.0 */
9815:
9816: asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
9817:
9818: printk(
9819: " use_sg %u, sglist_len %u, abort_reason %x\n",
9820: s->use_sg, s->sglist_len, s->abort_reason);
9821:
9822: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
9823: printk(
9824: " retries %d, allowed %d\n",
9825: s->retries, s->allowed);
9826: #else /* version >= v1.3.89 */
9827: printk(
9828: " serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
9829: (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
9830: s->retries, s->allowed);
9831: #endif /* version >= v1.3.89 */
9832:
9833: printk(
9834: " timeout_per_command %d, timeout_total %d, timeout %d\n",
9835: s->timeout_per_command, s->timeout_total, s->timeout);
9836:
9837: printk(
9838: " internal_timeout %u, flags %u, this_count %d\n",
9839: s->internal_timeout, s->flags, s->this_count);
9840:
9841: printk(
9842: " scsi_done %x, done %x, host_scribble %x, result %x\n",
9843: (unsigned) s->scsi_done, (unsigned) s->done,
9844: (unsigned) s->host_scribble, s->result);
9845:
9846: printk(
9847: " tag %u, pid %u\n",
9848: (unsigned) s->tag, (unsigned) s->pid);
9849: }
9850:
9851: /*
9852: * asc_prt_asc_dvc_var()
9853: */
9854: STATIC void
9855: asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
9856: {
9857: printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
9858:
9859: printk(
9860: " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
9861: h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
9862:
9863: printk(
9864: " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
9865: h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
9866: (unsigned) h->init_sdtr);
9867:
9868: printk(
9869: " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
9870: (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
9871: (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
9872:
9873: printk(
9874: " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
9875: (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
9876: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
9877:
9878: printk(
9879: " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
9880: (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
9881: (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
9882:
9883: printk(
9884: " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
9885: (unsigned) h->last_q_shortage, (unsigned) h->init_state,
9886: (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
9887:
9888: printk(
9889: " cfg %x, saved_ptr2func %x\n",
9890: (unsigned) h->cfg, (unsigned) h->saved_ptr2func);
9891: }
9892:
9893: /*
9894: * asc_prt_asc_dvc_cfg()
9895: */
9896: STATIC void
9897: asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
9898: {
9899: printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
9900:
9901: printk(
9902: " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n",
9903: h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable,
9904: h->sdtr_enable);
9905:
9906: printk(
9907: " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
9908: h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
9909: h->chip_version);
9910:
9911: printk(
9912: " pci_device_id %d, lib_serial_no %x, lib_version %x, mcode_date %x,\n",
9913: h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
9914:
9915: printk(
9916: " mcode_version %d, overrun_buf %x\n",
9917: h->mcode_version, (unsigned) h->overrun_buf);
9918: }
9919:
9920: /*
9921: * asc_prt_asc_scsi_q()
9922: */
9923: STATIC void
9924: asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
9925: {
9926: ASC_SG_HEAD *sgp;
9927: int i;
9928:
9929: printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
9930:
9931: printk(
9932: " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
9933: q->q2.target_ix, q->q1.target_lun,
9934: (unsigned) q->q2.srb_ptr, q->q2.tag_code);
9935:
9936: printk(
9937: " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
9938: (unsigned) q->q1.data_addr, q->q1.data_cnt,
9939: (unsigned) q->q1.sense_addr, q->q1.sense_len);
9940:
9941: printk(
9942: " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
9943: (unsigned) q->cdbptr, q->q2.cdb_len,
9944: (unsigned) q->sg_head, q->q1.sg_queue_cnt);
9945:
9946: if (q->sg_head) {
9947: sgp = q->sg_head;
9948: printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
9949: printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
9950: for (i = 0; i < sgp->entry_cnt; i++) {
9951: printk(" [%u]: addr %x, bytes %lu\n",
9952: i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
9953: }
9954:
9955: }
9956: }
9957:
9958: /*
9959: * asc_prt_asc_qdone_info()
9960: */
9961: STATIC void
9962: asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
9963: {
9964: printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
9965: printk(
9966: " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
9967: (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
9968: q->d2.tag_code, q->d3.done_stat);
9969: printk(
9970: " host_stat %x, scsi_stat %x, scsi_msg %x\n",
9971: q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
9972: }
9973:
9974: /*
9975: * asc_prt_adv_dvc_var()
9976: *
9977: * Display an ADV_DVC_VAR structure.
9978: */
9979: STATIC void
9980: asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
9981: {
9982: printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h);
9983:
9984: printk(
9985: " iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
9986: (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able);
9987:
9988: printk(
9989: " isr_callback 0x%x, sdtr_able 0x%x, wdtr_able 0x%x\n",
9990: (unsigned) h->isr_callback, (unsigned) h->wdtr_able,
9991: (unsigned) h->sdtr_able);
9992:
9993: printk(
9994: " start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
9995: (unsigned) h->start_motor,
9996: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
9997:
9998: printk(
9999: " max_host_qng 0x%x, cur_host_qng 0x%x, max_dvc_qng 0x%x\n",
10000: (unsigned) h->max_host_qng, (unsigned) h->cur_host_qng,
10001: (unsigned) h->max_dvc_qng);
10002:
10003: printk(
10004: " no_scam 0x%x, tagqng_able 0x%x, chip_scsi_id 0x%x, cfg 0x%lx\n",
10005: (unsigned) h->no_scam, (unsigned) h->tagqng_able,
10006: (unsigned) h->chip_scsi_id, (ulong) h->cfg);
10007:
10008: }
10009:
10010: /*
10011: * asc_prt_adv_dvc_cfg()
10012: *
10013: * Display an ADV_DVC_CFG structure.
10014: */
10015: STATIC void
10016: asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
10017: {
10018: printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h);
10019:
10020: printk(
10021: " disc_enable 0x%x, termination 0x%x\n",
10022: h->disc_enable, h->termination);
10023:
10024: printk(
10025: " chip_version 0x%x, mcode_date 0x%x\n",
10026: h->chip_version, h->mcode_date);
10027:
10028: printk(
10029: " mcode_version 0x%x, pci_device_id 0x%x, lib_version 0x%x\n",
10030: h->mcode_version, h->pci_device_id, h->lib_version);
10031:
10032: printk(
10033: " control_flag 0x%x, pci_slot_info 0x%x\n",
10034: h->control_flag, h->pci_slot_info);
10035: }
10036:
10037: /*
10038: * asc_prt_adv_scsi_req_q()
10039: *
10040: * Display an ADV_SCSI_REQ_Q structure.
10041: */
10042: STATIC void
10043: asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
10044: {
10045: int i;
10046: struct asc_sg_block *sg_ptr;
10047:
10048: printk("ADV_SCSI_REQ_Q at addr %x\n", (unsigned) q);
10049:
10050: printk(
10051: " target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
10052: q->target_id, q->target_lun, q->srb_ptr, q->a_flag);
10053:
10054: printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
10055: q->cntl, q->data_addr, q->vdata_addr);
10056:
10057: printk(
10058: " data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
10059: q->data_cnt, q->sense_addr, q->sense_len);
10060:
10061: printk(
10062: " cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
10063: q->cdb_len, q->done_status, q->host_status, q->scsi_status);
10064:
10065: printk(
10066: " vsense_addr 0x%lx, scsiq_ptr 0x%lx, ux_wk_data_cnt %lu\n",
10067: (ulong) q->vsense_addr, (ulong) q->scsiq_ptr,
10068: (ulong) q->ux_wk_data_cnt);
10069:
10070: printk(
10071: " sg_list_ptr 0x%lx, sg_real_addr 0x%lx, sg_entry_cnt %u\n",
10072: (ulong) q->sg_list_ptr, (ulong) q->sg_real_addr, q->sg_entry_cnt);
10073:
10074: printk(
10075: " ux_sg_ix %u, orig_sense_len %u\n",
10076: q->ux_sg_ix, q->orig_sense_len);
10077:
10078: /* Display the request's ADV_SG_BLOCK structures. */
10079: for (sg_ptr = q->sg_list_ptr, i = 0; sg_ptr != NULL;
10080: sg_ptr = sg_ptr->sg_ptr, i++) {
10081: /*
10082: * 'sg_ptr' is a physical address. Convert it to a virtual
10083: * address by indexing 'i' into the virtual address array
10084: * 'sg_list_ptr'.
10085: *
10086: * At the end of the each iteration of the loop 'sg_ptr' is
10087: * converted back into a physical address by setting 'sg_ptr'
10088: * to the next pointer 'sg_ptr->sg_ptr'.
10089: */
10090: sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[i]);
10091: asc_prt_adv_sgblock(i, sg_ptr);
10092: }
10093: }
10094:
10095: /*
10096: * asc_prt_adv_sgblock()
10097: *
10098: * Display an ADV_SG_BLOCK structure.
10099: */
10100: STATIC void
10101: asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
10102: {
10103: int i, s;
10104:
10105: /* Calculate starting entry number for the current block. */
10106: s = sgblockno * NO_OF_SG_PER_BLOCK;
10107:
10108: printk(" ADV_SG_BLOCK at addr 0x%lx (sgblockno %lu)\n",
10109: (ulong) b, (ulong) sgblockno);
10110: printk(
10111: " first_entry_no %lu, last_entry_no %lu, sg_ptr 0x%lx\n",
10112: (ulong) b->first_entry_no, (ulong) b->last_entry_no, (ulong) b->sg_ptr);
10113: ASC_ASSERT(b->first_entry_no - s >= 0);
10114: ASC_ASSERT(b->last_entry_no - s >= 0);
10115: ASC_ASSERT(b->last_entry_no - s <= NO_OF_SG_PER_BLOCK);
10116: ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
10117: ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
10118: ASC_ASSERT(b->first_entry_no - s <= b->last_entry_no - s);
10119: for (i = b->first_entry_no - s; i <= b->last_entry_no - s; i++) {
10120: printk(" [%lu]: sg_addr 0x%lx, sg_count 0x%lx\n",
10121: (ulong) i, (ulong) b->sg_list[i].sg_addr,
10122: (ulong) b->sg_list[i].sg_count);
10123: }
10124: }
10125:
10126: /*
10127: * asc_prt_hex()
10128: *
10129: * Print hexadecimal output in 4 byte groupings 32 bytes
10130: * or 8 double-words per line.
10131: */
10132: STATIC void
10133: asc_prt_hex(char *f, uchar *s, int l)
10134: {
10135: int i;
10136: int j;
10137: int k;
10138: int m;
10139:
10140: printk("%s: (%d bytes)\n", f, l);
10141:
10142: for (i = 0; i < l; i += 32) {
10143:
10144: /* Display a maximum of 8 double-words per line. */
10145: if ((k = (l - i) / 4) >= 8) {
10146: k = 8;
10147: m = 0;
10148: } else {
10149: m = (l - i) % 4 ;
10150: }
10151:
10152: for (j = 0; j < k; j++) {
10153: printk(" %2.2X%2.2X%2.2X%2.2X",
10154: (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
10155: (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
10156: }
10157:
10158: switch (m) {
10159: case 0:
10160: default:
10161: break;
10162: case 1:
10163: printk(" %2.2X",
10164: (unsigned) s[i+(j*4)]);
10165: break;
10166: case 2:
10167: printk(" %2.2X%2.2X",
10168: (unsigned) s[i+(j*4)],
10169: (unsigned) s[i+(j*4)+1]);
10170: break;
10171: case 3:
10172: printk(" %2.2X%2.2X%2.2X",
10173: (unsigned) s[i+(j*4)+1],
10174: (unsigned) s[i+(j*4)+2],
10175: (unsigned) s[i+(j*4)+3]);
10176: break;
10177: }
10178:
10179: printk("\n");
10180: }
10181: }
10182: #endif /* ADVANSYS_DEBUG */
10183:
10184: #ifdef ADVANSYS_ASSERT
10185: /*
10186: * interrupts_enabled()
10187: *
10188: * Return 1 if interrupts are enabled, otherwise return 0.
10189: */
10190: STATIC int
10191: interrupts_enabled(void)
10192: {
10193: int flags;
10194:
10195: save_flags(flags);
10196: if (flags & 0x0200) {
10197: return ASC_TRUE;
10198: } else {
10199: return ASC_FALSE;
10200: }
10201: }
10202: #endif /* ADVANSYS_ASSERT */
10203:
10204:
10205: /*
10206: * --- Asc Library Functions
10207: */
10208:
10209: ASC_INITFUNC(
10210: STATIC ushort
10211: AscGetEisaChipCfg(
10212: PortAddr iop_base
10213: )
10214: )
10215: {
10216: PortAddr eisa_cfg_iop;
10217:
10218: eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10219: (PortAddr) (ASC_EISA_CFG_IOP_MASK);
10220: return (inpw(eisa_cfg_iop));
10221: }
10222:
10223: ASC_INITFUNC(
10224: STATIC uchar
10225: AscSetChipScsiID(
10226: PortAddr iop_base,
10227: uchar new_host_id
10228: )
10229: )
10230: {
10231: ushort cfg_lsw;
10232:
10233: if (AscGetChipScsiID(iop_base) == new_host_id) {
10234: return (new_host_id);
10235: }
10236: cfg_lsw = AscGetChipCfgLsw(iop_base);
10237: cfg_lsw &= 0xF8FF;
10238: cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
10239: AscSetChipCfgLsw(iop_base, cfg_lsw);
10240: return (AscGetChipScsiID(iop_base));
10241: }
10242:
10243: ASC_INITFUNC(
10244: STATIC uchar
10245: AscGetChipScsiCtrl(
10246: PortAddr iop_base
10247: )
10248: )
10249: {
10250: uchar sc;
10251:
10252: AscSetBank(iop_base, 1);
10253: sc = inp(iop_base + IOP_REG_SC);
10254: AscSetBank(iop_base, 0);
10255: return (sc);
10256: }
10257:
10258: ASC_INITFUNC(
10259: STATIC uchar
10260: AscGetChipVersion(
10261: PortAddr iop_base,
10262: ushort bus_type
10263: )
10264: )
10265: {
10266: if ((bus_type & ASC_IS_EISA) != 0) {
10267: PortAddr eisa_iop;
10268: uchar revision;
10269: eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10270: (PortAddr) ASC_EISA_REV_IOP_MASK;
10271: revision = inp(eisa_iop);
10272: return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
10273: }
10274: return (AscGetChipVerNo(iop_base));
10275: }
10276:
10277: ASC_INITFUNC(
10278: STATIC ushort
10279: AscGetChipBusType(
10280: PortAddr iop_base
10281: )
10282: )
10283: {
10284: ushort chip_ver;
10285:
10286: chip_ver = AscGetChipVerNo(iop_base);
10287: if (
10288: (chip_ver >= ASC_CHIP_MIN_VER_VL)
10289: && (chip_ver <= ASC_CHIP_MAX_VER_VL)
10290: ) {
10291: if (
10292: ((iop_base & 0x0C30) == 0x0C30)
10293: || ((iop_base & 0x0C50) == 0x0C50)
10294: ) {
10295: return (ASC_IS_EISA);
10296: }
10297: return (ASC_IS_VL);
10298: }
10299: if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
10300: (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
10301: if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
10302: return (ASC_IS_ISAPNP);
10303: }
10304: return (ASC_IS_ISA);
10305: } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
10306: (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
10307: return (ASC_IS_PCI);
10308: }
10309: return (0);
10310: }
10311:
10312: ASC_INITFUNC(
10313: STATIC ulong
10314: AscLoadMicroCode(
10315: PortAddr iop_base,
10316: ushort s_addr,
10317: ushort *mcode_buf,
10318: ushort mcode_size
10319: )
10320: )
10321: {
10322: ulong chksum;
10323: ushort mcode_word_size;
10324: ushort mcode_chksum;
10325:
10326: mcode_word_size = (ushort) (mcode_size >> 1);
10327: AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
10328: AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
10329: chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
10330: mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
10331: (ushort) ASC_CODE_SEC_BEG,
10332: (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
10333: AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
10334: AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
10335: return (chksum);
10336: }
10337:
10338: ASC_INITFUNC(
10339: STATIC int
10340: AscFindSignature(
10341: PortAddr iop_base
10342: )
10343: )
10344: {
10345: ushort sig_word;
10346:
10347: if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
10348: sig_word = AscGetChipSignatureWord(iop_base);
10349: if ((sig_word == (ushort) ASC_1000_ID0W) ||
10350: (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
10351: return (1);
10352: }
10353: }
10354: return (0);
10355: }
10356:
10357: STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
10358: STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
10359: {
10360: 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
10361: ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
10362: };
10363:
10364: ASC_INITFUNC(
10365: STATIC PortAddr
10366: AscSearchIOPortAddr(
10367: PortAddr iop_beg,
10368: ushort bus_type
10369: )
10370: )
10371: {
10372: if (bus_type & ASC_IS_VL) {
10373: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
10374: if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
10375: return (iop_beg);
10376: }
10377: }
10378: return (0);
10379: }
10380: if (bus_type & ASC_IS_ISA) {
10381: if (_isa_pnp_inited == 0) {
10382: AscSetISAPNPWaitForKey();
10383: _isa_pnp_inited++;
10384: }
10385: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
10386: if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
10387: return (iop_beg);
10388: }
10389: }
10390: return (0);
10391: }
10392: if (bus_type & ASC_IS_EISA) {
10393: if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
10394: return (iop_beg);
10395: }
10396: return (0);
10397: }
10398: return (0);
10399: }
10400:
10401: ASC_INITFUNC(
10402: STATIC PortAddr
10403: AscSearchIOPortAddr11(
10404: PortAddr s_addr
10405: )
10406: )
10407: {
10408: int i;
10409: PortAddr iop_base;
10410:
10411: for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
10412: if (_asc_def_iop_base[i] > s_addr) {
10413: break;
10414: }
10415: }
10416: for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
10417: iop_base = _asc_def_iop_base[i];
10418: if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
10419: ASC_DBG1(1,
10420: "AscSearchIOPortAddr11: check_region() failed I/O port %x\n",
10421: iop_base);
10422: continue;
10423: }
10424: ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base);
10425: if (AscFindSignature(iop_base)) {
10426: return (iop_base);
10427: }
10428: }
10429: return (0);
10430: }
10431:
10432: ASC_INITFUNC(
10433: STATIC void
10434: AscToggleIRQAct(
10435: PortAddr iop_base
10436: )
10437: )
10438: {
10439: AscSetChipStatus(iop_base, CIW_IRQ_ACT);
10440: AscSetChipStatus(iop_base, 0);
10441: return;
10442: }
10443:
10444: ASC_INITFUNC(
10445: STATIC void
10446: AscSetISAPNPWaitForKey(
10447: void)
10448: )
10449: {
10450: outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
10451: outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
10452: return;
10453: }
10454:
10455: ASC_INITFUNC(
10456: STATIC uchar
10457: AscGetChipIRQ(
10458: PortAddr iop_base,
10459: ushort bus_type
10460: )
10461: )
10462: {
10463: ushort cfg_lsw;
10464: uchar chip_irq;
10465:
10466: if ((bus_type & ASC_IS_EISA) != 0) {
10467: cfg_lsw = AscGetEisaChipCfg(iop_base);
10468: chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
10469: if ((chip_irq == 13) || (chip_irq > 15)) {
10470: return (0);
10471: }
10472: return (chip_irq);
10473: }
10474: if ((bus_type & ASC_IS_VL) != 0) {
10475: cfg_lsw = AscGetChipCfgLsw(iop_base);
10476: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
10477: if ((chip_irq == 0) ||
10478: (chip_irq == 4) ||
10479: (chip_irq == 7)) {
10480: return (0);
10481: }
10482: return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
10483: }
10484: cfg_lsw = AscGetChipCfgLsw(iop_base);
10485: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
10486: if (chip_irq == 3)
10487: chip_irq += (uchar) 2;
10488: return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
10489: }
10490:
10491: ASC_INITFUNC(
10492: STATIC uchar
10493: AscSetChipIRQ(
10494: PortAddr iop_base,
10495: uchar irq_no,
10496: ushort bus_type
10497: )
10498: )
10499: {
10500: ushort cfg_lsw;
10501:
10502: if ((bus_type & ASC_IS_VL) != 0) {
10503: if (irq_no != 0) {
10504: if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
10505: irq_no = 0;
10506: } else {
10507: irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
10508: }
10509: }
10510: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
10511: cfg_lsw |= (ushort) 0x0010;
10512: AscSetChipCfgLsw(iop_base, cfg_lsw);
10513: AscToggleIRQAct(iop_base);
10514: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
10515: cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
10516: AscSetChipCfgLsw(iop_base, cfg_lsw);
10517: AscToggleIRQAct(iop_base);
10518: return (AscGetChipIRQ(iop_base, bus_type));
10519: }
10520: if ((bus_type & (ASC_IS_ISA)) != 0) {
10521: if (irq_no == 15)
10522: irq_no -= (uchar) 2;
10523: irq_no -= (uchar) ASC_MIN_IRQ_NO;
10524: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
10525: cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
10526: AscSetChipCfgLsw(iop_base, cfg_lsw);
10527: return (AscGetChipIRQ(iop_base, bus_type));
10528: }
10529: return (0);
10530: }
10531:
10532: ASC_INITFUNC(
10533: STATIC void
10534: AscEnableIsaDma(
10535: uchar dma_channel
10536: )
10537: )
10538: {
10539: if (dma_channel < 4) {
10540: outp(0x000B, (ushort) (0xC0 | dma_channel));
10541: outp(0x000A, dma_channel);
10542: } else if (dma_channel < 8) {
10543: outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
10544: outp(0x00D4, (ushort) (dma_channel - 4));
10545: }
10546: return;
10547: }
10548:
10549: STATIC int
10550: AscIsrChipHalted(
10551: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
10552: )
10553: {
10554: EXT_MSG ext_msg;
10555: EXT_MSG out_msg;
10556: ushort halt_q_addr;
10557: int sdtr_accept;
10558: ushort int_halt_code;
10559: ASC_SCSI_BIT_ID_TYPE scsi_busy;
10560: ASC_SCSI_BIT_ID_TYPE target_id;
10561: PortAddr iop_base;
10562: uchar tag_code;
10563: uchar q_status;
10564: uchar halt_qp;
10565: uchar sdtr_data;
10566: uchar target_ix;
10567: uchar q_cntl, tid_no;
10568: uchar cur_dvc_qng;
10569: uchar asyn_sdtr;
10570: uchar scsi_status;
10571: asc_board_t *boardp;
10572:
10573: ASC_ASSERT(asc_dvc->drv_ptr != 0);
10574: boardp = (asc_board_t *) asc_dvc->drv_ptr;
10575:
10576: iop_base = asc_dvc->iop_base;
10577: int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
10578:
10579: halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
10580: halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
10581: target_ix = AscReadLramByte(iop_base,
10582: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
10583: q_cntl = AscReadLramByte(iop_base,
10584: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
10585: tid_no = ASC_TIX_TO_TID(target_ix);
10586: target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
10587: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10588:
10589: asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
10590: } else {
10591: asyn_sdtr = 0;
10592: }
10593: if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
10594: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10595: AscSetChipSDTR(iop_base, 0, tid_no);
10596: boardp->sdtr_data[tid_no] = 0;
10597: }
10598: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10599: return (0);
10600: } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
10601: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10602: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10603: boardp->sdtr_data[tid_no] = asyn_sdtr;
10604: }
10605: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10606: return (0);
10607: } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
10608:
10609: AscMemWordCopyFromLram(iop_base,
10610: ASCV_MSGIN_BEG,
10611: (ushort *) & ext_msg,
10612: (ushort) (sizeof (EXT_MSG) >> 1));
10613:
10614: if (ext_msg.msg_type == MS_EXTEND &&
10615: ext_msg.msg_req == MS_SDTR_CODE &&
10616: ext_msg.msg_len == MS_SDTR_LEN) {
10617: sdtr_accept = TRUE;
10618: if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
10619:
10620: sdtr_accept = FALSE;
10621: ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
10622: }
10623: if ((ext_msg.xfer_period <
10624: asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) ||
10625: (ext_msg.xfer_period >
10626: asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) {
10627: sdtr_accept = FALSE;
10628: ext_msg.xfer_period =
10629: asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index];
10630: }
10631: if (sdtr_accept) {
10632: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10633: ext_msg.req_ack_offset);
10634: if ((sdtr_data == 0xFF)) {
10635:
10636: q_cntl |= QC_MSG_OUT;
10637: asc_dvc->init_sdtr &= ~target_id;
10638: asc_dvc->sdtr_done &= ~target_id;
10639: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10640: boardp->sdtr_data[tid_no] = asyn_sdtr;
10641: }
10642: }
10643: if (ext_msg.req_ack_offset == 0) {
10644:
10645: q_cntl &= ~QC_MSG_OUT;
10646: asc_dvc->init_sdtr &= ~target_id;
10647: asc_dvc->sdtr_done &= ~target_id;
10648: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10649: } else {
10650: if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
10651:
10652: q_cntl &= ~QC_MSG_OUT;
10653: asc_dvc->sdtr_done |= target_id;
10654: asc_dvc->init_sdtr |= target_id;
10655: asc_dvc->pci_fix_asyn_xfer &= ~target_id;
10656: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10657: ext_msg.req_ack_offset);
10658: AscSetChipSDTR(iop_base, sdtr_data, tid_no);
10659: boardp->sdtr_data[tid_no] = sdtr_data;
10660: } else {
10661:
10662: q_cntl |= QC_MSG_OUT;
10663: AscMsgOutSDTR(asc_dvc,
10664: ext_msg.xfer_period,
10665: ext_msg.req_ack_offset);
10666: asc_dvc->pci_fix_asyn_xfer &= ~target_id;
10667: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10668: ext_msg.req_ack_offset);
10669: AscSetChipSDTR(iop_base, sdtr_data, tid_no);
10670: boardp->sdtr_data[tid_no] = sdtr_data;
10671: asc_dvc->sdtr_done |= target_id;
10672: asc_dvc->init_sdtr |= target_id;
10673: }
10674: }
10675:
10676: AscWriteLramByte(iop_base,
10677: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10678: q_cntl);
10679: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10680: return (0);
10681: } else if (ext_msg.msg_type == MS_EXTEND &&
10682: ext_msg.msg_req == MS_WDTR_CODE &&
10683: ext_msg.msg_len == MS_WDTR_LEN) {
10684:
10685: ext_msg.wdtr_width = 0;
10686: AscMemWordCopyToLram(iop_base,
10687: ASCV_MSGOUT_BEG,
10688: (ushort *) & ext_msg,
10689: (ushort) (sizeof (EXT_MSG) >> 1));
10690: q_cntl |= QC_MSG_OUT;
10691: AscWriteLramByte(iop_base,
10692: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10693: q_cntl);
10694: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10695: return (0);
10696: } else {
10697:
10698: ext_msg.msg_type = M1_MSG_REJECT;
10699: AscMemWordCopyToLram(iop_base,
10700: ASCV_MSGOUT_BEG,
10701: (ushort *) & ext_msg,
10702: (ushort) (sizeof (EXT_MSG) >> 1));
10703: q_cntl |= QC_MSG_OUT;
10704: AscWriteLramByte(iop_base,
10705: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10706: q_cntl);
10707: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10708: return (0);
10709: }
10710: } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
10711:
10712: q_cntl |= QC_REQ_SENSE;
10713:
10714: if ((asc_dvc->init_sdtr & target_id) != 0) {
10715:
10716: asc_dvc->sdtr_done &= ~target_id;
10717:
10718: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10719: q_cntl |= QC_MSG_OUT;
10720: AscMsgOutSDTR(asc_dvc,
10721: asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
10722: (uchar) (asc_dvc->max_sdtr_index - 1)],
10723: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
10724: }
10725:
10726: AscWriteLramByte(iop_base,
10727: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10728: q_cntl);
10729:
10730: tag_code = AscReadLramByte(iop_base,
10731: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
10732: tag_code &= 0xDC;
10733: if (
10734: (asc_dvc->pci_fix_asyn_xfer & target_id)
10735: && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
10736: ) {
10737:
10738: tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
10739: | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
10740:
10741: }
10742: AscWriteLramByte(iop_base,
10743: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
10744: tag_code);
10745:
10746: q_status = AscReadLramByte(iop_base,
10747: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
10748: q_status |= (QS_READY | QS_BUSY);
10749: AscWriteLramByte(iop_base,
10750: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10751: q_status);
10752:
10753: scsi_busy = AscReadLramByte(iop_base,
10754: (ushort) ASCV_SCSIBUSY_B);
10755: scsi_busy &= ~target_id;
10756: AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10757:
10758: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10759: return (0);
10760: } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
10761:
10762: AscMemWordCopyFromLram(iop_base,
10763: ASCV_MSGOUT_BEG,
10764: (ushort *) & out_msg,
10765: (ushort) (sizeof (EXT_MSG) >> 1));
10766:
10767: if ((out_msg.msg_type == MS_EXTEND) &&
10768: (out_msg.msg_len == MS_SDTR_LEN) &&
10769: (out_msg.msg_req == MS_SDTR_CODE)) {
10770:
10771: asc_dvc->init_sdtr &= ~target_id;
10772: asc_dvc->sdtr_done &= ~target_id;
10773: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10774: boardp->sdtr_data[tid_no] = asyn_sdtr;
10775: }
10776: q_cntl &= ~QC_MSG_OUT;
10777: AscWriteLramByte(iop_base,
10778: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10779: q_cntl);
10780: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10781: return (0);
10782: } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
10783:
10784: scsi_status = AscReadLramByte(iop_base,
10785: (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
10786: cur_dvc_qng = AscReadLramByte(iop_base,
10787: (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
10788: if ((cur_dvc_qng > 0) &&
10789: (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
10790:
10791: scsi_busy = AscReadLramByte(iop_base,
10792: (ushort) ASCV_SCSIBUSY_B);
10793: scsi_busy |= target_id;
10794: AscWriteLramByte(iop_base,
10795: (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10796: asc_dvc->queue_full_or_busy |= target_id;
10797:
10798: if (scsi_status == SS_QUEUE_FULL) {
10799: if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
10800: cur_dvc_qng -= 1;
10801: asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
10802:
10803: AscWriteLramByte(iop_base,
10804: (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG +
10805: (ushort) tid_no),
10806: cur_dvc_qng);
10807:
10808: /*
10809: * Set the device queue depth to the number of
10810: * active requests when the QUEUE FULL condition
10811: * was encountered.
10812: */
10813: boardp->queue_full |= target_id;
10814: boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
10815: #if ASC_QUEUE_FLOW_CONTROL
10816: if (boardp->device[tid_no] != NULL &&
10817: boardp->device[tid_no]->queue_curr_depth >
10818: cur_dvc_qng) {
10819: boardp->device[tid_no]->queue_curr_depth =
10820: cur_dvc_qng;
10821: }
10822: #endif /* ASC_QUEUE_FLOW_CONTROL */
10823: }
10824: }
10825: }
10826: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10827: return (0);
10828: }
10829: return (0);
10830: }
10831:
10832: STATIC uchar
10833: _AscCopyLramScsiDoneQ(
10834: PortAddr iop_base,
10835: ushort q_addr,
10836: REG ASC_QDONE_INFO * scsiq,
10837: ulong max_dma_count
10838: )
10839: {
10840: ushort _val;
10841: uchar sg_queue_cnt;
10842:
10843: DvcGetQinfo(iop_base,
10844: (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
10845: (ushort *) scsiq,
10846: (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
10847: _val = AscReadLramWord(iop_base,
10848: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
10849: scsiq->q_status = (uchar) _val;
10850: scsiq->q_no = (uchar) (_val >> 8);
10851: _val = AscReadLramWord(iop_base,
10852: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
10853: scsiq->cntl = (uchar) _val;
10854: sg_queue_cnt = (uchar) (_val >> 8);
10855: _val = AscReadLramWord(iop_base,
10856: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
10857: scsiq->sense_len = (uchar) _val;
10858: scsiq->extra_bytes = (uchar) (_val >> 8);
10859: scsiq->remain_bytes = AscReadLramWord(iop_base,
10860: (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
10861: scsiq->remain_bytes &= max_dma_count;
10862: return (sg_queue_cnt);
10863: }
10864:
10865: STATIC int
10866: AscIsrQDone(
10867: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
10868: )
10869: {
10870: uchar next_qp;
10871: uchar n_q_used;
10872: uchar sg_list_qp;
10873: uchar sg_queue_cnt;
10874: uchar q_cnt;
10875: uchar done_q_tail;
10876: uchar tid_no;
10877: ASC_SCSI_BIT_ID_TYPE scsi_busy;
10878: ASC_SCSI_BIT_ID_TYPE target_id;
10879: PortAddr iop_base;
10880: ushort q_addr;
10881: ushort sg_q_addr;
10882: uchar cur_target_qng;
10883: ASC_QDONE_INFO scsiq_buf;
10884: REG ASC_QDONE_INFO *scsiq;
10885: int false_overrun;
10886: ASC_ISR_CALLBACK asc_isr_callback;
10887:
10888: iop_base = asc_dvc->iop_base;
10889: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
10890: n_q_used = 1;
10891: scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
10892: done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
10893: q_addr = ASC_QNO_TO_QADDR(done_q_tail);
10894: next_qp = AscReadLramByte(iop_base,
10895: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
10896: if (next_qp != ASC_QLINK_END) {
10897: AscPutVarDoneQTail(iop_base, next_qp);
10898: q_addr = ASC_QNO_TO_QADDR(next_qp);
10899: sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
10900: asc_dvc->max_dma_count);
10901: AscWriteLramByte(iop_base,
10902: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10903: (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
10904: tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
10905: target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
10906: if ((scsiq->cntl & QC_SG_HEAD) != 0) {
10907: sg_q_addr = q_addr;
10908: sg_list_qp = next_qp;
10909: for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
10910: sg_list_qp = AscReadLramByte(iop_base,
10911: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
10912: sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
10913: if (sg_list_qp == ASC_QLINK_END) {
10914: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
10915: scsiq->d3.done_stat = QD_WITH_ERROR;
10916: scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
10917: goto FATAL_ERR_QDONE;
10918: }
10919: AscWriteLramByte(iop_base,
10920: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10921: QS_FREE);
10922: }
10923: n_q_used = sg_queue_cnt + 1;
10924: AscPutVarDoneQTail(iop_base, sg_list_qp);
10925: }
10926: if (asc_dvc->queue_full_or_busy & target_id) {
10927: cur_target_qng = AscReadLramByte(iop_base,
10928: (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
10929: if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
10930: scsi_busy = AscReadLramByte(iop_base,
10931: (ushort) ASCV_SCSIBUSY_B);
10932: scsi_busy &= ~target_id;
10933: AscWriteLramByte(iop_base,
10934: (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10935: asc_dvc->queue_full_or_busy &= ~target_id;
10936: }
10937: }
10938: if (asc_dvc->cur_total_qng >= n_q_used) {
10939: asc_dvc->cur_total_qng -= n_q_used;
10940: if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
10941: asc_dvc->cur_dvc_qng[tid_no]--;
10942: }
10943: } else {
10944: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
10945: scsiq->d3.done_stat = QD_WITH_ERROR;
10946: goto FATAL_ERR_QDONE;
10947: }
10948: if ((scsiq->d2.srb_ptr == 0UL) ||
10949: ((scsiq->q_status & QS_ABORTED) != 0)) {
10950: return (0x11);
10951: } else if (scsiq->q_status == QS_DONE) {
10952: false_overrun = FALSE;
10953: if (scsiq->extra_bytes != 0) {
10954: scsiq->remain_bytes += (ulong) scsiq->extra_bytes;
10955: }
10956: if (scsiq->d3.done_stat == QD_WITH_ERROR) {
10957: if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) {
10958: if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
10959: scsiq->d3.done_stat = QD_NO_ERROR;
10960: scsiq->d3.host_stat = QHSTA_NO_ERROR;
10961: } else if (false_overrun) {
10962: scsiq->d3.done_stat = QD_NO_ERROR;
10963: scsiq->d3.host_stat = QHSTA_NO_ERROR;
10964: }
10965: } else if (scsiq->d3.host_stat ==
10966: QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
10967: AscStopChip(iop_base);
10968: AscSetChipControl(iop_base,
10969: (uchar) (CC_SCSI_RESET | CC_HALT));
10970: DvcDelayNanoSecond(asc_dvc, 60000);
10971: AscSetChipControl(iop_base, CC_HALT);
10972: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
10973: AscSetChipStatus(iop_base, 0);
10974: AscSetChipControl(iop_base, 0);
10975: }
10976: }
10977: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
10978: (*asc_isr_callback) (asc_dvc, scsiq);
10979: } else {
10980: if ((AscReadLramByte(iop_base,
10981: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
10982: SCSICMD_StartStopUnit)) {
10983: asc_dvc->unit_not_ready &= ~target_id;
10984: if (scsiq->d3.done_stat != QD_NO_ERROR) {
10985: asc_dvc->start_motor &= ~target_id;
10986: }
10987: }
10988: }
10989: return (1);
10990: } else {
10991: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
10992: FATAL_ERR_QDONE:
10993: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
10994: (*asc_isr_callback) (asc_dvc, scsiq);
10995: }
10996: return (0x80);
10997: }
10998: }
10999: return (0);
11000: }
11001:
11002: STATIC int
11003: AscISR(
11004: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11005: )
11006: {
11007: ASC_CS_TYPE chipstat;
11008: PortAddr iop_base;
11009: ushort saved_ram_addr;
11010: uchar ctrl_reg;
11011: uchar saved_ctrl_reg;
11012: int int_pending;
11013: int status;
11014: uchar host_flag;
11015:
11016: iop_base = asc_dvc->iop_base;
11017: int_pending = FALSE;
11018: if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
11019: || (asc_dvc->isr_callback == 0)
11020: ) {
11021: return (ERR);
11022: }
11023: if (asc_dvc->in_critical_cnt != 0) {
11024: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
11025: return (ERR);
11026: }
11027: if (asc_dvc->is_in_int) {
11028: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
11029: return (ERR);
11030: }
11031: asc_dvc->is_in_int = TRUE;
11032: ctrl_reg = AscGetChipControl(iop_base);
11033: saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
11034: CC_SINGLE_STEP | CC_DIAG | CC_TEST));
11035: chipstat = AscGetChipStatus(iop_base);
11036: if (chipstat & CSW_SCSI_RESET_LATCH) {
11037: if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
11038: int_pending = TRUE;
11039: asc_dvc->sdtr_done = 0;
11040: saved_ctrl_reg &= (uchar) (~CC_HALT);
11041: while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
11042: AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
11043: AscSetChipControl(iop_base, CC_HALT);
11044: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
11045: AscSetChipStatus(iop_base, 0);
11046: chipstat = AscGetChipStatus(iop_base);
11047: }
11048: }
11049: saved_ram_addr = AscGetChipLramAddr(iop_base);
11050: host_flag = AscReadLramByte(iop_base,
11051: ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR);
11052: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
11053: (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
11054: if ((chipstat & CSW_INT_PENDING)
11055: || (int_pending)
11056: ) {
11057: AscAckInterrupt(iop_base);
11058: int_pending = TRUE;
11059: if ((chipstat & CSW_HALTED) &&
11060: (ctrl_reg & CC_SINGLE_STEP)) {
11061: if (AscIsrChipHalted(asc_dvc) == ERR) {
11062: goto ISR_REPORT_QDONE_FATAL_ERROR;
11063: } else {
11064: saved_ctrl_reg &= (uchar) (~CC_HALT);
11065: }
11066: } else {
11067: ISR_REPORT_QDONE_FATAL_ERROR:
11068: if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
11069: while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
11070: }
11071: } else {
11072: do {
11073: if ((status = AscIsrQDone(asc_dvc)) == 1) {
11074: break;
11075: }
11076: } while (status == 0x11);
11077: }
11078: if ((status & 0x80) != 0)
11079: int_pending = ERR;
11080: }
11081: }
11082: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
11083: AscSetChipLramAddr(iop_base, saved_ram_addr);
11084: AscSetChipControl(iop_base, saved_ctrl_reg);
11085: asc_dvc->is_in_int = FALSE;
11086: return (int_pending);
11087: }
11088:
11089: STATIC uchar _asc_mcode_buf[] ASC_INITDATA =
11090: {
11091: 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11092: 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11093: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11094: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11095: 0x00, 0x00, 0x00, 0x00, 0x91, 0x10, 0x0A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
11096: 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11097: 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
11098: 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00,
11099: 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
11100: 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80,
11101: 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
11102: 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
11103: 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00,
11104: 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1,
11105: 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0xA6, 0x97, 0xCE, 0x81, 0x00, 0x33,
11106: 0x02, 0x00, 0xC0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00,
11107: 0x84, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x03, 0xDE,
11108: 0x00, 0x33, 0x05, 0x00, 0xC0, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60,
11109: 0x00, 0xA2, 0x80, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x2C, 0x01, 0x80, 0x81, 0x03, 0x03, 0x80, 0x63,
11110: 0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC0, 0x88, 0x03, 0x07, 0x02, 0x01,
11111: 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98,
11112: 0xCD, 0x04, 0x15, 0x23, 0xF6, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03,
11113: 0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xC0, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01,
11114: 0x00, 0x33, 0x0B, 0x00, 0xC0, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC0, 0x88,
11115: 0x50, 0x04, 0x90, 0x81, 0x06, 0xAB, 0x8A, 0x01, 0x90, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x9A, 0x01,
11116: 0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
11117: 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xC6, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01,
11118: 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xBC, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D,
11119: 0x00, 0x33, 0x1B, 0x00, 0xC0, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
11120: 0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01,
11121: 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE,
11122: 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
11123: 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0,
11124: 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x67, 0xEB,
11125: 0x11, 0x23, 0xF6, 0x88, 0x04, 0x98, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x32, 0x02,
11126: 0x7C, 0x95, 0x06, 0xA6, 0x3C, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0xC0, 0x88, 0x04, 0x01, 0x03, 0xD8,
11127: 0xB2, 0x98, 0x6A, 0x96, 0x4E, 0x82, 0xFE, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D,
11128: 0x02, 0xA6, 0x78, 0x02, 0x07, 0xA6, 0x66, 0x02, 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x6E, 0x02,
11129: 0x00, 0x33, 0x10, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x50, 0x82, 0x60, 0x96, 0x50, 0x82, 0x04, 0x23,
11130: 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61,
11131: 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01,
11132: 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xB6, 0x02, 0x07, 0xA6, 0x66, 0x02,
11133: 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xC0, 0x02, 0x00, 0xA6, 0xC0, 0x02,
11134: 0x00, 0x33, 0x12, 0x00, 0xC0, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x98, 0x02,
11135: 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
11136: 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xF6, 0x82, 0x18, 0x23, 0x04, 0x61,
11137: 0x18, 0xA0, 0xEE, 0x02, 0x04, 0x01, 0x9C, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xC0, 0x88, 0x08, 0x31,
11138: 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x20, 0x03, 0x00, 0xA6,
11139: 0x20, 0x03, 0x07, 0xA6, 0x18, 0x03, 0x06, 0xA6, 0x1C, 0x03, 0x03, 0xA6, 0x20, 0x04, 0x02, 0xA6,
11140: 0x78, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xFA, 0x82, 0x60, 0x96, 0xFA, 0x82,
11141: 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01,
11142: 0x00, 0xA2, 0x60, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, 0x7E, 0x98, 0x00, 0xA6,
11143: 0x22, 0x03, 0x07, 0xA6, 0x58, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, 0x5C, 0x03, 0x01, 0xA6,
11144: 0x22, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x3E, 0x83, 0x60, 0x96, 0x3E, 0x83,
11145: 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0xC0, 0x88, 0x00, 0x01, 0x05, 0x05,
11146: 0xFF, 0xA2, 0x7E, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x3A, 0x83, 0x05, 0x05, 0x15, 0x01,
11147: 0x00, 0xA2, 0x9E, 0x03, 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
11148: 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0x9A, 0x03, 0x12, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
11149: 0xA8, 0x03, 0x00, 0xA6, 0xC0, 0x03, 0x12, 0x84, 0xA6, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA8, 0x03,
11150: 0x07, 0xA6, 0xB6, 0x03, 0xD8, 0x83, 0x7C, 0x95, 0xAC, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC0, 0x88,
11151: 0xA6, 0x98, 0x80, 0x42, 0x00, 0xA6, 0xC0, 0x03, 0x07, 0xA6, 0xCE, 0x03, 0xD8, 0x83, 0x7C, 0x95,
11152: 0xC4, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC0, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
11153: 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x12, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0xF6, 0x03, 0x80, 0x6B,
11154: 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x10, 0x04, 0x07, 0xA6, 0x08, 0x04, 0x06, 0xA6,
11155: 0x0C, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xF6, 0x83, 0x60, 0x96, 0xF6, 0x83,
11156: 0x20, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
11157: 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33,
11158: 0x30, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC,
11159: 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
11160: 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01,
11161: 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00,
11162: 0x00, 0x33, 0x1D, 0x00, 0xC0, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
11163: 0xC0, 0x88, 0x42, 0x23, 0xF6, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3,
11164: 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23,
11165: 0xF6, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF6, 0x88, 0x04, 0x98,
11166: 0x00, 0xA2, 0xC0, 0x04, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF0, 0x81,
11167: 0x47, 0x23, 0xF6, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x81,
11168: 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xF6, 0x88, 0x04, 0x23,
11169: 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33,
11170: 0x27, 0x00, 0xC0, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01,
11171: 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
11172: 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04,
11173: 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85,
11174: 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
11175: 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01,
11176: 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01,
11177: 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
11178: 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05,
11179: 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC0, 0x88, 0x04, 0xA0,
11180: 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
11181: 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85,
11182: 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0,
11183: 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
11184: 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63,
11185: 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF6, 0x88, 0x07, 0x23,
11186: 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
11187: 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03,
11188: 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC0, 0x88, 0x1D, 0x01, 0x01, 0xD6,
11189: 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
11190: 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61,
11191: 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01,
11192: 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
11193: 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6,
11194: 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20,
11195: 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
11196: 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
11197: 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43,
11198: 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
11199: 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06,
11200: 0x00, 0x33, 0x2A, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6,
11201: 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC0, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
11202: 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01,
11203: 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33,
11204: 0x2C, 0x00, 0xC0, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
11205: 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC0, 0x88, 0x00, 0x00, 0x80, 0x67,
11206: 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61,
11207: 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
11208: 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05,
11209: 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01,
11210: 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
11211: 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00,
11212: 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00,
11213: 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
11214: 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33,
11215: 0x07, 0x00, 0xC0, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01,
11216: 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
11217: 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63,
11218: 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02,
11219: 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
11220: 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04,
11221: 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08,
11222: 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
11223: 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01,
11224: 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08,
11225: 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
11226: 0x00, 0x33, 0x3E, 0x00, 0xC0, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B,
11227: 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09,
11228: 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
11229: 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E,
11230: 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB2, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63,
11231: 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, 0x13, 0x23,
11232: 0xF6, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62,
11233: 0xE0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7,
11234: 0x41, 0x23, 0xF6, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
11235: };
11236:
11237: STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf);
11238: STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012B5442UL;
11239:
11240: #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
11241: STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
11242: {
11243: SCSICMD_Inquiry,
11244: SCSICMD_RequestSense,
11245: SCSICMD_ReadCapacity,
11246: SCSICMD_ReadTOC,
11247: SCSICMD_ModeSelect6,
11248: SCSICMD_ModeSense6,
11249: SCSICMD_ModeSelect10,
11250: SCSICMD_ModeSense10,
11251: 0xFF,
11252: 0xFF,
11253: 0xFF,
11254: 0xFF,
11255: 0xFF,
11256: 0xFF,
11257: 0xFF,
11258: 0xFF
11259: };
11260:
11261: STATIC int
11262: AscExeScsiQueue(
11263: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11264: REG ASC_SCSI_Q * scsiq
11265: )
11266: {
11267: PortAddr iop_base;
11268: int last_int_level;
11269: int sta;
11270: int n_q_required;
11271: int disable_syn_offset_one_fix;
11272: int i;
11273: ulong addr;
11274: ASC_EXE_CALLBACK asc_exe_callback;
11275: ushort sg_entry_cnt = 0;
11276: ushort sg_entry_cnt_minus_one = 0;
11277: uchar target_ix;
11278: uchar tid_no;
11279: uchar sdtr_data;
11280: uchar extra_bytes;
11281: uchar scsi_cmd;
11282: uchar disable_cmd;
11283: ASC_SG_HEAD *sg_head;
11284: ulong data_cnt;
11285:
11286: iop_base = asc_dvc->iop_base;
11287: sg_head = scsiq->sg_head;
11288: asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
11289: if (asc_dvc->err_code != 0)
11290: return (ERR);
11291: if (scsiq == (ASC_SCSI_Q *) 0L) {
11292: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
11293: return (ERR);
11294: }
11295: scsiq->q1.q_no = 0;
11296: if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
11297: scsiq->q1.extra_bytes = 0;
11298: }
11299: sta = 0;
11300: target_ix = scsiq->q2.target_ix;
11301: tid_no = ASC_TIX_TO_TID(target_ix);
11302: n_q_required = 1;
11303: if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
11304: if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
11305: asc_dvc->sdtr_done &= ~scsiq->q1.target_id ;
11306: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11307: AscMsgOutSDTR(asc_dvc,
11308: asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
11309: (uchar) (asc_dvc->max_sdtr_index - 1)],
11310: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
11311: scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
11312: }
11313: }
11314: last_int_level = DvcEnterCritical();
11315: if (asc_dvc->in_critical_cnt != 0) {
11316: DvcLeaveCritical(last_int_level);
11317: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
11318: return (ERR);
11319: }
11320: asc_dvc->in_critical_cnt++;
11321: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
11322: if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
11323: asc_dvc->in_critical_cnt--;
11324: DvcLeaveCritical(last_int_level);
11325: return (ERR);
11326: }
11327: if (sg_entry_cnt > ASC_MAX_SG_LIST) {
11328: return (ERR);
11329: }
11330: if (sg_entry_cnt == 1) {
11331: scsiq->q1.data_addr = sg_head->sg_list[0].addr;
11332: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
11333: scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
11334: }
11335: sg_entry_cnt_minus_one = sg_entry_cnt - 1;
11336: }
11337: scsi_cmd = scsiq->cdbptr[0];
11338: disable_syn_offset_one_fix = FALSE;
11339: if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
11340: !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
11341: if (scsiq->q1.cntl & QC_SG_HEAD) {
11342: data_cnt = 0;
11343: for (i = 0; i < sg_entry_cnt; i++) {
11344: data_cnt += sg_head->sg_list[i].bytes;
11345: }
11346: } else {
11347: data_cnt = scsiq->q1.data_cnt;
11348: }
11349: if (data_cnt != 0UL) {
11350: if (data_cnt < 512UL) {
11351: disable_syn_offset_one_fix = TRUE;
11352: } else {
11353: for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) {
11354: disable_cmd = _syn_offset_one_disable_cmd[i];
11355: if (disable_cmd == 0xFF) {
11356: break;
11357: }
11358: if (scsi_cmd == disable_cmd) {
11359: disable_syn_offset_one_fix = TRUE;
11360: break;
11361: }
11362: }
11363: }
11364: }
11365: }
11366: if (disable_syn_offset_one_fix) {
11367: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
11368: scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
11369: ASC_TAG_FLAG_DISABLE_DISCONNECT);
11370: } else {
11371: scsiq->q2.tag_code &= 0x23;
11372: }
11373: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
11374: if (asc_dvc->bug_fix_cntl) {
11375: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11376: if ((scsi_cmd == SCSICMD_Read6) ||
11377: (scsi_cmd == SCSICMD_Read10)) {
11378: addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr +
11379: sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
11380: extra_bytes = (uchar) ((ushort) addr & 0x0003);
11381: if ((extra_bytes != 0) &&
11382: ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
11383: == 0)) {
11384: scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
11385: scsiq->q1.extra_bytes = extra_bytes;
11386: sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
11387: (ulong) extra_bytes;
11388: }
11389: }
11390: }
11391: }
11392: sg_head->entry_to_copy = sg_head->entry_cnt;
11393: n_q_required = AscSgListToQueue(sg_entry_cnt);
11394: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
11395: (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11396: if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11397: n_q_required)) == 1) {
11398: asc_dvc->in_critical_cnt--;
11399: if (asc_exe_callback != 0) {
11400: (*asc_exe_callback) (asc_dvc, scsiq);
11401: }
11402: DvcLeaveCritical(last_int_level);
11403: return (sta);
11404: }
11405: }
11406: } else {
11407: if (asc_dvc->bug_fix_cntl) {
11408: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11409: if ((scsi_cmd == SCSICMD_Read6) ||
11410: (scsi_cmd == SCSICMD_Read10)) {
11411: addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
11412: extra_bytes = (uchar) ((ushort) addr & 0x0003);
11413: if ((extra_bytes != 0) &&
11414: ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
11415: == 0)) {
11416: if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
11417: scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
11418: scsiq->q1.data_cnt -= (ulong) extra_bytes;
11419: scsiq->q1.extra_bytes = extra_bytes;
11420: }
11421: }
11422: }
11423: }
11424: }
11425: n_q_required = 1;
11426: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
11427: ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11428: if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11429: n_q_required)) == 1) {
11430: asc_dvc->in_critical_cnt--;
11431: if (asc_exe_callback != 0) {
11432: (*asc_exe_callback) (asc_dvc, scsiq);
11433: }
11434: DvcLeaveCritical(last_int_level);
11435: return (sta);
11436: }
11437: }
11438: }
11439: asc_dvc->in_critical_cnt--;
11440: DvcLeaveCritical(last_int_level);
11441: return (sta);
11442: }
11443:
11444: STATIC int
11445: AscSendScsiQueue(
11446: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11447: REG ASC_SCSI_Q * scsiq,
11448: uchar n_q_required
11449: )
11450: {
11451: PortAddr iop_base;
11452: uchar free_q_head;
11453: uchar next_qp;
11454: uchar tid_no;
11455: uchar target_ix;
11456: int sta;
11457:
11458: iop_base = asc_dvc->iop_base;
11459: target_ix = scsiq->q2.target_ix;
11460: tid_no = ASC_TIX_TO_TID(target_ix);
11461: sta = 0;
11462: free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
11463: if (n_q_required > 1) {
11464: if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
11465: free_q_head, (uchar) (n_q_required)))
11466: != (uchar) ASC_QLINK_END) {
11467: asc_dvc->last_q_shortage = 0;
11468: scsiq->sg_head->queue_cnt = n_q_required - 1;
11469: scsiq->q1.q_no = free_q_head;
11470: if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
11471: free_q_head)) == 1) {
11472: AscPutVarFreeQHead(iop_base, next_qp);
11473: asc_dvc->cur_total_qng += (uchar) (n_q_required);
11474: asc_dvc->cur_dvc_qng[tid_no]++;
11475: }
11476: return (sta);
11477: }
11478: } else if (n_q_required == 1) {
11479: if ((next_qp = AscAllocFreeQueue(iop_base,
11480: free_q_head)) != ASC_QLINK_END) {
11481: scsiq->q1.q_no = free_q_head;
11482: if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
11483: free_q_head)) == 1) {
11484: AscPutVarFreeQHead(iop_base, next_qp);
11485: asc_dvc->cur_total_qng++;
11486: asc_dvc->cur_dvc_qng[tid_no]++;
11487: }
11488: return (sta);
11489: }
11490: }
11491: return (sta);
11492: }
11493:
11494: STATIC int
11495: AscSgListToQueue(
11496: int sg_list
11497: )
11498: {
11499: int n_sg_list_qs;
11500:
11501: n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
11502: if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
11503: n_sg_list_qs++;
11504: return (n_sg_list_qs + 1);
11505: }
11506:
11507:
11508: STATIC uint
11509: AscGetNumOfFreeQueue(
11510: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11511: uchar target_ix,
11512: uchar n_qs
11513: )
11514: {
11515: uint cur_used_qs;
11516: uint cur_free_qs;
11517: ASC_SCSI_BIT_ID_TYPE target_id;
11518: uchar tid_no;
11519:
11520: target_id = ASC_TIX_TO_TARGET_ID(target_ix);
11521: tid_no = ASC_TIX_TO_TID(target_ix);
11522: if ((asc_dvc->unit_not_ready & target_id) ||
11523: (asc_dvc->queue_full_or_busy & target_id)) {
11524: return (0);
11525: }
11526: if (n_qs == 1) {
11527: cur_used_qs = (uint) asc_dvc->cur_total_qng +
11528: (uint) asc_dvc->last_q_shortage +
11529: (uint) ASC_MIN_FREE_Q;
11530: } else {
11531: cur_used_qs = (uint) asc_dvc->cur_total_qng +
11532: (uint) ASC_MIN_FREE_Q;
11533: }
11534: if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
11535: cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
11536: if (asc_dvc->cur_dvc_qng[tid_no] >=
11537: asc_dvc->max_dvc_qng[tid_no]) {
11538: return (0);
11539: }
11540: return (cur_free_qs);
11541: }
11542: if (n_qs > 1) {
11543: if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
11544: asc_dvc->last_q_shortage = n_qs;
11545: }
11546: }
11547: return (0);
11548: }
11549:
11550: STATIC int
11551: AscPutReadyQueue(
11552: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11553: REG ASC_SCSI_Q * scsiq,
11554: uchar q_no
11555: )
11556: {
11557: ushort q_addr;
11558: uchar tid_no;
11559: uchar sdtr_data;
11560: uchar syn_period_ix;
11561: uchar syn_offset;
11562: PortAddr iop_base;
11563:
11564: iop_base = asc_dvc->iop_base;
11565: if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
11566: ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
11567: tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
11568: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11569: syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
11570: syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
11571: AscMsgOutSDTR(asc_dvc,
11572: asc_dvc->sdtr_period_tbl[syn_period_ix],
11573: syn_offset);
11574: scsiq->q1.cntl |= QC_MSG_OUT;
11575: }
11576: q_addr = ASC_QNO_TO_QADDR(q_no);
11577: if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
11578: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
11579: }
11580: scsiq->q1.status = QS_FREE;
11581: AscMemWordCopyToLram(iop_base,
11582: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
11583: (ushort *) scsiq->cdbptr,
11584: (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
11585: DvcPutScsiQ(iop_base,
11586: (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
11587: (ushort *) & scsiq->q1.cntl,
11588: (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
11589: AscWriteLramWord(iop_base,
11590: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
11591: (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
11592: return (1);
11593: }
11594:
11595: STATIC int
11596: AscPutReadySgListQueue(
11597: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11598: REG ASC_SCSI_Q * scsiq,
11599: uchar q_no
11600: )
11601: {
11602: int sta;
11603: int i;
11604: ASC_SG_HEAD *sg_head;
11605: ASC_SG_LIST_Q scsi_sg_q;
11606: ulong saved_data_addr;
11607: ulong saved_data_cnt;
11608: PortAddr iop_base;
11609: ushort sg_list_dwords;
11610: ushort sg_index;
11611: ushort sg_entry_cnt;
11612: ushort q_addr;
11613: uchar next_qp;
11614:
11615: iop_base = asc_dvc->iop_base;
11616: sg_head = scsiq->sg_head;
11617: saved_data_addr = scsiq->q1.data_addr;
11618: saved_data_cnt = scsiq->q1.data_cnt;
11619: scsiq->q1.data_addr = sg_head->sg_list[0].addr;
11620: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
11621: sg_entry_cnt = sg_head->entry_cnt - 1;
11622: if (sg_entry_cnt != 0) {
11623: scsiq->q1.cntl |= QC_SG_HEAD;
11624: q_addr = ASC_QNO_TO_QADDR(q_no);
11625: sg_index = 1;
11626: scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
11627: scsi_sg_q.sg_head_qp = q_no;
11628: scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
11629: for (i = 0; i < sg_head->queue_cnt; i++) {
11630: scsi_sg_q.seq_no = i + 1;
11631: if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
11632: sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
11633: sg_entry_cnt -= ASC_SG_LIST_PER_Q;
11634: if (i == 0) {
11635: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
11636: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
11637: } else {
11638: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
11639: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
11640: }
11641: } else {
11642: scsi_sg_q.cntl |= QCSG_SG_XFER_END;
11643: sg_list_dwords = sg_entry_cnt << 1;
11644: if (i == 0) {
11645: scsi_sg_q.sg_list_cnt = sg_entry_cnt;
11646: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
11647: } else {
11648: scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
11649: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
11650: }
11651: sg_entry_cnt = 0;
11652: }
11653: next_qp = AscReadLramByte(iop_base,
11654: (ushort) (q_addr + ASC_SCSIQ_B_FWD));
11655: scsi_sg_q.q_no = next_qp;
11656: q_addr = ASC_QNO_TO_QADDR(next_qp);
11657: AscMemWordCopyToLram(iop_base,
11658: (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
11659: (ushort *) & scsi_sg_q,
11660: (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
11661: AscMemDWordCopyToLram(iop_base,
11662: (ushort) (q_addr + ASC_SGQ_LIST_BEG),
11663: (ulong *) & sg_head->sg_list[sg_index],
11664: (ushort) sg_list_dwords);
11665: sg_index += ASC_SG_LIST_PER_Q;
11666: }
11667: } else {
11668: scsiq->q1.cntl &= ~QC_SG_HEAD;
11669: }
11670: sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
11671: scsiq->q1.data_addr = saved_data_addr;
11672: scsiq->q1.data_cnt = saved_data_cnt;
11673: return (sta);
11674: }
11675:
11676: STATIC int
11677: AscAbortSRB(
11678: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11679: ulong srb_ptr
11680: )
11681: {
11682: int sta;
11683: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
11684: PortAddr iop_base;
11685:
11686: iop_base = asc_dvc->iop_base;
11687: sta = ERR;
11688: saved_unit_not_ready = asc_dvc->unit_not_ready;
11689: asc_dvc->unit_not_ready = 0xFF;
11690: AscWaitISRDone(asc_dvc);
11691: if (AscStopQueueExe(iop_base) == 1) {
11692: if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
11693: sta = 1;
11694: AscCleanUpBusyQueue(iop_base);
11695: AscStartQueueExe(iop_base);
11696: } else {
11697: sta = 0;
11698: AscStartQueueExe(iop_base);
11699: }
11700: }
11701: asc_dvc->unit_not_ready = saved_unit_not_ready;
11702: return (sta);
11703: }
11704:
11705: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
11706: STATIC int
11707: AscResetDevice(
11708: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11709: uchar target_ix
11710: )
11711: {
11712: PortAddr iop_base;
11713: int sta;
11714: uchar tid_no;
11715:
11716: ASC_SCSI_BIT_ID_TYPE target_id;
11717: int i;
11718: ASC_SCSI_REQ_Q scsiq_buf;
11719: ASC_SCSI_REQ_Q *scsiq;
11720: uchar *buf;
11721: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
11722: iop_base = asc_dvc->iop_base;
11723: tid_no = ASC_TIX_TO_TID(target_ix);
11724: target_id = ASC_TID_TO_TARGET_ID(tid_no);
11725: saved_unit_not_ready = asc_dvc->unit_not_ready;
11726: asc_dvc->unit_not_ready = target_id;
11727: sta = ERR;
11728: AscWaitTixISRDone(asc_dvc, target_ix);
11729: if (AscStopQueueExe(iop_base) == 1) {
11730: if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
11731: AscCleanUpBusyQueue(iop_base);
11732: AscStartQueueExe(iop_base);
11733: AscWaitTixISRDone(asc_dvc, target_ix);
11734: sta = TRUE;
11735: scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
11736: buf = (uchar *) & scsiq_buf;
11737: for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
11738: *buf++ = 0x00;
11739: }
11740: scsiq->r1.status = (uchar) QS_READY;
11741: scsiq->r2.cdb_len = 6;
11742: scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
11743: scsiq->r1.target_id = target_id;
11744: scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
11745: scsiq->cdbptr = (uchar *) scsiq->cdb;
11746: scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
11747: AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
11748: M1_BUS_DVC_RESET);
11749: asc_dvc->unit_not_ready &= ~target_id;
11750: asc_dvc->sdtr_done |= target_id;
11751: if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq)
11752: == 1) {
11753: asc_dvc->unit_not_ready = target_id;
11754: DvcSleepMilliSecond(1000);
11755: _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq);
11756: if (AscStopQueueExe(iop_base) == 1) {
11757: AscCleanUpDiscQueue(iop_base);
11758: AscStartQueueExe(iop_base);
11759: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
11760: AscSetRunChipSynRegAtID(iop_base, tid_no,
11761: ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11762: }
11763: AscWaitTixISRDone(asc_dvc, target_ix);
11764: }
11765: } else {
11766: sta = 0;
11767: }
11768: asc_dvc->sdtr_done &= ~target_id;
11769: } else {
11770: sta = ERR;
11771: AscStartQueueExe(iop_base);
11772: }
11773: }
11774: asc_dvc->unit_not_ready = saved_unit_not_ready;
11775: return (sta);
11776: }
11777: #endif /* version >= v1.3.89 */
11778:
11779: STATIC int
11780: AscResetSB(
11781: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11782: )
11783: {
11784: int sta;
11785: int i;
11786: PortAddr iop_base;
11787:
11788: iop_base = asc_dvc->iop_base;
11789: asc_dvc->unit_not_ready = 0xFF;
11790: sta = TRUE;
11791: AscWaitISRDone(asc_dvc);
11792: AscStopQueueExe(iop_base);
11793: asc_dvc->sdtr_done = 0;
11794: AscResetChipAndScsiBus(asc_dvc);
11795: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
11796: AscReInitLram(asc_dvc);
11797: for (i = 0; i <= ASC_MAX_TID; i++) {
11798: asc_dvc->cur_dvc_qng[i] = 0;
11799: if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) {
11800: AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11801: }
11802: }
11803: asc_dvc->err_code = 0;
11804: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11805: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11806: sta = ERR;
11807: }
11808: if (AscStartChip(iop_base) == 0) {
11809: sta = ERR;
11810: }
11811: AscStartQueueExe(iop_base);
11812: asc_dvc->unit_not_ready = 0;
11813: asc_dvc->queue_full_or_busy = 0;
11814: return (sta);
11815: }
11816:
11817: STATIC int
11818: AscSetRunChipSynRegAtID(
11819: PortAddr iop_base,
11820: uchar tid_no,
11821: uchar sdtr_data
11822: )
11823: {
11824: int sta = FALSE;
11825:
11826: if (AscHostReqRiscHalt(iop_base)) {
11827: sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
11828: AscStartChip(iop_base);
11829: return (sta);
11830: }
11831: return (sta);
11832: }
11833:
11834: STATIC int
11835: AscSetChipSynRegAtID(
11836: PortAddr iop_base,
11837: uchar id,
11838: uchar sdtr_data
11839: )
11840: {
11841: ASC_SCSI_BIT_ID_TYPE org_id;
11842: int i;
11843: int sta = TRUE;
11844:
11845: AscSetBank(iop_base, 1);
11846: org_id = AscReadChipDvcID(iop_base);
11847: for (i = 0; i <= ASC_MAX_TID; i++) {
11848: if (org_id == (0x01 << i))
11849: break;
11850: }
11851: org_id = i;
11852: AscWriteChipDvcID(iop_base, id);
11853: if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
11854: AscSetBank(iop_base, 0);
11855: AscSetChipSyn(iop_base, sdtr_data);
11856: if (AscGetChipSyn(iop_base) != sdtr_data) {
11857: sta = FALSE;
11858: }
11859: } else {
11860: sta = FALSE;
11861: }
11862: AscSetBank(iop_base, 1);
11863: AscWriteChipDvcID(iop_base, org_id);
11864: AscSetBank(iop_base, 0);
11865: return (sta);
11866: }
11867:
11868: STATIC int
11869: AscReInitLram(
11870: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11871: )
11872: {
11873: AscInitLram(asc_dvc);
11874: AscInitQLinkVar(asc_dvc);
11875: return (0);
11876: }
11877:
11878: STATIC ushort
11879: AscInitLram(
11880: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11881: )
11882: {
11883: uchar i;
11884: ushort s_addr;
11885: PortAddr iop_base;
11886: ushort warn_code;
11887:
11888: iop_base = asc_dvc->iop_base;
11889: warn_code = 0;
11890: AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
11891: (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
11892: );
11893: i = ASC_MIN_ACTIVE_QNO;
11894: s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
11895: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11896: (uchar) (i + 1));
11897: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11898: (uchar) (asc_dvc->max_total_qng));
11899: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11900: (uchar) i);
11901: i++;
11902: s_addr += ASC_QBLK_SIZE;
11903: for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
11904: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11905: (uchar) (i + 1));
11906: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11907: (uchar) (i - 1));
11908: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11909: (uchar) i);
11910: }
11911: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11912: (uchar) ASC_QLINK_END);
11913: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11914: (uchar) (asc_dvc->max_total_qng - 1));
11915: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11916: (uchar) asc_dvc->max_total_qng);
11917: i++;
11918: s_addr += ASC_QBLK_SIZE;
11919: for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
11920: i++, s_addr += ASC_QBLK_SIZE) {
11921: AscWriteLramByte(iop_base,
11922: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
11923: AscWriteLramByte(iop_base,
11924: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
11925: AscWriteLramByte(iop_base,
11926: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
11927: }
11928: return (warn_code);
11929: }
11930:
11931: STATIC ushort
11932: AscInitQLinkVar(
11933: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11934: )
11935: {
11936: PortAddr iop_base;
11937: int i;
11938: ushort lram_addr;
11939:
11940: iop_base = asc_dvc->iop_base;
11941: AscPutRiscVarFreeQHead(iop_base, 1);
11942: AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
11943: AscPutVarFreeQHead(iop_base, 1);
11944: AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
11945: AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
11946: (uchar) ((int) asc_dvc->max_total_qng + 1));
11947: AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
11948: (uchar) ((int) asc_dvc->max_total_qng + 2));
11949: AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
11950: asc_dvc->max_total_qng);
11951: AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
11952: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11953: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
11954: AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
11955: AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
11956: AscPutQDoneInProgress(iop_base, 0);
11957: lram_addr = ASC_QADR_BEG;
11958: for (i = 0; i < 32; i++, lram_addr += 2) {
11959: AscWriteLramWord(iop_base, lram_addr, 0);
11960: }
11961: return (0);
11962: }
11963:
11964: STATIC int
11965: AscSetLibErrorCode(
11966: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11967: ushort err_code
11968: )
11969: {
11970: if (asc_dvc->err_code == 0) {
11971: asc_dvc->err_code = err_code;
11972: AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
11973: err_code);
11974: }
11975: return (err_code);
11976: }
11977:
11978:
11979: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
11980: STATIC int
11981: _AscWaitQDone(
11982: PortAddr iop_base,
11983: REG ASC_SCSI_Q * scsiq
11984: )
11985: {
11986: ushort q_addr;
11987: uchar q_status;
11988: int count = 0;
11989:
11990: while (scsiq->q1.q_no == 0) ;
11991: q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
11992: do {
11993: q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
11994: DvcSleepMilliSecond(100L);
11995: if (count++ > 30) {
11996: return (0);
11997: }
11998: } while ((q_status & QS_READY) != 0);
11999: return (1);
12000: }
12001: #endif /* version >= v1.3.89 */
12002:
12003: STATIC uchar
12004: AscMsgOutSDTR(
12005: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12006: uchar sdtr_period,
12007: uchar sdtr_offset
12008: )
12009: {
12010: EXT_MSG sdtr_buf;
12011: uchar sdtr_period_index;
12012: PortAddr iop_base;
12013:
12014: iop_base = asc_dvc->iop_base;
12015: sdtr_buf.msg_type = MS_EXTEND;
12016: sdtr_buf.msg_len = MS_SDTR_LEN;
12017: sdtr_buf.msg_req = MS_SDTR_CODE;
12018: sdtr_buf.xfer_period = sdtr_period;
12019: sdtr_offset &= ASC_SYN_MAX_OFFSET;
12020: sdtr_buf.req_ack_offset = sdtr_offset;
12021: if ((sdtr_period_index =
12022: AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
12023: asc_dvc->max_sdtr_index) {
12024: AscMemWordCopyToLram(iop_base,
12025: ASCV_MSGOUT_BEG,
12026: (ushort *) & sdtr_buf,
12027: (ushort) (sizeof (EXT_MSG) >> 1));
12028: return ((sdtr_period_index << 4) | sdtr_offset);
12029: } else {
12030:
12031: sdtr_buf.req_ack_offset = 0;
12032: AscMemWordCopyToLram(iop_base,
12033: ASCV_MSGOUT_BEG,
12034: (ushort *) & sdtr_buf,
12035: (ushort) (sizeof (EXT_MSG) >> 1));
12036: return (0);
12037: }
12038: }
12039:
12040: STATIC uchar
12041: AscCalSDTRData(
12042: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12043: uchar sdtr_period,
12044: uchar syn_offset
12045: )
12046: {
12047: uchar byte;
12048: uchar sdtr_period_ix;
12049:
12050: sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
12051: if (
12052: (sdtr_period_ix > asc_dvc->max_sdtr_index)
12053: ) {
12054: return (0xFF);
12055: }
12056: byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
12057: return (byte);
12058: }
12059:
12060: STATIC void
12061: AscSetChipSDTR(
12062: PortAddr iop_base,
12063: uchar sdtr_data,
12064: uchar tid_no
12065: )
12066: {
12067: AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
12068: AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
12069: return;
12070: }
12071:
12072: STATIC uchar
12073: AscGetSynPeriodIndex(
12074: ASC_DVC_VAR asc_ptr_type * asc_dvc,
12075: ruchar syn_time
12076: )
12077: {
12078: ruchar *period_table;
12079: int max_index;
12080: int min_index;
12081: int i;
12082:
12083: period_table = asc_dvc->sdtr_period_tbl;
12084: max_index = (int) asc_dvc->max_sdtr_index;
12085: min_index = (int)asc_dvc->host_init_sdtr_index ;
12086: if ((syn_time <= period_table[max_index])) {
12087: for (i = min_index; i < (max_index - 1); i++) {
12088: if (syn_time <= period_table[i]) {
12089: return ((uchar) i);
12090: }
12091: }
12092: return ((uchar) max_index);
12093: } else {
12094: return ((uchar) (max_index + 1));
12095: }
12096: }
12097:
12098: STATIC uchar
12099: AscAllocFreeQueue(
12100: PortAddr iop_base,
12101: uchar free_q_head
12102: )
12103: {
12104: ushort q_addr;
12105: uchar next_qp;
12106: uchar q_status;
12107:
12108: q_addr = ASC_QNO_TO_QADDR(free_q_head);
12109: q_status = (uchar) AscReadLramByte(iop_base,
12110: (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
12111: next_qp = AscReadLramByte(iop_base,
12112: (ushort) (q_addr + ASC_SCSIQ_B_FWD));
12113: if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
12114: return (next_qp);
12115: }
12116: return (ASC_QLINK_END);
12117: }
12118:
12119: STATIC uchar
12120: AscAllocMultipleFreeQueue(
12121: PortAddr iop_base,
12122: uchar free_q_head,
12123: uchar n_free_q
12124: )
12125: {
12126: uchar i;
12127:
12128: for (i = 0; i < n_free_q; i++) {
12129: if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
12130: == ASC_QLINK_END) {
12131: return (ASC_QLINK_END);
12132: }
12133: }
12134: return (free_q_head);
12135: }
12136:
12137: STATIC int
12138: AscRiscHaltedAbortSRB(
12139: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12140: ulong srb_ptr
12141: )
12142: {
12143: PortAddr iop_base;
12144: ushort q_addr;
12145: uchar q_no;
12146: ASC_QDONE_INFO scsiq_buf;
12147: ASC_QDONE_INFO *scsiq;
12148: ASC_ISR_CALLBACK asc_isr_callback;
12149: int last_int_level;
12150:
12151: iop_base = asc_dvc->iop_base;
12152: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
12153: last_int_level = DvcEnterCritical();
12154: scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
12155: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
12156: q_no++) {
12157: q_addr = ASC_QNO_TO_QADDR(q_no);
12158: scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
12159: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
12160: if (scsiq->d2.srb_ptr == srb_ptr) {
12161: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
12162: if (((scsiq->q_status & QS_READY) != 0)
12163: && ((scsiq->q_status & QS_ABORTED) == 0)
12164: && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
12165: scsiq->q_status |= QS_ABORTED;
12166: scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
12167: AscWriteLramDWord(iop_base,
12168: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
12169: 0L);
12170: AscWriteLramByte(iop_base,
12171: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12172: scsiq->q_status);
12173: (*asc_isr_callback) (asc_dvc, scsiq);
12174: return (1);
12175: }
12176: }
12177: }
12178: DvcLeaveCritical(last_int_level);
12179: return (0);
12180: }
12181:
12182: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12183: STATIC int
12184: AscRiscHaltedAbortTIX(
12185: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12186: uchar target_ix
12187: )
12188: {
12189: PortAddr iop_base;
12190: ushort q_addr;
12191: uchar q_no;
12192: ASC_QDONE_INFO scsiq_buf;
12193: ASC_QDONE_INFO *scsiq;
12194: ASC_ISR_CALLBACK asc_isr_callback;
12195: int last_int_level;
12196:
12197: iop_base = asc_dvc->iop_base;
12198: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
12199: last_int_level = DvcEnterCritical();
12200: scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
12201: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
12202: q_no++) {
12203: q_addr = ASC_QNO_TO_QADDR(q_no);
12204: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
12205: if (((scsiq->q_status & QS_READY) != 0) &&
12206: ((scsiq->q_status & QS_ABORTED) == 0) &&
12207: ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
12208: if (scsiq->d2.target_ix == target_ix) {
12209: scsiq->q_status |= QS_ABORTED;
12210: scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
12211: AscWriteLramDWord(iop_base,
12212: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
12213: 0L);
12214: AscWriteLramByte(iop_base,
12215: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12216: scsiq->q_status);
12217: (*asc_isr_callback) (asc_dvc, scsiq);
12218: }
12219: }
12220: }
12221: DvcLeaveCritical(last_int_level);
12222: return (1);
12223: }
12224: #endif /* version >= v1.3.89 */
12225:
12226: STATIC int
12227: AscHostReqRiscHalt(
12228: PortAddr iop_base
12229: )
12230: {
12231: int count = 0;
12232: int sta = 0;
12233: uchar saved_stop_code;
12234:
12235: if (AscIsChipHalted(iop_base))
12236: return (1);
12237: saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12238: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12239: ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
12240: );
12241: do {
12242: if (AscIsChipHalted(iop_base)) {
12243: sta = 1;
12244: break;
12245: }
12246: DvcSleepMilliSecond(100);
12247: } while (count++ < 20);
12248: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
12249: return (sta);
12250: }
12251:
12252: STATIC int
12253: AscStopQueueExe(
12254: PortAddr iop_base
12255: )
12256: {
12257: int count = 0;
12258:
12259: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
12260: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12261: ASC_STOP_REQ_RISC_STOP);
12262: do {
12263: if (
12264: AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
12265: ASC_STOP_ACK_RISC_STOP) {
12266: return (1);
12267: }
12268: DvcSleepMilliSecond(100);
12269: } while (count++ < 20);
12270: }
12271: return (0);
12272: }
12273:
12274: STATIC int
12275: AscStartQueueExe(
12276: PortAddr iop_base
12277: )
12278: {
12279: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12280: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
12281: }
12282: return (1);
12283: }
12284:
12285: STATIC int
12286: AscCleanUpBusyQueue(
12287: PortAddr iop_base
12288: )
12289: {
12290: int count;
12291: uchar stop_code;
12292:
12293: count = 0;
12294: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12295: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12296: ASC_STOP_CLEAN_UP_BUSY_Q);
12297: do {
12298: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12299: if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
12300: break;
12301: DvcSleepMilliSecond(100);
12302: } while (count++ < 20);
12303: }
12304: return (1);
12305: }
12306:
12307: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12308: STATIC int
12309: AscCleanUpDiscQueue(
12310: PortAddr iop_base
12311: )
12312: {
12313: int count;
12314: uchar stop_code;
12315:
12316: count = 0;
12317: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12318: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12319: ASC_STOP_CLEAN_UP_DISC_Q);
12320: do {
12321: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12322: if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
12323: break;
12324: DvcSleepMilliSecond(100);
12325: } while (count++ < 20);
12326: }
12327: return (1);
12328: }
12329: #endif /* version >= v1.3.89 */
12330:
12331: STATIC int
12332: AscWaitTixISRDone(
12333: ASC_DVC_VAR asc_ptr_type * asc_dvc,
12334: uchar target_ix
12335: )
12336: {
12337: uchar cur_req;
12338: uchar tid_no;
12339: int i = 0;
12340:
12341: tid_no = ASC_TIX_TO_TID(target_ix);
12342: while (i++ < 10) {
12343: if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
12344: break;
12345: }
12346: DvcSleepMilliSecond(1000L);
12347: if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
12348: break;
12349: }
12350: }
12351: return (1);
12352: }
12353:
12354: STATIC int
12355: AscWaitISRDone(
12356: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12357: )
12358: {
12359: int tid;
12360:
12361: for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12362: AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
12363: }
12364: return (1);
12365: }
12366:
12367: STATIC ulong
12368: AscGetOnePhyAddr(
12369: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12370: uchar * buf_addr,
12371: ulong buf_size
12372: )
12373: {
12374: ASC_MIN_SG_HEAD sg_head;
12375:
12376: sg_head.entry_cnt = ASC_MIN_SG_LIST;
12377: if (DvcGetSGList(asc_dvc, (uchar *) buf_addr,
12378: buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) {
12379: return (0L);
12380: }
12381: if (sg_head.entry_cnt > 1) {
12382: return (0L);
12383: }
12384: return (sg_head.sg_list[0].addr);
12385: }
12386:
12387: STATIC void
12388: DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
12389: {
12390: udelay(micro_sec);
12391: }
12392:
12393: STATIC void
12394: DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type * asc_dvc, ulong nano_sec)
12395: {
12396: udelay((nano_sec + 999)/1000);
12397: }
12398:
12399: ASC_INITFUNC(
12400: STATIC ulong
12401: AscGetEisaProductID(
12402: PortAddr iop_base
12403: )
12404: )
12405: {
12406: PortAddr eisa_iop;
12407: ushort product_id_high, product_id_low;
12408: ulong product_id;
12409:
12410: eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
12411: product_id_low = inpw(eisa_iop);
12412: product_id_high = inpw(eisa_iop + 2);
12413: product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
12414: return (product_id);
12415: }
12416:
12417: ASC_INITFUNC(
12418: STATIC PortAddr
12419: AscSearchIOPortAddrEISA(
12420: PortAddr iop_base
12421: )
12422: )
12423: {
12424: ulong eisa_product_id;
12425:
12426: if (iop_base == 0) {
12427: iop_base = ASC_EISA_MIN_IOP_ADDR;
12428: } else {
12429: if (iop_base == ASC_EISA_MAX_IOP_ADDR)
12430: return (0);
12431: if ((iop_base & 0x0050) == 0x0050) {
12432: iop_base += ASC_EISA_BIG_IOP_GAP;
12433: } else {
12434: iop_base += ASC_EISA_SMALL_IOP_GAP;
12435: }
12436: }
12437: while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
12438: eisa_product_id = AscGetEisaProductID(iop_base);
12439: if ((eisa_product_id == ASC_EISA_ID_740) ||
12440: (eisa_product_id == ASC_EISA_ID_750)) {
12441: if (AscFindSignature(iop_base)) {
12442: inpw(iop_base + 4);
12443: return (iop_base);
12444: }
12445: }
12446: if (iop_base == ASC_EISA_MAX_IOP_ADDR)
12447: return (0);
12448: if ((iop_base & 0x0050) == 0x0050) {
12449: iop_base += ASC_EISA_BIG_IOP_GAP;
12450: } else {
12451: iop_base += ASC_EISA_SMALL_IOP_GAP;
12452: }
12453: }
12454: return (0);
12455: }
12456:
12457: STATIC int
12458: AscStartChip(
12459: PortAddr iop_base
12460: )
12461: {
12462: AscSetChipControl(iop_base, 0);
12463: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
12464: return (0);
12465: }
12466: return (1);
12467: }
12468:
12469: STATIC int
12470: AscStopChip(
12471: PortAddr iop_base
12472: )
12473: {
12474: uchar cc_val;
12475:
12476: cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
12477: AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
12478: AscSetChipIH(iop_base, INS_HALT);
12479: AscSetChipIH(iop_base, INS_RFLAG_WTM);
12480: if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
12481: return (0);
12482: }
12483: return (1);
12484: }
12485:
12486: STATIC int
12487: AscIsChipHalted(
12488: PortAddr iop_base
12489: )
12490: {
12491: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
12492: if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
12493: return (1);
12494: }
12495: }
12496: return (0);
12497: }
12498:
12499: STATIC void
12500: AscSetChipIH(
12501: PortAddr iop_base,
12502: ushort ins_code
12503: )
12504: {
12505: AscSetBank(iop_base, 1);
12506: AscWriteChipIH(iop_base, ins_code);
12507: AscSetBank(iop_base, 0);
12508: return;
12509: }
12510:
12511: STATIC void
12512: AscAckInterrupt(
12513: PortAddr iop_base
12514: )
12515: {
12516: uchar host_flag;
12517: uchar risc_flag;
12518: ushort loop;
12519:
12520: loop = 0;
12521: do {
12522: risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
12523: if (loop++ > 0x7FFF) {
12524: break;
12525: }
12526: } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
12527: host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
12528: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
12529: (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
12530: AscSetChipStatus(iop_base, CIW_INT_ACK);
12531: loop = 0;
12532: while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
12533: AscSetChipStatus(iop_base, CIW_INT_ACK);
12534: if (loop++ > 3) {
12535: break;
12536: }
12537: }
12538: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
12539: return;
12540: }
12541:
12542: STATIC void
12543: AscDisableInterrupt(
12544: PortAddr iop_base
12545: )
12546: {
12547: ushort cfg;
12548:
12549: cfg = AscGetChipCfgLsw(iop_base);
12550: AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
12551: return;
12552: }
12553:
12554: STATIC void
12555: AscEnableInterrupt(
12556: PortAddr iop_base
12557: )
12558: {
12559: ushort cfg;
12560:
12561: cfg = AscGetChipCfgLsw(iop_base);
12562: AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
12563: return;
12564: }
12565:
12566:
12567:
12568: STATIC void
12569: AscSetBank(
12570: PortAddr iop_base,
12571: uchar bank
12572: )
12573: {
12574: uchar val;
12575:
12576: val = AscGetChipControl(iop_base) &
12577: (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
12578: if (bank == 1) {
12579: val |= CC_BANK_ONE;
12580: } else if (bank == 2) {
12581: val |= CC_DIAG | CC_BANK_ONE;
12582: } else {
12583: val &= ~CC_BANK_ONE;
12584: }
12585: AscSetChipControl(iop_base, val);
12586: return;
12587: }
12588:
12589: STATIC int
12590: AscResetChipAndScsiBus(
12591: ASC_DVC_VAR *asc_dvc
12592: )
12593: {
12594: PortAddr iop_base;
12595:
12596: iop_base = asc_dvc->iop_base;
12597: while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
12598: AscStopChip(iop_base);
12599: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
12600: DvcDelayNanoSecond(asc_dvc, 60000);
12601: AscSetChipIH(iop_base, INS_RFLAG_WTM);
12602: AscSetChipIH(iop_base, INS_HALT);
12603: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
12604: AscSetChipControl(iop_base, CC_HALT);
12605: DvcSleepMilliSecond(200);
12606: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
12607: AscSetChipStatus(iop_base, 0);
12608: return (AscIsChipHalted(iop_base));
12609: }
12610:
12611: ASC_INITFUNC(
12612: STATIC ulong
12613: AscGetMaxDmaCount(
12614: ushort bus_type
12615: )
12616: )
12617: {
12618: if (bus_type & ASC_IS_ISA)
12619: return (ASC_MAX_ISA_DMA_COUNT);
12620: else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
12621: return (ASC_MAX_VL_DMA_COUNT);
12622: return (ASC_MAX_PCI_DMA_COUNT);
12623: }
12624:
12625: ASC_INITFUNC(
12626: STATIC ushort
12627: AscGetIsaDmaChannel(
12628: PortAddr iop_base
12629: )
12630: )
12631: {
12632: ushort channel;
12633:
12634: channel = AscGetChipCfgLsw(iop_base) & 0x0003;
12635: if (channel == 0x03)
12636: return (0);
12637: else if (channel == 0x00)
12638: return (7);
12639: return (channel + 4);
12640: }
12641:
12642: ASC_INITFUNC(
12643: STATIC ushort
12644: AscSetIsaDmaChannel(
12645: PortAddr iop_base,
12646: ushort dma_channel
12647: )
12648: )
12649: {
12650: ushort cfg_lsw;
12651: uchar value;
12652:
12653: if ((dma_channel >= 5) && (dma_channel <= 7)) {
12654: if (dma_channel == 7)
12655: value = 0x00;
12656: else
12657: value = dma_channel - 4;
12658: cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
12659: cfg_lsw |= value;
12660: AscSetChipCfgLsw(iop_base, cfg_lsw);
12661: return (AscGetIsaDmaChannel(iop_base));
12662: }
12663: return (0);
12664: }
12665:
12666: ASC_INITFUNC(
12667: STATIC uchar
12668: AscSetIsaDmaSpeed(
12669: PortAddr iop_base,
12670: uchar speed_value
12671: )
12672: )
12673: {
12674: speed_value &= 0x07;
12675: AscSetBank(iop_base, 1);
12676: AscWriteChipDmaSpeed(iop_base, speed_value);
12677: AscSetBank(iop_base, 0);
12678: return (AscGetIsaDmaSpeed(iop_base));
12679: }
12680:
12681: ASC_INITFUNC(
12682: STATIC uchar
12683: AscGetIsaDmaSpeed(
12684: PortAddr iop_base
12685: )
12686: )
12687: {
12688: uchar speed_value;
12689:
12690: AscSetBank(iop_base, 1);
12691: speed_value = AscReadChipDmaSpeed(iop_base);
12692: speed_value &= 0x07;
12693: AscSetBank(iop_base, 0);
12694: return (speed_value);
12695: }
12696:
12697: ASC_INITFUNC(
12698: STATIC ushort
12699: AscReadPCIConfigWord(
12700: ASC_DVC_VAR asc_ptr_type *asc_dvc,
12701: ushort pci_config_offset)
12702: )
12703: {
12704: uchar lsb, msb;
12705:
12706: lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
12707: msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
12708: return ((ushort) ((msb << 8) | lsb));
12709: }
12710:
12711: ASC_INITFUNC(
12712: STATIC ushort
12713: AscInitGetConfig(
12714: ASC_DVC_VAR asc_ptr_type * asc_dvc
12715: )
12716: )
12717: {
12718: ushort warn_code;
12719: PortAddr iop_base;
12720: ushort PCIDeviceID;
12721: ushort PCIVendorID;
12722: uchar PCIRevisionID;
12723: uchar prevCmdRegBits;
12724:
12725: warn_code = 0;
12726: iop_base = asc_dvc->iop_base;
12727: asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
12728: if (asc_dvc->err_code != 0) {
12729: return (UW_ERR);
12730: }
12731: if (asc_dvc->bus_type == ASC_IS_PCI) {
12732: PCIVendorID = AscReadPCIConfigWord(asc_dvc,
12733: AscPCIConfigVendorIDRegister);
12734:
12735: PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
12736: AscPCIConfigDeviceIDRegister);
12737:
12738: PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
12739: AscPCIConfigRevisionIDRegister);
12740:
12741: if (PCIVendorID != ASC_PCI_VENDORID) {
12742: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12743: }
12744: prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
12745: AscPCIConfigCommandRegister);
12746:
12747: if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
12748: AscPCICmdRegBits_IOMemBusMaster) {
12749: DvcWritePCIConfigByte(asc_dvc,
12750: AscPCIConfigCommandRegister,
12751: (prevCmdRegBits |
12752: AscPCICmdRegBits_IOMemBusMaster));
12753:
12754: if ((DvcReadPCIConfigByte(asc_dvc,
12755: AscPCIConfigCommandRegister)
12756: & AscPCICmdRegBits_IOMemBusMaster)
12757: != AscPCICmdRegBits_IOMemBusMaster) {
12758: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12759: }
12760: }
12761: if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) ||
12762: (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) {
12763: DvcWritePCIConfigByte(asc_dvc,
12764: AscPCIConfigLatencyTimer, 0x00);
12765: if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer)
12766: != 0x00) {
12767: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12768: }
12769: } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) {
12770: if (DvcReadPCIConfigByte(asc_dvc,
12771: AscPCIConfigLatencyTimer) < 0x20) {
12772: DvcWritePCIConfigByte(asc_dvc,
12773: AscPCIConfigLatencyTimer, 0x20);
12774:
12775: if (DvcReadPCIConfigByte(asc_dvc,
12776: AscPCIConfigLatencyTimer) < 0x20) {
12777: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12778: }
12779: }
12780: }
12781: }
12782:
12783: if (AscFindSignature(iop_base)) {
12784: warn_code |= AscInitAscDvcVar(asc_dvc);
12785: warn_code |= AscInitFromEEP(asc_dvc);
12786: asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
12787: if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
12788: asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
12789: }
12790: } else {
12791: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12792: }
12793: return(warn_code);
12794: }
12795:
12796: ASC_INITFUNC(
12797: STATIC ushort
12798: AscInitSetConfig(
12799: ASC_DVC_VAR asc_ptr_type * asc_dvc
12800: )
12801: )
12802: {
12803: ushort warn_code = 0;
12804:
12805: asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12806: if (asc_dvc->err_code != 0)
12807: return (UW_ERR);
12808: if (AscFindSignature(asc_dvc->iop_base)) {
12809: warn_code |= AscInitFromAscDvcVar(asc_dvc);
12810: asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12811: } else {
12812: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12813: }
12814: return (warn_code);
12815: }
12816:
12817: ASC_INITFUNC(
12818: STATIC ushort
12819: AscInitFromAscDvcVar(
12820: ASC_DVC_VAR asc_ptr_type * asc_dvc
12821: )
12822: )
12823: {
12824: PortAddr iop_base;
12825: ushort cfg_msw;
12826: ushort warn_code;
12827: ushort pci_device_id;
12828:
12829: iop_base = asc_dvc->iop_base;
12830: pci_device_id = asc_dvc->cfg->pci_device_id;
12831: warn_code = 0;
12832: cfg_msw = AscGetChipCfgMsw(iop_base);
12833: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12834: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
12835: warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12836: AscSetChipCfgMsw(iop_base, cfg_msw);
12837: }
12838: if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12839: asc_dvc->cfg->cmd_qng_enabled) {
12840: asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12841: warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12842: }
12843: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12844: warn_code |= ASC_WARN_AUTO_CONFIG;
12845: }
12846: if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
12847: if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
12848: != asc_dvc->irq_no) {
12849: asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
12850: }
12851: }
12852: if (asc_dvc->bus_type & ASC_IS_PCI) {
12853: cfg_msw &= 0xFFC0;
12854: AscSetChipCfgMsw(iop_base, cfg_msw);
12855: if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12856: } else {
12857: if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
12858: (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
12859: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12860: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12861: }
12862: }
12863: } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12864: if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12865: == ASC_CHIP_VER_ASYN_BUG) {
12866: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12867: }
12868: }
12869: if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12870: asc_dvc->cfg->chip_scsi_id) {
12871: asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12872: }
12873: if (asc_dvc->bus_type & ASC_IS_ISA) {
12874: AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12875: AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12876: }
12877: return (warn_code);
12878: }
12879:
12880: ASC_INITFUNC(
12881: STATIC ushort
12882: AscInitAsc1000Driver(
12883: ASC_DVC_VAR asc_ptr_type * asc_dvc
12884: )
12885: )
12886: {
12887: ushort warn_code;
12888: PortAddr iop_base;
12889: extern ushort _asc_mcode_size;
12890: extern ulong _asc_mcode_chksum;
12891: extern uchar _asc_mcode_buf[];
12892:
12893: iop_base = asc_dvc->iop_base;
12894: warn_code = 0;
12895: if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
12896: !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
12897: AscResetChipAndScsiBus(asc_dvc);
12898: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
12899: }
12900: asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
12901: if (asc_dvc->err_code != 0)
12902: return (UW_ERR);
12903: if (!AscFindSignature(asc_dvc->iop_base)) {
12904: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12905: return (warn_code);
12906: }
12907: AscDisableInterrupt(iop_base);
12908: warn_code |= AscInitLram(asc_dvc);
12909: if (asc_dvc->err_code != 0)
12910: return (UW_ERR);
12911: if (AscLoadMicroCode(iop_base, 0, (ushort *) _asc_mcode_buf,
12912: _asc_mcode_size) != _asc_mcode_chksum) {
12913: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
12914: return (warn_code);
12915: }
12916: warn_code |= AscInitMicroCodeVar(asc_dvc);
12917: asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
12918: AscEnableInterrupt(iop_base);
12919: return (warn_code);
12920: }
12921:
12922: ASC_INITFUNC(
12923: STATIC ushort
12924: AscInitAscDvcVar(
12925: ASC_DVC_VAR asc_ptr_type * asc_dvc
12926: )
12927: )
12928: {
12929: int i;
12930: PortAddr iop_base;
12931: ushort warn_code;
12932: uchar chip_version;
12933:
12934: iop_base = asc_dvc->iop_base;
12935: warn_code = 0;
12936: asc_dvc->err_code = 0;
12937: if ((asc_dvc->bus_type &
12938: (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
12939: asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
12940: }
12941: AscSetChipControl(iop_base, CC_HALT);
12942: AscSetChipStatus(iop_base, 0);
12943: asc_dvc->bug_fix_cntl = 0;
12944: asc_dvc->pci_fix_asyn_xfer = 0;
12945: asc_dvc->pci_fix_asyn_xfer_always = 0;
12946: asc_dvc->init_state = 0;
12947: asc_dvc->sdtr_done = 0;
12948: asc_dvc->cur_total_qng = 0;
12949: asc_dvc->is_in_int = 0;
12950: asc_dvc->in_critical_cnt = 0;
12951: asc_dvc->last_q_shortage = 0;
12952: asc_dvc->use_tagged_qng = 0;
12953: asc_dvc->no_scam = 0;
12954: asc_dvc->unit_not_ready = 0;
12955: asc_dvc->queue_full_or_busy = 0;
12956: asc_dvc->redo_scam = 0 ;
12957: asc_dvc->res2 = 0 ;
12958: asc_dvc->host_init_sdtr_index = 0 ;
12959: asc_dvc->res7 = 0 ;
12960: asc_dvc->res8 = 0 ;
12961: asc_dvc->cfg->can_tagged_qng = 0 ;
12962: asc_dvc->cfg->cmd_qng_enabled = 0;
12963: asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
12964: asc_dvc->init_sdtr = 0;
12965: asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
12966: asc_dvc->scsi_reset_wait = 3;
12967: asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
12968: asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
12969: asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
12970: asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
12971: asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
12972: asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
12973: asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
12974: ASC_LIB_VERSION_MINOR;
12975: chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
12976: asc_dvc->cfg->chip_version = chip_version;
12977: asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
12978: asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
12979: asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
12980: asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
12981: asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
12982: asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
12983: asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
12984: asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
12985: asc_dvc->max_sdtr_index = 7;
12986: if ((asc_dvc->bus_type & ASC_IS_PCI) &&
12987: (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
12988: asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
12989: asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
12990: asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
12991: asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
12992: asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
12993: asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
12994: asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
12995: asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
12996: asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
12997: asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
12998: asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
12999: asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
13000: asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
13001: asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
13002: asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
13003: asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
13004: asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
13005: asc_dvc->max_sdtr_index = 15;
13006: if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
13007: {
13008: AscSetExtraControl(iop_base,
13009: (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13010: } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
13011: AscSetExtraControl(iop_base,
13012: (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
13013: }
13014: }
13015: if (asc_dvc->bus_type == ASC_IS_PCI) {
13016: AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13017: }
13018:
13019: asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
13020: if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
13021: AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
13022: asc_dvc->bus_type = ASC_IS_ISAPNP;
13023: }
13024: if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
13025: asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
13026: }
13027: for (i = 0; i <= ASC_MAX_TID; i++) {
13028: asc_dvc->cur_dvc_qng[i] = 0;
13029: asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
13030: asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L;
13031: asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L;
13032: asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
13033: }
13034: return (warn_code);
13035: }
13036:
13037: ASC_INITFUNC(
13038: STATIC ushort
13039: AscInitFromEEP(
13040: ASC_DVC_VAR asc_ptr_type * asc_dvc
13041: )
13042: )
13043: {
13044: ASCEEP_CONFIG eep_config_buf;
13045: ASCEEP_CONFIG *eep_config;
13046: PortAddr iop_base;
13047: ushort chksum;
13048: ushort warn_code;
13049: ushort cfg_msw, cfg_lsw;
13050: int i;
13051: int write_eep = 0;
13052:
13053: iop_base = asc_dvc->iop_base;
13054: warn_code = 0;
13055: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
13056: AscStopQueueExe(iop_base);
13057: if ((AscStopChip(iop_base) == FALSE) ||
13058: (AscGetChipScsiCtrl(iop_base) != 0)) {
13059: asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
13060: AscResetChipAndScsiBus(asc_dvc);
13061: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
13062: }
13063: if (AscIsChipHalted(iop_base) == FALSE) {
13064: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13065: return (warn_code);
13066: }
13067: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13068: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13069: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13070: return (warn_code);
13071: }
13072: eep_config = (ASCEEP_CONFIG *) & eep_config_buf;
13073: cfg_msw = AscGetChipCfgMsw(iop_base);
13074: cfg_lsw = AscGetChipCfgLsw(iop_base);
13075: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
13076: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
13077: warn_code |= ASC_WARN_CFG_MSW_RECOVER;
13078: AscSetChipCfgMsw(iop_base, cfg_msw);
13079: }
13080: chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13081: if (chksum == 0) {
13082: chksum = 0xaa55;
13083: }
13084: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
13085: warn_code |= ASC_WARN_AUTO_CONFIG;
13086: if (asc_dvc->cfg->chip_version == 3) {
13087: if (eep_config->cfg_lsw != cfg_lsw) {
13088: warn_code |= ASC_WARN_EEPROM_RECOVER;
13089: eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
13090: }
13091: if (eep_config->cfg_msw != cfg_msw) {
13092: warn_code |= ASC_WARN_EEPROM_RECOVER;
13093: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
13094: }
13095: }
13096: }
13097: eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
13098: eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
13099: if (chksum != eep_config->chksum) {
13100: if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
13101: ASC_CHIP_VER_PCI_ULTRA_3050 )
13102: {
13103: eep_config->init_sdtr = 0xFF;
13104: eep_config->disc_enable = 0xFF;
13105: eep_config->start_motor = 0xFF;
13106: eep_config->use_cmd_qng = 0;
13107: eep_config->max_total_qng = 0xF0;
13108: eep_config->max_tag_qng = 0x20;
13109: eep_config->cntl = 0xBFFF;
13110: eep_config->chip_scsi_id = 7;
13111: eep_config->no_scam = 0;
13112: eep_config->adapter_info[0] = 0;
13113: eep_config->adapter_info[1] = 0;
13114: eep_config->adapter_info[2] = 0;
13115: eep_config->adapter_info[3] = 0;
13116: eep_config->adapter_info[4] = 0;
13117: /* Indicate EEPROM-less board. */
13118: eep_config->adapter_info[5] = 0xBB;
13119: } else {
13120: write_eep = 1 ;
13121: warn_code |= ASC_WARN_EEPROM_CHKSUM ;
13122: }
13123: }
13124: asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr ;
13125: asc_dvc->cfg->disc_enable = eep_config->disc_enable;
13126: asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
13127: asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
13128: asc_dvc->start_motor = eep_config->start_motor;
13129: asc_dvc->dvc_cntl = eep_config->cntl;
13130: asc_dvc->no_scam = eep_config->no_scam;
13131: asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
13132: asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
13133: asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
13134: asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
13135: asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
13136: asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
13137: if (!AscTestExternalLram(asc_dvc)) {
13138: if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
13139: eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
13140: eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
13141: } else {
13142: eep_config->cfg_msw |= 0x0800;
13143: cfg_msw |= 0x0800;
13144: AscSetChipCfgMsw(iop_base, cfg_msw);
13145: eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
13146: eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
13147: }
13148: } else {
13149: }
13150: if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
13151: eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
13152: }
13153: if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
13154: eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
13155: }
13156: if (eep_config->max_tag_qng > eep_config->max_total_qng) {
13157: eep_config->max_tag_qng = eep_config->max_total_qng;
13158: }
13159: if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
13160: eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
13161: }
13162: asc_dvc->max_total_qng = eep_config->max_total_qng;
13163: if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
13164: eep_config->use_cmd_qng) {
13165: eep_config->disc_enable = eep_config->use_cmd_qng;
13166: warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
13167: }
13168: if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
13169: asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
13170: }
13171: eep_config->chip_scsi_id &= ASC_MAX_TID;
13172: asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
13173: if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
13174: !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
13175: asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
13176: }
13177:
13178: for (i = 0; i <= ASC_MAX_TID; i++) {
13179: asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
13180: asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
13181: asc_dvc->cfg->sdtr_period_offset[i] =
13182: (uchar) (ASC_DEF_SDTR_OFFSET |
13183: (asc_dvc->host_init_sdtr_index << 4));
13184: }
13185: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
13186: if (write_eep) {
13187: (void) AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13188: }
13189: return (warn_code);
13190: }
13191:
13192: ASC_INITFUNC(
13193: STATIC ushort
13194: AscInitMicroCodeVar(
13195: ASC_DVC_VAR asc_ptr_type * asc_dvc
13196: )
13197: )
13198: {
13199: int i;
13200: ushort warn_code;
13201: PortAddr iop_base;
13202: ulong phy_addr;
13203:
13204: iop_base = asc_dvc->iop_base;
13205: warn_code = 0;
13206: for (i = 0; i <= ASC_MAX_TID; i++) {
13207: AscPutMCodeInitSDTRAtID(iop_base, i,
13208: asc_dvc->cfg->sdtr_period_offset[i]
13209: );
13210: }
13211: AscInitQLinkVar(asc_dvc);
13212: AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
13213: asc_dvc->cfg->disc_enable);
13214: AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
13215: ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
13216: if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
13217: (uchar *) asc_dvc->cfg->overrun_buf,
13218: ASC_OVERRUN_BSIZE)) == 0L) {
13219: asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
13220: } else {
13221: phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
13222: AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
13223: AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
13224: ASC_OVERRUN_BSIZE - 8);
13225: }
13226: asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
13227: (ushort) ASCV_MC_DATE_W);
13228: asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
13229: (ushort) ASCV_MC_VER_W);
13230: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13231: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13232: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13233: return (warn_code);
13234: }
13235: if (AscStartChip(iop_base) != 1) {
13236: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13237: return (warn_code);
13238: }
13239: return (warn_code);
13240: }
13241:
13242: ASC_INITFUNC(
13243: STATIC int
13244: AscTestExternalLram(
13245: ASC_DVC_VAR asc_ptr_type * asc_dvc
13246: )
13247: )
13248: {
13249: PortAddr iop_base;
13250: ushort q_addr;
13251: ushort saved_word;
13252: int sta;
13253:
13254: iop_base = asc_dvc->iop_base;
13255: sta = 0;
13256: q_addr = ASC_QNO_TO_QADDR(241);
13257: saved_word = AscReadLramWord(iop_base, q_addr);
13258: AscSetChipLramAddr(iop_base, q_addr);
13259: AscSetChipLramData(iop_base, 0x55AA);
13260: DvcSleepMilliSecond(10);
13261: AscSetChipLramAddr(iop_base, q_addr);
13262: if (AscGetChipLramData(iop_base) == 0x55AA) {
13263: sta = 1;
13264: AscWriteLramWord(iop_base, q_addr, saved_word);
13265: }
13266: return (sta);
13267: }
13268:
13269: ASC_INITFUNC(
13270: STATIC int
13271: AscWriteEEPCmdReg(
13272: PortAddr iop_base,
13273: uchar cmd_reg
13274: )
13275: )
13276: {
13277: uchar read_back;
13278: int retry;
13279:
13280: retry = 0;
13281: while (TRUE) {
13282: AscSetChipEEPCmd(iop_base, cmd_reg);
13283: DvcSleepMilliSecond(1);
13284: read_back = AscGetChipEEPCmd(iop_base);
13285: if (read_back == cmd_reg) {
13286: return (1);
13287: }
13288: if (retry++ > ASC_EEP_MAX_RETRY) {
13289: return (0);
13290: }
13291: }
13292: }
13293:
13294: ASC_INITFUNC(
13295: STATIC int
13296: AscWriteEEPDataReg(
13297: PortAddr iop_base,
13298: ushort data_reg
13299: )
13300: )
13301: {
13302: ushort read_back;
13303: int retry;
13304:
13305: retry = 0;
13306: while (TRUE) {
13307: AscSetChipEEPData(iop_base, data_reg);
13308: DvcSleepMilliSecond(1);
13309: read_back = AscGetChipEEPData(iop_base);
13310: if (read_back == data_reg) {
13311: return (1);
13312: }
13313: if (retry++ > ASC_EEP_MAX_RETRY) {
13314: return (0);
13315: }
13316: }
13317: }
13318:
13319: ASC_INITFUNC(
13320: STATIC void
13321: AscWaitEEPRead(
13322: void
13323: )
13324: )
13325: {
13326: DvcSleepMilliSecond(1);
13327: return;
13328: }
13329:
13330: ASC_INITFUNC(
13331: STATIC void
13332: AscWaitEEPWrite(
13333: void
13334: )
13335: )
13336: {
13337: DvcSleepMilliSecond(20);
13338: return;
13339: }
13340:
13341: ASC_INITFUNC(
13342: STATIC ushort
13343: AscReadEEPWord(
13344: PortAddr iop_base,
13345: uchar addr
13346: )
13347: )
13348: {
13349: ushort read_wval;
13350: uchar cmd_reg;
13351:
13352: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
13353: AscWaitEEPRead();
13354: cmd_reg = addr | ASC_EEP_CMD_READ;
13355: AscWriteEEPCmdReg(iop_base, cmd_reg);
13356: AscWaitEEPRead();
13357: read_wval = AscGetChipEEPData(iop_base);
13358: AscWaitEEPRead();
13359: return (read_wval);
13360: }
13361:
13362: ASC_INITFUNC(
13363: STATIC ushort
13364: AscWriteEEPWord(
13365: PortAddr iop_base,
13366: uchar addr,
13367: ushort word_val
13368: )
13369: )
13370: {
13371: ushort read_wval;
13372:
13373: read_wval = AscReadEEPWord(iop_base, addr);
13374: if (read_wval != word_val) {
13375: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
13376: AscWaitEEPRead();
13377: AscWriteEEPDataReg(iop_base, word_val);
13378: AscWaitEEPRead();
13379: AscWriteEEPCmdReg(iop_base,
13380: (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
13381: AscWaitEEPWrite();
13382: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
13383: AscWaitEEPRead();
13384: return (AscReadEEPWord(iop_base, addr));
13385: }
13386: return (read_wval);
13387: }
13388:
13389: ASC_INITFUNC(
13390: STATIC ushort
13391: AscGetEEPConfig(
13392: PortAddr iop_base,
13393: ASCEEP_CONFIG * cfg_buf, ushort bus_type
13394: )
13395: )
13396: {
13397: ushort wval;
13398: ushort sum;
13399: ushort *wbuf;
13400: int cfg_beg;
13401: int cfg_end;
13402: int s_addr;
13403: int isa_pnp_wsize;
13404:
13405: wbuf = (ushort *) cfg_buf;
13406: sum = 0;
13407: isa_pnp_wsize = 0;
13408: for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
13409: wval = AscReadEEPWord(iop_base, (uchar) s_addr);
13410: sum += wval;
13411: *wbuf = wval;
13412: }
13413: if (bus_type & ASC_IS_VL) {
13414: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
13415: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
13416: } else {
13417: cfg_beg = ASC_EEP_DVC_CFG_BEG;
13418: cfg_end = ASC_EEP_MAX_DVC_ADDR;
13419: }
13420: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
13421: s_addr++, wbuf++) {
13422: wval = AscReadEEPWord(iop_base, (uchar) s_addr);
13423: sum += wval;
13424: *wbuf = wval;
13425: }
13426: *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
13427: return (sum);
13428: }
13429:
13430: ASC_INITFUNC(
13431: STATIC int
13432: AscSetEEPConfigOnce(
13433: PortAddr iop_base,
13434: ASCEEP_CONFIG * cfg_buf, ushort bus_type
13435: )
13436: )
13437: {
13438: int n_error;
13439: ushort *wbuf;
13440: ushort sum;
13441: int s_addr;
13442: int cfg_beg;
13443: int cfg_end;
13444:
13445: wbuf = (ushort *) cfg_buf;
13446: n_error = 0;
13447: sum = 0;
13448: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
13449: sum += *wbuf;
13450: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
13451: n_error++;
13452: }
13453: }
13454: if (bus_type & ASC_IS_VL) {
13455: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
13456: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
13457: } else {
13458: cfg_beg = ASC_EEP_DVC_CFG_BEG;
13459: cfg_end = ASC_EEP_MAX_DVC_ADDR;
13460: }
13461: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
13462: s_addr++, wbuf++) {
13463: sum += *wbuf;
13464: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
13465: n_error++;
13466: }
13467: }
13468: *wbuf = sum;
13469: if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
13470: n_error++;
13471: }
13472: wbuf = (ushort *) cfg_buf;
13473: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
13474: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
13475: n_error++;
13476: }
13477: }
13478: for (s_addr = cfg_beg; s_addr <= cfg_end;
13479: s_addr++, wbuf++) {
13480: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
13481: n_error++;
13482: }
13483: }
13484: return (n_error);
13485: }
13486:
13487: ASC_INITFUNC(
13488: STATIC int
13489: AscSetEEPConfig(
13490: PortAddr iop_base,
13491: ASCEEP_CONFIG * cfg_buf, ushort bus_type
13492: )
13493: )
13494: {
13495: int retry;
13496: int n_error;
13497:
13498: retry = 0;
13499: while (TRUE) {
13500: if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
13501: bus_type)) == 0) {
13502: break;
13503: }
13504: if (++retry > ASC_EEP_MAX_RETRY) {
13505: break;
13506: }
13507: }
13508: return (n_error);
13509: }
13510:
13511: STATIC void
13512: AscAsyncFix(
13513: ASC_DVC_VAR asc_ptr_type *asc_dvc,
13514: uchar tid_no,
13515: ASC_SCSI_INQUIRY *inq)
13516: {
13517: uchar dvc_type;
13518: ASC_SCSI_BIT_ID_TYPE tid_bits;
13519:
13520: dvc_type = inq->byte0.peri_dvc_type;
13521: tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
13522:
13523: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
13524: if (!(asc_dvc->init_sdtr & tid_bits)) {
13525: if ((dvc_type == SCSI_TYPE_CDROM) &&
13526: (AscCompareString((uchar *) inq->vendor_id,
13527: (uchar *) "HP ", 3) == 0)) {
13528: asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
13529: }
13530: asc_dvc->pci_fix_asyn_xfer |= tid_bits;
13531: if ((dvc_type == SCSI_TYPE_PROC) ||
13532: (dvc_type == SCSI_TYPE_SCANNER)) {
13533: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13534: }
13535: if ((dvc_type == SCSI_TYPE_SASD) &&
13536: (AscCompareString((uchar *) inq->vendor_id,
13537: (uchar *) "TANDBERG", 8) == 0) &&
13538: (AscCompareString((uchar *) inq->product_id,
13539: (uchar *) " TDC 36", 7) == 0)) {
13540: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13541: }
13542: if ((dvc_type == SCSI_TYPE_SASD) &&
13543: (AscCompareString((uchar *) inq->vendor_id,
13544: (uchar *) "WANGTEK ", 8) == 0)) {
13545: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13546: }
13547:
13548: if ((dvc_type == SCSI_TYPE_CDROM) &&
13549: (AscCompareString((uchar *) inq->vendor_id,
13550: (uchar *) "NEC ", 8) == 0) &&
13551: (AscCompareString((uchar *) inq->product_id,
13552: (uchar *) "CD-ROM DRIVE ", 16) == 0)) {
13553: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13554: }
13555:
13556: if ((dvc_type == SCSI_TYPE_CDROM) &&
13557: (AscCompareString((uchar *) inq->vendor_id,
13558: (uchar *) "YAMAHA", 6) == 0) &&
13559: (AscCompareString((uchar *) inq->product_id,
13560: (uchar *) "CDR400", 6) == 0)) {
13561: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13562: }
13563: if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
13564: AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
13565: ASYN_SDTR_DATA_FIX_PCI_REV_AB);
13566: }
13567: }
13568: }
13569: return;
13570: }
13571:
13572: STATIC int
13573: AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
13574: {
13575: if ((inq->add_len >= 32) &&
13576: (AscCompareString((uchar *) inq->vendor_id,
13577: (uchar *) "QUANTUM XP34301", 15) == 0) &&
13578: (AscCompareString((uchar *) inq->product_rev_level,
13579: (uchar *) "1071", 4) == 0))
13580: {
13581: return 0;
13582: }
13583: return 1;
13584: }
13585:
13586: STATIC void
13587: AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc,
13588: uchar tid_no, ASC_SCSI_INQUIRY *inq)
13589: {
13590: ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
13591: ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
13592:
13593: orig_init_sdtr = asc_dvc->init_sdtr;
13594: orig_use_tagged_qng = asc_dvc->use_tagged_qng;
13595:
13596: asc_dvc->init_sdtr &= ~tid_bit;
13597: asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
13598: asc_dvc->use_tagged_qng &= ~tid_bit;
13599:
13600: if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) {
13601: if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) {
13602: asc_dvc->init_sdtr |= tid_bit;
13603: }
13604: if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) {
13605: if (AscTagQueuingSafe(inq)) {
13606: asc_dvc->use_tagged_qng |= tid_bit;
13607: asc_dvc->cfg->can_tagged_qng |= tid_bit;
13608: }
13609: }
13610: }
13611: if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
13612: AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
13613: asc_dvc->cfg->disc_enable);
13614: AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
13615: asc_dvc->use_tagged_qng);
13616: AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
13617: asc_dvc->cfg->can_tagged_qng);
13618:
13619: asc_dvc->max_dvc_qng[tid_no] =
13620: asc_dvc->cfg->max_tag_qng[tid_no];
13621: AscWriteLramByte(asc_dvc->iop_base,
13622: (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no),
13623: asc_dvc->max_dvc_qng[tid_no]);
13624: }
13625: if (orig_init_sdtr != asc_dvc->init_sdtr) {
13626: AscAsyncFix(asc_dvc, tid_no, inq);
13627: }
13628: return;
13629: }
13630:
13631: STATIC int
13632: AscCompareString(
13633: ruchar * str1,
13634: ruchar * str2,
13635: int len
13636: )
13637: {
13638: int i;
13639: int diff;
13640:
13641: for (i = 0; i < len; i++) {
13642: diff = (int) (str1[i] - str2[i]);
13643: if (diff != 0)
13644: return (diff);
13645: }
13646: return (0);
13647: }
13648:
13649: STATIC uchar
13650: AscReadLramByte(
13651: PortAddr iop_base,
13652: ushort addr
13653: )
13654: {
13655: uchar byte_data;
13656: ushort word_data;
13657:
13658: if (isodd_word(addr)) {
13659: AscSetChipLramAddr(iop_base, addr - 1);
13660: word_data = AscGetChipLramData(iop_base);
13661: byte_data = (uchar) ((word_data >> 8) & 0xFF);
13662: } else {
13663: AscSetChipLramAddr(iop_base, addr);
13664: word_data = AscGetChipLramData(iop_base);
13665: byte_data = (uchar) (word_data & 0xFF);
13666: }
13667: return (byte_data);
13668: }
13669:
13670: STATIC ushort
13671: AscReadLramWord(
13672: PortAddr iop_base,
13673: ushort addr
13674: )
13675: {
13676: ushort word_data;
13677:
13678: AscSetChipLramAddr(iop_base, addr);
13679: word_data = AscGetChipLramData(iop_base);
13680: return (word_data);
13681: }
13682:
13683: STATIC ulong
13684: AscReadLramDWord(
13685: PortAddr iop_base,
13686: ushort addr
13687: )
13688: {
13689: ushort val_low, val_high;
13690: ulong dword_data;
13691:
13692: AscSetChipLramAddr(iop_base, addr);
13693: val_low = AscGetChipLramData(iop_base);
13694: val_high = AscGetChipLramData(iop_base);
13695: dword_data = ((ulong) val_high << 16) | (ulong) val_low;
13696: return (dword_data);
13697: }
13698:
13699: STATIC void
13700: AscWriteLramWord(
13701: PortAddr iop_base,
13702: ushort addr,
13703: ushort word_val
13704: )
13705: {
13706: AscSetChipLramAddr(iop_base, addr);
13707: AscSetChipLramData(iop_base, word_val);
13708: return;
13709: }
13710:
13711: STATIC void
13712: AscWriteLramDWord(
13713: PortAddr iop_base,
13714: ushort addr,
13715: ulong dword_val
13716: )
13717: {
13718: ushort word_val;
13719:
13720: AscSetChipLramAddr(iop_base, addr);
13721: word_val = (ushort) dword_val;
13722: AscSetChipLramData(iop_base, word_val);
13723: word_val = (ushort) (dword_val >> 16);
13724: AscSetChipLramData(iop_base, word_val);
13725: return;
13726: }
13727:
13728: STATIC void
13729: AscWriteLramByte(
13730: PortAddr iop_base,
13731: ushort addr,
13732: uchar byte_val
13733: )
13734: {
13735: ushort word_data;
13736:
13737: if (isodd_word(addr)) {
13738: addr--;
13739: word_data = AscReadLramWord(iop_base, addr);
13740: word_data &= 0x00FF;
13741: word_data |= (((ushort) byte_val << 8) & 0xFF00);
13742: } else {
13743: word_data = AscReadLramWord(iop_base, addr);
13744: word_data &= 0xFF00;
13745: word_data |= ((ushort) byte_val & 0x00FF);
13746: }
13747: AscWriteLramWord(iop_base, addr, word_data);
13748: return;
13749: }
13750:
13751: STATIC void
13752: AscMemWordCopyToLram(
13753: PortAddr iop_base,
13754: ushort s_addr,
13755: ushort * s_buffer,
13756: int words
13757: )
13758: {
13759: AscSetChipLramAddr(iop_base, s_addr);
13760: DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
13761: return;
13762: }
13763:
13764: STATIC void
13765: AscMemDWordCopyToLram(
13766: PortAddr iop_base,
13767: ushort s_addr,
13768: ulong * s_buffer,
13769: int dwords
13770: )
13771: {
13772: AscSetChipLramAddr(iop_base, s_addr);
13773: DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
13774: return;
13775: }
13776:
13777: STATIC void
13778: AscMemWordCopyFromLram(
13779: PortAddr iop_base,
13780: ushort s_addr,
13781: ushort * d_buffer,
13782: int words
13783: )
13784: {
13785: AscSetChipLramAddr(iop_base, s_addr);
13786: DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
13787: return;
13788: }
13789:
13790: STATIC ulong
13791: AscMemSumLramWord(
13792: PortAddr iop_base,
13793: ushort s_addr,
13794: rint words
13795: )
13796: {
13797: ulong sum;
13798: int i;
13799:
13800: sum = 0L;
13801: for (i = 0; i < words; i++, s_addr += 2) {
13802: sum += AscReadLramWord(iop_base, s_addr);
13803: }
13804: return (sum);
13805: }
13806:
13807: STATIC void
13808: AscMemWordSetLram(
13809: PortAddr iop_base,
13810: ushort s_addr,
13811: ushort set_wval,
13812: rint words
13813: )
13814: {
13815: rint i;
13816:
13817: AscSetChipLramAddr(iop_base, s_addr);
13818: for (i = 0; i < words; i++) {
13819: AscSetChipLramData(iop_base, set_wval);
13820: }
13821: return;
13822: }
13823:
13824:
13825: /*
13826: * --- Adv Library Functions
13827: */
13828:
13829: /* a_qswap.h */
13830: STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = {
13831: 0x9C, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x44, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13832: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13833: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x01, 0xD6, 0x11, 0x00, 0x00, 0x70, 0x01,
13834: 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x10, 0x2D, 0x03, 0x00, 0x00, 0x00, 0x00,
13835: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13836: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13837: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13838: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13839: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13840: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13841: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13842: 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13843: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13844: 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
13845: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13846: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13847: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13848: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13849: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12,
13850: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13851: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13852: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13853: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13854: 0x00, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x0C, 0x1C, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF2, 0xD6, 0x0A,
13855: 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x3E, 0x57, 0x3C, 0x56, 0x0C, 0x1C, 0x00, 0xFC,
13856: 0xA6, 0x00, 0x01, 0x58, 0xAA, 0x13, 0x20, 0xF0, 0xA6, 0x03, 0x06, 0xEC, 0xB9, 0x00, 0x0E, 0x47,
13857: 0x03, 0xE6, 0x10, 0x00, 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0x06, 0xEA, 0xB9, 0x00, 0x47, 0x4B,
13858: 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x4E, 0x12, 0x03, 0xF6, 0xC0, 0x00,
13859: 0x00, 0xF2, 0x68, 0x0A, 0x41, 0x58, 0x03, 0xF6, 0xD0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x49, 0x44,
13860: 0x59, 0xF0, 0x0A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x44, 0x58, 0x00, 0xF2,
13861: 0xE2, 0x0D, 0x02, 0xCC, 0x4A, 0xE4, 0x01, 0x00, 0x55, 0xF0, 0x08, 0x03, 0x45, 0xF4, 0x02, 0x00,
13862: 0x83, 0x5A, 0x04, 0xCC, 0x01, 0x4A, 0x12, 0x12, 0x00, 0xF2, 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4,
13863: 0x01, 0x00, 0xE9, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0xFA, 0x10, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00,
13864: 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0xCE, 0x47, 0x97, 0x13, 0x04, 0xEC, 0xB4, 0x00, 0x00, 0xF2,
13865: 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, 0x00, 0x00, 0x12, 0x12, 0x3E, 0x57, 0x06, 0xCC, 0x45, 0xF4,
13866: 0x02, 0x00, 0x83, 0x5A, 0x00, 0xCC, 0x00, 0xEA, 0xB4, 0x00, 0x92, 0x10, 0x00, 0xF0, 0x8C, 0x01,
13867: 0x43, 0xF0, 0x5C, 0x02, 0x44, 0xF0, 0x60, 0x02, 0x45, 0xF0, 0x64, 0x02, 0x46, 0xF0, 0x68, 0x02,
13868: 0x47, 0xF0, 0x6E, 0x02, 0x48, 0xF0, 0x9E, 0x02, 0xB9, 0x54, 0x62, 0x10, 0x00, 0x1C, 0x5A, 0x10,
13869: 0x02, 0x1C, 0x56, 0x10, 0x1E, 0x1C, 0x52, 0x10, 0x00, 0xF2, 0x1E, 0x11, 0x50, 0x10, 0x06, 0xFC,
13870: 0xA8, 0x00, 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x4E, 0x0A, 0x8C, 0x10, 0x01, 0xF6, 0x01, 0x00,
13871: 0x01, 0xFA, 0xA8, 0x00, 0x00, 0xF2, 0x2C, 0x0B, 0x06, 0x10, 0xB9, 0x54, 0x01, 0xFA, 0xA8, 0x00,
13872: 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x58, 0x0A, 0x01, 0xFC, 0xA8, 0x00, 0x20, 0x10, 0x58, 0x1C,
13873: 0x00, 0xF2, 0x1C, 0x0B, 0x5A, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00,
13874: 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x72, 0x01, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54,
13875: 0x00, 0xFA, 0xA6, 0x00, 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x80, 0x01, 0x03, 0xF6,
13876: 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x0A, 0x13, 0x00, 0xF2, 0x38, 0x10, 0x00, 0xF2,
13877: 0x54, 0x0F, 0x24, 0x10, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x02, 0xF6, 0xD0, 0x00,
13878: 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x49, 0x44, 0x5B, 0xF0, 0x04, 0x03, 0x00, 0xF2, 0x9C, 0x0F,
13879: 0x00, 0xF0, 0x80, 0x01, 0x00, 0xF2, 0x14, 0x10, 0x0C, 0x1C, 0x02, 0x4B, 0xBF, 0x57, 0x9E, 0x43,
13880: 0x77, 0x57, 0x07, 0x4B, 0x20, 0xF0, 0xA6, 0x03, 0x40, 0x1C, 0x1E, 0xF0, 0x30, 0x03, 0x26, 0xF0,
13881: 0x2C, 0x03, 0xA0, 0xF0, 0x1A, 0x03, 0x11, 0xF0, 0xA6, 0x03, 0x12, 0x10, 0x9F, 0xF0, 0x3E, 0x03,
13882: 0x46, 0x1C, 0x82, 0xE7, 0x05, 0x00, 0x9E, 0xE7, 0x11, 0x00, 0x00, 0xF0, 0x06, 0x0A, 0x0C, 0x1C,
13883: 0x48, 0x1C, 0x46, 0x1C, 0x38, 0x54, 0x00, 0xEC, 0xBA, 0x00, 0x08, 0x44, 0x00, 0xEA, 0xBA, 0x00,
13884: 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x08, 0x44, 0x00, 0x4C, 0x82, 0xE7, 0x02, 0x00,
13885: 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x70, 0x03, 0x00, 0xF2, 0x60, 0x0B,
13886: 0x06, 0xF0, 0x80, 0x03, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A,
13887: 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x55, 0xF0, 0xAC, 0x04, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2,
13888: 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x01, 0xF0,
13889: 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x46, 0x1C, 0x0C, 0x1C, 0x67, 0x1B, 0xBF, 0x57, 0x77, 0x57,
13890: 0x02, 0x4B, 0x48, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x96, 0xF0, 0xBC, 0x03,
13891: 0xB1, 0xF0, 0xC0, 0x03, 0x1E, 0xF0, 0xFC, 0x09, 0x85, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0xBE, 0x00,
13892: 0x98, 0x57, 0x14, 0x12, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11,
13893: 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A,
13894: 0x01, 0x48, 0x55, 0xF0, 0x98, 0x04, 0x03, 0x82, 0x03, 0xFC, 0xA0, 0x00, 0x9B, 0x57, 0x40, 0x12,
13895: 0x69, 0x18, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x42, 0x04, 0x69, 0x08, 0x00, 0xF2, 0x12, 0x11,
13896: 0x85, 0xF0, 0x02, 0x0A, 0x68, 0x08, 0x4C, 0x44, 0x28, 0x12, 0x44, 0x48, 0x03, 0xF6, 0xE0, 0x00,
13897: 0x00, 0xF2, 0x68, 0x0A, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xCC, 0x01, 0x48, 0x55, 0xF0,
13898: 0x98, 0x04, 0x4C, 0x44, 0xEF, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x14, 0x10, 0x08, 0x10,
13899: 0x68, 0x18, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x04, 0x80, 0x18, 0xE4, 0x10, 0x00, 0x28, 0x12,
13900: 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00,
13901: 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00,
13902: 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00,
13903: 0x0C, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x82, 0xE7,
13904: 0x02, 0x00, 0x1C, 0x90, 0x40, 0x5C, 0x00, 0x16, 0x01, 0xE6, 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D,
13905: 0x01, 0xF0, 0x80, 0x01, 0x1E, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0xA0, 0x04, 0x42, 0x5B, 0x06, 0xF7,
13906: 0x03, 0x00, 0x46, 0x59, 0xBF, 0x57, 0x77, 0x57, 0x01, 0xE6, 0x80, 0x00, 0x07, 0x80, 0x31, 0x44,
13907: 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x56, 0x13, 0x20, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x4E, 0x12,
13908: 0x00, 0xFC, 0xA2, 0x00, 0x98, 0x57, 0x55, 0xF0, 0x1C, 0x05, 0x31, 0xE4, 0x40, 0x00, 0x00, 0xFC,
13909: 0xA0, 0x00, 0x98, 0x57, 0x36, 0x12, 0x4C, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x89, 0x48, 0x00, 0xF2,
13910: 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x82, 0xE7, 0x06, 0x00, 0x1B, 0x80, 0x48, 0xE4, 0x22, 0x00,
13911: 0x5B, 0xF0, 0x0C, 0x05, 0x48, 0xE4, 0x20, 0x00, 0x59, 0xF0, 0x10, 0x05, 0x00, 0xE6, 0x20, 0x00,
13912: 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x83, 0x80, 0x04, 0x10, 0x00, 0xF2,
13913: 0xA2, 0x0D, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x26, 0x01, 0x01, 0xEA, 0x27, 0x01, 0x04, 0x80,
13914: 0x18, 0xE4, 0x10, 0x00, 0x36, 0x12, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x01, 0xE6, 0x06, 0x00,
13915: 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4E, 0x0D,
13916: 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x04, 0xE6, 0x02, 0x00,
13917: 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0x20, 0x01,
13918: 0x98, 0x57, 0x34, 0x12, 0x00, 0xFC, 0x24, 0x01, 0x98, 0x57, 0x2C, 0x13, 0xB9, 0x54, 0x00, 0xF2,
13919: 0xF6, 0x0E, 0x86, 0xF0, 0xA8, 0x05, 0x03, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0x8C, 0x0E, 0x85, 0xF0,
13920: 0x9E, 0x05, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC,
13921: 0x24, 0x01, 0xB0, 0x57, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFC, 0x9E, 0x00, 0x98, 0x57, 0x5A, 0x12,
13922: 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, 0x52, 0x13, 0x03, 0xE6, 0x0C, 0x00, 0x00, 0xFC, 0x9C, 0x00,
13923: 0x98, 0x57, 0x04, 0x13, 0x03, 0xE6, 0x19, 0x00, 0x05, 0xE6, 0x08, 0x00, 0x00, 0xF6, 0x00, 0x01,
13924: 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x04, 0x13, 0x05, 0xE6,
13925: 0x0F, 0x00, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x86, 0xF0, 0x0A, 0x06, 0x00, 0xF2, 0xBA, 0x0E,
13926: 0x85, 0xF0, 0x00, 0x06, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00,
13927: 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0xF2,
13928: 0xF6, 0x0E, 0x9C, 0x32, 0x4E, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x82, 0xE7,
13929: 0x04, 0x00, 0xB1, 0xF0, 0x22, 0x06, 0x0A, 0xF0, 0x3E, 0x06, 0x05, 0xF0, 0xD6, 0x06, 0x06, 0xF0,
13930: 0xDC, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x04, 0x80,
13931: 0x18, 0xE4, 0x20, 0x00, 0x30, 0x12, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80,
13932: 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2,
13933: 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x99, 0xA4, 0x00, 0xF2, 0x12, 0x11,
13934: 0x09, 0xE7, 0x00, 0x00, 0x9A, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x34, 0x12, 0x09, 0xE7,
13935: 0x1B, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2,
13936: 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2,
13937: 0x12, 0x11, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF0,
13938: 0x0C, 0x09, 0xBB, 0x55, 0x9A, 0x81, 0x03, 0xF7, 0x20, 0x00, 0x09, 0x6F, 0x93, 0x45, 0x55, 0xF0,
13939: 0xE2, 0x06, 0xB1, 0xF0, 0xC2, 0x06, 0x0A, 0xF0, 0xBA, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0,
13940: 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0x47, 0x10, 0x09, 0xE7, 0x08, 0x00,
13941: 0x41, 0x10, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, 0x1E, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA,
13942: 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x2C, 0x90, 0xAE, 0x90, 0x08, 0x50, 0x8A, 0x50, 0x38, 0x54,
13943: 0x1F, 0x40, 0x00, 0xF2, 0xB4, 0x0D, 0x08, 0x10, 0x08, 0x90, 0x8A, 0x90, 0x30, 0x50, 0xB2, 0x50,
13944: 0x9C, 0x32, 0x0C, 0x92, 0x8E, 0x92, 0x38, 0x54, 0x04, 0x80, 0x30, 0xE4, 0x08, 0x00, 0x04, 0x40,
13945: 0x0C, 0x1C, 0x00, 0xF6, 0x03, 0x00, 0xB1, 0xF0, 0x26, 0x07, 0x9E, 0xF0, 0x3A, 0x07, 0x01, 0x48,
13946: 0x55, 0xF0, 0xFC, 0x09, 0x0C, 0x1C, 0x10, 0x44, 0xED, 0x10, 0x0B, 0xF0, 0x5E, 0x07, 0x0C, 0xF0,
13947: 0x62, 0x07, 0x05, 0xF0, 0x52, 0x07, 0x06, 0xF0, 0x58, 0x07, 0x09, 0xF0, 0x24, 0x09, 0x00, 0xF0,
13948: 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0xCF, 0x10, 0x09, 0xE7, 0x08, 0x00, 0xC9, 0x10, 0x2E, 0x1C,
13949: 0x02, 0x10, 0x2C, 0x1C, 0xAA, 0xF0, 0x64, 0x07, 0xAC, 0xF0, 0x72, 0x07, 0x40, 0x10, 0x34, 0x1C,
13950: 0xF3, 0x10, 0xAD, 0xF0, 0x7C, 0x07, 0xC8, 0x10, 0x36, 0x1C, 0xE9, 0x10, 0x2B, 0xF0, 0x82, 0x08,
13951: 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFE, 0x20, 0x12, 0x01, 0x58, 0xD2, 0xF0, 0x82, 0x08, 0x76, 0x18,
13952: 0x18, 0xF4, 0x03, 0x00, 0xEC, 0x12, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xE2, 0x12,
13953: 0x0B, 0xF0, 0x64, 0x07, 0x0C, 0xF0, 0x64, 0x07, 0x36, 0x1C, 0x34, 0x1C, 0xB7, 0x10, 0x38, 0x54,
13954: 0xB9, 0x54, 0x84, 0x80, 0x19, 0xE4, 0x20, 0x00, 0xB2, 0x13, 0x85, 0x80, 0x81, 0x48, 0x66, 0x12,
13955: 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x58, 0x13, 0x1F, 0x80, 0x08, 0x44, 0xC8, 0x44, 0x9F, 0x12,
13956: 0x1F, 0x40, 0x34, 0x91, 0xB6, 0x91, 0x44, 0x55, 0xE5, 0x55, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49,
13957: 0xBB, 0x55, 0x82, 0x81, 0xC0, 0x55, 0x48, 0xF4, 0x0F, 0x00, 0x5A, 0xF0, 0x1A, 0x08, 0x4A, 0xE4,
13958: 0x17, 0x00, 0xD5, 0xF0, 0xFA, 0x07, 0x02, 0xF6, 0x0F, 0x00, 0x02, 0xF4, 0x02, 0x00, 0x02, 0xEA,
13959: 0xB8, 0x00, 0x04, 0x91, 0x86, 0x91, 0x02, 0x4B, 0x2C, 0x90, 0x08, 0x50, 0x2E, 0x90, 0x0A, 0x50,
13960: 0x2C, 0x51, 0xAE, 0x51, 0x00, 0xF2, 0xB6, 0x10, 0x38, 0x54, 0x00, 0xF2, 0xB4, 0x0D, 0x56, 0x10,
13961: 0x34, 0x91, 0xB6, 0x91, 0x0C, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x41, 0x12, 0x0C, 0x91,
13962: 0x8E, 0x91, 0x04, 0x80, 0x18, 0xE4, 0xF7, 0x00, 0x04, 0x40, 0x30, 0x90, 0xB2, 0x90, 0x36, 0x10,
13963: 0x02, 0x80, 0x48, 0xE4, 0x10, 0x00, 0x31, 0x12, 0x82, 0xE7, 0x10, 0x00, 0x84, 0x80, 0x19, 0xE4,
13964: 0x20, 0x00, 0x10, 0x13, 0x0C, 0x90, 0x8E, 0x90, 0x5D, 0xF0, 0x78, 0x07, 0x0C, 0x58, 0x8D, 0x58,
13965: 0x00, 0xF0, 0x64, 0x07, 0x38, 0x54, 0xB9, 0x54, 0x19, 0x80, 0xF1, 0x10, 0x3A, 0x55, 0x19, 0x81,
13966: 0xBB, 0x55, 0x10, 0x90, 0x92, 0x90, 0x10, 0x58, 0x91, 0x58, 0x14, 0x59, 0x95, 0x59, 0x00, 0xF0,
13967: 0x64, 0x07, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x6C, 0x19, 0x19, 0x41, 0x7C, 0x10,
13968: 0x6C, 0x19, 0x0C, 0x51, 0xED, 0x19, 0x8E, 0x51, 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFF, 0x02, 0x13,
13969: 0x6A, 0x10, 0x01, 0x58, 0xD2, 0xF0, 0xC0, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x0A, 0x12,
13970: 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0x06, 0x13, 0x9E, 0xE7, 0x16, 0x00, 0x4C, 0x10,
13971: 0xD1, 0xF0, 0xCA, 0x08, 0x9E, 0xE7, 0x17, 0x00, 0x42, 0x10, 0xD0, 0xF0, 0xD4, 0x08, 0x9E, 0xE7,
13972: 0x19, 0x00, 0x38, 0x10, 0xCF, 0xF0, 0xDE, 0x08, 0x9E, 0xE7, 0x20, 0x00, 0x2E, 0x10, 0xCE, 0xF0,
13973: 0xE8, 0x08, 0x9E, 0xE7, 0x21, 0x00, 0x24, 0x10, 0xCD, 0xF0, 0xF2, 0x08, 0x9E, 0xE7, 0x22, 0x00,
13974: 0x1A, 0x10, 0xCC, 0xF0, 0x04, 0x09, 0x84, 0x80, 0x19, 0xE4, 0x04, 0x00, 0x06, 0x12, 0x9E, 0xE7,
13975: 0x12, 0x00, 0x08, 0x10, 0xCB, 0xF0, 0x0C, 0x09, 0x9E, 0xE7, 0x24, 0x00, 0xB1, 0xF0, 0x0C, 0x09,
13976: 0x05, 0xF0, 0x1E, 0x09, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0xE4, 0x10, 0x00, 0xF2,
13977: 0x60, 0x0B, 0xE9, 0x10, 0x9C, 0x32, 0x82, 0xE7, 0x20, 0x00, 0x32, 0x1C, 0xE9, 0x09, 0x00, 0xF2,
13978: 0x12, 0x11, 0x85, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x01, 0xF0, 0x44, 0x09, 0x1E, 0xF0, 0xFC, 0x09,
13979: 0x00, 0xF0, 0x38, 0x09, 0x30, 0x44, 0x06, 0x12, 0x9E, 0xE7, 0x42, 0x00, 0xB8, 0x10, 0x04, 0xF6,
13980: 0x01, 0x00, 0xB3, 0x45, 0x74, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x22, 0x13, 0x4B, 0xE4,
13981: 0x02, 0x00, 0x36, 0x12, 0x4B, 0xE4, 0x28, 0x00, 0xAC, 0x13, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2,
13982: 0xC8, 0x11, 0x03, 0xF6, 0xD0, 0x00, 0xFA, 0x14, 0x82, 0xE7, 0x01, 0x00, 0x00, 0xF0, 0x80, 0x01,
13983: 0x9E, 0xE7, 0x44, 0x00, 0x4B, 0xE4, 0x02, 0x00, 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x76, 0x10,
13984: 0x00, 0xF2, 0xA2, 0x0D, 0x03, 0xE6, 0x02, 0x00, 0x6C, 0x10, 0x00, 0xF2, 0xA2, 0x0D, 0x19, 0x82,
13985: 0x34, 0x46, 0x0A, 0x13, 0x03, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x43, 0x00, 0x68, 0x10, 0x04, 0x80,
13986: 0x30, 0xE4, 0x20, 0x00, 0x04, 0x40, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x82, 0xE7,
13987: 0x01, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x08, 0x03, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00,
13988: 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x3E, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x3A, 0x12,
13989: 0x04, 0x80, 0x18, 0xE4, 0xFD, 0x00, 0x04, 0x40, 0x1C, 0x1C, 0x9D, 0xF0, 0xEA, 0x09, 0x1C, 0x1C,
13990: 0x9D, 0xF0, 0xF0, 0x09, 0xC1, 0x10, 0x9E, 0xE7, 0x13, 0x00, 0x0A, 0x10, 0x9E, 0xE7, 0x41, 0x00,
13991: 0x04, 0x10, 0x9E, 0xE7, 0x24, 0x00, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0xD5, 0xF0, 0x8A, 0x02,
13992: 0x04, 0xE6, 0x04, 0x00, 0x06, 0x10, 0x04, 0xE6, 0x04, 0x00, 0x9D, 0x41, 0x1C, 0x42, 0x9F, 0xE7,
13993: 0x00, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x03, 0xF6, 0xE0, 0x00, 0x3C, 0x14, 0x44, 0x58, 0x45, 0x58,
13994: 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x3C, 0x14, 0x1E, 0x1C,
13995: 0x00, 0xF0, 0x80, 0x01, 0x12, 0x1C, 0x22, 0x1C, 0xD2, 0x14, 0x00, 0xF0, 0x72, 0x01, 0x83, 0x59,
13996: 0x03, 0xDC, 0x73, 0x57, 0x80, 0x5D, 0x00, 0x16, 0x83, 0x59, 0x03, 0xDC, 0x38, 0x54, 0x70, 0x57,
13997: 0x33, 0x54, 0x3B, 0x54, 0x80, 0x5D, 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x38, 0x54, 0x00, 0xCC,
13998: 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x00, 0x4C, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x01, 0x00,
13999: 0x0E, 0x12, 0x48, 0xE4, 0x05, 0x00, 0x08, 0x12, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11,
14000: 0xC1, 0x5A, 0x3A, 0x55, 0x02, 0xEC, 0xB5, 0x00, 0x45, 0x59, 0x00, 0xF2, 0xF6, 0x0D, 0x83, 0x58,
14001: 0x30, 0xE7, 0x00, 0x00, 0x10, 0x4D, 0x30, 0xE7, 0x40, 0x00, 0x10, 0x4F, 0x38, 0x90, 0xBA, 0x90,
14002: 0x10, 0x5C, 0x80, 0x5C, 0x83, 0x5A, 0x10, 0x4E, 0x04, 0xEA, 0xB5, 0x00, 0x43, 0x5B, 0x03, 0xF4,
14003: 0xE0, 0x00, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x0A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D,
14004: 0x00, 0xF2, 0x38, 0x10, 0x00, 0x16, 0x08, 0x1C, 0x00, 0xFC, 0xAC, 0x00, 0x06, 0x58, 0x67, 0x18,
14005: 0x18, 0xF4, 0x8F, 0xE1, 0x01, 0xFC, 0xAE, 0x00, 0x19, 0xF4, 0x70, 0x1E, 0xB0, 0x54, 0x07, 0x58,
14006: 0x00, 0xFC, 0xB0, 0x00, 0x08, 0x58, 0x00, 0xFC, 0xB2, 0x00, 0x09, 0x58, 0x0A, 0x1C, 0x00, 0xE6,
14007: 0x0F, 0x00, 0x00, 0xEA, 0xB9, 0x00, 0x38, 0x54, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFA, 0xB6, 0x00,
14008: 0x18, 0x1C, 0x14, 0x1C, 0x10, 0x1C, 0x32, 0x1C, 0x12, 0x1C, 0x00, 0x16, 0x3E, 0x57, 0x0C, 0x14,
14009: 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, 0xF5, 0x13, 0x00, 0x16, 0x00, 0xF2, 0xA2, 0x0D,
14010: 0x02, 0x4B, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x20, 0x12, 0x44, 0x58,
14011: 0x45, 0x58, 0x9E, 0xE7, 0x15, 0x00, 0x9C, 0xE7, 0x04, 0x00, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2,
14012: 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x7A, 0x0A, 0x1E, 0x1C, 0xD5, 0x10, 0x00, 0x16,
14013: 0x69, 0x08, 0x48, 0xE4, 0x04, 0x00, 0x64, 0x12, 0x48, 0xE4, 0x02, 0x00, 0x20, 0x12, 0x48, 0xE4,
14014: 0x03, 0x00, 0x1A, 0x12, 0x48, 0xE4, 0x08, 0x00, 0x14, 0x12, 0x48, 0xE4, 0x01, 0x00, 0xF0, 0x12,
14015: 0x48, 0xE4, 0x07, 0x00, 0x12, 0x12, 0x01, 0xE6, 0x07, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2,
14016: 0x12, 0x11, 0x05, 0xF0, 0x60, 0x0B, 0x00, 0x16, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x99, 0x00,
14017: 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0xE7, 0x12, 0x48, 0xE4, 0x06, 0x00, 0xE1, 0x12, 0x01, 0xE6,
14018: 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7,
14019: 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4,
14020: 0x10, 0x00, 0x1C, 0x12, 0x82, 0xE7, 0x08, 0x00, 0x3C, 0x56, 0x03, 0x82, 0x00, 0xF2, 0xE2, 0x0D,
14021: 0x30, 0xE7, 0x08, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x80, 0x01,
14022: 0x6C, 0x19, 0xED, 0x19, 0x5D, 0xF0, 0xD4, 0x0B, 0x44, 0x55, 0xE5, 0x55, 0x59, 0xF0, 0x52, 0x0C,
14023: 0x04, 0x55, 0xA5, 0x55, 0x1F, 0x80, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x49, 0x44,
14024: 0x2E, 0x13, 0x01, 0xEC, 0xB8, 0x00, 0x41, 0xE4, 0x02, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x49, 0xE4,
14025: 0x11, 0x00, 0x59, 0xF0, 0x2E, 0x0C, 0x01, 0xE6, 0x17, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x02, 0x4B,
14026: 0x88, 0x90, 0xAC, 0x50, 0x8A, 0x90, 0xAE, 0x50, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80,
14027: 0x10, 0x44, 0x02, 0x4B, 0x1F, 0x40, 0xC0, 0x44, 0x00, 0xF2, 0xB4, 0x0D, 0x04, 0x55, 0xA5, 0x55,
14028: 0x9F, 0x10, 0x0C, 0x51, 0x8E, 0x51, 0x30, 0x90, 0xB2, 0x90, 0x00, 0x56, 0xA1, 0x56, 0x30, 0x50,
14029: 0xB2, 0x50, 0x34, 0x90, 0xB6, 0x90, 0x40, 0x56, 0xE1, 0x56, 0x34, 0x50, 0xB6, 0x50, 0x65, 0x10,
14030: 0xB1, 0xF0, 0x70, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0xE9, 0x09, 0x4B, 0xE4, 0x03, 0x00, 0x78, 0x12,
14031: 0x4B, 0xE4, 0x02, 0x00, 0x01, 0x13, 0xB1, 0xF0, 0x86, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0x69, 0x08,
14032: 0x48, 0xE4, 0x03, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0xCA, 0x0B,
14033: 0xE8, 0x09, 0x3C, 0x56, 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x02, 0x13, 0xBB, 0x45, 0x4B, 0xE4,
14034: 0x00, 0x00, 0x08, 0x12, 0x03, 0xE6, 0x01, 0x00, 0x04, 0xF6, 0x00, 0x80, 0xA8, 0x14, 0xD2, 0x14,
14035: 0x30, 0x1C, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x10, 0x13, 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57,
14036: 0x02, 0x13, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57,
14037: 0x00, 0xFA, 0x24, 0x01, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B,
14038: 0x00, 0xF2, 0x8C, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0xB1, 0xF0, 0xF8, 0x0C, 0x85, 0xF0, 0x86, 0x0B,
14039: 0x69, 0x08, 0x48, 0xE4, 0x01, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0xFC, 0x14, 0x42, 0x58, 0x6C, 0x14,
14040: 0x80, 0x14, 0x30, 0x1C, 0x4A, 0xF4, 0x02, 0x00, 0x55, 0xF0, 0x86, 0x0B, 0x4A, 0xF4, 0x01, 0x00,
14041: 0x0E, 0x12, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x06, 0x13, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B,
14042: 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2,
14043: 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, 0x00, 0xF2, 0xBA, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0x4C, 0x1C,
14044: 0xB1, 0xF0, 0x50, 0x0D, 0x85, 0xF0, 0x5C, 0x0D, 0x69, 0x08, 0xF3, 0x10, 0x86, 0xF0, 0x64, 0x0D,
14045: 0x4E, 0x1C, 0x89, 0x48, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58,
14046: 0x00, 0xDC, 0x18, 0xF4, 0xFF, 0x7F, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01,
14047: 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x30, 0x56, 0x00, 0x5C,
14048: 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x0B, 0x58,
14049: 0x00, 0x16, 0x03, 0xF6, 0x24, 0x01, 0x00, 0xF2, 0x58, 0x0A, 0x03, 0xF6, 0xB6, 0x00, 0x00, 0xF2,
14050: 0x58, 0x0A, 0x00, 0x16, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0x18, 0xF4, 0xFF, 0x00, 0x00, 0x54,
14051: 0x00, 0x54, 0x00, 0x54, 0x00, 0xF4, 0x08, 0x00, 0xE1, 0x18, 0x80, 0x54, 0x03, 0x58, 0x00, 0xDD,
14052: 0x01, 0xDD, 0x02, 0xDD, 0x03, 0xDC, 0x02, 0x4B, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x51, 0xB6, 0x51,
14053: 0x00, 0x16, 0x45, 0x5A, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4,
14054: 0x02, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56,
14055: 0x05, 0xF4, 0x00, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x38, 0x54, 0xBB, 0x55, 0x3C, 0x56, 0xBD, 0x56,
14056: 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x82, 0x0E, 0xE9, 0x09, 0xC1, 0x59, 0x00, 0xF2, 0x12, 0x11,
14057: 0x85, 0xF0, 0x82, 0x0E, 0xE8, 0x0A, 0x83, 0x55, 0x83, 0x55, 0x4B, 0xF4, 0x90, 0x01, 0x5C, 0xF0,
14058: 0x36, 0x0E, 0xBD, 0x56, 0x40, 0x10, 0x4B, 0xF4, 0x30, 0x00, 0x59, 0xF0, 0x48, 0x0E, 0x01, 0xF6,
14059: 0x0C, 0x00, 0x00, 0xF6, 0x01, 0x00, 0x2E, 0x10, 0x02, 0xFC, 0x9C, 0x00, 0x9A, 0x57, 0x14, 0x13,
14060: 0x4B, 0xF4, 0x64, 0x00, 0x59, 0xF0, 0x64, 0x0E, 0x03, 0xF6, 0x64, 0x00, 0x01, 0xF6, 0x19, 0x00,
14061: 0x00, 0xF6, 0x01, 0x00, 0x43, 0xF4, 0x33, 0x00, 0x56, 0xF0, 0x76, 0x0E, 0x04, 0xF4, 0x00, 0x01,
14062: 0x43, 0xF4, 0x19, 0x00, 0xF3, 0x10, 0xB4, 0x56, 0xC3, 0x58, 0x02, 0xFC, 0x9E, 0x00, 0x9A, 0x57,
14063: 0x08, 0x13, 0x3C, 0x56, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x16, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00,
14064: 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x02, 0x00, 0x00, 0xF2, 0x12, 0x11,
14065: 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E,
14066: 0x4E, 0x1C, 0x89, 0x49, 0x00, 0xF2, 0x12, 0x11, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2,
14067: 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0,
14068: 0xF2, 0x0E, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x89, 0x49,
14069: 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x4E, 0x1C, 0x89, 0x4A, 0x00, 0xF2, 0x12, 0x11,
14070: 0x00, 0x16, 0x3C, 0x56, 0x00, 0x16, 0x00, 0xEC, 0x26, 0x01, 0x48, 0xE4, 0x01, 0x00, 0x1E, 0x13,
14071: 0x38, 0x44, 0x00, 0xEA, 0x26, 0x01, 0x49, 0xF4, 0x00, 0x00, 0x04, 0x12, 0x4E, 0x1C, 0x02, 0x10,
14072: 0x4C, 0x1C, 0x01, 0xEC, 0x27, 0x01, 0x89, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x02, 0x14, 0x00, 0x16,
14073: 0x85, 0xF0, 0x52, 0x0F, 0x38, 0x54, 0x00, 0xEA, 0x99, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x02, 0x80,
14074: 0x48, 0xE4, 0x06, 0x00, 0x1C, 0x13, 0x00, 0xEC, 0x99, 0x00, 0x48, 0xE4, 0x01, 0x00, 0x0A, 0x12,
14075: 0x04, 0x80, 0x30, 0xE4, 0x01, 0x00, 0x04, 0x40, 0x08, 0x10, 0x04, 0x80, 0x18, 0xE4, 0xFE, 0x00,
14076: 0x04, 0x40, 0x00, 0x16, 0x02, 0xF6, 0xE0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x81, 0x48,
14077: 0x22, 0x12, 0x00, 0x4E, 0x83, 0x5A, 0x90, 0x4C, 0x20, 0xE7, 0x00, 0x00, 0xC3, 0x58, 0x1B, 0xF4,
14078: 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x8B, 0x55, 0x83, 0x59,
14079: 0x00, 0x4E, 0x00, 0x16, 0x00, 0x4E, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x00, 0x4E,
14080: 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x20, 0xE7, 0x00, 0x00, 0x00, 0x16, 0x02, 0xF6, 0xF0, 0x00,
14081: 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x80, 0x4C,
14082: 0xC3, 0x58, 0x1B, 0xF4, 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12,
14083: 0x83, 0x59, 0x00, 0x4E, 0x00, 0x16, 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x3A, 0x55,
14084: 0x02, 0xCC, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0xC0, 0x5A, 0x40, 0x5C, 0x38, 0x54, 0x00, 0xCD,
14085: 0x01, 0xCC, 0x4A, 0x46, 0x0A, 0x13, 0x83, 0x59, 0x00, 0x4C, 0x01, 0x48, 0x16, 0x13, 0x0C, 0x10,
14086: 0xC5, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0x4C, 0x01, 0x48, 0x08, 0x13, 0x05, 0xF6, 0xF0, 0x00,
14087: 0x05, 0x57, 0x08, 0x10, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x8D, 0x56, 0x83, 0x5A, 0x80, 0x4C,
14088: 0x05, 0x17, 0x00, 0x16, 0x02, 0x4B, 0x06, 0xF7, 0x04, 0x00, 0x62, 0x0B, 0x03, 0x82, 0x00, 0xF2,
14089: 0xE2, 0x0D, 0x02, 0x80, 0x00, 0x4C, 0x45, 0xF4, 0x02, 0x00, 0x52, 0x14, 0x06, 0xF7, 0x02, 0x00,
14090: 0x06, 0x14, 0x00, 0xF2, 0x54, 0x0F, 0x00, 0x16, 0x02, 0x4B, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C,
14091: 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x1D, 0xF7, 0x3C, 0x00, 0xB8, 0xF0,
14092: 0x4E, 0x10, 0x9C, 0x14, 0x01, 0x48, 0x1C, 0x13, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00,
14093: 0xAF, 0x19, 0x03, 0x42, 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x02, 0xCC, 0x02, 0x41, 0x45, 0xF4,
14094: 0x02, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, 0x3E, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x01, 0xF6,
14095: 0xFF, 0x00, 0x38, 0x1C, 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x0E, 0xF7,
14096: 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, 0x0F, 0x79, 0x1C, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x9C, 0x10,
14097: 0x4E, 0x14, 0x01, 0x48, 0x06, 0x13, 0x45, 0xF4, 0x04, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0,
14098: 0x82, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x02, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x2C, 0xBC, 0xAE, 0xBC,
14099: 0xE2, 0x08, 0x00, 0xEC, 0xB8, 0x00, 0x02, 0x48, 0x1D, 0xF7, 0x80, 0x00, 0xB8, 0xF0, 0xCC, 0x10,
14100: 0x1E, 0x14, 0x01, 0x48, 0x0E, 0x13, 0x0E, 0xF7, 0x80, 0x00, 0x38, 0x54, 0x03, 0x58, 0xAF, 0x19,
14101: 0x82, 0x48, 0x00, 0x16, 0x82, 0x48, 0x12, 0x45, 0xD5, 0xF0, 0xBA, 0x10, 0x00, 0xF0, 0x9E, 0x02,
14102: 0x39, 0xF0, 0xF8, 0x10, 0x38, 0x44, 0x00, 0x16, 0x7E, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x04, 0x13,
14103: 0x61, 0x18, 0x00, 0x16, 0x38, 0x1C, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xF1, 0x12,
14104: 0xE3, 0x10, 0x30, 0x44, 0x30, 0x44, 0x30, 0x44, 0xB1, 0xF0, 0x18, 0x11, 0x00, 0x16, 0x3E, 0x57,
14105: 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x6A, 0x12, 0x45, 0x5A,
14106: 0x00, 0xF2, 0xF6, 0x0D, 0x02, 0x4B, 0x70, 0x14, 0x34, 0x13, 0x02, 0x80, 0x48, 0xE4, 0x08, 0x00,
14107: 0x18, 0x12, 0x9C, 0xE7, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2,
14108: 0x7A, 0x0A, 0x1E, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x30, 0xE4, 0x10, 0x00, 0x04, 0x40,
14109: 0x00, 0xF2, 0xE2, 0x0D, 0x20, 0xE7, 0x01, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x04, 0xDC,
14110: 0x01, 0x4A, 0x24, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x43, 0x5B, 0x06, 0xEC, 0x98, 0x00,
14111: 0x00, 0xF2, 0x38, 0x10, 0xC6, 0x59, 0x20, 0x14, 0x0A, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2,
14112: 0x14, 0x10, 0xA7, 0x10, 0x83, 0x5A, 0xD7, 0x10, 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47,
14113: 0x5A, 0xF0, 0x20, 0x11, 0xB9, 0x54, 0x00, 0x16, 0x14, 0x90, 0x96, 0x90, 0x02, 0xFC, 0xA8, 0x00,
14114: 0x03, 0xFC, 0xAA, 0x00, 0x48, 0x55, 0x02, 0x13, 0xC9, 0x55, 0x00, 0x16, 0x00, 0xEC, 0xBA, 0x00,
14115: 0x10, 0x44, 0x00, 0xEA, 0xBA, 0x00, 0x00, 0x16, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A,
14116: 0x10, 0x44, 0x00, 0x4C, 0x00, 0x16
14117: };
14118:
14119: unsigned short _adv_mcode_size ASC_INITDATA =
14120: sizeof(_adv_mcode_buf); /* 0x11D6 */
14121: unsigned long _adv_mcode_chksum ASC_INITDATA = 0x03494981UL;
14122:
14123: /* a_init.c */
14124: /*
14125: * EEPROM Configuration.
14126: *
14127: * All drivers should use this structure to set the default EEPROM
14128: * configuration. The BIOS now uses this structure when it is built.
14129: * Additional structure information can be found in a_condor.h where
14130: * the structure is defined.
14131: */
14132: STATIC ADVEEP_CONFIG
14133: Default_EEPROM_Config ASC_INITDATA = {
14134: ADV_EEPROM_BIOS_ENABLE, /* cfg_msw */
14135: 0x0000, /* cfg_lsw */
14136: 0xFFFF, /* disc_enable */
14137: 0xFFFF, /* wdtr_able */
14138: 0xFFFF, /* sdtr_able */
14139: 0xFFFF, /* start_motor */
14140: 0xFFFF, /* tagqng_able */
14141: 0xFFFF, /* bios_scan */
14142: 0, /* scam_tolerant */
14143: 7, /* adapter_scsi_id */
14144: 0, /* bios_boot_delay */
14145: 3, /* scsi_reset_delay */
14146: 0, /* bios_id_lun */
14147: 0, /* termination */
14148: 0, /* reserved1 */
14149: 0xFFEF, /* bios_ctrl */
14150: 0xFFFF, /* ultra_able */
14151: 0, /* reserved2 */
14152: ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
14153: ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
14154: 0, /* dvc_cntl */
14155: 0, /* bug_fix */
14156: 0, /* serial_number_word1 */
14157: 0, /* serial_number_word2 */
14158: 0, /* serial_number_word3 */
14159: 0, /* check_sum */
14160: { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */
14161: 0, /* dvc_err_code */
14162: 0, /* adv_err_code */
14163: 0, /* adv_err_addr */
14164: 0, /* saved_dvc_err_code */
14165: 0, /* saved_adv_err_code */
14166: 0, /* saved_adv_err_addr */
14167: 0 /* num_of_err */
14168: };
14169:
14170: /*
14171: * Initialize the ADV_DVC_VAR structure.
14172: *
14173: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14174: *
14175: * For a non-fatal error return a warning code. If there are no warnings
14176: * then 0 is returned.
14177: */
14178: ASC_INITFUNC(
14179: int
14180: AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
14181: )
14182: {
14183: ushort warn_code;
14184: AdvPortAddr iop_base;
14185: uchar pci_cmd_reg;
14186: int status;
14187:
14188: warn_code = 0;
14189: asc_dvc->err_code = 0;
14190: iop_base = asc_dvc->iop_base;
14191:
14192: /*
14193: * PCI Command Register
14194: */
14195:
14196: if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
14197: AscPCIConfigCommandRegister))
14198: & AscPCICmdRegBits_BusMastering)
14199: != AscPCICmdRegBits_BusMastering)
14200: {
14201: pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
14202:
14203: DvcAdvWritePCIConfigByte(asc_dvc,
14204: AscPCIConfigCommandRegister, pci_cmd_reg);
14205:
14206: if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister))
14207: & AscPCICmdRegBits_BusMastering)
14208: != AscPCICmdRegBits_BusMastering)
14209: {
14210: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14211: }
14212: }
14213:
14214: /*
14215: * PCI Latency Timer
14216: *
14217: * If the "latency timer" register is 0x20 or above, then we don't need
14218: * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
14219: * comes up less than 0x20).
14220: */
14221: if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
14222: DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20);
14223: if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20)
14224: {
14225: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14226: }
14227: }
14228:
14229: /*
14230: * Save the state of the PCI Configuration Command Register
14231: * "Parity Error Response Control" Bit. If the bit is clear (0),
14232: * in AdvInitAsc3550Driver() tell the microcode to ignore DMA
14233: * parity errors.
14234: */
14235: asc_dvc->cfg->control_flag = 0;
14236: if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
14237: & AscPCICmdRegBits_ParErrRespCtrl)) == 0)
14238: {
14239: asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
14240: }
14241:
14242: asc_dvc->cur_host_qng = 0;
14243:
14244: asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
14245: ADV_LIB_VERSION_MINOR;
14246: asc_dvc->cfg->chip_version =
14247: AdvGetChipVersion(iop_base, asc_dvc->bus_type);
14248:
14249: /*
14250: * Reset the chip to start and allow register writes.
14251: */
14252: if (AdvFindSignature(iop_base) == 0)
14253: {
14254: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
14255: return ADV_ERROR;
14256: }
14257: else {
14258:
14259: AdvResetChip(asc_dvc);
14260:
14261: if ((status = AdvInitFromEEP(asc_dvc)) == ADV_ERROR)
14262: {
14263: return ADV_ERROR;
14264: }
14265: warn_code |= status;
14266:
14267: /*
14268: * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14269: * Resets should be performed.
14270: */
14271: if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
14272: {
14273: AdvResetSCSIBus(asc_dvc);
14274: }
14275: }
14276:
14277: return warn_code;
14278: }
14279:
14280: /*
14281: * Initialize the ASC3550.
14282: *
14283: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14284: *
14285: * For a non-fatal error return a warning code. If there are no warnings
14286: * then 0 is returned.
14287: */
14288: ASC_INITFUNC(
14289: int
14290: AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
14291: )
14292: {
14293: AdvPortAddr iop_base;
14294: ushort warn_code;
14295: ulong sum;
14296: int begin_addr;
14297: int end_addr;
14298: int code_sum;
14299: int word;
14300: int rql_addr; /* RISC Queue List address */
14301: int i;
14302: ushort scsi_cfg1;
14303: uchar biosmem[ASC_MC_BIOSLEN]; /* BIOS RISC Memory 0x40-0x8F. */
14304:
14305: /* If there is already an error, don't continue. */
14306: if (asc_dvc->err_code != 0)
14307: {
14308: return ADV_ERROR;
14309: }
14310:
14311: warn_code = 0;
14312: iop_base = asc_dvc->iop_base;
14313:
14314: /*
14315: * Save the RISC memory BIOS region before writing the microcode.
14316: * The BIOS may already be loaded and using its RISC LRAM region
14317: * so its region must be saved and restored.
14318: *
14319: * Note: This code makes the assumption, which is currently true,
14320: * that a chip reset does not clear RISC LRAM.
14321: */
14322: for (i = 0; i < ASC_MC_BIOSLEN; i++)
14323: {
14324: AdvReadByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
14325: }
14326:
14327: /*
14328: * Load the Microcode
14329: *
14330: * Write the microcode image to RISC memory starting at address 0.
14331: */
14332: AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14333: for (word = 0; word < _adv_mcode_size; word += 2)
14334: {
14335: AdvWriteWordAutoIncLram(iop_base,
14336: *((ushort *) (&_adv_mcode_buf[word])));
14337: }
14338:
14339: /*
14340: * Clear the rest of Condor's Internal RAM (8KB).
14341: */
14342: for (; word < ADV_CONDOR_MEMSIZE; word += 2)
14343: {
14344: AdvWriteWordAutoIncLram(iop_base, 0);
14345: }
14346:
14347: /*
14348: * Verify the microcode checksum.
14349: */
14350: sum = 0;
14351: AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14352: for (word = 0; word < _adv_mcode_size; word += 2)
14353: {
14354: sum += AdvReadWordAutoIncLram(iop_base);
14355: }
14356:
14357: if (sum != _adv_mcode_chksum)
14358: {
14359: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14360: return ADV_ERROR;
14361: }
14362:
14363: /*
14364: * Restore the RISC memory BIOS region.
14365: */
14366: for (i = 0; i < ASC_MC_BIOSLEN; i++)
14367: {
14368: AdvWriteByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
14369: }
14370:
14371: /*
14372: * Calculate and write the microcode code checksum to the microcode
14373: * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14374: */
14375: AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14376: AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14377: code_sum = 0;
14378: for (word = begin_addr; word < end_addr; word += 2)
14379: {
14380: code_sum += *((ushort *) (&_adv_mcode_buf[word]));
14381: }
14382: AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
14383:
14384: /*
14385: * Read microcode version and date.
14386: */
14387: AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date);
14388: AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version);
14389:
14390: /*
14391: * Initialize microcode operating variables
14392: */
14393: AdvWriteWordLram(iop_base, ASC_MC_ADAPTER_SCSI_ID,
14394: asc_dvc->chip_scsi_id);
14395:
14396: /*
14397: * If the PCI Configuration Command Register "Parity Error Response
14398: * Control" Bit was clear (0), then set the microcode variable
14399: * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14400: * to ignore DMA parity errors.
14401: */
14402: if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR)
14403: {
14404: /*
14405: * Note: Don't remove the use of a temporary variable in
14406: * the following code, otherwise the Microsoft C compiler
14407: * will turn the following lines into a no-op.
14408: */
14409: AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14410: word |= CONTROL_FLAG_IGNORE_PERR;
14411: AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14412: }
14413:
14414: /*
14415: * Set default microcode operating variables for WDTR, SDTR, and
14416: * command tag queuing based on the EEPROM configuration values.
14417: *
14418: * These ADV_DVC_VAR fields and the microcode variables will be
14419: * changed in AdvInquiryHandling() if it is found a device is
14420: * incapable of a particular feature.
14421: */
14422:
14423: /*
14424: * Set the microcode ULTRA target mask from EEPROM value. The
14425: * SDTR target mask overrides the ULTRA target mask in the
14426: * microcode so it is safe to set this value without determining
14427: * whether the device supports SDTR.
14428: *
14429: * Note: There is no way to know whether a device supports ULTRA
14430: * speed without attempting a SDTR ULTRA speed negotiation with
14431: * the device. The device will reject the speed if it does not
14432: * support it by responding with an SDTR message containing a
14433: * slower speed.
14434: */
14435: AdvWriteWordLram(iop_base, ASC_MC_ULTRA_ABLE, asc_dvc->ultra_able);
14436: AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable);
14437:
14438:
14439: /*
14440: * Set SCSI_CFG0 Microcode Default Value.
14441: *
14442: * The microcode will set the SCSI_CFG0 register using this value
14443: * after it is started below.
14444: */
14445: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14446: PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id);
14447:
14448: /*
14449: * Determine SCSI_CFG1 Microcode Default Value.
14450: *
14451: * The microcode will set the SCSI_CFG1 register using this value
14452: * after it is started below.
14453: */
14454:
14455: /* Read current SCSI_CFG1 Register value. */
14456: scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14457:
14458: /*
14459: * If all three connectors are in use, return an error.
14460: */
14461: if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
14462: (scsi_cfg1 & CABLE_ILLEGAL_B) == 0)
14463: {
14464: asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
14465: return ADV_ERROR;
14466: }
14467:
14468: /*
14469: * If the internal narrow cable is reversed all of the SCSI_CTRL
14470: * register signals will be set. Check for and return an error if
14471: * this condition is found.
14472: */
14473: if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07)
14474: {
14475: asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14476: return ADV_ERROR;
14477: }
14478:
14479: /*
14480: * If this is a differential board and a single-ended device
14481: * is attached to one of the connectors, return an error.
14482: */
14483: if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0)
14484: {
14485: asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
14486: return ADV_ERROR;
14487: }
14488:
14489: /*
14490: * If automatic termination control is enabled, then set the
14491: * termination value based on a table listed in a_condor.h.
14492: *
14493: * If manual termination was specified with an EEPROM setting
14494: * then 'termination' was set-up in AdvInitFromEEP() and
14495: * is ready to be 'ored' into SCSI_CFG1.
14496: */
14497: if (asc_dvc->cfg->termination == 0)
14498: {
14499: /*
14500: * The software always controls termination by setting TERM_CTL_SEL.
14501: * If TERM_CTL_SEL were set to 0, the hardware would set termination.
14502: */
14503: asc_dvc->cfg->termination |= TERM_CTL_SEL;
14504:
14505: switch(scsi_cfg1 & CABLE_DETECT)
14506: {
14507: /* TERM_CTL_H: on, TERM_CTL_L: on */
14508: case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF:
14509: asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
14510: break;
14511:
14512: /* TERM_CTL_H: on, TERM_CTL_L: off */
14513: case 0x1: case 0x5: case 0x9: case 0xA: case 0xC:
14514: asc_dvc->cfg->termination |= TERM_CTL_H;
14515: break;
14516:
14517: /* TERM_CTL_H: off, TERM_CTL_L: off */
14518: case 0x2: case 0x6:
14519: break;
14520: }
14521: }
14522:
14523: /*
14524: * Clear any set TERM_CTL_H and TERM_CTL_L bits.
14525: */
14526: scsi_cfg1 &= ~TERM_CTL;
14527:
14528: /*
14529: * Invert the TERM_CTL_H and TERM_CTL_L bits and then
14530: * set 'scsi_cfg1'. The TERM_POL bit does not need to be
14531: * referenced, because the hardware internally inverts
14532: * the Termination High and Low bits if TERM_POL is set.
14533: */
14534: scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
14535:
14536: /*
14537: * Set SCSI_CFG1 Microcode Default Value
14538: *
14539: * Set filter value and possibly modified termination control
14540: * bits in the Microcode SCSI_CFG1 Register Value.
14541: *
14542: * The microcode will set the SCSI_CFG1 register using this value
14543: * after it is started below.
14544: */
14545: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
14546: FLTR_11_TO_20NS | scsi_cfg1);
14547:
14548: /*
14549: * Set SEL_MASK Microcode Default Value
14550: *
14551: * The microcode will set the SEL_MASK register using this value
14552: * after it is started below.
14553: */
14554: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14555: ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
14556:
14557: /*
14558: * Link all the RISC Queue Lists together in a doubly-linked
14559: * NULL terminated list.
14560: *
14561: * Skip the NULL (0) queue which is not used.
14562: */
14563: for (i = 1, rql_addr = ASC_MC_RISC_Q_LIST_BASE + ASC_MC_RISC_Q_LIST_SIZE;
14564: i < ASC_MC_RISC_Q_TOTAL_CNT;
14565: i++, rql_addr += ASC_MC_RISC_Q_LIST_SIZE)
14566: {
14567: /*
14568: * Set the current RISC Queue List's RQL_FWD and RQL_BWD pointers
14569: * in a one word write and set the state (RQL_STATE) to free.
14570: */
14571: AdvWriteWordLram(iop_base, rql_addr, ((i + 1) + ((i - 1) << 8)));
14572: AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
14573: }
14574:
14575: /*
14576: * Set the Host and RISC Queue List pointers.
14577: *
14578: * Both sets of pointers are initialized with the same values:
14579: * ASC_MC_RISC_Q_FIRST(0x01) and ASC_MC_RISC_Q_LAST (0xFF).
14580: */
14581: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, ASC_MC_RISC_Q_FIRST);
14582: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, ASC_MC_RISC_Q_LAST);
14583:
14584: AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_READY, ASC_MC_RISC_Q_FIRST);
14585: AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_DONE, ASC_MC_RISC_Q_LAST);
14586:
14587: /*
14588: * Finally, set up the last RISC Queue List (255) with
14589: * a NULL forward pointer.
14590: */
14591: AdvWriteWordLram(iop_base, rql_addr, (ASC_MC_NULL_Q + ((i - 1) << 8)));
14592: AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
14593:
14594: AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14595: (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR));
14596:
14597: /*
14598: * Note: Don't remove the use of a temporary variable in
14599: * the following code, otherwise the Microsoft C compiler
14600: * will turn the following lines into a no-op.
14601: */
14602: AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14603: AdvWriteWordRegister(iop_base, IOPW_PC, word);
14604:
14605: /* finally, finally, gentlemen, start your engine */
14606: AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
14607:
14608: return warn_code;
14609: }
14610:
14611: /*
14612: * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
14613: * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
14614: * all of this is done.
14615: *
14616: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14617: *
14618: * For a non-fatal error return a warning code. If there are no warnings
14619: * then 0 is returned.
14620: *
14621: * Note: Chip is stopped on entry.
14622: */
14623: ASC_INITFUNC(
14624: STATIC int
14625: AdvInitFromEEP(ADV_DVC_VAR *asc_dvc)
14626: )
14627: {
14628: AdvPortAddr iop_base;
14629: ushort warn_code;
14630: ADVEEP_CONFIG eep_config;
14631: int i;
14632:
14633: iop_base = asc_dvc->iop_base;
14634:
14635: warn_code = 0;
14636:
14637: /*
14638: * Read the board's EEPROM configuration.
14639: *
14640: * Set default values if a bad checksum is found.
14641: */
14642: if (AdvGetEEPConfig(iop_base, &eep_config) != eep_config.check_sum)
14643: {
14644: warn_code |= ASC_WARN_EEPROM_CHKSUM;
14645:
14646: /*
14647: * Set EEPROM default values.
14648: */
14649: for (i = 0; i < sizeof(ADVEEP_CONFIG); i++)
14650: {
14651: *((uchar *) &eep_config + i) =
14652: *((uchar *) &Default_EEPROM_Config + i);
14653: }
14654:
14655: /*
14656: * Assume the 6 byte board serial number that was read
14657: * from EEPROM is correct even if the EEPROM checksum
14658: * failed.
14659: */
14660: eep_config.serial_number_word3 =
14661: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1);
14662: eep_config.serial_number_word2 =
14663: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2);
14664: eep_config.serial_number_word1 =
14665: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3);
14666: AdvSetEEPConfig(iop_base, &eep_config);
14667: }
14668:
14669: /*
14670: * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
14671: * EEPROM configuration that was read.
14672: *
14673: * This is the mapping of EEPROM fields to Adv Library fields.
14674: */
14675: asc_dvc->wdtr_able = eep_config.wdtr_able;
14676: asc_dvc->sdtr_able = eep_config.sdtr_able;
14677: asc_dvc->ultra_able = eep_config.ultra_able;
14678: asc_dvc->tagqng_able = eep_config.tagqng_able;
14679: asc_dvc->cfg->disc_enable = eep_config.disc_enable;
14680: asc_dvc->max_host_qng = eep_config.max_host_qng;
14681: asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
14682: asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
14683: asc_dvc->start_motor = eep_config.start_motor;
14684: asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
14685: asc_dvc->cfg->bios_boot_wait = eep_config.bios_boot_delay;
14686: asc_dvc->bios_ctrl = eep_config.bios_ctrl;
14687: asc_dvc->no_scam = eep_config.scam_tolerant;
14688: asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
14689: asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
14690: asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
14691:
14692: /*
14693: * Set the host maximum queuing (max. 253, min. 16) and the per device
14694: * maximum queuing (max. 63, min. 4).
14695: */
14696: if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG)
14697: {
14698: eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
14699: } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG)
14700: {
14701: /* If the value is zero, assume it is uninitialized. */
14702: if (eep_config.max_host_qng == 0)
14703: {
14704: eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
14705: } else
14706: {
14707: eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
14708: }
14709: }
14710:
14711: if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG)
14712: {
14713: eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
14714: } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG)
14715: {
14716: /* If the value is zero, assume it is uninitialized. */
14717: if (eep_config.max_dvc_qng == 0)
14718: {
14719: eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
14720: } else
14721: {
14722: eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
14723: }
14724: }
14725:
14726: /*
14727: * If 'max_dvc_qng' is greater than 'max_host_qng', then
14728: * set 'max_dvc_qng' to 'max_host_qng'.
14729: */
14730: if (eep_config.max_dvc_qng > eep_config.max_host_qng)
14731: {
14732: eep_config.max_dvc_qng = eep_config.max_host_qng;
14733: }
14734:
14735: /*
14736: * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_CFG 'max_dvc_qng'
14737: * values based on possibly adjusted EEPROM values.
14738: */
14739: asc_dvc->max_host_qng = eep_config.max_host_qng;
14740: asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
14741:
14742:
14743: /*
14744: * If the EEPROM 'termination' field is set to automatic (0), then set
14745: * the ADV_DVC_CFG 'termination' field to automatic also.
14746: *
14747: * If the termination is specified with a non-zero 'termination'
14748: * value check that a legal value is set and set the ADV_DVC_CFG
14749: * 'termination' field appropriately.
14750: */
14751: if (eep_config.termination == 0)
14752: {
14753: asc_dvc->cfg->termination = 0; /* auto termination */
14754: } else
14755: {
14756: /* Enable manual control with low off / high off. */
14757: if (eep_config.termination == 1)
14758: {
14759: asc_dvc->cfg->termination = TERM_CTL_SEL;
14760:
14761: /* Enable manual control with low off / high on. */
14762: } else if (eep_config.termination == 2)
14763: {
14764: asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
14765:
14766: /* Enable manual control with low on / high on. */
14767: } else if (eep_config.termination == 3)
14768: {
14769: asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
14770: } else
14771: {
14772: /*
14773: * The EEPROM 'termination' field contains a bad value. Use
14774: * automatic termination instead.
14775: */
14776: asc_dvc->cfg->termination = 0;
14777: warn_code |= ASC_WARN_EEPROM_TERMINATION;
14778: }
14779: }
14780:
14781: return warn_code;
14782: }
14783:
14784: /*
14785: * Read EEPROM configuration into the specified buffer.
14786: *
14787: * Return a checksum based on the EEPROM configuration read.
14788: */
14789: ASC_INITFUNC(
14790: STATIC ushort
14791: AdvGetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
14792: )
14793: {
14794: ushort wval, chksum;
14795: ushort *wbuf;
14796: int eep_addr;
14797:
14798: wbuf = (ushort *) cfg_buf;
14799: chksum = 0;
14800:
14801: for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
14802: eep_addr < ASC_EEP_DVC_CFG_END;
14803: eep_addr++, wbuf++)
14804: {
14805: wval = AdvReadEEPWord(iop_base, eep_addr);
14806: chksum += wval;
14807: *wbuf = wval;
14808: }
14809: *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14810: wbuf++;
14811: for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
14812: eep_addr < ASC_EEP_MAX_WORD_ADDR;
14813: eep_addr++, wbuf++)
14814: {
14815: *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14816: }
14817: return chksum;
14818: }
14819:
14820: /*
14821: * Read the EEPROM from specified location
14822: */
14823: ASC_INITFUNC(
14824: STATIC ushort
14825: AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
14826: )
14827: {
14828: AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14829: ASC_EEP_CMD_READ | eep_word_addr);
14830: AdvWaitEEPCmd(iop_base);
14831: return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
14832: }
14833:
14834: /*
14835: * Wait for EEPROM command to complete
14836: */
14837: ASC_INITFUNC(
14838: STATIC void
14839: AdvWaitEEPCmd(AdvPortAddr iop_base)
14840: )
14841: {
14842: int eep_delay_ms;
14843:
14844: for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++)
14845: {
14846: if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE)
14847: {
14848: break;
14849: }
14850: DvcSleepMilliSecond(1);
14851: }
14852: if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0)
14853: {
14854: ADV_ASSERT(0);
14855: }
14856: return;
14857: }
14858:
14859: /*
14860: * Write the EEPROM from 'cfg_buf'.
14861: */
14862: ASC_INITFUNC(
14863: STATIC void
14864: AdvSetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
14865: )
14866: {
14867: ushort *wbuf;
14868: ushort addr, chksum;
14869:
14870: wbuf = (ushort *) cfg_buf;
14871: chksum = 0;
14872:
14873: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
14874: AdvWaitEEPCmd(iop_base);
14875:
14876: /*
14877: * Write EEPROM from word 0 to word 15
14878: */
14879: for (addr = ASC_EEP_DVC_CFG_BEGIN;
14880: addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++)
14881: {
14882: chksum += *wbuf;
14883: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
14884: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14885: AdvWaitEEPCmd(iop_base);
14886: DvcSleepMilliSecond(ASC_EEP_DELAY_MS);
14887: }
14888:
14889: /*
14890: * Write EEPROM checksum at word 18
14891: */
14892: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
14893: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14894: AdvWaitEEPCmd(iop_base);
14895: wbuf++; /* skip over check_sum */
14896:
14897: /*
14898: * Write EEPROM OEM name at words 19 to 26
14899: */
14900: for (addr = ASC_EEP_DVC_CTL_BEGIN;
14901: addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++)
14902: {
14903: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
14904: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14905: AdvWaitEEPCmd(iop_base);
14906: }
14907: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
14908: AdvWaitEEPCmd(iop_base);
14909: return;
14910: }
14911:
14912: /*
14913: * This function resets the chip and SCSI bus
14914: *
14915: * It is up to the caller to add a delay to let the bus settle after
14916: * calling this function.
14917: *
14918: * The SCSI_CFG0, SCSI_CFG1, and MEM_CFG registers are set-up in
14919: * AdvInitAsc3550Driver(). Here when doing a write to one of these
14920: * registers read first and then write.
14921: *
14922: * Note: A SCSI Bus Reset can not be done until after the EEPROM
14923: * configuration is read to determine whether SCSI Bus Resets
14924: * should be performed.
14925: */
14926: ASC_INITFUNC(
14927: STATIC void
14928: AdvResetChip(ADV_DVC_VAR *asc_dvc)
14929: )
14930: {
14931: AdvPortAddr iop_base;
14932: ushort word;
14933: uchar byte;
14934:
14935: iop_base = asc_dvc->iop_base;
14936:
14937: /*
14938: * Reset Chip.
14939: */
14940: AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14941: DvcSleepMilliSecond(100);
14942: AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG);
14943:
14944: /*
14945: * Initialize Chip registers.
14946: *
14947: * Note: Don't remove the use of a temporary variable in the following
14948: * code, otherwise the Microsoft C compiler will turn the following lines
14949: * into a no-op.
14950: */
14951: byte = AdvReadByteRegister(iop_base, IOPB_MEM_CFG);
14952: byte |= RAM_SZ_8KB;
14953: AdvWriteByteRegister(iop_base, IOPB_MEM_CFG, byte);
14954:
14955: word = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14956: word &= ~BIG_ENDIAN;
14957: AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, word);
14958:
14959: /*
14960: * Setting the START_CTL_EMFU 3:2 bits sets a FIFO threshold
14961: * of 128 bytes. This register is only accessible to the host.
14962: */
14963: AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14964: START_CTL_EMFU | READ_CMD_MRM);
14965: }
14966:
14967: /* a_advlib.c */
14968: /*
14969: * Description:
14970: * Send a SCSI request to the ASC3550 chip
14971: *
14972: * If there is no SG list for the request, set 'sg_entry_cnt' to 0.
14973: *
14974: * If 'sg_real_addr' is non-zero on entry, AscGetSGList() will not be
14975: * called. It is assumed the caller has already initialized 'sg_real_addr'.
14976: *
14977: * Return:
14978: * ADV_SUCCESS(1) - the request is in the mailbox
14979: * ADV_BUSY(0) - total request count > 253, try later
14980: * ADV_ERROR(-1) - invalid scsi request Q
14981: */
14982: STATIC int
14983: AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc,
14984: ADV_SCSI_REQ_Q *scsiq)
14985: {
14986: if (scsiq == (ADV_SCSI_REQ_Q *) 0L)
14987: {
14988: /* 'scsiq' should never be NULL. */
14989: ADV_ASSERT(0);
14990: return ADV_ERROR;
14991: }
14992:
14993: return AdvSendScsiCmd(asc_dvc, scsiq);
14994: }
14995:
14996: /*
14997: * Reset SCSI Bus and purge all outstanding requests.
14998: *
14999: * Return Value:
15000: * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
15001: *
15002: * Note: Should always return ADV_TRUE.
15003: */
15004: STATIC int
15005: AdvResetSB(ADV_DVC_VAR *asc_dvc)
15006: {
15007: int status;
15008:
15009: status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET, 0L, 0);
15010:
15011: AdvResetSCSIBus(asc_dvc);
15012:
15013: return status;
15014: }
15015:
15016: /*
15017: * Reset SCSI Bus and delay.
15018: */
15019: STATIC void
15020: AdvResetSCSIBus(ADV_DVC_VAR *asc_dvc)
15021: {
15022: AdvPortAddr iop_base;
15023: ushort scsi_ctrl;
15024:
15025: iop_base = asc_dvc->iop_base;
15026:
15027: /*
15028: * The microcode currently sets the SCSI Bus Reset signal while
15029: * handling the AscSendIdleCmd() IDLE_CMD_SCSI_RESET command above.
15030: * But the SCSI Bus Reset Hold Time in the microcode is not deterministic
15031: * (it may in fact be for less than the SCSI Spec. minimum of 25 us).
15032: * Therefore on return the Adv Library sets the SCSI Bus Reset signal
15033: * for ASC_SCSI_RESET_HOLD_TIME_US, which is defined to be greater
15034: * than 25 us.
15035: */
15036: scsi_ctrl = AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL);
15037: AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
15038: scsi_ctrl | ADV_SCSI_CTRL_RSTOUT);
15039: DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US);
15040: AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
15041: scsi_ctrl & ~ADV_SCSI_CTRL_RSTOUT);
15042:
15043: DvcSleepMilliSecond((ulong) asc_dvc->scsi_reset_wait * 1000);
15044: }
15045:
15046:
15047: /*
15048: * Adv Library Interrupt Service Routine
15049: *
15050: * This function is called by a driver's interrupt service routine.
15051: * The function disables and re-enables interrupts.
15052: *
15053: * When a microcode idle command is completed, the ADV_DVC_VAR
15054: * 'idle_cmd_done' field is set to ADV_TRUE.
15055: *
15056: * Note: AdvISR() can be called when interrupts are disabled or even
15057: * when there is no hardware interrupt condition present. It will
15058: * always check for completed idle commands and microcode requests.
15059: * This is an important feature that shouldn't be changed because it
15060: * allows commands to be completed from polling mode loops.
15061: *
15062: * Return:
15063: * ADV_TRUE(1) - interrupt was pending
15064: * ADV_FALSE(0) - no interrupt was pending
15065: */
15066: STATIC int
15067: AdvISR(ADV_DVC_VAR *asc_dvc)
15068: {
15069: AdvPortAddr iop_base;
15070: uchar int_stat;
15071: ushort next_done_loc, target_bit;
15072: int completed_q;
15073: int flags;
15074: ADV_SCSI_REQ_Q *scsiq;
15075: ASC_REQ_SENSE *sense_data;
15076: int ret;
15077:
15078: flags = DvcEnterCritical();
15079: iop_base = asc_dvc->iop_base;
15080:
15081: if (AdvIsIntPending(iop_base))
15082: {
15083: ret = ADV_TRUE;
15084: } else
15085: {
15086: ret = ADV_FALSE;
15087: }
15088:
15089: /* Reading the register clears the interrupt. */
15090: int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
15091:
15092: if (int_stat & ADV_INTR_STATUS_INTRB)
15093: {
15094: asc_dvc->idle_cmd_done = ADV_TRUE;
15095: }
15096:
15097: /*
15098: * Notify the driver of a hardware detected SCSI Bus Reset.
15099: */
15100: if (int_stat & ADV_INTR_STATUS_INTRC)
15101: {
15102: if (asc_dvc->sbreset_callback != 0)
15103: {
15104: (*(ADV_SBRESET_CALLBACK) asc_dvc->sbreset_callback)(asc_dvc);
15105: }
15106: }
15107:
15108: /*
15109: * ASC_MC_HOST_NEXT_DONE (0x129) is actually the last completed RISC
15110: * Queue List request. Its forward pointer (RQL_FWD) points to the
15111: * current completed RISC Queue List request.
15112: */
15113: AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, next_done_loc);
15114: next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
15115: (next_done_loc * ASC_MC_RISC_Q_LIST_SIZE) + RQL_FWD;
15116:
15117: AdvReadByteLram(iop_base, next_done_loc, completed_q);
15118:
15119: /* Loop until all completed Q's are processed. */
15120: while (completed_q != ASC_MC_NULL_Q)
15121: {
15122: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, completed_q);
15123:
15124: next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
15125: (completed_q * ASC_MC_RISC_Q_LIST_SIZE);
15126:
15127: /*
15128: * Read the ADV_SCSI_REQ_Q virtual address pointer from
15129: * the RISC list entry. The microcode has changed the
15130: * ADV_SCSI_REQ_Q physical address to its virtual address.
15131: *
15132: * Refer to comments at the end of AdvSendScsiCmd() for
15133: * more information on the RISC list structure.
15134: */
15135: {
15136: ushort lsw, msw;
15137: AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR, lsw);
15138: AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR + 2, msw);
15139:
15140: scsiq = (ADV_SCSI_REQ_Q *) (((ulong) msw << 16) | lsw);
15141: }
15142: ADV_ASSERT(scsiq != NULL);
15143:
15144: target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
15145:
15146: /*
15147: * Clear request microcode control flag.
15148: */
15149: scsiq->cntl = 0;
15150:
15151: /*
15152: * Check Condition handling
15153: */
15154: if ((scsiq->done_status == QD_WITH_ERROR) &&
15155: (scsiq->scsi_status == SS_CHK_CONDITION) &&
15156: (sense_data = (ASC_REQ_SENSE *) scsiq->vsense_addr) != 0 &&
15157: (scsiq->orig_sense_len - scsiq->sense_len) >= ASC_MIN_SENSE_LEN)
15158: {
15159: /*
15160: * Command returned with a check condition and valid
15161: * sense data.
15162: */
15163: }
15164: /*
15165: * If the command that completed was a SCSI INQUIRY and
15166: * LUN 0 was sent the command, then process the INQUIRY
15167: * command information for the device.
15168: */
15169: else if (scsiq->done_status == QD_NO_ERROR &&
15170: scsiq->cdb[0] == SCSICMD_Inquiry &&
15171: scsiq->target_lun == 0)
15172: {
15173: AdvInquiryHandling(asc_dvc, scsiq);
15174: }
15175:
15176:
15177: /* Change the RISC Queue List state to free. */
15178: AdvWriteByteLram(iop_base, next_done_loc + RQL_STATE, ASC_MC_QS_FREE);
15179:
15180: /* Get the RISC Queue List forward pointer. */
15181: AdvReadByteLram(iop_base, next_done_loc + RQL_FWD, completed_q);
15182:
15183: /*
15184: * Notify the driver of the completed request by passing
15185: * the ADV_SCSI_REQ_Q pointer to its callback function.
15186: */
15187: ADV_ASSERT(asc_dvc->cur_host_qng > 0);
15188: asc_dvc->cur_host_qng--;
15189: scsiq->a_flag |= ADV_SCSIQ_DONE;
15190: (*(ADV_ISR_CALLBACK) asc_dvc->isr_callback)(asc_dvc, scsiq);
15191: /*
15192: * Note: After the driver callback function is called, 'scsiq'
15193: * can no longer be referenced.
15194: *
15195: * Fall through and continue processing other completed
15196: * requests...
15197: */
15198:
15199: /*
15200: * Disable interrupts again in case the driver inadvertently
15201: * enabled interrupts in its callback function.
15202: *
15203: * The DvcEnterCritical() return value is ignored, because
15204: * the 'flags' saved when AdvISR() was first entered will be
15205: * used to restore the interrupt flag on exit.
15206: */
15207: (void) DvcEnterCritical();
15208: }
15209: DvcLeaveCritical(flags);
15210: return ret;
15211: }
15212:
15213: /*
15214: * Send an idle command to the chip and wait for completion.
15215: *
15216: * Interrupts do not have to be enabled on entry.
15217: *
15218: * Return Values:
15219: * ADV_TRUE - command completed successfully
15220: * ADV_FALSE - command failed
15221: */
15222: STATIC int
15223: AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
15224: ushort idle_cmd,
15225: ulong idle_cmd_parameter,
15226: int flags)
15227: {
15228: int last_int_level;
15229: ulong i;
15230: AdvPortAddr iop_base;
15231: int ret;
15232:
15233: asc_dvc->idle_cmd_done = 0;
15234:
15235: last_int_level = DvcEnterCritical();
15236: iop_base = asc_dvc->iop_base;
15237:
15238: /*
15239: * Write the idle command value after the idle command parameter
15240: * has been written to avoid a race condition. If the order is not
15241: * followed, the microcode may process the idle command before the
15242: * parameters have been written to LRAM.
15243: */
15244: AdvWriteDWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, idle_cmd_parameter);
15245: AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
15246: DvcLeaveCritical(last_int_level);
15247:
15248: /*
15249: * If the 'flags' argument contains the ADV_NOWAIT flag, then
15250: * return with success.
15251: */
15252: if (flags & ADV_NOWAIT)
15253: {
15254: return ADV_TRUE;
15255: }
15256:
15257: for (i = 0; i < SCSI_WAIT_10_SEC * SCSI_MS_PER_SEC; i++)
15258: {
15259: /*
15260: * 'idle_cmd_done' is set by AdvISR().
15261: */
15262: if (asc_dvc->idle_cmd_done)
15263: {
15264: break;
15265: }
15266: DvcSleepMilliSecond(1);
15267:
15268: /*
15269: * If interrupts were disabled on entry to AdvSendIdleCmd(),
15270: * then they will still be disabled here. Call AdvISR() to
15271: * check for the idle command completion.
15272: */
15273: (void) AdvISR(asc_dvc);
15274: }
15275:
15276: last_int_level = DvcEnterCritical();
15277:
15278: if (asc_dvc->idle_cmd_done == ADV_FALSE)
15279: {
15280: ADV_ASSERT(0); /* The idle command should never timeout. */
15281: return ADV_FALSE;
15282: } else
15283: {
15284: AdvReadWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, ret);
15285: return ret;
15286: }
15287: }
15288:
15289: /*
15290: * Send the SCSI request block to the adapter
15291: *
15292: * Each of the 255 Adv Library/Microcode RISC Lists or mailboxes has the
15293: * following structure:
15294: *
15295: * 0: RQL_FWD - RISC list forward pointer (1 byte)
15296: * 1: RQL_BWD - RISC list backward pointer (1 byte)
15297: * 2: RQL_STATE - RISC list state byte - free, ready, done, aborted (1 byte)
15298: * 3: RQL_TID - request target id (1 byte)
15299: * 4: RQL_PHYADDR - ADV_SCSI_REQ_Q physical pointer (4 bytes)
15300: *
15301: * Return:
15302: * ADV_SUCCESS(1) - the request is in the mailbox
15303: * ADV_BUSY(0) - total request count > 253, try later
15304: */
15305: STATIC int
15306: AdvSendScsiCmd(
15307: ADV_DVC_VAR *asc_dvc,
15308: ADV_SCSI_REQ_Q *scsiq)
15309: {
15310: ushort next_ready_loc;
15311: uchar next_ready_loc_fwd;
15312: int last_int_level;
15313: AdvPortAddr iop_base;
15314: long req_size;
15315: ulong q_phy_addr;
15316:
15317: /*
15318: * The ADV_SCSI_REQ_Q 'target_id' field should never be equal
15319: * to the host adapter ID or exceed ADV_MAX_TID.
15320: */
15321: if (scsiq->target_id == asc_dvc->chip_scsi_id ||
15322: scsiq->target_id > ADV_MAX_TID)
15323: {
15324: scsiq->host_status = QHSTA_M_INVALID_DEVICE;
15325: scsiq->done_status = QD_WITH_ERROR;
15326: return ADV_ERROR;
15327: }
15328:
15329: iop_base = asc_dvc->iop_base;
15330:
15331: last_int_level = DvcEnterCritical();
15332:
15333: if (asc_dvc->cur_host_qng >= asc_dvc->max_host_qng)
15334: {
15335: DvcLeaveCritical(last_int_level);
15336: return ADV_BUSY;
15337: } else
15338: {
15339: ADV_ASSERT(asc_dvc->cur_host_qng < ASC_MC_RISC_Q_TOTAL_CNT);
15340: asc_dvc->cur_host_qng++;
15341: }
15342:
15343: /*
15344: * Clear the ADV_SCSI_REQ_Q done flag.
15345: */
15346: scsiq->a_flag &= ~ADV_SCSIQ_DONE;
15347:
15348: /*
15349: * Save the original sense buffer length.
15350: *
15351: * After the request completes 'sense_len' will be set to the residual
15352: * byte count of the Auto-Request Sense if a command returns CHECK
15353: * CONDITION and the Sense Data is valid indicated by 'host_status' not
15354: * being set to QHSTA_M_AUTO_REQ_SENSE_FAIL. To determine the valid
15355: * Sense Data Length subtract 'sense_len' from 'orig_sense_len'.
15356: */
15357: scsiq->orig_sense_len = scsiq->sense_len;
15358:
15359: AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc);
15360: next_ready_loc = ASC_MC_RISC_Q_LIST_BASE +
15361: (next_ready_loc * ASC_MC_RISC_Q_LIST_SIZE);
15362:
15363: /*
15364: * Write the physical address of the Q to the mailbox.
15365: * We need to skip the first four bytes, because the microcode
15366: * uses them internally for linking Q's together.
15367: */
15368: req_size = sizeof(ADV_SCSI_REQ_Q);
15369: q_phy_addr = DvcGetPhyAddr(asc_dvc, scsiq,
15370: (uchar *) scsiq, &req_size,
15371: ADV_IS_SCSIQ_FLAG);
15372: ADV_ASSERT(ADV_DWALIGN(q_phy_addr) == q_phy_addr);
15373: ADV_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
15374:
15375: scsiq->scsiq_ptr = (ADV_SCSI_REQ_Q *) scsiq;
15376:
15377: /*
15378: * The RISC list structure, which 'next_ready_loc' is a pointer
15379: * to in microcode LRAM, has the format detailed in the comment
15380: * header for this function.
15381: *
15382: * Write the ADV_SCSI_REQ_Q physical pointer to 'next_ready_loc' request.
15383: */
15384: AdvWriteDWordLram(iop_base, next_ready_loc + RQL_PHYADDR, q_phy_addr);
15385:
15386: /* Write target_id to 'next_ready_loc' request. */
15387: AdvWriteByteLram(iop_base, next_ready_loc + RQL_TID, scsiq->target_id);
15388:
15389: /*
15390: * Set the ASC_MC_HOST_NEXT_READY (0x128) microcode variable to
15391: * the 'next_ready_loc' request forward pointer.
15392: *
15393: * Do this *before* changing the 'next_ready_loc' queue to QS_READY.
15394: * After the state is changed to QS_READY 'RQL_FWD' will be changed
15395: * by the microcode.
15396: *
15397: * NOTE: The temporary variable 'next_ready_loc_fwd' is required to
15398: * prevent some compilers from optimizing out 'AdvReadByteLram()' if
15399: * it were used as the 3rd argument to 'AdvWriteByteLram()'.
15400: */
15401: AdvReadByteLram(iop_base, next_ready_loc + RQL_FWD, next_ready_loc_fwd);
15402: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc_fwd);
15403:
15404: /*
15405: * Change the state of 'next_ready_loc' request from QS_FREE to
15406: * QS_READY which will cause the microcode to pick it up and
15407: * execute it.
15408: *
15409: * Can't reference 'next_ready_loc' after changing the request
15410: * state to QS_READY. The microcode now owns the request.
15411: */
15412: AdvWriteByteLram(iop_base, next_ready_loc + RQL_STATE, ASC_MC_QS_READY);
15413:
15414: DvcLeaveCritical(last_int_level);
15415: return ADV_SUCCESS;
15416: }
15417:
15418: /*
15419: * Inquiry Information Byte 7 Handling
15420: *
15421: * Handle SCSI Inquiry Command information for a device by setting
15422: * microcode operating variables that affect WDTR, SDTR, and Tag
15423: * Queuing.
15424: */
15425: STATIC void
15426: AdvInquiryHandling(
15427: ADV_DVC_VAR *asc_dvc,
15428: ADV_SCSI_REQ_Q *scsiq)
15429: {
15430: AdvPortAddr iop_base;
15431: uchar tid;
15432: ASC_SCSI_INQUIRY *inq;
15433: ushort tidmask;
15434: ushort cfg_word;
15435:
15436: /*
15437: * AdvInquiryHandling() requires up to INQUIRY information Byte 7
15438: * to be available.
15439: *
15440: * If less than 8 bytes of INQUIRY information were requested or less
15441: * than 8 bytes were transferred, then return. cdb[4] is the request
15442: * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
15443: * microcode to the transfer residual count.
15444: */
15445: if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8)
15446: {
15447: return;
15448: }
15449:
15450: iop_base = asc_dvc->iop_base;
15451: tid = scsiq->target_id;
15452: inq = (ASC_SCSI_INQUIRY *) scsiq->vdata_addr;
15453:
15454: /*
15455: * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
15456: */
15457: if (inq->byte3.rsp_data_fmt < 2 && inq->byte2.ansi_apr_ver < 2)
15458: {
15459: return;
15460: } else
15461: {
15462: /*
15463: * INQUIRY Byte 7 Handling
15464: *
15465: * Use a device's INQUIRY byte 7 to determine whether it
15466: * supports WDTR, SDTR, and Tag Queuing. If the feature
15467: * is enabled in the EEPROM and the device supports the
15468: * feature, then enable it in the microcode.
15469: */
15470:
15471: tidmask = ADV_TID_TO_TIDMASK(tid);
15472:
15473: /*
15474: * Wide Transfers
15475: *
15476: * If the EEPROM enabled WDTR for the device and the device
15477: * supports wide bus (16 bit) transfers, then turn on the
15478: * device's 'wdtr_able' bit and write the new value to the
15479: * microcode.
15480: */
15481: if ((asc_dvc->wdtr_able & tidmask) && inq->byte7.WBus16)
15482: {
15483: AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
15484: if ((cfg_word & tidmask) == 0)
15485: {
15486: cfg_word |= tidmask;
15487: AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
15488:
15489: /*
15490: * Clear the microcode "WDTR negotiation" done indicator
15491: * for the target to cause it to negotiate with the new
15492: * setting set above.
15493: */
15494: AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
15495: cfg_word &= ~tidmask;
15496: AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
15497: }
15498: }
15499:
15500: /*
15501: * Synchronous Transfers
15502: *
15503: * If the EEPROM enabled SDTR for the device and the device
15504: * supports synchronous transfers, then turn on the device's
15505: * 'sdtr_able' bit. Write the new value to the microcode.
15506: */
15507: if ((asc_dvc->sdtr_able & tidmask) && inq->byte7.Sync)
15508: {
15509: AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
15510: if ((cfg_word & tidmask) == 0)
15511: {
15512: cfg_word |= tidmask;
15513: AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
15514:
15515: /*
15516: * Clear the microcode "SDTR negotiation" done indicator
15517: * for the target to cause it to negotiate with the new
15518: * setting set above.
15519: */
15520: AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
15521: cfg_word &= ~tidmask;
15522: AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
15523: }
15524: }
15525:
15526: /*
15527: * If the EEPROM enabled Tag Queuing for device and the
15528: * device supports Tag Queuing, then turn on the device's
15529: * 'tagqng_enable' bit in the microcode and set the microcode
15530: * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
15531: * value.
15532: *
15533: * Tag Queuing is disabled for the BIOS which runs in polled
15534: * mode and would see no benefit from Tag Queuing. Also by
15535: * disabling Tag Queuing in the BIOS devices with Tag Queuing
15536: * bugs will at least work with the BIOS.
15537: */
15538: if ((asc_dvc->tagqng_able & tidmask) && inq->byte7.CmdQue)
15539: {
15540: AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
15541: cfg_word |= tidmask;
15542: AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
15543: AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
15544: asc_dvc->max_dvc_qng);
15545: }
15546: }
15547: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.