|
|
1.1.1.2 root 1: /* $Id: advansys.c,v 1.1.4.1 2005/06/02 18:52:38 ams Exp $ */
1.1 root 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);
1.1.1.2 root 2036: STATIC long DvcEnterCritical(void);
2037: STATIC void DvcLeaveCritical(long);
1.1 root 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: */
1.1.1.2 root 2873: STATIC long DvcEnterCritical(void);
2874: STATIC void DvcLeaveCritical(long);
1.1 root 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: */
1.1.1.2 root 3139: STATIC ADVEEP_CONFIG Default_EEPROM_Config;
1.1 root 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;
1.1.1.2 root 3259: #define REQPNEXT(reqp) ((reqp)->host_scribble)
1.1 root 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:
4719: /*
4720: * Modify board configuration.
4721: */
4722: ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
4723: switch (ret = AscInitSetConfig(asc_dvc_varp)) {
4724: case 0: /* No error. */
4725: break;
4726: case ASC_WARN_IO_PORT_ROTATE:
4727: ASC_PRINT1(
4728: "AscInitSetConfig: board %d: I/O port address modified\n",
4729: boardp->id);
4730: break;
4731: case ASC_WARN_AUTO_CONFIG:
4732: ASC_PRINT1(
4733: "AscInitSetConfig: board %d: I/O port increment switch enabled\n",
4734: boardp->id);
4735: break;
4736: case ASC_WARN_EEPROM_CHKSUM:
4737: ASC_PRINT1(
4738: "AscInitSetConfig: board %d: EEPROM checksum error\n",
4739: boardp->id);
4740: break;
4741: case ASC_WARN_IRQ_MODIFIED:
4742: ASC_PRINT1(
4743: "AscInitSetConfig: board %d: IRQ modified\n",
4744: boardp->id);
4745: break;
4746: case ASC_WARN_CMD_QNG_CONFLICT:
4747: ASC_PRINT1(
4748: "AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
4749: boardp->id);
4750: break;
4751: default:
4752: ASC_PRINT2(
4753: "AscInitSetConfig: board %d: unknown warning: %x\n",
4754: boardp->id, ret);
4755: break;
4756: }
4757: if (asc_dvc_varp->err_code != 0) {
4758: ASC_PRINT3(
4759: "AscInitSetConfig: board %d error: init_state %x, err_code %x\n",
4760: boardp->id, asc_dvc_varp->init_state,
4761: asc_dvc_varp->err_code);
4762: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4763: kfree(boardp->prtbuf);
4764: #endif /* version >= v1.3.0 */
4765: scsi_unregister(shp);
4766: asc_board_count--;
4767: continue;
4768: }
4769:
4770: /*
4771: * Finish initializing the 'Scsi_Host' structure.
4772: */
4773: /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
4774: if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
4775: shp->irq = asc_dvc_varp->irq_no;
4776: }
4777: } else {
4778:
4779: ADVEEP_CONFIG *ep;
4780:
4781: /*
4782: * Save Wide EEP Configuration Information.
4783: */
4784: ep = &boardp->eep_config.adv_eep;
4785:
4786: ep->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
4787: ep->max_host_qng = adv_dvc_varp->max_host_qng;
4788: ep->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
4789: ep->termination = adv_dvc_varp->cfg->termination;
4790: ep->disc_enable = adv_dvc_varp->cfg->disc_enable;
4791: ep->bios_ctrl = adv_dvc_varp->bios_ctrl;
4792: ep->wdtr_able = adv_dvc_varp->wdtr_able;
4793: ep->sdtr_able = adv_dvc_varp->sdtr_able;
4794: ep->ultra_able = adv_dvc_varp->ultra_able;
4795: ep->tagqng_able = adv_dvc_varp->tagqng_able;
4796: ep->start_motor = adv_dvc_varp->start_motor;
4797: ep->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait;
4798: ep->bios_boot_delay = adv_dvc_varp->cfg->bios_boot_wait;
4799: ep->serial_number_word1 = adv_dvc_varp->cfg->serial1;
4800: ep->serial_number_word2 = adv_dvc_varp->cfg->serial2;
4801: ep->serial_number_word3 = adv_dvc_varp->cfg->serial3;
4802:
4803: /*
4804: * Set the adapter's target id bit in the 'init_tidmask' field.
4805: */
4806: boardp->init_tidmask |=
4807: ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
4808:
4809: /*
4810: * Finish initializing the 'Scsi_Host' structure.
4811: */
4812: shp->irq = adv_dvc_varp->irq_no;
4813: }
4814:
4815: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
4816: /*
4817: * Channels are numbered beginning with 0. For AdvanSys One host
4818: * structure supports one channel. Multi-channel boards have a
4819: * separate host structure for each channel.
4820: */
4821: shp->max_channel = 0;
4822: #endif /* version >= v1.3.89 */
4823: if (ASC_NARROW_BOARD(boardp)) {
4824: shp->max_id = ASC_MAX_TID + 1;
4825: shp->max_lun = ASC_MAX_LUN + 1;
4826:
4827: shp->io_port = asc_dvc_varp->iop_base;
4828: shp->n_io_port = ASC_IOADR_GAP;
4829: shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
4830:
4831: /* Set maximum number of queues the adapter can handle. */
4832: shp->can_queue = asc_dvc_varp->max_total_qng;
4833: } else {
4834: shp->max_id = ADV_MAX_TID + 1;
4835: shp->max_lun = ADV_MAX_LUN + 1;
4836:
4837: /*
4838: * Save the I/O Port address and length even though the
4839: * in v1.3.0 and greater kernels the region is not used
4840: * by a Wide board. Instead the board is accessed with
4841: * Memory Mapped I/O.
4842: */
4843: shp->io_port = iop;
4844: shp->n_io_port = ADV_CONDOR_IOLEN;
4845:
4846: shp->this_id = adv_dvc_varp->chip_scsi_id;
4847:
4848: /* Set maximum number of queues the adapter can handle. */
4849: shp->can_queue = adv_dvc_varp->max_host_qng;
4850: }
4851:
4852: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
4853: /*
4854: * In old kernels without tag queuing support and with memory
4855: * allocation problems set a conservative 'cmd_per_lun' value.
4856: */
4857: #ifdef MODULE
4858: shp->cmd_per_lun = 1;
4859: #else /* MODULE */
4860: shp->cmd_per_lun = 4;
4861: #endif /* MODULE */
4862: ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
4863: #else /* version >= v1.3.89 */
4864: /*
4865: * Following v1.3.89, 'cmd_per_lun' is no longer needed
4866: * and should be set to zero.
4867: *
4868: * But because of a bug introduced in v1.3.89 if the driver is
4869: * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
4870: * SCSI function 'allocate_device' will panic. To allow the driver
4871: * to work as a module in these kernels set 'cmd_per_lun' to 1.
4872: */
4873: #ifdef MODULE
4874: shp->cmd_per_lun = 1;
4875: #else /* MODULE */
4876: shp->cmd_per_lun = 0;
4877: #endif /* MODULE */
4878: /*
4879: * Use the host 'select_queue_depths' function to determine
4880: * the number of commands to queue per device.
4881: */
4882: shp->select_queue_depths = advansys_select_queue_depths;
4883: #endif /* version >= v1.3.89 */
4884:
4885: /*
4886: * Set the maximum number of scatter-gather elements the
4887: * adapter can handle.
4888: */
4889: if (ASC_NARROW_BOARD(boardp)) {
4890: /*
4891: * Allow two commands with 'sg_tablesize' scatter-gather
4892: * elements to be executed simultaneously. This value is
4893: * the theoretical hardware limit. It may be decreased
4894: * below.
4895: */
4896: shp->sg_tablesize =
4897: (((asc_dvc_varp->max_total_qng - 2) / 2) *
4898: ASC_SG_LIST_PER_Q) + 1;
4899: } else {
4900: shp->sg_tablesize = ADV_MAX_SG_LIST;
4901: }
4902:
4903: #ifdef MODULE
4904: /*
4905: * If the driver is compiled as a module, set a limit on the
4906: * 'sg_tablesize' value to prevent memory allocation failures.
4907: * Memory allocation errors are more likely to occur at module
4908: * load time, then at driver initialization time.
4909: */
4910: if (shp->sg_tablesize > 64) {
4911: shp->sg_tablesize = 64;
4912: }
4913: #endif /* MODULE */
4914:
4915: /*
4916: * The value of 'sg_tablesize' can not exceed the SCSI
4917: * mid-level driver definition of SG_ALL. SG_ALL also
4918: * must not be exceeded, because it is used to define the
4919: * size of the scatter-gather table in 'struct asc_sg_head'.
4920: */
4921: if (shp->sg_tablesize > SG_ALL) {
4922: shp->sg_tablesize = SG_ALL;
4923: }
4924:
4925: ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
4926: shp->sg_tablesize);
4927:
4928: /* BIOS start address. */
4929: if (ASC_NARROW_BOARD(boardp)) {
4930: shp->base = (char *) ((ulong) AscGetChipBiosAddress(
4931: asc_dvc_varp->iop_base,
4932: asc_dvc_varp->bus_type));
4933: } else {
4934: /*
4935: * Fill-in BIOS board variables. The Wide BIOS saves
4936: * information in LRAM that is used by the driver.
4937: */
4938: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE,
4939: boardp->bios_signature);
4940: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION,
4941: boardp->bios_version);
4942: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG,
4943: boardp->bios_codeseg);
4944: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN,
4945: boardp->bios_codelen);
4946:
4947: ASC_DBG2(1,
4948: "advansys_detect: bios_signature %x, bios_version %x\n",
4949: boardp->bios_signature, boardp->bios_version);
4950:
4951: ASC_DBG2(1,
4952: "advansys_detect: bios_codeseg %x, bios_codelen %x\n",
4953: boardp->bios_codeseg, boardp->bios_codelen);
4954:
4955: /*
4956: * If the BIOS saved a valid signature, then fill in
4957: * the BIOS code segment base address.
4958: */
4959: if (boardp->bios_signature == 0x55AA) {
4960: /*
4961: * Convert x86 realmode code segment to a linear
4962: * address by shifting left 4.
4963: */
4964: shp->base = (uchar *) (boardp->bios_codeseg << 4);
4965: } else {
4966: shp->base = 0;
4967: }
4968: }
4969:
4970: /*
4971: * Register Board Resources - I/O Port, DMA, IRQ
4972: */
4973:
4974: /* Register I/O port range. */
4975: ASC_DBG(2, "advansys_detect: request_region()\n");
4976: request_region(shp->io_port, shp->n_io_port, "advansys");
4977:
4978: /* Register DMA Channel for Narrow boards. */
4979: shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
4980: if (ASC_NARROW_BOARD(boardp)) {
4981: /* Register DMA channel for ISA bus. */
4982: if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4983: shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
4984: if ((ret =
4985: request_dma(shp->dma_channel, "advansys")) != 0) {
4986: ASC_PRINT3(
4987: "advansys_detect: board %d: request_dma() %d failed %d\n",
4988: boardp->id, shp->dma_channel, ret);
4989: release_region(shp->io_port, shp->n_io_port);
4990: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
4991: kfree(boardp->prtbuf);
4992: #endif /* version >= v1.3.0 */
4993: scsi_unregister(shp);
4994: asc_board_count--;
4995: continue;
4996: }
4997: AscEnableIsaDma(shp->dma_channel);
4998: }
4999: }
5000:
5001: /* Register IRQ Number. */
5002: ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
5003: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5004: if ((ret = request_irq(shp->irq, advansys_interrupt,
5005: SA_INTERRUPT, "advansys")) != 0)
5006: #else /* version >= v1.3.70 */
5007: /*
5008: * If request_irq() fails with the SA_INTERRUPT flag set,
5009: * then try again without the SA_INTERRUPT flag set. This
5010: * allows IRQ sharing to work even with other drivers that
5011: * do not set the SA_INTERRUPT flag.
5012: *
5013: * If SA_INTERRUPT is not set, then interrupts are enabled
5014: * before the driver interrupt function is called.
5015: */
5016: if (((ret = request_irq(shp->irq, advansys_interrupt,
5017: SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
5018: "advansys", boardp)) != 0) &&
5019: ((ret = request_irq(shp->irq, advansys_interrupt,
5020: (share_irq == TRUE ? SA_SHIRQ : 0),
5021: "advansys", boardp)) != 0))
5022: #endif /* version >= v1.3.70 */
5023: {
5024: if (ret == -EBUSY) {
5025: ASC_PRINT2(
5026: "advansys_detect: board %d: request_irq(): IRQ %d already in use.\n",
5027: boardp->id, shp->irq);
5028: } else if (ret == -EINVAL) {
5029: ASC_PRINT2(
5030: "advansys_detect: board %d: request_irq(): IRQ %d not valid.\n",
5031: boardp->id, shp->irq);
5032: } else {
5033: ASC_PRINT3(
5034: "advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n",
5035: boardp->id, shp->irq, ret);
5036: }
5037: release_region(shp->io_port, shp->n_io_port);
5038: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5039: iounmap(boardp->ioremap_addr);
5040: #endif /* version >= v1,3,0 */
5041: if (shp->dma_channel != NO_ISA_DMA) {
5042: free_dma(shp->dma_channel);
5043: }
5044: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5045: kfree(boardp->prtbuf);
5046: #endif /* version >= v1.3.0 */
5047: scsi_unregister(shp);
5048: asc_board_count--;
5049: continue;
5050: }
5051:
5052: /*
5053: * Initialize board RISC chip and enable interrupts.
5054: */
5055: if (ASC_NARROW_BOARD(boardp)) {
5056: ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
5057: warn_code = AscInitAsc1000Driver(asc_dvc_varp);
5058: err_code = asc_dvc_varp->err_code;
5059:
5060: if (warn_code || err_code) {
5061: ASC_PRINT4(
5062: "AscInitAsc1000Driver: board %d: error: init_state %x, warn %x error %x\n",
5063: boardp->id, asc_dvc_varp->init_state,
5064: warn_code, err_code);
5065: }
5066: } else {
5067: int req_cnt;
5068: adv_req_t *reqp = NULL;
5069: int sg_cnt;
5070: adv_sgblk_t *sgp = NULL;
5071:
5072: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
5073: req_cnt = sizeof(adv_req_buf)/sizeof(adv_req_t);
5074: sg_cnt = sizeof(adv_sgblk_buf)/sizeof(adv_sgblk_t);
5075: reqp = (adv_req_t *) &adv_req_buf[0];
5076: sgp = (adv_sgblk_t *) &adv_sgblk_buf[0];
5077: #else /* version >= v1.3.0 */
5078: /*
5079: * Allocate up to 'max_host_qng' request structures for
5080: * the Wide board.
5081: */
5082: for (req_cnt = adv_dvc_varp->max_host_qng;
5083: req_cnt > 0; req_cnt--) {
5084:
5085: reqp = (adv_req_t *)
5086: kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
5087:
5088: ASC_DBG3(1,
5089: "advansys_detect: reqp %x, req_cnt %d, bytes %d\n",
5090: (unsigned) reqp, req_cnt, sizeof(adv_req_t) * req_cnt);
5091:
5092: if (reqp != NULL) {
5093: break;
5094: }
5095: }
5096:
5097: /*
5098: * Allocate up to ADV_TOT_SG_LIST request structures for
5099: * the Wide board.
5100: */
5101: for (sg_cnt = ADV_TOT_SG_LIST; sg_cnt > 0; sg_cnt--) {
5102:
5103: sgp = (adv_sgblk_t *)
5104: kmalloc(sizeof(adv_sgblk_t) * sg_cnt, GFP_ATOMIC);
5105:
5106: ASC_DBG3(1,
5107: "advansys_detect: sgp %x, sg_cnt %d, bytes %d\n",
5108: (unsigned) sgp, sg_cnt, sizeof(adv_sgblk_t) * sg_cnt);
5109:
5110: if (sgp != NULL) {
5111: break;
5112: }
5113: }
5114: #endif /* version >= v1.3.0 */
5115:
5116: /*
5117: * If no request structures or scatter-gather structures could
5118: * be allocated, then return an error. Otherwise continue with
5119: * initialization.
5120: */
5121: if (reqp == NULL) {
5122: ASC_PRINT1(
5123: "advansys_detect: board %d: error: failed to kmalloc() adv_req_t buffer.\n",
5124: boardp->id);
5125: err_code = ADV_ERROR;
5126: } else if (sgp == NULL) {
5127: kfree(reqp);
5128: ASC_PRINT1(
5129: "advansys_detect: board %d: error: failed to kmalloc() adv_sgblk_t buffer.\n",
5130: boardp->id);
5131: err_code = ADV_ERROR;
5132: } else {
5133:
5134: /*
5135: * Save original pointer for kfree() in case the
5136: * driver is built as a module and can be unloaded.
5137: */
5138: boardp->orig_reqp = reqp;
5139:
5140: /*
5141: * Point 'adv_reqp' to the request structures and
5142: * link them together.
5143: */
5144: req_cnt--;
5145: reqp[req_cnt].next_reqp = NULL;
5146: for (; req_cnt > 0; req_cnt--) {
5147: reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
5148: }
5149: boardp->adv_reqp = &reqp[0];
5150:
5151: /*
5152: * Save original pointer for kfree() in case the
5153: * driver is built as a module and can be unloaded.
5154: */
5155: boardp->orig_sgblkp = sgp;
5156:
5157: /*
5158: * Point 'adv_sgblkp' to the request structures and
5159: * link them together.
5160: */
5161: sg_cnt--;
5162: sgp[sg_cnt].next_sgblkp = NULL;
5163: for (; sg_cnt > 0; sg_cnt--) {
5164: sgp[sg_cnt - 1].next_sgblkp = &sgp[sg_cnt];
5165: }
5166: boardp->adv_sgblkp = &sgp[0];
5167:
5168: ASC_DBG(2, "advansys_detect: AdvInitAsc3550Driver()\n");
5169: warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
5170: err_code = adv_dvc_varp->err_code;
5171:
5172: if (warn_code || err_code) {
5173: ASC_PRINT3(
5174: "AdvInitAsc3550Driver: board %d: error: warn %x, error %x\n",
5175: boardp->id, warn_code, adv_dvc_varp->err_code);
5176: }
5177: }
5178: }
5179:
5180: if (err_code != 0) {
5181: release_region(shp->io_port, shp->n_io_port);
5182: if (ASC_WIDE_BOARD(boardp)) {
5183: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5184: iounmap(boardp->ioremap_addr);
5185: #endif /* version >= v1,3,0 */
5186: if (boardp->orig_reqp) {
5187: kfree(boardp->orig_reqp);
5188: boardp->orig_reqp = boardp->adv_reqp = NULL;
5189: }
5190: if (boardp->orig_sgblkp) {
5191: kfree(boardp->orig_sgblkp);
5192: boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5193: }
5194: }
5195: if (shp->dma_channel != NO_ISA_DMA) {
5196: free_dma(shp->dma_channel);
5197: }
5198: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5199: kfree(boardp->prtbuf);
5200: #endif /* version >= v1.3.0 */
5201: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5202: free_irq(shp->irq);
5203: #else /* version >= v1.3.70 */
5204: free_irq(shp->irq, boardp);
5205: #endif /* version >= v1.3.70 */
5206: scsi_unregister(shp);
5207: asc_board_count--;
5208: continue;
5209: }
5210: ASC_DBG_PRT_SCSI_HOST(2, shp);
5211: }
5212: }
5213: ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
5214: return asc_board_count;
5215: }
5216:
5217: /*
5218: * advansys_release()
5219: *
5220: * Release resources allocated for a single AdvanSys adapter.
5221: */
5222: int
5223: advansys_release(struct Scsi_Host *shp)
5224: {
5225: asc_board_t *boardp;
5226:
5227: ASC_DBG(1, "advansys_release: begin\n");
5228: boardp = ASC_BOARDP(shp);
5229: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
5230: free_irq(shp->irq);
5231: #else /* version >= v1.3.70 */
5232: free_irq(shp->irq, boardp);
5233: #endif /* version >= v1.3.70 */
5234: if (shp->dma_channel != NO_ISA_DMA) {
5235: ASC_DBG(1, "advansys_release: free_dma()\n");
5236: free_dma(shp->dma_channel);
5237: }
5238: release_region(shp->io_port, shp->n_io_port);
5239: if (ASC_WIDE_BOARD(boardp)) {
5240: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5241: iounmap(boardp->ioremap_addr);
5242: #endif /* version >= v1,3,0 */
5243: if (boardp->orig_reqp) {
5244: kfree(boardp->orig_reqp);
5245: boardp->orig_reqp = boardp->adv_reqp = NULL;
5246: }
5247: if (boardp->orig_sgblkp) {
5248: kfree(boardp->orig_sgblkp);
5249: boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
5250: }
5251: }
5252: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
5253: ASC_ASSERT(boardp->prtbuf != NULL);
5254: kfree(boardp->prtbuf);
5255: #endif /* version >= v1.3.0 */
5256: scsi_unregister(shp);
5257: ASC_DBG(1, "advansys_release: end\n");
5258: return 0;
5259: }
5260:
5261: /*
5262: * advansys_info()
5263: *
5264: * Return suitable for printing on the console with the argument
5265: * adapter's configuration information.
5266: *
5267: * Note: The information line should not exceed ASC_INFO_SIZE bytes,
5268: * otherwise the static 'info' array will be overrun.
5269: */
5270: const char *
5271: advansys_info(struct Scsi_Host *shp)
5272: {
5273: static char info[ASC_INFO_SIZE];
5274: asc_board_t *boardp;
5275: ASC_DVC_VAR *asc_dvc_varp;
5276: ADV_DVC_VAR *adv_dvc_varp;
5277: char *busname;
5278:
5279: boardp = ASC_BOARDP(shp);
5280: if (ASC_NARROW_BOARD(boardp)) {
5281: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5282: ASC_DBG(1, "advansys_info: begin\n");
5283: if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
5284: if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
5285: busname = "ISA PnP";
5286: } else {
5287: busname = "ISA";
5288: }
5289: sprintf(info,
5290: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5291: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u",
5292: #else /* version >= v2.1.92 */
5293: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u",
5294: #endif /* version >= v2.1.92 */
5295: ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5296: (unsigned) shp->base,
5297: shp->io_port, shp->n_io_port - 1,
5298: shp->irq, shp->dma_channel);
5299: } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
5300: if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
5301: == ASC_IS_PCI_ULTRA) {
5302: busname = "PCI Ultra";
5303: } else {
5304: busname = "PCI";
5305: }
5306: sprintf(info,
5307: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5308: "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u",
5309: #else /* version >= v2.1.92 */
5310: "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u",
5311: #endif /* version >= v2.1.92 */
5312: ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5313: shp->io_port, shp->n_io_port - 1, shp->irq);
5314: } else {
5315: if (asc_dvc_varp->bus_type & ASC_IS_VL) {
5316: busname = "VL";
5317: } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
5318: busname = "EISA";
5319: } else {
5320: busname = "?";
5321: ASC_PRINT2(
5322: "advansys_info: board %d: unknown bus type %d\n",
5323: boardp->id, asc_dvc_varp->bus_type);
5324: }
5325: sprintf(info,
5326: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
5327: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u",
5328: #else /* version >= v2.1.92 */
5329: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u",
5330: #endif /* version >= v2.1.92 */
5331: ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
5332: (unsigned) shp->base, shp->io_port - 1,
5333: shp->n_io_port, shp->irq);
5334: }
5335: } else {
5336: /*
5337: * Wide Adapter Information
5338: *
5339: * Memory-mapped I/O is used instead of I/O space to access
5340: * the adapter, but display the I/O Port range. The Memory
5341: * I/O address is displayed through the driver /proc file.
5342: */
5343: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5344: if (boardp->bios_signature == 0x55AA) {
5345: sprintf(info,
5346: "AdvanSys SCSI %s: PCI Ultra-Wide: BIOS %X/%X, IO %X/%X, IRQ %u",
5347: ASC_VERSION,
5348: boardp->bios_codeseg << 4,
5349: boardp->bios_codelen > 0 ?
5350: (boardp->bios_codelen << 9) - 1 : 0,
5351: (unsigned) boardp->ioport, ADV_CONDOR_IOLEN - 1,
5352: shp->irq);
5353: } else {
5354: sprintf(info,
5355: "AdvanSys SCSI %s: PCI Ultra-Wide: IO %X/%X, IRQ %u",
5356: ASC_VERSION,
5357: (unsigned) boardp->ioport,
5358: (ADV_CONDOR_IOLEN - 1),
5359: shp->irq);
5360: }
5361: }
5362: ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
5363: ASC_DBG(1, "advansys_info: end\n");
5364: return info;
5365: }
5366:
5367: /*
5368: * advansys_command() - polled I/O entrypoint.
5369: *
5370: * Apparently host drivers shouldn't return until the command
5371: * is finished.
5372: *
5373: * Note: This is an old interface that is no longer used by the SCSI
5374: * mid-level driver. The new interface, advansys_queuecommand(),
5375: * currently handles all requests.
5376: */
5377: int
5378: advansys_command(Scsi_Cmnd *scp)
5379: {
5380: ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
5381: ASC_STATS(scp->host, command);
5382: scp->SCp.Status = 0; /* Set to a known state */
5383: advansys_queuecommand(scp, advansys_command_done);
5384: while (scp->SCp.Status == 0) {
5385: continue;
5386: }
5387: ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
5388: return scp->result;
5389: }
5390:
5391: /*
5392: * advansys_queuecommand() - interrupt-driven I/O entrypoint.
5393: *
5394: * This function always returns 0. Command return status is saved
5395: * in the 'scp' result field.
5396: */
5397: int
5398: advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
5399: {
5400: struct Scsi_Host *shp;
5401: asc_board_t *boardp;
1.1.1.2 root 5402: long flags;
1.1 root 5403: Scsi_Cmnd *done_scp;
5404:
5405: shp = scp->host;
5406: boardp = ASC_BOARDP(shp);
5407: ASC_STATS(shp, queuecommand);
5408:
5409: /*
5410: * Disable interrupts to preserve request ordering and provide
5411: * mutually exclusive access to global structures used to initiate
5412: * a request.
5413: */
5414: save_flags(flags);
5415: cli();
5416:
5417: /*
5418: * Block new commands while handling a reset or abort request.
5419: */
5420: if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5421: if (boardp->flags & ASC_HOST_IN_RESET) {
5422: ASC_DBG1(1,
5423: "advansys_queuecommand: scp %x blocked for reset request\n",
5424: (unsigned) scp);
5425: scp->result = HOST_BYTE(DID_RESET);
5426: } else {
5427: ASC_DBG1(1,
5428: "advansys_queuecommand: scp %x blocked for abort request\n",
5429: (unsigned) scp);
5430: scp->result = HOST_BYTE(DID_ABORT);
5431: }
5432:
5433: /*
5434: * Add blocked requests to the board's 'done' queue. The queued
5435: * requests will be completed at the end of the abort or reset
5436: * handling.
5437: */
5438: asc_enqueue(&boardp->done, scp, ASC_BACK);
5439: restore_flags(flags);
5440: return 0;
5441: }
5442:
5443: /*
5444: * Attempt to execute any waiting commands for the board.
5445: */
5446: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5447: ASC_DBG(1,
5448: "advansys_queuecommand: before asc_execute_queue() waiting\n");
5449: asc_execute_queue(&boardp->waiting);
5450: }
5451:
5452: /*
5453: * Save the function pointer to Linux mid-level 'done' function
5454: * and attempt to execute the command.
5455: *
5456: * If ASC_ERROR is returned the request has been added to the
5457: * board's 'active' queue and will be completed by the interrupt
5458: * handler.
5459: *
5460: * If ASC_BUSY is returned add the request to the board's per
5461: * target waiting list.
5462: *
5463: * If an error occurred, the request will have been placed on the
5464: * board's 'done' queue and must be completed before returning.
5465: */
5466: scp->scsi_done = done;
5467: switch (asc_execute_scsi_cmnd(scp)) {
5468: case ASC_NOERROR:
5469: break;
5470: case ASC_BUSY:
5471: asc_enqueue(&boardp->waiting, scp, ASC_BACK);
5472: break;
5473: case ASC_ERROR:
5474: default:
5475: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5476: /* Interrupts could be enabled here. */
5477: asc_scsi_done_list(done_scp);
5478: break;
5479: }
5480:
5481: restore_flags(flags);
5482: return 0;
5483: }
5484:
5485: /*
5486: * advansys_abort()
5487: *
5488: * Abort the command specified by 'scp'.
5489: */
5490: int
5491: advansys_abort(Scsi_Cmnd *scp)
5492: {
5493: struct Scsi_Host *shp;
5494: asc_board_t *boardp;
5495: ASC_DVC_VAR *asc_dvc_varp;
5496: ADV_DVC_VAR *adv_dvc_varp;
1.1.1.2 root 5497: long flags;
1.1 root 5498: int do_scsi_done;
5499: int scp_found;
5500: Scsi_Cmnd *done_scp = NULL;
5501: int ret;
5502:
5503: /* Save current flags and disable interrupts. */
5504: save_flags(flags);
5505: cli();
5506:
5507: ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
5508:
5509: #ifdef ADVANSYS_STATS
5510: if (scp->host != NULL) {
5511: ASC_STATS(scp->host, abort);
5512: }
5513: #endif /* ADVANSYS_STATS */
5514:
5515: #ifdef ADVANSYS_ASSERT
5516: do_scsi_done = ASC_ERROR;
5517: scp_found = ASC_ERROR;
5518: ret = ASC_ERROR;
5519: #endif /* ADVANSYS_ASSERT */
5520:
5521: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5522: if (scp->serial_number != scp->serial_number_at_timeout) {
5523: ASC_PRINT1(
5524: "advansys_abort: timeout serial number changed for request %x\n",
5525: (unsigned) scp);
5526: do_scsi_done = ASC_FALSE;
5527: scp_found = ASC_FALSE;
5528: ret = SCSI_ABORT_NOT_RUNNING;
5529: } else
5530: #endif /* version >= v1.3.89 */
5531: if ((shp = scp->host) == NULL) {
5532: scp->result = HOST_BYTE(DID_ERROR);
5533: do_scsi_done = ASC_TRUE;
5534: scp_found = ASC_FALSE;
5535: ret = SCSI_ABORT_ERROR;
5536: } else if ((boardp = ASC_BOARDP(shp))->flags &
5537: (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5538: ASC_PRINT2(
5539: "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
5540: boardp->id, boardp->flags);
5541: do_scsi_done = ASC_TRUE;
5542: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5543: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5544: scp_found = ASC_TRUE;
5545: } else {
5546: scp_found = ASC_FALSE;
5547: }
5548: scp->result = HOST_BYTE(DID_ERROR);
5549: ret = SCSI_ABORT_ERROR;
5550: } else {
5551: /* Set abort flag to avoid nested reset or abort requests. */
5552: boardp->flags |= ASC_HOST_IN_ABORT;
5553:
5554: do_scsi_done = ASC_TRUE;
5555: if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
5556: /*
5557: * If asc_rmqueue() found the command on the waiting
5558: * queue, it had not been sent to the device. After
5559: * the queue is removed, no other handling is required.
5560: */
5561: ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
5562: (unsigned) scp);
5563: scp_found = ASC_TRUE;
5564: scp->result = HOST_BYTE(DID_ABORT);
5565: ret = SCSI_ABORT_SUCCESS;
5566: } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
5567: /*
5568: * If asc_isqueued() found the command on the active
5569: * queue, it has been sent to the device. The command
5570: * will be returned through the interrupt handler after
5571: * it has been aborted.
5572: */
5573:
5574: if (ASC_NARROW_BOARD(boardp)) {
5575: /*
5576: * Narrow Board
5577: */
5578: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5579: scp->result = HOST_BYTE(DID_ABORT);
5580:
5581: sti(); /* Enable interrupts for AscAbortSRB(). */
5582: ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
5583: (unsigned) scp);
5584: switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
5585: case ASC_TRUE:
5586: /* asc_isr_callback() will be called */
5587: ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
5588: ret = SCSI_ABORT_PENDING;
5589: break;
5590: case ASC_FALSE:
5591: /* Request has apparently already completed. */
5592: ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
5593: ret = SCSI_ABORT_NOT_RUNNING;
5594: break;
5595: case ASC_ERROR:
5596: default:
5597: ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
5598: ret = SCSI_ABORT_ERROR;
5599: break;
5600: }
5601: cli();
5602: } else {
5603: /*
5604: * Wide Board
5605: */
5606: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5607: scp->result = HOST_BYTE(DID_ABORT);
5608:
5609: ASC_DBG1(1, "advansys_abort: before AdvAbortSRB(), scp %x\n",
5610: (unsigned) scp);
5611: switch (AdvAbortSRB(adv_dvc_varp, (ulong) scp)) {
5612: case ASC_TRUE:
5613: /* asc_isr_callback() will be called */
5614: ASC_DBG(1, "advansys_abort: AdvAbortSRB() TRUE\n");
5615: ret = SCSI_ABORT_PENDING;
5616: break;
5617: case ASC_FALSE:
5618: /* Request has apparently already completed. */
5619: ASC_DBG(1, "advansys_abort: AdvAbortSRB() FALSE\n");
5620: ret = SCSI_ABORT_NOT_RUNNING;
5621: break;
5622: case ASC_ERROR:
5623: default:
5624: ASC_DBG(1, "advansys_abort: AdvAbortSRB() ERROR\n");
5625: ret = SCSI_ABORT_ERROR;
5626: break;
5627: }
5628: /*
5629: * Ensure all requests completed by the microcode have
5630: * been processed by calling AdvISR().
5631: */
5632: (void) AdvISR(adv_dvc_varp);
5633: }
5634:
5635: /*
5636: * The request will either still be on the active queue
5637: * or have been added to the board's done queue.
5638: */
5639: if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
5640: scp->result = HOST_BYTE(DID_ABORT);
5641: scp_found = ASC_TRUE;
5642: } else {
5643: scp_found = asc_rmqueue(&boardp->done, scp);
5644: ASC_ASSERT(scp_found == ASC_TRUE);
5645: }
5646:
5647: } else {
5648: /*
5649: * The command was not found on the active or waiting queues.
5650: */
5651: do_scsi_done = ASC_TRUE;
5652: scp_found = ASC_FALSE;
5653: ret = SCSI_ABORT_NOT_RUNNING;
5654: }
5655:
5656: /* Clear abort flag. */
5657: boardp->flags &= ~ASC_HOST_IN_ABORT;
5658:
5659: /*
5660: * Because the ASC_HOST_IN_ABORT flag causes both
5661: * 'advansys_interrupt' and 'asc_isr_callback' to
5662: * queue requests to the board's 'done' queue and
5663: * prevents waiting commands from being executed,
5664: * these queued requests must be handled here.
5665: */
5666: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
5667:
5668: /*
5669: * Start any waiting commands for the board.
5670: */
5671: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
5672: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
5673: asc_execute_queue(&boardp->waiting);
5674: }
5675: }
5676:
5677: /* Interrupts could be enabled here. */
5678:
5679: /*
5680: * Complete the request to be aborted, unless it has been
5681: * restarted as detected above, even if it was not found on
5682: * the device active or waiting queues.
5683: */
5684: ASC_ASSERT(do_scsi_done != ASC_ERROR);
5685: ASC_ASSERT(scp_found != ASC_ERROR);
5686: if (do_scsi_done == ASC_TRUE) {
5687: if (scp->scsi_done == NULL) {
5688: ASC_PRINT1(
5689: "advansys_abort: aborted request scsi_done() is NULL, %x\n",
5690: (unsigned) scp);
5691: } else {
5692: if (scp_found == ASC_FALSE) {
5693: ASC_PRINT1(
5694: "advansys_abort: abort request not active or waiting, completing anyway %x\n",
5695: (unsigned) scp);
5696: }
5697: ASC_STATS(scp->host, done);
5698: scp->scsi_done(scp);
5699: }
5700: }
5701:
5702: /*
5703: * It is possible for the request done function to re-enable
5704: * interrupts without confusing the driver. But here interrupts
5705: * aren't enabled until all requests have been completed.
5706: */
5707: if (done_scp != NULL) {
5708: asc_scsi_done_list(done_scp);
5709: }
5710:
5711: ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
5712:
5713: /* Re-enable interrupts, if they were enabled on entry. */
5714: restore_flags(flags);
5715:
5716: ASC_ASSERT(ret != ASC_ERROR);
5717: return ret;
5718: }
5719:
5720: /*
5721: * advansys_reset()
5722: *
5723: * Reset the device associated with the command 'scp'.
5724: */
5725: int
5726: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
5727: advansys_reset(Scsi_Cmnd *scp)
5728: #else /* version >= v1.3.89 */
5729: advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
5730: #endif /* version >= v1.3.89 */
5731: {
5732: struct Scsi_Host *shp;
5733: asc_board_t *boardp;
5734: ASC_DVC_VAR *asc_dvc_varp;
5735: ADV_DVC_VAR *adv_dvc_varp;
1.1.1.2 root 5736: long flags;
1.1 root 5737: Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
5738: Scsi_Cmnd *tscp, *new_last_scp;
5739: int do_scsi_done;
5740: int scp_found;
5741: int status;
5742: int target;
5743: int ret;
5744: int device_reset = ASC_FALSE;
5745:
5746: /* Save current flags and disable interrupts. */
5747: save_flags(flags);
5748: cli();
5749:
5750: ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
5751:
5752: #ifdef ADVANSYS_STATS
5753: if (scp->host != NULL) {
5754: ASC_STATS(scp->host, reset);
5755: }
5756: #endif /* ADVANSYS_STATS */
5757:
5758: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5759: if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) &&
5760: (scp->serial_number != scp->serial_number_at_timeout)) {
5761: ASC_PRINT1(
5762: "advansys_reset: timeout serial number changed for request %x\n",
5763: (unsigned) scp);
5764: do_scsi_done = ASC_FALSE;
5765: scp_found = ASC_FALSE;
5766: ret = SCSI_RESET_NOT_RUNNING;
5767: } else
5768: #endif /* version >= v1.3.89 */
5769: if ((shp = scp->host) == NULL) {
5770: scp->result = HOST_BYTE(DID_ERROR);
5771: do_scsi_done = ASC_TRUE;
5772: scp_found = ASC_FALSE;
5773: ret = SCSI_RESET_ERROR;
5774: } else if ((boardp = ASC_BOARDP(shp))->flags &
5775: (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
5776: ASC_PRINT2(
5777: "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
5778: boardp->id, boardp->flags);
5779: do_scsi_done = ASC_TRUE;
5780: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5781: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5782: scp_found = ASC_TRUE;
5783: } else {
5784: scp_found = ASC_FALSE;
5785: }
5786: scp->result = HOST_BYTE(DID_ERROR);
5787: ret = SCSI_RESET_ERROR;
5788: } else if (jiffies >= boardp->last_reset &&
5789: jiffies < (boardp->last_reset + (10 * HZ))) {
5790: /*
5791: * Don't allow a reset to be attempted within 10 seconds
5792: * of the last reset.
5793: *
5794: * If 'jiffies' wrapping occurs, the reset request will go
5795: * through, because a wrapped 'jiffies' would not pass the
5796: * test above.
5797: */
5798: ASC_DBG(1,
5799: "advansys_reset: reset within 10 sec of last reset ignored\n");
5800: do_scsi_done = ASC_TRUE;
5801: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
5802: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
5803: scp_found = ASC_TRUE;
5804: } else {
5805: scp_found = ASC_FALSE;
5806: }
5807: scp->result = HOST_BYTE(DID_ERROR);
5808: ret = SCSI_RESET_ERROR;
5809: } else {
5810: do_scsi_done = ASC_TRUE;
5811:
5812: /* Set reset flag to avoid nested reset or abort requests. */
5813: boardp->flags |= ASC_HOST_IN_RESET;
5814:
5815: /*
5816: * If the request is on the target waiting or active queue
5817: * or the board done queue, then remove it and note that it
5818: * was found.
5819: */
5820: if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
5821: ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
5822: scp_found = ASC_TRUE;
5823: } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
5824: ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
5825: scp_found = ASC_TRUE;
5826: } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
5827: scp_found = ASC_TRUE;
5828: } else {
5829: scp_found = ASC_FALSE;
5830: }
5831:
5832:
5833: if (ASC_NARROW_BOARD(boardp)) {
5834: /*
5835: * Narrow Board
5836: *
5837: * If the suggest reset bus flags are set, then reset the bus.
5838: * Otherwise only reset the device.
5839: */
5840: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
5841: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5842: if (reset_flags &
5843: (SCSI_RESET_SUGGEST_BUS_RESET |
5844: SCSI_RESET_SUGGEST_HOST_RESET)) {
5845: #endif /* version >= v1.3.89 */
5846:
5847: /*
5848: * Reset the target's SCSI bus.
5849: */
5850: ASC_DBG(1, "advansys_reset: before AscResetSB()\n");
5851: sti(); /* Enable interrupts for AscResetSB(). */
5852: status = AscResetSB(asc_dvc_varp);
5853: cli();
5854: switch (status) {
5855: case ASC_TRUE:
5856: ASC_DBG(1, "advansys_reset: AscResetSB() success\n");
5857: ret = SCSI_RESET_SUCCESS;
5858: break;
5859: case ASC_ERROR:
5860: default:
5861: ASC_DBG(1, "advansys_reset: AscResetSB() failed\n");
5862: ret = SCSI_RESET_ERROR;
5863: break;
5864: }
5865:
5866: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5867: } else {
5868: /*
5869: * Reset the specified device. If the device reset fails,
5870: * then reset the SCSI bus.
5871: */
5872:
5873: ASC_DBG1(1,
5874: "advansys_reset: before AscResetDevice(), target %d\n",
5875: scp->target);
5876: sti(); /* Enable interrupts for AscResetDevice(). */
5877: status = AscResetDevice(asc_dvc_varp, scp->target);
5878: cli();
5879:
5880: switch (status) {
5881: case ASC_TRUE:
5882: ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
5883: device_reset = ASC_TRUE;
5884: ret = SCSI_RESET_SUCCESS;
5885: break;
5886: case ASC_ERROR:
5887: default:
5888: ASC_DBG(1,
5889: "advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n");
5890: sti(); /* Enable interrupts for AscResetSB(). */
5891: status = AscResetSB(asc_dvc_varp);
5892: cli();
5893: switch (status) {
5894: case ASC_TRUE:
5895: ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
5896: ret = SCSI_RESET_SUCCESS;
5897: break;
5898: case ASC_ERROR:
5899: default:
5900: ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
5901: ret = SCSI_RESET_ERROR;
5902: break;
5903: }
5904: break;
5905: }
5906: }
5907: #endif /* version >= v1.3.89 */
5908: } else {
5909: /*
5910: * Wide Board
5911: *
5912: * If the suggest reset bus flags are set, then reset the bus.
5913: * Otherwise only reset the device.
5914: */
5915: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
5916: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5917: if (reset_flags &
5918: (SCSI_RESET_SUGGEST_BUS_RESET |
5919: SCSI_RESET_SUGGEST_HOST_RESET)) {
5920: #endif /* version >= v1.3.89 */
5921:
5922: /*
5923: * Reset the target's SCSI bus.
5924: */
5925: ASC_DBG(1, "advansys_reset: before AdvResetSB()\n");
5926: switch (AdvResetSB(adv_dvc_varp)) {
5927: case ASC_TRUE:
5928: ASC_DBG(1, "advansys_reset: AdvResetSB() success\n");
5929: ret = SCSI_RESET_SUCCESS;
5930: break;
5931: case ASC_FALSE:
5932: default:
5933: ASC_DBG(1, "advansys_reset: AdvResetSB() failed\n");
5934: ret = SCSI_RESET_ERROR;
5935: break;
5936: }
5937: /*
5938: * Ensure all requests completed by the microcode have
5939: * been processed by calling AdvISR().
5940: */
5941: (void) AdvISR(adv_dvc_varp);
5942: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
5943: } else {
5944: /*
5945: * Reset the specified device. If the device reset fails,
5946: * then reset the SCSI bus.
5947: */
5948:
5949: ASC_DBG1(1,
5950: "advansys_reset: before AdvResetDevice(), target %d\n",
5951: scp->target);
5952:
5953: switch (AdvResetDevice(adv_dvc_varp, scp->target)) {
5954: case ASC_TRUE:
5955: ASC_DBG(1, "advansys_reset: AdvResetDevice() success\n");
5956: device_reset = ASC_TRUE;
5957: ret = SCSI_RESET_SUCCESS;
5958: break;
5959: case ASC_FALSE:
5960: default:
5961: ASC_DBG(1,
5962: "advansys_reset: AdvResetDevice() failed; Calling AdvResetSB()\n");
5963:
5964: switch (AdvResetSB(adv_dvc_varp)) {
5965: case ASC_TRUE:
5966: ASC_DBG(1, "advansys_reset: AdvResetSB() TRUE\n");
5967: ret = SCSI_RESET_SUCCESS;
5968: break;
5969: case ASC_FALSE:
5970: default:
5971: ASC_DBG(1, "advansys_reset: AdvResetSB() ERROR\n");
5972: ret = SCSI_RESET_ERROR;
5973: break;
5974: }
5975: break;
5976: }
5977: /*
5978: * Ensure all requests completed by the microcode have
5979: * been processed by calling AdvISR().
5980: */
5981: (void) AdvISR(adv_dvc_varp);
5982: }
5983: #endif /* version >= v1.3.89 */
5984: }
5985:
5986: /*
5987: * Because the ASC_HOST_IN_RESET flag causes both
5988: * 'advansys_interrupt' and 'asc_isr_callback' to
5989: * queue requests to the board's 'done' queue and
5990: * prevents waiting commands from being executed,
5991: * these queued requests must be handled here.
5992: */
5993: done_scp = asc_dequeue_list(&boardp->done, &last_scp,
5994: ASC_TID_ALL);
5995:
5996: /*
5997: * If a device reset was performed dequeue all waiting
5998: * and active requests for the device and set the request
5999: * status to DID_RESET.
6000: *
6001: * If a SCSI bus reset was performed dequeue all waiting
6002: * and active requests for all devices and set the request
6003: * status to DID_RESET.
6004: */
6005: if (device_reset == ASC_TRUE) {
6006: target = scp->target;
6007: } else {
6008: target = ASC_TID_ALL;
6009: }
6010:
6011: /*
6012: * Add active requests to 'done_scp' and set the request status
6013: * to DID_RESET.
6014: */
6015: if (done_scp == NULL) {
6016: done_scp = asc_dequeue_list(&boardp->active, &last_scp, target);
1.1.1.2 root 6017: for (tscp = done_scp; tscp; tscp = (REQP) REQPNEXT(tscp)) {
1.1 root 6018: tscp->result = HOST_BYTE(DID_RESET);
6019: }
6020: } else {
6021: ASC_ASSERT(last_scp != NULL);
1.1.1.2 root 6022: REQPNEXT(last_scp) =
6023: (unsigned char *) asc_dequeue_list(&boardp->active,
6024: &new_last_scp, target);
6025: if (new_last_scp != (Scsi_Cmnd *) NULL) {
6026: ASC_ASSERT((REQP) REQPNEXT(last_scp) != NULL);
6027: for (tscp = (Scsi_Cmnd *) REQPNEXT(last_scp);
6028: tscp;
6029: tscp = (Scsi_Cmnd *) REQPNEXT(tscp)) {
1.1 root 6030: tscp->result = HOST_BYTE(DID_RESET);
6031: }
6032: last_scp = new_last_scp;
6033: }
6034: }
6035:
6036: /*
6037: * Add waiting requests to 'done_scp' and set the request status
6038: * to DID_RESET.
6039: */
6040: if (done_scp == NULL) {
6041: done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target);
1.1.1.2 root 6042: for (tscp = done_scp; tscp; tscp = (REQP) REQPNEXT(tscp)) {
1.1 root 6043: tscp->result = HOST_BYTE(DID_RESET);
6044: }
6045: } else {
6046: ASC_ASSERT(last_scp != NULL);
1.1.1.2 root 6047: REQPNEXT(last_scp) =
6048: (unsigned char *) asc_dequeue_list(&boardp->waiting,
6049: &new_last_scp, target);
1.1 root 6050: if (new_last_scp != NULL) {
1.1.1.2 root 6051: ASC_ASSERT((REQP) REQPNEXT(last_scp) != NULL);
6052: for (tscp = (REQP) REQPNEXT(last_scp);
6053: tscp;
6054: tscp = (REQP) REQPNEXT(tscp)) {
1.1 root 6055: tscp->result = HOST_BYTE(DID_RESET);
6056: }
6057: last_scp = new_last_scp;
6058: }
6059: }
6060:
6061: /* Save the time of the most recently completed reset. */
6062: boardp->last_reset = jiffies;
6063:
6064: /* Clear reset flag. */
6065: boardp->flags &= ~ASC_HOST_IN_RESET;
6066:
6067: /*
6068: * Start any waiting commands for the board.
6069: */
6070: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6071: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6072: asc_execute_queue(&boardp->waiting);
6073: }
6074: ret = SCSI_RESET_SUCCESS;
6075: }
6076:
6077: /* Interrupts could be enabled here. */
6078:
6079: ASC_ASSERT(do_scsi_done != ASC_ERROR);
6080: ASC_ASSERT(scp_found != ASC_ERROR);
6081: if (do_scsi_done == ASC_TRUE) {
6082: if (scp->scsi_done == NULL) {
6083: ASC_PRINT1(
6084: "advansys_reset: reset request scsi_done() is NULL, %x\n",
6085: (unsigned) scp);
6086: } else {
6087: if (scp_found == ASC_FALSE) {
6088: ASC_PRINT1(
6089: "advansys_reset: reset request not active or waiting, completing anyway %x\n",
6090: (unsigned) scp);
6091: }
6092: ASC_STATS(scp->host, done);
6093: scp->scsi_done(scp);
6094: }
6095: }
6096:
6097: /*
6098: * It is possible for the request done function to re-enable
6099: * interrupts without confusing the driver. But here interrupts
6100: * aren't enabled until requests have been completed.
6101: */
6102: if (done_scp != NULL) {
6103: asc_scsi_done_list(done_scp);
6104: }
6105:
6106: ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
6107:
6108: /* Re-enable interrupts, if they were enabled on entry. */
6109: restore_flags(flags);
6110:
6111: ASC_ASSERT(ret != ASC_ERROR);
6112: return ret;
6113: }
6114:
6115: /*
6116: * advansys_biosparam()
6117: *
6118: * Translate disk drive geometry if the "BIOS greater than 1 GB"
6119: * support is enabled for a drive.
6120: *
6121: * ip (information pointer) is an int array with the following definition:
6122: * ip[0]: heads
6123: * ip[1]: sectors
6124: * ip[2]: cylinders
6125: */
6126: int
6127: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
6128: advansys_biosparam(Disk *dp, int dep, int ip[])
6129: #else /* version >= v1.3.0 */
6130: advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
6131: #endif /* version >= v1.3.0 */
6132: {
6133: asc_board_t *boardp;
6134:
6135: ASC_DBG(1, "advansys_biosparam: begin\n");
6136: ASC_STATS(dp->device->host, biosparam);
6137: boardp = ASC_BOARDP(dp->device->host);
6138: if (ASC_NARROW_BOARD(boardp)) {
6139: if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
6140: ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
6141: ip[0] = 255;
6142: ip[1] = 63;
6143: } else {
6144: ip[0] = 64;
6145: ip[1] = 32;
6146: }
6147: } else {
6148: if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
6149: BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) {
6150: ip[0] = 255;
6151: ip[1] = 63;
6152: } else {
6153: ip[0] = 64;
6154: ip[1] = 32;
6155: }
6156: }
6157: ip[2] = dp->capacity / (ip[0] * ip[1]);
6158: ASC_DBG(1, "advansys_biosparam: end\n");
6159: return 0;
6160: }
6161:
6162: /*
6163: * advansys_setup()
6164: *
6165: * This function is called from init/main.c at boot time.
6166: * It it passed LILO parameters that can be set from the
6167: * LILO command line or in /etc/lilo.conf.
6168: *
6169: * It is used by the AdvanSys driver to either disable I/O
6170: * port scanning or to limit scanning to 1 - 4 I/O ports.
6171: * Regardless of the option setting EISA and PCI boards
6172: * will still be searched for and detected. This option
6173: * only affects searching for ISA and VL boards.
6174: *
6175: * If ADVANSYS_DEBUG is defined the driver debug level may
6176: * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
6177: *
6178: * Examples:
6179: * 1. Eliminate I/O port scanning:
6180: * boot: linux advansys=
6181: * or
6182: * boot: linux advansys=0x0
6183: * 2. Limit I/O port scanning to one I/O port:
6184: * boot: linux advansys=0x110
6185: * 3. Limit I/O port scanning to four I/O ports:
6186: * boot: linux advansys=0x110,0x210,0x230,0x330
6187: * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
6188: * set the driver debug level to 2.
6189: * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
6190: *
6191: * ints[0] - number of arguments
6192: * ints[1] - first argument
6193: * ints[2] - second argument
6194: * ...
6195: */
6196: ASC_INITFUNC(
6197: void
6198: advansys_setup(char *str, int *ints)
6199: )
6200: {
6201: int i;
6202:
6203: if (asc_iopflag == ASC_TRUE) {
6204: printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
6205: return;
6206: }
6207:
6208: asc_iopflag = ASC_TRUE;
6209:
6210: if (ints[0] > ASC_NUM_IOPORT_PROBE) {
6211: #ifdef ADVANSYS_DEBUG
6212: if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
6213: (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
6214: asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
6215: } else {
6216: #endif /* ADVANSYS_DEBUG */
6217: printk("AdvanSys SCSI: only %d I/O ports accepted\n",
6218: ASC_NUM_IOPORT_PROBE);
6219: #ifdef ADVANSYS_DEBUG
6220: }
6221: #endif /* ADVANSYS_DEBUG */
6222: }
6223:
6224: #ifdef ADVANSYS_DEBUG
6225: ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
6226: for (i = 1; i < ints[0]; i++) {
6227: ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
6228: }
6229: ASC_DBG(1, "\n");
6230: #endif /* ADVANSYS_DEBUG */
6231:
6232: for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
6233: asc_ioport[i-1] = ints[i];
6234: ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
6235: i - 1, asc_ioport[i-1]);
6236: }
6237: }
6238:
6239:
6240: /*
6241: * --- Loadable Driver Support
6242: */
6243:
6244: #ifdef MODULE
6245: Scsi_Host_Template driver_template = ADVANSYS;
6246: # include "scsi_module.c"
6247: #endif /* MODULE */
6248:
6249:
6250: /*
6251: * --- Miscellaneous Driver Functions
6252: */
6253:
6254: /*
6255: * First-level interrupt handler.
6256: *
6257: * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting
6258: * adapter's asc_board_t. Because all boards are currently checked
6259: * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id'
6260: * could be used to identify an interrupt passed to the AdvanSys driver,
6261: * which is for a device sharing an interrupt with an AdvanSys adapter.
6262: */
6263: STATIC void
6264: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
6265: advansys_interrupt(int irq, struct pt_regs *regs)
6266: #else /* version >= v1.3.70 */
6267: advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
6268: #endif /* version >= v1.3.70 */
6269: {
6270: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
1.1.1.2 root 6271: long flags;
1.1 root 6272: #else /* version >= v2.1.95 */
6273: unsigned long flags;
6274: #endif /* version >= v2.1.95 */
6275: int i;
6276: asc_board_t *boardp;
6277: Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
6278: Scsi_Cmnd *new_last_scp;
6279:
6280: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6281: /* Disable interrupts, if they aren't already disabled. */
6282: save_flags(flags);
6283: cli();
6284: #else /* version >= v2.1.95 */
6285: /*
6286: * Disable interrupts, if they aren't already disabled and acquire
6287: * the I/O spinlock.
6288: */
6289: spin_lock_irqsave(&io_request_lock, flags);
6290: #endif /* version >= v2.1.95 */
6291:
6292: ASC_DBG(1, "advansys_interrupt: begin\n");
6293:
6294: /*
6295: * Check for interrupts on all boards.
6296: * AscISR() will call asc_isr_callback().
6297: */
6298: for (i = 0; i < asc_board_count; i++) {
6299: boardp = ASC_BOARDP(asc_host[i]);
6300: ASC_DBG2(2, "advansys_interrupt: i %d, boardp %lx\n",
6301: i, (ulong) boardp)
6302: if (ASC_NARROW_BOARD(boardp)) {
6303: /*
6304: * Narrow Board
6305: */
6306: if (AscIsIntPending(asc_host[i]->io_port)) {
6307: ASC_STATS(asc_host[i], interrupt);
6308: ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
6309: AscISR(&boardp->dvc_var.asc_dvc_var);
6310: }
6311: } else {
6312: /*
6313: * Wide Board
6314: */
6315: ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
6316: if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
6317: ASC_STATS(asc_host[i], interrupt);
6318: }
6319: }
6320:
6321: /*
6322: * Start waiting requests and create a list of completed requests.
6323: *
6324: * If a reset or abort request is being performed for the board,
6325: * the reset or abort handler will complete pending requests after
6326: * it has completed.
6327: */
6328: if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) {
6329: ASC_DBG2(1, "advansys_interrupt: done_scp %lx, last_scp %lx\n",
6330: (ulong) done_scp, (ulong) last_scp);
6331:
6332: /* Start any waiting commands for the board. */
6333: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
6334: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
6335: asc_execute_queue(&boardp->waiting);
6336: }
6337:
6338: /*
6339: * Add to the list of requests that must be completed.
6340: *
6341: * 'done_scp' will always be NULL on the first iteration
6342: * of this loop. 'last_scp' is set at the same time as
6343: * 'done_scp'.
6344: */
6345: if (done_scp == NULL) {
6346: done_scp = asc_dequeue_list(&boardp->done, &last_scp,
6347: ASC_TID_ALL);
6348: } else {
6349: ASC_ASSERT(last_scp != NULL);
1.1.1.2 root 6350: REQPNEXT(last_scp) =
6351: (unsigned char *) asc_dequeue_list(&boardp->done,
6352: &new_last_scp,
6353: ASC_TID_ALL);
1.1 root 6354: if (new_last_scp != NULL) {
6355: ASC_ASSERT(REQPNEXT(last_scp) != NULL);
6356: last_scp = new_last_scp;
6357: }
6358: }
6359: }
6360: }
6361:
6362: /* Interrupts could be enabled here. */
6363:
6364: /*
6365: * It is possible for the request done function to re-enable
6366: * interrupts without confusing the driver. But here the
6367: * original flags aren't restored until all requests have been
6368: * completed.
6369: */
6370: asc_scsi_done_list(done_scp);
6371:
6372: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
6373: /*
6374: * Restore the original flags which will enable interrupts
6375: * if and only if they were enabled on entry.
6376: */
6377: restore_flags(flags);
6378: #else /* version >= v2.1.95 */
6379: /*
6380: * Release the I/O spinlock and restore the original flags
6381: * which will enable interrupts if and only if they were
6382: * enabled on entry.
6383: */
6384: spin_unlock_irqrestore(&io_request_lock, flags);
6385: #endif /* version >= v2.1.95 */
6386:
6387: ASC_DBG(1, "advansys_interrupt: end\n");
6388: return;
6389: }
6390:
6391: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
6392: /*
6393: * Set the number of commands to queue per device for the
6394: * specified host adapter.
6395: */
6396: STATIC void
6397: advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
6398: {
6399: Scsi_Device *device;
6400: asc_board_t *boardp;
6401:
6402: boardp = ASC_BOARDP(shp);
6403: boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
6404: for (device = devicelist; device != NULL; device = device->next) {
6405: if (device->host != shp) {
6406: continue;
6407: }
6408: /*
6409: * Save a pointer to the device and set its initial/maximum
6410: * queue depth.
6411: */
6412: boardp->device[device->id] = device;
6413: if (ASC_NARROW_BOARD(boardp)) {
6414: device->queue_depth =
6415: boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id];
6416: } else {
6417: device->queue_depth =
6418: boardp->dvc_var.adv_dvc_var.max_dvc_qng;
6419: }
6420: ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
6421: (unsigned) shp, device->id, device->queue_depth);
6422: }
6423: }
6424: #endif /* version >= v1.3.89 */
6425:
6426: /*
6427: * Function used only with polled I/O requests that are initiated by
6428: * advansys_command().
6429: */
6430: STATIC void
6431: advansys_command_done(Scsi_Cmnd *scp)
6432: {
6433: ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
6434: scp->SCp.Status = 1;
6435: }
6436:
6437: /*
6438: * Complete all requests on the singly linked list pointed
6439: * to by 'scp'.
6440: *
6441: * Interrupts can be enabled on entry.
6442: */
6443: STATIC void
6444: asc_scsi_done_list(Scsi_Cmnd *scp)
6445: {
6446: Scsi_Cmnd *tscp;
6447:
6448: ASC_DBG(2, "asc_scsi_done_list: begin\n");
6449: while (scp != NULL) {
6450: ASC_DBG1(3, "asc_scsi_done_list: scp %x\n", (unsigned) scp);
1.1.1.2 root 6451: tscp = (REQP) REQPNEXT(scp);
1.1 root 6452: REQPNEXT(scp) = NULL;
6453: ASC_STATS(scp->host, done);
6454: ASC_ASSERT(scp->scsi_done != NULL);
6455: scp->scsi_done(scp);
6456: scp = tscp;
6457: }
6458: ASC_DBG(2, "asc_scsi_done_list: done\n");
6459: return;
6460: }
6461:
6462: /*
6463: * Execute a single 'Scsi_Cmnd'.
6464: *
6465: * The function 'done' is called when the request has been completed.
6466: *
6467: * Scsi_Cmnd:
6468: *
6469: * host - board controlling device
6470: * device - device to send command
6471: * target - target of device
6472: * lun - lun of device
6473: * cmd_len - length of SCSI CDB
6474: * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
6475: * use_sg - if non-zero indicates scatter-gather request with use_sg elements
6476: *
6477: * if (use_sg == 0) {
6478: * request_buffer - buffer address for request
6479: * request_bufflen - length of request buffer
6480: * } else {
6481: * request_buffer - pointer to scatterlist structure
6482: * }
6483: *
6484: * sense_buffer - sense command buffer
6485: *
6486: * result (4 bytes of an int):
6487: * Byte Meaning
6488: * 0 SCSI Status Byte Code
6489: * 1 SCSI One Byte Message Code
6490: * 2 Host Error Code
6491: * 3 Mid-Level Error Code
6492: *
6493: * host driver fields:
6494: * SCp - Scsi_Pointer used for command processing status
6495: * scsi_done - used to save caller's done function
6496: * host_scribble - used for pointer to another Scsi_Cmnd
6497: *
6498: * If this function returns ASC_NOERROR or ASC_ERROR the request
6499: * has been enqueued on the board's 'done' queue and must be
6500: * completed by the caller.
6501: *
6502: * If ASC_BUSY is returned the request must be enqueued by the
6503: * caller and re-tried later.
6504: */
6505: STATIC int
6506: asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
6507: {
6508: asc_board_t *boardp;
6509: ASC_DVC_VAR *asc_dvc_varp;
6510: ADV_DVC_VAR *adv_dvc_varp;
6511: ADV_SCSI_REQ_Q *adv_scsiqp;
6512: Scsi_Device *device;
6513: int ret;
6514:
6515: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
6516: ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
6517: (unsigned) scp, (unsigned) scp->scsi_done);
6518:
6519: boardp = ASC_BOARDP(scp->host);
6520: device = boardp->device[scp->target];
6521:
6522: if (ASC_NARROW_BOARD(boardp)) {
6523: /*
6524: * Build and execute Narrow Board request.
6525: */
6526:
6527: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
6528:
6529: /*
6530: * Build Asc Library request structure using the
6531: * global structures 'asc_scsi_req' and 'asc_sg_head'.
6532: *
6533: * asc_build_req() can not return ASC_BUSY.
6534: */
6535: if (asc_build_req(boardp, scp) == ASC_ERROR) {
6536: ASC_STATS(scp->host, build_error);
6537: return ASC_ERROR;
6538: }
6539:
6540: /*
6541: * Execute the command. If there is no error, add the command
6542: * to the active queue.
6543: */
6544: switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
6545: case ASC_NOERROR:
6546: ASC_STATS(scp->host, exe_noerror);
6547: /*
6548: * Increment monotonically increasing per device successful
6549: * request counter. Wrapping doesn't matter.
6550: */
6551: boardp->reqcnt[scp->target]++;
6552:
6553: #if ASC_QUEUE_FLOW_CONTROL
6554: /*
6555: * Conditionally increment the device queue depth.
6556: *
6557: * If no error occurred and there have been 100 consecutive
6558: * successful requests and the current queue depth is less
6559: * than the maximum queue depth, then increment the current
6560: * queue depth.
6561: */
6562: if (boardp->nerrcnt[scp->target]++ > 100) {
6563: boardp->nerrcnt[scp->target] = 0;
6564: if (device != NULL &&
6565: (device->queue_curr_depth < device->queue_depth) &&
6566: (!(boardp->queue_full &
6567: ADV_TID_TO_TIDMASK(scp->target)) ||
6568: (boardp->queue_full_cnt[scp->target] >
6569: device->queue_curr_depth))) {
6570: device->queue_curr_depth++;
6571: }
6572: }
6573: #endif /* ASC_QUEUE_FLOW_CONTROL */
6574: asc_enqueue(&boardp->active, scp, ASC_BACK);
6575: ASC_DBG(1,
6576: "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
6577: break;
6578: case ASC_BUSY:
6579: /* Caller must enqueue request and retry later. */
6580: ASC_STATS(scp->host, exe_busy);
6581: #if ASC_QUEUE_FLOW_CONTROL
6582: /*
6583: * Clear consecutive no error counter and if possible decrement
6584: * queue depth.
6585: */
6586: boardp->nerrcnt[scp->target] = 0;
6587: if (device != NULL && device->queue_curr_depth > 1) {
6588: device->queue_curr_depth--;
6589: }
6590: #endif /* ASC_QUEUE_FLOW_CONTROL */
6591: break;
6592: case ASC_ERROR:
6593: ASC_PRINT2(
6594: "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
6595: boardp->id, asc_dvc_varp->err_code);
6596: ASC_STATS(scp->host, exe_error);
6597: #if ASC_QUEUE_FLOW_CONTROL
6598: /* Clear consecutive no error counter. */
6599: boardp->nerrcnt[scp->target] = 0;
6600: #endif /* ASC_QUEUE_FLOW_CONTROL */
6601: scp->result = HOST_BYTE(DID_ERROR);
6602: asc_enqueue(&boardp->done, scp, ASC_BACK);
6603: break;
6604: default:
6605: ASC_PRINT2(
6606: "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
6607: boardp->id, asc_dvc_varp->err_code);
6608: ASC_STATS(scp->host, exe_unknown);
6609: #if ASC_QUEUE_FLOW_CONTROL
6610: /* Clear consecutive no error counter. */
6611: boardp->nerrcnt[scp->target] = 0;
6612: #endif /* ASC_QUEUE_FLOW_CONTROL */
6613: scp->result = HOST_BYTE(DID_ERROR);
6614: asc_enqueue(&boardp->done, scp, ASC_BACK);
6615: break;
6616: }
6617: } else {
6618: /*
6619: * Build and execute Wide Board request.
6620: */
6621: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
6622:
6623: /*
6624: * Build and get a pointer to an Adv Library request structure.
6625: *
6626: * If the request is successfully built then send it below,
6627: * otherwise return with an error.
6628: */
6629: switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
6630: case ASC_NOERROR:
6631: ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
6632: break;
6633: case ASC_BUSY:
6634: ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
6635: return ASC_BUSY;
6636: case ASC_ERROR:
6637: default:
6638: ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
6639: ASC_STATS(scp->host, build_error);
6640: return ASC_ERROR;
6641: }
6642:
6643: /*
6644: * Execute the command. If there is no error, add the command
6645: * to the active queue.
6646: */
6647: switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
6648: case ASC_NOERROR:
6649: ASC_STATS(scp->host, exe_noerror);
6650: /*
6651: * Increment monotonically increasing per device successful
6652: * request counter. Wrapping doesn't matter.
6653: */
6654: boardp->reqcnt[scp->target]++;
6655: asc_enqueue(&boardp->active, scp, ASC_BACK);
6656: ASC_DBG(1,
6657: "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
6658: break;
6659: case ASC_BUSY:
6660: /* Caller must enqueue request and retry later. */
6661: ASC_STATS(scp->host, exe_busy);
6662: break;
6663: case ASC_ERROR:
6664: ASC_PRINT2(
6665: "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code %x\n",
6666: boardp->id, adv_dvc_varp->err_code);
6667: ASC_STATS(scp->host, exe_error);
6668: scp->result = HOST_BYTE(DID_ERROR);
6669: asc_enqueue(&boardp->done, scp, ASC_BACK);
6670: break;
6671: default:
6672: ASC_PRINT2(
6673: "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code %x\n",
6674: boardp->id, adv_dvc_varp->err_code);
6675: ASC_STATS(scp->host, exe_unknown);
6676: scp->result = HOST_BYTE(DID_ERROR);
6677: asc_enqueue(&boardp->done, scp, ASC_BACK);
6678: break;
6679: }
6680: }
6681:
6682: ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
6683: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
6684: return ret;
6685: }
6686:
6687: /*
6688: * Build a request structure for the Asc Library (Narrow Board).
6689: *
6690: * The global structures 'asc_scsi_q' and 'asc_sg_head' are
6691: * used to build the request.
6692: *
6693: * If an error occurs, then return ASC_ERROR.
6694: */
6695: STATIC int
6696: asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp)
6697: {
6698: /*
6699: * Mutually exclusive access is required to 'asc_scsi_q' and
6700: * 'asc_sg_head' until after the request is started.
6701: */
6702: memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
6703:
6704: /*
6705: * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
6706: */
6707: asc_scsi_q.q2.srb_ptr = (ulong) scp;
6708:
6709: /*
6710: * Build the ASC_SCSI_Q request.
6711: */
6712: ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
6713: if (scp->cmd_len > ASC_MAX_CDB_LEN) {
6714: scp->cmd_len = ASC_MAX_CDB_LEN;
6715: }
6716: asc_scsi_q.cdbptr = &scp->cmnd[0];
6717: asc_scsi_q.q2.cdb_len = scp->cmd_len;
6718: asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
6719: asc_scsi_q.q1.target_lun = scp->lun;
6720: asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
6721: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6722: asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
6723: #else /* version >= v2.0.0 */
6724: asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
6725: #endif /* version >= v2.0.0 */
6726: asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
6727:
6728: /*
6729: * If there are any outstanding requests for the current target,
6730: * then every 255th request send an ORDERED request. This heuristic
6731: * tries to retain the benefit of request sorting while preventing
6732: * request starvation. 255 is the max number of tags or pending commands
6733: * a device may have outstanding.
6734: *
6735: * The request count is incremented below for every successfully
6736: * started request.
6737: *
6738: */
6739: if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->target] > 0) &&
6740: (boardp->reqcnt[scp->target] % 255) == 0) {
6741: asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
6742: } else {
6743: asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
6744: }
6745:
6746: /*
6747: * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
6748: * buffer command.
6749: */
6750: if (scp->use_sg == 0) {
6751: /*
6752: * CDB request of single contiguous buffer.
6753: */
6754: ASC_STATS(scp->host, cont_cnt);
6755: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6756: asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
6757: #else /* version >= v2.0.0 */
6758: asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
6759: #endif /* version >= v2.0.0 */
6760: asc_scsi_q.q1.data_cnt = scp->request_bufflen;
6761: ASC_STATS_ADD(scp->host, cont_xfer,
6762: ASC_CEILING(scp->request_bufflen, 512));
6763: asc_scsi_q.q1.sg_queue_cnt = 0;
6764: asc_scsi_q.sg_head = NULL;
6765: } else {
6766: /*
6767: * CDB scatter-gather request list.
6768: */
6769: int sgcnt;
6770: struct scatterlist *slp;
6771:
6772: if (scp->use_sg > scp->host->sg_tablesize) {
6773: ASC_PRINT3(
6774: "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
6775: boardp->id, scp->use_sg, scp->host->sg_tablesize);
6776: scp->result = HOST_BYTE(DID_ERROR);
6777: asc_enqueue(&boardp->done, scp, ASC_BACK);
6778: return ASC_ERROR;
6779: }
6780:
6781: ASC_STATS(scp->host, sg_cnt);
6782:
6783: /*
6784: * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
6785: * structure to point to it.
6786: */
6787: memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
6788:
6789: asc_scsi_q.q1.cntl |= QC_SG_HEAD;
6790: asc_scsi_q.sg_head = &asc_sg_head;
6791: asc_scsi_q.q1.data_cnt = 0;
6792: asc_scsi_q.q1.data_addr = 0;
6793: asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
6794: ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt);
6795:
6796: /*
6797: * Convert scatter-gather list into ASC_SG_HEAD list.
6798: */
6799: slp = (struct scatterlist *) scp->request_buffer;
6800: for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
6801: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6802: asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
6803: #else /* version >= v2.0.0 */
6804: asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
6805: #endif /* version >= v2.0.0 */
6806: asc_sg_head.sg_list[sgcnt].bytes = slp->length;
6807: ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
6808: }
6809: }
6810:
6811: ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
6812: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
6813:
6814: return ASC_NOERROR;
6815: }
6816:
6817: /*
6818: * Build a request structure for the Adv Library (Wide Board).
6819: *
6820: * If an adv_req_t can not be allocated to issue the request,
6821: * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
6822: */
6823: STATIC int
6824: adv_build_req(asc_board_t *boardp, Scsi_Cmnd *scp,
6825: ADV_SCSI_REQ_Q **adv_scsiqpp)
6826: {
6827: adv_req_t *reqp;
6828: ADV_SCSI_REQ_Q *scsiqp;
6829: int i;
6830:
6831: /*
6832: * Allocate an adv_req_t structure from the board to execute
6833: * the command.
6834: */
6835: if (boardp->adv_reqp == NULL) {
6836: ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
6837: ASC_STATS(scp->host, adv_build_noreq);
6838: return ASC_BUSY;
6839: } else {
6840: reqp = boardp->adv_reqp;
6841: boardp->adv_reqp = reqp->next_reqp;
6842: reqp->next_reqp = NULL;
6843: }
6844:
6845: /*
6846: * Get 4-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
6847: */
6848: scsiqp = (ADV_SCSI_REQ_Q *) ADV_DWALIGN(&reqp->scsi_req_q);
6849: memset(scsiqp, 0, sizeof(ADV_SCSI_REQ_Q));
6850:
6851: /*
6852: * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
6853: */
6854: scsiqp->srb_ptr = (ulong) reqp;
6855:
6856: /*
6857: * Set the adv_req_t 'cmndp' to point to the Scsi_Cmnd structure.
6858: */
6859: reqp->cmndp = scp;
6860:
6861: /*
6862: * Build the ADV_SCSI_REQ_Q request.
6863: */
6864:
6865: /*
6866: * Set CDB length and copy it to the request structure.
6867: */
6868: ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
6869: if (scp->cmd_len > ASC_MAX_CDB_LEN) {
6870: scp->cmd_len = ASC_MAX_CDB_LEN;
6871: }
6872: scsiqp->cdb_len = scp->cmd_len;
6873: for (i = 0; i < scp->cmd_len; i++) {
6874: scsiqp->cdb[i] = scp->cmnd[i];
6875: }
6876:
6877: scsiqp->target_id = scp->target;
6878: scsiqp->target_lun = scp->lun;
6879:
6880: scsiqp->vsense_addr = (ulong) &scp->sense_buffer[0];
6881: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6882: scsiqp->sense_addr = (ulong) &scp->sense_buffer[0];
6883: #else /* version >= v2.0.0 */
6884: scsiqp->sense_addr = virt_to_bus(&scp->sense_buffer[0]);
6885: #endif /* version >= v2.0.0 */
6886: scsiqp->sense_len = sizeof(scp->sense_buffer);
6887:
6888: /*
6889: * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
6890: * buffer command.
6891: */
6892: scsiqp->data_cnt = scp->request_bufflen;
6893: scsiqp->vdata_addr = (ulong) scp->request_buffer;
6894: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
6895: scsiqp->data_addr = (ulong) scp->request_buffer;
6896: #else /* version >= v2.0.0 */
6897: scsiqp->data_addr = virt_to_bus(scp->request_buffer);
6898: #endif /* version >= v2.0.0 */
6899:
6900: if (scp->use_sg == 0) {
6901: /*
6902: * CDB request of single contiguous buffer.
6903: */
6904: reqp->sgblkp = NULL;
6905: scsiqp->sg_list_ptr = NULL;
6906: ASC_STATS(scp->host, cont_cnt);
6907: ASC_STATS_ADD(scp->host, cont_xfer,
6908: ASC_CEILING(scp->request_bufflen, 512));
6909: } else {
6910: /*
6911: * CDB scatter-gather request list.
6912: */
6913: if (scp->use_sg > ADV_MAX_SG_LIST) {
6914: ASC_PRINT3(
6915: "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
6916: boardp->id, scp->use_sg, scp->host->sg_tablesize);
6917: scp->result = HOST_BYTE(DID_ERROR);
6918: asc_enqueue(&boardp->done, scp, ASC_BACK);
6919:
6920: /*
6921: * Free the 'adv_req_t' structure by adding it back to the
6922: * board free list.
6923: */
6924: reqp->next_reqp = boardp->adv_reqp;
6925: boardp->adv_reqp = reqp;
6926:
6927: return ASC_ERROR;
6928: }
6929:
6930: /*
6931: * Allocate an 'adv_sgblk_t' structure from the board to
6932: * execute the command.
6933: */
6934: if (boardp->adv_sgblkp == NULL) {
6935: ASC_DBG(1, "adv_build_req: no free adv_sgblk_t\n");
6936: ASC_STATS(scp->host, adv_build_nosg);
6937: /*
6938: * Free the 'adv_req_t' structure by adding it back to the
6939: * board free list.
6940: */
6941: reqp->next_reqp = boardp->adv_reqp;
6942: boardp->adv_reqp = reqp;
6943: return ASC_BUSY;
6944: } else {
6945: reqp->sgblkp = boardp->adv_sgblkp;
6946: boardp->adv_sgblkp = reqp->sgblkp->next_sgblkp;
6947: reqp->sgblkp->next_sgblkp = NULL;
6948: }
6949:
6950: /*
6951: * Build scatter-gather list.
6952: */
6953: scsiqp->sg_list_ptr = (ADV_SG_BLOCK *)
6954: ADV_DWALIGN(&reqp->sgblkp->sg_block[0]);
6955:
6956: memset(scsiqp->sg_list_ptr, 0, sizeof(ADV_SG_BLOCK) *
6957: (ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING));
6958:
6959: if (adv_get_sglist(&boardp->dvc_var.adv_dvc_var, scsiqp, scp) ==
6960: ADV_ERROR) {
6961:
6962: /*
6963: * Free the adv_sgblk_t structure, if any, by adding it back
6964: * to the board free list.
6965: */
6966: ASC_ASSERT(reqp->sgblkp != NULL);
6967: reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
6968: boardp->adv_sgblkp = reqp->sgblkp;
6969:
6970: /*
6971: * Free the adv_req_t structure by adding it back to the
6972: * board free list.
6973: */
6974: reqp->next_reqp = boardp->adv_reqp;
6975: boardp->adv_reqp = reqp;
6976:
6977: return ADV_ERROR;
6978: }
6979:
6980: ASC_STATS(scp->host, sg_cnt);
6981: ASC_STATS_ADD(scp->host, sg_elem, scp->use_sg);
6982: }
6983:
6984: ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
6985: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
6986:
6987: *adv_scsiqpp = scsiqp;
6988:
6989: return ASC_NOERROR;
6990: }
6991:
6992: /*
6993: * Build scatter-gather list for Adv Library (Wide Board).
6994: *
6995: * Return:
6996: * ADV_SUCCESS(1) - SG List successfully created
6997: * ADV_ERROR(-1) - SG List creation failed
6998: */
6999: STATIC int
7000: adv_get_sglist(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp,
7001: Scsi_Cmnd *scp)
7002: {
7003: ADV_SG_BLOCK *sg_block; /* virtual address of a SG */
7004: ulong sg_block_next_addr; /* block and its next */
7005: ulong sg_block_physical_addr;
7006: int sg_block_index, i; /* how many SG entries */
7007: struct scatterlist *slp;
7008: int sg_elem_cnt;
7009:
7010: slp = (struct scatterlist *) scp->request_buffer;
7011: sg_elem_cnt = scp->use_sg;
7012:
7013: sg_block = scsiqp->sg_list_ptr;
7014: sg_block_next_addr = (ulong) sg_block; /* allow math operation */
7015: sg_block_physical_addr =
7016: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7017: (ulong) scsiqp->sg_list_ptr;
7018: #else /* version >= v2.0.0 */
7019: virt_to_bus(scsiqp->sg_list_ptr);
7020: #endif /* version >= v2.0.0 */
7021: ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7022: sg_block_physical_addr);
7023: scsiqp->sg_real_addr = sg_block_physical_addr;
7024:
7025: sg_block_index = 0;
7026: do
7027: {
7028: sg_block->first_entry_no = sg_block_index;
7029: for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
7030: {
7031: sg_block->sg_list[i].sg_addr =
7032: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
7033: (ulong) slp->address;
7034: #else /* version >= v2.0.0 */
7035: virt_to_bus(slp->address);
7036: #endif /* version >= v2.0.0 */
7037: sg_block->sg_list[i].sg_count = slp->length;
7038: ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
7039:
7040: if (--sg_elem_cnt == 0)
7041: { /* last entry, get out */
7042: scsiqp->sg_entry_cnt = sg_block_index + i + 1;
7043: sg_block->last_entry_no = sg_block_index + i;
7044: sg_block->sg_ptr = 0L; /* next link = NULL */
7045: return ADV_SUCCESS;
7046: }
7047: slp++;
7048: }
7049: sg_block_next_addr += sizeof(ADV_SG_BLOCK);
7050: sg_block_physical_addr += sizeof(ADV_SG_BLOCK);
7051: ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
7052: sg_block_physical_addr);
7053:
7054: sg_block_index += NO_OF_SG_PER_BLOCK;
7055: sg_block->sg_ptr = (ADV_SG_BLOCK *) sg_block_physical_addr;
7056: sg_block->last_entry_no = sg_block_index - 1;
7057: sg_block = (ADV_SG_BLOCK *) sg_block_next_addr; /* virtual addr */
7058: }
7059: while (1);
7060: /* NOTREACHED */
7061: }
7062:
7063: /*
7064: * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
7065: *
7066: * Interrupt callback function for the Narrow SCSI Asc Library.
7067: */
7068: STATIC void
7069: asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
7070: {
7071: asc_board_t *boardp;
7072: Scsi_Cmnd *scp;
7073: struct Scsi_Host *shp;
7074: int underrun = ASC_FALSE;
7075: int i;
7076:
7077: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7078: ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n",
7079: (unsigned) asc_dvc_varp, (unsigned) qdonep);
7080: ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
7081:
7082: /*
7083: * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7084: * command that has been completed.
7085: */
7086: scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
7087: ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
7088:
7089: if (scp == NULL) {
7090: ASC_PRINT("asc_isr_callback: scp is NULL\n");
7091: return;
7092: }
7093: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7094:
7095: /*
7096: * If the request's host pointer is not valid, display a
7097: * message and return.
7098: */
7099: shp = scp->host;
7100: for (i = 0; i < asc_board_count; i++) {
7101: if (asc_host[i] == shp) {
7102: break;
7103: }
7104: }
7105: if (i == asc_board_count) {
7106: ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n",
7107: (unsigned) scp, (unsigned) shp);
7108: return;
7109: }
7110:
7111: ASC_STATS(shp, callback);
7112: ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
7113:
7114: /*
7115: * If the request isn't found on the active queue, it may
7116: * have been removed to handle a reset or abort request.
7117: * Display a message and return.
7118: */
7119: boardp = ASC_BOARDP(shp);
7120: ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
7121: if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7122: ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
7123: boardp->id, (unsigned) scp);
7124: return;
7125: }
7126:
7127: /*
7128: * Check for an underrun condition.
7129: */
7130: if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
7131: qdonep->remain_bytes <= scp->request_bufflen != 0) {
7132: ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
7133: (unsigned) qdonep->remain_bytes);
7134: underrun = ASC_TRUE;
7135: }
7136:
7137: /*
7138: * 'qdonep' contains the command's ending status.
7139: */
7140: switch (qdonep->d3.done_stat) {
7141: case QD_NO_ERROR:
7142: ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
7143: switch (qdonep->d3.host_stat) {
7144: case QHSTA_NO_ERROR:
7145: scp->result = 0;
7146: break;
7147: default:
7148: /* QHSTA error occurred */
7149: scp->result = HOST_BYTE(DID_ERROR);
7150: break;
7151: }
7152:
7153: /*
7154: * If an INQUIRY command completed successfully, then call
7155: * the AscInquiryHandling() function to set-up the device.
7156: */
7157: if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 &&
7158: (scp->request_bufflen - qdonep->remain_bytes) >= 8)
7159: {
7160: AscInquiryHandling(asc_dvc_varp, scp->target & 0x7,
7161: (ASC_SCSI_INQUIRY *) scp->request_buffer);
7162: }
7163:
7164: /*
7165: * If there was an underrun without any other error,
7166: * set DID_ERROR to indicate the underrun error.
7167: *
7168: * Note: There is no way yet to indicate the number
7169: * of underrun bytes.
7170: */
7171: if (scp->result == 0 && underrun == ASC_TRUE) {
7172: scp->result = HOST_BYTE(DID_UNDERRUN);
7173: }
7174: break;
7175:
7176: case QD_WITH_ERROR:
7177: ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
7178: switch (qdonep->d3.host_stat) {
7179: case QHSTA_NO_ERROR:
7180: if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
7181: ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
7182: ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7183: sizeof(scp->sense_buffer));
7184: /*
7185: * Note: The 'status_byte()' macro used by target drivers
7186: * defined in scsi.h shifts the status byte returned by
7187: * host drivers right by 1 bit. This is why target drivers
7188: * also use right shifted status byte definitions. For
7189: * instance target drivers use CHECK_CONDITION, defined to
7190: * 0x1, instead of the SCSI defined check condition value
7191: * of 0x2. Host drivers are supposed to return the status
7192: * byte as it is defined by SCSI.
7193: */
7194: scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7195: STATUS_BYTE(qdonep->d3.scsi_stat);
7196: } else {
7197: scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
7198: }
7199: break;
7200:
7201: default:
7202: /* QHSTA error occurred */
7203: ASC_DBG1(1, "asc_isr_callback: host_stat %x\n",
7204: qdonep->d3.host_stat);
7205: scp->result = HOST_BYTE(DID_BAD_TARGET);
7206: break;
7207: }
7208: break;
7209:
7210: case QD_ABORTED_BY_HOST:
7211: ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
7212: scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
7213: STATUS_BYTE(qdonep->d3.scsi_stat);
7214: break;
7215:
7216: default:
7217: ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
7218: scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
7219: STATUS_BYTE(qdonep->d3.scsi_stat);
7220: break;
7221: }
7222:
7223: /*
7224: * If the 'init_tidmask' bit isn't already set for the target and the
7225: * current request finished normally, then set the bit for the target
7226: * to indicate that a device is present.
7227: */
7228: if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7229: qdonep->d3.done_stat == QD_NO_ERROR &&
7230: qdonep->d3.host_stat == QHSTA_NO_ERROR) {
7231: boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7232: }
7233:
7234: /*
7235: * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7236: * function, add the command to the end of the board's done queue.
7237: * The done function for the command will be called from
7238: * advansys_interrupt().
7239: */
7240: asc_enqueue(&boardp->done, scp, ASC_BACK);
7241:
7242: return;
7243: }
7244:
7245: /*
7246: * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
7247: *
7248: * Callback function for the Wide SCSI Adv Library.
7249: */
7250: STATIC void
7251: adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
7252: {
7253: asc_board_t *boardp;
7254: adv_req_t *reqp;
7255: Scsi_Cmnd *scp;
7256: struct Scsi_Host *shp;
7257: int underrun = ASC_FALSE;
7258: int i;
7259:
7260: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7261: ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %x, scsiqp %x\n",
7262: (unsigned) adv_dvc_varp, (unsigned) scsiqp);
7263: ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
7264:
7265: /*
7266: * Get the adv_req_t structure for the command that has been
7267: * completed. The adv_req_t structure actually contains the
7268: * completed ADV_SCSI_REQ_Q structure.
7269: */
7270: reqp = (adv_req_t *) scsiqp->srb_ptr;
7271: ASC_DBG1(1, "adv_isr_callback: reqp %x\n", (unsigned) reqp);
7272: if (reqp == NULL) {
7273: ASC_PRINT("adv_isr_callback: reqp is NULL\n");
7274: return;
7275: }
7276:
7277: /*
7278: * Get the Scsi_Cmnd structure and Scsi_Host structure for the
7279: * command that has been completed.
7280: *
7281: * Note: The adv_req_t request structure and adv_sgblk_t structure,
7282: * if any, * dropped, because a board structure pointer can not be
7283: * determined.
7284: */
7285: scp = reqp->cmndp;
7286: ASC_DBG1(1, "adv_isr_callback: scp %x\n", (unsigned) scp);
7287: if (scp == NULL) {
7288: ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
7289: return;
7290: }
7291: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
7292:
7293: /*
7294: * If the request's host pointer is not valid, display a message
7295: * and return.
7296: */
7297: shp = scp->host;
7298: for (i = 0; i < asc_board_count; i++) {
7299: if (asc_host[i] == shp) {
7300: break;
7301: }
7302: }
7303: /*
7304: * Note: If the host structure is not found, the adv_req_t request
7305: * structure and adv_sgblk_t structure, if any, is dropped.
7306: */
7307: if (i == asc_board_count) {
7308: ASC_PRINT2("adv_isr_callback: scp %x has bad host pointer, host %x\n",
7309: (unsigned) scp, (unsigned) shp);
7310: return;
7311: }
7312:
7313: ASC_STATS(shp, callback);
7314: ASC_DBG1(1, "adv_isr_callback: shp %x\n", (unsigned) shp);
7315:
7316: /*
7317: * If the request isn't found on the active queue, it may have been
7318: * removed to handle a reset or abort request. Display a message and
7319: * return.
7320: *
7321: * Note: Because the structure may still be in use don't attempt
7322: * to free the adv_req_t and adv_sgblk_t, if any, structures.
7323: */
7324: boardp = ASC_BOARDP(shp);
7325: ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
7326: if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
7327: ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n",
7328: boardp->id, (unsigned) scp);
7329: return;
7330: }
7331:
7332: /*
7333: * Check for an underrun condition.
7334: */
7335: if (scp->request_bufflen != 0 && scsiqp->data_cnt != 0) {
7336: ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n",
7337: scsiqp->data_cnt);
7338: underrun = ASC_TRUE;
7339: }
7340:
7341: /*
7342: * 'done_status' contains the command's ending status.
7343: */
7344: switch (scsiqp->done_status) {
7345: case QD_NO_ERROR:
7346: ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
7347: switch (scsiqp->host_status) {
7348: case QHSTA_NO_ERROR:
7349: scp->result = 0;
7350: break;
7351: default:
7352: /* QHSTA error occurred. */
7353: ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
7354: scsiqp->host_status);
7355: scp->result = HOST_BYTE(DID_ERROR);
7356: break;
7357: }
7358: /*
7359: * If there was an underrun without any other error,
7360: * set DID_ERROR to indicate the underrun error.
7361: *
7362: * Note: There is no way yet to indicate the number
7363: * of underrun bytes.
7364: */
7365: if (scp->result == 0 && underrun == ASC_TRUE) {
7366: scp->result = HOST_BYTE(DID_UNDERRUN);
7367: }
7368: break;
7369:
7370: case QD_WITH_ERROR:
7371: ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
7372: switch (scsiqp->host_status) {
7373: case QHSTA_NO_ERROR:
7374: if (scsiqp->scsi_status == SS_CHK_CONDITION) {
7375: ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n");
7376: ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
7377: sizeof(scp->sense_buffer));
7378: /*
7379: * Note: The 'status_byte()' macro used by target drivers
7380: * defined in scsi.h shifts the status byte returned by
7381: * host drivers right by 1 bit. This is why target drivers
7382: * also use right shifted status byte definitions. For
7383: * instance target drivers use CHECK_CONDITION, defined to
7384: * 0x1, instead of the SCSI defined check condition value
7385: * of 0x2. Host drivers are supposed to return the status
7386: * byte as it is defined by SCSI.
7387: */
7388: scp->result = DRIVER_BYTE(DRIVER_SENSE) |
7389: STATUS_BYTE(scsiqp->scsi_status);
7390: } else {
7391: scp->result = STATUS_BYTE(scsiqp->scsi_status);
7392: }
7393: break;
7394:
7395: default:
7396: /* Some other QHSTA error occurred. */
7397: ASC_DBG1(1, "adv_isr_callback: host_status %x\n",
7398: scsiqp->host_status);
7399: scp->result = HOST_BYTE(DID_BAD_TARGET);
7400: break;
7401: }
7402: break;
7403:
7404: case QD_ABORTED_BY_HOST:
7405: ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
7406: scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
7407: break;
7408:
7409: default:
7410: ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status);
7411: scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
7412: break;
7413: }
7414:
7415: /*
7416: * If the 'init_tidmask' bit isn't already set for the target and the
7417: * current request finished normally, then set the bit for the target
7418: * to indicate that a device is present.
7419: */
7420: if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
7421: scsiqp->done_status == QD_NO_ERROR &&
7422: scsiqp->host_status == QHSTA_NO_ERROR) {
7423: boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
7424: }
7425:
7426: /*
7427: * Because interrupts may be enabled by the 'Scsi_Cmnd' done
7428: * function, add the command to the end of the board's done queue.
7429: * The done function for the command will be called from
7430: * advansys_interrupt().
7431: */
7432: asc_enqueue(&boardp->done, scp, ASC_BACK);
7433:
7434: /*
7435: * Free the adv_sgblk_t structure, if any, by adding it back
7436: * to the board free list.
7437: */
7438: if (reqp->sgblkp != NULL) {
7439: reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
7440: boardp->adv_sgblkp = reqp->sgblkp;
7441: }
7442:
7443: /*
7444: * Free the adv_req_t structure used with the command by adding
7445: * it back to the board free list.
7446: */
7447: reqp->next_reqp = boardp->adv_reqp;
7448: boardp->adv_reqp = reqp;
7449:
7450: ASC_DBG(1, "adv_isr_callback: done\n");
7451:
7452: return;
7453: }
7454:
7455: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
7456: #ifdef ASC_CONFIG_PCI
7457: /*
7458: * Search for an AdvanSys PCI device in the PCI configuration space.
7459: */
7460: ASC_INITFUNC(
7461: STATIC int
7462: asc_srch_pci_dev(PCI_DEVICE *pciDevice)
7463: )
7464: {
7465: int ret = PCI_DEVICE_NOT_FOUND;
7466:
7467: ASC_DBG(2, "asc_srch_pci_dev: begin\n");
7468:
7469: if (pci_scan_method == -1) {
7470: pci_scan_method = asc_scan_method();
7471: }
7472: pciDevice->type = pci_scan_method;
7473: ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
7474:
7475: ret = asc_pci_find_dev(pciDevice);
7476: ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
7477: if (ret == PCI_DEVICE_FOUND) {
7478: pciDevice->slotNumber = pciDevice->slotFound + 1;
7479: pciDevice->startSlot = pciDevice->slotFound + 1;
7480: } else {
7481: if (pciDevice->bridge > pciDevice->busNumber) {
7482: ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
7483: pciDevice->bridge, pciDevice->busNumber);
7484: pciDevice->busNumber++;
7485: pciDevice->slotNumber = 0;
7486: pciDevice->startSlot = 0;
7487: pciDevice->endSlot = 0x0f;
7488: ret = asc_srch_pci_dev(pciDevice);
7489: ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
7490: }
7491: }
7492:
7493: ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
7494: return ret;
7495: }
7496:
7497: /*
7498: * Determine the access method to be used for 'pciDevice'.
7499: */
7500: ASC_INITFUNC(
7501: STATIC uchar
7502: asc_scan_method(void)
7503: )
7504: {
7505: ushort data;
7506: PCI_DATA pciData;
7507: uchar type;
7508: uchar slot;
7509:
7510: ASC_DBG(2, "asc_scan_method: begin\n");
7511: memset(&pciData, 0, sizeof(pciData));
7512: for (type = 1; type < 3; type++) {
7513: pciData.type = type;
7514: for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
7515: pciData.slot = slot;
7516: data = asc_get_cfg_word(&pciData);
7517: if ((data != 0xFFFF) && (data != 0x0000)) {
7518: ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
7519: return (type);
7520: }
7521: }
7522: }
7523: ASC_DBG1(4, "asc_scan_method: type %d\n", type);
7524: return (type);
7525: }
7526:
7527: /*
7528: * Check for an AdvanSys PCI device in 'pciDevice'.
7529: *
7530: * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
7531: */
7532: ASC_INITFUNC(
7533: STATIC int
7534: asc_pci_find_dev(PCI_DEVICE *pciDevice)
7535: )
7536: {
7537: PCI_DATA pciData;
7538: ushort vendorid, deviceid;
7539: uchar classcode, subclass;
7540: uchar lslot;
7541:
7542: ASC_DBG(3, "asc_pci_find_dev: begin\n");
7543: pciData.type = pciDevice->type;
7544: pciData.bus = pciDevice->busNumber;
7545: pciData.func = pciDevice->devFunc;
7546: lslot = pciDevice->startSlot;
7547: for (; lslot < pciDevice->endSlot; lslot++) {
7548: pciData.slot = lslot;
7549: pciData.offset = VENDORID_OFFSET;
7550: vendorid = asc_get_cfg_word(&pciData);
7551: ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
7552: if (vendorid != 0xffff) {
7553: pciData.offset = DEVICEID_OFFSET;
7554: deviceid = asc_get_cfg_word(&pciData);
7555: ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
7556: if ((vendorid == ASC_PCI_VENDORID) &&
7557: ((deviceid == ASC_PCI_DEVICE_ID_1100) ||
7558: (deviceid == ASC_PCI_DEVICE_ID_1200) ||
7559: (deviceid == ASC_PCI_DEVICE_ID_1300) ||
7560: (deviceid == ASC_PCI_DEVICE_ID_2300))) {
7561: pciDevice->slotFound = lslot;
7562: ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
7563: return PCI_DEVICE_FOUND;
7564: } else {
7565: pciData.offset = SUBCLASS_OFFSET;
7566: subclass = asc_get_cfg_byte(&pciData);
7567: pciData.offset = CLASSCODE_OFFSET;
7568: classcode = asc_get_cfg_byte(&pciData);
7569: if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
7570: (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
7571: pciDevice->bridge++;
7572: }
7573: ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
7574: subclass, classcode);
7575: }
7576: }
7577: }
7578: return PCI_DEVICE_NOT_FOUND;
7579: }
7580:
7581: /*
7582: * Read PCI configuration data into 'pciConfig'.
7583: */
7584: ASC_INITFUNC(
7585: STATIC void
7586: asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
7587: )
7588: {
7589: PCI_DATA pciData;
7590: uchar counter;
7591: uchar *localConfig;
7592:
7593: ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ",
7594: pciDevice->slotFound);
7595:
7596: pciData.type = pciDevice->type;
7597: pciData.bus = pciDevice->busNumber;
7598: pciData.slot = pciDevice->slotFound;
7599: pciData.func = pciDevice->devFunc;
7600: localConfig = (uchar *) pciConfig;
7601:
7602: for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
7603: pciData.offset = counter;
7604: *localConfig = asc_get_cfg_byte(&pciData);
7605: ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
7606: localConfig++;
7607: }
7608: ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
7609: }
7610:
7611: /*
7612: * Read a word (16 bits) from the PCI configuration space.
7613: *
7614: * The configuration mechanism is checked for the correct access method.
7615: */
7616: ASC_INITFUNC(
7617: STATIC ushort
7618: asc_get_cfg_word(PCI_DATA *pciData)
7619: )
7620: {
7621: ushort tmp;
7622: ulong address;
7623: ulong lbus = pciData->bus;
7624: ulong lslot = pciData->slot;
7625: ulong lfunc = pciData->func;
7626: uchar t2CFA, t2CF8;
7627: ulong t1CF8, t1CFC;
7628:
7629: ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
7630: pciData->type, lbus, lslot, lfunc);
7631:
7632: /*
7633: * Check type of configuration mechanism.
7634: */
7635: if (pciData->type == 2) {
7636: /*
7637: * Save registers to be restored later.
7638: */
7639: t2CFA = inp(0xCFA); /* save PCI bus register */
7640: t2CF8 = inp(0xCF8); /* save config space enable register */
7641:
7642: /*
7643: * Write the bus and enable registers.
7644: */
7645: /* set for type 1 cycle, if needed */
7646: outp(0xCFA, pciData->bus);
7647: /* set the function number */
7648: outp(0xCF8, 0x10 | (pciData->func << 1)) ;
7649:
7650: /*
7651: * Read the configuration space type 2 locations.
7652: */
7653: tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
7654:
7655: outp(0xCFA, t2CFA); /* save PCI bus register */
7656: outp(0xCF8, t2CF8); /* save config space enable register */
7657: } else {
7658: /*
7659: * Type 1 or 3 configuration mechanism.
7660: *
7661: * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
7662: */
7663: t1CF8 = inpl(0xCF8);
7664: t1CFC = inpl(0xCFC);
7665:
7666: /*
7667: * enable <31>, bus = <23:16>, slot = <15:11>,
7668: * func = <10:8>, reg = <7:2>
7669: */
7670: address = (ulong) ((lbus << 16) | (lslot << 11) |
7671: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
7672:
7673: /*
7674: * Write out the address to CONFIG_ADDRESS.
7675: */
7676: outpl(0xCF8, address);
7677:
7678: /*
7679: * Read in word from CONFIG_DATA.
7680: */
7681: tmp = (ushort) ((inpl(0xCFC) >>
7682: ((pciData->offset & 2) * 8)) & 0xFFFF);
7683:
7684: /*
7685: * Restore registers.
7686: */
7687: outpl(0xCF8, t1CF8);
7688: outpl(0xCFC, t1CFC);
7689: }
7690: ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
7691: return tmp;
7692: }
7693:
7694: /*
7695: * Reads a byte from the PCI configuration space.
7696: *
7697: * The configuration mechanism is checked for the correct access method.
7698: */
7699: ASC_INITFUNC(
7700: STATIC uchar
7701: asc_get_cfg_byte(PCI_DATA *pciData)
7702: )
7703: {
7704: uchar tmp;
7705: ulong address;
7706: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
7707: uchar t2CFA, t2CF8;
7708: ulong t1CF8, t1CFC;
7709:
7710: ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
7711:
7712: /*
7713: * Check type of configuration mechanism.
7714: */
7715: if (pciData->type == 2) {
7716: /*
7717: * Save registers to be restored later.
7718: */
7719: t2CFA = inp(0xCFA); /* save PCI bus register */
7720: t2CF8 = inp(0xCF8); /* save config space enable register */
7721:
7722: /*
7723: * Write the bus and enable registers.
7724: */
7725: /* set for type 1 cycle, if needed */
7726: outp(0xCFA, pciData->bus);
7727: /* set the function number */
7728: outp(0xCF8, 0x10 | (pciData->func << 1));
7729:
7730: /*
7731: * Read configuration space type 2 locations.
7732: */
7733: tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
7734:
7735: /*
7736: * Restore registers.
7737: */
7738: outp(0xCF8, t2CF8); /* restore the enable register */
7739: outp(0xCFA, t2CFA); /* restore PCI bus register */
7740: } else {
7741: /*
7742: * Type 1 or 3 configuration mechanism.
7743: *
7744: * Save CONFIG_ADDRESS and CONFIG_DATA register values.
7745: */
7746: t1CF8 = inpl(0xCF8);
7747: t1CFC = inpl(0xCFC);
7748:
7749: /*
7750: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
7751: * reg = <7:2>
7752: */
7753: address = (ulong) ((lbus << 16) | (lslot << 11) |
7754: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
7755:
7756: /*
7757: * Write out address to CONFIG_ADDRESS.
7758: */
7759: outpl(0xCF8, address);
7760:
7761: /*
7762: * Read in word from CONFIG_DATA.
7763: */
7764: tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
7765:
7766: /*
7767: * Restore registers.
7768: */
7769: outpl(0xCF8, t1CF8);
7770: outpl(0xCFC, t1CFC);
7771: }
7772: ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
7773: return tmp;
7774: }
7775:
7776: /*
7777: * Write a byte to the PCI configuration space.
7778: */
7779: ASC_INITFUNC(
7780: STATIC void
7781: asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
7782: )
7783: {
7784: ulong tmpl;
7785: ulong address;
7786: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
7787: uchar t2CFA, t2CF8;
7788: ulong t1CF8, t1CFC;
7789:
7790: ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n",
7791: pciData->type, byte_data);
7792:
7793: /*
7794: * Check type of configuration mechanism.
7795: */
7796: if (pciData->type == 2) {
7797:
7798: /*
7799: * Save registers to be restored later.
7800: */
7801: t2CFA = inp(0xCFA); /* save PCI bus register */
7802: t2CF8 = inp(0xCF8); /* save config space enable register */
7803:
7804: /*
7805: * Write bus and enable registers.
7806: */
7807: outp(0xCFA, pciData->bus);
7808:
7809: /*
7810: * Set the function number.
7811: */
7812: outp(0xCF8, 0x10 | (pciData->func << 1));
7813:
7814: /*
7815: * Write the configuration space type 2 locations.
7816: */
7817: outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data);
7818:
7819: /*
7820: * Restore registers.
7821: */
7822: outp(0xCF8, t2CF8); /* restore the enable register */
7823: outp(0xCFA, t2CFA); /* restore PCI bus register */
7824: } else {
7825:
7826: /*
7827: * Type 1 or 3 configuration mechanism.
7828: *
7829: * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
7830: */
7831: t1CF8 = inpl(0xCF8);
7832: t1CFC = inpl(0xCFC);
7833:
7834: /*
7835: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
7836: * reg = <7:2>
7837: */
7838: address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) |
7839: (pciData->offset & 0xFC) | 0x80000000L);
7840: /*
7841: * Write out address to CONFIG_ADDRESS.
7842: */
7843: outpl(0xCF8, address);
7844:
7845: /*
7846: * Write double word to CONFIG_DATA preserving the bytes
7847: * in the double not written.
7848: */
7849: tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8));
7850: outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8)));
7851:
7852: /*
7853: * Restore registers.
7854: */
7855: outpl(0xCF8, t1CF8);
7856: outpl(0xCFC, t1CFC);
7857: }
7858: ASC_DBG(4, "asc_put_cfg_byte: end\n");
7859: }
7860: #endif /* ASC_CONFIG_PCI */
7861: #endif /* version < v2.1.93 */
7862:
7863: /*
7864: * Add a 'REQP' to the end of specified queue. Set 'tidmask'
7865: * to indicate a command is queued for the device.
7866: *
7867: * 'flag' may be either ASC_FRONT or ASC_BACK.
7868: *
7869: * 'REQPNEXT(reqp)' returns reqp's next pointer.
7870: */
7871: STATIC void
7872: asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
7873: {
7874: int tid;
7875:
7876: ASC_DBG3(3, "asc_enqueue: ascq %x, reqp %x, flag %d\n",
7877: (unsigned) ascq, (unsigned) reqp, flag);
7878: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7879: ASC_ASSERT(reqp != NULL);
7880: ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
7881: tid = REQPTID(reqp);
7882: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
7883: if (flag == ASC_FRONT) {
1.1.1.2 root 7884: REQPNEXT(reqp) = (unsigned char *) ascq->q_first[tid];
1.1 root 7885: ascq->q_first[tid] = reqp;
7886: /* If the queue was empty, set the last pointer. */
7887: if (ascq->q_last[tid] == NULL) {
7888: ascq->q_last[tid] = reqp;
7889: }
7890: } else { /* ASC_BACK */
7891: if (ascq->q_last[tid] != NULL) {
1.1.1.2 root 7892: REQPNEXT(ascq->q_last[tid]) = (unsigned char *) reqp;
1.1 root 7893: }
7894: ascq->q_last[tid] = reqp;
7895: REQPNEXT(reqp) = NULL;
7896: /* If the queue was empty, set the first pointer. */
7897: if (ascq->q_first[tid] == NULL) {
7898: ascq->q_first[tid] = reqp;
7899: }
7900: }
7901: /* The queue has at least one entry, set its bit. */
7902: ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
7903: #ifdef ADVANSYS_STATS
7904: /* Maintain request queue statistics. */
7905: ascq->q_tot_cnt[tid]++;
7906: ascq->q_cur_cnt[tid]++;
7907: if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
7908: ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
7909: ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
7910: tid, ascq->q_max_cnt[tid]);
7911: }
7912: REQPTIME(reqp) = REQTIMESTAMP();
7913: #endif /* ADVANSYS_STATS */
7914: ASC_DBG1(3, "asc_enqueue: reqp %x\n", (unsigned) reqp);
7915: return;
7916: }
7917:
7918: /*
7919: * Return first queued 'REQP' on the specified queue for
7920: * the specified target device. Clear the 'tidmask' bit for
7921: * the device if no more commands are left queued for it.
7922: *
7923: * 'REQPNEXT(reqp)' returns reqp's next pointer.
7924: */
7925: STATIC REQP
7926: asc_dequeue(asc_queue_t *ascq, int tid)
7927: {
7928: REQP reqp;
7929:
7930: ASC_DBG2(3, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid);
7931: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7932: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
7933: if ((reqp = ascq->q_first[tid]) != NULL) {
7934: ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
1.1.1.2 root 7935: ascq->q_first[tid] = (REQP) REQPNEXT(reqp);
1.1 root 7936: /* If the queue is empty, clear its bit and the last pointer. */
7937: if (ascq->q_first[tid] == NULL) {
7938: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
7939: ASC_ASSERT(ascq->q_last[tid] == reqp);
7940: ascq->q_last[tid] = NULL;
7941: }
7942: #ifdef ADVANSYS_STATS
7943: /* Maintain request queue statistics. */
7944: ascq->q_cur_cnt[tid]--;
7945: ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
7946: REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
7947: #endif /* ADVANSYS_STATS */
7948: }
7949: ASC_DBG1(3, "asc_dequeue: reqp %x\n", (unsigned) reqp);
7950: return reqp;
7951: }
7952:
7953: /*
7954: * Return a pointer to a singly linked list of all the requests queued
7955: * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
7956: *
7957: * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
7958: * the last request returned in the singly linked list.
7959: *
7960: * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
7961: * then all queued requests are concatenated into one list and
7962: * returned.
7963: *
7964: * Note: If 'lastpp' is used to append a new list to the end of
7965: * an old list, only change the old list last pointer if '*lastpp'
7966: * (or the function return value) is not NULL, i.e. use a temporary
7967: * variable for 'lastpp' and check its value after the function return
7968: * before assigning it to the list last pointer.
7969: *
7970: * Unfortunately collecting queuing time statistics adds overhead to
7971: * the function that isn't inherent to the function's algorithm.
7972: */
7973: STATIC REQP
7974: asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
7975: {
7976: REQP firstp, lastp;
7977: int i;
7978:
7979: ASC_DBG2(3, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid);
7980: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
7981: ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
7982:
7983: /*
7984: * If 'tid' is not ASC_TID_ALL, return requests only for
7985: * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
7986: * requests for all tids.
7987: */
7988: if (tid != ASC_TID_ALL) {
7989: /* Return all requests for the specified 'tid'. */
7990: if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
7991: /* List is empty; Set first and last return pointers to NULL. */
7992: firstp = lastp = NULL;
7993: } else {
7994: firstp = ascq->q_first[tid];
7995: lastp = ascq->q_last[tid];
7996: ascq->q_first[tid] = ascq->q_last[tid] = NULL;
7997: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
7998: #ifdef ADVANSYS_STATS
7999: {
8000: REQP reqp;
8001: ascq->q_cur_cnt[tid] = 0;
1.1.1.2 root 8002: for (reqp = firstp; reqp; reqp = (REQP) REQPNEXT(reqp)) {
1.1 root 8003: REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
8004: }
8005: }
8006: #endif /* ADVANSYS_STATS */
8007: }
8008: } else {
8009: /* Return all requests for all tids. */
8010: firstp = lastp = NULL;
8011: for (i = 0; i <= ADV_MAX_TID; i++) {
8012: if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
8013: if (firstp == NULL) {
8014: firstp = ascq->q_first[i];
8015: lastp = ascq->q_last[i];
8016: } else {
8017: ASC_ASSERT(lastp != NULL);
1.1.1.2 root 8018: REQPNEXT(lastp) = (unsigned char *) ascq->q_first[i];
1.1 root 8019: lastp = ascq->q_last[i];
8020: }
8021: ascq->q_first[i] = ascq->q_last[i] = NULL;
8022: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8023: #ifdef ADVANSYS_STATS
8024: ascq->q_cur_cnt[i] = 0;
8025: #endif /* ADVANSYS_STATS */
8026: }
8027: }
8028: #ifdef ADVANSYS_STATS
8029: {
8030: REQP reqp;
1.1.1.2 root 8031: for (reqp = firstp; reqp; reqp = (REQP) REQPNEXT(reqp)) {
1.1 root 8032: REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
8033: }
8034: }
8035: #endif /* ADVANSYS_STATS */
8036: }
8037: if (lastpp) {
8038: *lastpp = lastp;
8039: }
8040: ASC_DBG1(3, "asc_dequeue_list: firstp %x\n", (unsigned) firstp);
8041: return firstp;
8042: }
8043:
8044: /*
8045: * Remove the specified 'REQP' from the specified queue for
8046: * the specified target device. Clear the 'tidmask' bit for the
8047: * device if no more commands are left queued for it.
8048: *
8049: * 'REQPNEXT(reqp)' returns reqp's the next pointer.
8050: *
8051: * Return ASC_TRUE if the command was found and removed,
8052: * otherwise return ASC_FALSE.
8053: */
8054: STATIC int
8055: asc_rmqueue(asc_queue_t *ascq, REQP reqp)
8056: {
8057: REQP currp, prevp;
8058: int tid;
8059: int ret = ASC_FALSE;
8060:
8061: ASC_DBG2(3, "asc_rmqueue: ascq %x, reqp %x\n",
8062: (unsigned) ascq, (unsigned) reqp);
8063: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8064: ASC_ASSERT(reqp != NULL);
8065:
8066: tid = REQPTID(reqp);
8067: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8068:
8069: /*
8070: * Handle the common case of 'reqp' being the first
8071: * entry on the queue.
8072: */
8073: if (reqp == ascq->q_first[tid]) {
8074: ret = ASC_TRUE;
1.1.1.2 root 8075: ascq->q_first[tid] = (REQP) REQPNEXT(reqp);
1.1 root 8076: /* If the queue is now empty, clear its bit and the last pointer. */
8077: if (ascq->q_first[tid] == NULL) {
8078: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
8079: ASC_ASSERT(ascq->q_last[tid] == reqp);
8080: ascq->q_last[tid] = NULL;
8081: }
8082: } else if (ascq->q_first[tid] != NULL) {
8083: ASC_ASSERT(ascq->q_last[tid] != NULL);
8084: /*
8085: * Because the case of 'reqp' being the first entry has been
8086: * handled above and it is known the queue is not empty, if
8087: * 'reqp' is found on the queue it is guaranteed the queue will
8088: * not become empty and that 'q_first[tid]' will not be changed.
8089: *
8090: * Set 'prevp' to the first entry, 'currp' to the second entry,
8091: * and search for 'reqp'.
8092: */
1.1.1.2 root 8093: for (prevp = ascq->q_first[tid], currp = (REQP) REQPNEXT(prevp);
8094: currp; prevp = currp, currp = (REQP) REQPNEXT(currp)) {
1.1 root 8095: if (currp == reqp) {
8096: ret = ASC_TRUE;
8097: REQPNEXT(prevp) = REQPNEXT(currp);
8098: REQPNEXT(reqp) = NULL;
8099: if (ascq->q_last[tid] == reqp) {
8100: ascq->q_last[tid] = prevp;
8101: }
8102: break;
8103: }
8104: }
8105: }
8106: #ifdef ADVANSYS_STATS
8107: /* Maintain request queue statistics. */
8108: if (ret == ASC_TRUE) {
8109: ascq->q_cur_cnt[tid]--;
8110: REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
8111: }
8112: ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
8113: #endif /* ADVANSYS_STATS */
8114: ASC_DBG2(3, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret);
8115: return ret;
8116: }
8117:
8118: /*
8119: * If the specified 'REQP' is queued on the specified queue for
8120: * the specified target device, return ASC_TRUE.
8121: */
8122: STATIC int
8123: asc_isqueued(asc_queue_t *ascq, REQP reqp)
8124: {
8125: REQP treqp;
8126: int tid;
8127: int ret = ASC_FALSE;
8128:
8129: ASC_DBG2(3, "asc_isqueued: ascq %x, reqp %x\n",
8130: (unsigned) ascq, (unsigned) reqp);
8131: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8132: ASC_ASSERT(reqp != NULL);
8133:
8134: tid = REQPTID(reqp);
8135: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
8136:
1.1.1.2 root 8137: for (treqp = ascq->q_first[tid]; treqp; treqp = (REQP) REQPNEXT(treqp)) {
1.1 root 8138: ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
8139: if (treqp == reqp) {
8140: ret = ASC_TRUE;
8141: break;
8142: }
8143: }
8144: ASC_DBG1(3, "asc_isqueued: ret %x\n", ret);
8145: return ret;
8146: }
8147:
8148: /*
8149: * Execute as many queued requests as possible for the specified queue.
8150: *
8151: * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd.
8152: */
8153: STATIC void
8154: asc_execute_queue(asc_queue_t *ascq)
8155: {
8156: ADV_SCSI_BIT_ID_TYPE scan_tidmask;
8157: REQP reqp;
8158: int i;
8159:
8160: ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq);
8161: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
8162: /*
8163: * Execute queued commands for devices attached to
8164: * the current board in round-robin fashion.
8165: */
8166: scan_tidmask = ascq->q_tidmask;
8167: do {
8168: for (i = 0; i <= ADV_MAX_TID; i++) {
8169: if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
8170: if ((reqp = asc_dequeue(ascq, i)) == NULL) {
8171: scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8172: } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp)
8173: == ASC_BUSY) {
8174: scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
8175: /* Put the request back at front of the list. */
8176: asc_enqueue(ascq, reqp, ASC_FRONT);
8177: }
8178: }
8179: }
8180: } while (scan_tidmask);
8181: return;
8182: }
8183:
8184: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
8185: /*
8186: * asc_prt_board_devices()
8187: *
8188: * Print driver information for devices attached to the board.
8189: *
8190: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8191: * cf. asc_prt_line().
8192: *
8193: * Return the number of characters copied into 'cp'. No more than
8194: * 'cplen' characters will be copied to 'cp'.
8195: */
8196: STATIC int
8197: asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
8198: {
8199: asc_board_t *boardp;
8200: int leftlen;
8201: int totlen;
8202: int len;
8203: int chip_scsi_id;
8204: int i;
8205:
8206: boardp = ASC_BOARDP(shp);
8207: leftlen = cplen;
8208: totlen = len = 0;
8209:
8210: len = asc_prt_line(cp, leftlen,
8211: "\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no);
8212: ASC_PRT_NEXT();
8213:
8214: if (ASC_NARROW_BOARD(boardp)) {
8215: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8216: } else {
8217: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8218: }
8219:
8220: len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
8221: ASC_PRT_NEXT();
8222: for (i = 0; i <= ADV_MAX_TID; i++) {
8223: if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
8224: len = asc_prt_line(cp, leftlen, " %X,", i);
8225: ASC_PRT_NEXT();
8226: }
8227: }
8228: len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
8229: ASC_PRT_NEXT();
8230:
8231: return totlen;
8232: }
8233:
8234: /*
8235: * Display Wide Board BIOS Information.
8236: */
8237: STATIC int
8238: asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen)
8239: {
8240: asc_board_t *boardp;
8241: int leftlen;
8242: int totlen;
8243: int len;
8244: int upgrade = ASC_FALSE;
8245: ushort major, minor, letter;
8246:
8247: boardp = ASC_BOARDP(shp);
8248: leftlen = cplen;
8249: totlen = len = 0;
8250:
8251: len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
8252: ASC_PRT_NEXT();
8253:
8254: /*
8255: * If the BIOS saved a valid signature, then fill in
8256: * the BIOS code segment base address.
8257: */
8258: if (boardp->bios_signature != 0x55AA) {
8259: len = asc_prt_line(cp, leftlen, "Pre-3.1\n");
8260: ASC_PRT_NEXT();
8261: upgrade = ASC_TRUE;
8262: } else {
8263: major = (boardp->bios_version >> 12) & 0xF;
8264: minor = (boardp->bios_version >> 8) & 0xF;
8265: letter = (boardp->bios_version & 0xFF);
8266:
8267: len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
8268: major, minor, letter >= 26 ? '?' : letter + 'A');
8269: ASC_PRT_NEXT();
8270:
8271: /* Current available ROM BIOS release is 3.1C. */
8272: if (major < 3 || (major <= 3 && minor < 1) ||
8273: (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) {
8274: upgrade = ASC_TRUE;
8275: }
8276: }
8277: if (upgrade == ASC_TRUE) {
8278: len = asc_prt_line(cp, leftlen,
8279: "Newer version of ROM BIOS available: ftp://ftp.advansys.com/pub\n");
8280: ASC_PRT_NEXT();
8281: }
8282:
8283: return totlen;
8284: }
8285:
8286: /*
8287: * Add serial number to information bar if signature AAh
8288: * is found in at bit 15-9 (7 bits) of word 1.
8289: *
8290: * Serial Number consists fo 12 alpha-numeric digits.
8291: *
8292: * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
8293: * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
8294: * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
8295: * 5 - Product revision (A-J) Word0: " "
8296: *
8297: * Signature Word1: 15-9 (7 bits)
8298: * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
8299: * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
8300: *
8301: * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
8302: *
8303: * Note 1: Only production cards will have a serial number.
8304: *
8305: * Note 2: Signature is most significant 7 bits (0xFE).
8306: *
8307: * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
8308: */
8309: STATIC int
8310: asc_get_eeprom_string(ushort *serialnum, uchar *cp)
8311: {
8312: ushort w, num;
8313:
8314: if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) {
8315: return ASC_FALSE;
8316: } else {
8317: /*
8318: * First word - 6 digits.
8319: */
8320: w = serialnum[0];
8321:
8322: /* Product type - 1st digit. */
8323: if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
8324: /* Product type is P=Prototype */
8325: *cp += 0x8;
8326: }
8327: cp++;
8328:
8329: /* Manufacturing location - 2nd digit. */
8330: *cp++ = 'A' + ((w & 0x1C00) >> 10);
8331:
8332: /* Product ID - 3rd, 4th digits. */
8333: num = w & 0x3FF;
8334: *cp++ = '0' + (num / 100);
8335: num %= 100;
8336: *cp++ = '0' + (num / 10);
8337:
8338: /* Product revision - 5th digit. */
8339: *cp++ = 'A' + (num % 10);
8340:
8341: /*
8342: * Second word
8343: */
8344: w = serialnum[1];
8345:
8346: /*
8347: * Year - 6th digit.
8348: *
8349: * If bit 15 of third word is set, then the
8350: * last digit of the year is greater than 7.
8351: */
8352: if (serialnum[2] & 0x8000) {
8353: *cp++ = '8' + ((w & 0x1C0) >> 6);
8354: } else {
8355: *cp++ = '0' + ((w & 0x1C0) >> 6);
8356: }
8357:
8358: /* Week of year - 7th, 8th digits. */
8359: num = w & 0x003F;
8360: *cp++ = '0' + num / 10;
8361: num %= 10;
8362: *cp++ = '0' + num;
8363:
8364: /*
8365: * Third word
8366: */
8367: w = serialnum[2] & 0x7FFF;
8368:
8369: /* Serial number - 9th digit. */
8370: *cp++ = 'A' + (w / 1000);
8371:
8372: /* 10th, 11th, 12th digits. */
8373: num = w % 1000;
8374: *cp++ = '0' + num / 100;
8375: num %= 100;
8376: *cp++ = '0' + num / 10;
8377: num %= 10;
8378: *cp++ = '0' + num;
8379:
8380: *cp = '\0'; /* Null Terminate the string. */
8381: return ASC_TRUE;
8382: }
8383: }
8384:
8385: /*
8386: * asc_prt_asc_board_eeprom()
8387: *
8388: * Print board EEPROM configuration.
8389: *
8390: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8391: * cf. asc_prt_line().
8392: *
8393: * Return the number of characters copied into 'cp'. No more than
8394: * 'cplen' characters will be copied to 'cp'.
8395: */
8396: STATIC int
8397: asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8398: {
8399: asc_board_t *boardp;
8400: ASC_DVC_VAR *asc_dvc_varp;
8401: int leftlen;
8402: int totlen;
8403: int len;
8404: ASCEEP_CONFIG *ep;
8405: int i;
8406: int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
8407: uchar serialstr[13];
8408:
8409: boardp = ASC_BOARDP(shp);
8410: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
8411: ep = &boardp->eep_config.asc_eep;
8412:
8413: leftlen = cplen;
8414: totlen = len = 0;
8415:
8416: len = asc_prt_line(cp, leftlen,
8417: "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8418: ASC_PRT_NEXT();
8419:
8420: if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) ==
8421: ASC_TRUE) {
8422: len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8423: ASC_PRT_NEXT();
8424: } else {
8425: if (ep->adapter_info[5] == 0xBB) {
8426: len = asc_prt_line(cp, leftlen,
8427: " Default Settings Used for EEPROM-less Adapter.\n");
8428: ASC_PRT_NEXT();
8429: } else {
8430: len = asc_prt_line(cp, leftlen,
8431: " Serial Number Signature Not Present.\n");
8432: ASC_PRT_NEXT();
8433: }
8434: }
8435:
8436: len = asc_prt_line(cp, leftlen,
8437: " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8438: ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng);
8439: ASC_PRT_NEXT();
8440:
8441: len = asc_prt_line(cp, leftlen,
8442: " cntl %x, no_scam %x\n",
8443: ep->cntl, ep->no_scam);
8444: ASC_PRT_NEXT();
8445:
8446: len = asc_prt_line(cp, leftlen,
8447: " Target ID: ");
8448: ASC_PRT_NEXT();
8449: for (i = 0; i <= ASC_MAX_TID; i++) {
8450: len = asc_prt_line(cp, leftlen, " %d", i);
8451: ASC_PRT_NEXT();
8452: }
8453: len = asc_prt_line(cp, leftlen, "\n");
8454: ASC_PRT_NEXT();
8455:
8456: len = asc_prt_line(cp, leftlen,
8457: " Disconnects: ");
8458: ASC_PRT_NEXT();
8459: for (i = 0; i <= ASC_MAX_TID; i++) {
8460: len = asc_prt_line(cp, leftlen, " %c",
8461: (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8462: ASC_PRT_NEXT();
8463: }
8464: len = asc_prt_line(cp, leftlen, "\n");
8465: ASC_PRT_NEXT();
8466:
8467: len = asc_prt_line(cp, leftlen,
8468: " Command Queuing: ");
8469: ASC_PRT_NEXT();
8470: for (i = 0; i <= ASC_MAX_TID; i++) {
8471: len = asc_prt_line(cp, leftlen, " %c",
8472: (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8473: ASC_PRT_NEXT();
8474: }
8475: len = asc_prt_line(cp, leftlen, "\n");
8476: ASC_PRT_NEXT();
8477:
8478: len = asc_prt_line(cp, leftlen,
8479: " Start Motor: ");
8480: ASC_PRT_NEXT();
8481: for (i = 0; i <= ASC_MAX_TID; i++) {
8482: len = asc_prt_line(cp, leftlen, " %c",
8483: (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8484: ASC_PRT_NEXT();
8485: }
8486: len = asc_prt_line(cp, leftlen, "\n");
8487: ASC_PRT_NEXT();
8488:
8489: len = asc_prt_line(cp, leftlen,
8490: " Synchronous Transfer:");
8491: ASC_PRT_NEXT();
8492: for (i = 0; i <= ASC_MAX_TID; i++) {
8493: len = asc_prt_line(cp, leftlen, " %c",
8494: (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8495: ASC_PRT_NEXT();
8496: }
8497: len = asc_prt_line(cp, leftlen, "\n");
8498: ASC_PRT_NEXT();
8499:
8500: if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
8501: len = asc_prt_line(cp, leftlen,
8502: " Host ISA DMA speed: %d MB/S\n",
8503: isa_dma_speed[ep->isa_dma_speed]);
8504: ASC_PRT_NEXT();
8505: }
8506:
8507: return totlen;
8508: }
8509:
8510: /*
8511: * asc_prt_adv_board_eeprom()
8512: *
8513: * Print board EEPROM configuration.
8514: *
8515: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8516: * cf. asc_prt_line().
8517: *
8518: * Return the number of characters copied into 'cp'. No more than
8519: * 'cplen' characters will be copied to 'cp'.
8520: */
8521: STATIC int
8522: asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
8523: {
8524: asc_board_t *boardp;
8525: ADV_DVC_VAR *adv_dvc_varp;
8526: int leftlen;
8527: int totlen;
8528: int len;
8529: int i;
8530: char *termstr;
8531: uchar serialstr[13];
8532: ADVEEP_CONFIG *ep;
8533:
8534: boardp = ASC_BOARDP(shp);
8535: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
8536: ep = &boardp->eep_config.adv_eep;
8537:
8538: leftlen = cplen;
8539: totlen = len = 0;
8540:
8541: len = asc_prt_line(cp, leftlen,
8542: "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
8543: ASC_PRT_NEXT();
8544:
8545: if (asc_get_eeprom_string(&ep->serial_number_word1, serialstr) ==
8546: ASC_TRUE) {
8547: len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
8548: ASC_PRT_NEXT();
8549: } else {
8550: len = asc_prt_line(cp, leftlen,
8551: " Serial Number Signature Not Present.\n");
8552: ASC_PRT_NEXT();
8553: }
8554:
8555: len = asc_prt_line(cp, leftlen,
8556: " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
8557: ep->adapter_scsi_id, ep->max_host_qng, ep->max_dvc_qng);
8558: ASC_PRT_NEXT();
8559:
8560: switch (ep->termination) {
8561: case 1:
8562: termstr = "Low Off/High Off";
8563: break;
8564: case 2:
8565: termstr = "Low Off/High On";
8566: break;
8567: case 3:
8568: termstr = "Low On/High On";
8569: break;
8570: default:
8571: case 0:
8572: termstr = "Automatic";
8573: break;
8574: }
8575:
8576: len = asc_prt_line(cp, leftlen,
8577: " termination: %u (%s), bios_ctrl: %x\n",
8578: ep->termination, termstr, ep->bios_ctrl);
8579: ASC_PRT_NEXT();
8580:
8581: len = asc_prt_line(cp, leftlen,
8582: " Target ID: ");
8583: ASC_PRT_NEXT();
8584: for (i = 0; i <= ADV_MAX_TID; i++) {
8585: len = asc_prt_line(cp, leftlen, " %X", i);
8586: ASC_PRT_NEXT();
8587: }
8588: len = asc_prt_line(cp, leftlen, "\n");
8589: ASC_PRT_NEXT();
8590:
8591: len = asc_prt_line(cp, leftlen,
8592: " Disconnects: ");
8593: ASC_PRT_NEXT();
8594: for (i = 0; i <= ADV_MAX_TID; i++) {
8595: len = asc_prt_line(cp, leftlen, " %c",
8596: (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8597: ASC_PRT_NEXT();
8598: }
8599: len = asc_prt_line(cp, leftlen, "\n");
8600: ASC_PRT_NEXT();
8601:
8602: len = asc_prt_line(cp, leftlen,
8603: " Command Queuing: ");
8604: ASC_PRT_NEXT();
8605: for (i = 0; i <= ADV_MAX_TID; i++) {
8606: len = asc_prt_line(cp, leftlen, " %c",
8607: (ep->tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8608: ASC_PRT_NEXT();
8609: }
8610: len = asc_prt_line(cp, leftlen, "\n");
8611: ASC_PRT_NEXT();
8612:
8613: len = asc_prt_line(cp, leftlen,
8614: " Start Motor: ");
8615: ASC_PRT_NEXT();
8616: for (i = 0; i <= ADV_MAX_TID; i++) {
8617: len = asc_prt_line(cp, leftlen, " %c",
8618: (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8619: ASC_PRT_NEXT();
8620: }
8621: len = asc_prt_line(cp, leftlen, "\n");
8622: ASC_PRT_NEXT();
8623:
8624: len = asc_prt_line(cp, leftlen,
8625: " Synchronous Transfer:");
8626: ASC_PRT_NEXT();
8627: for (i = 0; i <= ADV_MAX_TID; i++) {
8628: len = asc_prt_line(cp, leftlen, " %c",
8629: (ep->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8630: ASC_PRT_NEXT();
8631: }
8632: len = asc_prt_line(cp, leftlen, "\n");
8633: ASC_PRT_NEXT();
8634:
8635: len = asc_prt_line(cp, leftlen,
8636: " Ultra Transfer: ");
8637: ASC_PRT_NEXT();
8638: for (i = 0; i <= ADV_MAX_TID; i++) {
8639: len = asc_prt_line(cp, leftlen, " %c",
8640: (ep->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8641: ASC_PRT_NEXT();
8642: }
8643: len = asc_prt_line(cp, leftlen, "\n");
8644: ASC_PRT_NEXT();
8645:
8646: len = asc_prt_line(cp, leftlen,
8647: " Wide Transfer: ");
8648: ASC_PRT_NEXT();
8649: for (i = 0; i <= ADV_MAX_TID; i++) {
8650: len = asc_prt_line(cp, leftlen, " %c",
8651: (ep->wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8652: ASC_PRT_NEXT();
8653: }
8654: len = asc_prt_line(cp, leftlen, "\n");
8655: ASC_PRT_NEXT();
8656:
8657: return totlen;
8658: }
8659:
8660: /*
8661: * asc_prt_driver_conf()
8662: *
8663: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8664: * cf. asc_prt_line().
8665: *
8666: * Return the number of characters copied into 'cp'. No more than
8667: * 'cplen' characters will be copied to 'cp'.
8668: */
8669: STATIC int
8670: asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
8671: {
8672: asc_board_t *boardp;
8673: int leftlen;
8674: int totlen;
8675: int len;
8676: int chip_scsi_id;
8677: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
8678: int i;
8679: #endif /* version >= v1.3.89 */
8680:
8681: boardp = ASC_BOARDP(shp);
8682:
8683: leftlen = cplen;
8684: totlen = len = 0;
8685:
8686: len = asc_prt_line(cp, leftlen,
8687: "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
8688: shp->host_no);
8689: ASC_PRT_NEXT();
8690:
8691: len = asc_prt_line(cp, leftlen,
8692: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
8693: " host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
8694: shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
8695: #else /* version >= v1.3.89 */
8696: " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
8697: shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
8698: shp->max_channel);
8699: #endif /* version >= v1.3.89 */
8700: ASC_PRT_NEXT();
8701:
8702: len = asc_prt_line(cp, leftlen,
8703: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
8704: " can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
8705: shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
8706: #else /* version >= v1.3.57 */
8707: " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
8708: shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
8709: shp->cmd_per_lun);
8710: #endif /* version >= v1.3.57 */
8711: ASC_PRT_NEXT();
8712:
8713: len = asc_prt_line(cp, leftlen,
8714: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
8715: " unchecked_isa_dma %d, loaded_as_module %d\n",
8716: shp->unchecked_isa_dma, shp->loaded_as_module);
8717: #else /* version >= v1.3.57 */
8718: " unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
8719: shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
8720: #endif /* version >= v1.3.57 */
8721: ASC_PRT_NEXT();
8722:
8723: len = asc_prt_line(cp, leftlen, " flags %x, last_reset %x, jiffies %x\n",
8724: boardp->flags, boardp->last_reset, jiffies);
8725: ASC_PRT_NEXT();
8726:
8727: if (ASC_NARROW_BOARD(boardp)) {
8728: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
8729: } else {
8730: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
8731: }
8732:
8733: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
8734: if (boardp->flags & ASC_SELECT_QUEUE_DEPTHS) {
8735: len = asc_prt_line(cp, leftlen, " queue_depth:");
8736: ASC_PRT_NEXT();
8737: for (i = 0; i <= ADV_MAX_TID; i++) {
8738: if ((chip_scsi_id == i) ||
8739: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8740: continue;
8741: }
8742: if (boardp->device[i] == NULL) {
8743: continue;
8744: }
8745: len = asc_prt_line(cp, leftlen, " %X:%d",
8746: i, boardp->device[i]->queue_depth);
8747: ASC_PRT_NEXT();
8748: }
8749: len = asc_prt_line(cp, leftlen, "\n");
8750: ASC_PRT_NEXT();
8751: }
8752: #endif /* version >= v1.3.89 */
8753:
8754: #if ASC_QUEUE_FLOW_CONTROL
8755: if (ASC_NARROW_BOARD(boardp)) {
8756: len = asc_prt_line(cp, leftlen, " queue_curr_depth:");
8757: ASC_PRT_NEXT();
8758: /* Use ASC_MAX_TID for Narrow Board. */
8759: for (i = 0; i <= ASC_MAX_TID; i++) {
8760: if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
8761: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8762: continue;
8763: }
8764: if (boardp->device[i] == NULL) {
8765: continue;
8766: }
8767: len = asc_prt_line(cp, leftlen, " %d:%d",
8768: i, boardp->device[i]->queue_curr_depth);
8769: ASC_PRT_NEXT();
8770: }
8771: len = asc_prt_line(cp, leftlen, "\n");
8772: ASC_PRT_NEXT();
8773:
8774: len = asc_prt_line(cp, leftlen, " queue_count:");
8775: ASC_PRT_NEXT();
8776: /* Use ASC_MAX_TID for Narrow Board. */
8777: for (i = 0; i <= ASC_MAX_TID; i++) {
8778: if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
8779: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8780: continue;
8781: }
8782: if (boardp->device[i] == NULL) {
8783: continue;
8784: }
8785: len = asc_prt_line(cp, leftlen, " %d:%d",
8786: i, boardp->device[i]->queue_count);
8787: ASC_PRT_NEXT();
8788: }
8789: len = asc_prt_line(cp, leftlen, "\n");
8790: ASC_PRT_NEXT();
8791: }
8792: #endif /* ASC_QUEUE_FLOW_CONTROL */
8793:
8794: return totlen;
8795: }
8796:
8797: /*
8798: * asc_prt_asc_board_info()
8799: *
8800: * Print dynamic board configuration information.
8801: *
8802: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8803: * cf. asc_prt_line().
8804: *
8805: * Return the number of characters copied into 'cp'. No more than
8806: * 'cplen' characters will be copied to 'cp'.
8807: */
8808: STATIC int
8809: asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen)
8810: {
8811: asc_board_t *boardp;
8812: int leftlen;
8813: int totlen;
8814: int len;
8815: ASC_DVC_VAR *v;
8816: ASC_DVC_CFG *c;
8817: int i;
8818:
8819: boardp = ASC_BOARDP(shp);
8820: v = &boardp->dvc_var.asc_dvc_var;
8821: c = &boardp->dvc_cfg.asc_dvc_cfg;
8822:
8823: leftlen = cplen;
8824: totlen = len = 0;
8825:
8826: len = asc_prt_line(cp, leftlen,
8827: "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
8828: shp->host_no);
8829: ASC_PRT_NEXT();
8830:
8831: len = asc_prt_line(cp, leftlen,
8832: " chip_version %u, lib_version %x, lib_serial_no %u, mcode_date %x\n",
8833: c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date);
8834: ASC_PRT_NEXT();
8835:
8836: len = asc_prt_line(cp, leftlen,
8837: " mcode_version %x, err_code %u\n",
8838: c->mcode_version, v->err_code);
8839: ASC_PRT_NEXT();
8840:
8841: /* Current number of commands waiting for the host. */
8842: len = asc_prt_line(cp, leftlen,
8843: " Total Command Pending: %d\n", v->cur_total_qng);
8844: ASC_PRT_NEXT();
8845:
8846: len = asc_prt_line(cp, leftlen,
8847: " Command Queuing:");
8848: ASC_PRT_NEXT();
8849: for (i = 0; i <= ASC_MAX_TID; i++) {
8850: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8851: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8852: continue;
8853: }
8854: len = asc_prt_line(cp, leftlen, " %d:%c",
8855: i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8856: ASC_PRT_NEXT();
8857: }
8858: len = asc_prt_line(cp, leftlen, "\n");
8859: ASC_PRT_NEXT();
8860:
8861: /* Current number of commands waiting for a device. */
8862: len = asc_prt_line(cp, leftlen,
8863: " Command Queue Pending:");
8864: ASC_PRT_NEXT();
8865: for (i = 0; i <= ASC_MAX_TID; i++) {
8866: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8867: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8868: continue;
8869: }
8870: len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
8871: ASC_PRT_NEXT();
8872: }
8873: len = asc_prt_line(cp, leftlen, "\n");
8874: ASC_PRT_NEXT();
8875:
8876: /* Current limit on number of commands that can be sent to a device. */
8877: len = asc_prt_line(cp, leftlen,
8878: " Command Queue Limit:");
8879: ASC_PRT_NEXT();
8880: for (i = 0; i <= ASC_MAX_TID; i++) {
8881: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8882: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8883: continue;
8884: }
8885: len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
8886: ASC_PRT_NEXT();
8887: }
8888: len = asc_prt_line(cp, leftlen, "\n");
8889: ASC_PRT_NEXT();
8890:
8891: /* Indicate whether the device has returned queue full status. */
8892: len = asc_prt_line(cp, leftlen,
8893: " Command Queue Full:");
8894: ASC_PRT_NEXT();
8895: for (i = 0; i <= ASC_MAX_TID; i++) {
8896: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8897: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8898: continue;
8899: }
8900: if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
8901: len = asc_prt_line(cp, leftlen, " %d:Y-%d",
8902: i, boardp->queue_full_cnt[i]);
8903: } else {
8904: len = asc_prt_line(cp, leftlen, " %d:N", i);
8905: }
8906: ASC_PRT_NEXT();
8907: }
8908: len = asc_prt_line(cp, leftlen, "\n");
8909: ASC_PRT_NEXT();
8910:
8911: len = asc_prt_line(cp, leftlen,
8912: " Synchronous Transfer:");
8913: ASC_PRT_NEXT();
8914: for (i = 0; i <= ASC_MAX_TID; i++) {
8915: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8916: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8917: continue;
8918: }
8919: len = asc_prt_line(cp, leftlen, " %d:%c",
8920: i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
8921: ASC_PRT_NEXT();
8922: }
8923: len = asc_prt_line(cp, leftlen, "\n");
8924: ASC_PRT_NEXT();
8925:
8926: for (i = 0; i <= ASC_MAX_TID; i++) {
8927: uchar syn_period_ix;
8928:
8929: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
8930: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
8931: continue;
8932: }
8933: if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
8934: continue;
8935: }
8936: syn_period_ix = (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1);
8937: len = asc_prt_line(cp, leftlen, " %d:", i);
8938: ASC_PRT_NEXT();
8939:
8940: len = asc_prt_line(cp, leftlen,
8941: " Transfer Period Factor: %d (%d.%d Mhz),",
8942: v->sdtr_period_tbl[syn_period_ix],
8943: 250 / v->sdtr_period_tbl[syn_period_ix],
8944: ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix]));
8945: ASC_PRT_NEXT();
8946:
8947: len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
8948: boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
8949: ASC_PRT_NEXT();
8950: }
8951:
8952: return totlen;
8953: }
8954:
8955: /*
8956: * asc_prt_adv_board_info()
8957: *
8958: * Print dynamic board configuration information.
8959: *
8960: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
8961: * cf. asc_prt_line().
8962: *
8963: * Return the number of characters copied into 'cp'. No more than
8964: * 'cplen' characters will be copied to 'cp'.
8965: */
8966: STATIC int
8967: asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen)
8968: {
8969: asc_board_t *boardp;
8970: int leftlen;
8971: int totlen;
8972: int len;
8973: int i;
8974: ADV_DVC_VAR *v;
8975: ADV_DVC_CFG *c;
8976: AdvPortAddr iop_base;
8977: ushort chip_scsi_id;
8978: ushort lramword;
8979: uchar lrambyte;
8980: ushort sdtr_able;
8981: ushort period;
8982:
8983: boardp = ASC_BOARDP(shp);
8984: v = &boardp->dvc_var.adv_dvc_var;
8985: c = &boardp->dvc_cfg.adv_dvc_cfg;
8986: iop_base = v->iop_base;
8987: chip_scsi_id = v->chip_scsi_id;
8988:
8989: leftlen = cplen;
8990: totlen = len = 0;
8991:
8992: len = asc_prt_line(cp, leftlen,
8993: "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
8994: shp->host_no);
8995: ASC_PRT_NEXT();
8996:
8997: len = asc_prt_line(cp, leftlen,
8998: " iop_base %lx, cable_detect: %X, err_code %u, idle_cmd_done %u\n",
8999: v->iop_base,
9000: AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT,
9001: v->err_code, v->idle_cmd_done);
9002: ASC_PRT_NEXT();
9003:
9004: len = asc_prt_line(cp, leftlen,
9005: " chip_version %u, lib_version %x, mcode_date %x, mcode_version %x\n",
9006: c->chip_version, c->lib_version, c->mcode_date, c->mcode_version);
9007: ASC_PRT_NEXT();
9008:
9009: AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, lramword);
9010: len = asc_prt_line(cp, leftlen,
9011: " Queuing Enabled:");
9012: ASC_PRT_NEXT();
9013: for (i = 0; i <= ADV_MAX_TID; i++) {
9014: if ((chip_scsi_id == i) ||
9015: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9016: continue;
9017: }
9018:
9019: len = asc_prt_line(cp, leftlen, " %X:%c",
9020: i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9021: ASC_PRT_NEXT();
9022: }
9023: len = asc_prt_line(cp, leftlen, "\n");
9024: ASC_PRT_NEXT();
9025:
9026: len = asc_prt_line(cp, leftlen,
9027: " Queue Limit:");
9028: ASC_PRT_NEXT();
9029: for (i = 0; i <= ADV_MAX_TID; i++) {
9030: if ((chip_scsi_id == i) ||
9031: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9032: continue;
9033: }
9034:
9035: AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte);
9036:
9037: len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9038: ASC_PRT_NEXT();
9039: }
9040: len = asc_prt_line(cp, leftlen, "\n");
9041: ASC_PRT_NEXT();
9042:
9043: len = asc_prt_line(cp, leftlen,
9044: " Command Pending:");
9045: ASC_PRT_NEXT();
9046: for (i = 0; i <= ADV_MAX_TID; i++) {
9047: if ((chip_scsi_id == i) ||
9048: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9049: continue;
9050: }
9051:
9052: AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte);
9053:
9054: len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
9055: ASC_PRT_NEXT();
9056: }
9057: len = asc_prt_line(cp, leftlen, "\n");
9058: ASC_PRT_NEXT();
9059:
9060: AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, lramword);
9061: len = asc_prt_line(cp, leftlen,
9062: " Wide Enabled:");
9063: ASC_PRT_NEXT();
9064: for (i = 0; i <= ADV_MAX_TID; i++) {
9065: if ((chip_scsi_id == i) ||
9066: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9067: continue;
9068: }
9069:
9070: len = asc_prt_line(cp, leftlen, " %X:%c",
9071: i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9072: ASC_PRT_NEXT();
9073: }
9074: len = asc_prt_line(cp, leftlen, "\n");
9075: ASC_PRT_NEXT();
9076:
9077: len = asc_prt_line(cp, leftlen,
9078: " Transfer Bit Width:");
9079: ASC_PRT_NEXT();
9080: for (i = 0; i <= ADV_MAX_TID; i++) {
9081: if ((chip_scsi_id == i) ||
9082: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9083: continue;
9084: }
9085:
9086: AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9087: lramword);
9088: len = asc_prt_line(cp, leftlen, " %X:%d",
9089: i, (lramword & 0x8000) ? 16 : 8);
9090: ASC_PRT_NEXT();
9091: }
9092: len = asc_prt_line(cp, leftlen, "\n");
9093: ASC_PRT_NEXT();
9094:
9095: AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
9096: len = asc_prt_line(cp, leftlen,
9097: " Synchronous Enabled:");
9098: ASC_PRT_NEXT();
9099: for (i = 0; i <= ADV_MAX_TID; i++) {
9100: if ((chip_scsi_id == i) ||
9101: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9102: continue;
9103: }
9104:
9105: len = asc_prt_line(cp, leftlen, " %X:%c",
9106: i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
9107: ASC_PRT_NEXT();
9108: }
9109: len = asc_prt_line(cp, leftlen, "\n");
9110: ASC_PRT_NEXT();
9111:
9112: for (i = 0; i <= ADV_MAX_TID; i++) {
9113:
9114: AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
9115: lramword);
9116: lramword &= ~0x8000;
9117:
9118: if ((chip_scsi_id == i) ||
9119: ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0) ||
9120: (lramword == 0)) {
9121: continue;
9122: }
9123:
9124: len = asc_prt_line(cp, leftlen, " %X:", i);
9125: ASC_PRT_NEXT();
9126:
9127: period = (((lramword >> 8) * 25) + 50)/4;
9128:
9129: len = asc_prt_line(cp, leftlen,
9130: " Transfer Period Factor: %d (%d.%d Mhz),",
9131: period, 250/period, ASC_TENTHS(250, period));
9132: ASC_PRT_NEXT();
9133:
9134: len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
9135: lramword & 0x1F);
9136: ASC_PRT_NEXT();
9137: }
9138:
9139: return totlen;
9140: }
9141:
9142: /*
9143: * asc_proc_copy()
9144: *
9145: * Copy proc information to a read buffer taking into account the current
9146: * read offset in the file and the remaining space in the read buffer.
9147: */
9148: STATIC int
9149: asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
9150: char *cp, int cplen)
9151: {
9152: int cnt = 0;
9153:
9154: ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
9155: (unsigned) offset, (unsigned) advoffset, cplen);
9156: if (offset <= advoffset) {
9157: /* Read offset below current offset, copy everything. */
9158: cnt = ASC_MIN(cplen, leftlen);
9159: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9160: (unsigned) curbuf, (unsigned) cp, cnt);
9161: memcpy(curbuf, cp, cnt);
9162: } else if (offset < advoffset + cplen) {
9163: /* Read offset within current range, partial copy. */
9164: cnt = (advoffset + cplen) - offset;
9165: cp = (cp + cplen) - cnt;
9166: cnt = ASC_MIN(cnt, leftlen);
9167: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
9168: (unsigned) curbuf, (unsigned) cp, cnt);
9169: memcpy(curbuf, cp, cnt);
9170: }
9171: return cnt;
9172: }
9173:
9174: /*
9175: * asc_prt_line()
9176: *
9177: * If 'cp' is NULL print to the console, otherwise print to a buffer.
9178: *
9179: * Return 0 if printing to the console, otherwise return the number of
9180: * bytes written to the buffer.
9181: *
9182: * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
9183: * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
9184: */
9185: STATIC int
9186: asc_prt_line(char *buf, int buflen, char *fmt, ...)
9187: {
9188: va_list args;
9189: int ret;
9190: char s[ASC_PRTLINE_SIZE];
9191:
9192: va_start(args, fmt);
9193: ret = vsprintf(s, fmt, args);
9194: ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
9195: if (buf == NULL) {
1.1.1.2 root 9196: (void) printk("%s", s);
1.1 root 9197: ret = 0;
9198: } else {
9199: ret = ASC_MIN(buflen, ret);
9200: memcpy(buf, s, ret);
9201: }
9202: va_end(args);
9203: return ret;
9204: }
9205: #endif /* version >= v1.3.0 */
9206:
9207:
9208: /*
9209: * --- Functions Required by the Asc Library
9210: */
9211:
9212: /*
9213: * Delay for 'n' milliseconds. Don't use the 'jiffies'
9214: * global variable which is incremented once every 5 ms
9215: * from a timer interrupt, because this function may be
9216: * called when interrupts are disabled.
9217: */
9218: STATIC void
9219: DvcSleepMilliSecond(ulong n)
9220: {
9221: ulong i;
9222:
9223: ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
9224: for (i = 0; i < n; i++) {
9225: udelay(1000);
9226: }
9227: }
9228:
1.1.1.2 root 9229: STATIC long
1.1 root 9230: DvcEnterCritical(void)
9231: {
1.1.1.2 root 9232: long flags;
1.1 root 9233:
9234: save_flags(flags);
9235: cli();
9236: return flags;
9237: }
9238:
9239: STATIC void
1.1.1.2 root 9240: DvcLeaveCritical(long flags)
1.1 root 9241: {
9242: restore_flags(flags);
9243: }
9244:
9245: STATIC ulong
9246: DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
9247: ASC_SG_HEAD *asc_sg_head_ptr)
9248: {
9249: ulong buf_size;
9250:
9251: buf_size = buf_len;
9252: asc_sg_head_ptr->entry_cnt = 1;
9253: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9254: asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
9255: #else /* version >= v2.0.0 */
9256: asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
9257: #endif /* version >= v2.0.0 */
9258: asc_sg_head_ptr->sg_list[0].bytes = buf_size;
9259: return buf_size;
9260: }
9261:
9262: /*
9263: * void
9264: * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9265: *
9266: * Calling/Exit State:
9267: * none
9268: *
9269: * Description:
9270: * Output an ASC_SCSI_Q structure to the chip
9271: */
9272: STATIC void
9273: DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
9274: {
9275: int i;
9276:
9277: ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
9278: AscSetChipLramAddr(iop_base, s_addr);
9279: for (i = 0; i < words; i++, outbuf++) {
9280: if (i == 2 || i == 10) {
9281: continue;
9282: }
9283: AscSetChipLramDataNoSwap(iop_base, *outbuf);
9284: }
9285: }
9286:
9287: /*
9288: * void
9289: * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9290: *
9291: * Calling/Exit State:
9292: * none
9293: *
9294: * Description:
9295: * Input an ASC_QDONE_INFO structure from the chip
9296: */
9297: STATIC void
9298: DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
9299: {
9300: int i;
9301:
9302: AscSetChipLramAddr(iop_base, s_addr);
9303: for (i = 0; i < words; i++, inbuf++) {
9304: if (i == 5) {
9305: continue;
9306: }
9307: *inbuf = AscGetChipLramDataNoSwap(iop_base);
9308: }
9309: ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
9310: }
9311:
9312: /*
9313: * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
9314: *
9315: * Calling/Exit State:
9316: * none
9317: *
9318: * Description:
9319: * output a buffer to an i/o port address
9320: */
9321: STATIC void
9322: DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
9323: {
9324: int i;
9325:
9326: for (i = 0; i < words; i++, outbuf++)
9327: outpw(iop_base, *outbuf);
9328: }
9329:
9330: /*
9331: * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
9332: *
9333: * Calling/Exit State:
9334: * none
9335: *
9336: * Description:
9337: * input a buffer from an i/o port address
9338: */
9339: STATIC void
9340: DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
9341: {
9342: int i;
9343:
9344: for (i = 0; i < words; i++, inbuf++)
9345: *inbuf = inpw(iop_base);
9346: }
9347:
9348: /*
9349: * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
9350: *
9351: * Calling/Exit State:
9352: * none
9353: *
9354: * Description:
9355: * output a buffer of 32-bit integers to an i/o port address in
9356: * 16 bit integer units
9357: */
9358: STATIC void
9359: DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
9360: {
9361: int i;
9362: int words;
9363: ushort *pw;
9364:
9365: pw = (ushort *) pdw;
9366: words = dwords << 1;
9367: for(i = 0; i < words; i++, pw++) {
9368: outpw(port, *pw);
9369: }
9370: return;
9371: }
9372:
9373: /*
9374: * Read a PCI configuration byte.
9375: */
9376: ASC_INITFUNC(
9377: STATIC uchar
9378: DvcReadPCIConfigByte(
9379: ASC_DVC_VAR asc_ptr_type *asc_dvc,
9380: ushort offset)
9381: )
9382: {
9383: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9384: #ifdef ASC_CONFIG_PCI
9385: PCI_DATA pciData;
9386:
9387: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9388: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9389: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9390: pciData.offset = offset;
9391: pciData.type = pci_scan_method;
9392: return asc_get_cfg_byte(&pciData);
9393: #else /* ASC_CONFIG_PCI */
9394: return 0;
9395: #endif /* ASC_CONFIG_PCI */
9396: #else /* version >= v2.1.93 */
9397: #ifdef CONFIG_PCI
9398: uchar byte_data;
9399: pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9400: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9401: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9402: offset, &byte_data);
9403: return byte_data;
9404: #else /* CONFIG_PCI */
9405: return 0;
9406: #endif /* CONFIG_PCI */
9407: #endif /* version >= v2.1.93 */
9408: }
9409:
9410: /*
9411: * Write a PCI configuration byte.
9412: */
9413: ASC_INITFUNC(
9414: STATIC void
9415: DvcWritePCIConfigByte(
9416: ASC_DVC_VAR asc_ptr_type *asc_dvc,
9417: ushort offset,
9418: uchar byte_data)
9419: )
9420: {
9421: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9422: #ifdef ASC_CONFIG_PCI
9423: PCI_DATA pciData;
9424:
9425: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9426: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9427: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9428: pciData.offset = offset;
9429: pciData.type = pci_scan_method;
9430: asc_put_cfg_byte(&pciData, byte_data);
9431: #endif /* ASC_CONFIG_PCI */
9432: #else /* version >= v2.1.93 */
9433: #ifdef CONFIG_PCI
9434: pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9435: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9436: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9437: offset, byte_data);
9438: #endif /* CONFIG_PCI */
9439: #endif /* version >= v2.1.93 */
9440: }
9441:
9442: /*
9443: * Return the BIOS address of the adapter at the specified
9444: * I/O port and with the specified bus type.
9445: */
9446: ASC_INITFUNC(
9447: STATIC ushort
9448: AscGetChipBiosAddress(
9449: PortAddr iop_base,
9450: ushort bus_type
9451: )
9452: )
9453: {
9454: ushort cfg_lsw ;
9455: ushort bios_addr ;
9456:
9457: /*
9458: * The PCI BIOS is re-located by the motherboard BIOS. Because
9459: * of this the driver can not determine where a PCI BIOS is
9460: * loaded and executes.
9461: */
9462: if (bus_type & ASC_IS_PCI)
9463: {
9464: return(0);
9465: }
9466:
9467: if((bus_type & ASC_IS_EISA) != 0)
9468: {
9469: cfg_lsw = AscGetEisaChipCfg(iop_base) ;
9470: cfg_lsw &= 0x000F ;
9471: bios_addr = (ushort)(ASC_BIOS_MIN_ADDR +
9472: (cfg_lsw * ASC_BIOS_BANK_SIZE)) ;
9473: return(bios_addr) ;
9474: }/* if */
9475:
9476: cfg_lsw = AscGetChipCfgLsw(iop_base) ;
9477:
9478: /*
9479: * ISA PnP uses the top bit as the 32K BIOS flag
9480: */
9481: if (bus_type == ASC_IS_ISAPNP)
9482: {
9483: cfg_lsw &= 0x7FFF;
9484: }/* if */
9485:
9486: bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
9487: ASC_BIOS_MIN_ADDR) ;
9488: return(bios_addr) ;
9489: }
9490:
9491:
9492: /*
9493: * --- Functions Required by the Adv Library
9494: */
9495:
9496: /*
9497: * DvcGetPhyAddr()
9498: *
9499: * Return the physical address of 'vaddr' and set '*lenp' to the
9500: * number of physically contiguous bytes that follow 'vaddr'.
9501: * 'flag' indicates the type of structure whose physical address
9502: * is being translated.
9503: *
9504: * Note: Because Linux currently doesn't page the kernel and all
9505: * kernel buffers are physically contiguous, leave '*lenp' unchanged.
9506: */
9507: ulong
9508: DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
9509: uchar *vaddr, long *lenp, int flag)
9510: {
9511: ulong paddr;
9512:
9513: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
9514: paddr = (ulong) vaddr;
9515: #else /* version >= v2.0.0 */
9516: paddr = virt_to_bus(vaddr);
9517: #endif /* version >= v2.0.0 */
9518:
9519: ASC_DBG4(4,
9520: "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
9521: (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), paddr);
9522:
9523: return paddr;
9524: }
9525:
9526: /*
9527: * Read a PCI configuration byte.
9528: */
9529: ASC_INITFUNC(
9530: STATIC uchar
9531: DvcAdvReadPCIConfigByte(
9532: ADV_DVC_VAR *asc_dvc,
9533: ushort offset)
9534: )
9535: {
9536: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9537: #ifdef ASC_CONFIG_PCI
9538: PCI_DATA pciData;
9539:
9540: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9541: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9542: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9543: pciData.offset = offset;
9544: pciData.type = pci_scan_method;
9545: return asc_get_cfg_byte(&pciData);
9546: #else /* ASC_CONFIG_PCI */
9547: return 0;
9548: #endif /* ASC_CONFIG_PCI */
9549: #else /* version >= v2.1.93 */
9550: #ifdef CONFIG_PCI
9551: uchar byte_data;
9552: pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9553: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9554: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9555: offset, &byte_data);
9556: return byte_data;
9557: #else /* CONFIG_PCI */
9558: return 0;
9559: #endif /* CONFIG_PCI */
9560: #endif /* version >= v2.1.93 */
9561: }
9562:
9563: /*
9564: * Write a PCI configuration byte.
9565: */
9566: ASC_INITFUNC(
9567: STATIC void
9568: DvcAdvWritePCIConfigByte(
9569: ADV_DVC_VAR *asc_dvc,
9570: ushort offset,
9571: uchar byte_data)
9572: )
9573: {
9574: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
9575: #ifdef ASC_CONFIG_PCI
9576: PCI_DATA pciData;
9577:
9578: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
9579: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
9580: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
9581: pciData.offset = offset;
9582: pciData.type = pci_scan_method;
9583: asc_put_cfg_byte(&pciData, byte_data);
9584: #endif /* ASC_CONFIG_PCI */
9585: #else /* version >= v2.1.93 */
9586: #ifdef CONFIG_PCI
9587: pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
9588: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
9589: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
9590: offset, byte_data);
9591: #endif /* CONFIG_PCI */
9592: #endif /* version >= v2.1.93 */
9593: }
9594:
9595: /*
9596: * --- Tracing and Debugging Functions
9597: */
9598:
9599: #ifdef ADVANSYS_STATS
9600: /*
9601: * asc_prt_board_stats()
9602: *
9603: * Note: no single line should be greater than ASC_PRTLINE_SIZE,
9604: * cf. asc_prt_line().
9605: *
9606: * Return the number of characters copied into 'cp'. No more than
9607: * 'cplen' characters will be copied to 'cp'.
9608: */
9609: STATIC int
9610: asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
9611: {
9612: int leftlen;
9613: int totlen;
9614: int len;
9615: struct asc_stats *s;
9616: int i;
9617: ushort chip_scsi_id;
9618: asc_board_t *boardp;
9619: asc_queue_t *active;
9620: asc_queue_t *waiting;
9621:
9622: leftlen = cplen;
9623: totlen = len = 0;
9624:
9625: boardp = ASC_BOARDP(shp);
9626: s = &boardp->asc_stats;
9627:
9628: len = asc_prt_line(cp, leftlen,
9629: "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no);
9630: ASC_PRT_NEXT();
9631:
9632: len = asc_prt_line(cp, leftlen,
9633: " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n",
9634: s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
9635: ASC_PRT_NEXT();
9636:
9637: len = asc_prt_line(cp, leftlen,
9638: " interrupt %lu, callback %lu, done %lu\n",
9639: s->interrupt, s->callback, s->done);
9640: ASC_PRT_NEXT();
9641:
9642: len = asc_prt_line(cp, leftlen,
9643: " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
9644: s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown);
9645: ASC_PRT_NEXT();
9646:
9647: if (ASC_NARROW_BOARD(boardp)) {
9648: len = asc_prt_line(cp, leftlen,
9649: " build_error %lu\n",
9650: s->build_error);
9651: } else {
9652: len = asc_prt_line(cp, leftlen,
9653: " build_error %lu, build_noreq %lu, build_nosg %lu\n",
9654: s->build_error, s->adv_build_noreq, s->adv_build_nosg);
9655: }
9656: ASC_PRT_NEXT();
9657:
9658: /*
9659: * Display data transfer statistics.
9660: */
9661: if (s->cont_cnt > 0) {
9662: len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
9663: ASC_PRT_NEXT();
9664:
9665: len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
9666: s->cont_xfer/2,
9667: ASC_TENTHS(s->cont_xfer, 2));
9668: ASC_PRT_NEXT();
9669:
9670: /* Contiguous transfer average size */
9671: len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
9672: (s->cont_xfer/2)/s->cont_cnt,
9673: ASC_TENTHS((s->cont_xfer/2), s->cont_cnt));
9674: ASC_PRT_NEXT();
9675: }
9676:
9677: if (s->sg_cnt > 0) {
9678:
9679: len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
9680: s->sg_cnt, s->sg_elem);
9681: ASC_PRT_NEXT();
9682:
9683: len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
9684: s->sg_xfer/2,
9685: ASC_TENTHS(s->sg_xfer, 2));
9686: ASC_PRT_NEXT();
9687:
9688: /* Scatter gather transfer statistics */
9689: len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
9690: s->sg_elem/s->sg_cnt,
9691: ASC_TENTHS(s->sg_elem, s->sg_cnt));
9692: ASC_PRT_NEXT();
9693:
9694: len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
9695: (s->sg_xfer/2)/s->sg_elem,
9696: ASC_TENTHS((s->sg_xfer/2), s->sg_elem));
9697: ASC_PRT_NEXT();
9698:
9699: len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
9700: (s->sg_xfer/2)/s->sg_cnt,
9701: ASC_TENTHS((s->sg_xfer/2), s->sg_cnt));
9702: ASC_PRT_NEXT();
9703: }
9704:
9705: /*
9706: * Display request queuing statistics.
9707: */
9708: len = asc_prt_line(cp, leftlen,
9709: " Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ);
9710: ASC_PRT_NEXT();
9711:
9712: active = &ASC_BOARDP(shp)->active;
9713: waiting = &ASC_BOARDP(shp)->waiting;
9714:
9715: if (ASC_NARROW_BOARD(boardp)) {
9716: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
9717: } else {
9718: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
9719: }
9720:
9721: for (i = 0; i <= ADV_MAX_TID; i++) {
9722:
9723: if ((chip_scsi_id == i) ||
9724: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
9725: continue;
9726: }
9727:
9728: if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
9729: len = asc_prt_line(cp, leftlen, " target %d\n", i);
9730: ASC_PRT_NEXT();
9731:
9732: len = asc_prt_line(cp, leftlen,
9733: " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
9734: active->q_cur_cnt[i], active->q_max_cnt[i],
9735: active->q_tot_cnt[i],
9736: active->q_min_tim[i], active->q_max_tim[i],
9737: (active->q_tot_cnt[i] == 0) ? 0 :
9738: (active->q_tot_tim[i]/active->q_tot_cnt[i]),
9739: (active->q_tot_cnt[i] == 0) ? 0 :
9740: ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
9741: ASC_PRT_NEXT();
9742:
9743: len = asc_prt_line(cp, leftlen,
9744: " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
9745: waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
9746: waiting->q_tot_cnt[i],
9747: waiting->q_min_tim[i], waiting->q_max_tim[i],
9748: (waiting->q_tot_cnt[i] == 0) ? 0 :
9749: (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
9750: (waiting->q_tot_cnt[i] == 0) ? 0 :
9751: ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
9752: ASC_PRT_NEXT();
9753: }
9754: }
9755:
9756: return totlen;
9757: }
9758: #endif /* ADVANSYS_STATS */
9759:
9760: #ifdef ADVANSYS_DEBUG
9761: /*
9762: * asc_prt_scsi_host()
9763: */
9764: STATIC void
9765: asc_prt_scsi_host(struct Scsi_Host *s)
9766: {
9767: asc_board_t *boardp;
9768:
9769: boardp = ASC_BOARDP(s);
9770:
9771: printk("Scsi_Host at addr %x\n", (unsigned) s);
9772: printk(
9773: " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
9774: (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
9775: (unsigned) s->last_reset);
9776:
9777: printk(
9778: " host_wait %x, host_queue %x, hostt %x, block %x,\n",
9779: (unsigned) s->host_wait, (unsigned) s->host_queue,
9780: (unsigned) s->hostt, (unsigned) s->block);
9781:
9782: printk(
9783: " wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
9784: s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
9785: s->irq, s->dma_channel);
9786:
9787: printk(
9788: " this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
9789:
9790: printk(
9791: " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
9792: s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
9793: s->loaded_as_module);
9794:
9795: if (ASC_NARROW_BOARD(boardp)) {
9796: asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
9797: asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
9798: } else {
9799: asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
9800: asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
9801: }
9802: }
9803:
9804: /*
9805: * asc_prt_scsi_cmnd()
9806: */
9807: STATIC void
9808: asc_prt_scsi_cmnd(Scsi_Cmnd *s)
9809: {
9810: printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
9811:
9812: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
9813: printk(
9814: " host %x, device %x, target %u, lun %u\n",
9815: (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
9816: #else /* version >= v1.3.0 */
9817: printk(
9818: " host %x, device %x, target %u, lun %u, channel %u,\n",
9819: (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
9820: s->channel);
9821: #endif /* version >= v1.3.0 */
9822:
9823: asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
9824:
9825: printk(
9826: " use_sg %u, sglist_len %u, abort_reason %x\n",
9827: s->use_sg, s->sglist_len, s->abort_reason);
9828:
9829: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
9830: printk(
9831: " retries %d, allowed %d\n",
9832: s->retries, s->allowed);
9833: #else /* version >= v1.3.89 */
9834: printk(
9835: " serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
9836: (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
9837: s->retries, s->allowed);
9838: #endif /* version >= v1.3.89 */
9839:
9840: printk(
9841: " timeout_per_command %d, timeout_total %d, timeout %d\n",
9842: s->timeout_per_command, s->timeout_total, s->timeout);
9843:
9844: printk(
9845: " internal_timeout %u, flags %u, this_count %d\n",
9846: s->internal_timeout, s->flags, s->this_count);
9847:
9848: printk(
9849: " scsi_done %x, done %x, host_scribble %x, result %x\n",
9850: (unsigned) s->scsi_done, (unsigned) s->done,
9851: (unsigned) s->host_scribble, s->result);
9852:
9853: printk(
9854: " tag %u, pid %u\n",
9855: (unsigned) s->tag, (unsigned) s->pid);
9856: }
9857:
9858: /*
9859: * asc_prt_asc_dvc_var()
9860: */
9861: STATIC void
9862: asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
9863: {
9864: printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
9865:
9866: printk(
9867: " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
9868: h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
9869:
9870: printk(
9871: " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
9872: h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
9873: (unsigned) h->init_sdtr);
9874:
9875: printk(
9876: " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
9877: (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
9878: (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
9879:
9880: printk(
9881: " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
9882: (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
9883: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
9884:
9885: printk(
9886: " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
9887: (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
9888: (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
9889:
9890: printk(
9891: " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
9892: (unsigned) h->last_q_shortage, (unsigned) h->init_state,
9893: (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
9894:
9895: printk(
9896: " cfg %x, saved_ptr2func %x\n",
9897: (unsigned) h->cfg, (unsigned) h->saved_ptr2func);
9898: }
9899:
9900: /*
9901: * asc_prt_asc_dvc_cfg()
9902: */
9903: STATIC void
9904: asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
9905: {
9906: printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
9907:
9908: printk(
9909: " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n",
9910: h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable,
9911: h->sdtr_enable);
9912:
9913: printk(
9914: " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
9915: h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
9916: h->chip_version);
9917:
9918: printk(
9919: " pci_device_id %d, lib_serial_no %x, lib_version %x, mcode_date %x,\n",
9920: h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
9921:
9922: printk(
9923: " mcode_version %d, overrun_buf %x\n",
9924: h->mcode_version, (unsigned) h->overrun_buf);
9925: }
9926:
9927: /*
9928: * asc_prt_asc_scsi_q()
9929: */
9930: STATIC void
9931: asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
9932: {
9933: ASC_SG_HEAD *sgp;
9934: int i;
9935:
9936: printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
9937:
9938: printk(
9939: " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
9940: q->q2.target_ix, q->q1.target_lun,
9941: (unsigned) q->q2.srb_ptr, q->q2.tag_code);
9942:
9943: printk(
9944: " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
9945: (unsigned) q->q1.data_addr, q->q1.data_cnt,
9946: (unsigned) q->q1.sense_addr, q->q1.sense_len);
9947:
9948: printk(
9949: " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
9950: (unsigned) q->cdbptr, q->q2.cdb_len,
9951: (unsigned) q->sg_head, q->q1.sg_queue_cnt);
9952:
9953: if (q->sg_head) {
9954: sgp = q->sg_head;
9955: printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
9956: printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
9957: for (i = 0; i < sgp->entry_cnt; i++) {
9958: printk(" [%u]: addr %x, bytes %lu\n",
9959: i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
9960: }
9961:
9962: }
9963: }
9964:
9965: /*
9966: * asc_prt_asc_qdone_info()
9967: */
9968: STATIC void
9969: asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
9970: {
9971: printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
9972: printk(
9973: " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
9974: (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
9975: q->d2.tag_code, q->d3.done_stat);
9976: printk(
9977: " host_stat %x, scsi_stat %x, scsi_msg %x\n",
9978: q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
9979: }
9980:
9981: /*
9982: * asc_prt_adv_dvc_var()
9983: *
9984: * Display an ADV_DVC_VAR structure.
9985: */
9986: STATIC void
9987: asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
9988: {
9989: printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h);
9990:
9991: printk(
9992: " iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
9993: (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able);
9994:
9995: printk(
9996: " isr_callback 0x%x, sdtr_able 0x%x, wdtr_able 0x%x\n",
9997: (unsigned) h->isr_callback, (unsigned) h->wdtr_able,
9998: (unsigned) h->sdtr_able);
9999:
10000: printk(
10001: " start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
10002: (unsigned) h->start_motor,
10003: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
10004:
10005: printk(
10006: " max_host_qng 0x%x, cur_host_qng 0x%x, max_dvc_qng 0x%x\n",
10007: (unsigned) h->max_host_qng, (unsigned) h->cur_host_qng,
10008: (unsigned) h->max_dvc_qng);
10009:
10010: printk(
10011: " no_scam 0x%x, tagqng_able 0x%x, chip_scsi_id 0x%x, cfg 0x%lx\n",
10012: (unsigned) h->no_scam, (unsigned) h->tagqng_able,
10013: (unsigned) h->chip_scsi_id, (ulong) h->cfg);
10014:
10015: }
10016:
10017: /*
10018: * asc_prt_adv_dvc_cfg()
10019: *
10020: * Display an ADV_DVC_CFG structure.
10021: */
10022: STATIC void
10023: asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
10024: {
10025: printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h);
10026:
10027: printk(
10028: " disc_enable 0x%x, termination 0x%x\n",
10029: h->disc_enable, h->termination);
10030:
10031: printk(
10032: " chip_version 0x%x, mcode_date 0x%x\n",
10033: h->chip_version, h->mcode_date);
10034:
10035: printk(
10036: " mcode_version 0x%x, pci_device_id 0x%x, lib_version 0x%x\n",
10037: h->mcode_version, h->pci_device_id, h->lib_version);
10038:
10039: printk(
10040: " control_flag 0x%x, pci_slot_info 0x%x\n",
10041: h->control_flag, h->pci_slot_info);
10042: }
10043:
10044: /*
10045: * asc_prt_adv_scsi_req_q()
10046: *
10047: * Display an ADV_SCSI_REQ_Q structure.
10048: */
10049: STATIC void
10050: asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
10051: {
10052: int i;
10053: struct asc_sg_block *sg_ptr;
10054:
10055: printk("ADV_SCSI_REQ_Q at addr %x\n", (unsigned) q);
10056:
10057: printk(
10058: " target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
10059: q->target_id, q->target_lun, q->srb_ptr, q->a_flag);
10060:
10061: printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
10062: q->cntl, q->data_addr, q->vdata_addr);
10063:
10064: printk(
10065: " data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
10066: q->data_cnt, q->sense_addr, q->sense_len);
10067:
10068: printk(
10069: " cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
10070: q->cdb_len, q->done_status, q->host_status, q->scsi_status);
10071:
10072: printk(
10073: " vsense_addr 0x%lx, scsiq_ptr 0x%lx, ux_wk_data_cnt %lu\n",
10074: (ulong) q->vsense_addr, (ulong) q->scsiq_ptr,
10075: (ulong) q->ux_wk_data_cnt);
10076:
10077: printk(
10078: " sg_list_ptr 0x%lx, sg_real_addr 0x%lx, sg_entry_cnt %u\n",
10079: (ulong) q->sg_list_ptr, (ulong) q->sg_real_addr, q->sg_entry_cnt);
10080:
10081: printk(
10082: " ux_sg_ix %u, orig_sense_len %u\n",
10083: q->ux_sg_ix, q->orig_sense_len);
10084:
10085: /* Display the request's ADV_SG_BLOCK structures. */
10086: for (sg_ptr = q->sg_list_ptr, i = 0; sg_ptr != NULL;
10087: sg_ptr = sg_ptr->sg_ptr, i++) {
10088: /*
10089: * 'sg_ptr' is a physical address. Convert it to a virtual
10090: * address by indexing 'i' into the virtual address array
10091: * 'sg_list_ptr'.
10092: *
10093: * At the end of the each iteration of the loop 'sg_ptr' is
10094: * converted back into a physical address by setting 'sg_ptr'
10095: * to the next pointer 'sg_ptr->sg_ptr'.
10096: */
10097: sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[i]);
10098: asc_prt_adv_sgblock(i, sg_ptr);
10099: }
10100: }
10101:
10102: /*
10103: * asc_prt_adv_sgblock()
10104: *
10105: * Display an ADV_SG_BLOCK structure.
10106: */
10107: STATIC void
10108: asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
10109: {
10110: int i, s;
10111:
10112: /* Calculate starting entry number for the current block. */
10113: s = sgblockno * NO_OF_SG_PER_BLOCK;
10114:
10115: printk(" ADV_SG_BLOCK at addr 0x%lx (sgblockno %lu)\n",
10116: (ulong) b, (ulong) sgblockno);
10117: printk(
10118: " first_entry_no %lu, last_entry_no %lu, sg_ptr 0x%lx\n",
10119: (ulong) b->first_entry_no, (ulong) b->last_entry_no, (ulong) b->sg_ptr);
10120: ASC_ASSERT(b->first_entry_no - s >= 0);
10121: ASC_ASSERT(b->last_entry_no - s >= 0);
10122: ASC_ASSERT(b->last_entry_no - s <= NO_OF_SG_PER_BLOCK);
10123: ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
10124: ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
10125: ASC_ASSERT(b->first_entry_no - s <= b->last_entry_no - s);
10126: for (i = b->first_entry_no - s; i <= b->last_entry_no - s; i++) {
10127: printk(" [%lu]: sg_addr 0x%lx, sg_count 0x%lx\n",
10128: (ulong) i, (ulong) b->sg_list[i].sg_addr,
10129: (ulong) b->sg_list[i].sg_count);
10130: }
10131: }
10132:
10133: /*
10134: * asc_prt_hex()
10135: *
10136: * Print hexadecimal output in 4 byte groupings 32 bytes
10137: * or 8 double-words per line.
10138: */
10139: STATIC void
10140: asc_prt_hex(char *f, uchar *s, int l)
10141: {
10142: int i;
10143: int j;
10144: int k;
10145: int m;
10146:
10147: printk("%s: (%d bytes)\n", f, l);
10148:
10149: for (i = 0; i < l; i += 32) {
10150:
10151: /* Display a maximum of 8 double-words per line. */
10152: if ((k = (l - i) / 4) >= 8) {
10153: k = 8;
10154: m = 0;
10155: } else {
10156: m = (l - i) % 4 ;
10157: }
10158:
10159: for (j = 0; j < k; j++) {
10160: printk(" %2.2X%2.2X%2.2X%2.2X",
10161: (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
10162: (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
10163: }
10164:
10165: switch (m) {
10166: case 0:
10167: default:
10168: break;
10169: case 1:
10170: printk(" %2.2X",
10171: (unsigned) s[i+(j*4)]);
10172: break;
10173: case 2:
10174: printk(" %2.2X%2.2X",
10175: (unsigned) s[i+(j*4)],
10176: (unsigned) s[i+(j*4)+1]);
10177: break;
10178: case 3:
10179: printk(" %2.2X%2.2X%2.2X",
10180: (unsigned) s[i+(j*4)+1],
10181: (unsigned) s[i+(j*4)+2],
10182: (unsigned) s[i+(j*4)+3]);
10183: break;
10184: }
10185:
10186: printk("\n");
10187: }
10188: }
10189: #endif /* ADVANSYS_DEBUG */
10190:
10191: #ifdef ADVANSYS_ASSERT
10192: /*
10193: * interrupts_enabled()
10194: *
10195: * Return 1 if interrupts are enabled, otherwise return 0.
10196: */
10197: STATIC int
10198: interrupts_enabled(void)
10199: {
1.1.1.2 root 10200: long flags;
1.1 root 10201:
10202: save_flags(flags);
10203: if (flags & 0x0200) {
10204: return ASC_TRUE;
10205: } else {
10206: return ASC_FALSE;
10207: }
10208: }
10209: #endif /* ADVANSYS_ASSERT */
10210:
10211:
10212: /*
10213: * --- Asc Library Functions
10214: */
10215:
10216: ASC_INITFUNC(
10217: STATIC ushort
10218: AscGetEisaChipCfg(
10219: PortAddr iop_base
10220: )
10221: )
10222: {
10223: PortAddr eisa_cfg_iop;
10224:
10225: eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10226: (PortAddr) (ASC_EISA_CFG_IOP_MASK);
10227: return (inpw(eisa_cfg_iop));
10228: }
10229:
10230: ASC_INITFUNC(
10231: STATIC uchar
10232: AscSetChipScsiID(
10233: PortAddr iop_base,
10234: uchar new_host_id
10235: )
10236: )
10237: {
10238: ushort cfg_lsw;
10239:
10240: if (AscGetChipScsiID(iop_base) == new_host_id) {
10241: return (new_host_id);
10242: }
10243: cfg_lsw = AscGetChipCfgLsw(iop_base);
10244: cfg_lsw &= 0xF8FF;
10245: cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
10246: AscSetChipCfgLsw(iop_base, cfg_lsw);
10247: return (AscGetChipScsiID(iop_base));
10248: }
10249:
10250: ASC_INITFUNC(
10251: STATIC uchar
10252: AscGetChipScsiCtrl(
10253: PortAddr iop_base
10254: )
10255: )
10256: {
10257: uchar sc;
10258:
10259: AscSetBank(iop_base, 1);
10260: sc = inp(iop_base + IOP_REG_SC);
10261: AscSetBank(iop_base, 0);
10262: return (sc);
10263: }
10264:
10265: ASC_INITFUNC(
10266: STATIC uchar
10267: AscGetChipVersion(
10268: PortAddr iop_base,
10269: ushort bus_type
10270: )
10271: )
10272: {
10273: if ((bus_type & ASC_IS_EISA) != 0) {
10274: PortAddr eisa_iop;
10275: uchar revision;
10276: eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
10277: (PortAddr) ASC_EISA_REV_IOP_MASK;
10278: revision = inp(eisa_iop);
10279: return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
10280: }
10281: return (AscGetChipVerNo(iop_base));
10282: }
10283:
10284: ASC_INITFUNC(
10285: STATIC ushort
10286: AscGetChipBusType(
10287: PortAddr iop_base
10288: )
10289: )
10290: {
10291: ushort chip_ver;
10292:
10293: chip_ver = AscGetChipVerNo(iop_base);
10294: if (
10295: (chip_ver >= ASC_CHIP_MIN_VER_VL)
10296: && (chip_ver <= ASC_CHIP_MAX_VER_VL)
10297: ) {
10298: if (
10299: ((iop_base & 0x0C30) == 0x0C30)
10300: || ((iop_base & 0x0C50) == 0x0C50)
10301: ) {
10302: return (ASC_IS_EISA);
10303: }
10304: return (ASC_IS_VL);
10305: }
10306: if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
10307: (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
10308: if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
10309: return (ASC_IS_ISAPNP);
10310: }
10311: return (ASC_IS_ISA);
10312: } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
10313: (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
10314: return (ASC_IS_PCI);
10315: }
10316: return (0);
10317: }
10318:
10319: ASC_INITFUNC(
10320: STATIC ulong
10321: AscLoadMicroCode(
10322: PortAddr iop_base,
10323: ushort s_addr,
10324: ushort *mcode_buf,
10325: ushort mcode_size
10326: )
10327: )
10328: {
10329: ulong chksum;
10330: ushort mcode_word_size;
10331: ushort mcode_chksum;
10332:
10333: mcode_word_size = (ushort) (mcode_size >> 1);
10334: AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
10335: AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
10336: chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
10337: mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
10338: (ushort) ASC_CODE_SEC_BEG,
10339: (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
10340: AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
10341: AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
10342: return (chksum);
10343: }
10344:
10345: ASC_INITFUNC(
10346: STATIC int
10347: AscFindSignature(
10348: PortAddr iop_base
10349: )
10350: )
10351: {
10352: ushort sig_word;
10353:
10354: if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
10355: sig_word = AscGetChipSignatureWord(iop_base);
10356: if ((sig_word == (ushort) ASC_1000_ID0W) ||
10357: (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
10358: return (1);
10359: }
10360: }
10361: return (0);
10362: }
10363:
10364: STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
10365: STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
10366: {
10367: 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
10368: ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
10369: };
10370:
10371: ASC_INITFUNC(
10372: STATIC PortAddr
10373: AscSearchIOPortAddr(
10374: PortAddr iop_beg,
10375: ushort bus_type
10376: )
10377: )
10378: {
10379: if (bus_type & ASC_IS_VL) {
10380: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
10381: if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
10382: return (iop_beg);
10383: }
10384: }
10385: return (0);
10386: }
10387: if (bus_type & ASC_IS_ISA) {
10388: if (_isa_pnp_inited == 0) {
10389: AscSetISAPNPWaitForKey();
10390: _isa_pnp_inited++;
10391: }
10392: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
10393: if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
10394: return (iop_beg);
10395: }
10396: }
10397: return (0);
10398: }
10399: if (bus_type & ASC_IS_EISA) {
10400: if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
10401: return (iop_beg);
10402: }
10403: return (0);
10404: }
10405: return (0);
10406: }
10407:
10408: ASC_INITFUNC(
10409: STATIC PortAddr
10410: AscSearchIOPortAddr11(
10411: PortAddr s_addr
10412: )
10413: )
10414: {
10415: int i;
10416: PortAddr iop_base;
10417:
10418: for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
10419: if (_asc_def_iop_base[i] > s_addr) {
10420: break;
10421: }
10422: }
10423: for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
10424: iop_base = _asc_def_iop_base[i];
10425: if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
10426: ASC_DBG1(1,
10427: "AscSearchIOPortAddr11: check_region() failed I/O port %x\n",
10428: iop_base);
10429: continue;
10430: }
10431: ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base);
10432: if (AscFindSignature(iop_base)) {
10433: return (iop_base);
10434: }
10435: }
10436: return (0);
10437: }
10438:
10439: ASC_INITFUNC(
10440: STATIC void
10441: AscToggleIRQAct(
10442: PortAddr iop_base
10443: )
10444: )
10445: {
10446: AscSetChipStatus(iop_base, CIW_IRQ_ACT);
10447: AscSetChipStatus(iop_base, 0);
10448: return;
10449: }
10450:
10451: ASC_INITFUNC(
10452: STATIC void
10453: AscSetISAPNPWaitForKey(
10454: void)
10455: )
10456: {
10457: outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
10458: outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
10459: return;
10460: }
10461:
10462: ASC_INITFUNC(
10463: STATIC uchar
10464: AscGetChipIRQ(
10465: PortAddr iop_base,
10466: ushort bus_type
10467: )
10468: )
10469: {
10470: ushort cfg_lsw;
10471: uchar chip_irq;
10472:
10473: if ((bus_type & ASC_IS_EISA) != 0) {
10474: cfg_lsw = AscGetEisaChipCfg(iop_base);
10475: chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
10476: if ((chip_irq == 13) || (chip_irq > 15)) {
10477: return (0);
10478: }
10479: return (chip_irq);
10480: }
10481: if ((bus_type & ASC_IS_VL) != 0) {
10482: cfg_lsw = AscGetChipCfgLsw(iop_base);
10483: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
10484: if ((chip_irq == 0) ||
10485: (chip_irq == 4) ||
10486: (chip_irq == 7)) {
10487: return (0);
10488: }
10489: return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
10490: }
10491: cfg_lsw = AscGetChipCfgLsw(iop_base);
10492: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
10493: if (chip_irq == 3)
10494: chip_irq += (uchar) 2;
10495: return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
10496: }
10497:
10498: ASC_INITFUNC(
10499: STATIC uchar
10500: AscSetChipIRQ(
10501: PortAddr iop_base,
10502: uchar irq_no,
10503: ushort bus_type
10504: )
10505: )
10506: {
10507: ushort cfg_lsw;
10508:
10509: if ((bus_type & ASC_IS_VL) != 0) {
10510: if (irq_no != 0) {
10511: if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
10512: irq_no = 0;
10513: } else {
10514: irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
10515: }
10516: }
10517: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
10518: cfg_lsw |= (ushort) 0x0010;
10519: AscSetChipCfgLsw(iop_base, cfg_lsw);
10520: AscToggleIRQAct(iop_base);
10521: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
10522: cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
10523: AscSetChipCfgLsw(iop_base, cfg_lsw);
10524: AscToggleIRQAct(iop_base);
10525: return (AscGetChipIRQ(iop_base, bus_type));
10526: }
10527: if ((bus_type & (ASC_IS_ISA)) != 0) {
10528: if (irq_no == 15)
10529: irq_no -= (uchar) 2;
10530: irq_no -= (uchar) ASC_MIN_IRQ_NO;
10531: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
10532: cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
10533: AscSetChipCfgLsw(iop_base, cfg_lsw);
10534: return (AscGetChipIRQ(iop_base, bus_type));
10535: }
10536: return (0);
10537: }
10538:
10539: ASC_INITFUNC(
10540: STATIC void
10541: AscEnableIsaDma(
10542: uchar dma_channel
10543: )
10544: )
10545: {
10546: if (dma_channel < 4) {
10547: outp(0x000B, (ushort) (0xC0 | dma_channel));
10548: outp(0x000A, dma_channel);
10549: } else if (dma_channel < 8) {
10550: outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
10551: outp(0x00D4, (ushort) (dma_channel - 4));
10552: }
10553: return;
10554: }
10555:
10556: STATIC int
10557: AscIsrChipHalted(
10558: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
10559: )
10560: {
10561: EXT_MSG ext_msg;
10562: EXT_MSG out_msg;
10563: ushort halt_q_addr;
10564: int sdtr_accept;
10565: ushort int_halt_code;
10566: ASC_SCSI_BIT_ID_TYPE scsi_busy;
10567: ASC_SCSI_BIT_ID_TYPE target_id;
10568: PortAddr iop_base;
10569: uchar tag_code;
10570: uchar q_status;
10571: uchar halt_qp;
10572: uchar sdtr_data;
10573: uchar target_ix;
10574: uchar q_cntl, tid_no;
10575: uchar cur_dvc_qng;
10576: uchar asyn_sdtr;
10577: uchar scsi_status;
10578: asc_board_t *boardp;
10579:
10580: ASC_ASSERT(asc_dvc->drv_ptr != 0);
10581: boardp = (asc_board_t *) asc_dvc->drv_ptr;
10582:
10583: iop_base = asc_dvc->iop_base;
10584: int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
10585:
10586: halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
10587: halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
10588: target_ix = AscReadLramByte(iop_base,
10589: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
10590: q_cntl = AscReadLramByte(iop_base,
10591: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
10592: tid_no = ASC_TIX_TO_TID(target_ix);
10593: target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
10594: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10595:
10596: asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
10597: } else {
10598: asyn_sdtr = 0;
10599: }
10600: if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
10601: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10602: AscSetChipSDTR(iop_base, 0, tid_no);
10603: boardp->sdtr_data[tid_no] = 0;
10604: }
10605: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10606: return (0);
10607: } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
10608: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
10609: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10610: boardp->sdtr_data[tid_no] = asyn_sdtr;
10611: }
10612: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10613: return (0);
10614: } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
10615:
10616: AscMemWordCopyFromLram(iop_base,
10617: ASCV_MSGIN_BEG,
10618: (ushort *) & ext_msg,
10619: (ushort) (sizeof (EXT_MSG) >> 1));
10620:
10621: if (ext_msg.msg_type == MS_EXTEND &&
10622: ext_msg.msg_req == MS_SDTR_CODE &&
10623: ext_msg.msg_len == MS_SDTR_LEN) {
10624: sdtr_accept = TRUE;
10625: if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
10626:
10627: sdtr_accept = FALSE;
10628: ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
10629: }
10630: if ((ext_msg.xfer_period <
10631: asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) ||
10632: (ext_msg.xfer_period >
10633: asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) {
10634: sdtr_accept = FALSE;
10635: ext_msg.xfer_period =
10636: asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index];
10637: }
10638: if (sdtr_accept) {
10639: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10640: ext_msg.req_ack_offset);
10641: if ((sdtr_data == 0xFF)) {
10642:
10643: q_cntl |= QC_MSG_OUT;
10644: asc_dvc->init_sdtr &= ~target_id;
10645: asc_dvc->sdtr_done &= ~target_id;
10646: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10647: boardp->sdtr_data[tid_no] = asyn_sdtr;
10648: }
10649: }
10650: if (ext_msg.req_ack_offset == 0) {
10651:
10652: q_cntl &= ~QC_MSG_OUT;
10653: asc_dvc->init_sdtr &= ~target_id;
10654: asc_dvc->sdtr_done &= ~target_id;
10655: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10656: } else {
10657: if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
10658:
10659: q_cntl &= ~QC_MSG_OUT;
10660: asc_dvc->sdtr_done |= target_id;
10661: asc_dvc->init_sdtr |= target_id;
10662: asc_dvc->pci_fix_asyn_xfer &= ~target_id;
10663: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10664: ext_msg.req_ack_offset);
10665: AscSetChipSDTR(iop_base, sdtr_data, tid_no);
10666: boardp->sdtr_data[tid_no] = sdtr_data;
10667: } else {
10668:
10669: q_cntl |= QC_MSG_OUT;
10670: AscMsgOutSDTR(asc_dvc,
10671: ext_msg.xfer_period,
10672: ext_msg.req_ack_offset);
10673: asc_dvc->pci_fix_asyn_xfer &= ~target_id;
10674: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
10675: ext_msg.req_ack_offset);
10676: AscSetChipSDTR(iop_base, sdtr_data, tid_no);
10677: boardp->sdtr_data[tid_no] = sdtr_data;
10678: asc_dvc->sdtr_done |= target_id;
10679: asc_dvc->init_sdtr |= target_id;
10680: }
10681: }
10682:
10683: AscWriteLramByte(iop_base,
10684: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10685: q_cntl);
10686: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10687: return (0);
10688: } else if (ext_msg.msg_type == MS_EXTEND &&
10689: ext_msg.msg_req == MS_WDTR_CODE &&
10690: ext_msg.msg_len == MS_WDTR_LEN) {
10691:
10692: ext_msg.wdtr_width = 0;
10693: AscMemWordCopyToLram(iop_base,
10694: ASCV_MSGOUT_BEG,
10695: (ushort *) & ext_msg,
10696: (ushort) (sizeof (EXT_MSG) >> 1));
10697: q_cntl |= QC_MSG_OUT;
10698: AscWriteLramByte(iop_base,
10699: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10700: q_cntl);
10701: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10702: return (0);
10703: } else {
10704:
10705: ext_msg.msg_type = M1_MSG_REJECT;
10706: AscMemWordCopyToLram(iop_base,
10707: ASCV_MSGOUT_BEG,
10708: (ushort *) & ext_msg,
10709: (ushort) (sizeof (EXT_MSG) >> 1));
10710: q_cntl |= QC_MSG_OUT;
10711: AscWriteLramByte(iop_base,
10712: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10713: q_cntl);
10714: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10715: return (0);
10716: }
10717: } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
10718:
10719: q_cntl |= QC_REQ_SENSE;
10720:
10721: if ((asc_dvc->init_sdtr & target_id) != 0) {
10722:
10723: asc_dvc->sdtr_done &= ~target_id;
10724:
10725: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
10726: q_cntl |= QC_MSG_OUT;
10727: AscMsgOutSDTR(asc_dvc,
10728: asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
10729: (uchar) (asc_dvc->max_sdtr_index - 1)],
10730: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
10731: }
10732:
10733: AscWriteLramByte(iop_base,
10734: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10735: q_cntl);
10736:
10737: tag_code = AscReadLramByte(iop_base,
10738: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
10739: tag_code &= 0xDC;
10740: if (
10741: (asc_dvc->pci_fix_asyn_xfer & target_id)
10742: && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
10743: ) {
10744:
10745: tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
10746: | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
10747:
10748: }
10749: AscWriteLramByte(iop_base,
10750: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
10751: tag_code);
10752:
10753: q_status = AscReadLramByte(iop_base,
10754: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
10755: q_status |= (QS_READY | QS_BUSY);
10756: AscWriteLramByte(iop_base,
10757: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10758: q_status);
10759:
10760: scsi_busy = AscReadLramByte(iop_base,
10761: (ushort) ASCV_SCSIBUSY_B);
10762: scsi_busy &= ~target_id;
10763: AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10764:
10765: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10766: return (0);
10767: } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
10768:
10769: AscMemWordCopyFromLram(iop_base,
10770: ASCV_MSGOUT_BEG,
10771: (ushort *) & out_msg,
10772: (ushort) (sizeof (EXT_MSG) >> 1));
10773:
10774: if ((out_msg.msg_type == MS_EXTEND) &&
10775: (out_msg.msg_len == MS_SDTR_LEN) &&
10776: (out_msg.msg_req == MS_SDTR_CODE)) {
10777:
10778: asc_dvc->init_sdtr &= ~target_id;
10779: asc_dvc->sdtr_done &= ~target_id;
10780: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
10781: boardp->sdtr_data[tid_no] = asyn_sdtr;
10782: }
10783: q_cntl &= ~QC_MSG_OUT;
10784: AscWriteLramByte(iop_base,
10785: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
10786: q_cntl);
10787: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10788: return (0);
10789: } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
10790:
10791: scsi_status = AscReadLramByte(iop_base,
10792: (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
10793: cur_dvc_qng = AscReadLramByte(iop_base,
10794: (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
10795: if ((cur_dvc_qng > 0) &&
10796: (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
10797:
10798: scsi_busy = AscReadLramByte(iop_base,
10799: (ushort) ASCV_SCSIBUSY_B);
10800: scsi_busy |= target_id;
10801: AscWriteLramByte(iop_base,
10802: (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10803: asc_dvc->queue_full_or_busy |= target_id;
10804:
10805: if (scsi_status == SS_QUEUE_FULL) {
10806: if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
10807: cur_dvc_qng -= 1;
10808: asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
10809:
10810: AscWriteLramByte(iop_base,
10811: (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG +
10812: (ushort) tid_no),
10813: cur_dvc_qng);
10814:
10815: /*
10816: * Set the device queue depth to the number of
10817: * active requests when the QUEUE FULL condition
10818: * was encountered.
10819: */
10820: boardp->queue_full |= target_id;
10821: boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
10822: #if ASC_QUEUE_FLOW_CONTROL
10823: if (boardp->device[tid_no] != NULL &&
10824: boardp->device[tid_no]->queue_curr_depth >
10825: cur_dvc_qng) {
10826: boardp->device[tid_no]->queue_curr_depth =
10827: cur_dvc_qng;
10828: }
10829: #endif /* ASC_QUEUE_FLOW_CONTROL */
10830: }
10831: }
10832: }
10833: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
10834: return (0);
10835: }
10836: return (0);
10837: }
10838:
10839: STATIC uchar
10840: _AscCopyLramScsiDoneQ(
10841: PortAddr iop_base,
10842: ushort q_addr,
10843: REG ASC_QDONE_INFO * scsiq,
10844: ulong max_dma_count
10845: )
10846: {
10847: ushort _val;
10848: uchar sg_queue_cnt;
10849:
10850: DvcGetQinfo(iop_base,
10851: (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
10852: (ushort *) scsiq,
10853: (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
10854: _val = AscReadLramWord(iop_base,
10855: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
10856: scsiq->q_status = (uchar) _val;
10857: scsiq->q_no = (uchar) (_val >> 8);
10858: _val = AscReadLramWord(iop_base,
10859: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
10860: scsiq->cntl = (uchar) _val;
10861: sg_queue_cnt = (uchar) (_val >> 8);
10862: _val = AscReadLramWord(iop_base,
10863: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
10864: scsiq->sense_len = (uchar) _val;
10865: scsiq->extra_bytes = (uchar) (_val >> 8);
10866: scsiq->remain_bytes = AscReadLramWord(iop_base,
10867: (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
10868: scsiq->remain_bytes &= max_dma_count;
10869: return (sg_queue_cnt);
10870: }
10871:
10872: STATIC int
10873: AscIsrQDone(
10874: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
10875: )
10876: {
10877: uchar next_qp;
10878: uchar n_q_used;
10879: uchar sg_list_qp;
10880: uchar sg_queue_cnt;
10881: uchar q_cnt;
10882: uchar done_q_tail;
10883: uchar tid_no;
10884: ASC_SCSI_BIT_ID_TYPE scsi_busy;
10885: ASC_SCSI_BIT_ID_TYPE target_id;
10886: PortAddr iop_base;
10887: ushort q_addr;
10888: ushort sg_q_addr;
10889: uchar cur_target_qng;
10890: ASC_QDONE_INFO scsiq_buf;
10891: REG ASC_QDONE_INFO *scsiq;
10892: int false_overrun;
10893: ASC_ISR_CALLBACK asc_isr_callback;
10894:
10895: iop_base = asc_dvc->iop_base;
10896: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
10897: n_q_used = 1;
10898: scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
10899: done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
10900: q_addr = ASC_QNO_TO_QADDR(done_q_tail);
10901: next_qp = AscReadLramByte(iop_base,
10902: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
10903: if (next_qp != ASC_QLINK_END) {
10904: AscPutVarDoneQTail(iop_base, next_qp);
10905: q_addr = ASC_QNO_TO_QADDR(next_qp);
10906: sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
10907: asc_dvc->max_dma_count);
10908: AscWriteLramByte(iop_base,
10909: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10910: (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
10911: tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
10912: target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
10913: if ((scsiq->cntl & QC_SG_HEAD) != 0) {
10914: sg_q_addr = q_addr;
10915: sg_list_qp = next_qp;
10916: for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
10917: sg_list_qp = AscReadLramByte(iop_base,
10918: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
10919: sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
10920: if (sg_list_qp == ASC_QLINK_END) {
10921: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
10922: scsiq->d3.done_stat = QD_WITH_ERROR;
10923: scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
10924: goto FATAL_ERR_QDONE;
10925: }
10926: AscWriteLramByte(iop_base,
10927: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
10928: QS_FREE);
10929: }
10930: n_q_used = sg_queue_cnt + 1;
10931: AscPutVarDoneQTail(iop_base, sg_list_qp);
10932: }
10933: if (asc_dvc->queue_full_or_busy & target_id) {
10934: cur_target_qng = AscReadLramByte(iop_base,
10935: (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
10936: if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
10937: scsi_busy = AscReadLramByte(iop_base,
10938: (ushort) ASCV_SCSIBUSY_B);
10939: scsi_busy &= ~target_id;
10940: AscWriteLramByte(iop_base,
10941: (ushort) ASCV_SCSIBUSY_B, scsi_busy);
10942: asc_dvc->queue_full_or_busy &= ~target_id;
10943: }
10944: }
10945: if (asc_dvc->cur_total_qng >= n_q_used) {
10946: asc_dvc->cur_total_qng -= n_q_used;
10947: if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
10948: asc_dvc->cur_dvc_qng[tid_no]--;
10949: }
10950: } else {
10951: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
10952: scsiq->d3.done_stat = QD_WITH_ERROR;
10953: goto FATAL_ERR_QDONE;
10954: }
10955: if ((scsiq->d2.srb_ptr == 0UL) ||
10956: ((scsiq->q_status & QS_ABORTED) != 0)) {
10957: return (0x11);
10958: } else if (scsiq->q_status == QS_DONE) {
10959: false_overrun = FALSE;
10960: if (scsiq->extra_bytes != 0) {
10961: scsiq->remain_bytes += (ulong) scsiq->extra_bytes;
10962: }
10963: if (scsiq->d3.done_stat == QD_WITH_ERROR) {
10964: if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) {
10965: if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
10966: scsiq->d3.done_stat = QD_NO_ERROR;
10967: scsiq->d3.host_stat = QHSTA_NO_ERROR;
10968: } else if (false_overrun) {
10969: scsiq->d3.done_stat = QD_NO_ERROR;
10970: scsiq->d3.host_stat = QHSTA_NO_ERROR;
10971: }
10972: } else if (scsiq->d3.host_stat ==
10973: QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
10974: AscStopChip(iop_base);
10975: AscSetChipControl(iop_base,
10976: (uchar) (CC_SCSI_RESET | CC_HALT));
10977: DvcDelayNanoSecond(asc_dvc, 60000);
10978: AscSetChipControl(iop_base, CC_HALT);
10979: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
10980: AscSetChipStatus(iop_base, 0);
10981: AscSetChipControl(iop_base, 0);
10982: }
10983: }
10984: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
10985: (*asc_isr_callback) (asc_dvc, scsiq);
10986: } else {
10987: if ((AscReadLramByte(iop_base,
10988: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
10989: SCSICMD_StartStopUnit)) {
10990: asc_dvc->unit_not_ready &= ~target_id;
10991: if (scsiq->d3.done_stat != QD_NO_ERROR) {
10992: asc_dvc->start_motor &= ~target_id;
10993: }
10994: }
10995: }
10996: return (1);
10997: } else {
10998: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
10999: FATAL_ERR_QDONE:
11000: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
11001: (*asc_isr_callback) (asc_dvc, scsiq);
11002: }
11003: return (0x80);
11004: }
11005: }
11006: return (0);
11007: }
11008:
11009: STATIC int
11010: AscISR(
11011: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11012: )
11013: {
11014: ASC_CS_TYPE chipstat;
11015: PortAddr iop_base;
11016: ushort saved_ram_addr;
11017: uchar ctrl_reg;
11018: uchar saved_ctrl_reg;
11019: int int_pending;
11020: int status;
11021: uchar host_flag;
11022:
11023: iop_base = asc_dvc->iop_base;
11024: int_pending = FALSE;
11025: if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
11026: || (asc_dvc->isr_callback == 0)
11027: ) {
11028: return (ERR);
11029: }
11030: if (asc_dvc->in_critical_cnt != 0) {
11031: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
11032: return (ERR);
11033: }
11034: if (asc_dvc->is_in_int) {
11035: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
11036: return (ERR);
11037: }
11038: asc_dvc->is_in_int = TRUE;
11039: ctrl_reg = AscGetChipControl(iop_base);
11040: saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
11041: CC_SINGLE_STEP | CC_DIAG | CC_TEST));
11042: chipstat = AscGetChipStatus(iop_base);
11043: if (chipstat & CSW_SCSI_RESET_LATCH) {
11044: if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
11045: int_pending = TRUE;
11046: asc_dvc->sdtr_done = 0;
11047: saved_ctrl_reg &= (uchar) (~CC_HALT);
11048: while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
11049: AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
11050: AscSetChipControl(iop_base, CC_HALT);
11051: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
11052: AscSetChipStatus(iop_base, 0);
11053: chipstat = AscGetChipStatus(iop_base);
11054: }
11055: }
11056: saved_ram_addr = AscGetChipLramAddr(iop_base);
11057: host_flag = AscReadLramByte(iop_base,
11058: ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR);
11059: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
11060: (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
11061: if ((chipstat & CSW_INT_PENDING)
11062: || (int_pending)
11063: ) {
11064: AscAckInterrupt(iop_base);
11065: int_pending = TRUE;
11066: if ((chipstat & CSW_HALTED) &&
11067: (ctrl_reg & CC_SINGLE_STEP)) {
11068: if (AscIsrChipHalted(asc_dvc) == ERR) {
11069: goto ISR_REPORT_QDONE_FATAL_ERROR;
11070: } else {
11071: saved_ctrl_reg &= (uchar) (~CC_HALT);
11072: }
11073: } else {
11074: ISR_REPORT_QDONE_FATAL_ERROR:
11075: if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
11076: while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
11077: }
11078: } else {
11079: do {
11080: if ((status = AscIsrQDone(asc_dvc)) == 1) {
11081: break;
11082: }
11083: } while (status == 0x11);
11084: }
11085: if ((status & 0x80) != 0)
11086: int_pending = ERR;
11087: }
11088: }
11089: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
11090: AscSetChipLramAddr(iop_base, saved_ram_addr);
11091: AscSetChipControl(iop_base, saved_ctrl_reg);
11092: asc_dvc->is_in_int = FALSE;
11093: return (int_pending);
11094: }
11095:
11096: STATIC uchar _asc_mcode_buf[] ASC_INITDATA =
11097: {
11098: 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11099: 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11100: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11101: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11102: 0x00, 0x00, 0x00, 0x00, 0x91, 0x10, 0x0A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
11103: 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11104: 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
11105: 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00,
11106: 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
11107: 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80,
11108: 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
11109: 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
11110: 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00,
11111: 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1,
11112: 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0xA6, 0x97, 0xCE, 0x81, 0x00, 0x33,
11113: 0x02, 0x00, 0xC0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00,
11114: 0x84, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x03, 0xDE,
11115: 0x00, 0x33, 0x05, 0x00, 0xC0, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60,
11116: 0x00, 0xA2, 0x80, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x2C, 0x01, 0x80, 0x81, 0x03, 0x03, 0x80, 0x63,
11117: 0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC0, 0x88, 0x03, 0x07, 0x02, 0x01,
11118: 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98,
11119: 0xCD, 0x04, 0x15, 0x23, 0xF6, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03,
11120: 0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xC0, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01,
11121: 0x00, 0x33, 0x0B, 0x00, 0xC0, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC0, 0x88,
11122: 0x50, 0x04, 0x90, 0x81, 0x06, 0xAB, 0x8A, 0x01, 0x90, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x9A, 0x01,
11123: 0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
11124: 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xC6, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01,
11125: 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xBC, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D,
11126: 0x00, 0x33, 0x1B, 0x00, 0xC0, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
11127: 0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01,
11128: 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE,
11129: 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
11130: 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0,
11131: 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x67, 0xEB,
11132: 0x11, 0x23, 0xF6, 0x88, 0x04, 0x98, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x32, 0x02,
11133: 0x7C, 0x95, 0x06, 0xA6, 0x3C, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0xC0, 0x88, 0x04, 0x01, 0x03, 0xD8,
11134: 0xB2, 0x98, 0x6A, 0x96, 0x4E, 0x82, 0xFE, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D,
11135: 0x02, 0xA6, 0x78, 0x02, 0x07, 0xA6, 0x66, 0x02, 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x6E, 0x02,
11136: 0x00, 0x33, 0x10, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x50, 0x82, 0x60, 0x96, 0x50, 0x82, 0x04, 0x23,
11137: 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61,
11138: 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01,
11139: 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xB6, 0x02, 0x07, 0xA6, 0x66, 0x02,
11140: 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xC0, 0x02, 0x00, 0xA6, 0xC0, 0x02,
11141: 0x00, 0x33, 0x12, 0x00, 0xC0, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x98, 0x02,
11142: 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
11143: 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xF6, 0x82, 0x18, 0x23, 0x04, 0x61,
11144: 0x18, 0xA0, 0xEE, 0x02, 0x04, 0x01, 0x9C, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xC0, 0x88, 0x08, 0x31,
11145: 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x20, 0x03, 0x00, 0xA6,
11146: 0x20, 0x03, 0x07, 0xA6, 0x18, 0x03, 0x06, 0xA6, 0x1C, 0x03, 0x03, 0xA6, 0x20, 0x04, 0x02, 0xA6,
11147: 0x78, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xFA, 0x82, 0x60, 0x96, 0xFA, 0x82,
11148: 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01,
11149: 0x00, 0xA2, 0x60, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, 0x7E, 0x98, 0x00, 0xA6,
11150: 0x22, 0x03, 0x07, 0xA6, 0x58, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, 0x5C, 0x03, 0x01, 0xA6,
11151: 0x22, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x3E, 0x83, 0x60, 0x96, 0x3E, 0x83,
11152: 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0xC0, 0x88, 0x00, 0x01, 0x05, 0x05,
11153: 0xFF, 0xA2, 0x7E, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x3A, 0x83, 0x05, 0x05, 0x15, 0x01,
11154: 0x00, 0xA2, 0x9E, 0x03, 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
11155: 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0x9A, 0x03, 0x12, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
11156: 0xA8, 0x03, 0x00, 0xA6, 0xC0, 0x03, 0x12, 0x84, 0xA6, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA8, 0x03,
11157: 0x07, 0xA6, 0xB6, 0x03, 0xD8, 0x83, 0x7C, 0x95, 0xAC, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC0, 0x88,
11158: 0xA6, 0x98, 0x80, 0x42, 0x00, 0xA6, 0xC0, 0x03, 0x07, 0xA6, 0xCE, 0x03, 0xD8, 0x83, 0x7C, 0x95,
11159: 0xC4, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC0, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
11160: 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x12, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0xF6, 0x03, 0x80, 0x6B,
11161: 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x10, 0x04, 0x07, 0xA6, 0x08, 0x04, 0x06, 0xA6,
11162: 0x0C, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xF6, 0x83, 0x60, 0x96, 0xF6, 0x83,
11163: 0x20, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
11164: 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33,
11165: 0x30, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC,
11166: 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
11167: 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01,
11168: 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00,
11169: 0x00, 0x33, 0x1D, 0x00, 0xC0, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
11170: 0xC0, 0x88, 0x42, 0x23, 0xF6, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3,
11171: 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23,
11172: 0xF6, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF6, 0x88, 0x04, 0x98,
11173: 0x00, 0xA2, 0xC0, 0x04, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF0, 0x81,
11174: 0x47, 0x23, 0xF6, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x81,
11175: 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xF6, 0x88, 0x04, 0x23,
11176: 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33,
11177: 0x27, 0x00, 0xC0, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01,
11178: 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
11179: 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04,
11180: 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85,
11181: 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
11182: 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01,
11183: 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01,
11184: 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
11185: 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05,
11186: 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC0, 0x88, 0x04, 0xA0,
11187: 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
11188: 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85,
11189: 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0,
11190: 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
11191: 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63,
11192: 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF6, 0x88, 0x07, 0x23,
11193: 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
11194: 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03,
11195: 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC0, 0x88, 0x1D, 0x01, 0x01, 0xD6,
11196: 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
11197: 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61,
11198: 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01,
11199: 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
11200: 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6,
11201: 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20,
11202: 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
11203: 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
11204: 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43,
11205: 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
11206: 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06,
11207: 0x00, 0x33, 0x2A, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6,
11208: 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC0, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
11209: 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01,
11210: 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33,
11211: 0x2C, 0x00, 0xC0, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
11212: 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC0, 0x88, 0x00, 0x00, 0x80, 0x67,
11213: 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61,
11214: 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
11215: 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05,
11216: 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01,
11217: 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
11218: 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00,
11219: 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00,
11220: 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
11221: 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33,
11222: 0x07, 0x00, 0xC0, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01,
11223: 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
11224: 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63,
11225: 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02,
11226: 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
11227: 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04,
11228: 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08,
11229: 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
11230: 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01,
11231: 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08,
11232: 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
11233: 0x00, 0x33, 0x3E, 0x00, 0xC0, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B,
11234: 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09,
11235: 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
11236: 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E,
11237: 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB2, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63,
11238: 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, 0x13, 0x23,
11239: 0xF6, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62,
11240: 0xE0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7,
11241: 0x41, 0x23, 0xF6, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
11242: };
11243:
11244: STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf);
11245: STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012B5442UL;
11246:
11247: #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
11248: STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
11249: {
11250: SCSICMD_Inquiry,
11251: SCSICMD_RequestSense,
11252: SCSICMD_ReadCapacity,
11253: SCSICMD_ReadTOC,
11254: SCSICMD_ModeSelect6,
11255: SCSICMD_ModeSense6,
11256: SCSICMD_ModeSelect10,
11257: SCSICMD_ModeSense10,
11258: 0xFF,
11259: 0xFF,
11260: 0xFF,
11261: 0xFF,
11262: 0xFF,
11263: 0xFF,
11264: 0xFF,
11265: 0xFF
11266: };
11267:
11268: STATIC int
11269: AscExeScsiQueue(
11270: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11271: REG ASC_SCSI_Q * scsiq
11272: )
11273: {
11274: PortAddr iop_base;
11275: int last_int_level;
11276: int sta;
11277: int n_q_required;
11278: int disable_syn_offset_one_fix;
11279: int i;
11280: ulong addr;
11281: ASC_EXE_CALLBACK asc_exe_callback;
11282: ushort sg_entry_cnt = 0;
11283: ushort sg_entry_cnt_minus_one = 0;
11284: uchar target_ix;
11285: uchar tid_no;
11286: uchar sdtr_data;
11287: uchar extra_bytes;
11288: uchar scsi_cmd;
11289: uchar disable_cmd;
11290: ASC_SG_HEAD *sg_head;
11291: ulong data_cnt;
11292:
11293: iop_base = asc_dvc->iop_base;
11294: sg_head = scsiq->sg_head;
11295: asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
11296: if (asc_dvc->err_code != 0)
11297: return (ERR);
11298: if (scsiq == (ASC_SCSI_Q *) 0L) {
11299: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
11300: return (ERR);
11301: }
11302: scsiq->q1.q_no = 0;
11303: if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
11304: scsiq->q1.extra_bytes = 0;
11305: }
11306: sta = 0;
11307: target_ix = scsiq->q2.target_ix;
11308: tid_no = ASC_TIX_TO_TID(target_ix);
11309: n_q_required = 1;
11310: if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
11311: if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
11312: asc_dvc->sdtr_done &= ~scsiq->q1.target_id ;
11313: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11314: AscMsgOutSDTR(asc_dvc,
11315: asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
11316: (uchar) (asc_dvc->max_sdtr_index - 1)],
11317: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
11318: scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
11319: }
11320: }
11321: last_int_level = DvcEnterCritical();
11322: if (asc_dvc->in_critical_cnt != 0) {
11323: DvcLeaveCritical(last_int_level);
11324: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
11325: return (ERR);
11326: }
11327: asc_dvc->in_critical_cnt++;
11328: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
11329: if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
11330: asc_dvc->in_critical_cnt--;
11331: DvcLeaveCritical(last_int_level);
11332: return (ERR);
11333: }
11334: if (sg_entry_cnt > ASC_MAX_SG_LIST) {
11335: return (ERR);
11336: }
11337: if (sg_entry_cnt == 1) {
11338: scsiq->q1.data_addr = sg_head->sg_list[0].addr;
11339: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
11340: scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
11341: }
11342: sg_entry_cnt_minus_one = sg_entry_cnt - 1;
11343: }
11344: scsi_cmd = scsiq->cdbptr[0];
11345: disable_syn_offset_one_fix = FALSE;
11346: if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
11347: !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
11348: if (scsiq->q1.cntl & QC_SG_HEAD) {
11349: data_cnt = 0;
11350: for (i = 0; i < sg_entry_cnt; i++) {
11351: data_cnt += sg_head->sg_list[i].bytes;
11352: }
11353: } else {
11354: data_cnt = scsiq->q1.data_cnt;
11355: }
11356: if (data_cnt != 0UL) {
11357: if (data_cnt < 512UL) {
11358: disable_syn_offset_one_fix = TRUE;
11359: } else {
11360: for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) {
11361: disable_cmd = _syn_offset_one_disable_cmd[i];
11362: if (disable_cmd == 0xFF) {
11363: break;
11364: }
11365: if (scsi_cmd == disable_cmd) {
11366: disable_syn_offset_one_fix = TRUE;
11367: break;
11368: }
11369: }
11370: }
11371: }
11372: }
11373: if (disable_syn_offset_one_fix) {
11374: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
11375: scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
11376: ASC_TAG_FLAG_DISABLE_DISCONNECT);
11377: } else {
11378: scsiq->q2.tag_code &= 0x23;
11379: }
11380: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
11381: if (asc_dvc->bug_fix_cntl) {
11382: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11383: if ((scsi_cmd == SCSICMD_Read6) ||
11384: (scsi_cmd == SCSICMD_Read10)) {
11385: addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr +
11386: sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
11387: extra_bytes = (uchar) ((ushort) addr & 0x0003);
11388: if ((extra_bytes != 0) &&
11389: ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
11390: == 0)) {
11391: scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
11392: scsiq->q1.extra_bytes = extra_bytes;
11393: sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
11394: (ulong) extra_bytes;
11395: }
11396: }
11397: }
11398: }
11399: sg_head->entry_to_copy = sg_head->entry_cnt;
11400: n_q_required = AscSgListToQueue(sg_entry_cnt);
11401: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
11402: (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11403: if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11404: n_q_required)) == 1) {
11405: asc_dvc->in_critical_cnt--;
11406: if (asc_exe_callback != 0) {
11407: (*asc_exe_callback) (asc_dvc, scsiq);
11408: }
11409: DvcLeaveCritical(last_int_level);
11410: return (sta);
11411: }
11412: }
11413: } else {
11414: if (asc_dvc->bug_fix_cntl) {
11415: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
11416: if ((scsi_cmd == SCSICMD_Read6) ||
11417: (scsi_cmd == SCSICMD_Read10)) {
11418: addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
11419: extra_bytes = (uchar) ((ushort) addr & 0x0003);
11420: if ((extra_bytes != 0) &&
11421: ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
11422: == 0)) {
11423: if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
11424: scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
11425: scsiq->q1.data_cnt -= (ulong) extra_bytes;
11426: scsiq->q1.extra_bytes = extra_bytes;
11427: }
11428: }
11429: }
11430: }
11431: }
11432: n_q_required = 1;
11433: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
11434: ((scsiq->q1.cntl & QC_URGENT) != 0)) {
11435: if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
11436: n_q_required)) == 1) {
11437: asc_dvc->in_critical_cnt--;
11438: if (asc_exe_callback != 0) {
11439: (*asc_exe_callback) (asc_dvc, scsiq);
11440: }
11441: DvcLeaveCritical(last_int_level);
11442: return (sta);
11443: }
11444: }
11445: }
11446: asc_dvc->in_critical_cnt--;
11447: DvcLeaveCritical(last_int_level);
11448: return (sta);
11449: }
11450:
11451: STATIC int
11452: AscSendScsiQueue(
11453: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11454: REG ASC_SCSI_Q * scsiq,
11455: uchar n_q_required
11456: )
11457: {
11458: PortAddr iop_base;
11459: uchar free_q_head;
11460: uchar next_qp;
11461: uchar tid_no;
11462: uchar target_ix;
11463: int sta;
11464:
11465: iop_base = asc_dvc->iop_base;
11466: target_ix = scsiq->q2.target_ix;
11467: tid_no = ASC_TIX_TO_TID(target_ix);
11468: sta = 0;
11469: free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
11470: if (n_q_required > 1) {
11471: if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
11472: free_q_head, (uchar) (n_q_required)))
11473: != (uchar) ASC_QLINK_END) {
11474: asc_dvc->last_q_shortage = 0;
11475: scsiq->sg_head->queue_cnt = n_q_required - 1;
11476: scsiq->q1.q_no = free_q_head;
11477: if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
11478: free_q_head)) == 1) {
11479: AscPutVarFreeQHead(iop_base, next_qp);
11480: asc_dvc->cur_total_qng += (uchar) (n_q_required);
11481: asc_dvc->cur_dvc_qng[tid_no]++;
11482: }
11483: return (sta);
11484: }
11485: } else if (n_q_required == 1) {
11486: if ((next_qp = AscAllocFreeQueue(iop_base,
11487: free_q_head)) != ASC_QLINK_END) {
11488: scsiq->q1.q_no = free_q_head;
11489: if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
11490: free_q_head)) == 1) {
11491: AscPutVarFreeQHead(iop_base, next_qp);
11492: asc_dvc->cur_total_qng++;
11493: asc_dvc->cur_dvc_qng[tid_no]++;
11494: }
11495: return (sta);
11496: }
11497: }
11498: return (sta);
11499: }
11500:
11501: STATIC int
11502: AscSgListToQueue(
11503: int sg_list
11504: )
11505: {
11506: int n_sg_list_qs;
11507:
11508: n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
11509: if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
11510: n_sg_list_qs++;
11511: return (n_sg_list_qs + 1);
11512: }
11513:
11514:
11515: STATIC uint
11516: AscGetNumOfFreeQueue(
11517: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11518: uchar target_ix,
11519: uchar n_qs
11520: )
11521: {
11522: uint cur_used_qs;
11523: uint cur_free_qs;
11524: ASC_SCSI_BIT_ID_TYPE target_id;
11525: uchar tid_no;
11526:
11527: target_id = ASC_TIX_TO_TARGET_ID(target_ix);
11528: tid_no = ASC_TIX_TO_TID(target_ix);
11529: if ((asc_dvc->unit_not_ready & target_id) ||
11530: (asc_dvc->queue_full_or_busy & target_id)) {
11531: return (0);
11532: }
11533: if (n_qs == 1) {
11534: cur_used_qs = (uint) asc_dvc->cur_total_qng +
11535: (uint) asc_dvc->last_q_shortage +
11536: (uint) ASC_MIN_FREE_Q;
11537: } else {
11538: cur_used_qs = (uint) asc_dvc->cur_total_qng +
11539: (uint) ASC_MIN_FREE_Q;
11540: }
11541: if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
11542: cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
11543: if (asc_dvc->cur_dvc_qng[tid_no] >=
11544: asc_dvc->max_dvc_qng[tid_no]) {
11545: return (0);
11546: }
11547: return (cur_free_qs);
11548: }
11549: if (n_qs > 1) {
11550: if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
11551: asc_dvc->last_q_shortage = n_qs;
11552: }
11553: }
11554: return (0);
11555: }
11556:
11557: STATIC int
11558: AscPutReadyQueue(
11559: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11560: REG ASC_SCSI_Q * scsiq,
11561: uchar q_no
11562: )
11563: {
11564: ushort q_addr;
11565: uchar tid_no;
11566: uchar sdtr_data;
11567: uchar syn_period_ix;
11568: uchar syn_offset;
11569: PortAddr iop_base;
11570:
11571: iop_base = asc_dvc->iop_base;
11572: if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
11573: ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
11574: tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
11575: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
11576: syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
11577: syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
11578: AscMsgOutSDTR(asc_dvc,
11579: asc_dvc->sdtr_period_tbl[syn_period_ix],
11580: syn_offset);
11581: scsiq->q1.cntl |= QC_MSG_OUT;
11582: }
11583: q_addr = ASC_QNO_TO_QADDR(q_no);
11584: if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
11585: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
11586: }
11587: scsiq->q1.status = QS_FREE;
11588: AscMemWordCopyToLram(iop_base,
11589: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
11590: (ushort *) scsiq->cdbptr,
11591: (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
11592: DvcPutScsiQ(iop_base,
11593: (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
11594: (ushort *) & scsiq->q1.cntl,
11595: (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
11596: AscWriteLramWord(iop_base,
11597: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
11598: (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
11599: return (1);
11600: }
11601:
11602: STATIC int
11603: AscPutReadySgListQueue(
11604: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11605: REG ASC_SCSI_Q * scsiq,
11606: uchar q_no
11607: )
11608: {
11609: int sta;
11610: int i;
11611: ASC_SG_HEAD *sg_head;
11612: ASC_SG_LIST_Q scsi_sg_q;
11613: ulong saved_data_addr;
11614: ulong saved_data_cnt;
11615: PortAddr iop_base;
11616: ushort sg_list_dwords;
11617: ushort sg_index;
11618: ushort sg_entry_cnt;
11619: ushort q_addr;
11620: uchar next_qp;
11621:
11622: iop_base = asc_dvc->iop_base;
11623: sg_head = scsiq->sg_head;
11624: saved_data_addr = scsiq->q1.data_addr;
11625: saved_data_cnt = scsiq->q1.data_cnt;
11626: scsiq->q1.data_addr = sg_head->sg_list[0].addr;
11627: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
11628: sg_entry_cnt = sg_head->entry_cnt - 1;
11629: if (sg_entry_cnt != 0) {
11630: scsiq->q1.cntl |= QC_SG_HEAD;
11631: q_addr = ASC_QNO_TO_QADDR(q_no);
11632: sg_index = 1;
11633: scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
11634: scsi_sg_q.sg_head_qp = q_no;
11635: scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
11636: for (i = 0; i < sg_head->queue_cnt; i++) {
11637: scsi_sg_q.seq_no = i + 1;
11638: if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
11639: sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
11640: sg_entry_cnt -= ASC_SG_LIST_PER_Q;
11641: if (i == 0) {
11642: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
11643: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
11644: } else {
11645: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
11646: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
11647: }
11648: } else {
11649: scsi_sg_q.cntl |= QCSG_SG_XFER_END;
11650: sg_list_dwords = sg_entry_cnt << 1;
11651: if (i == 0) {
11652: scsi_sg_q.sg_list_cnt = sg_entry_cnt;
11653: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
11654: } else {
11655: scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
11656: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
11657: }
11658: sg_entry_cnt = 0;
11659: }
11660: next_qp = AscReadLramByte(iop_base,
11661: (ushort) (q_addr + ASC_SCSIQ_B_FWD));
11662: scsi_sg_q.q_no = next_qp;
11663: q_addr = ASC_QNO_TO_QADDR(next_qp);
11664: AscMemWordCopyToLram(iop_base,
11665: (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
11666: (ushort *) & scsi_sg_q,
11667: (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
11668: AscMemDWordCopyToLram(iop_base,
11669: (ushort) (q_addr + ASC_SGQ_LIST_BEG),
11670: (ulong *) & sg_head->sg_list[sg_index],
11671: (ushort) sg_list_dwords);
11672: sg_index += ASC_SG_LIST_PER_Q;
11673: }
11674: } else {
11675: scsiq->q1.cntl &= ~QC_SG_HEAD;
11676: }
11677: sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
11678: scsiq->q1.data_addr = saved_data_addr;
11679: scsiq->q1.data_cnt = saved_data_cnt;
11680: return (sta);
11681: }
11682:
11683: STATIC int
11684: AscAbortSRB(
11685: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11686: ulong srb_ptr
11687: )
11688: {
11689: int sta;
11690: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
11691: PortAddr iop_base;
11692:
11693: iop_base = asc_dvc->iop_base;
11694: sta = ERR;
11695: saved_unit_not_ready = asc_dvc->unit_not_ready;
11696: asc_dvc->unit_not_ready = 0xFF;
11697: AscWaitISRDone(asc_dvc);
11698: if (AscStopQueueExe(iop_base) == 1) {
11699: if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
11700: sta = 1;
11701: AscCleanUpBusyQueue(iop_base);
11702: AscStartQueueExe(iop_base);
11703: } else {
11704: sta = 0;
11705: AscStartQueueExe(iop_base);
11706: }
11707: }
11708: asc_dvc->unit_not_ready = saved_unit_not_ready;
11709: return (sta);
11710: }
11711:
11712: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
11713: STATIC int
11714: AscResetDevice(
11715: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11716: uchar target_ix
11717: )
11718: {
11719: PortAddr iop_base;
11720: int sta;
11721: uchar tid_no;
11722:
11723: ASC_SCSI_BIT_ID_TYPE target_id;
11724: int i;
11725: ASC_SCSI_REQ_Q scsiq_buf;
11726: ASC_SCSI_REQ_Q *scsiq;
11727: uchar *buf;
11728: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
11729: iop_base = asc_dvc->iop_base;
11730: tid_no = ASC_TIX_TO_TID(target_ix);
11731: target_id = ASC_TID_TO_TARGET_ID(tid_no);
11732: saved_unit_not_ready = asc_dvc->unit_not_ready;
11733: asc_dvc->unit_not_ready = target_id;
11734: sta = ERR;
11735: AscWaitTixISRDone(asc_dvc, target_ix);
11736: if (AscStopQueueExe(iop_base) == 1) {
11737: if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
11738: AscCleanUpBusyQueue(iop_base);
11739: AscStartQueueExe(iop_base);
11740: AscWaitTixISRDone(asc_dvc, target_ix);
11741: sta = TRUE;
11742: scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
11743: buf = (uchar *) & scsiq_buf;
11744: for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
11745: *buf++ = 0x00;
11746: }
11747: scsiq->r1.status = (uchar) QS_READY;
11748: scsiq->r2.cdb_len = 6;
11749: scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
11750: scsiq->r1.target_id = target_id;
11751: scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
11752: scsiq->cdbptr = (uchar *) scsiq->cdb;
11753: scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
11754: AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
11755: M1_BUS_DVC_RESET);
11756: asc_dvc->unit_not_ready &= ~target_id;
11757: asc_dvc->sdtr_done |= target_id;
11758: if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq)
11759: == 1) {
11760: asc_dvc->unit_not_ready = target_id;
11761: DvcSleepMilliSecond(1000);
11762: _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq);
11763: if (AscStopQueueExe(iop_base) == 1) {
11764: AscCleanUpDiscQueue(iop_base);
11765: AscStartQueueExe(iop_base);
11766: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
11767: AscSetRunChipSynRegAtID(iop_base, tid_no,
11768: ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11769: }
11770: AscWaitTixISRDone(asc_dvc, target_ix);
11771: }
11772: } else {
11773: sta = 0;
11774: }
11775: asc_dvc->sdtr_done &= ~target_id;
11776: } else {
11777: sta = ERR;
11778: AscStartQueueExe(iop_base);
11779: }
11780: }
11781: asc_dvc->unit_not_ready = saved_unit_not_ready;
11782: return (sta);
11783: }
11784: #endif /* version >= v1.3.89 */
11785:
11786: STATIC int
11787: AscResetSB(
11788: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11789: )
11790: {
11791: int sta;
11792: int i;
11793: PortAddr iop_base;
11794:
11795: iop_base = asc_dvc->iop_base;
11796: asc_dvc->unit_not_ready = 0xFF;
11797: sta = TRUE;
11798: AscWaitISRDone(asc_dvc);
11799: AscStopQueueExe(iop_base);
11800: asc_dvc->sdtr_done = 0;
11801: AscResetChipAndScsiBus(asc_dvc);
11802: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
11803: AscReInitLram(asc_dvc);
11804: for (i = 0; i <= ASC_MAX_TID; i++) {
11805: asc_dvc->cur_dvc_qng[i] = 0;
11806: if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) {
11807: AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
11808: }
11809: }
11810: asc_dvc->err_code = 0;
11811: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
11812: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
11813: sta = ERR;
11814: }
11815: if (AscStartChip(iop_base) == 0) {
11816: sta = ERR;
11817: }
11818: AscStartQueueExe(iop_base);
11819: asc_dvc->unit_not_ready = 0;
11820: asc_dvc->queue_full_or_busy = 0;
11821: return (sta);
11822: }
11823:
11824: STATIC int
11825: AscSetRunChipSynRegAtID(
11826: PortAddr iop_base,
11827: uchar tid_no,
11828: uchar sdtr_data
11829: )
11830: {
11831: int sta = FALSE;
11832:
11833: if (AscHostReqRiscHalt(iop_base)) {
11834: sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
11835: AscStartChip(iop_base);
11836: return (sta);
11837: }
11838: return (sta);
11839: }
11840:
11841: STATIC int
11842: AscSetChipSynRegAtID(
11843: PortAddr iop_base,
11844: uchar id,
11845: uchar sdtr_data
11846: )
11847: {
11848: ASC_SCSI_BIT_ID_TYPE org_id;
11849: int i;
11850: int sta = TRUE;
11851:
11852: AscSetBank(iop_base, 1);
11853: org_id = AscReadChipDvcID(iop_base);
11854: for (i = 0; i <= ASC_MAX_TID; i++) {
11855: if (org_id == (0x01 << i))
11856: break;
11857: }
11858: org_id = i;
11859: AscWriteChipDvcID(iop_base, id);
11860: if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
11861: AscSetBank(iop_base, 0);
11862: AscSetChipSyn(iop_base, sdtr_data);
11863: if (AscGetChipSyn(iop_base) != sdtr_data) {
11864: sta = FALSE;
11865: }
11866: } else {
11867: sta = FALSE;
11868: }
11869: AscSetBank(iop_base, 1);
11870: AscWriteChipDvcID(iop_base, org_id);
11871: AscSetBank(iop_base, 0);
11872: return (sta);
11873: }
11874:
11875: STATIC int
11876: AscReInitLram(
11877: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11878: )
11879: {
11880: AscInitLram(asc_dvc);
11881: AscInitQLinkVar(asc_dvc);
11882: return (0);
11883: }
11884:
11885: STATIC ushort
11886: AscInitLram(
11887: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11888: )
11889: {
11890: uchar i;
11891: ushort s_addr;
11892: PortAddr iop_base;
11893: ushort warn_code;
11894:
11895: iop_base = asc_dvc->iop_base;
11896: warn_code = 0;
11897: AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
11898: (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
11899: );
11900: i = ASC_MIN_ACTIVE_QNO;
11901: s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
11902: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11903: (uchar) (i + 1));
11904: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11905: (uchar) (asc_dvc->max_total_qng));
11906: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11907: (uchar) i);
11908: i++;
11909: s_addr += ASC_QBLK_SIZE;
11910: for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
11911: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11912: (uchar) (i + 1));
11913: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11914: (uchar) (i - 1));
11915: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11916: (uchar) i);
11917: }
11918: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
11919: (uchar) ASC_QLINK_END);
11920: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
11921: (uchar) (asc_dvc->max_total_qng - 1));
11922: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
11923: (uchar) asc_dvc->max_total_qng);
11924: i++;
11925: s_addr += ASC_QBLK_SIZE;
11926: for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
11927: i++, s_addr += ASC_QBLK_SIZE) {
11928: AscWriteLramByte(iop_base,
11929: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
11930: AscWriteLramByte(iop_base,
11931: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
11932: AscWriteLramByte(iop_base,
11933: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
11934: }
11935: return (warn_code);
11936: }
11937:
11938: STATIC ushort
11939: AscInitQLinkVar(
11940: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
11941: )
11942: {
11943: PortAddr iop_base;
11944: int i;
11945: ushort lram_addr;
11946:
11947: iop_base = asc_dvc->iop_base;
11948: AscPutRiscVarFreeQHead(iop_base, 1);
11949: AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
11950: AscPutVarFreeQHead(iop_base, 1);
11951: AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
11952: AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
11953: (uchar) ((int) asc_dvc->max_total_qng + 1));
11954: AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
11955: (uchar) ((int) asc_dvc->max_total_qng + 2));
11956: AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
11957: asc_dvc->max_total_qng);
11958: AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
11959: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
11960: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
11961: AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
11962: AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
11963: AscPutQDoneInProgress(iop_base, 0);
11964: lram_addr = ASC_QADR_BEG;
11965: for (i = 0; i < 32; i++, lram_addr += 2) {
11966: AscWriteLramWord(iop_base, lram_addr, 0);
11967: }
11968: return (0);
11969: }
11970:
11971: STATIC int
11972: AscSetLibErrorCode(
11973: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
11974: ushort err_code
11975: )
11976: {
11977: if (asc_dvc->err_code == 0) {
11978: asc_dvc->err_code = err_code;
11979: AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
11980: err_code);
11981: }
11982: return (err_code);
11983: }
11984:
11985:
11986: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
11987: STATIC int
11988: _AscWaitQDone(
11989: PortAddr iop_base,
11990: REG ASC_SCSI_Q * scsiq
11991: )
11992: {
11993: ushort q_addr;
11994: uchar q_status;
11995: int count = 0;
11996:
11997: while (scsiq->q1.q_no == 0) ;
11998: q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
11999: do {
12000: q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
12001: DvcSleepMilliSecond(100L);
12002: if (count++ > 30) {
12003: return (0);
12004: }
12005: } while ((q_status & QS_READY) != 0);
12006: return (1);
12007: }
12008: #endif /* version >= v1.3.89 */
12009:
12010: STATIC uchar
12011: AscMsgOutSDTR(
12012: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12013: uchar sdtr_period,
12014: uchar sdtr_offset
12015: )
12016: {
12017: EXT_MSG sdtr_buf;
12018: uchar sdtr_period_index;
12019: PortAddr iop_base;
12020:
12021: iop_base = asc_dvc->iop_base;
12022: sdtr_buf.msg_type = MS_EXTEND;
12023: sdtr_buf.msg_len = MS_SDTR_LEN;
12024: sdtr_buf.msg_req = MS_SDTR_CODE;
12025: sdtr_buf.xfer_period = sdtr_period;
12026: sdtr_offset &= ASC_SYN_MAX_OFFSET;
12027: sdtr_buf.req_ack_offset = sdtr_offset;
12028: if ((sdtr_period_index =
12029: AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
12030: asc_dvc->max_sdtr_index) {
12031: AscMemWordCopyToLram(iop_base,
12032: ASCV_MSGOUT_BEG,
12033: (ushort *) & sdtr_buf,
12034: (ushort) (sizeof (EXT_MSG) >> 1));
12035: return ((sdtr_period_index << 4) | sdtr_offset);
12036: } else {
12037:
12038: sdtr_buf.req_ack_offset = 0;
12039: AscMemWordCopyToLram(iop_base,
12040: ASCV_MSGOUT_BEG,
12041: (ushort *) & sdtr_buf,
12042: (ushort) (sizeof (EXT_MSG) >> 1));
12043: return (0);
12044: }
12045: }
12046:
12047: STATIC uchar
12048: AscCalSDTRData(
12049: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12050: uchar sdtr_period,
12051: uchar syn_offset
12052: )
12053: {
12054: uchar byte;
12055: uchar sdtr_period_ix;
12056:
12057: sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
12058: if (
12059: (sdtr_period_ix > asc_dvc->max_sdtr_index)
12060: ) {
12061: return (0xFF);
12062: }
12063: byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
12064: return (byte);
12065: }
12066:
12067: STATIC void
12068: AscSetChipSDTR(
12069: PortAddr iop_base,
12070: uchar sdtr_data,
12071: uchar tid_no
12072: )
12073: {
12074: AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
12075: AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
12076: return;
12077: }
12078:
12079: STATIC uchar
12080: AscGetSynPeriodIndex(
12081: ASC_DVC_VAR asc_ptr_type * asc_dvc,
12082: ruchar syn_time
12083: )
12084: {
12085: ruchar *period_table;
12086: int max_index;
12087: int min_index;
12088: int i;
12089:
12090: period_table = asc_dvc->sdtr_period_tbl;
12091: max_index = (int) asc_dvc->max_sdtr_index;
12092: min_index = (int)asc_dvc->host_init_sdtr_index ;
12093: if ((syn_time <= period_table[max_index])) {
12094: for (i = min_index; i < (max_index - 1); i++) {
12095: if (syn_time <= period_table[i]) {
12096: return ((uchar) i);
12097: }
12098: }
12099: return ((uchar) max_index);
12100: } else {
12101: return ((uchar) (max_index + 1));
12102: }
12103: }
12104:
12105: STATIC uchar
12106: AscAllocFreeQueue(
12107: PortAddr iop_base,
12108: uchar free_q_head
12109: )
12110: {
12111: ushort q_addr;
12112: uchar next_qp;
12113: uchar q_status;
12114:
12115: q_addr = ASC_QNO_TO_QADDR(free_q_head);
12116: q_status = (uchar) AscReadLramByte(iop_base,
12117: (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
12118: next_qp = AscReadLramByte(iop_base,
12119: (ushort) (q_addr + ASC_SCSIQ_B_FWD));
12120: if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
12121: return (next_qp);
12122: }
12123: return (ASC_QLINK_END);
12124: }
12125:
12126: STATIC uchar
12127: AscAllocMultipleFreeQueue(
12128: PortAddr iop_base,
12129: uchar free_q_head,
12130: uchar n_free_q
12131: )
12132: {
12133: uchar i;
12134:
12135: for (i = 0; i < n_free_q; i++) {
12136: if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
12137: == ASC_QLINK_END) {
12138: return (ASC_QLINK_END);
12139: }
12140: }
12141: return (free_q_head);
12142: }
12143:
12144: STATIC int
12145: AscRiscHaltedAbortSRB(
12146: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12147: ulong srb_ptr
12148: )
12149: {
12150: PortAddr iop_base;
12151: ushort q_addr;
12152: uchar q_no;
12153: ASC_QDONE_INFO scsiq_buf;
12154: ASC_QDONE_INFO *scsiq;
12155: ASC_ISR_CALLBACK asc_isr_callback;
12156: int last_int_level;
12157:
12158: iop_base = asc_dvc->iop_base;
12159: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
12160: last_int_level = DvcEnterCritical();
12161: scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
12162: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
12163: q_no++) {
12164: q_addr = ASC_QNO_TO_QADDR(q_no);
12165: scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
12166: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
12167: if (scsiq->d2.srb_ptr == srb_ptr) {
12168: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
12169: if (((scsiq->q_status & QS_READY) != 0)
12170: && ((scsiq->q_status & QS_ABORTED) == 0)
12171: && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
12172: scsiq->q_status |= QS_ABORTED;
12173: scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
12174: AscWriteLramDWord(iop_base,
12175: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
12176: 0L);
12177: AscWriteLramByte(iop_base,
12178: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12179: scsiq->q_status);
12180: (*asc_isr_callback) (asc_dvc, scsiq);
12181: return (1);
12182: }
12183: }
12184: }
12185: DvcLeaveCritical(last_int_level);
12186: return (0);
12187: }
12188:
12189: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12190: STATIC int
12191: AscRiscHaltedAbortTIX(
12192: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12193: uchar target_ix
12194: )
12195: {
12196: PortAddr iop_base;
12197: ushort q_addr;
12198: uchar q_no;
12199: ASC_QDONE_INFO scsiq_buf;
12200: ASC_QDONE_INFO *scsiq;
12201: ASC_ISR_CALLBACK asc_isr_callback;
12202: int last_int_level;
12203:
12204: iop_base = asc_dvc->iop_base;
12205: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
12206: last_int_level = DvcEnterCritical();
12207: scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
12208: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
12209: q_no++) {
12210: q_addr = ASC_QNO_TO_QADDR(q_no);
12211: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
12212: if (((scsiq->q_status & QS_READY) != 0) &&
12213: ((scsiq->q_status & QS_ABORTED) == 0) &&
12214: ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
12215: if (scsiq->d2.target_ix == target_ix) {
12216: scsiq->q_status |= QS_ABORTED;
12217: scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
12218: AscWriteLramDWord(iop_base,
12219: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
12220: 0L);
12221: AscWriteLramByte(iop_base,
12222: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
12223: scsiq->q_status);
12224: (*asc_isr_callback) (asc_dvc, scsiq);
12225: }
12226: }
12227: }
12228: DvcLeaveCritical(last_int_level);
12229: return (1);
12230: }
12231: #endif /* version >= v1.3.89 */
12232:
12233: STATIC int
12234: AscHostReqRiscHalt(
12235: PortAddr iop_base
12236: )
12237: {
12238: int count = 0;
12239: int sta = 0;
12240: uchar saved_stop_code;
12241:
12242: if (AscIsChipHalted(iop_base))
12243: return (1);
12244: saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12245: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12246: ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
12247: );
12248: do {
12249: if (AscIsChipHalted(iop_base)) {
12250: sta = 1;
12251: break;
12252: }
12253: DvcSleepMilliSecond(100);
12254: } while (count++ < 20);
12255: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
12256: return (sta);
12257: }
12258:
12259: STATIC int
12260: AscStopQueueExe(
12261: PortAddr iop_base
12262: )
12263: {
12264: int count = 0;
12265:
12266: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
12267: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12268: ASC_STOP_REQ_RISC_STOP);
12269: do {
12270: if (
12271: AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
12272: ASC_STOP_ACK_RISC_STOP) {
12273: return (1);
12274: }
12275: DvcSleepMilliSecond(100);
12276: } while (count++ < 20);
12277: }
12278: return (0);
12279: }
12280:
12281: STATIC int
12282: AscStartQueueExe(
12283: PortAddr iop_base
12284: )
12285: {
12286: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12287: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
12288: }
12289: return (1);
12290: }
12291:
12292: STATIC int
12293: AscCleanUpBusyQueue(
12294: PortAddr iop_base
12295: )
12296: {
12297: int count;
12298: uchar stop_code;
12299:
12300: count = 0;
12301: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12302: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12303: ASC_STOP_CLEAN_UP_BUSY_Q);
12304: do {
12305: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12306: if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
12307: break;
12308: DvcSleepMilliSecond(100);
12309: } while (count++ < 20);
12310: }
12311: return (1);
12312: }
12313:
12314: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
12315: STATIC int
12316: AscCleanUpDiscQueue(
12317: PortAddr iop_base
12318: )
12319: {
12320: int count;
12321: uchar stop_code;
12322:
12323: count = 0;
12324: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
12325: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
12326: ASC_STOP_CLEAN_UP_DISC_Q);
12327: do {
12328: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
12329: if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
12330: break;
12331: DvcSleepMilliSecond(100);
12332: } while (count++ < 20);
12333: }
12334: return (1);
12335: }
12336: #endif /* version >= v1.3.89 */
12337:
12338: STATIC int
12339: AscWaitTixISRDone(
12340: ASC_DVC_VAR asc_ptr_type * asc_dvc,
12341: uchar target_ix
12342: )
12343: {
12344: uchar cur_req;
12345: uchar tid_no;
12346: int i = 0;
12347:
12348: tid_no = ASC_TIX_TO_TID(target_ix);
12349: while (i++ < 10) {
12350: if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
12351: break;
12352: }
12353: DvcSleepMilliSecond(1000L);
12354: if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
12355: break;
12356: }
12357: }
12358: return (1);
12359: }
12360:
12361: STATIC int
12362: AscWaitISRDone(
12363: REG ASC_DVC_VAR asc_ptr_type * asc_dvc
12364: )
12365: {
12366: int tid;
12367:
12368: for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12369: AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
12370: }
12371: return (1);
12372: }
12373:
12374: STATIC ulong
12375: AscGetOnePhyAddr(
12376: REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
12377: uchar * buf_addr,
12378: ulong buf_size
12379: )
12380: {
12381: ASC_MIN_SG_HEAD sg_head;
12382:
12383: sg_head.entry_cnt = ASC_MIN_SG_LIST;
12384: if (DvcGetSGList(asc_dvc, (uchar *) buf_addr,
12385: buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) {
12386: return (0L);
12387: }
12388: if (sg_head.entry_cnt > 1) {
12389: return (0L);
12390: }
12391: return (sg_head.sg_list[0].addr);
12392: }
12393:
12394: STATIC void
12395: DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
12396: {
12397: udelay(micro_sec);
12398: }
12399:
12400: STATIC void
12401: DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type * asc_dvc, ulong nano_sec)
12402: {
12403: udelay((nano_sec + 999)/1000);
12404: }
12405:
12406: ASC_INITFUNC(
12407: STATIC ulong
12408: AscGetEisaProductID(
12409: PortAddr iop_base
12410: )
12411: )
12412: {
12413: PortAddr eisa_iop;
12414: ushort product_id_high, product_id_low;
12415: ulong product_id;
12416:
12417: eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
12418: product_id_low = inpw(eisa_iop);
12419: product_id_high = inpw(eisa_iop + 2);
12420: product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
12421: return (product_id);
12422: }
12423:
12424: ASC_INITFUNC(
12425: STATIC PortAddr
12426: AscSearchIOPortAddrEISA(
12427: PortAddr iop_base
12428: )
12429: )
12430: {
12431: ulong eisa_product_id;
12432:
12433: if (iop_base == 0) {
12434: iop_base = ASC_EISA_MIN_IOP_ADDR;
12435: } else {
12436: if (iop_base == ASC_EISA_MAX_IOP_ADDR)
12437: return (0);
12438: if ((iop_base & 0x0050) == 0x0050) {
12439: iop_base += ASC_EISA_BIG_IOP_GAP;
12440: } else {
12441: iop_base += ASC_EISA_SMALL_IOP_GAP;
12442: }
12443: }
12444: while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
12445: eisa_product_id = AscGetEisaProductID(iop_base);
12446: if ((eisa_product_id == ASC_EISA_ID_740) ||
12447: (eisa_product_id == ASC_EISA_ID_750)) {
12448: if (AscFindSignature(iop_base)) {
12449: inpw(iop_base + 4);
12450: return (iop_base);
12451: }
12452: }
12453: if (iop_base == ASC_EISA_MAX_IOP_ADDR)
12454: return (0);
12455: if ((iop_base & 0x0050) == 0x0050) {
12456: iop_base += ASC_EISA_BIG_IOP_GAP;
12457: } else {
12458: iop_base += ASC_EISA_SMALL_IOP_GAP;
12459: }
12460: }
12461: return (0);
12462: }
12463:
12464: STATIC int
12465: AscStartChip(
12466: PortAddr iop_base
12467: )
12468: {
12469: AscSetChipControl(iop_base, 0);
12470: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
12471: return (0);
12472: }
12473: return (1);
12474: }
12475:
12476: STATIC int
12477: AscStopChip(
12478: PortAddr iop_base
12479: )
12480: {
12481: uchar cc_val;
12482:
12483: cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
12484: AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
12485: AscSetChipIH(iop_base, INS_HALT);
12486: AscSetChipIH(iop_base, INS_RFLAG_WTM);
12487: if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
12488: return (0);
12489: }
12490: return (1);
12491: }
12492:
12493: STATIC int
12494: AscIsChipHalted(
12495: PortAddr iop_base
12496: )
12497: {
12498: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
12499: if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
12500: return (1);
12501: }
12502: }
12503: return (0);
12504: }
12505:
12506: STATIC void
12507: AscSetChipIH(
12508: PortAddr iop_base,
12509: ushort ins_code
12510: )
12511: {
12512: AscSetBank(iop_base, 1);
12513: AscWriteChipIH(iop_base, ins_code);
12514: AscSetBank(iop_base, 0);
12515: return;
12516: }
12517:
12518: STATIC void
12519: AscAckInterrupt(
12520: PortAddr iop_base
12521: )
12522: {
12523: uchar host_flag;
12524: uchar risc_flag;
12525: ushort loop;
12526:
12527: loop = 0;
12528: do {
12529: risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
12530: if (loop++ > 0x7FFF) {
12531: break;
12532: }
12533: } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
12534: host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
12535: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
12536: (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
12537: AscSetChipStatus(iop_base, CIW_INT_ACK);
12538: loop = 0;
12539: while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
12540: AscSetChipStatus(iop_base, CIW_INT_ACK);
12541: if (loop++ > 3) {
12542: break;
12543: }
12544: }
12545: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
12546: return;
12547: }
12548:
12549: STATIC void
12550: AscDisableInterrupt(
12551: PortAddr iop_base
12552: )
12553: {
12554: ushort cfg;
12555:
12556: cfg = AscGetChipCfgLsw(iop_base);
12557: AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
12558: return;
12559: }
12560:
12561: STATIC void
12562: AscEnableInterrupt(
12563: PortAddr iop_base
12564: )
12565: {
12566: ushort cfg;
12567:
12568: cfg = AscGetChipCfgLsw(iop_base);
12569: AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
12570: return;
12571: }
12572:
12573:
12574:
12575: STATIC void
12576: AscSetBank(
12577: PortAddr iop_base,
12578: uchar bank
12579: )
12580: {
12581: uchar val;
12582:
12583: val = AscGetChipControl(iop_base) &
12584: (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
12585: if (bank == 1) {
12586: val |= CC_BANK_ONE;
12587: } else if (bank == 2) {
12588: val |= CC_DIAG | CC_BANK_ONE;
12589: } else {
12590: val &= ~CC_BANK_ONE;
12591: }
12592: AscSetChipControl(iop_base, val);
12593: return;
12594: }
12595:
12596: STATIC int
12597: AscResetChipAndScsiBus(
12598: ASC_DVC_VAR *asc_dvc
12599: )
12600: {
12601: PortAddr iop_base;
12602:
12603: iop_base = asc_dvc->iop_base;
12604: while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
12605: AscStopChip(iop_base);
12606: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
12607: DvcDelayNanoSecond(asc_dvc, 60000);
12608: AscSetChipIH(iop_base, INS_RFLAG_WTM);
12609: AscSetChipIH(iop_base, INS_HALT);
12610: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
12611: AscSetChipControl(iop_base, CC_HALT);
12612: DvcSleepMilliSecond(200);
12613: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
12614: AscSetChipStatus(iop_base, 0);
12615: return (AscIsChipHalted(iop_base));
12616: }
12617:
12618: ASC_INITFUNC(
12619: STATIC ulong
12620: AscGetMaxDmaCount(
12621: ushort bus_type
12622: )
12623: )
12624: {
12625: if (bus_type & ASC_IS_ISA)
12626: return (ASC_MAX_ISA_DMA_COUNT);
12627: else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
12628: return (ASC_MAX_VL_DMA_COUNT);
12629: return (ASC_MAX_PCI_DMA_COUNT);
12630: }
12631:
12632: ASC_INITFUNC(
12633: STATIC ushort
12634: AscGetIsaDmaChannel(
12635: PortAddr iop_base
12636: )
12637: )
12638: {
12639: ushort channel;
12640:
12641: channel = AscGetChipCfgLsw(iop_base) & 0x0003;
12642: if (channel == 0x03)
12643: return (0);
12644: else if (channel == 0x00)
12645: return (7);
12646: return (channel + 4);
12647: }
12648:
12649: ASC_INITFUNC(
12650: STATIC ushort
12651: AscSetIsaDmaChannel(
12652: PortAddr iop_base,
12653: ushort dma_channel
12654: )
12655: )
12656: {
12657: ushort cfg_lsw;
12658: uchar value;
12659:
12660: if ((dma_channel >= 5) && (dma_channel <= 7)) {
12661: if (dma_channel == 7)
12662: value = 0x00;
12663: else
12664: value = dma_channel - 4;
12665: cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
12666: cfg_lsw |= value;
12667: AscSetChipCfgLsw(iop_base, cfg_lsw);
12668: return (AscGetIsaDmaChannel(iop_base));
12669: }
12670: return (0);
12671: }
12672:
12673: ASC_INITFUNC(
12674: STATIC uchar
12675: AscSetIsaDmaSpeed(
12676: PortAddr iop_base,
12677: uchar speed_value
12678: )
12679: )
12680: {
12681: speed_value &= 0x07;
12682: AscSetBank(iop_base, 1);
12683: AscWriteChipDmaSpeed(iop_base, speed_value);
12684: AscSetBank(iop_base, 0);
12685: return (AscGetIsaDmaSpeed(iop_base));
12686: }
12687:
12688: ASC_INITFUNC(
12689: STATIC uchar
12690: AscGetIsaDmaSpeed(
12691: PortAddr iop_base
12692: )
12693: )
12694: {
12695: uchar speed_value;
12696:
12697: AscSetBank(iop_base, 1);
12698: speed_value = AscReadChipDmaSpeed(iop_base);
12699: speed_value &= 0x07;
12700: AscSetBank(iop_base, 0);
12701: return (speed_value);
12702: }
12703:
12704: ASC_INITFUNC(
12705: STATIC ushort
12706: AscReadPCIConfigWord(
12707: ASC_DVC_VAR asc_ptr_type *asc_dvc,
12708: ushort pci_config_offset)
12709: )
12710: {
12711: uchar lsb, msb;
12712:
12713: lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
12714: msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
12715: return ((ushort) ((msb << 8) | lsb));
12716: }
12717:
12718: ASC_INITFUNC(
12719: STATIC ushort
12720: AscInitGetConfig(
12721: ASC_DVC_VAR asc_ptr_type * asc_dvc
12722: )
12723: )
12724: {
12725: ushort warn_code;
12726: PortAddr iop_base;
12727: ushort PCIDeviceID;
12728: ushort PCIVendorID;
12729: uchar PCIRevisionID;
12730: uchar prevCmdRegBits;
12731:
12732: warn_code = 0;
12733: iop_base = asc_dvc->iop_base;
12734: asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
12735: if (asc_dvc->err_code != 0) {
12736: return (UW_ERR);
12737: }
12738: if (asc_dvc->bus_type == ASC_IS_PCI) {
12739: PCIVendorID = AscReadPCIConfigWord(asc_dvc,
12740: AscPCIConfigVendorIDRegister);
12741:
12742: PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
12743: AscPCIConfigDeviceIDRegister);
12744:
12745: PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
12746: AscPCIConfigRevisionIDRegister);
12747:
12748: if (PCIVendorID != ASC_PCI_VENDORID) {
12749: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12750: }
12751: prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
12752: AscPCIConfigCommandRegister);
12753:
12754: if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
12755: AscPCICmdRegBits_IOMemBusMaster) {
12756: DvcWritePCIConfigByte(asc_dvc,
12757: AscPCIConfigCommandRegister,
12758: (prevCmdRegBits |
12759: AscPCICmdRegBits_IOMemBusMaster));
12760:
12761: if ((DvcReadPCIConfigByte(asc_dvc,
12762: AscPCIConfigCommandRegister)
12763: & AscPCICmdRegBits_IOMemBusMaster)
12764: != AscPCICmdRegBits_IOMemBusMaster) {
12765: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12766: }
12767: }
12768: if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) ||
12769: (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) {
12770: DvcWritePCIConfigByte(asc_dvc,
12771: AscPCIConfigLatencyTimer, 0x00);
12772: if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer)
12773: != 0x00) {
12774: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12775: }
12776: } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) {
12777: if (DvcReadPCIConfigByte(asc_dvc,
12778: AscPCIConfigLatencyTimer) < 0x20) {
12779: DvcWritePCIConfigByte(asc_dvc,
12780: AscPCIConfigLatencyTimer, 0x20);
12781:
12782: if (DvcReadPCIConfigByte(asc_dvc,
12783: AscPCIConfigLatencyTimer) < 0x20) {
12784: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
12785: }
12786: }
12787: }
12788: }
12789:
12790: if (AscFindSignature(iop_base)) {
12791: warn_code |= AscInitAscDvcVar(asc_dvc);
12792: warn_code |= AscInitFromEEP(asc_dvc);
12793: asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
12794: if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
12795: asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
12796: }
12797: } else {
12798: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12799: }
12800: return(warn_code);
12801: }
12802:
12803: ASC_INITFUNC(
12804: STATIC ushort
12805: AscInitSetConfig(
12806: ASC_DVC_VAR asc_ptr_type * asc_dvc
12807: )
12808: )
12809: {
12810: ushort warn_code = 0;
12811:
12812: asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
12813: if (asc_dvc->err_code != 0)
12814: return (UW_ERR);
12815: if (AscFindSignature(asc_dvc->iop_base)) {
12816: warn_code |= AscInitFromAscDvcVar(asc_dvc);
12817: asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
12818: } else {
12819: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12820: }
12821: return (warn_code);
12822: }
12823:
12824: ASC_INITFUNC(
12825: STATIC ushort
12826: AscInitFromAscDvcVar(
12827: ASC_DVC_VAR asc_ptr_type * asc_dvc
12828: )
12829: )
12830: {
12831: PortAddr iop_base;
12832: ushort cfg_msw;
12833: ushort warn_code;
12834: ushort pci_device_id;
12835:
12836: iop_base = asc_dvc->iop_base;
12837: pci_device_id = asc_dvc->cfg->pci_device_id;
12838: warn_code = 0;
12839: cfg_msw = AscGetChipCfgMsw(iop_base);
12840: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
12841: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
12842: warn_code |= ASC_WARN_CFG_MSW_RECOVER;
12843: AscSetChipCfgMsw(iop_base, cfg_msw);
12844: }
12845: if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
12846: asc_dvc->cfg->cmd_qng_enabled) {
12847: asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
12848: warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
12849: }
12850: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
12851: warn_code |= ASC_WARN_AUTO_CONFIG;
12852: }
12853: if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
12854: if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
12855: != asc_dvc->irq_no) {
12856: asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
12857: }
12858: }
12859: if (asc_dvc->bus_type & ASC_IS_PCI) {
12860: cfg_msw &= 0xFFC0;
12861: AscSetChipCfgMsw(iop_base, cfg_msw);
12862: if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
12863: } else {
12864: if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
12865: (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
12866: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
12867: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12868: }
12869: }
12870: } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
12871: if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
12872: == ASC_CHIP_VER_ASYN_BUG) {
12873: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
12874: }
12875: }
12876: if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
12877: asc_dvc->cfg->chip_scsi_id) {
12878: asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
12879: }
12880: if (asc_dvc->bus_type & ASC_IS_ISA) {
12881: AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
12882: AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
12883: }
12884: return (warn_code);
12885: }
12886:
12887: ASC_INITFUNC(
12888: STATIC ushort
12889: AscInitAsc1000Driver(
12890: ASC_DVC_VAR asc_ptr_type * asc_dvc
12891: )
12892: )
12893: {
12894: ushort warn_code;
12895: PortAddr iop_base;
12896: extern ushort _asc_mcode_size;
12897: extern ulong _asc_mcode_chksum;
12898: extern uchar _asc_mcode_buf[];
12899:
12900: iop_base = asc_dvc->iop_base;
12901: warn_code = 0;
12902: if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
12903: !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
12904: AscResetChipAndScsiBus(asc_dvc);
12905: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
12906: }
12907: asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
12908: if (asc_dvc->err_code != 0)
12909: return (UW_ERR);
12910: if (!AscFindSignature(asc_dvc->iop_base)) {
12911: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
12912: return (warn_code);
12913: }
12914: AscDisableInterrupt(iop_base);
12915: warn_code |= AscInitLram(asc_dvc);
12916: if (asc_dvc->err_code != 0)
12917: return (UW_ERR);
12918: if (AscLoadMicroCode(iop_base, 0, (ushort *) _asc_mcode_buf,
12919: _asc_mcode_size) != _asc_mcode_chksum) {
12920: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
12921: return (warn_code);
12922: }
12923: warn_code |= AscInitMicroCodeVar(asc_dvc);
12924: asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
12925: AscEnableInterrupt(iop_base);
12926: return (warn_code);
12927: }
12928:
12929: ASC_INITFUNC(
12930: STATIC ushort
12931: AscInitAscDvcVar(
12932: ASC_DVC_VAR asc_ptr_type * asc_dvc
12933: )
12934: )
12935: {
12936: int i;
12937: PortAddr iop_base;
12938: ushort warn_code;
12939: uchar chip_version;
12940:
12941: iop_base = asc_dvc->iop_base;
12942: warn_code = 0;
12943: asc_dvc->err_code = 0;
12944: if ((asc_dvc->bus_type &
12945: (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
12946: asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
12947: }
12948: AscSetChipControl(iop_base, CC_HALT);
12949: AscSetChipStatus(iop_base, 0);
12950: asc_dvc->bug_fix_cntl = 0;
12951: asc_dvc->pci_fix_asyn_xfer = 0;
12952: asc_dvc->pci_fix_asyn_xfer_always = 0;
12953: asc_dvc->init_state = 0;
12954: asc_dvc->sdtr_done = 0;
12955: asc_dvc->cur_total_qng = 0;
12956: asc_dvc->is_in_int = 0;
12957: asc_dvc->in_critical_cnt = 0;
12958: asc_dvc->last_q_shortage = 0;
12959: asc_dvc->use_tagged_qng = 0;
12960: asc_dvc->no_scam = 0;
12961: asc_dvc->unit_not_ready = 0;
12962: asc_dvc->queue_full_or_busy = 0;
12963: asc_dvc->redo_scam = 0 ;
12964: asc_dvc->res2 = 0 ;
12965: asc_dvc->host_init_sdtr_index = 0 ;
12966: asc_dvc->res7 = 0 ;
12967: asc_dvc->res8 = 0 ;
12968: asc_dvc->cfg->can_tagged_qng = 0 ;
12969: asc_dvc->cfg->cmd_qng_enabled = 0;
12970: asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
12971: asc_dvc->init_sdtr = 0;
12972: asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
12973: asc_dvc->scsi_reset_wait = 3;
12974: asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
12975: asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
12976: asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
12977: asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
12978: asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
12979: asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
12980: asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
12981: ASC_LIB_VERSION_MINOR;
12982: chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
12983: asc_dvc->cfg->chip_version = chip_version;
12984: asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
12985: asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
12986: asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
12987: asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
12988: asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
12989: asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
12990: asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
12991: asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
12992: asc_dvc->max_sdtr_index = 7;
12993: if ((asc_dvc->bus_type & ASC_IS_PCI) &&
12994: (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
12995: asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
12996: asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
12997: asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
12998: asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
12999: asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
13000: asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
13001: asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
13002: asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
13003: asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
13004: asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
13005: asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
13006: asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
13007: asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
13008: asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
13009: asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
13010: asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
13011: asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
13012: asc_dvc->max_sdtr_index = 15;
13013: if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
13014: {
13015: AscSetExtraControl(iop_base,
13016: (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13017: } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
13018: AscSetExtraControl(iop_base,
13019: (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
13020: }
13021: }
13022: if (asc_dvc->bus_type == ASC_IS_PCI) {
13023: AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
13024: }
13025:
13026: asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
13027: if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
13028: AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
13029: asc_dvc->bus_type = ASC_IS_ISAPNP;
13030: }
13031: if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
13032: asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
13033: }
13034: for (i = 0; i <= ASC_MAX_TID; i++) {
13035: asc_dvc->cur_dvc_qng[i] = 0;
13036: asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
13037: asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L;
13038: asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L;
13039: asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
13040: }
13041: return (warn_code);
13042: }
13043:
13044: ASC_INITFUNC(
13045: STATIC ushort
13046: AscInitFromEEP(
13047: ASC_DVC_VAR asc_ptr_type * asc_dvc
13048: )
13049: )
13050: {
13051: ASCEEP_CONFIG eep_config_buf;
13052: ASCEEP_CONFIG *eep_config;
13053: PortAddr iop_base;
13054: ushort chksum;
13055: ushort warn_code;
13056: ushort cfg_msw, cfg_lsw;
13057: int i;
13058: int write_eep = 0;
13059:
13060: iop_base = asc_dvc->iop_base;
13061: warn_code = 0;
13062: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
13063: AscStopQueueExe(iop_base);
13064: if ((AscStopChip(iop_base) == FALSE) ||
13065: (AscGetChipScsiCtrl(iop_base) != 0)) {
13066: asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
13067: AscResetChipAndScsiBus(asc_dvc);
13068: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
13069: }
13070: if (AscIsChipHalted(iop_base) == FALSE) {
13071: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13072: return (warn_code);
13073: }
13074: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13075: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13076: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13077: return (warn_code);
13078: }
13079: eep_config = (ASCEEP_CONFIG *) & eep_config_buf;
13080: cfg_msw = AscGetChipCfgMsw(iop_base);
13081: cfg_lsw = AscGetChipCfgLsw(iop_base);
13082: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
13083: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
13084: warn_code |= ASC_WARN_CFG_MSW_RECOVER;
13085: AscSetChipCfgMsw(iop_base, cfg_msw);
13086: }
13087: chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13088: if (chksum == 0) {
13089: chksum = 0xaa55;
13090: }
13091: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
13092: warn_code |= ASC_WARN_AUTO_CONFIG;
13093: if (asc_dvc->cfg->chip_version == 3) {
13094: if (eep_config->cfg_lsw != cfg_lsw) {
13095: warn_code |= ASC_WARN_EEPROM_RECOVER;
13096: eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
13097: }
13098: if (eep_config->cfg_msw != cfg_msw) {
13099: warn_code |= ASC_WARN_EEPROM_RECOVER;
13100: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
13101: }
13102: }
13103: }
13104: eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
13105: eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
13106: if (chksum != eep_config->chksum) {
13107: if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
13108: ASC_CHIP_VER_PCI_ULTRA_3050 )
13109: {
13110: eep_config->init_sdtr = 0xFF;
13111: eep_config->disc_enable = 0xFF;
13112: eep_config->start_motor = 0xFF;
13113: eep_config->use_cmd_qng = 0;
13114: eep_config->max_total_qng = 0xF0;
13115: eep_config->max_tag_qng = 0x20;
13116: eep_config->cntl = 0xBFFF;
13117: eep_config->chip_scsi_id = 7;
13118: eep_config->no_scam = 0;
13119: eep_config->adapter_info[0] = 0;
13120: eep_config->adapter_info[1] = 0;
13121: eep_config->adapter_info[2] = 0;
13122: eep_config->adapter_info[3] = 0;
13123: eep_config->adapter_info[4] = 0;
13124: /* Indicate EEPROM-less board. */
13125: eep_config->adapter_info[5] = 0xBB;
13126: } else {
13127: write_eep = 1 ;
13128: warn_code |= ASC_WARN_EEPROM_CHKSUM ;
13129: }
13130: }
13131: asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr ;
13132: asc_dvc->cfg->disc_enable = eep_config->disc_enable;
13133: asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
13134: asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
13135: asc_dvc->start_motor = eep_config->start_motor;
13136: asc_dvc->dvc_cntl = eep_config->cntl;
13137: asc_dvc->no_scam = eep_config->no_scam;
13138: asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
13139: asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
13140: asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
13141: asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
13142: asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
13143: asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
13144: if (!AscTestExternalLram(asc_dvc)) {
13145: if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
13146: eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
13147: eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
13148: } else {
13149: eep_config->cfg_msw |= 0x0800;
13150: cfg_msw |= 0x0800;
13151: AscSetChipCfgMsw(iop_base, cfg_msw);
13152: eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
13153: eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
13154: }
13155: } else {
13156: }
13157: if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
13158: eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
13159: }
13160: if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
13161: eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
13162: }
13163: if (eep_config->max_tag_qng > eep_config->max_total_qng) {
13164: eep_config->max_tag_qng = eep_config->max_total_qng;
13165: }
13166: if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
13167: eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
13168: }
13169: asc_dvc->max_total_qng = eep_config->max_total_qng;
13170: if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
13171: eep_config->use_cmd_qng) {
13172: eep_config->disc_enable = eep_config->use_cmd_qng;
13173: warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
13174: }
13175: if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
13176: asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
13177: }
13178: eep_config->chip_scsi_id &= ASC_MAX_TID;
13179: asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
13180: if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
13181: !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
13182: asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
13183: }
13184:
13185: for (i = 0; i <= ASC_MAX_TID; i++) {
13186: asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
13187: asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
13188: asc_dvc->cfg->sdtr_period_offset[i] =
13189: (uchar) (ASC_DEF_SDTR_OFFSET |
13190: (asc_dvc->host_init_sdtr_index << 4));
13191: }
13192: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
13193: if (write_eep) {
13194: (void) AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
13195: }
13196: return (warn_code);
13197: }
13198:
13199: ASC_INITFUNC(
13200: STATIC ushort
13201: AscInitMicroCodeVar(
13202: ASC_DVC_VAR asc_ptr_type * asc_dvc
13203: )
13204: )
13205: {
13206: int i;
13207: ushort warn_code;
13208: PortAddr iop_base;
13209: ulong phy_addr;
13210:
13211: iop_base = asc_dvc->iop_base;
13212: warn_code = 0;
13213: for (i = 0; i <= ASC_MAX_TID; i++) {
13214: AscPutMCodeInitSDTRAtID(iop_base, i,
13215: asc_dvc->cfg->sdtr_period_offset[i]
13216: );
13217: }
13218: AscInitQLinkVar(asc_dvc);
13219: AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
13220: asc_dvc->cfg->disc_enable);
13221: AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
13222: ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
13223: if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
13224: (uchar *) asc_dvc->cfg->overrun_buf,
13225: ASC_OVERRUN_BSIZE)) == 0L) {
13226: asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
13227: } else {
13228: phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
13229: AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
13230: AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
13231: ASC_OVERRUN_BSIZE - 8);
13232: }
13233: asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
13234: (ushort) ASCV_MC_DATE_W);
13235: asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
13236: (ushort) ASCV_MC_VER_W);
13237: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
13238: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
13239: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
13240: return (warn_code);
13241: }
13242: if (AscStartChip(iop_base) != 1) {
13243: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
13244: return (warn_code);
13245: }
13246: return (warn_code);
13247: }
13248:
13249: ASC_INITFUNC(
13250: STATIC int
13251: AscTestExternalLram(
13252: ASC_DVC_VAR asc_ptr_type * asc_dvc
13253: )
13254: )
13255: {
13256: PortAddr iop_base;
13257: ushort q_addr;
13258: ushort saved_word;
13259: int sta;
13260:
13261: iop_base = asc_dvc->iop_base;
13262: sta = 0;
13263: q_addr = ASC_QNO_TO_QADDR(241);
13264: saved_word = AscReadLramWord(iop_base, q_addr);
13265: AscSetChipLramAddr(iop_base, q_addr);
13266: AscSetChipLramData(iop_base, 0x55AA);
13267: DvcSleepMilliSecond(10);
13268: AscSetChipLramAddr(iop_base, q_addr);
13269: if (AscGetChipLramData(iop_base) == 0x55AA) {
13270: sta = 1;
13271: AscWriteLramWord(iop_base, q_addr, saved_word);
13272: }
13273: return (sta);
13274: }
13275:
13276: ASC_INITFUNC(
13277: STATIC int
13278: AscWriteEEPCmdReg(
13279: PortAddr iop_base,
13280: uchar cmd_reg
13281: )
13282: )
13283: {
13284: uchar read_back;
13285: int retry;
13286:
13287: retry = 0;
13288: while (TRUE) {
13289: AscSetChipEEPCmd(iop_base, cmd_reg);
13290: DvcSleepMilliSecond(1);
13291: read_back = AscGetChipEEPCmd(iop_base);
13292: if (read_back == cmd_reg) {
13293: return (1);
13294: }
13295: if (retry++ > ASC_EEP_MAX_RETRY) {
13296: return (0);
13297: }
13298: }
13299: }
13300:
13301: ASC_INITFUNC(
13302: STATIC int
13303: AscWriteEEPDataReg(
13304: PortAddr iop_base,
13305: ushort data_reg
13306: )
13307: )
13308: {
13309: ushort read_back;
13310: int retry;
13311:
13312: retry = 0;
13313: while (TRUE) {
13314: AscSetChipEEPData(iop_base, data_reg);
13315: DvcSleepMilliSecond(1);
13316: read_back = AscGetChipEEPData(iop_base);
13317: if (read_back == data_reg) {
13318: return (1);
13319: }
13320: if (retry++ > ASC_EEP_MAX_RETRY) {
13321: return (0);
13322: }
13323: }
13324: }
13325:
13326: ASC_INITFUNC(
13327: STATIC void
13328: AscWaitEEPRead(
13329: void
13330: )
13331: )
13332: {
13333: DvcSleepMilliSecond(1);
13334: return;
13335: }
13336:
13337: ASC_INITFUNC(
13338: STATIC void
13339: AscWaitEEPWrite(
13340: void
13341: )
13342: )
13343: {
13344: DvcSleepMilliSecond(20);
13345: return;
13346: }
13347:
13348: ASC_INITFUNC(
13349: STATIC ushort
13350: AscReadEEPWord(
13351: PortAddr iop_base,
13352: uchar addr
13353: )
13354: )
13355: {
13356: ushort read_wval;
13357: uchar cmd_reg;
13358:
13359: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
13360: AscWaitEEPRead();
13361: cmd_reg = addr | ASC_EEP_CMD_READ;
13362: AscWriteEEPCmdReg(iop_base, cmd_reg);
13363: AscWaitEEPRead();
13364: read_wval = AscGetChipEEPData(iop_base);
13365: AscWaitEEPRead();
13366: return (read_wval);
13367: }
13368:
13369: ASC_INITFUNC(
13370: STATIC ushort
13371: AscWriteEEPWord(
13372: PortAddr iop_base,
13373: uchar addr,
13374: ushort word_val
13375: )
13376: )
13377: {
13378: ushort read_wval;
13379:
13380: read_wval = AscReadEEPWord(iop_base, addr);
13381: if (read_wval != word_val) {
13382: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
13383: AscWaitEEPRead();
13384: AscWriteEEPDataReg(iop_base, word_val);
13385: AscWaitEEPRead();
13386: AscWriteEEPCmdReg(iop_base,
13387: (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
13388: AscWaitEEPWrite();
13389: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
13390: AscWaitEEPRead();
13391: return (AscReadEEPWord(iop_base, addr));
13392: }
13393: return (read_wval);
13394: }
13395:
13396: ASC_INITFUNC(
13397: STATIC ushort
13398: AscGetEEPConfig(
13399: PortAddr iop_base,
13400: ASCEEP_CONFIG * cfg_buf, ushort bus_type
13401: )
13402: )
13403: {
13404: ushort wval;
13405: ushort sum;
13406: ushort *wbuf;
13407: int cfg_beg;
13408: int cfg_end;
13409: int s_addr;
13410: int isa_pnp_wsize;
13411:
13412: wbuf = (ushort *) cfg_buf;
13413: sum = 0;
13414: isa_pnp_wsize = 0;
13415: for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
13416: wval = AscReadEEPWord(iop_base, (uchar) s_addr);
13417: sum += wval;
13418: *wbuf = wval;
13419: }
13420: if (bus_type & ASC_IS_VL) {
13421: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
13422: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
13423: } else {
13424: cfg_beg = ASC_EEP_DVC_CFG_BEG;
13425: cfg_end = ASC_EEP_MAX_DVC_ADDR;
13426: }
13427: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
13428: s_addr++, wbuf++) {
13429: wval = AscReadEEPWord(iop_base, (uchar) s_addr);
13430: sum += wval;
13431: *wbuf = wval;
13432: }
13433: *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
13434: return (sum);
13435: }
13436:
13437: ASC_INITFUNC(
13438: STATIC int
13439: AscSetEEPConfigOnce(
13440: PortAddr iop_base,
13441: ASCEEP_CONFIG * cfg_buf, ushort bus_type
13442: )
13443: )
13444: {
13445: int n_error;
13446: ushort *wbuf;
13447: ushort sum;
13448: int s_addr;
13449: int cfg_beg;
13450: int cfg_end;
13451:
13452: wbuf = (ushort *) cfg_buf;
13453: n_error = 0;
13454: sum = 0;
13455: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
13456: sum += *wbuf;
13457: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
13458: n_error++;
13459: }
13460: }
13461: if (bus_type & ASC_IS_VL) {
13462: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
13463: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
13464: } else {
13465: cfg_beg = ASC_EEP_DVC_CFG_BEG;
13466: cfg_end = ASC_EEP_MAX_DVC_ADDR;
13467: }
13468: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
13469: s_addr++, wbuf++) {
13470: sum += *wbuf;
13471: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
13472: n_error++;
13473: }
13474: }
13475: *wbuf = sum;
13476: if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
13477: n_error++;
13478: }
13479: wbuf = (ushort *) cfg_buf;
13480: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
13481: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
13482: n_error++;
13483: }
13484: }
13485: for (s_addr = cfg_beg; s_addr <= cfg_end;
13486: s_addr++, wbuf++) {
13487: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
13488: n_error++;
13489: }
13490: }
13491: return (n_error);
13492: }
13493:
13494: ASC_INITFUNC(
13495: STATIC int
13496: AscSetEEPConfig(
13497: PortAddr iop_base,
13498: ASCEEP_CONFIG * cfg_buf, ushort bus_type
13499: )
13500: )
13501: {
13502: int retry;
13503: int n_error;
13504:
13505: retry = 0;
13506: while (TRUE) {
13507: if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
13508: bus_type)) == 0) {
13509: break;
13510: }
13511: if (++retry > ASC_EEP_MAX_RETRY) {
13512: break;
13513: }
13514: }
13515: return (n_error);
13516: }
13517:
13518: STATIC void
13519: AscAsyncFix(
13520: ASC_DVC_VAR asc_ptr_type *asc_dvc,
13521: uchar tid_no,
13522: ASC_SCSI_INQUIRY *inq)
13523: {
13524: uchar dvc_type;
13525: ASC_SCSI_BIT_ID_TYPE tid_bits;
13526:
13527: dvc_type = inq->byte0.peri_dvc_type;
13528: tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
13529:
13530: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
13531: if (!(asc_dvc->init_sdtr & tid_bits)) {
13532: if ((dvc_type == SCSI_TYPE_CDROM) &&
13533: (AscCompareString((uchar *) inq->vendor_id,
13534: (uchar *) "HP ", 3) == 0)) {
13535: asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
13536: }
13537: asc_dvc->pci_fix_asyn_xfer |= tid_bits;
13538: if ((dvc_type == SCSI_TYPE_PROC) ||
13539: (dvc_type == SCSI_TYPE_SCANNER)) {
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 *) "TANDBERG", 8) == 0) &&
13545: (AscCompareString((uchar *) inq->product_id,
13546: (uchar *) " TDC 36", 7) == 0)) {
13547: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13548: }
13549: if ((dvc_type == SCSI_TYPE_SASD) &&
13550: (AscCompareString((uchar *) inq->vendor_id,
13551: (uchar *) "WANGTEK ", 8) == 0)) {
13552: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13553: }
13554:
13555: if ((dvc_type == SCSI_TYPE_CDROM) &&
13556: (AscCompareString((uchar *) inq->vendor_id,
13557: (uchar *) "NEC ", 8) == 0) &&
13558: (AscCompareString((uchar *) inq->product_id,
13559: (uchar *) "CD-ROM DRIVE ", 16) == 0)) {
13560: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13561: }
13562:
13563: if ((dvc_type == SCSI_TYPE_CDROM) &&
13564: (AscCompareString((uchar *) inq->vendor_id,
13565: (uchar *) "YAMAHA", 6) == 0) &&
13566: (AscCompareString((uchar *) inq->product_id,
13567: (uchar *) "CDR400", 6) == 0)) {
13568: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
13569: }
13570: if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
13571: AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
13572: ASYN_SDTR_DATA_FIX_PCI_REV_AB);
13573: }
13574: }
13575: }
13576: return;
13577: }
13578:
13579: STATIC int
13580: AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
13581: {
13582: if ((inq->add_len >= 32) &&
13583: (AscCompareString((uchar *) inq->vendor_id,
13584: (uchar *) "QUANTUM XP34301", 15) == 0) &&
13585: (AscCompareString((uchar *) inq->product_rev_level,
13586: (uchar *) "1071", 4) == 0))
13587: {
13588: return 0;
13589: }
13590: return 1;
13591: }
13592:
13593: STATIC void
13594: AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc,
13595: uchar tid_no, ASC_SCSI_INQUIRY *inq)
13596: {
13597: ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
13598: ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
13599:
13600: orig_init_sdtr = asc_dvc->init_sdtr;
13601: orig_use_tagged_qng = asc_dvc->use_tagged_qng;
13602:
13603: asc_dvc->init_sdtr &= ~tid_bit;
13604: asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
13605: asc_dvc->use_tagged_qng &= ~tid_bit;
13606:
13607: if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) {
13608: if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) {
13609: asc_dvc->init_sdtr |= tid_bit;
13610: }
13611: if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) {
13612: if (AscTagQueuingSafe(inq)) {
13613: asc_dvc->use_tagged_qng |= tid_bit;
13614: asc_dvc->cfg->can_tagged_qng |= tid_bit;
13615: }
13616: }
13617: }
13618: if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
13619: AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
13620: asc_dvc->cfg->disc_enable);
13621: AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
13622: asc_dvc->use_tagged_qng);
13623: AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
13624: asc_dvc->cfg->can_tagged_qng);
13625:
13626: asc_dvc->max_dvc_qng[tid_no] =
13627: asc_dvc->cfg->max_tag_qng[tid_no];
13628: AscWriteLramByte(asc_dvc->iop_base,
13629: (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no),
13630: asc_dvc->max_dvc_qng[tid_no]);
13631: }
13632: if (orig_init_sdtr != asc_dvc->init_sdtr) {
13633: AscAsyncFix(asc_dvc, tid_no, inq);
13634: }
13635: return;
13636: }
13637:
13638: STATIC int
13639: AscCompareString(
13640: ruchar * str1,
13641: ruchar * str2,
13642: int len
13643: )
13644: {
13645: int i;
13646: int diff;
13647:
13648: for (i = 0; i < len; i++) {
13649: diff = (int) (str1[i] - str2[i]);
13650: if (diff != 0)
13651: return (diff);
13652: }
13653: return (0);
13654: }
13655:
13656: STATIC uchar
13657: AscReadLramByte(
13658: PortAddr iop_base,
13659: ushort addr
13660: )
13661: {
13662: uchar byte_data;
13663: ushort word_data;
13664:
13665: if (isodd_word(addr)) {
13666: AscSetChipLramAddr(iop_base, addr - 1);
13667: word_data = AscGetChipLramData(iop_base);
13668: byte_data = (uchar) ((word_data >> 8) & 0xFF);
13669: } else {
13670: AscSetChipLramAddr(iop_base, addr);
13671: word_data = AscGetChipLramData(iop_base);
13672: byte_data = (uchar) (word_data & 0xFF);
13673: }
13674: return (byte_data);
13675: }
13676:
13677: STATIC ushort
13678: AscReadLramWord(
13679: PortAddr iop_base,
13680: ushort addr
13681: )
13682: {
13683: ushort word_data;
13684:
13685: AscSetChipLramAddr(iop_base, addr);
13686: word_data = AscGetChipLramData(iop_base);
13687: return (word_data);
13688: }
13689:
13690: STATIC ulong
13691: AscReadLramDWord(
13692: PortAddr iop_base,
13693: ushort addr
13694: )
13695: {
13696: ushort val_low, val_high;
13697: ulong dword_data;
13698:
13699: AscSetChipLramAddr(iop_base, addr);
13700: val_low = AscGetChipLramData(iop_base);
13701: val_high = AscGetChipLramData(iop_base);
13702: dword_data = ((ulong) val_high << 16) | (ulong) val_low;
13703: return (dword_data);
13704: }
13705:
13706: STATIC void
13707: AscWriteLramWord(
13708: PortAddr iop_base,
13709: ushort addr,
13710: ushort word_val
13711: )
13712: {
13713: AscSetChipLramAddr(iop_base, addr);
13714: AscSetChipLramData(iop_base, word_val);
13715: return;
13716: }
13717:
13718: STATIC void
13719: AscWriteLramDWord(
13720: PortAddr iop_base,
13721: ushort addr,
13722: ulong dword_val
13723: )
13724: {
13725: ushort word_val;
13726:
13727: AscSetChipLramAddr(iop_base, addr);
13728: word_val = (ushort) dword_val;
13729: AscSetChipLramData(iop_base, word_val);
13730: word_val = (ushort) (dword_val >> 16);
13731: AscSetChipLramData(iop_base, word_val);
13732: return;
13733: }
13734:
13735: STATIC void
13736: AscWriteLramByte(
13737: PortAddr iop_base,
13738: ushort addr,
13739: uchar byte_val
13740: )
13741: {
13742: ushort word_data;
13743:
13744: if (isodd_word(addr)) {
13745: addr--;
13746: word_data = AscReadLramWord(iop_base, addr);
13747: word_data &= 0x00FF;
13748: word_data |= (((ushort) byte_val << 8) & 0xFF00);
13749: } else {
13750: word_data = AscReadLramWord(iop_base, addr);
13751: word_data &= 0xFF00;
13752: word_data |= ((ushort) byte_val & 0x00FF);
13753: }
13754: AscWriteLramWord(iop_base, addr, word_data);
13755: return;
13756: }
13757:
13758: STATIC void
13759: AscMemWordCopyToLram(
13760: PortAddr iop_base,
13761: ushort s_addr,
13762: ushort * s_buffer,
13763: int words
13764: )
13765: {
13766: AscSetChipLramAddr(iop_base, s_addr);
13767: DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
13768: return;
13769: }
13770:
13771: STATIC void
13772: AscMemDWordCopyToLram(
13773: PortAddr iop_base,
13774: ushort s_addr,
13775: ulong * s_buffer,
13776: int dwords
13777: )
13778: {
13779: AscSetChipLramAddr(iop_base, s_addr);
13780: DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
13781: return;
13782: }
13783:
13784: STATIC void
13785: AscMemWordCopyFromLram(
13786: PortAddr iop_base,
13787: ushort s_addr,
13788: ushort * d_buffer,
13789: int words
13790: )
13791: {
13792: AscSetChipLramAddr(iop_base, s_addr);
13793: DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
13794: return;
13795: }
13796:
13797: STATIC ulong
13798: AscMemSumLramWord(
13799: PortAddr iop_base,
13800: ushort s_addr,
13801: rint words
13802: )
13803: {
13804: ulong sum;
13805: int i;
13806:
13807: sum = 0L;
13808: for (i = 0; i < words; i++, s_addr += 2) {
13809: sum += AscReadLramWord(iop_base, s_addr);
13810: }
13811: return (sum);
13812: }
13813:
13814: STATIC void
13815: AscMemWordSetLram(
13816: PortAddr iop_base,
13817: ushort s_addr,
13818: ushort set_wval,
13819: rint words
13820: )
13821: {
13822: rint i;
13823:
13824: AscSetChipLramAddr(iop_base, s_addr);
13825: for (i = 0; i < words; i++) {
13826: AscSetChipLramData(iop_base, set_wval);
13827: }
13828: return;
13829: }
13830:
13831:
13832: /*
13833: * --- Adv Library Functions
13834: */
13835:
13836: /* a_qswap.h */
13837: STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = {
13838: 0x9C, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x44, 0x0A, 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, 0x72, 0x01, 0xD6, 0x11, 0x00, 0x00, 0x70, 0x01,
13841: 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x10, 0x2D, 0x03, 0x00, 0x00, 0x00, 0x00,
13842: 0x00, 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: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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: 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13850: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13851: 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13855: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13856: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12,
13857: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13858: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13859: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13860: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13861: 0x00, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x0C, 0x1C, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF2, 0xD6, 0x0A,
13862: 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x3E, 0x57, 0x3C, 0x56, 0x0C, 0x1C, 0x00, 0xFC,
13863: 0xA6, 0x00, 0x01, 0x58, 0xAA, 0x13, 0x20, 0xF0, 0xA6, 0x03, 0x06, 0xEC, 0xB9, 0x00, 0x0E, 0x47,
13864: 0x03, 0xE6, 0x10, 0x00, 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0x06, 0xEA, 0xB9, 0x00, 0x47, 0x4B,
13865: 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x4E, 0x12, 0x03, 0xF6, 0xC0, 0x00,
13866: 0x00, 0xF2, 0x68, 0x0A, 0x41, 0x58, 0x03, 0xF6, 0xD0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x49, 0x44,
13867: 0x59, 0xF0, 0x0A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x44, 0x58, 0x00, 0xF2,
13868: 0xE2, 0x0D, 0x02, 0xCC, 0x4A, 0xE4, 0x01, 0x00, 0x55, 0xF0, 0x08, 0x03, 0x45, 0xF4, 0x02, 0x00,
13869: 0x83, 0x5A, 0x04, 0xCC, 0x01, 0x4A, 0x12, 0x12, 0x00, 0xF2, 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4,
13870: 0x01, 0x00, 0xE9, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0xFA, 0x10, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00,
13871: 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0xCE, 0x47, 0x97, 0x13, 0x04, 0xEC, 0xB4, 0x00, 0x00, 0xF2,
13872: 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, 0x00, 0x00, 0x12, 0x12, 0x3E, 0x57, 0x06, 0xCC, 0x45, 0xF4,
13873: 0x02, 0x00, 0x83, 0x5A, 0x00, 0xCC, 0x00, 0xEA, 0xB4, 0x00, 0x92, 0x10, 0x00, 0xF0, 0x8C, 0x01,
13874: 0x43, 0xF0, 0x5C, 0x02, 0x44, 0xF0, 0x60, 0x02, 0x45, 0xF0, 0x64, 0x02, 0x46, 0xF0, 0x68, 0x02,
13875: 0x47, 0xF0, 0x6E, 0x02, 0x48, 0xF0, 0x9E, 0x02, 0xB9, 0x54, 0x62, 0x10, 0x00, 0x1C, 0x5A, 0x10,
13876: 0x02, 0x1C, 0x56, 0x10, 0x1E, 0x1C, 0x52, 0x10, 0x00, 0xF2, 0x1E, 0x11, 0x50, 0x10, 0x06, 0xFC,
13877: 0xA8, 0x00, 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x4E, 0x0A, 0x8C, 0x10, 0x01, 0xF6, 0x01, 0x00,
13878: 0x01, 0xFA, 0xA8, 0x00, 0x00, 0xF2, 0x2C, 0x0B, 0x06, 0x10, 0xB9, 0x54, 0x01, 0xFA, 0xA8, 0x00,
13879: 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x58, 0x0A, 0x01, 0xFC, 0xA8, 0x00, 0x20, 0x10, 0x58, 0x1C,
13880: 0x00, 0xF2, 0x1C, 0x0B, 0x5A, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00,
13881: 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x72, 0x01, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54,
13882: 0x00, 0xFA, 0xA6, 0x00, 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x80, 0x01, 0x03, 0xF6,
13883: 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x0A, 0x13, 0x00, 0xF2, 0x38, 0x10, 0x00, 0xF2,
13884: 0x54, 0x0F, 0x24, 0x10, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x02, 0xF6, 0xD0, 0x00,
13885: 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x49, 0x44, 0x5B, 0xF0, 0x04, 0x03, 0x00, 0xF2, 0x9C, 0x0F,
13886: 0x00, 0xF0, 0x80, 0x01, 0x00, 0xF2, 0x14, 0x10, 0x0C, 0x1C, 0x02, 0x4B, 0xBF, 0x57, 0x9E, 0x43,
13887: 0x77, 0x57, 0x07, 0x4B, 0x20, 0xF0, 0xA6, 0x03, 0x40, 0x1C, 0x1E, 0xF0, 0x30, 0x03, 0x26, 0xF0,
13888: 0x2C, 0x03, 0xA0, 0xF0, 0x1A, 0x03, 0x11, 0xF0, 0xA6, 0x03, 0x12, 0x10, 0x9F, 0xF0, 0x3E, 0x03,
13889: 0x46, 0x1C, 0x82, 0xE7, 0x05, 0x00, 0x9E, 0xE7, 0x11, 0x00, 0x00, 0xF0, 0x06, 0x0A, 0x0C, 0x1C,
13890: 0x48, 0x1C, 0x46, 0x1C, 0x38, 0x54, 0x00, 0xEC, 0xBA, 0x00, 0x08, 0x44, 0x00, 0xEA, 0xBA, 0x00,
13891: 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x08, 0x44, 0x00, 0x4C, 0x82, 0xE7, 0x02, 0x00,
13892: 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x70, 0x03, 0x00, 0xF2, 0x60, 0x0B,
13893: 0x06, 0xF0, 0x80, 0x03, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A,
13894: 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x55, 0xF0, 0xAC, 0x04, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2,
13895: 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x01, 0xF0,
13896: 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x46, 0x1C, 0x0C, 0x1C, 0x67, 0x1B, 0xBF, 0x57, 0x77, 0x57,
13897: 0x02, 0x4B, 0x48, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x96, 0xF0, 0xBC, 0x03,
13898: 0xB1, 0xF0, 0xC0, 0x03, 0x1E, 0xF0, 0xFC, 0x09, 0x85, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0xBE, 0x00,
13899: 0x98, 0x57, 0x14, 0x12, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11,
13900: 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A,
13901: 0x01, 0x48, 0x55, 0xF0, 0x98, 0x04, 0x03, 0x82, 0x03, 0xFC, 0xA0, 0x00, 0x9B, 0x57, 0x40, 0x12,
13902: 0x69, 0x18, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x42, 0x04, 0x69, 0x08, 0x00, 0xF2, 0x12, 0x11,
13903: 0x85, 0xF0, 0x02, 0x0A, 0x68, 0x08, 0x4C, 0x44, 0x28, 0x12, 0x44, 0x48, 0x03, 0xF6, 0xE0, 0x00,
13904: 0x00, 0xF2, 0x68, 0x0A, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xCC, 0x01, 0x48, 0x55, 0xF0,
13905: 0x98, 0x04, 0x4C, 0x44, 0xEF, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x14, 0x10, 0x08, 0x10,
13906: 0x68, 0x18, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x04, 0x80, 0x18, 0xE4, 0x10, 0x00, 0x28, 0x12,
13907: 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00,
13908: 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00,
13909: 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00,
13910: 0x0C, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x82, 0xE7,
13911: 0x02, 0x00, 0x1C, 0x90, 0x40, 0x5C, 0x00, 0x16, 0x01, 0xE6, 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D,
13912: 0x01, 0xF0, 0x80, 0x01, 0x1E, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0xA0, 0x04, 0x42, 0x5B, 0x06, 0xF7,
13913: 0x03, 0x00, 0x46, 0x59, 0xBF, 0x57, 0x77, 0x57, 0x01, 0xE6, 0x80, 0x00, 0x07, 0x80, 0x31, 0x44,
13914: 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x56, 0x13, 0x20, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x4E, 0x12,
13915: 0x00, 0xFC, 0xA2, 0x00, 0x98, 0x57, 0x55, 0xF0, 0x1C, 0x05, 0x31, 0xE4, 0x40, 0x00, 0x00, 0xFC,
13916: 0xA0, 0x00, 0x98, 0x57, 0x36, 0x12, 0x4C, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x89, 0x48, 0x00, 0xF2,
13917: 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x82, 0xE7, 0x06, 0x00, 0x1B, 0x80, 0x48, 0xE4, 0x22, 0x00,
13918: 0x5B, 0xF0, 0x0C, 0x05, 0x48, 0xE4, 0x20, 0x00, 0x59, 0xF0, 0x10, 0x05, 0x00, 0xE6, 0x20, 0x00,
13919: 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x83, 0x80, 0x04, 0x10, 0x00, 0xF2,
13920: 0xA2, 0x0D, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x26, 0x01, 0x01, 0xEA, 0x27, 0x01, 0x04, 0x80,
13921: 0x18, 0xE4, 0x10, 0x00, 0x36, 0x12, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x01, 0xE6, 0x06, 0x00,
13922: 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4E, 0x0D,
13923: 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x04, 0xE6, 0x02, 0x00,
13924: 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0x20, 0x01,
13925: 0x98, 0x57, 0x34, 0x12, 0x00, 0xFC, 0x24, 0x01, 0x98, 0x57, 0x2C, 0x13, 0xB9, 0x54, 0x00, 0xF2,
13926: 0xF6, 0x0E, 0x86, 0xF0, 0xA8, 0x05, 0x03, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0x8C, 0x0E, 0x85, 0xF0,
13927: 0x9E, 0x05, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC,
13928: 0x24, 0x01, 0xB0, 0x57, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFC, 0x9E, 0x00, 0x98, 0x57, 0x5A, 0x12,
13929: 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, 0x52, 0x13, 0x03, 0xE6, 0x0C, 0x00, 0x00, 0xFC, 0x9C, 0x00,
13930: 0x98, 0x57, 0x04, 0x13, 0x03, 0xE6, 0x19, 0x00, 0x05, 0xE6, 0x08, 0x00, 0x00, 0xF6, 0x00, 0x01,
13931: 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x04, 0x13, 0x05, 0xE6,
13932: 0x0F, 0x00, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x86, 0xF0, 0x0A, 0x06, 0x00, 0xF2, 0xBA, 0x0E,
13933: 0x85, 0xF0, 0x00, 0x06, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00,
13934: 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0xF2,
13935: 0xF6, 0x0E, 0x9C, 0x32, 0x4E, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x82, 0xE7,
13936: 0x04, 0x00, 0xB1, 0xF0, 0x22, 0x06, 0x0A, 0xF0, 0x3E, 0x06, 0x05, 0xF0, 0xD6, 0x06, 0x06, 0xF0,
13937: 0xDC, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x04, 0x80,
13938: 0x18, 0xE4, 0x20, 0x00, 0x30, 0x12, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80,
13939: 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2,
13940: 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x99, 0xA4, 0x00, 0xF2, 0x12, 0x11,
13941: 0x09, 0xE7, 0x00, 0x00, 0x9A, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x34, 0x12, 0x09, 0xE7,
13942: 0x1B, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2,
13943: 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2,
13944: 0x12, 0x11, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF0,
13945: 0x0C, 0x09, 0xBB, 0x55, 0x9A, 0x81, 0x03, 0xF7, 0x20, 0x00, 0x09, 0x6F, 0x93, 0x45, 0x55, 0xF0,
13946: 0xE2, 0x06, 0xB1, 0xF0, 0xC2, 0x06, 0x0A, 0xF0, 0xBA, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0,
13947: 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0x47, 0x10, 0x09, 0xE7, 0x08, 0x00,
13948: 0x41, 0x10, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, 0x1E, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA,
13949: 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x2C, 0x90, 0xAE, 0x90, 0x08, 0x50, 0x8A, 0x50, 0x38, 0x54,
13950: 0x1F, 0x40, 0x00, 0xF2, 0xB4, 0x0D, 0x08, 0x10, 0x08, 0x90, 0x8A, 0x90, 0x30, 0x50, 0xB2, 0x50,
13951: 0x9C, 0x32, 0x0C, 0x92, 0x8E, 0x92, 0x38, 0x54, 0x04, 0x80, 0x30, 0xE4, 0x08, 0x00, 0x04, 0x40,
13952: 0x0C, 0x1C, 0x00, 0xF6, 0x03, 0x00, 0xB1, 0xF0, 0x26, 0x07, 0x9E, 0xF0, 0x3A, 0x07, 0x01, 0x48,
13953: 0x55, 0xF0, 0xFC, 0x09, 0x0C, 0x1C, 0x10, 0x44, 0xED, 0x10, 0x0B, 0xF0, 0x5E, 0x07, 0x0C, 0xF0,
13954: 0x62, 0x07, 0x05, 0xF0, 0x52, 0x07, 0x06, 0xF0, 0x58, 0x07, 0x09, 0xF0, 0x24, 0x09, 0x00, 0xF0,
13955: 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0xCF, 0x10, 0x09, 0xE7, 0x08, 0x00, 0xC9, 0x10, 0x2E, 0x1C,
13956: 0x02, 0x10, 0x2C, 0x1C, 0xAA, 0xF0, 0x64, 0x07, 0xAC, 0xF0, 0x72, 0x07, 0x40, 0x10, 0x34, 0x1C,
13957: 0xF3, 0x10, 0xAD, 0xF0, 0x7C, 0x07, 0xC8, 0x10, 0x36, 0x1C, 0xE9, 0x10, 0x2B, 0xF0, 0x82, 0x08,
13958: 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFE, 0x20, 0x12, 0x01, 0x58, 0xD2, 0xF0, 0x82, 0x08, 0x76, 0x18,
13959: 0x18, 0xF4, 0x03, 0x00, 0xEC, 0x12, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xE2, 0x12,
13960: 0x0B, 0xF0, 0x64, 0x07, 0x0C, 0xF0, 0x64, 0x07, 0x36, 0x1C, 0x34, 0x1C, 0xB7, 0x10, 0x38, 0x54,
13961: 0xB9, 0x54, 0x84, 0x80, 0x19, 0xE4, 0x20, 0x00, 0xB2, 0x13, 0x85, 0x80, 0x81, 0x48, 0x66, 0x12,
13962: 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x58, 0x13, 0x1F, 0x80, 0x08, 0x44, 0xC8, 0x44, 0x9F, 0x12,
13963: 0x1F, 0x40, 0x34, 0x91, 0xB6, 0x91, 0x44, 0x55, 0xE5, 0x55, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49,
13964: 0xBB, 0x55, 0x82, 0x81, 0xC0, 0x55, 0x48, 0xF4, 0x0F, 0x00, 0x5A, 0xF0, 0x1A, 0x08, 0x4A, 0xE4,
13965: 0x17, 0x00, 0xD5, 0xF0, 0xFA, 0x07, 0x02, 0xF6, 0x0F, 0x00, 0x02, 0xF4, 0x02, 0x00, 0x02, 0xEA,
13966: 0xB8, 0x00, 0x04, 0x91, 0x86, 0x91, 0x02, 0x4B, 0x2C, 0x90, 0x08, 0x50, 0x2E, 0x90, 0x0A, 0x50,
13967: 0x2C, 0x51, 0xAE, 0x51, 0x00, 0xF2, 0xB6, 0x10, 0x38, 0x54, 0x00, 0xF2, 0xB4, 0x0D, 0x56, 0x10,
13968: 0x34, 0x91, 0xB6, 0x91, 0x0C, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x41, 0x12, 0x0C, 0x91,
13969: 0x8E, 0x91, 0x04, 0x80, 0x18, 0xE4, 0xF7, 0x00, 0x04, 0x40, 0x30, 0x90, 0xB2, 0x90, 0x36, 0x10,
13970: 0x02, 0x80, 0x48, 0xE4, 0x10, 0x00, 0x31, 0x12, 0x82, 0xE7, 0x10, 0x00, 0x84, 0x80, 0x19, 0xE4,
13971: 0x20, 0x00, 0x10, 0x13, 0x0C, 0x90, 0x8E, 0x90, 0x5D, 0xF0, 0x78, 0x07, 0x0C, 0x58, 0x8D, 0x58,
13972: 0x00, 0xF0, 0x64, 0x07, 0x38, 0x54, 0xB9, 0x54, 0x19, 0x80, 0xF1, 0x10, 0x3A, 0x55, 0x19, 0x81,
13973: 0xBB, 0x55, 0x10, 0x90, 0x92, 0x90, 0x10, 0x58, 0x91, 0x58, 0x14, 0x59, 0x95, 0x59, 0x00, 0xF0,
13974: 0x64, 0x07, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x6C, 0x19, 0x19, 0x41, 0x7C, 0x10,
13975: 0x6C, 0x19, 0x0C, 0x51, 0xED, 0x19, 0x8E, 0x51, 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFF, 0x02, 0x13,
13976: 0x6A, 0x10, 0x01, 0x58, 0xD2, 0xF0, 0xC0, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x0A, 0x12,
13977: 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0x06, 0x13, 0x9E, 0xE7, 0x16, 0x00, 0x4C, 0x10,
13978: 0xD1, 0xF0, 0xCA, 0x08, 0x9E, 0xE7, 0x17, 0x00, 0x42, 0x10, 0xD0, 0xF0, 0xD4, 0x08, 0x9E, 0xE7,
13979: 0x19, 0x00, 0x38, 0x10, 0xCF, 0xF0, 0xDE, 0x08, 0x9E, 0xE7, 0x20, 0x00, 0x2E, 0x10, 0xCE, 0xF0,
13980: 0xE8, 0x08, 0x9E, 0xE7, 0x21, 0x00, 0x24, 0x10, 0xCD, 0xF0, 0xF2, 0x08, 0x9E, 0xE7, 0x22, 0x00,
13981: 0x1A, 0x10, 0xCC, 0xF0, 0x04, 0x09, 0x84, 0x80, 0x19, 0xE4, 0x04, 0x00, 0x06, 0x12, 0x9E, 0xE7,
13982: 0x12, 0x00, 0x08, 0x10, 0xCB, 0xF0, 0x0C, 0x09, 0x9E, 0xE7, 0x24, 0x00, 0xB1, 0xF0, 0x0C, 0x09,
13983: 0x05, 0xF0, 0x1E, 0x09, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0xE4, 0x10, 0x00, 0xF2,
13984: 0x60, 0x0B, 0xE9, 0x10, 0x9C, 0x32, 0x82, 0xE7, 0x20, 0x00, 0x32, 0x1C, 0xE9, 0x09, 0x00, 0xF2,
13985: 0x12, 0x11, 0x85, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x01, 0xF0, 0x44, 0x09, 0x1E, 0xF0, 0xFC, 0x09,
13986: 0x00, 0xF0, 0x38, 0x09, 0x30, 0x44, 0x06, 0x12, 0x9E, 0xE7, 0x42, 0x00, 0xB8, 0x10, 0x04, 0xF6,
13987: 0x01, 0x00, 0xB3, 0x45, 0x74, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x22, 0x13, 0x4B, 0xE4,
13988: 0x02, 0x00, 0x36, 0x12, 0x4B, 0xE4, 0x28, 0x00, 0xAC, 0x13, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2,
13989: 0xC8, 0x11, 0x03, 0xF6, 0xD0, 0x00, 0xFA, 0x14, 0x82, 0xE7, 0x01, 0x00, 0x00, 0xF0, 0x80, 0x01,
13990: 0x9E, 0xE7, 0x44, 0x00, 0x4B, 0xE4, 0x02, 0x00, 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x76, 0x10,
13991: 0x00, 0xF2, 0xA2, 0x0D, 0x03, 0xE6, 0x02, 0x00, 0x6C, 0x10, 0x00, 0xF2, 0xA2, 0x0D, 0x19, 0x82,
13992: 0x34, 0x46, 0x0A, 0x13, 0x03, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x43, 0x00, 0x68, 0x10, 0x04, 0x80,
13993: 0x30, 0xE4, 0x20, 0x00, 0x04, 0x40, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x82, 0xE7,
13994: 0x01, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x08, 0x03, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00,
13995: 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x3E, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x3A, 0x12,
13996: 0x04, 0x80, 0x18, 0xE4, 0xFD, 0x00, 0x04, 0x40, 0x1C, 0x1C, 0x9D, 0xF0, 0xEA, 0x09, 0x1C, 0x1C,
13997: 0x9D, 0xF0, 0xF0, 0x09, 0xC1, 0x10, 0x9E, 0xE7, 0x13, 0x00, 0x0A, 0x10, 0x9E, 0xE7, 0x41, 0x00,
13998: 0x04, 0x10, 0x9E, 0xE7, 0x24, 0x00, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0xD5, 0xF0, 0x8A, 0x02,
13999: 0x04, 0xE6, 0x04, 0x00, 0x06, 0x10, 0x04, 0xE6, 0x04, 0x00, 0x9D, 0x41, 0x1C, 0x42, 0x9F, 0xE7,
14000: 0x00, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x03, 0xF6, 0xE0, 0x00, 0x3C, 0x14, 0x44, 0x58, 0x45, 0x58,
14001: 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x3C, 0x14, 0x1E, 0x1C,
14002: 0x00, 0xF0, 0x80, 0x01, 0x12, 0x1C, 0x22, 0x1C, 0xD2, 0x14, 0x00, 0xF0, 0x72, 0x01, 0x83, 0x59,
14003: 0x03, 0xDC, 0x73, 0x57, 0x80, 0x5D, 0x00, 0x16, 0x83, 0x59, 0x03, 0xDC, 0x38, 0x54, 0x70, 0x57,
14004: 0x33, 0x54, 0x3B, 0x54, 0x80, 0x5D, 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x38, 0x54, 0x00, 0xCC,
14005: 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x00, 0x4C, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x01, 0x00,
14006: 0x0E, 0x12, 0x48, 0xE4, 0x05, 0x00, 0x08, 0x12, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11,
14007: 0xC1, 0x5A, 0x3A, 0x55, 0x02, 0xEC, 0xB5, 0x00, 0x45, 0x59, 0x00, 0xF2, 0xF6, 0x0D, 0x83, 0x58,
14008: 0x30, 0xE7, 0x00, 0x00, 0x10, 0x4D, 0x30, 0xE7, 0x40, 0x00, 0x10, 0x4F, 0x38, 0x90, 0xBA, 0x90,
14009: 0x10, 0x5C, 0x80, 0x5C, 0x83, 0x5A, 0x10, 0x4E, 0x04, 0xEA, 0xB5, 0x00, 0x43, 0x5B, 0x03, 0xF4,
14010: 0xE0, 0x00, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x0A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D,
14011: 0x00, 0xF2, 0x38, 0x10, 0x00, 0x16, 0x08, 0x1C, 0x00, 0xFC, 0xAC, 0x00, 0x06, 0x58, 0x67, 0x18,
14012: 0x18, 0xF4, 0x8F, 0xE1, 0x01, 0xFC, 0xAE, 0x00, 0x19, 0xF4, 0x70, 0x1E, 0xB0, 0x54, 0x07, 0x58,
14013: 0x00, 0xFC, 0xB0, 0x00, 0x08, 0x58, 0x00, 0xFC, 0xB2, 0x00, 0x09, 0x58, 0x0A, 0x1C, 0x00, 0xE6,
14014: 0x0F, 0x00, 0x00, 0xEA, 0xB9, 0x00, 0x38, 0x54, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFA, 0xB6, 0x00,
14015: 0x18, 0x1C, 0x14, 0x1C, 0x10, 0x1C, 0x32, 0x1C, 0x12, 0x1C, 0x00, 0x16, 0x3E, 0x57, 0x0C, 0x14,
14016: 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, 0xF5, 0x13, 0x00, 0x16, 0x00, 0xF2, 0xA2, 0x0D,
14017: 0x02, 0x4B, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x20, 0x12, 0x44, 0x58,
14018: 0x45, 0x58, 0x9E, 0xE7, 0x15, 0x00, 0x9C, 0xE7, 0x04, 0x00, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2,
14019: 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x7A, 0x0A, 0x1E, 0x1C, 0xD5, 0x10, 0x00, 0x16,
14020: 0x69, 0x08, 0x48, 0xE4, 0x04, 0x00, 0x64, 0x12, 0x48, 0xE4, 0x02, 0x00, 0x20, 0x12, 0x48, 0xE4,
14021: 0x03, 0x00, 0x1A, 0x12, 0x48, 0xE4, 0x08, 0x00, 0x14, 0x12, 0x48, 0xE4, 0x01, 0x00, 0xF0, 0x12,
14022: 0x48, 0xE4, 0x07, 0x00, 0x12, 0x12, 0x01, 0xE6, 0x07, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2,
14023: 0x12, 0x11, 0x05, 0xF0, 0x60, 0x0B, 0x00, 0x16, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x99, 0x00,
14024: 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0xE7, 0x12, 0x48, 0xE4, 0x06, 0x00, 0xE1, 0x12, 0x01, 0xE6,
14025: 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7,
14026: 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4,
14027: 0x10, 0x00, 0x1C, 0x12, 0x82, 0xE7, 0x08, 0x00, 0x3C, 0x56, 0x03, 0x82, 0x00, 0xF2, 0xE2, 0x0D,
14028: 0x30, 0xE7, 0x08, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x80, 0x01,
14029: 0x6C, 0x19, 0xED, 0x19, 0x5D, 0xF0, 0xD4, 0x0B, 0x44, 0x55, 0xE5, 0x55, 0x59, 0xF0, 0x52, 0x0C,
14030: 0x04, 0x55, 0xA5, 0x55, 0x1F, 0x80, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x49, 0x44,
14031: 0x2E, 0x13, 0x01, 0xEC, 0xB8, 0x00, 0x41, 0xE4, 0x02, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x49, 0xE4,
14032: 0x11, 0x00, 0x59, 0xF0, 0x2E, 0x0C, 0x01, 0xE6, 0x17, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x02, 0x4B,
14033: 0x88, 0x90, 0xAC, 0x50, 0x8A, 0x90, 0xAE, 0x50, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80,
14034: 0x10, 0x44, 0x02, 0x4B, 0x1F, 0x40, 0xC0, 0x44, 0x00, 0xF2, 0xB4, 0x0D, 0x04, 0x55, 0xA5, 0x55,
14035: 0x9F, 0x10, 0x0C, 0x51, 0x8E, 0x51, 0x30, 0x90, 0xB2, 0x90, 0x00, 0x56, 0xA1, 0x56, 0x30, 0x50,
14036: 0xB2, 0x50, 0x34, 0x90, 0xB6, 0x90, 0x40, 0x56, 0xE1, 0x56, 0x34, 0x50, 0xB6, 0x50, 0x65, 0x10,
14037: 0xB1, 0xF0, 0x70, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0xE9, 0x09, 0x4B, 0xE4, 0x03, 0x00, 0x78, 0x12,
14038: 0x4B, 0xE4, 0x02, 0x00, 0x01, 0x13, 0xB1, 0xF0, 0x86, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0x69, 0x08,
14039: 0x48, 0xE4, 0x03, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0xCA, 0x0B,
14040: 0xE8, 0x09, 0x3C, 0x56, 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x02, 0x13, 0xBB, 0x45, 0x4B, 0xE4,
14041: 0x00, 0x00, 0x08, 0x12, 0x03, 0xE6, 0x01, 0x00, 0x04, 0xF6, 0x00, 0x80, 0xA8, 0x14, 0xD2, 0x14,
14042: 0x30, 0x1C, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x10, 0x13, 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57,
14043: 0x02, 0x13, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57,
14044: 0x00, 0xFA, 0x24, 0x01, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B,
14045: 0x00, 0xF2, 0x8C, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0xB1, 0xF0, 0xF8, 0x0C, 0x85, 0xF0, 0x86, 0x0B,
14046: 0x69, 0x08, 0x48, 0xE4, 0x01, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0xFC, 0x14, 0x42, 0x58, 0x6C, 0x14,
14047: 0x80, 0x14, 0x30, 0x1C, 0x4A, 0xF4, 0x02, 0x00, 0x55, 0xF0, 0x86, 0x0B, 0x4A, 0xF4, 0x01, 0x00,
14048: 0x0E, 0x12, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x06, 0x13, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B,
14049: 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2,
14050: 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, 0x00, 0xF2, 0xBA, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0x4C, 0x1C,
14051: 0xB1, 0xF0, 0x50, 0x0D, 0x85, 0xF0, 0x5C, 0x0D, 0x69, 0x08, 0xF3, 0x10, 0x86, 0xF0, 0x64, 0x0D,
14052: 0x4E, 0x1C, 0x89, 0x48, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58,
14053: 0x00, 0xDC, 0x18, 0xF4, 0xFF, 0x7F, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01,
14054: 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x30, 0x56, 0x00, 0x5C,
14055: 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x0B, 0x58,
14056: 0x00, 0x16, 0x03, 0xF6, 0x24, 0x01, 0x00, 0xF2, 0x58, 0x0A, 0x03, 0xF6, 0xB6, 0x00, 0x00, 0xF2,
14057: 0x58, 0x0A, 0x00, 0x16, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0x18, 0xF4, 0xFF, 0x00, 0x00, 0x54,
14058: 0x00, 0x54, 0x00, 0x54, 0x00, 0xF4, 0x08, 0x00, 0xE1, 0x18, 0x80, 0x54, 0x03, 0x58, 0x00, 0xDD,
14059: 0x01, 0xDD, 0x02, 0xDD, 0x03, 0xDC, 0x02, 0x4B, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x51, 0xB6, 0x51,
14060: 0x00, 0x16, 0x45, 0x5A, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4,
14061: 0x02, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56,
14062: 0x05, 0xF4, 0x00, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x38, 0x54, 0xBB, 0x55, 0x3C, 0x56, 0xBD, 0x56,
14063: 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x82, 0x0E, 0xE9, 0x09, 0xC1, 0x59, 0x00, 0xF2, 0x12, 0x11,
14064: 0x85, 0xF0, 0x82, 0x0E, 0xE8, 0x0A, 0x83, 0x55, 0x83, 0x55, 0x4B, 0xF4, 0x90, 0x01, 0x5C, 0xF0,
14065: 0x36, 0x0E, 0xBD, 0x56, 0x40, 0x10, 0x4B, 0xF4, 0x30, 0x00, 0x59, 0xF0, 0x48, 0x0E, 0x01, 0xF6,
14066: 0x0C, 0x00, 0x00, 0xF6, 0x01, 0x00, 0x2E, 0x10, 0x02, 0xFC, 0x9C, 0x00, 0x9A, 0x57, 0x14, 0x13,
14067: 0x4B, 0xF4, 0x64, 0x00, 0x59, 0xF0, 0x64, 0x0E, 0x03, 0xF6, 0x64, 0x00, 0x01, 0xF6, 0x19, 0x00,
14068: 0x00, 0xF6, 0x01, 0x00, 0x43, 0xF4, 0x33, 0x00, 0x56, 0xF0, 0x76, 0x0E, 0x04, 0xF4, 0x00, 0x01,
14069: 0x43, 0xF4, 0x19, 0x00, 0xF3, 0x10, 0xB4, 0x56, 0xC3, 0x58, 0x02, 0xFC, 0x9E, 0x00, 0x9A, 0x57,
14070: 0x08, 0x13, 0x3C, 0x56, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x16, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00,
14071: 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x02, 0x00, 0x00, 0xF2, 0x12, 0x11,
14072: 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E,
14073: 0x4E, 0x1C, 0x89, 0x49, 0x00, 0xF2, 0x12, 0x11, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2,
14074: 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0,
14075: 0xF2, 0x0E, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x89, 0x49,
14076: 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x4E, 0x1C, 0x89, 0x4A, 0x00, 0xF2, 0x12, 0x11,
14077: 0x00, 0x16, 0x3C, 0x56, 0x00, 0x16, 0x00, 0xEC, 0x26, 0x01, 0x48, 0xE4, 0x01, 0x00, 0x1E, 0x13,
14078: 0x38, 0x44, 0x00, 0xEA, 0x26, 0x01, 0x49, 0xF4, 0x00, 0x00, 0x04, 0x12, 0x4E, 0x1C, 0x02, 0x10,
14079: 0x4C, 0x1C, 0x01, 0xEC, 0x27, 0x01, 0x89, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x02, 0x14, 0x00, 0x16,
14080: 0x85, 0xF0, 0x52, 0x0F, 0x38, 0x54, 0x00, 0xEA, 0x99, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x02, 0x80,
14081: 0x48, 0xE4, 0x06, 0x00, 0x1C, 0x13, 0x00, 0xEC, 0x99, 0x00, 0x48, 0xE4, 0x01, 0x00, 0x0A, 0x12,
14082: 0x04, 0x80, 0x30, 0xE4, 0x01, 0x00, 0x04, 0x40, 0x08, 0x10, 0x04, 0x80, 0x18, 0xE4, 0xFE, 0x00,
14083: 0x04, 0x40, 0x00, 0x16, 0x02, 0xF6, 0xE0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x81, 0x48,
14084: 0x22, 0x12, 0x00, 0x4E, 0x83, 0x5A, 0x90, 0x4C, 0x20, 0xE7, 0x00, 0x00, 0xC3, 0x58, 0x1B, 0xF4,
14085: 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x8B, 0x55, 0x83, 0x59,
14086: 0x00, 0x4E, 0x00, 0x16, 0x00, 0x4E, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x00, 0x4E,
14087: 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x20, 0xE7, 0x00, 0x00, 0x00, 0x16, 0x02, 0xF6, 0xF0, 0x00,
14088: 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x80, 0x4C,
14089: 0xC3, 0x58, 0x1B, 0xF4, 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12,
14090: 0x83, 0x59, 0x00, 0x4E, 0x00, 0x16, 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x3A, 0x55,
14091: 0x02, 0xCC, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0xC0, 0x5A, 0x40, 0x5C, 0x38, 0x54, 0x00, 0xCD,
14092: 0x01, 0xCC, 0x4A, 0x46, 0x0A, 0x13, 0x83, 0x59, 0x00, 0x4C, 0x01, 0x48, 0x16, 0x13, 0x0C, 0x10,
14093: 0xC5, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0x4C, 0x01, 0x48, 0x08, 0x13, 0x05, 0xF6, 0xF0, 0x00,
14094: 0x05, 0x57, 0x08, 0x10, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x8D, 0x56, 0x83, 0x5A, 0x80, 0x4C,
14095: 0x05, 0x17, 0x00, 0x16, 0x02, 0x4B, 0x06, 0xF7, 0x04, 0x00, 0x62, 0x0B, 0x03, 0x82, 0x00, 0xF2,
14096: 0xE2, 0x0D, 0x02, 0x80, 0x00, 0x4C, 0x45, 0xF4, 0x02, 0x00, 0x52, 0x14, 0x06, 0xF7, 0x02, 0x00,
14097: 0x06, 0x14, 0x00, 0xF2, 0x54, 0x0F, 0x00, 0x16, 0x02, 0x4B, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C,
14098: 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x1D, 0xF7, 0x3C, 0x00, 0xB8, 0xF0,
14099: 0x4E, 0x10, 0x9C, 0x14, 0x01, 0x48, 0x1C, 0x13, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00,
14100: 0xAF, 0x19, 0x03, 0x42, 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x02, 0xCC, 0x02, 0x41, 0x45, 0xF4,
14101: 0x02, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, 0x3E, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x01, 0xF6,
14102: 0xFF, 0x00, 0x38, 0x1C, 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x0E, 0xF7,
14103: 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, 0x0F, 0x79, 0x1C, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x9C, 0x10,
14104: 0x4E, 0x14, 0x01, 0x48, 0x06, 0x13, 0x45, 0xF4, 0x04, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0,
14105: 0x82, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x02, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x2C, 0xBC, 0xAE, 0xBC,
14106: 0xE2, 0x08, 0x00, 0xEC, 0xB8, 0x00, 0x02, 0x48, 0x1D, 0xF7, 0x80, 0x00, 0xB8, 0xF0, 0xCC, 0x10,
14107: 0x1E, 0x14, 0x01, 0x48, 0x0E, 0x13, 0x0E, 0xF7, 0x80, 0x00, 0x38, 0x54, 0x03, 0x58, 0xAF, 0x19,
14108: 0x82, 0x48, 0x00, 0x16, 0x82, 0x48, 0x12, 0x45, 0xD5, 0xF0, 0xBA, 0x10, 0x00, 0xF0, 0x9E, 0x02,
14109: 0x39, 0xF0, 0xF8, 0x10, 0x38, 0x44, 0x00, 0x16, 0x7E, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x04, 0x13,
14110: 0x61, 0x18, 0x00, 0x16, 0x38, 0x1C, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xF1, 0x12,
14111: 0xE3, 0x10, 0x30, 0x44, 0x30, 0x44, 0x30, 0x44, 0xB1, 0xF0, 0x18, 0x11, 0x00, 0x16, 0x3E, 0x57,
14112: 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x6A, 0x12, 0x45, 0x5A,
14113: 0x00, 0xF2, 0xF6, 0x0D, 0x02, 0x4B, 0x70, 0x14, 0x34, 0x13, 0x02, 0x80, 0x48, 0xE4, 0x08, 0x00,
14114: 0x18, 0x12, 0x9C, 0xE7, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2,
14115: 0x7A, 0x0A, 0x1E, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x30, 0xE4, 0x10, 0x00, 0x04, 0x40,
14116: 0x00, 0xF2, 0xE2, 0x0D, 0x20, 0xE7, 0x01, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x04, 0xDC,
14117: 0x01, 0x4A, 0x24, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x43, 0x5B, 0x06, 0xEC, 0x98, 0x00,
14118: 0x00, 0xF2, 0x38, 0x10, 0xC6, 0x59, 0x20, 0x14, 0x0A, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2,
14119: 0x14, 0x10, 0xA7, 0x10, 0x83, 0x5A, 0xD7, 0x10, 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47,
14120: 0x5A, 0xF0, 0x20, 0x11, 0xB9, 0x54, 0x00, 0x16, 0x14, 0x90, 0x96, 0x90, 0x02, 0xFC, 0xA8, 0x00,
14121: 0x03, 0xFC, 0xAA, 0x00, 0x48, 0x55, 0x02, 0x13, 0xC9, 0x55, 0x00, 0x16, 0x00, 0xEC, 0xBA, 0x00,
14122: 0x10, 0x44, 0x00, 0xEA, 0xBA, 0x00, 0x00, 0x16, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A,
14123: 0x10, 0x44, 0x00, 0x4C, 0x00, 0x16
14124: };
14125:
14126: unsigned short _adv_mcode_size ASC_INITDATA =
14127: sizeof(_adv_mcode_buf); /* 0x11D6 */
14128: unsigned long _adv_mcode_chksum ASC_INITDATA = 0x03494981UL;
14129:
14130: /* a_init.c */
14131: /*
14132: * EEPROM Configuration.
14133: *
14134: * All drivers should use this structure to set the default EEPROM
14135: * configuration. The BIOS now uses this structure when it is built.
14136: * Additional structure information can be found in a_condor.h where
14137: * the structure is defined.
14138: */
14139: STATIC ADVEEP_CONFIG
14140: Default_EEPROM_Config ASC_INITDATA = {
14141: ADV_EEPROM_BIOS_ENABLE, /* cfg_msw */
14142: 0x0000, /* cfg_lsw */
14143: 0xFFFF, /* disc_enable */
14144: 0xFFFF, /* wdtr_able */
14145: 0xFFFF, /* sdtr_able */
14146: 0xFFFF, /* start_motor */
14147: 0xFFFF, /* tagqng_able */
14148: 0xFFFF, /* bios_scan */
14149: 0, /* scam_tolerant */
14150: 7, /* adapter_scsi_id */
14151: 0, /* bios_boot_delay */
14152: 3, /* scsi_reset_delay */
14153: 0, /* bios_id_lun */
14154: 0, /* termination */
14155: 0, /* reserved1 */
14156: 0xFFEF, /* bios_ctrl */
14157: 0xFFFF, /* ultra_able */
14158: 0, /* reserved2 */
14159: ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
14160: ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
14161: 0, /* dvc_cntl */
14162: 0, /* bug_fix */
14163: 0, /* serial_number_word1 */
14164: 0, /* serial_number_word2 */
14165: 0, /* serial_number_word3 */
14166: 0, /* check_sum */
14167: { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */
14168: 0, /* dvc_err_code */
14169: 0, /* adv_err_code */
14170: 0, /* adv_err_addr */
14171: 0, /* saved_dvc_err_code */
14172: 0, /* saved_adv_err_code */
14173: 0, /* saved_adv_err_addr */
14174: 0 /* num_of_err */
14175: };
14176:
14177: /*
14178: * Initialize the ADV_DVC_VAR structure.
14179: *
14180: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14181: *
14182: * For a non-fatal error return a warning code. If there are no warnings
14183: * then 0 is returned.
14184: */
14185: ASC_INITFUNC(
14186: int
14187: AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
14188: )
14189: {
14190: ushort warn_code;
14191: AdvPortAddr iop_base;
14192: uchar pci_cmd_reg;
14193: int status;
14194:
14195: warn_code = 0;
14196: asc_dvc->err_code = 0;
14197: iop_base = asc_dvc->iop_base;
14198:
14199: /*
14200: * PCI Command Register
14201: */
14202:
14203: if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
14204: AscPCIConfigCommandRegister))
14205: & AscPCICmdRegBits_BusMastering)
14206: != AscPCICmdRegBits_BusMastering)
14207: {
14208: pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
14209:
14210: DvcAdvWritePCIConfigByte(asc_dvc,
14211: AscPCIConfigCommandRegister, pci_cmd_reg);
14212:
14213: if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister))
14214: & AscPCICmdRegBits_BusMastering)
14215: != AscPCICmdRegBits_BusMastering)
14216: {
14217: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14218: }
14219: }
14220:
14221: /*
14222: * PCI Latency Timer
14223: *
14224: * If the "latency timer" register is 0x20 or above, then we don't need
14225: * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
14226: * comes up less than 0x20).
14227: */
14228: if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
14229: DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20);
14230: if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20)
14231: {
14232: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
14233: }
14234: }
14235:
14236: /*
14237: * Save the state of the PCI Configuration Command Register
14238: * "Parity Error Response Control" Bit. If the bit is clear (0),
14239: * in AdvInitAsc3550Driver() tell the microcode to ignore DMA
14240: * parity errors.
14241: */
14242: asc_dvc->cfg->control_flag = 0;
14243: if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
14244: & AscPCICmdRegBits_ParErrRespCtrl)) == 0)
14245: {
14246: asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
14247: }
14248:
14249: asc_dvc->cur_host_qng = 0;
14250:
14251: asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
14252: ADV_LIB_VERSION_MINOR;
14253: asc_dvc->cfg->chip_version =
14254: AdvGetChipVersion(iop_base, asc_dvc->bus_type);
14255:
14256: /*
14257: * Reset the chip to start and allow register writes.
14258: */
14259: if (AdvFindSignature(iop_base) == 0)
14260: {
14261: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
14262: return ADV_ERROR;
14263: }
14264: else {
14265:
14266: AdvResetChip(asc_dvc);
14267:
14268: if ((status = AdvInitFromEEP(asc_dvc)) == ADV_ERROR)
14269: {
14270: return ADV_ERROR;
14271: }
14272: warn_code |= status;
14273:
14274: /*
14275: * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
14276: * Resets should be performed.
14277: */
14278: if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
14279: {
14280: AdvResetSCSIBus(asc_dvc);
14281: }
14282: }
14283:
14284: return warn_code;
14285: }
14286:
14287: /*
14288: * Initialize the ASC3550.
14289: *
14290: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14291: *
14292: * For a non-fatal error return a warning code. If there are no warnings
14293: * then 0 is returned.
14294: */
14295: ASC_INITFUNC(
14296: int
14297: AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
14298: )
14299: {
14300: AdvPortAddr iop_base;
14301: ushort warn_code;
14302: ulong sum;
14303: int begin_addr;
14304: int end_addr;
14305: int code_sum;
14306: int word;
14307: int rql_addr; /* RISC Queue List address */
14308: int i;
14309: ushort scsi_cfg1;
14310: uchar biosmem[ASC_MC_BIOSLEN]; /* BIOS RISC Memory 0x40-0x8F. */
14311:
14312: /* If there is already an error, don't continue. */
14313: if (asc_dvc->err_code != 0)
14314: {
14315: return ADV_ERROR;
14316: }
14317:
14318: warn_code = 0;
14319: iop_base = asc_dvc->iop_base;
14320:
14321: /*
14322: * Save the RISC memory BIOS region before writing the microcode.
14323: * The BIOS may already be loaded and using its RISC LRAM region
14324: * so its region must be saved and restored.
14325: *
14326: * Note: This code makes the assumption, which is currently true,
14327: * that a chip reset does not clear RISC LRAM.
14328: */
14329: for (i = 0; i < ASC_MC_BIOSLEN; i++)
14330: {
14331: AdvReadByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
14332: }
14333:
14334: /*
14335: * Load the Microcode
14336: *
14337: * Write the microcode image to RISC memory starting at address 0.
14338: */
14339: AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14340: for (word = 0; word < _adv_mcode_size; word += 2)
14341: {
14342: AdvWriteWordAutoIncLram(iop_base,
14343: *((ushort *) (&_adv_mcode_buf[word])));
14344: }
14345:
14346: /*
14347: * Clear the rest of Condor's Internal RAM (8KB).
14348: */
14349: for (; word < ADV_CONDOR_MEMSIZE; word += 2)
14350: {
14351: AdvWriteWordAutoIncLram(iop_base, 0);
14352: }
14353:
14354: /*
14355: * Verify the microcode checksum.
14356: */
14357: sum = 0;
14358: AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14359: for (word = 0; word < _adv_mcode_size; word += 2)
14360: {
14361: sum += AdvReadWordAutoIncLram(iop_base);
14362: }
14363:
14364: if (sum != _adv_mcode_chksum)
14365: {
14366: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14367: return ADV_ERROR;
14368: }
14369:
14370: /*
14371: * Restore the RISC memory BIOS region.
14372: */
14373: for (i = 0; i < ASC_MC_BIOSLEN; i++)
14374: {
14375: AdvWriteByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
14376: }
14377:
14378: /*
14379: * Calculate and write the microcode code checksum to the microcode
14380: * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
14381: */
14382: AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
14383: AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
14384: code_sum = 0;
14385: for (word = begin_addr; word < end_addr; word += 2)
14386: {
14387: code_sum += *((ushort *) (&_adv_mcode_buf[word]));
14388: }
14389: AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
14390:
14391: /*
14392: * Read microcode version and date.
14393: */
14394: AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date);
14395: AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version);
14396:
14397: /*
14398: * Initialize microcode operating variables
14399: */
14400: AdvWriteWordLram(iop_base, ASC_MC_ADAPTER_SCSI_ID,
14401: asc_dvc->chip_scsi_id);
14402:
14403: /*
14404: * If the PCI Configuration Command Register "Parity Error Response
14405: * Control" Bit was clear (0), then set the microcode variable
14406: * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
14407: * to ignore DMA parity errors.
14408: */
14409: if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR)
14410: {
14411: /*
14412: * Note: Don't remove the use of a temporary variable in
14413: * the following code, otherwise the Microsoft C compiler
14414: * will turn the following lines into a no-op.
14415: */
14416: AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14417: word |= CONTROL_FLAG_IGNORE_PERR;
14418: AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
14419: }
14420:
14421: /*
14422: * Set default microcode operating variables for WDTR, SDTR, and
14423: * command tag queuing based on the EEPROM configuration values.
14424: *
14425: * These ADV_DVC_VAR fields and the microcode variables will be
14426: * changed in AdvInquiryHandling() if it is found a device is
14427: * incapable of a particular feature.
14428: */
14429:
14430: /*
14431: * Set the microcode ULTRA target mask from EEPROM value. The
14432: * SDTR target mask overrides the ULTRA target mask in the
14433: * microcode so it is safe to set this value without determining
14434: * whether the device supports SDTR.
14435: *
14436: * Note: There is no way to know whether a device supports ULTRA
14437: * speed without attempting a SDTR ULTRA speed negotiation with
14438: * the device. The device will reject the speed if it does not
14439: * support it by responding with an SDTR message containing a
14440: * slower speed.
14441: */
14442: AdvWriteWordLram(iop_base, ASC_MC_ULTRA_ABLE, asc_dvc->ultra_able);
14443: AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable);
14444:
14445:
14446: /*
14447: * Set SCSI_CFG0 Microcode Default Value.
14448: *
14449: * The microcode will set the SCSI_CFG0 register using this value
14450: * after it is started below.
14451: */
14452: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
14453: PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id);
14454:
14455: /*
14456: * Determine SCSI_CFG1 Microcode Default Value.
14457: *
14458: * The microcode will set the SCSI_CFG1 register using this value
14459: * after it is started below.
14460: */
14461:
14462: /* Read current SCSI_CFG1 Register value. */
14463: scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14464:
14465: /*
14466: * If all three connectors are in use, return an error.
14467: */
14468: if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
14469: (scsi_cfg1 & CABLE_ILLEGAL_B) == 0)
14470: {
14471: asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
14472: return ADV_ERROR;
14473: }
14474:
14475: /*
14476: * If the internal narrow cable is reversed all of the SCSI_CTRL
14477: * register signals will be set. Check for and return an error if
14478: * this condition is found.
14479: */
14480: if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07)
14481: {
14482: asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
14483: return ADV_ERROR;
14484: }
14485:
14486: /*
14487: * If this is a differential board and a single-ended device
14488: * is attached to one of the connectors, return an error.
14489: */
14490: if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0)
14491: {
14492: asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
14493: return ADV_ERROR;
14494: }
14495:
14496: /*
14497: * If automatic termination control is enabled, then set the
14498: * termination value based on a table listed in a_condor.h.
14499: *
14500: * If manual termination was specified with an EEPROM setting
14501: * then 'termination' was set-up in AdvInitFromEEP() and
14502: * is ready to be 'ored' into SCSI_CFG1.
14503: */
14504: if (asc_dvc->cfg->termination == 0)
14505: {
14506: /*
14507: * The software always controls termination by setting TERM_CTL_SEL.
14508: * If TERM_CTL_SEL were set to 0, the hardware would set termination.
14509: */
14510: asc_dvc->cfg->termination |= TERM_CTL_SEL;
14511:
14512: switch(scsi_cfg1 & CABLE_DETECT)
14513: {
14514: /* TERM_CTL_H: on, TERM_CTL_L: on */
14515: case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF:
14516: asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
14517: break;
14518:
14519: /* TERM_CTL_H: on, TERM_CTL_L: off */
14520: case 0x1: case 0x5: case 0x9: case 0xA: case 0xC:
14521: asc_dvc->cfg->termination |= TERM_CTL_H;
14522: break;
14523:
14524: /* TERM_CTL_H: off, TERM_CTL_L: off */
14525: case 0x2: case 0x6:
14526: break;
14527: }
14528: }
14529:
14530: /*
14531: * Clear any set TERM_CTL_H and TERM_CTL_L bits.
14532: */
14533: scsi_cfg1 &= ~TERM_CTL;
14534:
14535: /*
14536: * Invert the TERM_CTL_H and TERM_CTL_L bits and then
14537: * set 'scsi_cfg1'. The TERM_POL bit does not need to be
14538: * referenced, because the hardware internally inverts
14539: * the Termination High and Low bits if TERM_POL is set.
14540: */
14541: scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
14542:
14543: /*
14544: * Set SCSI_CFG1 Microcode Default Value
14545: *
14546: * Set filter value and possibly modified termination control
14547: * bits in the Microcode SCSI_CFG1 Register Value.
14548: *
14549: * The microcode will set the SCSI_CFG1 register using this value
14550: * after it is started below.
14551: */
14552: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
14553: FLTR_11_TO_20NS | scsi_cfg1);
14554:
14555: /*
14556: * Set SEL_MASK Microcode Default Value
14557: *
14558: * The microcode will set the SEL_MASK register using this value
14559: * after it is started below.
14560: */
14561: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
14562: ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
14563:
14564: /*
14565: * Link all the RISC Queue Lists together in a doubly-linked
14566: * NULL terminated list.
14567: *
14568: * Skip the NULL (0) queue which is not used.
14569: */
14570: for (i = 1, rql_addr = ASC_MC_RISC_Q_LIST_BASE + ASC_MC_RISC_Q_LIST_SIZE;
14571: i < ASC_MC_RISC_Q_TOTAL_CNT;
14572: i++, rql_addr += ASC_MC_RISC_Q_LIST_SIZE)
14573: {
14574: /*
14575: * Set the current RISC Queue List's RQL_FWD and RQL_BWD pointers
14576: * in a one word write and set the state (RQL_STATE) to free.
14577: */
14578: AdvWriteWordLram(iop_base, rql_addr, ((i + 1) + ((i - 1) << 8)));
14579: AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
14580: }
14581:
14582: /*
14583: * Set the Host and RISC Queue List pointers.
14584: *
14585: * Both sets of pointers are initialized with the same values:
14586: * ASC_MC_RISC_Q_FIRST(0x01) and ASC_MC_RISC_Q_LAST (0xFF).
14587: */
14588: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, ASC_MC_RISC_Q_FIRST);
14589: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, ASC_MC_RISC_Q_LAST);
14590:
14591: AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_READY, ASC_MC_RISC_Q_FIRST);
14592: AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_DONE, ASC_MC_RISC_Q_LAST);
14593:
14594: /*
14595: * Finally, set up the last RISC Queue List (255) with
14596: * a NULL forward pointer.
14597: */
14598: AdvWriteWordLram(iop_base, rql_addr, (ASC_MC_NULL_Q + ((i - 1) << 8)));
14599: AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
14600:
14601: AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
14602: (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR));
14603:
14604: /*
14605: * Note: Don't remove the use of a temporary variable in
14606: * the following code, otherwise the Microsoft C compiler
14607: * will turn the following lines into a no-op.
14608: */
14609: AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
14610: AdvWriteWordRegister(iop_base, IOPW_PC, word);
14611:
14612: /* finally, finally, gentlemen, start your engine */
14613: AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
14614:
14615: return warn_code;
14616: }
14617:
14618: /*
14619: * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
14620: * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
14621: * all of this is done.
14622: *
14623: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
14624: *
14625: * For a non-fatal error return a warning code. If there are no warnings
14626: * then 0 is returned.
14627: *
14628: * Note: Chip is stopped on entry.
14629: */
14630: ASC_INITFUNC(
14631: STATIC int
14632: AdvInitFromEEP(ADV_DVC_VAR *asc_dvc)
14633: )
14634: {
14635: AdvPortAddr iop_base;
14636: ushort warn_code;
14637: ADVEEP_CONFIG eep_config;
14638: int i;
14639:
14640: iop_base = asc_dvc->iop_base;
14641:
14642: warn_code = 0;
14643:
14644: /*
14645: * Read the board's EEPROM configuration.
14646: *
14647: * Set default values if a bad checksum is found.
14648: */
14649: if (AdvGetEEPConfig(iop_base, &eep_config) != eep_config.check_sum)
14650: {
14651: warn_code |= ASC_WARN_EEPROM_CHKSUM;
14652:
14653: /*
14654: * Set EEPROM default values.
14655: */
14656: for (i = 0; i < sizeof(ADVEEP_CONFIG); i++)
14657: {
14658: *((uchar *) &eep_config + i) =
14659: *((uchar *) &Default_EEPROM_Config + i);
14660: }
14661:
14662: /*
14663: * Assume the 6 byte board serial number that was read
14664: * from EEPROM is correct even if the EEPROM checksum
14665: * failed.
14666: */
14667: eep_config.serial_number_word3 =
14668: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1);
14669: eep_config.serial_number_word2 =
14670: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2);
14671: eep_config.serial_number_word1 =
14672: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3);
14673: AdvSetEEPConfig(iop_base, &eep_config);
14674: }
14675:
14676: /*
14677: * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
14678: * EEPROM configuration that was read.
14679: *
14680: * This is the mapping of EEPROM fields to Adv Library fields.
14681: */
14682: asc_dvc->wdtr_able = eep_config.wdtr_able;
14683: asc_dvc->sdtr_able = eep_config.sdtr_able;
14684: asc_dvc->ultra_able = eep_config.ultra_able;
14685: asc_dvc->tagqng_able = eep_config.tagqng_able;
14686: asc_dvc->cfg->disc_enable = eep_config.disc_enable;
14687: asc_dvc->max_host_qng = eep_config.max_host_qng;
14688: asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
14689: asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
14690: asc_dvc->start_motor = eep_config.start_motor;
14691: asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
14692: asc_dvc->cfg->bios_boot_wait = eep_config.bios_boot_delay;
14693: asc_dvc->bios_ctrl = eep_config.bios_ctrl;
14694: asc_dvc->no_scam = eep_config.scam_tolerant;
14695: asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
14696: asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
14697: asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
14698:
14699: /*
14700: * Set the host maximum queuing (max. 253, min. 16) and the per device
14701: * maximum queuing (max. 63, min. 4).
14702: */
14703: if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG)
14704: {
14705: eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
14706: } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG)
14707: {
14708: /* If the value is zero, assume it is uninitialized. */
14709: if (eep_config.max_host_qng == 0)
14710: {
14711: eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
14712: } else
14713: {
14714: eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
14715: }
14716: }
14717:
14718: if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG)
14719: {
14720: eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
14721: } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG)
14722: {
14723: /* If the value is zero, assume it is uninitialized. */
14724: if (eep_config.max_dvc_qng == 0)
14725: {
14726: eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
14727: } else
14728: {
14729: eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
14730: }
14731: }
14732:
14733: /*
14734: * If 'max_dvc_qng' is greater than 'max_host_qng', then
14735: * set 'max_dvc_qng' to 'max_host_qng'.
14736: */
14737: if (eep_config.max_dvc_qng > eep_config.max_host_qng)
14738: {
14739: eep_config.max_dvc_qng = eep_config.max_host_qng;
14740: }
14741:
14742: /*
14743: * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_CFG 'max_dvc_qng'
14744: * values based on possibly adjusted EEPROM values.
14745: */
14746: asc_dvc->max_host_qng = eep_config.max_host_qng;
14747: asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
14748:
14749:
14750: /*
14751: * If the EEPROM 'termination' field is set to automatic (0), then set
14752: * the ADV_DVC_CFG 'termination' field to automatic also.
14753: *
14754: * If the termination is specified with a non-zero 'termination'
14755: * value check that a legal value is set and set the ADV_DVC_CFG
14756: * 'termination' field appropriately.
14757: */
14758: if (eep_config.termination == 0)
14759: {
14760: asc_dvc->cfg->termination = 0; /* auto termination */
14761: } else
14762: {
14763: /* Enable manual control with low off / high off. */
14764: if (eep_config.termination == 1)
14765: {
14766: asc_dvc->cfg->termination = TERM_CTL_SEL;
14767:
14768: /* Enable manual control with low off / high on. */
14769: } else if (eep_config.termination == 2)
14770: {
14771: asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
14772:
14773: /* Enable manual control with low on / high on. */
14774: } else if (eep_config.termination == 3)
14775: {
14776: asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
14777: } else
14778: {
14779: /*
14780: * The EEPROM 'termination' field contains a bad value. Use
14781: * automatic termination instead.
14782: */
14783: asc_dvc->cfg->termination = 0;
14784: warn_code |= ASC_WARN_EEPROM_TERMINATION;
14785: }
14786: }
14787:
14788: return warn_code;
14789: }
14790:
14791: /*
14792: * Read EEPROM configuration into the specified buffer.
14793: *
14794: * Return a checksum based on the EEPROM configuration read.
14795: */
14796: ASC_INITFUNC(
14797: STATIC ushort
14798: AdvGetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
14799: )
14800: {
14801: ushort wval, chksum;
14802: ushort *wbuf;
14803: int eep_addr;
14804:
14805: wbuf = (ushort *) cfg_buf;
14806: chksum = 0;
14807:
14808: for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
14809: eep_addr < ASC_EEP_DVC_CFG_END;
14810: eep_addr++, wbuf++)
14811: {
14812: wval = AdvReadEEPWord(iop_base, eep_addr);
14813: chksum += wval;
14814: *wbuf = wval;
14815: }
14816: *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14817: wbuf++;
14818: for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
14819: eep_addr < ASC_EEP_MAX_WORD_ADDR;
14820: eep_addr++, wbuf++)
14821: {
14822: *wbuf = AdvReadEEPWord(iop_base, eep_addr);
14823: }
14824: return chksum;
14825: }
14826:
14827: /*
14828: * Read the EEPROM from specified location
14829: */
14830: ASC_INITFUNC(
14831: STATIC ushort
14832: AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
14833: )
14834: {
14835: AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
14836: ASC_EEP_CMD_READ | eep_word_addr);
14837: AdvWaitEEPCmd(iop_base);
14838: return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
14839: }
14840:
14841: /*
14842: * Wait for EEPROM command to complete
14843: */
14844: ASC_INITFUNC(
14845: STATIC void
14846: AdvWaitEEPCmd(AdvPortAddr iop_base)
14847: )
14848: {
14849: int eep_delay_ms;
14850:
14851: for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++)
14852: {
14853: if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE)
14854: {
14855: break;
14856: }
14857: DvcSleepMilliSecond(1);
14858: }
14859: if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0)
14860: {
14861: ADV_ASSERT(0);
14862: }
14863: return;
14864: }
14865:
14866: /*
14867: * Write the EEPROM from 'cfg_buf'.
14868: */
14869: ASC_INITFUNC(
14870: STATIC void
14871: AdvSetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
14872: )
14873: {
14874: ushort *wbuf;
14875: ushort addr, chksum;
14876:
14877: wbuf = (ushort *) cfg_buf;
14878: chksum = 0;
14879:
14880: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
14881: AdvWaitEEPCmd(iop_base);
14882:
14883: /*
14884: * Write EEPROM from word 0 to word 15
14885: */
14886: for (addr = ASC_EEP_DVC_CFG_BEGIN;
14887: addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++)
14888: {
14889: chksum += *wbuf;
14890: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
14891: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14892: AdvWaitEEPCmd(iop_base);
14893: DvcSleepMilliSecond(ASC_EEP_DELAY_MS);
14894: }
14895:
14896: /*
14897: * Write EEPROM checksum at word 18
14898: */
14899: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
14900: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14901: AdvWaitEEPCmd(iop_base);
14902: wbuf++; /* skip over check_sum */
14903:
14904: /*
14905: * Write EEPROM OEM name at words 19 to 26
14906: */
14907: for (addr = ASC_EEP_DVC_CTL_BEGIN;
14908: addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++)
14909: {
14910: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
14911: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
14912: AdvWaitEEPCmd(iop_base);
14913: }
14914: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
14915: AdvWaitEEPCmd(iop_base);
14916: return;
14917: }
14918:
14919: /*
14920: * This function resets the chip and SCSI bus
14921: *
14922: * It is up to the caller to add a delay to let the bus settle after
14923: * calling this function.
14924: *
14925: * The SCSI_CFG0, SCSI_CFG1, and MEM_CFG registers are set-up in
14926: * AdvInitAsc3550Driver(). Here when doing a write to one of these
14927: * registers read first and then write.
14928: *
14929: * Note: A SCSI Bus Reset can not be done until after the EEPROM
14930: * configuration is read to determine whether SCSI Bus Resets
14931: * should be performed.
14932: */
14933: ASC_INITFUNC(
14934: STATIC void
14935: AdvResetChip(ADV_DVC_VAR *asc_dvc)
14936: )
14937: {
14938: AdvPortAddr iop_base;
14939: ushort word;
14940: uchar byte;
14941:
14942: iop_base = asc_dvc->iop_base;
14943:
14944: /*
14945: * Reset Chip.
14946: */
14947: AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
14948: DvcSleepMilliSecond(100);
14949: AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG);
14950:
14951: /*
14952: * Initialize Chip registers.
14953: *
14954: * Note: Don't remove the use of a temporary variable in the following
14955: * code, otherwise the Microsoft C compiler will turn the following lines
14956: * into a no-op.
14957: */
14958: byte = AdvReadByteRegister(iop_base, IOPB_MEM_CFG);
14959: byte |= RAM_SZ_8KB;
14960: AdvWriteByteRegister(iop_base, IOPB_MEM_CFG, byte);
14961:
14962: word = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
14963: word &= ~BIG_ENDIAN;
14964: AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, word);
14965:
14966: /*
14967: * Setting the START_CTL_EMFU 3:2 bits sets a FIFO threshold
14968: * of 128 bytes. This register is only accessible to the host.
14969: */
14970: AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
14971: START_CTL_EMFU | READ_CMD_MRM);
14972: }
14973:
14974: /* a_advlib.c */
14975: /*
14976: * Description:
14977: * Send a SCSI request to the ASC3550 chip
14978: *
14979: * If there is no SG list for the request, set 'sg_entry_cnt' to 0.
14980: *
14981: * If 'sg_real_addr' is non-zero on entry, AscGetSGList() will not be
14982: * called. It is assumed the caller has already initialized 'sg_real_addr'.
14983: *
14984: * Return:
14985: * ADV_SUCCESS(1) - the request is in the mailbox
14986: * ADV_BUSY(0) - total request count > 253, try later
14987: * ADV_ERROR(-1) - invalid scsi request Q
14988: */
14989: STATIC int
14990: AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc,
14991: ADV_SCSI_REQ_Q *scsiq)
14992: {
14993: if (scsiq == (ADV_SCSI_REQ_Q *) 0L)
14994: {
14995: /* 'scsiq' should never be NULL. */
14996: ADV_ASSERT(0);
14997: return ADV_ERROR;
14998: }
14999:
15000: return AdvSendScsiCmd(asc_dvc, scsiq);
15001: }
15002:
15003: /*
15004: * Reset SCSI Bus and purge all outstanding requests.
15005: *
15006: * Return Value:
15007: * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
15008: *
15009: * Note: Should always return ADV_TRUE.
15010: */
15011: STATIC int
15012: AdvResetSB(ADV_DVC_VAR *asc_dvc)
15013: {
15014: int status;
15015:
15016: status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET, 0L, 0);
15017:
15018: AdvResetSCSIBus(asc_dvc);
15019:
15020: return status;
15021: }
15022:
15023: /*
15024: * Reset SCSI Bus and delay.
15025: */
15026: STATIC void
15027: AdvResetSCSIBus(ADV_DVC_VAR *asc_dvc)
15028: {
15029: AdvPortAddr iop_base;
15030: ushort scsi_ctrl;
15031:
15032: iop_base = asc_dvc->iop_base;
15033:
15034: /*
15035: * The microcode currently sets the SCSI Bus Reset signal while
15036: * handling the AscSendIdleCmd() IDLE_CMD_SCSI_RESET command above.
15037: * But the SCSI Bus Reset Hold Time in the microcode is not deterministic
15038: * (it may in fact be for less than the SCSI Spec. minimum of 25 us).
15039: * Therefore on return the Adv Library sets the SCSI Bus Reset signal
15040: * for ASC_SCSI_RESET_HOLD_TIME_US, which is defined to be greater
15041: * than 25 us.
15042: */
15043: scsi_ctrl = AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL);
15044: AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
15045: scsi_ctrl | ADV_SCSI_CTRL_RSTOUT);
15046: DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US);
15047: AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
15048: scsi_ctrl & ~ADV_SCSI_CTRL_RSTOUT);
15049:
15050: DvcSleepMilliSecond((ulong) asc_dvc->scsi_reset_wait * 1000);
15051: }
15052:
15053:
15054: /*
15055: * Adv Library Interrupt Service Routine
15056: *
15057: * This function is called by a driver's interrupt service routine.
15058: * The function disables and re-enables interrupts.
15059: *
15060: * When a microcode idle command is completed, the ADV_DVC_VAR
15061: * 'idle_cmd_done' field is set to ADV_TRUE.
15062: *
15063: * Note: AdvISR() can be called when interrupts are disabled or even
15064: * when there is no hardware interrupt condition present. It will
15065: * always check for completed idle commands and microcode requests.
15066: * This is an important feature that shouldn't be changed because it
15067: * allows commands to be completed from polling mode loops.
15068: *
15069: * Return:
15070: * ADV_TRUE(1) - interrupt was pending
15071: * ADV_FALSE(0) - no interrupt was pending
15072: */
15073: STATIC int
15074: AdvISR(ADV_DVC_VAR *asc_dvc)
15075: {
15076: AdvPortAddr iop_base;
15077: uchar int_stat;
15078: ushort next_done_loc, target_bit;
15079: int completed_q;
1.1.1.2 root 15080: long flags;
1.1 root 15081: ADV_SCSI_REQ_Q *scsiq;
15082: ASC_REQ_SENSE *sense_data;
15083: int ret;
15084:
15085: flags = DvcEnterCritical();
15086: iop_base = asc_dvc->iop_base;
15087:
15088: if (AdvIsIntPending(iop_base))
15089: {
15090: ret = ADV_TRUE;
15091: } else
15092: {
15093: ret = ADV_FALSE;
15094: }
15095:
15096: /* Reading the register clears the interrupt. */
15097: int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
15098:
15099: if (int_stat & ADV_INTR_STATUS_INTRB)
15100: {
15101: asc_dvc->idle_cmd_done = ADV_TRUE;
15102: }
15103:
15104: /*
15105: * Notify the driver of a hardware detected SCSI Bus Reset.
15106: */
15107: if (int_stat & ADV_INTR_STATUS_INTRC)
15108: {
15109: if (asc_dvc->sbreset_callback != 0)
15110: {
15111: (*(ADV_SBRESET_CALLBACK) asc_dvc->sbreset_callback)(asc_dvc);
15112: }
15113: }
15114:
15115: /*
15116: * ASC_MC_HOST_NEXT_DONE (0x129) is actually the last completed RISC
15117: * Queue List request. Its forward pointer (RQL_FWD) points to the
15118: * current completed RISC Queue List request.
15119: */
15120: AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, next_done_loc);
15121: next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
15122: (next_done_loc * ASC_MC_RISC_Q_LIST_SIZE) + RQL_FWD;
15123:
15124: AdvReadByteLram(iop_base, next_done_loc, completed_q);
15125:
15126: /* Loop until all completed Q's are processed. */
15127: while (completed_q != ASC_MC_NULL_Q)
15128: {
15129: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, completed_q);
15130:
15131: next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
15132: (completed_q * ASC_MC_RISC_Q_LIST_SIZE);
15133:
15134: /*
15135: * Read the ADV_SCSI_REQ_Q virtual address pointer from
15136: * the RISC list entry. The microcode has changed the
15137: * ADV_SCSI_REQ_Q physical address to its virtual address.
15138: *
15139: * Refer to comments at the end of AdvSendScsiCmd() for
15140: * more information on the RISC list structure.
15141: */
15142: {
15143: ushort lsw, msw;
15144: AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR, lsw);
15145: AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR + 2, msw);
15146:
15147: scsiq = (ADV_SCSI_REQ_Q *) (((ulong) msw << 16) | lsw);
15148: }
15149: ADV_ASSERT(scsiq != NULL);
15150:
15151: target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
15152:
15153: /*
15154: * Clear request microcode control flag.
15155: */
15156: scsiq->cntl = 0;
15157:
15158: /*
15159: * Check Condition handling
15160: */
15161: if ((scsiq->done_status == QD_WITH_ERROR) &&
15162: (scsiq->scsi_status == SS_CHK_CONDITION) &&
15163: (sense_data = (ASC_REQ_SENSE *) scsiq->vsense_addr) != 0 &&
15164: (scsiq->orig_sense_len - scsiq->sense_len) >= ASC_MIN_SENSE_LEN)
15165: {
15166: /*
15167: * Command returned with a check condition and valid
15168: * sense data.
15169: */
15170: }
15171: /*
15172: * If the command that completed was a SCSI INQUIRY and
15173: * LUN 0 was sent the command, then process the INQUIRY
15174: * command information for the device.
15175: */
15176: else if (scsiq->done_status == QD_NO_ERROR &&
15177: scsiq->cdb[0] == SCSICMD_Inquiry &&
15178: scsiq->target_lun == 0)
15179: {
15180: AdvInquiryHandling(asc_dvc, scsiq);
15181: }
15182:
15183:
15184: /* Change the RISC Queue List state to free. */
15185: AdvWriteByteLram(iop_base, next_done_loc + RQL_STATE, ASC_MC_QS_FREE);
15186:
15187: /* Get the RISC Queue List forward pointer. */
15188: AdvReadByteLram(iop_base, next_done_loc + RQL_FWD, completed_q);
15189:
15190: /*
15191: * Notify the driver of the completed request by passing
15192: * the ADV_SCSI_REQ_Q pointer to its callback function.
15193: */
15194: ADV_ASSERT(asc_dvc->cur_host_qng > 0);
15195: asc_dvc->cur_host_qng--;
15196: scsiq->a_flag |= ADV_SCSIQ_DONE;
15197: (*(ADV_ISR_CALLBACK) asc_dvc->isr_callback)(asc_dvc, scsiq);
15198: /*
15199: * Note: After the driver callback function is called, 'scsiq'
15200: * can no longer be referenced.
15201: *
15202: * Fall through and continue processing other completed
15203: * requests...
15204: */
15205:
15206: /*
15207: * Disable interrupts again in case the driver inadvertently
15208: * enabled interrupts in its callback function.
15209: *
15210: * The DvcEnterCritical() return value is ignored, because
15211: * the 'flags' saved when AdvISR() was first entered will be
15212: * used to restore the interrupt flag on exit.
15213: */
15214: (void) DvcEnterCritical();
15215: }
15216: DvcLeaveCritical(flags);
15217: return ret;
15218: }
15219:
15220: /*
15221: * Send an idle command to the chip and wait for completion.
15222: *
15223: * Interrupts do not have to be enabled on entry.
15224: *
15225: * Return Values:
15226: * ADV_TRUE - command completed successfully
15227: * ADV_FALSE - command failed
15228: */
15229: STATIC int
15230: AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
15231: ushort idle_cmd,
15232: ulong idle_cmd_parameter,
15233: int flags)
15234: {
15235: int last_int_level;
15236: ulong i;
15237: AdvPortAddr iop_base;
15238: int ret;
15239:
15240: asc_dvc->idle_cmd_done = 0;
15241:
15242: last_int_level = DvcEnterCritical();
15243: iop_base = asc_dvc->iop_base;
15244:
15245: /*
15246: * Write the idle command value after the idle command parameter
15247: * has been written to avoid a race condition. If the order is not
15248: * followed, the microcode may process the idle command before the
15249: * parameters have been written to LRAM.
15250: */
15251: AdvWriteDWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, idle_cmd_parameter);
15252: AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
15253: DvcLeaveCritical(last_int_level);
15254:
15255: /*
15256: * If the 'flags' argument contains the ADV_NOWAIT flag, then
15257: * return with success.
15258: */
15259: if (flags & ADV_NOWAIT)
15260: {
15261: return ADV_TRUE;
15262: }
15263:
15264: for (i = 0; i < SCSI_WAIT_10_SEC * SCSI_MS_PER_SEC; i++)
15265: {
15266: /*
15267: * 'idle_cmd_done' is set by AdvISR().
15268: */
15269: if (asc_dvc->idle_cmd_done)
15270: {
15271: break;
15272: }
15273: DvcSleepMilliSecond(1);
15274:
15275: /*
15276: * If interrupts were disabled on entry to AdvSendIdleCmd(),
15277: * then they will still be disabled here. Call AdvISR() to
15278: * check for the idle command completion.
15279: */
15280: (void) AdvISR(asc_dvc);
15281: }
15282:
15283: last_int_level = DvcEnterCritical();
15284:
15285: if (asc_dvc->idle_cmd_done == ADV_FALSE)
15286: {
15287: ADV_ASSERT(0); /* The idle command should never timeout. */
15288: return ADV_FALSE;
15289: } else
15290: {
15291: AdvReadWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, ret);
15292: return ret;
15293: }
15294: }
15295:
15296: /*
15297: * Send the SCSI request block to the adapter
15298: *
15299: * Each of the 255 Adv Library/Microcode RISC Lists or mailboxes has the
15300: * following structure:
15301: *
15302: * 0: RQL_FWD - RISC list forward pointer (1 byte)
15303: * 1: RQL_BWD - RISC list backward pointer (1 byte)
15304: * 2: RQL_STATE - RISC list state byte - free, ready, done, aborted (1 byte)
15305: * 3: RQL_TID - request target id (1 byte)
15306: * 4: RQL_PHYADDR - ADV_SCSI_REQ_Q physical pointer (4 bytes)
15307: *
15308: * Return:
15309: * ADV_SUCCESS(1) - the request is in the mailbox
15310: * ADV_BUSY(0) - total request count > 253, try later
15311: */
15312: STATIC int
15313: AdvSendScsiCmd(
15314: ADV_DVC_VAR *asc_dvc,
15315: ADV_SCSI_REQ_Q *scsiq)
15316: {
15317: ushort next_ready_loc;
15318: uchar next_ready_loc_fwd;
15319: int last_int_level;
15320: AdvPortAddr iop_base;
15321: long req_size;
15322: ulong q_phy_addr;
15323:
15324: /*
15325: * The ADV_SCSI_REQ_Q 'target_id' field should never be equal
15326: * to the host adapter ID or exceed ADV_MAX_TID.
15327: */
15328: if (scsiq->target_id == asc_dvc->chip_scsi_id ||
15329: scsiq->target_id > ADV_MAX_TID)
15330: {
15331: scsiq->host_status = QHSTA_M_INVALID_DEVICE;
15332: scsiq->done_status = QD_WITH_ERROR;
15333: return ADV_ERROR;
15334: }
15335:
15336: iop_base = asc_dvc->iop_base;
15337:
15338: last_int_level = DvcEnterCritical();
15339:
15340: if (asc_dvc->cur_host_qng >= asc_dvc->max_host_qng)
15341: {
15342: DvcLeaveCritical(last_int_level);
15343: return ADV_BUSY;
15344: } else
15345: {
15346: ADV_ASSERT(asc_dvc->cur_host_qng < ASC_MC_RISC_Q_TOTAL_CNT);
15347: asc_dvc->cur_host_qng++;
15348: }
15349:
15350: /*
15351: * Clear the ADV_SCSI_REQ_Q done flag.
15352: */
15353: scsiq->a_flag &= ~ADV_SCSIQ_DONE;
15354:
15355: /*
15356: * Save the original sense buffer length.
15357: *
15358: * After the request completes 'sense_len' will be set to the residual
15359: * byte count of the Auto-Request Sense if a command returns CHECK
15360: * CONDITION and the Sense Data is valid indicated by 'host_status' not
15361: * being set to QHSTA_M_AUTO_REQ_SENSE_FAIL. To determine the valid
15362: * Sense Data Length subtract 'sense_len' from 'orig_sense_len'.
15363: */
15364: scsiq->orig_sense_len = scsiq->sense_len;
15365:
15366: AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc);
15367: next_ready_loc = ASC_MC_RISC_Q_LIST_BASE +
15368: (next_ready_loc * ASC_MC_RISC_Q_LIST_SIZE);
15369:
15370: /*
15371: * Write the physical address of the Q to the mailbox.
15372: * We need to skip the first four bytes, because the microcode
15373: * uses them internally for linking Q's together.
15374: */
15375: req_size = sizeof(ADV_SCSI_REQ_Q);
15376: q_phy_addr = DvcGetPhyAddr(asc_dvc, scsiq,
15377: (uchar *) scsiq, &req_size,
15378: ADV_IS_SCSIQ_FLAG);
15379: ADV_ASSERT(ADV_DWALIGN(q_phy_addr) == q_phy_addr);
15380: ADV_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
15381:
15382: scsiq->scsiq_ptr = (ADV_SCSI_REQ_Q *) scsiq;
15383:
15384: /*
15385: * The RISC list structure, which 'next_ready_loc' is a pointer
15386: * to in microcode LRAM, has the format detailed in the comment
15387: * header for this function.
15388: *
15389: * Write the ADV_SCSI_REQ_Q physical pointer to 'next_ready_loc' request.
15390: */
15391: AdvWriteDWordLram(iop_base, next_ready_loc + RQL_PHYADDR, q_phy_addr);
15392:
15393: /* Write target_id to 'next_ready_loc' request. */
15394: AdvWriteByteLram(iop_base, next_ready_loc + RQL_TID, scsiq->target_id);
15395:
15396: /*
15397: * Set the ASC_MC_HOST_NEXT_READY (0x128) microcode variable to
15398: * the 'next_ready_loc' request forward pointer.
15399: *
15400: * Do this *before* changing the 'next_ready_loc' queue to QS_READY.
15401: * After the state is changed to QS_READY 'RQL_FWD' will be changed
15402: * by the microcode.
15403: *
15404: * NOTE: The temporary variable 'next_ready_loc_fwd' is required to
15405: * prevent some compilers from optimizing out 'AdvReadByteLram()' if
15406: * it were used as the 3rd argument to 'AdvWriteByteLram()'.
15407: */
15408: AdvReadByteLram(iop_base, next_ready_loc + RQL_FWD, next_ready_loc_fwd);
15409: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc_fwd);
15410:
15411: /*
15412: * Change the state of 'next_ready_loc' request from QS_FREE to
15413: * QS_READY which will cause the microcode to pick it up and
15414: * execute it.
15415: *
15416: * Can't reference 'next_ready_loc' after changing the request
15417: * state to QS_READY. The microcode now owns the request.
15418: */
15419: AdvWriteByteLram(iop_base, next_ready_loc + RQL_STATE, ASC_MC_QS_READY);
15420:
15421: DvcLeaveCritical(last_int_level);
15422: return ADV_SUCCESS;
15423: }
15424:
15425: /*
15426: * Inquiry Information Byte 7 Handling
15427: *
15428: * Handle SCSI Inquiry Command information for a device by setting
15429: * microcode operating variables that affect WDTR, SDTR, and Tag
15430: * Queuing.
15431: */
15432: STATIC void
15433: AdvInquiryHandling(
15434: ADV_DVC_VAR *asc_dvc,
15435: ADV_SCSI_REQ_Q *scsiq)
15436: {
15437: AdvPortAddr iop_base;
15438: uchar tid;
15439: ASC_SCSI_INQUIRY *inq;
15440: ushort tidmask;
15441: ushort cfg_word;
15442:
15443: /*
15444: * AdvInquiryHandling() requires up to INQUIRY information Byte 7
15445: * to be available.
15446: *
15447: * If less than 8 bytes of INQUIRY information were requested or less
15448: * than 8 bytes were transferred, then return. cdb[4] is the request
15449: * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
15450: * microcode to the transfer residual count.
15451: */
15452: if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8)
15453: {
15454: return;
15455: }
15456:
15457: iop_base = asc_dvc->iop_base;
15458: tid = scsiq->target_id;
15459: inq = (ASC_SCSI_INQUIRY *) scsiq->vdata_addr;
15460:
15461: /*
15462: * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
15463: */
15464: if (inq->byte3.rsp_data_fmt < 2 && inq->byte2.ansi_apr_ver < 2)
15465: {
15466: return;
15467: } else
15468: {
15469: /*
15470: * INQUIRY Byte 7 Handling
15471: *
15472: * Use a device's INQUIRY byte 7 to determine whether it
15473: * supports WDTR, SDTR, and Tag Queuing. If the feature
15474: * is enabled in the EEPROM and the device supports the
15475: * feature, then enable it in the microcode.
15476: */
15477:
15478: tidmask = ADV_TID_TO_TIDMASK(tid);
15479:
15480: /*
15481: * Wide Transfers
15482: *
15483: * If the EEPROM enabled WDTR for the device and the device
15484: * supports wide bus (16 bit) transfers, then turn on the
15485: * device's 'wdtr_able' bit and write the new value to the
15486: * microcode.
15487: */
15488: if ((asc_dvc->wdtr_able & tidmask) && inq->byte7.WBus16)
15489: {
15490: AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
15491: if ((cfg_word & tidmask) == 0)
15492: {
15493: cfg_word |= tidmask;
15494: AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
15495:
15496: /*
15497: * Clear the microcode "WDTR negotiation" done indicator
15498: * for the target to cause it to negotiate with the new
15499: * setting set above.
15500: */
15501: AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
15502: cfg_word &= ~tidmask;
15503: AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
15504: }
15505: }
15506:
15507: /*
15508: * Synchronous Transfers
15509: *
15510: * If the EEPROM enabled SDTR for the device and the device
15511: * supports synchronous transfers, then turn on the device's
15512: * 'sdtr_able' bit. Write the new value to the microcode.
15513: */
15514: if ((asc_dvc->sdtr_able & tidmask) && inq->byte7.Sync)
15515: {
15516: AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
15517: if ((cfg_word & tidmask) == 0)
15518: {
15519: cfg_word |= tidmask;
15520: AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
15521:
15522: /*
15523: * Clear the microcode "SDTR negotiation" done indicator
15524: * for the target to cause it to negotiate with the new
15525: * setting set above.
15526: */
15527: AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
15528: cfg_word &= ~tidmask;
15529: AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
15530: }
15531: }
15532:
15533: /*
15534: * If the EEPROM enabled Tag Queuing for device and the
15535: * device supports Tag Queuing, then turn on the device's
15536: * 'tagqng_enable' bit in the microcode and set the microcode
15537: * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
15538: * value.
15539: *
15540: * Tag Queuing is disabled for the BIOS which runs in polled
15541: * mode and would see no benefit from Tag Queuing. Also by
15542: * disabling Tag Queuing in the BIOS devices with Tag Queuing
15543: * bugs will at least work with the BIOS.
15544: */
15545: if ((asc_dvc->tagqng_able & tidmask) && inq->byte7.CmdQue)
15546: {
15547: AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
15548: cfg_word |= tidmask;
15549: AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
15550: AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
15551: asc_dvc->max_dvc_qng);
15552: }
15553: }
15554: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.