|
|
1.1 root 1: /* $Id: advansys.c,v 1.1.1.1 1997/02/25 21:27:45 thomas Exp $ */
2: /*
3: * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
4: *
5: * Copyright (c) 1995-1996 Advanced System Products, Inc.
6: * All Rights Reserved.
7: *
8: * This driver may be modified and freely distributed provided that
9: * the above copyright message and this comment are included in the
10: * distribution. The latest version of this driver is available at
11: * the AdvanSys FTP and BBS sites listed below.
12: *
13: * Please send questions, comments, bug reports to:
14: * [email protected] (Bob Frey)
15: */
16:
17: /* The driver has been tested with Linux 1.2.1 and 1.3.57 kernels. */
18: #define ASC_VERSION "1.2" /* AdvanSys Driver Version */
19:
20: /*
21:
22: Documentation for the AdvanSys Driver
23:
24: A. Adapters Supported by this Driver
25: B. Linux 1.2.X - Directions for Adding the AdvanSys Driver
26: C. Linux 1.3.X - Directions for Adding the AdvanSys Driver
27: D. Source Comments
28: E. Driver Compile Time Options and Debugging
29: F. Driver LILO Option
30: G. Release History
31: H. Known Problems or Issues
32: I. Credits
33: J. AdvanSys Contact Information
34:
35:
36: A. Adapters Supported by this Driver
37:
38: AdvanSys (Advanced System Products, Inc.) manufactures the following
39: Bus-Mastering SCSI-2 Host Adapters for the ISA, EISA, VL, and PCI
40: buses. This Linux driver supports all of these adapters.
41:
42: The CDB counts below indicate the number of SCSI CDB (Command
43: Descriptor Block) requests that can be stored in the RISC chip
44: cache and board LRAM. The driver detect routine will display the
45: number of CDBs available for each adapter detected. This value
46: can be lowered in the BIOS by changing the 'Host Queue Size'
47: adapter setting.
48:
49: Connectivity Products:
50: ABP920 - Bus-Master PCI 16 CDB
51: ABP930 - Bus-Master PCI 16 CDB
52: ABP5140 - Bus-Master PnP ISA 16 CDB
53:
54: Single Channel Products:
55: ABP542 - Bus-Master ISA 240 CDB
56: ABP5150 - Bus-Master ISA 240 CDB *
57: ABP742 - Bus-Master EISA 240 CDB
58: ABP842 - Bus-Master VL 240 CDB
59: ABP940 - Bus-Master PCI 240 CDB
60:
61: Dual Channel Products:
62: ABP950 - Dual Channel Bus-Master PCI 240 CDB Per Channel
63: ABP852 - Dual Channel Bus-Master VL 240 CDB Per Channel
64: ABP752 - Dual Channel Bus-Master EISA 240 CDB Per Channel
65:
66: * This board is shipped by HP with the 4020i CD-R drive. It has
67: no BIOS so it cannot control a boot device, but it can control
68: any secondary devices.
69:
70: B. Linux 1.2.X - Directions for Adding the AdvanSys Driver
71:
72: There are two source files: advansys.h and advansys.c. Copy
73: both of these files to the directory /usr/src/linux/drivers/scsi.
74:
75: 1. Add the following line to /usr/src/linux/arch/i386/config.in
76: after "comment 'SCSI low-level drivers'":
77:
78: bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
79:
80: 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
81: after "#include "hosts.h"":
82:
83: #ifdef CONFIG_SCSI_ADVANSYS
84: #include "advansys.h"
85: #endif
86:
87: and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
88:
89: #ifdef CONFIG_SCSI_ADVANSYS
90: ADVANSYS,
91: #endif
92:
93: 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
94:
95: ifdef CONFIG_SCSI_ADVANSYS
96: SCSI_SRCS := $(SCSI_SRCS) advansys.c
97: SCSI_OBJS := $(SCSI_OBJS) advansys.o
98: else
99: SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
100: endif
101:
102: 4. (Optional) If you would like to enable the LILO command line
103: and /etc/lilo.conf 'advansys' option, make the following changes.
104: This option can be used to disable I/O port scanning or to limit
105: I/O port scanning to specific addresses. Refer to the 'Driver
106: LILO Option' section below. Add the following lines to
107: /usr/src/linux/init/main.c in the prototype section:
108:
109: extern void advansys_setup(char *str, int *ints);
110:
111: and add the following lines to the bootsetups[] array.
112:
113: #ifdef CONFIG_SCSI_ADVANSYS
114: { "advansys=", advansys_setup },
115: #endif
116:
117: 5. If you have the HP 4020i CD-R driver and Linux 1.2.X you should
118: add a fix to the CD-ROM target driver. This fix will allow
119: you to mount CDs with the iso9660 file system. Linux 1.3.X
120: already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
121: and function get_sectorsize() after the line:
122:
123: if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
124:
125: add the following line:
126:
127: if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
128:
129: 6. In the directory /usr/src/linux run 'make config' to configure
130: the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
131: make the kernel. If the AdvanSys driver is not configured, then
132: a loadable module can be built by running 'make modules' and
133: 'make modules_install'. Use 'insmod' and 'rmmod' to install
134: and remove advansys.o.
135:
136: C. Linux 1.3.X - Directions for Adding the AdvanSys Driver
137:
138: There are two source files: advansys.h and advansys.c. Copy
139: both of these files to the directory /usr/src/linux/drivers/scsi.
140:
141: 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
142: after "comment 'SCSI low-level drivers'":
143:
144: dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
145:
146: 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
147: after "#include "hosts.h"":
148:
149: #ifdef CONFIG_SCSI_ADVANSYS
150: #include "advansys.h"
151: #endif
152:
153: and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
154:
155: #ifdef CONFIG_SCSI_ADVANSYS
156: ADVANSYS,
157: #endif
158:
159: 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
160:
161: ifeq ($(CONFIG_SCSI_ADVANSYS),y)
162: L_OBJS += advansys.o
163: else
164: ifeq ($(CONFIG_SCSI_ADVANSYS),m)
165: M_OBJS += advansys.o
166: endif
167: endif
168:
169: 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
170: in the enum scsi_directory_inos array:
171:
172: PROC_SCSI_ADVANSYS,
173:
174: 5. (Optional) If you would like to enable the LILO command line
175: and /etc/lilo.conf 'advansys' option, make the following changes.
176: This option can be used to disable I/O port scanning or to limit
177: I/O port scanning to specific addresses. Refer to the 'Driver
178: LILO Option' section below. Add the following lines to
179: /usr/src/linux/init/main.c in the prototype section:
180:
181: extern void advansys_setup(char *str, int *ints);
182:
183: and add the following lines to the bootsetups[] array.
184:
185: #ifdef CONFIG_SCSI_ADVANSYS
186: { "advansys=", advansys_setup },
187: #endif
188:
189: 6. In the directory /usr/src/linux run 'make config' to configure
190: the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
191: make the kernel. If the AdvanSys driver is not configured, then
192: a loadable module can be built by running 'make modules' and
193: 'make modules_install'. Use 'insmod' and 'rmmod' to install
194: and remove advansys.o.
195:
196: D. Source Comments
197:
198: 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
199:
200: 2. This driver should be maintained in multiple files. But to make
201: it easier to include with Linux and to follow Linux conventions,
202: the whole driver is maintained in the source files advansys.h and
203: advansys.c. In this file logical sections of the driver begin with
204: a comment that contains '---'. The following are the logical sections
205: of the driver below.
206:
207: --- Linux Version
208: --- Linux Include Files
209: --- Driver Options
210: --- Asc Library Constants and Macros
211: --- Debugging Header
212: --- Driver Constants
213: --- Driver Macros
214: --- Driver Structures
215: --- Driver Data
216: --- Driver Function Prototypes
217: --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
218: --- Loadable Driver Support
219: --- Miscellaneous Driver Functions
220: --- Functions Required by the Asc Library
221: --- Tracing and Debugging Functions
222: --- Asc Library Functions
223:
224: 3. The string 'XXX' is used to flag code that needs to be re-written
225: or that contains a problem that needs to be addressed.
226:
227: 4. I have stripped comments from and reformatted the source for the
228: Asc Library which is included in this file. I haven't done this
229: to obfuscate the code. Actually I have done this to deobfuscate
230: the code. The Asc Library source can be found under the following
231: headings.
232:
233: --- Asc Library Constants and Macros
234: --- Asc Library Functions
235:
236: E. Driver Compile Time Options and Debugging
237:
238: In this source file the following constants can be defined. They are
239: defined in the source below. Both of these options are enabled by
240: default.
241:
242: 1. ADVANSYS_DEBUG - enable for debugging and assertions
243:
244: The amount of debugging output can be controlled with the global
245: variable 'asc_dbglvl'. The higher the number the more output. By
246: default the debug level is 0.
247:
248: If the driver is loaded at boot time and the LILO Driver Option
249: is included in the system, the debug level can be changed by
250: specifying a 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. The
251: first three hex digits of the pseudo I/O Port must be set to
252: 'deb' and the fourth hex digit specifies the debug level: 0 - F.
253: The following command line will look for an adapter at 0x330
254: and set the debug level to 2.
255:
256: linux advansys=0x330,0x0,0x0,0x0,0xdeb2
257:
258: If the driver is built as a loadable module this variable can be
259: defined when the driver is loaded. The following insmod command
260: will set the debug level to one.
261:
262: insmod advansys.o asc_dbglvl=1
263:
264:
265: Debugging Message Levels:
266: 0: Errors Only
267: 1: High-Level Tracing
268: 2-N: Verbose Tracing
269:
270: I don't know the approved way for turning on printk()s to the
271: console. Here's a program I use to do this. Debug output is
272: logged in /var/adm/messages.
273:
274: main()
275: {
276: syscall(103, 7, 0, 0);
277: }
278:
279: I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
280: prevents most level 1 debug messages from being lost.
281:
282: 2. ADVANSYS_STATS - enable statistics and tracing
283:
284: For Linux 1.2.X if ADVANSYS_STATS_1_2_PRINT is defined every
285: 10,000 I/O operations the driver will print statistics to the
286: console. This value can be changed by modifying the constant
287: used in advansys_queuecommand(). ADVANSYS_STATS_1_2_PRINT is
288: off by default.
289:
290: For Linux 1.3.X statistics can be accessed by reading the
291: /proc/scsi/advansys/[0-9] files.
292:
293: Note: these statistics are currently maintained on a global driver
294: basis and not per board.
295:
296: F. Driver LILO Option
297:
298: If init/main.c is modified as described in the 'Directions for Adding
299: the AdvanSys Driver to Linux' section (B.4.) above, the driver will
300: recognize the 'advansys' LILO command line and /etc/lilo.conf option.
301: This option can be used to either disable I/O port scanning or to limit
302: scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
303: PCI boards will still be searched for and detected. This option only
304: affects searching for ISA and VL boards.
305:
306: Examples:
307: 1. Eliminate I/O port scanning:
308: boot: linux advansys=
309: or
310: boot: linux advansys=0x0
311: 2. Limit I/O port scanning to one I/O port:
312: boot: linux advansys=0x110
313: 3. Limit I/O port scanning to four I/O ports:
314: boot: linux advansys=0x110,0x210,0x230,0x330
315:
316: For a loadable module the same effect can be achieved by setting
317: the 'asc_iopflag' variable and 'asc_ioport' array when loading
318: the driver, e.g.
319:
320: insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
321:
322: If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 1)
323: I/O Port may be added to specify the driver debug level. Refer to
324: the 'Driver Compile Time Options and Debugging' section above for
325: more information.
326:
327: G. Release History
328:
329: 12/23/95 BETA-1.0:
330: First Release
331:
332: 12/28/95 BETA-1.1:
333: 1. Prevent advansys_detect() from being called twice.
334: 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
335:
336: 1/12/96 1.2:
337: 1. Prevent re-entrancy in the interrupt handler which
338: resulted in the driver hanging Linux.
339: 2. Fix problem that prevented ABP-940 cards from being
340: recognized on some PCI motherboards.
341: 3. Add support for the ABP-5140 PnP ISA card.
342: 4. Fix check condition return status.
343: 5. Add conditionally compiled code for Linux 1.3.X.
344:
345: H. Known Problems or Issues
346:
347: 1. The setting for 'cmd_per_lun' needs to be changed. It is currently
348: less then what the AdvanSys boards can queue. Because the target and
349: mid-level Linux drivers base memory allocation on 'cmd_per_lun' (as
350: well as 'sg_tablesize') memory use gets out of hand with a large
351: 'cmd_per_lun'. 'cmd_per_lun' should be per device instead of per
352: adapter. When the driver is compiled as a loadable module both
353: 'cmd_per_lun' and 'sg_tablesize' are tuned down to try to prevent
354: memory allocation errors.
355:
356: 2. For the first scsi command sent to a device the driver increases
357: the timeout value. This gives the driver more time to perform
358: its own initialization for the board and each device. The timeout
359: value is only changed on the first scsi command for each device
360: and never thereafter.
361:
362: I. Credits
363:
364: Nathan Hartwell ([email protected]) provided the directions and
365: and basis for the Linux 1.3.X changes which were included in the
366: 1.2 release.
367:
368: J. AdvanSys Contact Information
369:
370: Mail: Advanced System Products, Inc.
371: 1150 Ringwood Court
372: San Jose, CA 95131 USA
373: Operator: 1-408-383-9400
374: FAX: 1-408-383-9612
375: Tech Support: 1-800-525-7440
376: BBS: 1-408-383-9540 (9600,N,8,1)
377: Interactive FAX: 1-408-383-9753
378: Customer Direct Sales: 1-800-883-1099
379: Tech Support E-Mail: [email protected]
380: Linux Support E-Mail: [email protected]
381: FTP Site: ftp.advansys.com (login: anonymous)
382: Web Site: http://www.advansys.com
383:
384: */
385:
386:
387: /*
388: * --- Linux Version
389: */
390:
391: /*
392: * The driver can be used in Linux 1.2.X or 1.3.X.
393: */
394: #if !defined(LINUX_1_2) && !defined(LINUX_1_3)
395: #ifndef LINUX_VERSION_CODE
396: #include <linux/version.h>
397: #endif /* LINUX_VERSION_CODE */
398: #if LINUX_VERSION_CODE > 65536 + 3 * 256
399: #define LINUX_1_3
400: #else /* LINUX_VERSION_CODE */
401: #define LINUX_1_2
402: #endif /* LINUX_VERSION_CODE */
403: #endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */
404:
405:
406: /*
407: * --- Linux Include Files
408: */
409:
410: #ifdef MODULE
411: #ifdef LINUX_1_3
412: #include <linux/autoconf.h>
413: #endif /* LINUX_1_3 */
414: #include <linux/module.h>
415: #endif /* MODULE */
416: #include <linux/string.h>
417: #include <linux/sched.h>
418: #include <linux/kernel.h>
419: #include <linux/head.h>
420: #include <linux/types.h>
421: #include <linux/ioport.h>
422: #include <linux/delay.h>
423: #include <linux/malloc.h>
424: #include <linux/config.h>
425: #ifdef LINUX_1_3
426: #include <linux/proc_fs.h>
427: #endif /* LINUX_1_3 */
428: #include <asm/io.h>
429: #include <asm/system.h>
430: #include <asm/dma.h>
431: #ifdef LINUX_1_2
432: #include "../block/blk.h"
433: #else /* LINUX_1_3 */
434: #include <linux/blk.h>
435: #include <linux/stat.h>
436: #endif /* LINUX_1_3 */
437: #include "scsi.h"
438: #include "hosts.h"
439: #include "sd.h"
440: #include "advansys.h"
441:
442:
443: /*
444: * --- Driver Options
445: */
446: #define ADVANSYS_DEBUG /* Enable for debugging and assertions. */
447: #define ADVANSYS_STATS /* Enable for statistics and tracing. */
448: #ifdef LINUX_1_2
449: #undef ADVANSYS_STATS_1_2_PRINT /* Enable to print statistics to console. */
450: #endif /* LINUX_1_2 */
451:
452:
453: /*
454: * --- Asc Library Constants and Macros
455: */
456:
457: #define ASC_LIB_VERSION_MAJOR 1
458: #define ASC_LIB_VERSION_MINOR 16
459: #define ASC_LIB_SERIAL_NUMBER 53
460:
461: typedef unsigned char uchar;
462: typedef unsigned char BYTE;
463: typedef unsigned short WORD;
464: typedef unsigned long DWORD;
465:
466: typedef int BOOL;
467:
468: #ifndef NULL
469: #define NULL (0)
470: #endif
471:
472: #ifndef TRUE
473: #define TRUE (1)
474: #endif
475:
476: #ifndef FALSE
477: #define FALSE (0)
478: #endif
479:
480: #define REG register
481:
482: #define rchar REG char
483: #define rshort REG short
484: #define rint REG int
485: #define rlong REG long
486:
487: #define ruchar REG uchar
488: #define rushort REG ushort
489: #define ruint REG uint
490: #define rulong REG ulong
491:
492: #define NULLPTR ( void *)0
493: #define FNULLPTR ( void dosfar *)0UL
494: #define EOF (-1)
495: #define EOS '\0'
496: #define ERR (-1)
497: #define UB_ERR (uchar)(0xFF)
498: #define UW_ERR (uint)(0xFFFF)
499: #define UL_ERR (ulong)(0xFFFFFFFFUL)
500:
501: #define iseven_word( val ) ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 )
502: #define isodd_word( val ) ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 )
503: #define toeven_word( val ) ( ( ( uint )val ) & ( uint )0xFFFE )
504:
505: #define biton( val, bits ) ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 )
506: #define bitoff( val, bits ) ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 )
507: #define lbiton( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 )
508: #define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 )
509:
510: #define absh( val ) ( ( val ) < 0 ? -( val ) : ( val ) )
511:
512: #define swapbyte( ch ) ( ( ( (ch) << 4 ) | ( (ch) >> 4 ) ) )
513:
514: #ifndef GBYTE
515: #define GBYTE (0x40000000UL)
516: #endif
517:
518: #ifndef MBYTE
519: #define MBYTE (0x100000UL)
520: #endif
521:
522: #ifndef KBYTE
523: #define KBYTE (0x400)
524: #endif
525:
526: #define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) )
527: #define LO_BYTE(x) ( *( ( BYTE *)&x ) )
528:
529: #define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) )
530: #define LO_WORD(x) ( *( ( WORD *)&x ) )
531:
532: #ifndef MAKEWORD
533: #define MAKEWORD(lo, hi) ((WORD) (((WORD) lo) | ((WORD) hi << 8)))
534: #endif
535:
536: #ifndef MAKELONG
537: #define MAKELONG(lo, hi) ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16)))
538: #endif
539:
540: #define SwapWords(dWord) ((DWORD) ((dWord >> 16) | (dWord << 16)))
541: #define SwapBytes(word) ((WORD) ((word >> 8) | (word << 8)))
542:
543: #define BigToLittle(dWord) \
544: ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
545: #define LittleToBig(dWord) BigToLittle(dWord)
546:
547: #define Lptr
548: #define dosfar
549: #define far
550: #define PortAddr unsigned short
551: #define Ptr2Func ulong
552:
553: #define inp(port) inb(port)
554: #define inpw(port) inw(port)
555: #define outp(port, byte) outb((byte), (port))
556: #define outpw(port, word) outw((word), (port))
557:
558: #define ASC_MAX_SG_QUEUE 5
559: #define ASC_MAX_SG_LIST (1 + ((ASC_SG_LIST_PER_Q) * (ASC_MAX_SG_QUEUE)))
560:
561: #define CC_INIT_INQ_DISPLAY FALSE
562:
563: #define CC_CLEAR_LRAM_SRB_PTR FALSE
564: #define CC_VERIFY_LRAM_COPY FALSE
565:
566: #define CC_DEBUG_SG_LIST FALSE
567: #define CC_FAST_STRING_IO FALSE
568:
569: #define CC_WRITE_IO_COUNT FALSE
570: #define CC_CLEAR_DMA_REMAIN FALSE
571:
572: #define CC_DISABLE_PCI_PARITY_INT TRUE
573:
574: #define CC_LINK_BUSY_Q FALSE
575:
576: #define CC_TARGET_MODE FALSE
577:
578: #define CC_SCAM FALSE
579:
580: #define CC_LITTLE_ENDIAN_HOST TRUE
581:
582: #ifndef CC_TEST_LRAM_ENDIAN
583:
584: #if CC_LITTLE_ENDIAN_HOST
585: #define CC_TEST_LRAM_ENDIAN FALSE
586: #else
587: #define CC_TEST_LRAM_ENDIAN TRUE
588: #endif
589:
590: #endif
591:
592: #define CC_STRUCT_ALIGNED TRUE
593:
594: #define CC_MEMORY_MAPPED_IO FALSE
595:
596: #ifndef CC_TARGET_MODE
597: #define CC_TARGET_MODE FALSE
598: #endif
599:
600: #ifndef CC_STRUCT_ALIGNED
601: #define CC_STRUCT_ALIGNED FALSE
602: #endif
603:
604: #ifndef CC_LITTLE_ENDIAN_HOST
605: #define CC_LITTLE_ENDIAN_HOST TRUE
606: #endif
607:
608: #if !CC_LITTLE_ENDIAN_HOST
609:
610: #ifndef CC_TEST_LRAM_ENDIAN
611: #define CC_TEST_LRAM_ENDIAN TRUE
612: #endif
613:
614: #endif
615:
616: #ifndef CC_MEMORY_MAPPED_IO
617: #define CC_MEMORY_MAPPED_IO FALSE
618: #endif
619:
620: #ifndef CC_WRITE_IO_COUNT
621: #define CC_WRITE_IO_COUNT FALSE
622: #endif
623:
624: #ifndef CC_CLEAR_DMA_REMAIN
625: #define CC_CLEAR_DMA_REMAIN FALSE
626: #endif
627:
628: #define ASC_CS_TYPE unsigned short
629:
630: #ifndef asc_ptr_type
631: #define asc_ptr_type
632: #endif
633:
634: #ifndef CC_SCAM
635: #define CC_SCAM FALSE
636: #endif
637:
638: #ifndef ASC_GET_PTR2FUNC
639: #define ASC_GET_PTR2FUNC( fun ) ( Ptr2Func )( fun )
640: #endif
641:
642: #define FLIP_BYTE_NIBBLE( x ) ( ((x<<4)& 0xFF) | (x>>4) )
643:
644: #define ASC_IS_ISA (0x0001)
645: #define ASC_IS_ISAPNP (0x0081)
646: #define ASC_IS_EISA (0x0002)
647: #define ASC_IS_PCI (0x0004)
648: #define ASC_IS_PCMCIA (0x0008)
649: #define ASC_IS_PNP (0x0010)
650: #define ASC_IS_MCA (0x0020)
651: #define ASC_IS_VL (0x0040)
652:
653: #define ASC_ISA_PNP_PORT_ADDR (0x279)
654: #define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
655:
656: #define ASC_IS_WIDESCSI_16 (0x0100)
657: #define ASC_IS_WIDESCSI_32 (0x0200)
658:
659: #define ASC_IS_BIG_ENDIAN (0x8000)
660:
661: #define ASC_CHIP_MIN_VER_VL (0x01)
662: #define ASC_CHIP_MAX_VER_VL (0x07)
663:
664: #define ASC_CHIP_MIN_VER_PCI (0x09)
665: #define ASC_CHIP_MAX_VER_PCI (0x0F)
666: #define ASC_CHIP_VER_PCI_BIT (0x08)
667:
668: #define ASC_CHIP_MIN_VER_ISA (0x11)
669: #define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
670: #define ASC_CHIP_MAX_VER_ISA (0x27)
671: #define ASC_CHIP_VER_ISA_BIT (0x30)
672: #define ASC_CHIP_VER_ISAPNP_BIT (0x20)
673:
674: #define ASC_CHIP_VER_ASYN_BUG (0x21)
675:
676: #define ASC_CHIP_MIN_VER_EISA (0x41)
677: #define ASC_CHIP_MAX_VER_EISA (0x47)
678: #define ASC_CHIP_VER_EISA_BIT (0x40)
679:
680: #define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
681: #define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
682:
683: #define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
684: #define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
685:
686: #define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
687: #define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
688:
689: #define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
690: #define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
691:
692: #if !CC_STRUCT_ALIGNED
693:
694: #define DvcGetQinfo( iop_base, s_addr, outbuf, words) \
695: AscMemWordCopyFromLram( iop_base, s_addr, outbuf, words)
696:
697: #define DvcPutScsiQ( iop_base, s_addr, outbuf, words) \
698: AscMemWordCopyToLram( iop_base, s_addr, outbuf, words)
699:
700: #endif
701:
702: #define ASC_SCSI_ID_BITS 3
703: #define ASC_SCSI_TIX_TYPE uchar
704: #define ASC_ALL_DEVICE_BIT_SET 0xFF
705:
706: #ifdef ASC_WIDESCSI_16
707:
708: #undef ASC_SCSI_ID_BITS
709: #define ASC_SCSI_ID_BITS 4
710: #define ASC_ALL_DEVICE_BIT_SET 0xFFFF
711:
712: #endif
713:
714: #ifdef ASC_WIDESCSI_32
715:
716: #undef ASC_SCSI_ID_BITS
717: #define ASC_SCSI_ID_BITS 5
718: #define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL
719:
720: #endif
721:
722: #if ASC_SCSI_ID_BITS == 3
723:
724: #define ASC_SCSI_BIT_ID_TYPE uchar
725: #define ASC_MAX_TID 7
726: #define ASC_MAX_LUN 7
727: #define ASC_SCSI_WIDTH_BIT_SET 0xFF
728:
729: #elif ASC_SCSI_ID_BITS == 4
730:
731: #define ASC_SCSI_BIT_ID_TYPE ushort
732: #define ASC_MAX_TID 15
733: #define ASC_MAX_LUN 7
734: #define ASC_SCSI_WIDTH_BIT_SET 0xFFFF
735:
736: #elif ASC_SCSI_ID_BITS == 5
737:
738: #define ASC_SCSI_BIT_ID_TYPE ulong
739: #define ASC_MAX_TID 31
740: #define ASC_MAX_LUN 7
741: #define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF
742:
743: #else
744:
745: #error ASC_SCSI_ID_BITS definition is wrong
746:
747: #endif
748:
749: #define ASC_MAX_SENSE_LEN 32
750: #define ASC_MIN_SENSE_LEN 14
751:
752: #define ASC_MAX_CDB_LEN 12
753:
754: #define SCSICMD_TestUnitReady 0x00
755: #define SCSICMD_Rewind 0x01
756: #define SCSICMD_Rezero 0x01
757: #define SCSICMD_RequestSense 0x03
758: #define SCSICMD_Format 0x04
759: #define SCSICMD_FormatUnit 0x04
760: #define SCSICMD_Read6 0x08
761: #define SCSICMD_Write6 0x0A
762: #define SCSICMD_Seek6 0x0B
763: #define SCSICMD_Inquiry 0x12
764: #define SCSICMD_Verify6 0x13
765: #define SCSICMD_ModeSelect6 0x15
766: #define SCSICMD_ModeSense6 0x1A
767:
768: #define SCSICMD_StartStopUnit 0x1B
769: #define SCSICMD_LoadUnloadTape 0x1B
770: #define SCSICMD_ReadCapacity 0x25
771: #define SCSICMD_Read10 0x28
772: #define SCSICMD_Write10 0x2A
773: #define SCSICMD_Seek10 0x2B
774: #define SCSICMD_Erase10 0x2C
775: #define SCSICMD_WriteAndVerify10 0x2E
776: #define SCSICMD_Verify10 0x2F
777:
778: #define SCSICMD_ModeSelect10 0x55
779: #define SCSICMD_ModeSense10 0x5A
780:
781: #define SCSI_TYPE_DASD 0x00
782: #define SCSI_TYPE_SASD 0x01
783: #define SCSI_TYPE_PRN 0x02
784: #define SCSI_TYPE_PROC 0x03
785:
786: #define SCSI_TYPE_WORM 0x04
787: #define SCSI_TYPE_CDROM 0x05
788: #define SCSI_TYPE_SCANNER 0x06
789: #define SCSI_TYPE_OPTMEM 0x07
790: #define SCSI_TYPE_MED_CHG 0x08
791: #define SCSI_TYPE_COMM 0x09
792: #define SCSI_TYPE_UNKNOWN 0x1F
793: #define SCSI_TYPE_NO_DVC 0xFF
794:
795: #define ASC_SCSIDIR_NOCHK 0x00
796:
797: #define ASC_SCSIDIR_T2H 0x08
798:
799: #define ASC_SCSIDIR_H2T 0x10
800:
801: #define ASC_SCSIDIR_NODATA 0x18
802:
803: #define SCSI_SENKEY_NO_SENSE 0x00
804: #define SCSI_SENKEY_UNDEFINED 0x01
805: #define SCSI_SENKEY_NOT_READY 0x02
806: #define SCSI_SENKEY_MEDIUM_ERR 0x03
807: #define SCSI_SENKEY_HW_ERR 0x04
808: #define SCSI_SENKEY_ILLEGAL 0x05
809: #define SCSI_SENKEY_ATTENSION 0x06
810: #define SCSI_SENKEY_PROTECTED 0x07
811: #define SCSI_SENKEY_BLANK 0x08
812: #define SCSI_SENKEY_V_UNIQUE 0x09
813: #define SCSI_SENKEY_CPY_ABORT 0x0A
814: #define SCSI_SENKEY_ABORT 0x0B
815: #define SCSI_SENKEY_EQUAL 0x0C
816: #define SCSI_SENKEY_VOL_OVERFLOW 0x0D
817: #define SCSI_SENKEY_MISCOMP 0x0E
818: #define SCSI_SENKEY_RESERVED 0x0F
819:
820: #define ASC_SRB_HOST( x ) ( ( uchar )( ( uchar )( x ) >> 4 ) )
821: #define ASC_SRB_TID( x ) ( ( uchar )( ( uchar )( x ) & ( uchar )0x0F ) )
822:
823: #define ASC_SRB_LUN( x ) ( ( uchar )( ( uint )( x ) >> 13 ) )
824:
825: #define PUT_CDB1( x ) ( ( uchar )( ( uint )( x ) >> 8 ) )
826:
827: #define SS_GOOD 0x00
828: #define SS_CHK_CONDITION 0x02
829: #define SS_CONDITION_MET 0x04
830: #define SS_TARGET_BUSY 0x08
831: #define SS_INTERMID 0x10
832: #define SS_INTERMID_COND_MET 0x14
833:
834: #define SS_RSERV_CONFLICT 0x18
835: #define SS_CMD_TERMINATED 0x22
836:
837: #define SS_QUEUE_FULL 0x28
838:
839: #define MS_CMD_DONE 0x00
840: #define MS_EXTEND 0x01
841: #define MS_SDTR_LEN 0x03
842: #define MS_SDTR_CODE 0x01
843:
844: #define M1_SAVE_DATA_PTR 0x02
845: #define M1_RESTORE_PTRS 0x03
846: #define M1_DISCONNECT 0x04
847: #define M1_INIT_DETECTED_ERR 0x05
848: #define M1_ABORT 0x06
849: #define M1_MSG_REJECT 0x07
850: #define M1_NO_OP 0x08
851: #define M1_MSG_PARITY_ERR 0x09
852: #define M1_LINK_CMD_DONE 0x0A
853: #define M1_LINK_CMD_DONE_WFLAG 0x0B
854: #define M1_BUS_DVC_RESET 0x0C
855: #define M1_ABORT_TAG 0x0D
856: #define M1_CLR_QUEUE 0x0E
857: #define M1_INIT_RECOVERY 0x0F
858: #define M1_RELEASE_RECOVERY 0x10
859: #define M1_KILL_IO_PROC 0x11
860:
861: #define M2_QTAG_MSG_SIMPLE 0x20
862: #define M2_QTAG_MSG_HEAD 0x21
863: #define M2_QTAG_MSG_ORDERED 0x22
864: #define M2_IGNORE_WIDE_RESIDUE 0x23
865:
866: typedef struct {
867: uchar peri_dvc_type:5;
868: uchar peri_qualifier:3;
869: } ASC_SCSI_INQ0;
870:
871: typedef struct {
872: uchar dvc_type_modifier:7;
873: uchar rmb:1;
874: } ASC_SCSI_INQ1;
875:
876: typedef struct {
877: uchar ansi_apr_ver:3;
878: uchar ecma_ver:3;
879: uchar iso_ver:2;
880: } ASC_SCSI_INQ2;
881:
882: typedef struct {
883: uchar rsp_data_fmt:4;
884:
885: uchar res:2;
886: uchar TemIOP:1;
887: uchar aenc:1;
888: } ASC_SCSI_INQ3;
889:
890: typedef struct {
891: uchar StfRe:1;
892: uchar CmdQue:1;
893: uchar Reserved:1;
894: uchar Linked:1;
895: uchar Sync:1;
896: uchar WBus16:1;
897: uchar WBus32:1;
898: uchar RelAdr:1;
899: } ASC_SCSI_INQ7;
900:
901: typedef struct {
902: ASC_SCSI_INQ0 byte0;
903: ASC_SCSI_INQ1 byte1;
904: ASC_SCSI_INQ2 byte2;
905: ASC_SCSI_INQ3 byte3;
906: uchar add_len;
907: uchar res1;
908: uchar res2;
909: ASC_SCSI_INQ7 byte7;
910: uchar vendor_id[8];
911: uchar product_id[16];
912: uchar product_rev_level[4];
913: } ASC_SCSI_INQUIRY;
914:
915: typedef struct asc_req_sense {
916: uchar err_code:7;
917: uchar info_valid:1;
918: uchar segment_no;
919: uchar sense_key:4;
920: uchar reserved_bit:1;
921: uchar sense_ILI:1;
922: uchar sense_EOM:1;
923: uchar file_mark:1;
924: uchar info1[4];
925: uchar add_sense_len;
926: uchar cmd_sp_info[4];
927: uchar asc;
928: uchar ascq;
929:
930: uchar fruc;
931: uchar sks_byte0:7;
932: uchar sks_valid:1;
933: uchar sks_bytes[2];
934: uchar notused[2];
935: uchar ex_sense_code;
936: uchar info2[4];
937: } ASC_REQ_SENSE;
938:
939: #define ASC_SG_LIST_PER_Q 7
940:
941: #define QS_FREE 0x00
942: #define QS_READY 0x01
943: #define QS_DISC1 0x02
944: #define QS_DISC2 0x04
945: #define QS_BUSY 0x08
946:
947: #define QS_ABORTED 0x40
948: #define QS_DONE 0x80
949:
950: #define QC_NO_CALLBACK 0x01
951:
952: #define QC_SG_SWAP_QUEUE 0x02
953: #define QC_SG_HEAD 0x04
954: #define QC_DATA_IN 0x08
955: #define QC_DATA_OUT 0x10
956:
957: #define QC_URGENT 0x20
958: #define QC_MSG_OUT 0x40
959: #define QC_REQ_SENSE 0x80
960:
961: #define QCSG_SG_XFER_LIST 0x02
962: #define QCSG_SG_XFER_MORE 0x04
963: #define QCSG_SG_XFER_END 0x08
964:
965: #define QD_IN_PROGRESS 0x00
966: #define QD_NO_ERROR 0x01
967: #define QD_ABORTED_BY_HOST 0x02
968: #define QD_WITH_ERROR 0x04
969: #define QD_INVALID_REQUEST 0x80
970: #define QD_INVALID_HOST_NUM 0x81
971: #define QD_INVALID_DEVICE 0x82
972: #define QD_ERR_INTERNAL 0xFF
973:
974: #define QHSTA_NO_ERROR 0x00
975: #define QHSTA_M_SEL_TIMEOUT 0x11
976: #define QHSTA_M_DATA_OVER_RUN 0x12
977: #define QHSTA_M_DATA_UNDER_RUN 0x12
978: #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
979: #define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
980:
981: #define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
982: #define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
983: #define QHSTA_D_HOST_ABORT_FAILED 0x23
984: #define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
985: #define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
986:
987: #define QHSTA_D_ASPI_NO_BUF_POOL 0x26
988:
989: #define QHSTA_M_WTM_TIMEOUT 0x41
990: #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
991: #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
992: #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
993: #define QHSTA_M_TARGET_STATUS_BUSY 0x45
994: #define QHSTA_M_BAD_TAG_CODE 0x46
995:
996: #define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
997:
998: #define QHSTA_D_LRAM_CMP_ERROR 0x81
999: #define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
1000:
1001: #define ASC_FLAG_SCSIQ_REQ 0x01
1002: #define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
1003: #define ASC_FLAG_BIOS_ASYNC_IO 0x04
1004: #define ASC_FLAG_SRB_LINEAR_ADDR 0x08
1005:
1006: #define ASC_FLAG_WIN16 0x10
1007: #define ASC_FLAG_WIN32 0x20
1008:
1009: #define ASC_FLAG_DOS_VM_CALLBACK 0x80
1010:
1011: #define ASC_TAG_FLAG_ADD_ONE_BYTE 0x10
1012: #define ASC_TAG_FLAG_ISAPNP_ADD_BYTES 0x40
1013:
1014: #define ASC_SCSIQ_CPY_BEG 4
1015: #define ASC_SCSIQ_SGHD_CPY_BEG 2
1016:
1017: #define ASC_SCSIQ_B_FWD 0
1018: #define ASC_SCSIQ_B_BWD 1
1019:
1020: #define ASC_SCSIQ_B_STATUS 2
1021: #define ASC_SCSIQ_B_QNO 3
1022:
1023: #define ASC_SCSIQ_B_CNTL 4
1024: #define ASC_SCSIQ_B_SG_QUEUE_CNT 5
1025:
1026: #define ASC_SCSIQ_D_DATA_ADDR 8
1027: #define ASC_SCSIQ_D_DATA_CNT 12
1028: #define ASC_SCSIQ_B_SENSE_LEN 20
1029: #define ASC_SCSIQ_DONE_INFO_BEG 22
1030: #define ASC_SCSIQ_D_SRBPTR 22
1031: #define ASC_SCSIQ_B_TARGET_IX 26
1032: #define ASC_SCSIQ_B_CDB_LEN 28
1033: #define ASC_SCSIQ_B_TAG_CODE 29
1034: #define ASC_SCSIQ_W_VM_ID 30
1035: #define ASC_SCSIQ_DONE_STATUS 32
1036: #define ASC_SCSIQ_HOST_STATUS 33
1037: #define ASC_SCSIQ_SCSI_STATUS 34
1038: #define ASC_SCSIQ_CDB_BEG 36
1039: #define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
1040: #define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
1041: #define ASC_SCSIQ_B_SG_WK_QP 49
1042: #define ASC_SCSIQ_B_SG_WK_IX 50
1043: #define ASC_SCSIQ_W_REQ_COUNT 52
1044: #define ASC_SCSIQ_B_LIST_CNT 6
1045: #define ASC_SCSIQ_B_CUR_LIST_CNT 7
1046:
1047: #define ASC_SGQ_B_SG_CNTL 4
1048: #define ASC_SGQ_B_SG_HEAD_QP 5
1049: #define ASC_SGQ_B_SG_LIST_CNT 6
1050: #define ASC_SGQ_B_SG_CUR_LIST_CNT 7
1051: #define ASC_SGQ_LIST_BEG 8
1052:
1053: #define ASC_DEF_SCSI1_QNG 2
1054: #define ASC_MAX_SCSI1_QNG 2
1055: #define ASC_DEF_SCSI2_QNG 16
1056: #define ASC_MAX_SCSI2_QNG 32
1057:
1058: #define ASC_TAG_CODE_MASK 0x23
1059:
1060: #define ASC_STOP_REQ_RISC_STOP 0x01
1061:
1062: #define ASC_STOP_ACK_RISC_STOP 0x03
1063:
1064: #define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
1065: #define ASC_STOP_CLEAN_UP_DISC_Q 0x20
1066: #define ASC_STOP_HOST_REQ_RISC_HALT 0x40
1067: #define ASC_STOP_SEND_INT_TO_HOST 0x80
1068:
1069: #define ASC_TIDLUN_TO_IX( tid, lun ) ( ASC_SCSI_TIX_TYPE )( (tid) + ((lun)<<ASC_SCSI_ID_BITS) )
1070:
1071: #define ASC_TID_TO_TARGET_ID( tid ) ( ASC_SCSI_BIT_ID_TYPE )( 0x01 << (tid) )
1072: #define ASC_TIX_TO_TARGET_ID( tix ) ( 0x01 << ( (tix) & ASC_MAX_TID ) )
1073: #define ASC_TIX_TO_TID( tix ) ( (tix) & ASC_MAX_TID )
1074: #define ASC_TID_TO_TIX( tid ) ( (tid) & ASC_MAX_TID )
1075: #define ASC_TIX_TO_LUN( tix ) ( ( (tix) >> ASC_SCSI_ID_BITS ) & ASC_MAX_LUN )
1076:
1077: #define ASC_QNO_TO_QADDR( q_no ) ( (ASC_QADR_BEG)+( ( int )(q_no) << 6 ) )
1078:
1079: typedef struct asc_scisq_1 {
1080: uchar status;
1081: uchar q_no;
1082: uchar cntl;
1083: uchar sg_queue_cnt;
1084:
1085: uchar target_id;
1086: uchar target_lun;
1087:
1088: ulong data_addr;
1089: ulong data_cnt;
1090: ulong sense_addr;
1091: uchar sense_len;
1092: uchar user_def;
1093: } ASC_SCSIQ_1;
1094:
1095: typedef struct asc_scisq_2 {
1096: ulong srb_ptr;
1097: uchar target_ix;
1098:
1099: uchar flag;
1100: uchar cdb_len;
1101: uchar tag_code;
1102:
1103: ushort vm_id;
1104: } ASC_SCSIQ_2;
1105:
1106: typedef struct asc_scsiq_3 {
1107: uchar done_stat;
1108: uchar host_stat;
1109: uchar scsi_stat;
1110: uchar scsi_msg;
1111: } ASC_SCSIQ_3;
1112:
1113: typedef struct asc_scsiq_4 {
1114: uchar cdb[ASC_MAX_CDB_LEN];
1115: uchar y_first_sg_list_qp;
1116: uchar y_working_sg_qp;
1117: uchar y_working_sg_ix;
1118: uchar y_cntl;
1119: ushort x_req_count;
1120: ushort x_reconnect_rtn;
1121: ulong x_saved_data_addr;
1122: ulong x_saved_data_cnt;
1123: } ASC_SCSIQ_4;
1124:
1125: typedef struct asc_q_done_info {
1126: ASC_SCSIQ_2 d2;
1127: ASC_SCSIQ_3 d3;
1128: uchar q_status;
1129: uchar q_no;
1130: uchar cntl;
1131: uchar sense_len;
1132: uchar user_def;
1133: uchar res;
1134: ulong remain_bytes;
1135: } ASC_QDONE_INFO;
1136:
1137: typedef struct asc_sg_list {
1138: ulong addr;
1139: ulong bytes;
1140: } ASC_SG_LIST;
1141:
1142: typedef struct asc_sg_head {
1143: uchar entry_cnt;
1144:
1145: uchar queue_cnt;
1146:
1147: uchar entry_to_copy;
1148: uchar res;
1149: ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
1150: } ASC_SG_HEAD;
1151:
1152: #define ASC_MIN_SG_LIST 2
1153:
1154: typedef struct asc_min_sg_head {
1155: uchar entry_cnt;
1156:
1157: uchar queue_cnt;
1158:
1159: uchar entry_to_copy;
1160: uchar res;
1161: ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
1162: } ASC_MIN_SG_HEAD;
1163:
1164: #define QCX_SORT (0x0001)
1165: #define QCX_COALEASE (0x0002)
1166:
1167: #if CC_LINK_BUSY_Q
1168: typedef struct asc_ext_scsi_q {
1169: ulong lba;
1170: ushort lba_len;
1171: struct asc_scsi_q dosfar *next;
1172: struct asc_scsi_q dosfar *join;
1173: ushort cntl;
1174: ushort buffer_id;
1175: uchar q_required;
1176: uchar res;
1177: } ASC_EXT_SCSI_Q;
1178:
1179: #endif
1180:
1181: typedef struct asc_scsi_q {
1182: ASC_SCSIQ_1 q1;
1183: ASC_SCSIQ_2 q2;
1184: uchar dosfar *cdbptr;
1185:
1186: ASC_SG_HEAD dosfar *sg_head;
1187:
1188: #if CC_LINK_BUSY_Q
1189: ASC_EXT_SCSI_Q ext;
1190: #endif
1191:
1192: } ASC_SCSI_Q;
1193:
1194: typedef struct asc_scsi_req_q {
1195: ASC_SCSIQ_1 r1;
1196: ASC_SCSIQ_2 r2;
1197: uchar dosfar *cdbptr;
1198: ASC_SG_HEAD dosfar *sg_head;
1199:
1200: #if CC_LINK_BUSY_Q
1201: ASC_EXT_SCSI_Q ext;
1202: #endif
1203:
1204: uchar dosfar *sense_ptr;
1205:
1206: ASC_SCSIQ_3 r3;
1207: uchar cdb[ASC_MAX_CDB_LEN];
1208: uchar sense[ASC_MIN_SENSE_LEN];
1209: } ASC_SCSI_REQ_Q;
1210:
1211: typedef struct asc_risc_q {
1212: uchar fwd;
1213: uchar bwd;
1214: ASC_SCSIQ_1 i1;
1215: ASC_SCSIQ_2 i2;
1216: ASC_SCSIQ_3 i3;
1217: ASC_SCSIQ_4 i4;
1218: } ASC_RISC_Q;
1219:
1220: typedef struct asc_sg_list_q {
1221:
1222: uchar seq_no;
1223: uchar q_no;
1224: uchar cntl;
1225: uchar sg_head_qp;
1226: uchar sg_list_cnt;
1227: uchar sg_cur_list_cnt;
1228:
1229: } ASC_SG_LIST_Q;
1230:
1231: typedef struct asc_risc_sg_list_q {
1232: uchar fwd;
1233: uchar bwd;
1234: ASC_SG_LIST_Q sg;
1235: ASC_SG_LIST sg_list[7];
1236: } ASC_RISC_SG_LIST_Q;
1237:
1238: #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
1239: #define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
1240:
1241: #define ASCQ_ERR_NO_ERROR 0
1242: #define ASCQ_ERR_IO_NOT_FOUND 1
1243: #define ASCQ_ERR_LOCAL_MEM 2
1244: #define ASCQ_ERR_CHKSUM 3
1245: #define ASCQ_ERR_START_CHIP 4
1246: #define ASCQ_ERR_INT_TARGET_ID 5
1247: #define ASCQ_ERR_INT_LOCAL_MEM 6
1248: #define ASCQ_ERR_HALT_RISC 7
1249: #define ASCQ_ERR_GET_ASPI_ENTRY 8
1250: #define ASCQ_ERR_CLOSE_ASPI 9
1251: #define ASCQ_ERR_HOST_INQUIRY 0x0A
1252: #define ASCQ_ERR_SAVED_SRB_BAD 0x0B
1253: #define ASCQ_ERR_QCNTL_SG_LIST 0x0C
1254: #define ASCQ_ERR_Q_STATUS 0x0D
1255: #define ASCQ_ERR_WR_SCSIQ 0x0E
1256: #define ASCQ_ERR_PC_ADDR 0x0F
1257: #define ASCQ_ERR_SYN_OFFSET 0x10
1258: #define ASCQ_ERR_SYN_XFER_TIME 0x11
1259: #define ASCQ_ERR_LOCK_DMA 0x12
1260: #define ASCQ_ERR_UNLOCK_DMA 0x13
1261: #define ASCQ_ERR_VDS_CHK_INSTALL 0x14
1262: #define ASCQ_ERR_MICRO_CODE_HALT 0x15
1263: #define ASCQ_ERR_SET_LRAM_ADDR 0x16
1264: #define ASCQ_ERR_CUR_QNG 0x17
1265: #define ASCQ_ERR_SG_Q_LINKS 0x18
1266: #define ASCQ_ERR_SCSIQ_PTR 0x19
1267: #define ASCQ_ERR_ISR_RE_ENTRY 0x1A
1268: #define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
1269: #define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
1270: #define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D
1271: #define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
1272: #define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F
1273: #define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20
1274: #define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21
1275: #define ASCQ_ERR_SEND_SCSI_Q 0x22
1276: #define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23
1277: #define ASCQ_ERR_RESET_SDTR 0x24
1278:
1279: #define ASC_WARN_NO_ERROR 0x0000
1280: #define ASC_WARN_IO_PORT_ROTATE 0x0001
1281: #define ASC_WARN_EEPROM_CHKSUM 0x0002
1282: #define ASC_WARN_IRQ_MODIFIED 0x0004
1283: #define ASC_WARN_AUTO_CONFIG 0x0008
1284: #define ASC_WARN_CMD_QNG_CONFLICT 0x0010
1285:
1286: #define ASC_WARN_EEPROM_RECOVER 0x0020
1287: #define ASC_WARN_CFG_MSW_RECOVER 0x0040
1288:
1289: #define ASC_IERR_WRITE_EEPROM 0x0001
1290: #define ASC_IERR_MCODE_CHKSUM 0x0002
1291: #define ASC_IERR_SET_PC_ADDR 0x0004
1292: #define ASC_IERR_START_STOP_CHIP 0x0008
1293:
1294: #define ASC_IERR_IRQ_NO 0x0010
1295:
1296: #define ASC_IERR_SET_IRQ_NO 0x0020
1297: #define ASC_IERR_CHIP_VERSION 0x0040
1298: #define ASC_IERR_SET_SCSI_ID 0x0080
1299: #define ASC_IERR_GET_PHY_ADDR 0x0100
1300: #define ASC_IERR_BAD_SIGNATURE 0x0200
1301: #define ASC_IERR_NO_BUS_TYPE 0x0400
1302: #define ASC_IERR_SCAM 0x0800
1303: #define ASC_IERR_SET_SDTR 0x1000
1304: #define ASC_IERR_RW_LRAM 0x8000
1305:
1306: #define ASC_DEF_IRQ_NO 10
1307: #define ASC_MAX_IRQ_NO 15
1308: #define ASC_MIN_IRQ_NO 10
1309:
1310: #define ASC_MIN_REMAIN_Q (0x02)
1311: #define ASC_DEF_MAX_TOTAL_QNG (0x40)
1312:
1313: #define ASC_MIN_TAG_Q_PER_DVC (0x04)
1314: #define ASC_DEF_TAG_Q_PER_DVC (0x04)
1315:
1316: #define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
1317:
1318: #define ASC_MIN_TOTAL_QNG (( ASC_MAX_SG_QUEUE )+( ASC_MIN_FREE_Q ))
1319:
1320: #define ASC_MAX_TOTAL_QNG 240
1321: #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
1322:
1323: #define ASC_MAX_INRAM_TAG_QNG 16
1324:
1325: typedef struct asc_dvc_cfg {
1326: ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
1327:
1328: ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
1329: ASC_SCSI_BIT_ID_TYPE disc_enable;
1330: uchar res;
1331: uchar chip_scsi_id:4;
1332:
1333: uchar isa_dma_speed:4;
1334:
1335: uchar isa_dma_channel;
1336: uchar chip_version;
1337: ushort pci_device_id;
1338: ushort lib_serial_no;
1339: ushort lib_version;
1340: ushort mcode_date;
1341: ushort mcode_version;
1342: uchar sdtr_data[ASC_MAX_TID + 1];
1343: uchar max_tag_qng[ASC_MAX_TID + 1];
1344: uchar dosfar *overrun_buf;
1345:
1346: } ASC_DVC_CFG;
1347:
1348: #define ASC_DEF_DVC_CNTL 0xFFFF
1349: #define ASC_DEF_CHIP_SCSI_ID 7
1350: #define ASC_DEF_ISA_DMA_SPEED 4
1351:
1352: #define ASC_INIT_STATE_NULL 0x0000
1353: #define ASC_INIT_STATE_BEG_GET_CFG 0x0001
1354: #define ASC_INIT_STATE_END_GET_CFG 0x0002
1355: #define ASC_INIT_STATE_BEG_SET_CFG 0x0004
1356: #define ASC_INIT_STATE_END_SET_CFG 0x0008
1357: #define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
1358: #define ASC_INIT_STATE_END_LOAD_MC 0x0020
1359: #define ASC_INIT_STATE_BEG_INQUIRY 0x0040
1360: #define ASC_INIT_STATE_END_INQUIRY 0x0080
1361: #define ASC_INIT_RESET_SCSI_DONE 0x0100
1362:
1363: #define ASC_PCI_DEVICE_ID_REV_A 0x1100
1364: #define ASC_PCI_DEVICE_ID_REV_B 0x1200
1365:
1366: #define ASC_BUG_FIX_ADD_ONE_BYTE 0x0001
1367:
1368: #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
1369:
1370: #define ASC_MIN_TAGGED_CMD 7
1371:
1372: typedef struct asc_dvc_var {
1373: PortAddr iop_base;
1374: ushort err_code;
1375: ushort dvc_cntl;
1376: ushort bug_fix_cntl;
1377: ushort bus_type;
1378: Ptr2Func isr_callback;
1379: Ptr2Func exe_callback;
1380:
1381: ASC_SCSI_BIT_ID_TYPE init_sdtr;
1382:
1383: ASC_SCSI_BIT_ID_TYPE sdtr_done;
1384:
1385: ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
1386:
1387: ASC_SCSI_BIT_ID_TYPE unit_not_ready;
1388:
1389: ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
1390:
1391: ASC_SCSI_BIT_ID_TYPE start_motor;
1392: uchar scsi_reset_wait;
1393: uchar chip_no;
1394:
1395: char is_in_int;
1396: uchar max_total_qng;
1397:
1398: uchar cur_total_qng;
1399:
1400: uchar in_critical_cnt;
1401:
1402: uchar irq_no;
1403: uchar last_q_shortage;
1404:
1405: ushort init_state;
1406: uchar cur_dvc_qng[ASC_MAX_TID + 1];
1407: uchar max_dvc_qng[ASC_MAX_TID + 1];
1408:
1409: ASC_SCSI_Q dosfar *scsiq_busy_head[ASC_MAX_TID + 1];
1410: ASC_SCSI_Q dosfar *scsiq_busy_tail[ASC_MAX_TID + 1];
1411:
1412: ulong int_count;
1413: ulong req_count;
1414: ulong busy_count;
1415:
1416: ASC_DVC_CFG dosfar *cfg;
1417: Ptr2Func saved_ptr2func;
1418: ulong reserved2;
1419: ulong reserved3;
1420: ulong max_dma_count;
1421: ASC_SCSI_BIT_ID_TYPE no_scam;
1422: ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
1423: } ASC_DVC_VAR;
1424:
1425: typedef int (dosfar * ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO dosfar *);
1426: typedef int (dosfar * ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
1427:
1428: typedef struct asc_dvc_inq_info {
1429: uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1430: } ASC_DVC_INQ_INFO;
1431:
1432: typedef struct asc_cap_info {
1433: ulong lba;
1434: ulong blk_size;
1435: } ASC_CAP_INFO;
1436:
1437: typedef struct asc_cap_info_array {
1438: ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
1439: } ASC_CAP_INFO_ARRAY;
1440:
1441: #define ASC_IOADR_TABLE_MAX_IX 11
1442: #define ASC_IOADR_GAP 0x10
1443: #define ASC_SEARCH_IOP_GAP 0x10
1444: #define ASC_MIN_IOP_ADDR ( PortAddr )0x0100
1445: #define ASC_MAX_IOP_ADDR ( PortAddr )0x3F0
1446:
1447: #define ASC_IOADR_1 ( PortAddr )0x0110
1448: #define ASC_IOADR_2 ( PortAddr )0x0130
1449: #define ASC_IOADR_3 ( PortAddr )0x0150
1450: #define ASC_IOADR_4 ( PortAddr )0x0190
1451: #define ASC_IOADR_5 ( PortAddr )0x0210
1452: #define ASC_IOADR_6 ( PortAddr )0x0230
1453: #define ASC_IOADR_7 ( PortAddr )0x0250
1454: #define ASC_IOADR_8 ( PortAddr )0x0330
1455: #define ASC_IOADR_DEF ASC_IOADR_8
1456:
1457: #define ASC_SYN_XFER_NO 8
1458: #define ASC_MAX_SDTR_PERIOD_INDEX 7
1459: #define ASC_SYN_MAX_OFFSET 0x0F
1460: #define ASC_DEF_SDTR_OFFSET 0x0F
1461: #define ASC_DEF_SDTR_INDEX 0x00
1462:
1463: #define SYN_XFER_NS_0 25
1464: #define SYN_XFER_NS_1 30
1465: #define SYN_XFER_NS_2 35
1466: #define SYN_XFER_NS_3 40
1467: #define SYN_XFER_NS_4 50
1468: #define SYN_XFER_NS_5 60
1469: #define SYN_XFER_NS_6 70
1470: #define SYN_XFER_NS_7 85
1471:
1472: #define ASC_SDTR_PERIOD_IX_MIN 7
1473:
1474: #define SYN_XMSG_WLEN 3
1475:
1476: typedef struct sdtr_xmsg {
1477: uchar msg_type;
1478: uchar msg_len;
1479: uchar msg_req;
1480: uchar xfer_period;
1481: uchar req_ack_offset;
1482: uchar res;
1483: } SDTR_XMSG;
1484:
1485: #define ASC_MCNTL_NO_SEL_TIMEOUT ( ushort )0x0001
1486: #define ASC_MCNTL_NULL_TARGET ( ushort )0x0002
1487:
1488: #define ASC_CNTL_INITIATOR ( ushort )0x0001
1489: #define ASC_CNTL_BIOS_GT_1GB ( ushort )0x0002
1490: #define ASC_CNTL_BIOS_GT_2_DISK ( ushort )0x0004
1491: #define ASC_CNTL_BIOS_REMOVABLE ( ushort )0x0008
1492: #define ASC_CNTL_NO_SCAM ( ushort )0x0010
1493: #define ASC_CNTL_NO_PCI_FIX_ASYN_XFER ( ushort )0x0020
1494:
1495: #define ASC_CNTL_INT_MULTI_Q ( ushort )0x0080
1496:
1497: #define ASC_CNTL_NO_LUN_SUPPORT ( ushort )0x0040
1498:
1499: #define ASC_CNTL_NO_VERIFY_COPY ( ushort )0x0100
1500: #define ASC_CNTL_RESET_SCSI ( ushort )0x0200
1501: #define ASC_CNTL_INIT_INQUIRY ( ushort )0x0400
1502: #define ASC_CNTL_INIT_VERBOSE ( ushort )0x0800
1503:
1504: #define ASC_CNTL_SCSI_PARITY ( ushort )0x1000
1505: #define ASC_CNTL_BURST_MODE ( ushort )0x2000
1506:
1507: #define ASC_CNTL_USE_8_IOP_BASE ( ushort )0x4000
1508:
1509: #define ASC_EEP_DVC_CFG_BEG_VL 2
1510: #define ASC_EEP_MAX_DVC_ADDR_VL 15
1511:
1512: #define ASC_EEP_DVC_CFG_BEG 32
1513: #define ASC_EEP_MAX_DVC_ADDR 45
1514:
1515: #define ASC_EEP_DEFINED_WORDS 10
1516: #define ASC_EEP_MAX_ADDR 63
1517: #define ASC_EEP_RES_WORDS 0
1518: #define ASC_EEP_MAX_RETRY 20
1519: #define ASC_MAX_INIT_BUSY_RETRY 8
1520:
1521: #define ASC_EEP_ISA_PNP_WSIZE 16
1522:
1523: typedef struct asceep_config {
1524: ushort cfg_lsw;
1525: ushort cfg_msw;
1526:
1527: uchar init_sdtr;
1528: uchar disc_enable;
1529:
1530: uchar use_cmd_qng;
1531:
1532: uchar start_motor;
1533: uchar max_total_qng;
1534: uchar max_tag_qng;
1535: uchar bios_scan;
1536:
1537: uchar power_up_wait;
1538:
1539: uchar no_scam;
1540: uchar chip_scsi_id:4;
1541:
1542: uchar isa_dma_speed:4;
1543:
1544: uchar sdtr_data[ASC_MAX_TID + 1];
1545:
1546: uchar adapter_info[6];
1547:
1548: ushort cntl;
1549:
1550: ushort chksum;
1551: } ASCEEP_CONFIG;
1552:
1553: #define ASC_EEP_CMD_READ 0x80
1554: #define ASC_EEP_CMD_WRITE 0x40
1555: #define ASC_EEP_CMD_WRITE_ABLE 0x30
1556: #define ASC_EEP_CMD_WRITE_DISABLE 0x00
1557:
1558: #define ASC_OVERRUN_BSIZE 0x00000048UL
1559:
1560: #define ASCV_MSGOUT_BEG 0x0000
1561: #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
1562: #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
1563:
1564: #define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
1565: #define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
1566: #define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
1567:
1568: #define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
1569: #define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
1570: #define ASCV_MAX_DVC_QNG_BEG ( ushort )0x0020
1571:
1572: #define ASCV_ASCDVC_ERR_CODE_W ( ushort )0x0030
1573: #define ASCV_MCODE_CHKSUM_W ( ushort )0x0032
1574: #define ASCV_MCODE_SIZE_W ( ushort )0x0034
1575: #define ASCV_STOP_CODE_B ( ushort )0x0036
1576: #define ASCV_DVC_ERR_CODE_B ( ushort )0x0037
1577:
1578: #define ASCV_OVERRUN_PADDR_D ( ushort )0x0038
1579: #define ASCV_OVERRUN_BSIZE_D ( ushort )0x003C
1580:
1581: #define ASCV_HALTCODE_W ( ushort )0x0040
1582: #define ASCV_CHKSUM_W ( ushort )0x0042
1583: #define ASCV_MC_DATE_W ( ushort )0x0044
1584: #define ASCV_MC_VER_W ( ushort )0x0046
1585: #define ASCV_NEXTRDY_B ( ushort )0x0048
1586: #define ASCV_DONENEXT_B ( ushort )0x0049
1587: #define ASCV_USE_TAGGED_QNG_B ( ushort )0x004A
1588: #define ASCV_SCSIBUSY_B ( ushort )0x004B
1589: #define ASCV_CDBCNT_B ( ushort )0x004C
1590: #define ASCV_CURCDB_B ( ushort )0x004D
1591: #define ASCV_RCLUN_B ( ushort )0x004E
1592: #define ASCV_BUSY_QHEAD_B ( ushort )0x004F
1593: #define ASCV_DISC1_QHEAD_B ( ushort )0x0050
1594:
1595: #define ASCV_DISC_ENABLE_B ( ushort )0x0052
1596: #define ASCV_CAN_TAGGED_QNG_B ( ushort )0x0053
1597: #define ASCV_HOSTSCSI_ID_B ( ushort )0x0055
1598: #define ASCV_MCODE_CNTL_B ( ushort )0x0056
1599: #define ASCV_NULL_TARGET_B ( ushort )0x0057
1600:
1601: #define ASCV_FREE_Q_HEAD_W ( ushort )0x0058
1602: #define ASCV_DONE_Q_TAIL_W ( ushort )0x005A
1603: #define ASCV_FREE_Q_HEAD_B ( ushort )(ASCV_FREE_Q_HEAD_W+1)
1604: #define ASCV_DONE_Q_TAIL_B ( ushort )(ASCV_DONE_Q_TAIL_W+1)
1605:
1606: #define ASCV_HOST_FLAG_B ( ushort )0x005D
1607:
1608: #define ASCV_TOTAL_READY_Q_B ( ushort )0x0064
1609: #define ASCV_VER_SERIAL_B ( ushort )0x0065
1610: #define ASCV_HALTCODE_SAVED_W ( ushort )0x0066
1611: #define ASCV_WTM_FLAG_B ( ushort )0x0068
1612: #define ASCV_RISC_FLAG_B ( ushort )0x006A
1613: #define ASCV_REQ_SG_LIST_QP ( ushort )0x006B
1614:
1615: #define ASC_HOST_FLAG_IN_ISR 0x01
1616: #define ASC_HOST_FLAG_ACK_INT 0x02
1617:
1618: #define ASC_RISC_FLAG_GEN_INT 0x01
1619: #define ASC_RISC_FLAG_REQ_SG_LIST 0x02
1620:
1621: #define IOP_CTRL (0x0F)
1622: #define IOP_STATUS (0x0E)
1623: #define IOP_INT_ACK IOP_STATUS
1624:
1625: #define IOP_REG_IFC (0x0D)
1626:
1627: #define IOP_SYN_OFFSET (0x0B)
1628: #define IOP_REG_PC (0x0C)
1629: #define IOP_RAM_ADDR (0x0A)
1630: #define IOP_RAM_DATA (0x08)
1631: #define IOP_EEP_DATA (0x06)
1632: #define IOP_EEP_CMD (0x07)
1633:
1634: #define IOP_VERSION (0x03)
1635: #define IOP_CONFIG_HIGH (0x04)
1636: #define IOP_CONFIG_LOW (0x02)
1637: #define IOP_ASPI_ID_LOW (0x01)
1638: #define IOP_ASPI_ID_HIGH (0x00)
1639:
1640: #define IOP_REG_DC1 (0x0E)
1641: #define IOP_REG_DC0 (0x0C)
1642: #define IOP_REG_SB (0x0B)
1643: #define IOP_REG_DA1 (0x0A)
1644: #define IOP_REG_DA0 (0x08)
1645: #define IOP_REG_SC (0x09)
1646: #define IOP_DMA_SPEED (0x07)
1647: #define IOP_REG_FLAG (0x07)
1648: #define IOP_FIFO_H (0x06)
1649: #define IOP_FIFO_L (0x04)
1650: #define IOP_REG_ID (0x05)
1651: #define IOP_REG_QP (0x03)
1652: #define IOP_REG_IH (0x02)
1653: #define IOP_REG_IX (0x01)
1654: #define IOP_REG_AX (0x00)
1655:
1656: #define IFC_REG_LOCK (0x00)
1657: #define IFC_REG_UNLOCK (0x09)
1658:
1659: #define IFC_WR_EN_FILTER (0x10)
1660: #define IFC_RD_NO_EEPROM (0x10)
1661: #define IFC_SLEW_RATE (0x20)
1662: #define IFC_ACT_NEG (0x40)
1663: #define IFC_INP_FILTER (0x80)
1664:
1665: #define IFC_INIT_DEFAULT ( IFC_ACT_NEG | IFC_REG_UNLOCK )
1666:
1667: #define SC_SEL (0x80)
1668: #define SC_BSY (0x40)
1669: #define SC_ACK (0x20)
1670: #define SC_REQ (0x10)
1671: #define SC_ATN (0x08)
1672: #define SC_IO (0x04)
1673: #define SC_CD (0x02)
1674: #define SC_MSG (0x01)
1675:
1676: #define AscGetVarFreeQHead( port ) AscReadLramWord( port, ASCV_FREE_Q_HEAD_W )
1677: #define AscGetVarDoneQTail( port ) AscReadLramWord( port, ASCV_DONE_Q_TAIL_W )
1678: #define AscPutVarFreeQHead( port, val ) AscWriteLramWord( port, ASCV_FREE_Q_HEAD_W, val )
1679: #define AscPutVarDoneQTail( port, val ) AscWriteLramWord( port, ASCV_DONE_Q_TAIL_W, val )
1680:
1681: #define AscGetRiscVarFreeQHead( port ) AscReadLramByte( port, ASCV_NEXTRDY_B )
1682: #define AscGetRiscVarDoneQTail( port ) AscReadLramByte( port, ASCV_DONENEXT_B )
1683: #define AscPutRiscVarFreeQHead( port, val ) AscWriteLramByte( port, ASCV_NEXTRDY_B, val )
1684: #define AscPutRiscVarDoneQTail( port, val ) AscWriteLramByte( port, ASCV_DONENEXT_B, val )
1685:
1686: #define AscGetChipIFC( port ) inp( (port)+IOP_REG_IFC )
1687: #define AscPutChipIFC( port, data ) outp( (port)+IOP_REG_IFC, data )
1688:
1689: #define AscGetChipLramAddr( port ) ( ushort )inpw( ( PortAddr )((port)+IOP_RAM_ADDR) )
1690: #define AscSetChipLramAddr( port, addr ) outpw( ( PortAddr )( (port)+IOP_RAM_ADDR ), addr )
1691: #define AscPutChipLramData( port, data ) outpw( (port)+IOP_RAM_DATA, data )
1692: #define AscGetChipLramData( port ) inpw( (port)+IOP_RAM_DATA )
1693:
1694: #define AscWriteChipSyn( port, data ) outp( (port)+IOP_SYN_OFFSET, data )
1695: #define AscReadChipSyn( port ) inp( (port)+IOP_SYN_OFFSET )
1696:
1697: #define AscWriteChipIH( port, data ) outpw( (port)+IOP_REG_IH, data )
1698: #define AscReadChipIH( port ) inpw( (port)+IOP_REG_IH )
1699:
1700: #define AscWriteChipScsiID( port, data ) outp( (port)+IOP_REG_ID, data )
1701: #define AscReadChipScsiID( port ) inp( (port)+IOP_REG_ID )
1702:
1703: #define AscGetChipDmaSpeed( port ) ( uchar )inp( (port)+IOP_DMA_SPEED )
1704: #define AscSetChipDmaSpeed( port, data ) outp( (port)+IOP_DMA_SPEED, data )
1705: #define AscGetChipQP( port ) ( uchar )inp( (port)+IOP_REG_QP )
1706: #define AscSetPCAddr( port, data ) outpw( (port)+IOP_REG_PC, data )
1707: #define AscGetPCAddr( port ) inpw( (port)+IOP_REG_PC )
1708: #define AscGetChipVerNo( port ) ( uchar )inp( (port)+IOP_VERSION )
1709:
1710: #define AscGetChipEEPCmd( port ) ( uchar )inp( (port)+IOP_EEP_CMD )
1711: #define AscSetChipEEPCmd( port, data ) outp( (port)+IOP_EEP_CMD, data )
1712: #define AscGetChipEEPData( port ) inpw( (port)+IOP_EEP_DATA )
1713: #define AscSetChipEEPData( port, data ) outpw( (port)+IOP_EEP_DATA, data )
1714:
1715: #define AscGetChipControl( port ) ( uchar )inp( (port)+IOP_CTRL )
1716: #define AscSetChipControl( port, cc_val ) outp( (port)+IOP_CTRL, cc_val )
1717:
1718: #define AscGetChipStatus( port ) ( ASC_CS_TYPE )inpw( (port)+IOP_STATUS )
1719: #define AscSetChipStatus( port, cs_val ) outpw( (port)+IOP_STATUS, cs_val )
1720:
1721: #define AscGetChipCfgLsw( port ) ( ushort )inpw( (port)+IOP_CONFIG_LOW )
1722: #define AscGetChipCfgMsw( port ) ( ushort )inpw( (port)+IOP_CONFIG_HIGH )
1723: #define AscSetChipCfgLsw( port, data ) outpw( (port)+IOP_CONFIG_LOW, data )
1724: #define AscSetChipCfgMsw( port, data ) outpw( (port)+IOP_CONFIG_HIGH, data )
1725:
1726: #define AscIsIntPending( port ) ( AscGetChipStatus( port ) & CSW_INT_PENDING )
1727: #define AscGetChipScsiID( port ) ( ( AscGetChipCfgLsw( port ) >> 8 ) & ASC_MAX_TID )
1728:
1729: #define ASC_HALT_EXTMSG_IN ( ushort )0x8000
1730: #define ASC_HALT_CHK_CONDITION ( ushort )0x8100
1731: #define ASC_HALT_SS_QUEUE_FULL ( ushort )0x8200
1732: #define ASC_HALT_SDTR_REJECTED ( ushort )0x4000
1733:
1734: #define ASC_MAX_QNO 0xF8
1735: #define ASC_DATA_SEC_BEG ( ushort )0x0080
1736: #define ASC_DATA_SEC_END ( ushort )0x0080
1737: #define ASC_CODE_SEC_BEG ( ushort )0x0080
1738: #define ASC_CODE_SEC_END ( ushort )0x0080
1739: #define ASC_QADR_BEG (0x4000)
1740: #define ASC_QADR_USED ( ushort )( ASC_MAX_QNO * 64 )
1741: #define ASC_QADR_END ( ushort )0x7FFF
1742: #define ASC_QLAST_ADR ( ushort )0x7FC0
1743: #define ASC_QBLK_SIZE 0x40
1744: #define ASC_BIOS_DATA_QBEG 0xF8
1745:
1746: #define ASC_MIN_ACTIVE_QNO 0x01
1747:
1748: #define ASC_QLINK_END 0xFF
1749: #define ASC_EEPROM_WORDS 0x10
1750: #define ASC_MAX_MGS_LEN 0x10
1751:
1752: #define ASC_BIOS_ADDR_DEF 0xDC00
1753: #define ASC_BIOS_SIZE 0x3800
1754: #define ASC_BIOS_RAM_OFF 0x3800
1755: #define ASC_BIOS_RAM_SIZE 0x800
1756: #define ASC_BIOS_MIN_ADDR 0xC000
1757: #define ASC_BIOS_MAX_ADDR 0xEC00
1758: #define ASC_BIOS_BANK_SIZE 0x0400
1759:
1760: #define ASC_MCODE_START_ADDR 0x0080
1761:
1762: #define ASC_CFG0_HOST_INT_ON 0x0020
1763: #define ASC_CFG0_BIOS_ON 0x0040
1764: #define ASC_CFG0_VERA_BURST_ON 0x0080
1765: #define ASC_CFG0_SCSI_PARITY_ON 0x0800
1766:
1767: #define ASC_CFG1_SCSI_TARGET_ON 0x0080
1768: #define ASC_CFG1_LRAM_8BITS_ON 0x0800
1769:
1770: #define ASC_CFG_MSW_CLR_MASK 0xF0C0
1771:
1772: #define CSW_TEST1 ( ASC_CS_TYPE )0x8000
1773: #define CSW_AUTO_CONFIG ( ASC_CS_TYPE )0x4000
1774: #define CSW_RESERVED1 ( ASC_CS_TYPE )0x2000
1775: #define CSW_IRQ_WRITTEN ( ASC_CS_TYPE )0x1000
1776: #define CSW_33MHZ_SELECTED ( ASC_CS_TYPE )0x0800
1777: #define CSW_TEST2 ( ASC_CS_TYPE )0x0400
1778: #define CSW_TEST3 ( ASC_CS_TYPE )0x0200
1779: #define CSW_RESERVED2 ( ASC_CS_TYPE )0x0100
1780: #define CSW_DMA_DONE ( ASC_CS_TYPE )0x0080
1781: #define CSW_FIFO_RDY ( ASC_CS_TYPE )0x0040
1782:
1783: #define CSW_EEP_READ_DONE ( ASC_CS_TYPE )0x0020
1784:
1785: #define CSW_HALTED ( ASC_CS_TYPE )0x0010
1786: #define CSW_SCSI_RESET_ACTIVE ( ASC_CS_TYPE )0x0008
1787:
1788: #define CSW_PARITY_ERR ( ASC_CS_TYPE )0x0004
1789: #define CSW_SCSI_RESET_LATCH ( ASC_CS_TYPE )0x0002
1790:
1791: #define CSW_INT_PENDING ( ASC_CS_TYPE )0x0001
1792:
1793: #define CIW_INT_ACK ( ASC_CS_TYPE )0x0100
1794: #define CIW_TEST1 ( ASC_CS_TYPE )0x0200
1795: #define CIW_TEST2 ( ASC_CS_TYPE )0x0400
1796: #define CIW_SEL_33MHZ ( ASC_CS_TYPE )0x0800
1797:
1798: #define CIW_IRQ_ACT ( ASC_CS_TYPE )0x1000
1799:
1800: #define CC_CHIP_RESET ( uchar )0x80
1801: #define CC_SCSI_RESET ( uchar )0x40
1802: #define CC_HALT ( uchar )0x20
1803: #define CC_SINGLE_STEP ( uchar )0x10
1804: #define CC_DMA_ABLE ( uchar )0x08
1805: #define CC_TEST ( uchar )0x04
1806: #define CC_BANK_ONE ( uchar )0x02
1807: #define CC_DIAG ( uchar )0x01
1808:
1809: #define ASC_1000_ID0W 0x04C1
1810: #define ASC_1000_ID0W_FIX 0x00C1
1811: #define ASC_1000_ID1B 0x25
1812:
1813: #define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50)
1814: #define ASC_EISA_SMALL_IOP_GAP (0x0020)
1815: #define ASC_EISA_MIN_IOP_ADDR (0x0C30)
1816: #define ASC_EISA_MAX_IOP_ADDR (0xFC50)
1817: #define ASC_EISA_REV_IOP_MASK (0x0C83)
1818: #define ASC_EISA_PID_IOP_MASK (0x0C80)
1819: #define ASC_EISA_CFG_IOP_MASK (0x0C86)
1820:
1821: #define ASC_GET_EISA_SLOT( iop ) ( PortAddr )( (iop) & 0xF000 )
1822:
1823: #define ASC_EISA_ID_740 0x01745004UL
1824: #define ASC_EISA_ID_750 0x01755004UL
1825:
1826: #define INS_HALTINT ( ushort )0x6281
1827: #define INS_HALT ( ushort )0x6280
1828: #define INS_SINT ( ushort )0x6200
1829: #define INS_RFLAG_WTM ( ushort )0x7380
1830:
1831: #define ASC_MC_SAVE_CODE_WSIZE 0x500
1832: #define ASC_MC_SAVE_DATA_WSIZE 0x40
1833:
1834: typedef struct asc_mc_saved {
1835: ushort data[ASC_MC_SAVE_DATA_WSIZE];
1836: ushort code[ASC_MC_SAVE_CODE_WSIZE];
1837: } ASC_MC_SAVED;
1838:
1839: int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1840: int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1841: void AscWaitEEPRead(void);
1842: void AscWaitEEPWrite(void);
1843: ushort AscReadEEPWord(PortAddr, uchar);
1844: ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1845: ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
1846: int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
1847: int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
1848: ushort AscEEPSum(PortAddr, uchar, uchar);
1849:
1850: int AscStartChip(PortAddr);
1851: int AscStopChip(PortAddr);
1852: void AscSetChipIH(PortAddr, ushort);
1853: int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1854:
1855: int AscIsChipHalted(PortAddr);
1856:
1857: void AscSetChipCfgDword(PortAddr, ulong);
1858: ulong AscGetChipCfgDword(PortAddr);
1859:
1860: void AscAckInterrupt(PortAddr);
1861: void AscDisableInterrupt(PortAddr);
1862: void AscEnableInterrupt(PortAddr);
1863: void AscSetBank(PortAddr, uchar);
1864: uchar AscGetBank(PortAddr);
1865: int AscResetChipAndScsiBus(PortAddr);
1866: ushort AscGetIsaDmaChannel(PortAddr);
1867: ushort AscSetIsaDmaChannel(PortAddr, ushort);
1868: uchar AscSetIsaDmaSpeed(PortAddr, uchar);
1869: uchar AscGetIsaDmaSpeed(PortAddr);
1870:
1871: uchar AscReadLramByte(PortAddr, ushort);
1872: ushort AscReadLramWord(PortAddr, ushort);
1873: ulong AscReadLramDWord(PortAddr, ushort);
1874: void AscWriteLramWord(PortAddr, ushort, ushort);
1875: void AscWriteLramDWord(PortAddr, ushort, ulong);
1876: void AscWriteLramByte(PortAddr, ushort, uchar);
1877: int AscVerWriteLramDWord(PortAddr, ushort, ulong);
1878: int AscVerWriteLramWord(PortAddr, ushort, ushort);
1879: int AscVerWriteLramByte(PortAddr, ushort, uchar);
1880:
1881: ulong AscMemSumLramWord(PortAddr, ushort, int);
1882: void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1883: void AscMemWordCopyToLram(PortAddr, ushort, ushort dosfar *, int);
1884: void AscMemDWordCopyToLram(PortAddr, ushort, ulong dosfar *, int);
1885: void AscMemWordCopyFromLram(PortAddr, ushort, ushort dosfar *, int);
1886: int AscMemWordCmpToLram(PortAddr, ushort, ushort dosfar *, int);
1887:
1888: ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1889: ulong AscLoadMicroCode(PortAddr, ushort,
1890: ushort dosfar *, ushort);
1891: ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
1892: ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
1893: ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
1894:
1895: void dosfar AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *,
1896: ASC_QDONE_INFO dosfar *);
1897: int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
1898: ushort AscTestLramEndian(PortAddr);
1899:
1900: uchar AscMsgOutSDTR(PortAddr, uchar, uchar);
1901:
1902: uchar AscCalSDTRData(uchar, uchar);
1903: void AscSetChipSDTR(PortAddr, uchar, uchar);
1904: int AscInitChipAllSynReg(ASC_DVC_VAR asc_ptr_type *, uchar);
1905: uchar AscGetSynPeriodIndex(uchar);
1906: uchar AscSynIndexToPeriod(uchar);
1907: uchar AscAllocFreeQueue(PortAddr, uchar);
1908: uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1909: int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
1910: int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
1911: int AscRiscHaltedAbortALL(ASC_DVC_VAR asc_ptr_type *);
1912: int AscHostReqRiscHalt(PortAddr);
1913: int AscStopQueueExe(PortAddr);
1914: int AscStartQueueExe(PortAddr);
1915: int AscCleanUpDiscQueue(PortAddr);
1916: int AscCleanUpBusyQueue(PortAddr);
1917: int _AscAbortTidBusyQueue(ASC_DVC_VAR asc_ptr_type *,
1918: ASC_QDONE_INFO dosfar *, uchar);
1919: int _AscAbortSrbBusyQueue(ASC_DVC_VAR asc_ptr_type *,
1920: ASC_QDONE_INFO dosfar *, ulong);
1921: int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
1922: int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
1923: ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong);
1924:
1925: int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
1926: ASC_SCSI_Q dosfar * scsiq,
1927: uchar n_q_required);
1928: int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *, uchar);
1929: int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
1930: ASC_SCSI_Q dosfar *, uchar);
1931: int AscAbortScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
1932: void AscExeScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
1933: int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1934: int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1935: ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *);
1936: int AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
1937: ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
1938: int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
1939: int _AscWaitQDone(PortAddr, ASC_SCSI_Q dosfar *);
1940:
1941: int AscEnterCritical(void);
1942: void AscLeaveCritical(int);
1943:
1944: int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
1945: uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1946: ASC_QDONE_INFO dosfar *, ulong);
1947: int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
1948: ushort AscIsrExeBusyQueue(ASC_DVC_VAR asc_ptr_type *, uchar);
1949: int AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
1950: uchar dosfar *, ulong);
1951:
1952: int AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
1953: uchar dosfar *, int);
1954: int AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *);
1955: int AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *,
1956: ASC_SCSI_REQ_Q dosfar *, uchar);
1957: int AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
1958: ASC_SCSI_REQ_Q dosfar *,
1959: uchar dosfar *);
1960:
1961: ulong dosfar *swapfarbuf4(uchar dosfar *);
1962: int PollQueueDone(ASC_DVC_VAR asc_ptr_type *,
1963: ASC_SCSI_REQ_Q dosfar *,
1964: int);
1965: int PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
1966: ASC_SCSI_REQ_Q dosfar *,
1967: ASC_CAP_INFO dosfar *);
1968: int PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
1969: uchar dosfar *, int);
1970: int PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
1971: ASC_SCSI_REQ_Q dosfar *);
1972: int PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *,
1973: ASC_SCSI_REQ_Q dosfar *);
1974: int InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
1975: ASC_SCSI_REQ_Q dosfar *);
1976: void AscDispInquiry(uchar, uchar, ASC_SCSI_INQUIRY dosfar *);
1977: int AscPollQDone(ASC_DVC_VAR asc_ptr_type *,
1978: ASC_SCSI_REQ_Q dosfar *, int);
1979:
1980: int AscSetBIOSBank(PortAddr, int, ushort);
1981: int AscSetVlBIOSBank(PortAddr, int);
1982: int AscSetEisaBIOSBank(PortAddr, int);
1983: int AscSetIsaBIOSBank(PortAddr, int);
1984:
1985: int AscIsBiosEnabled(PortAddr, ushort);
1986: void AscResetScsiBus(PortAddr);
1987: void AscClrResetScsiBus(PortAddr);
1988:
1989: void AscSingleStepChip(PortAddr);
1990: uchar AscSetChipScsiID(PortAddr, uchar);
1991: ushort AscGetChipBiosAddress(PortAddr, ushort);
1992: ushort AscSetChipBiosAddress(PortAddr, ushort, ushort);
1993: uchar AscGetChipVersion(PortAddr, ushort);
1994: ushort AscGetChipBusType(PortAddr);
1995:
1996: PortAddr AscSearchIOPortAddr11(PortAddr);
1997: PortAddr AscSearchIOPortAddr100(PortAddr);
1998: int AscFindSignature(PortAddr);
1999: void AscToggleIRQAct(PortAddr);
2000: int AscResetChip(PortAddr);
2001: void AscClrResetChip(PortAddr);
2002:
2003: short itos(ushort, uchar dosfar *, short, short);
2004: int insnchar(uchar dosfar *, short, short, ruchar, short);
2005: void itoh(ushort, ruchar dosfar *);
2006: void btoh(uchar, ruchar dosfar *);
2007: void ltoh(ulong, ruchar dosfar *);
2008: uchar dosfar *todstr(ushort, uchar dosfar *);
2009: uchar dosfar *tohstr(ushort, uchar dosfar *);
2010: uchar dosfar *tobhstr(uchar, uchar dosfar *);
2011: uchar dosfar *tolhstr(ulong, uchar dosfar *);
2012:
2013: void AscSetISAPNPWaitForKey(void);
2014: uchar AscGetChipIRQ(PortAddr, ushort);
2015: uchar AscSetChipIRQ(PortAddr, uchar, ushort);
2016: uchar AscGetChipScsiCtrl(PortAddr);
2017:
2018: ushort AscGetEisaChipCfg(PortAddr);
2019: ushort AscGetEisaChipGpReg(PortAddr);
2020: ushort AscSetEisaChipCfg(PortAddr, ushort);
2021: ushort AscSetEisaChipGpReg(PortAddr, ushort);
2022:
2023: ulong AscGetEisaProductID(PortAddr);
2024: PortAddr AscSearchIOPortAddrEISA(PortAddr);
2025:
2026: int AscPollQTailSync(PortAddr);
2027: int AscPollQHeadSync(PortAddr);
2028: int AscWaitQTailSync(PortAddr);
2029:
2030: int _AscRestoreMicroCode(PortAddr, ASC_MC_SAVED dosfar *);
2031:
2032: int AscSCAM(ASC_DVC_VAR asc_ptr_type *);
2033:
2034: ushort SwapByteOfWord(ushort word_val);
2035: ulong SwapWordOfDWord(ulong dword_val);
2036: ulong AdjEndianDword(ulong dword_val);
2037:
2038: int AscAdjEndianScsiQ(ASC_SCSI_Q dosfar *);
2039: int AscAdjEndianQDoneInfo(ASC_QDONE_INFO dosfar *);
2040:
2041: extern int DvcEnterCritical(void);
2042: extern void DvcLeaveCritical(int);
2043:
2044: extern void DvcInPortWords(PortAddr, ushort dosfar *, int);
2045: extern void DvcOutPortWords(PortAddr, ushort dosfar *, int);
2046: extern void DvcOutPortDWords(PortAddr, ulong dosfar *, int);
2047:
2048: extern void DvcSleepMilliSecond(ulong);
2049: extern void DvcDisplayString(uchar dosfar *);
2050: extern ulong DvcGetPhyAddr(uchar dosfar * buf_addr, ulong buf_len);
2051: extern ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong,
2052: ASC_SG_HEAD dosfar *);
2053:
2054: extern void DvcSCAMDelayMS(ulong);
2055: extern int DvcDisableCPUInterrupt(void);
2056: extern void DvcRestoreCPUInterrupt(int);
2057:
2058: void DvcPutScsiQ(PortAddr, ushort, ushort dosfar *, int);
2059: void DvcGetQinfo(PortAddr, ushort, ushort dosfar *, int);
2060:
2061: PortAddr AscSearchIOPortAddr(PortAddr, ushort);
2062: ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
2063: ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
2064: ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
2065: int AscInitScsiTarget(ASC_DVC_VAR asc_ptr_type *,
2066: ASC_DVC_INQ_INFO dosfar *,
2067: uchar dosfar *,
2068: ASC_CAP_INFO_ARRAY dosfar *,
2069: ushort);
2070: int AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *);
2071: int AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *);
2072: int AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *,
2073: ASC_SCSI_REQ_Q dosfar *,
2074: ASC_SCSI_INQUIRY dosfar *,
2075: ASC_CAP_INFO dosfar *);
2076: int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
2077:
2078: int AscISR(ASC_DVC_VAR asc_ptr_type *);
2079: void AscISR_AckInterrupt(ASC_DVC_VAR asc_ptr_type *);
2080: int AscISR_CheckQDone(ASC_DVC_VAR asc_ptr_type *,
2081: ASC_QDONE_INFO dosfar *,
2082: uchar dosfar *);
2083:
2084: int AscStartUnit(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_TIX_TYPE);
2085: int AscStopUnit(
2086: ASC_DVC_VAR asc_ptr_type * asc_dvc,
2087: ASC_SCSI_TIX_TYPE target_ix
2088: );
2089:
2090: uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
2091: int AscSgListToQueue(int);
2092: int AscQueueToSgList(int);
2093: int AscSetDvcErrorCode(ASC_DVC_VAR asc_ptr_type *, uchar);
2094:
2095: int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
2096: int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
2097: int AscResetSB(ASC_DVC_VAR asc_ptr_type *);
2098:
2099: void AscEnableIsaDma(uchar);
2100: void AscDisableIsaDma(uchar);
2101:
2102: ulong AscGetMaxDmaAddress(ushort);
2103: ulong AscGetMaxDmaCount(ushort);
2104:
2105: int AscSaveMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
2106: int AscRestoreOldMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
2107: int AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
2108:
2109: /*
2110: * --- Debugging Header
2111: */
2112:
2113: #ifdef ADVANSYS_DEBUG
2114: #define STATIC
2115: #else /* ADVANSYS_DEBUG */
2116: #define STATIC static
2117: #endif /* ADVANSYS_DEBUG */
2118:
2119:
2120: /*
2121: * --- Driver Constants and Macros
2122: */
2123:
2124: #define ASC_NUM_BOARD_SUPPORTED 4
2125: #define ASC_NUM_BUS 4
2126:
2127: /* Reference Scsi_Host hostdata */
2128: #define ASC_BOARD(host) ((struct asc_board *) &(host)->hostdata)
2129:
2130: #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
2131:
2132: #ifndef min
2133: #define min(a, b) (((a) < (b)) ? (a) : (b))
2134: #endif /* min */
2135:
2136: /* Asc Library return codes */
2137: #define ASC_TRUE 1
2138: #define ASC_FALSE 0
2139: #define ASC_NOERROR 1
2140: #define ASC_BUSY 0
2141: #define ASC_ERROR (-1)
2142:
2143: /* Scsi_Cmnd function return codes */
2144: #define STATUS_BYTE(byte) (byte)
2145: #define MSG_BYTE(byte) ((byte) << 8)
2146: #define HOST_BYTE(byte) ((byte) << 16)
2147: #define DRIVER_BYTE(byte) ((byte) << 24)
2148:
2149: /* asc_enqueue() flags */
2150: #define ASC_FRONT 1
2151: #define ASC_BACK 2
2152:
2153: /* PCI configuration declarations */
2154:
2155: #define ASC_PCI_REV_A_INIT 0x01
2156: #define ASC_PCI_REV_A_DONE 0x02
2157: #define ASC_PCI_REV_B_INIT 0x04
2158: #define ASC_PCI_REV_B_DONE 0x08
2159:
2160: #define PCI_BASE_CLASS_PREDEFINED 0x00
2161: #define PCI_BASE_CLASS_MASS_STORAGE 0x01
2162: #define PCI_BASE_CLASS_NETWORK 0x02
2163: #define PCI_BASE_CLASS_DISPLAY 0x03
2164: #define PCI_BASE_CLASS_MULTIMEDIA 0x04
2165: #define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05
2166: #define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06
2167:
2168: /* MASS STORAGE */
2169: #define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00
2170: #define PCI_SUB_CLASS_IDE_CONTROLLER 0x01
2171: #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02
2172: #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03
2173: #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80
2174:
2175: /* NETWORK CONTROLLER */
2176: #define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00
2177: #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01
2178: #define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02
2179: #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80
2180:
2181: /* DISPLAY CONTROLLER */
2182: #define PCI_SUB_CLASS_VGA_CONTROLLER 0x00
2183: #define PCI_SUB_CLASS_XGA_CONTROLLER 0x01
2184: #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80
2185:
2186: /* MULTIMEDIA CONTROLLER */
2187: #define PCI_SUB_CLASS_VIDEO_DEVICE 0x00
2188: #define PCI_SUB_CLASS_AUDIO_DEVICE 0x01
2189: #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80
2190:
2191: /* MEMORY CONTROLLER */
2192: #define PCI_SUB_CLASS_RAM_CONTROLLER 0x00
2193: #define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01
2194: #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80
2195:
2196: /* BRIDGE CONTROLLER */
2197: #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00
2198: #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01
2199: #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02
2200: #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03
2201: #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04
2202: #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05
2203: #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80
2204:
2205: #define PCI_MAX_SLOT 0x1F
2206: #define PCI_MAX_BUS 0xFF
2207: #define ASC_PCI_VENDORID 0x10CD
2208: #define PCI_IOADDRESS_MASK 0xFFFE
2209:
2210: /* PCI IO Port Addresses to generate special cycle */
2211:
2212: #define PCI_CONFIG_ADDRESS_MECH1 0x0CF8
2213: #define PCI_CONFIG_DATA_MECH1 0x0CFC
2214:
2215: #define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */
2216:
2217: #define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000
2218: #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00
2219: #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8
2220:
2221: #define PCI_DEVICE_FOUND 0x0000
2222: #define PCI_DEVICE_NOT_FOUND 0xffff
2223:
2224: #define SUBCLASS_OFFSET 0x0A
2225: #define CLASSCODE_OFFSET 0x0B
2226: #define VENDORID_OFFSET 0x00
2227: #define DEVICEID_OFFSET 0x02
2228:
2229: /*
2230: * --- Driver Macros
2231: */
2232:
2233: #ifndef ADVANSYS_STATS
2234: #define ASC_STATS(counter)
2235: #define ASC_STATS_ADD(counter, count)
2236: #else /* ADVANSYS_STATS */
2237: #define ASC_STATS(counter) asc_stats.counter++
2238: #define ASC_STATS_ADD(counter, count) asc_stats.counter += (count)
2239: #endif /* ADVANSYS_STATS */
2240:
2241: #ifndef ADVANSYS_DEBUG
2242:
2243: #define ASC_DBG(lvl, s)
2244: #define ASC_DBG1(lvl, s, a1)
2245: #define ASC_DBG2(lvl, s, a1, a2)
2246: #define ASC_DBG3(lvl, s, a1, a2, a3)
2247: #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2248: #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2249: #define ASC_DBG_PRT_DVC_VAR(lvl, v)
2250: #define ASC_DBG_PRT_DVC_CFG(lvl, c)
2251: #define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp)
2252: #define ASC_DBG_PRT_QDONE_INFO(lvl, qdone)
2253: #define ASC_DBG_PRT_HEX(lvl, name, start, length)
2254: #define ASC_DBG_PRT_CDB(lvl, cdb, len)
2255: #define ASC_DBG_PRT_SENSE(lvl, sense, len)
2256: #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2257: #define ASC_ASSERT(a)
2258:
2259: #else /* ADVANSYS_DEBUG */
2260:
2261: /*
2262: * Debugging Message Levels:
2263: * 0: Errors Only
2264: * 1: High-Level Tracing
2265: * 2-N: Verbose Tracing
2266: */
2267:
2268: #define ASC_DBG(lvl, s) \
2269: { \
2270: if (asc_dbglvl >= (lvl)) { \
2271: printk(s); \
2272: } \
2273: }
2274:
2275: #define ASC_DBG1(lvl, s, a1) \
2276: { \
2277: if (asc_dbglvl >= (lvl)) { \
2278: printk((s), (a1)); \
2279: } \
2280: }
2281:
2282: #define ASC_DBG2(lvl, s, a1, a2) \
2283: { \
2284: if (asc_dbglvl >= (lvl)) { \
2285: printk((s), (a1), (a2)); \
2286: } \
2287: }
2288:
2289: #define ASC_DBG3(lvl, s, a1, a2, a3) \
2290: { \
2291: if (asc_dbglvl >= (lvl)) { \
2292: printk((s), (a1), (a2), (a3)); \
2293: } \
2294: }
2295:
2296: #define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2297: { \
2298: if (asc_dbglvl >= (lvl)) { \
2299: printk((s), (a1), (a2), (a3), (a4)); \
2300: } \
2301: }
2302:
2303: #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2304: { \
2305: if (asc_dbglvl >= (lvl)) { \
2306: asc_prt_scsi_host(s); \
2307: } \
2308: }
2309:
2310: #define ASC_DBG_PRT_DVC_VAR(lvl, v) \
2311: { \
2312: if (asc_dbglvl >= (lvl)) { \
2313: asc_prt_dvc_var(v); \
2314: } \
2315: }
2316:
2317: #define ASC_DBG_PRT_DVC_CFG(lvl, c) \
2318: { \
2319: if (asc_dbglvl >= (lvl)) { \
2320: asc_prt_dvc_cfg(c); \
2321: } \
2322: }
2323:
2324: #define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \
2325: { \
2326: if (asc_dbglvl >= (lvl)) { \
2327: asc_prt_scsi_q(scsiqp); \
2328: } \
2329: }
2330:
2331: #define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \
2332: { \
2333: if (asc_dbglvl >= (lvl)) { \
2334: asc_prt_qdone_info(qdone); \
2335: } \
2336: }
2337:
2338: #define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2339: { \
2340: if (asc_dbglvl >= (lvl)) { \
2341: asc_prt_hex((name), (start), (length)); \
2342: } \
2343: }
2344:
2345: #define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2346: ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2347:
2348: #define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2349: ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2350:
2351: #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2352: ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2353:
2354: #define ASC_ASSERT(a) \
2355: { \
2356: if (!(a)) { \
2357: printk("ASC_ASSERT() Failure: file %s, line %d\n", \
2358: __FILE__, __LINE__); \
2359: } \
2360: }
2361: #endif /* ADVANSYS_DEBUG */
2362:
2363:
2364: /*
2365: * --- Driver Structures
2366: */
2367:
2368: /*
2369: * Structure allocated for each board.
2370: *
2371: * This structure is allocated by scsi_register() at the end
2372: * of the 'Scsi_Host' structure starting at the 'hostdata'
2373: * field. It is guaranteed to be allocated from DMA-able memory.
2374: */
2375: struct asc_board {
2376: /* Asc Library */
2377: ASC_DVC_VAR board; /* Board configuration */
2378: ASC_DVC_CFG cfg; /* Device configuration */
2379: uchar overrun_buf[ASC_OVERRUN_BSIZE];
2380: /* Queued Commands */
2381: ASC_SCSI_BIT_ID_TYPE pending_tidmask; /* Pending command mask */
2382: Scsi_Cmnd *pending[ASC_MAX_TID];
2383: /* Target Initialization */
2384: ASC_SCSI_BIT_ID_TYPE init_tidmask; /* Target initialized mask */
2385: ASC_SCSI_REQ_Q scsireqq;
2386: ASC_CAP_INFO cap_info;
2387: ASC_SCSI_INQUIRY inquiry;
2388: };
2389:
2390: /*
2391: * PCI configuration structures
2392: */
2393: typedef struct _PCI_DATA_
2394: {
2395: uchar type;
2396: uchar bus;
2397: uchar slot;
2398: uchar func;
2399: uchar offset;
2400: } PCI_DATA;
2401:
2402: typedef struct _PCI_DEVICE_
2403: {
2404: ushort vendorID;
2405: ushort deviceID;
2406: ushort slotNumber;
2407: ushort slotFound;
2408: uchar busNumber;
2409: uchar maxBusNumber;
2410: uchar devFunc;
2411: ushort startSlot;
2412: ushort endSlot;
2413: uchar bridge;
2414: uchar type;
2415: } PCI_DEVICE;
2416:
2417: typedef struct _PCI_CONFIG_SPACE_
2418: {
2419: ushort vendorID;
2420: ushort deviceID;
2421: ushort command;
2422: ushort status;
2423: uchar revision;
2424: uchar classCode[3];
2425: uchar cacheSize;
2426: uchar latencyTimer;
2427: uchar headerType;
2428: uchar bist;
2429: ulong baseAddress[6];
2430: ushort reserved[4];
2431: ulong optionRomAddr;
2432: ushort reserved2[4];
2433: uchar irqLine;
2434: uchar irqPin;
2435: uchar minGnt;
2436: uchar maxLatency;
2437: } PCI_CONFIG_SPACE;
2438:
2439: #ifdef ADVANSYS_STATS
2440: struct asc_stats {
2441: ulong command; /* # calls to advansys_command() */
2442: ulong queuecommand; /* # calls to advansys_queuecommand() */
2443: ulong abort; /* # calls to advansys_abort() */
2444: ulong reset; /* # calls to advansys_reset() */
2445: ulong biosparam; /* # calls to advansys_biosparam() */
2446: ulong interrupt; /* # calls to advansys_interrupt() */
2447: ulong callback; /* # calls asc_isr_callback() */
2448: ulong cont_cnt; /* # non-scatter-gather I/O requests received */
2449: ulong cont_xfer; /* contiguous transfer total (512 byte units) */
2450: ulong sg_cnt; /* # scatter-gather I/O requests received */
2451: ulong sg_elem; /* scatter-gather element total */
2452: ulong sg_xfer; /* scatter-gather tranfer total (512 byte units) */
2453: ulong error; /* # AscExeScsiQueue() ASC_ERROR returns. */
2454: /*
2455: * Number of times interrupts disabled in advansys_queuecommand() and
2456: * asc_isr_callback(), respectively. For the former indicates how many
2457: * times commands were pending when a new command was received.
2458: */
2459: ulong cmd_disable;
2460: ulong intr_disable;
2461: /*
2462: * Number of times asc_enqueue() called. Indicates how many ASC_BUSY
2463: * returns have occurred.
2464: */
2465: ulong enqueue;
2466: ulong dequeue; /* # calls to asc_dequeue(). */
2467: /*
2468: * Number of times asc_rmqueue() called and the specified command
2469: * was found and removed.
2470: */
2471: ulong rmqueue;
2472: } asc_stats;
2473: #endif /* ADVANSYS_STATS */
2474:
2475:
2476: /*
2477: * --- Driver Data
2478: */
2479:
2480: #ifdef LINUX_1_3
2481: struct proc_dir_entry proc_scsi_advansys =
2482: {
2483: PROC_SCSI_ADVANSYS, /* unsigned short low_ino */
2484: 8, /* unsigned short namelen */
2485: "advansys", /* const char *name */
2486: S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */
2487: 2 /* nlink_t nlink */
2488: };
2489: #endif /* LINUX_1_3 */
2490:
2491: STATIC int asc_board_count; /* Number of boards detected in system. */
2492: STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED];
2493: STATIC Scsi_Cmnd *asc_scsi_done; /* Commands needing done function call. */
2494:
2495: STATIC ushort asc_bus[ASC_NUM_BUS] = {
2496: ASC_IS_ISA,
2497: ASC_IS_VL,
2498: ASC_IS_EISA,
2499: ASC_IS_PCI,
2500: };
2501:
2502: /*
2503: * Used with the LILO 'advansys' option to eliminate or
2504: * limit I/O port probing at boot time, cf. advansys_setup().
2505: */
2506: int asc_iopflag = ASC_FALSE;
2507: int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 };
2508:
2509: #ifdef ADVANSYS_DEBUG
2510: char *
2511: asc_bus_name[ASC_NUM_BUS] = {
2512: "ASC_IS_ISA",
2513: "ASC_IS_VL",
2514: "ASC_IS_EISA",
2515: "ASC_IS_PCI",
2516: };
2517:
2518: int asc_dbglvl = 0;
2519: #endif /* ADVANSYS_DEBUG */
2520:
2521:
2522: /*
2523: * --- Driver Function Prototypes
2524: *
2525: * advansys.h contains function prototypes for functions global to Linux.
2526: */
2527:
2528: #ifdef LINUX_1_3
2529: STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int);
2530: #endif /* LINUX_1_3 */
2531: STATIC void advansys_interrupt(int, struct pt_regs *);
2532: STATIC void advansys_command_done(Scsi_Cmnd *);
2533: STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
2534: STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
2535: STATIC void asc_execute_pending(struct Scsi_Host *);
2536: STATIC int asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
2537: STATIC int asc_srch_pci_dev(PCI_DEVICE *);
2538: STATIC uchar asc_scan_method(PCI_DEVICE *);
2539: STATIC int asc_pci_find_dev(PCI_DEVICE *);
2540: STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
2541: STATIC ushort asc_get_cfg_word(PCI_DATA *);
2542: STATIC uchar asc_get_cfg_byte(PCI_DATA *);
2543: STATIC void asc_enqueue(struct Scsi_Host *, Scsi_Cmnd *, int, int);
2544: STATIC Scsi_Cmnd *asc_dequeue(struct Scsi_Host *, int);
2545: STATIC int asc_rmqueue(struct Scsi_Host *, Scsi_Cmnd *, int);
2546:
2547: /* XXX - Asc Library Routines not supposed to be used directly */
2548: ushort AscGetChipBiosAddress(PortAddr, ushort);
2549: int AscFindSignature(PortAddr);
2550:
2551: #ifdef ADVANSYS_STATS
2552: STATIC int asc_prt_stats(char *, int);
2553: STATIC int asc_prt_stats_line(char *, int, char *fmt, ...);
2554: #endif /* ADVANSYS_STATS */
2555: #ifdef ADVANSYS_DEBUG
2556: STATIC void asc_prt_scsi_host(struct Scsi_Host *);
2557: STATIC void asc_prt_dvc_cfg(ASC_DVC_CFG *);
2558: STATIC void asc_prt_dvc_var(ASC_DVC_VAR *);
2559: STATIC void asc_prt_scsi_q(ASC_SCSI_Q *);
2560: STATIC void asc_prt_qdone_info(ASC_QDONE_INFO *);
2561: STATIC void asc_prt_hex(char *f, uchar *, int);
2562: STATIC int interrupts_enabled(void);
2563: #endif /* ADVANSYS_DEBUG */
2564:
2565:
2566: /*
2567: * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
2568: */
2569:
2570: #ifdef LINUX_1_3
2571: /*
2572: * advansys_proc_info() - /proc/scsi/advansys/[0-ASC_NUM_BOARD_SUPPORTED]
2573: *
2574: * *buffer: I/O buffer
2575: * **start: if inout == FALSE pointer into buffer where user read should start
2576: * offset: current offset into /proc/scsi/advansys file
2577: * length: length of buffer
2578: * hostno: Scsi_Host host_no
2579: * inout: TRUE - user is writing; FALSE - user is reading
2580: *
2581: * Return the number of bytes read from or written to
2582: * /proc/scsi/advansys file.
2583: */
2584: int
2585: advansys_proc_info(char *buffer, char **start, off_t offset, int length,
2586: int hostno, int inout)
2587: {
2588: struct Scsi_Host *shp;
2589: int i;
2590: char *cp;
2591: int cplen;
2592: int cnt;
2593: int totcnt;
2594: int leftlen;
2595: char *curbuf;
2596: off_t advoffset;
2597: Scsi_Device *scd;
2598: char prtbuf[480]; /* 6 lines */
2599:
2600: ASC_DBG(1, "advansys_proc_info: begin\n");
2601:
2602: /*
2603: * User write not supported.
2604: */
2605: if (inout == TRUE) {
2606: return(-ENOSYS);
2607: }
2608:
2609: /*
2610: * User read of /proc/scsi/advansys file.
2611: */
2612:
2613: /* Find the specified board. */
2614: for (i = 0; i < asc_board_count; i++) {
2615: if (asc_host[i]->host_no == hostno) {
2616: break;
2617: }
2618: }
2619: if (i == asc_board_count) {
2620: return(-ENOENT);
2621: }
2622: shp = asc_host[i];
2623:
2624: /* Always copy read data to the beginning of the buffer. */
2625: *start = buffer;
2626:
2627: curbuf = buffer;
2628: advoffset = 0;
2629: totcnt = 0;
2630: leftlen = length;
2631:
2632: /* Get board information. */
2633: cp = (char *) advansys_info(shp);
2634: strcat(cp, "\n");
2635: cplen = strlen(cp);
2636:
2637: /* Copy board information. */
2638: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2639: totcnt += cnt;
2640: leftlen -= cnt;
2641: if (leftlen == 0) {
2642: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2643: return totcnt;
2644: }
2645: advoffset += cplen;
2646: curbuf += cnt;
2647:
2648: /*
2649: * Get and copy information for each device attached to the board.
2650: */
2651: cp = &prtbuf[0];
2652: sprintf(cp, "\nDevices attached to SCSI Host %d:\n", shp->host_no);
2653: cplen = strlen(cp);
2654: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2655: totcnt += cnt;
2656: leftlen -= cnt;
2657: if (leftlen == 0) {
2658: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2659: return totcnt;
2660: }
2661: advoffset += cplen;
2662: curbuf += cnt;
2663:
2664: cp = &prtbuf[0];
2665: for (scd = scsi_devices; scd; scd = scd->next) {
2666: if (scd->host == shp) {
2667: proc_print_scsidevice(scd, cp, &cplen, 0);
2668: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2669: totcnt += cnt;
2670: leftlen -= cnt;
2671: if (leftlen == 0) {
2672: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2673: return totcnt;
2674: }
2675: advoffset += cplen;
2676: curbuf += cnt;
2677: }
2678: }
2679:
2680: #ifdef ADVANSYS_STATS
2681: /*
2682: * prtbuf[] has about 6 lines worth of space. If the statistics ever
2683: * get longer than 6 lines, prtbuf[] should be increased in size. If
2684: * prtbuf[] is too small it will not be overwritten. Instead the user
2685: * just won't get all of the available statistics.
2686: */
2687: cp = &prtbuf[0];
2688: cplen = asc_prt_stats(cp, sizeof(prtbuf));
2689: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2690: totcnt += cnt;
2691: leftlen -= cnt;
2692: if (leftlen == 0) {
2693: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2694: return totcnt;
2695: }
2696: advoffset += cplen;
2697: curbuf += cnt;
2698: #endif /* ADVANSYS_STATS */
2699:
2700: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2701:
2702: return totcnt;
2703: }
2704: #endif /* LINUX_1_3 */
2705:
2706:
2707: /*
2708: * advansys_detect()
2709: *
2710: * Detect function for AdvanSys adapters.
2711: *
2712: * Argument is a pointer to the host driver's scsi_hosts entry.
2713: *
2714: * Return number of adapters found.
2715: *
2716: * Note: Because this function is called during system initialization
2717: * it must not call SCSI mid-level functions including scsi_malloc()
2718: * and scsi_free().
2719: */
2720: int
2721: advansys_detect(Scsi_Host_Template *tpnt)
2722: {
2723: static int detect_called = ASC_FALSE;
2724: int iop;
2725: int bus;
2726: struct Scsi_Host *shp;
2727: ASC_DVC_VAR *boardp;
2728: int ioport = 0;
2729: PCI_DEVICE pciDevice;
2730: PCI_CONFIG_SPACE pciConfig;
2731: int ret;
2732: extern PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX];
2733:
2734:
2735: if (detect_called == ASC_FALSE) {
2736: detect_called = ASC_TRUE;
2737: } else {
2738: printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n");
2739: return 0;
2740: }
2741:
2742: ASC_DBG(1, "advansys_detect: begin\n");
2743:
2744: #ifdef LINUX_1_3
2745: tpnt->proc_dir = &proc_scsi_advansys;
2746: #endif /* LINUX_1_3 */
2747:
2748: #ifdef ADVANSYS_STATS
2749: memset(&asc_stats, 0, sizeof(asc_stats));
2750: #endif /* ADVANSYS_STATS */
2751:
2752: asc_board_count = 0;
2753:
2754: /*
2755: * If I/O port probing has been modified, then verify and
2756: * clean-up the 'asc_ioport' list.
2757: */
2758: if (asc_iopflag == ASC_TRUE) {
2759: for (ioport = 0; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
2760: ASC_DBG2(1, "asdvansys_detect: asc_ioport[%d] %x\n",
2761: ioport, asc_ioport[ioport]);
2762: if (asc_ioport[ioport] != 0) {
2763: for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
2764: if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
2765: break;
2766: }
2767: }
2768: if (iop == ASC_IOADR_TABLE_MAX_IX) {
2769: printk("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
2770: asc_ioport[ioport]);
2771: asc_ioport[ioport] = 0;
2772: }
2773: }
2774: }
2775: ioport = 0;
2776: }
2777:
2778: memset(&pciDevice, 0, sizeof(PCI_DEVICE));
2779: memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
2780: pciDevice.maxBusNumber = PCI_MAX_BUS;
2781: pciDevice.endSlot = PCI_MAX_SLOT;
2782:
2783: for (bus = 0; bus < ASC_NUM_BUS; bus++) {
2784:
2785: ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
2786: bus, asc_bus_name[bus]);
2787: iop = 0;
2788:
2789: while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
2790:
2791: ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
2792: asc_board_count);
2793:
2794: switch (asc_bus[bus]) {
2795: case ASC_IS_ISA:
2796: case ASC_IS_VL:
2797: if (asc_iopflag == ASC_FALSE) {
2798: iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
2799: } else {
2800: /*
2801: * ISA and VL I/O port scanning has either been
2802: * eliminated or limited to selected ports on
2803: * the LILO command line, /etc/lilo.conf, or
2804: * by setting variables when the module was loaded.
2805: */
2806: ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
2807: ioport_try_again:
2808: iop = 0;
2809: for (; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
2810: if ((iop = asc_ioport[ioport]) != 0) {
2811: break;
2812: }
2813: }
2814: if (iop) {
2815: ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
2816: iop);
2817: if (check_region(iop, ASC_IOADR_GAP) != 0) {
2818: printk("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
2819: /* Don't try this I/O port twice. */
2820: asc_ioport[ioport] = 0;
2821: goto ioport_try_again;
2822: } else if (AscFindSignature(iop) == ASC_FALSE) {
2823: printk("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
2824: /* Don't try this I/O port twice. */
2825: asc_ioport[ioport] = 0;
2826: goto ioport_try_again;
2827: } else {
2828: /*
2829: * If this isn't an ISA board, then it must be
2830: * a VL board. If currently looking an ISA
2831: * board is being looked for then try for
2832: * another ISA board in 'asc_ioport'.
2833: */
2834: if (asc_bus[bus] == ASC_IS_ISA &&
2835: (AscGetChipVersion(iop, ASC_IS_ISA) &
2836: ASC_CHIP_VER_ISA_BIT) == 0) {
2837: /*
2838: * Don't clear 'asc_ioport[ioport]'. Try
2839: * this board again for VL. Increment
2840: * 'ioport' past this board.
2841: */
2842: ioport++;
2843: goto ioport_try_again;
2844: }
2845: }
2846: /*
2847: * This board appears good, don't try the I/O port
2848: * again by clearing its value. Increment 'ioport'
2849: * for the next iteration.
2850: */
2851: asc_ioport[ioport++] = 0;
2852: }
2853: }
2854: break;
2855:
2856: case ASC_IS_EISA:
2857: iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
2858: break;
2859:
2860: case ASC_IS_PCI:
2861: if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
2862: iop = 0;
2863: } else {
2864: ASC_DBG2(2,
2865: "advansys_detect: slotFound %d, busNumber %d\n",
2866: pciDevice.slotFound, pciDevice.busNumber);
2867: asc_get_pci_cfg(&pciDevice, &pciConfig);
2868: iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
2869: ASC_DBG2(2, "advansys_detect: iop %x, irqLine %d\n",
2870: iop, pciConfig.irqLine);
2871: }
2872: break;
2873:
2874: default:
2875: ASC_DBG(0, "advansys_detect: unknown bus type\n");
2876: break;
2877: }
2878: ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
2879:
2880: /*
2881: * Adapter not found, try next bus type.
2882: */
2883: if (iop == 0) {
2884: break;
2885: }
2886:
2887: /*
2888: * Adapter found.
2889: *
2890: * Register the adapter, get its configuration, and
2891: * initialize it.
2892: */
2893: ASC_DBG(2, "advansys_detect: scsi_register()\n");
2894: shp = scsi_register(tpnt, sizeof(struct asc_board));
2895:
2896: /* Save a pointer to the Scsi_host of each found board. */
2897: asc_host[asc_board_count++] = shp;
2898:
2899: /* Initialize private per board data */
2900: memset(ASC_BOARD(shp), 0, sizeof(struct asc_board));
2901: boardp = &ASC_BOARD(shp)->board;
2902: boardp->cfg = &ASC_BOARD(shp)->cfg;
2903: boardp->cfg->overrun_buf = &ASC_BOARD(shp)->overrun_buf[0];
2904: boardp->iop_base = iop;
2905:
2906: /*
2907: * Set the board bus type and PCI IRQ for AscInitGetConfig().
2908: */
2909: boardp->bus_type = asc_bus[bus];
2910: switch (boardp->bus_type) {
2911: case ASC_IS_ISA:
2912: shp->unchecked_isa_dma = TRUE;
2913: break;
2914: case ASC_IS_EISA:
2915: shp->unchecked_isa_dma = FALSE;
2916: break;
2917: case ASC_IS_VL:
2918: shp->unchecked_isa_dma = FALSE;
2919: break;
2920: case ASC_IS_PCI:
2921: shp->irq = boardp->irq_no = pciConfig.irqLine;
2922: boardp->cfg->pci_device_id = pciConfig.deviceID;
2923: shp->unchecked_isa_dma = FALSE;
2924: break;
2925: default:
2926: ASC_DBG(0, "advansys_detect: unknown adapter type");
2927: shp->unchecked_isa_dma = TRUE;
2928: break;
2929: }
2930:
2931: /*
2932: * Get the board configuration. AscInitGetConfig() may change
2933: * the board's bus_type value. The asc_bus[bus] value should no
2934: * longer be used.
2935: */
2936: ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
2937: switch(ret = AscInitGetConfig(boardp)) {
2938: case 0: /* No error */
2939: break;
2940: case ASC_WARN_IO_PORT_ROTATE:
2941: ASC_DBG(0, "AscInitGetConfig: I/O port address modified\n");
2942: break;
2943: case ASC_WARN_EEPROM_CHKSUM:
2944: ASC_DBG(0, "AscInitGetConfig: EEPROM checksum error\n");
2945: break;
2946: case ASC_WARN_IRQ_MODIFIED:
2947: ASC_DBG(0, "AscInitGetConfig: IRQ modified\n");
2948: break;
2949: case ASC_WARN_CMD_QNG_CONFLICT:
2950: ASC_DBG(0,
2951: "AscInitGetConfig: Tag queuing enabled w/o disconnects\n");
2952: break;
2953: default:
2954: ASC_DBG1(0, "AscInitGetConfig: Unknown warning: %x\n", ret);
2955: break;
2956: }
2957: if (boardp->err_code != 0) {
2958: ASC_DBG2(0,
2959: "AscInitGetConfig: error: init_state %x, err_code %x\n",
2960: boardp->init_state, boardp->err_code);
2961: scsi_unregister(shp);
2962: asc_board_count--;
2963: continue;
2964: }
2965:
2966: /*
2967: * Modify board configuration.
2968: */
2969: boardp->isr_callback = (Ptr2Func) asc_isr_callback;
2970: boardp->exe_callback = (Ptr2Func) NULL;
2971:
2972: ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
2973: switch (ret = AscInitSetConfig(boardp)) {
2974: case 0: /* No error. */
2975: break;
2976: case ASC_WARN_IO_PORT_ROTATE:
2977: ASC_DBG(0, "AscInitSetConfig: I/O port address modified\n");
2978: break;
2979: case ASC_WARN_EEPROM_CHKSUM:
2980: ASC_DBG(0, "AscInitSetConfig: EEPROM checksum error\n");
2981: break;
2982: case ASC_WARN_IRQ_MODIFIED:
2983: ASC_DBG(0, "AscInitSetConfig: IRQ modified\n");
2984: break;
2985: case ASC_WARN_CMD_QNG_CONFLICT:
2986: ASC_DBG(0, "AscInitSetConfig: Tag queuing w/o disconnects\n");
2987: break;
2988: default:
2989: ASC_DBG1(0, "AscInitSetConfig: Unknown warning: %x\n", ret);
2990: break;
2991: }
2992: if (boardp->err_code != 0) {
2993: ASC_DBG2(0,
2994: "AscInitSetConfig: error: init_state %x, err_code %x\n",
2995: boardp->init_state, boardp->err_code);
2996: scsi_unregister(shp);
2997: asc_board_count--;
2998: continue;
2999: }
3000:
3001: /*
3002: * Finish initializing the 'Scsi_Host' structure.
3003: */
3004:
3005: /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
3006: if (boardp->bus_type != ASC_IS_PCI) {
3007: shp->irq = boardp->irq_no;
3008: }
3009:
3010: shp->io_port = boardp->iop_base;
3011: shp->n_io_port = ASC_IOADR_GAP;
3012: shp->this_id = boardp->cfg->chip_scsi_id;
3013:
3014: /* Maximum number of queues this adapter can handle. */
3015: shp->can_queue = boardp->max_total_qng;
3016:
3017: /*
3018: * XXX - Command queuing limits are maintained per target
3019: * by AdvanSys adapters. Set 'cmd_per_lun' to the minimum
3020: * value of the all the target settings for the adapter.
3021: *
3022: * For now set 'cmd_per_lun' to 'max_total_qng'. This
3023: * value should be adjusted every time a new device is
3024: * found in asc_init_dev().
3025: *
3026: * XXX - memory allocation is done by the mid-level scsi
3027: * driver based on 'cmd_per_lun'. If 'sg_tablesize' is too large
3028: * allocation failures can occur in scsi_register_host().
3029: * A 'Scsi_Cmnd' structure is pre-allocated for each command
3030: * also DMA memory is reserved. Set it artificially low for now.
3031: *
3032: * shp->cmd_per_lun = boardp->max_total_qng;
3033: */
3034: #ifdef MODULE
3035: shp->cmd_per_lun = 1;
3036: #else /* MODULE */
3037: shp->cmd_per_lun = 4;
3038: #endif /* MODULE */
3039: ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
3040:
3041: /* Maximum number of scatter-gather elements adapter can handle. */
3042: /*
3043: * XXX - memory allocation is done by the mid-level scsi
3044: * driver based on sg_tablesize. If 'sg_tablesize' is too large
3045: * allocation failures can occur in scsi_register_host().
3046: */
3047: #ifdef MODULE
3048: shp->sg_tablesize = 8;
3049: #else /* MODULE */
3050: shp->sg_tablesize = ASC_MAX_SG_LIST;
3051: #endif /* MODULE */
3052: ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
3053: shp->sg_tablesize);
3054:
3055: /* BIOS start address. */
3056: shp->base = (char *) ((ulong) AscGetChipBiosAddress(
3057: boardp->iop_base,
3058: boardp->bus_type));
3059:
3060: /*
3061: * Register Board Resources - I/O Port, DMA, IRQ
3062: */
3063:
3064: /* Register I/O port range */
3065: ASC_DBG(2, "advansys_detect: request_region()\n");
3066: request_region(shp->io_port, shp->n_io_port, "advansys");
3067:
3068: /* Register DMA channel for ISA bus. */
3069: if ((boardp->bus_type & ASC_IS_ISA) == 0) {
3070: shp->dma_channel = NO_ISA_DMA;
3071: } else {
3072: shp->dma_channel = boardp->cfg->isa_dma_channel;
3073: if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) {
3074: ASC_DBG2(0, "advansys_detect: request_dma() %d failed %d\n",
3075: shp->dma_channel, ret);
3076: release_region(shp->io_port, shp->n_io_port);
3077: scsi_unregister(shp);
3078: asc_board_count--;
3079: continue;
3080: }
3081: AscEnableIsaDma(shp->dma_channel);
3082: }
3083:
3084: /* Register IRQ Number. */
3085: ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
3086: if ((ret = request_irq(shp->irq, advansys_interrupt,
3087: SA_INTERRUPT, "advansys")) != 0) {
3088: ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret);
3089: release_region(shp->io_port, shp->n_io_port);
3090: if (shp->dma_channel != NO_ISA_DMA) {
3091: free_dma(shp->dma_channel);
3092: }
3093: scsi_unregister(shp);
3094: asc_board_count--;
3095: continue;
3096: }
3097:
3098: /*
3099: * Initialize board RISC chip and enable interrupts.
3100: */
3101: ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
3102: if (AscInitAsc1000Driver(boardp)) {
3103: ASC_DBG2(0,
3104: "AscInitAsc1000Driver: error: init_state %x, err_code %x\n",
3105: boardp->init_state, boardp->err_code);
3106: release_region(shp->io_port, shp->n_io_port);
3107: if (shp->dma_channel != NO_ISA_DMA) {
3108: free_dma(shp->dma_channel);
3109: }
3110: free_irq(shp->irq);
3111: scsi_unregister(shp);
3112: asc_board_count--;
3113: continue;
3114: }
3115: ASC_DBG_PRT_SCSI_HOST(2, shp);
3116: }
3117: }
3118:
3119: ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
3120: return asc_board_count;
3121: }
3122:
3123: /*
3124: * advansys_release()
3125: *
3126: * Release resources allocated for a single AdvanSys adapter.
3127: */
3128: int
3129: advansys_release(struct Scsi_Host *shp)
3130: {
3131: ASC_DBG(1, "advansys_release: begin\n");
3132: free_irq(shp->irq);
3133: if (shp->dma_channel != NO_ISA_DMA) {
3134: ASC_DBG(1, "advansys_release: free_dma()\n");
3135: free_dma(shp->dma_channel);
3136: }
3137: release_region(shp->io_port, shp->n_io_port);
3138: scsi_unregister(shp);
3139: ASC_DBG(1, "advansys_release: end\n");
3140: return 0;
3141: }
3142:
3143: /*
3144: * advansys_info()
3145: *
3146: * Return suitable for printing on the console with the argument
3147: * adapter's configuration information.
3148: */
3149: const char *
3150: advansys_info(struct Scsi_Host *shp)
3151: {
3152: static char info[128];
3153: ASC_DVC_VAR *boardp;
3154: char *busname;
3155:
3156: boardp = &ASC_BOARD(shp)->board;
3157: ASC_DBG(1, "advansys_info: begin\n");
3158: if (boardp->bus_type & ASC_IS_ISA) {
3159: sprintf(info,
3160: "AdvanSys SCSI %s: ISA (%u CDB): BIOS %X, IO %X-%X, IRQ %u, DMA %u",
3161: ASC_VERSION, ASC_BOARD(shp)->board.max_total_qng,
3162: (unsigned) shp->base, shp->io_port,
3163: shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
3164: } else {
3165: switch (boardp->bus_type) {
3166: case ASC_IS_EISA:
3167: busname = "EISA";
3168: break;
3169: case ASC_IS_VL:
3170: busname = "VL";
3171: break;
3172: case ASC_IS_PCI:
3173: busname = "PCI";
3174: break;
3175: default:
3176: busname = "?";
3177: ASC_DBG1(0, "advansys_info: unknown bus type %d\n",
3178: boardp->bus_type);
3179: break;
3180: }
3181: /* No DMA channel for non-ISA busses. */
3182: sprintf(info,
3183: "AdvanSys SCSI %s: %s (%u CDB): BIOS %X, IO %X-%X, IRQ %u",
3184: ASC_VERSION, busname, ASC_BOARD(shp)->board.max_total_qng,
3185: (unsigned) shp->base, shp->io_port,
3186: shp->io_port + (shp->n_io_port - 1), shp->irq);
3187: }
3188: ASC_DBG(1, "advansys_info: end\n");
3189: return info;
3190: }
3191:
3192: /*
3193: * advansys_command()
3194: *
3195: * Polled-I/O. Apparently host driver shouldn't return until
3196: * command is finished.
3197: *
3198: * XXX - Can host driver block here instead of spinning on command status?
3199: */
3200: int
3201: advansys_command(Scsi_Cmnd *scp)
3202: {
3203: ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
3204: ASC_STATS(command);
3205: scp->SCp.Status = 0; /* Set to a known state */
3206: advansys_queuecommand(scp, advansys_command_done);
3207: while (scp->SCp.Status == 0) {
3208: continue;
3209: }
3210: ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
3211: return scp->result;
3212: }
3213:
3214: /*
3215: * advansys_queuecommand()
3216: *
3217: * This function always returns 0. Command return status is saved
3218: * in the 'scp' result field.
3219: */
3220: int
3221: advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
3222: {
3223: struct Scsi_Host *shp;
3224: int flags = 0;
3225: int interrupts_disabled;
3226:
3227: ASC_STATS(queuecommand);
3228: shp = scp->host;
3229:
3230: #ifdef LINUX_1_2
3231: /*
3232: * For LINUX_1_3, if statistics are enabled they can be accessed
3233: * by reading /proc/scsi/advansys/[0-9].
3234: */
3235: #ifdef ADVANSYS_STATS_1_2_PRINT
3236: /* Display statistics every 10000 commands. */
3237: if ((asc_stats.queuecommand % 10000) == 0) {
3238: printk("\n");
3239: (void) asc_prt_stats(NULL, 0);
3240: printk("\n");
3241: }
3242: #endif /* ADVANSYS_STATS_1_2_PRINT */
3243: #endif /* LINUX_1_2 */
3244:
3245: /*
3246: * If there are any pending commands for this board before trying
3247: * to execute them, disable interrupts to preserve request ordering.
3248: *
3249: * The typical case will be no pending commands and interrupts
3250: * not disabled.
3251: */
3252: if (ASC_BOARD(shp)->pending_tidmask == 0) {
3253: interrupts_disabled = ASC_FALSE;
3254: } else {
3255: ASC_STATS(cmd_disable);
3256: /* Disable interrupts */
3257: interrupts_disabled = ASC_TRUE;
3258: save_flags(flags);
3259: cli();
3260: ASC_DBG1(1, "advansys_queuecommand: asc_execute_pending() %x\n",
3261: ASC_BOARD(shp)->pending_tidmask);
3262: asc_execute_pending(shp);
3263: }
3264:
3265: /*
3266: * Save the function pointer to Linux mid-level 'done' function and
3267: * execute the command.
3268: */
3269: scp->scsi_done = done;
3270: if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
3271: if (interrupts_disabled == ASC_FALSE) {
3272: save_flags(flags);
3273: cli();
3274: interrupts_disabled = ASC_TRUE;
3275: }
3276: asc_enqueue(shp, scp, scp->target, ASC_BACK);
3277: }
3278:
3279: if (interrupts_disabled == ASC_TRUE) {
3280: restore_flags(flags);
3281: }
3282:
3283: return 0;
3284: }
3285:
3286: /*
3287: * advansys_abort()
3288: *
3289: * Abort the specified command and reset the device
3290: * associated with the command 'scp'.
3291: */
3292: int
3293: advansys_abort(Scsi_Cmnd *scp)
3294: {
3295: ASC_DVC_VAR *boardp;
3296: int flags;
3297: int ret;
3298:
3299: ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
3300: save_flags(flags);
3301: cli();
3302: ASC_STATS(abort);
3303: if (scp->host == NULL) {
3304: scp->result = HOST_BYTE(DID_ERROR);
3305: ret = SCSI_ABORT_ERROR;
3306: } else if (asc_rmqueue(scp->host, scp, scp->target) == ASC_TRUE) {
3307: scp->result = HOST_BYTE(DID_ABORT);
3308: ret = SCSI_ABORT_SUCCESS;
3309: (void) AscResetDevice(&ASC_BOARD(scp->host)->board, scp->target);
3310: } else {
3311: /* Must enable interrupts for AscAbortSRB() */
3312: sti();
3313: boardp = &ASC_BOARD(scp->host)->board;
3314: scp->result = HOST_BYTE(DID_ABORT);
3315: switch (AscAbortSRB(boardp, (ulong) scp)) {
3316: case ASC_TRUE:
3317: /* asc_isr_callback() will be called */
3318: ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
3319: ret = SCSI_ABORT_PENDING;
3320: break;
3321: case ASC_FALSE:
3322: /* Request has apparently already completed. */
3323: ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
3324: ret = SCSI_ABORT_NOT_RUNNING;
3325: break;
3326: case ASC_ERROR:
3327: default:
3328: ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
3329: ret = SCSI_ABORT_ERROR;
3330: break;
3331: }
3332: (void) AscResetDevice(boardp, scp->target);
3333: }
3334: restore_flags(flags);
3335: ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
3336: return ret;
3337: }
3338:
3339: /*
3340: * advansys_reset()
3341: *
3342: * Reset all devices and the SCSI bus for the board
3343: * associated with 'scp'.
3344: */
3345: int
3346: advansys_reset(Scsi_Cmnd *scp)
3347: {
3348: ASC_DVC_VAR *boardp;
3349: int flags;
3350: Scsi_Cmnd *tscp;
3351: int i;
3352: int ret;
3353:
3354: ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
3355: save_flags(flags);
3356: cli();
3357: ASC_STATS(reset);
3358: if (scp->host == NULL) {
3359: scp->result = HOST_BYTE(DID_ERROR);
3360: ret = SCSI_RESET_ERROR;
3361: } else {
3362: /* Remove any pending commands, set DID_RESET, and done them. */
3363: for (i = 0; i < ASC_MAX_TID; i++) {
3364: while ((tscp = asc_dequeue(scp->host, i)) != NULL) {
3365: tscp->result = HOST_BYTE(DID_RESET);
3366: tscp->scsi_done(tscp);
3367: }
3368: }
3369: /* Must enable interrupts for AscResetSB() */
3370: sti();
3371: boardp = &ASC_BOARD(scp->host)->board;
3372: scp->result = HOST_BYTE(DID_RESET);
3373: switch (AscResetSB(boardp)) {
3374: case ASC_TRUE:
3375: ASC_DBG(1, "advansys_abort: AscResetSB() TRUE\n");
3376: ret = SCSI_RESET_SUCCESS;
3377: break;
3378: case ASC_ERROR:
3379: default:
3380: ASC_DBG(1, "advansys_abort: AscResetSB() ERROR\n");
3381: ret = SCSI_RESET_ERROR;
3382: break;
3383: }
3384: }
3385: restore_flags(flags);
3386: ASC_DBG1(1, "advansys_reset: ret %d", ret);
3387: return ret;
3388: }
3389:
3390: /*
3391: * advansys_biosparam()
3392: *
3393: * Translate disk drive geometry if the "BIOS greater than 1 GB"
3394: * support is enabled for a drive.
3395: *
3396: * ip (information pointer) is an int array with the following definition:
3397: * ip[0]: heads
3398: * ip[1]: sectors
3399: * ip[2]: cylinders
3400: */
3401: int
3402: #ifdef LINUX_1_2
3403: advansys_biosparam(Disk *dp, int dep, int ip[])
3404: #else /* LINUX_1_3 */
3405: advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
3406: #endif /* LINUX_1_3 */
3407: {
3408: ASC_DBG(1, "advansys_biosparam: begin\n");
3409: ASC_STATS(biosparam);
3410: if ((ASC_BOARD(dp->device->host)->board.dvc_cntl & ASC_CNTL_BIOS_GT_1GB) &&
3411: dp->capacity > 0x200000) {
3412: ip[0] = 255;
3413: ip[1] = 64;
3414: } else {
3415: ip[0] = 64;
3416: ip[1] = 32;
3417: }
3418: ip[2] = dp->capacity / (ip[0] * ip[1]);
3419: ASC_DBG(1, "advansys_biosparam: end\n");
3420: return 0;
3421: }
3422:
3423: /*
3424: * advansys_setup()
3425: *
3426: * This function is called from init/main.c at boot time.
3427: * It it passed LILO parameters that can be set from the
3428: * LILO command line or in /etc/lilo.conf.
3429: *
3430: * It is used by the AdvanSys driver to either disable I/O
3431: * port scanning or to limit scanning to 1 - 4 I/O ports.
3432: * Regardless of the option setting EISA and PCI boards
3433: * will still be searched for and detected. This option
3434: * only affects searching for ISA and VL boards.
3435: *
3436: * If ADVANSYS_DEBUG is defined the driver debug level may
3437: * be set using the 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port.
3438: *
3439: * Examples:
3440: * 1. Eliminate I/O port scanning:
3441: * boot: linux advansys=
3442: * or
3443: * boot: linux advansys=0x0
3444: * 2. Limit I/O port scanning to one I/O port:
3445: * boot: linux advansys=0x110
3446: * 3. Limit I/O port scanning to four I/O ports:
3447: * boot: linux advansys=0x110,0x210,0x230,0x330
3448: * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
3449: * set the driver debug level to 2.
3450: * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
3451: *
3452: * ints[0] - number of arguments
3453: * ints[1] - first argument
3454: * ints[2] - second argument
3455: * ...
3456: */
3457: void
3458: advansys_setup(char *str, int *ints)
3459: {
3460: int i;
3461:
3462: if (asc_iopflag == ASC_TRUE) {
3463: printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
3464: return;
3465: }
3466:
3467: asc_iopflag = ASC_TRUE;
3468:
3469: if (ints[0] > ASC_NUM_BOARD_SUPPORTED) {
3470: #ifdef ADVANSYS_DEBUG
3471: if ((ints[0] == ASC_NUM_BOARD_SUPPORTED + 1) &&
3472: (ints[ASC_NUM_BOARD_SUPPORTED + 1] >> 4 == 0xdeb)) {
3473: asc_dbglvl = ints[ASC_NUM_BOARD_SUPPORTED + 1] & 0xf;
3474: } else {
3475: #endif /* ADVANSYS_DEBUG */
3476: printk("AdvanSys SCSI: only %d I/O ports accepted\n",
3477: ASC_NUM_BOARD_SUPPORTED);
3478: #ifdef ADVANSYS_DEBUG
3479: }
3480: #endif /* ADVANSYS_DEBUG */
3481: }
3482:
3483: #ifdef ADVANSYS_DEBUG
3484: ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
3485: for (i = 1; i < ints[0]; i++) {
3486: ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
3487: }
3488: ASC_DBG(1, "\n");
3489: #endif /* ADVANSYS_DEBUG */
3490:
3491: for (i = 1; i <= ints[0] && i <= ASC_NUM_BOARD_SUPPORTED; i++) {
3492: asc_ioport[i-1] = ints[i];
3493: ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
3494: i - 1, asc_ioport[i-1]);
3495: }
3496: }
3497:
3498:
3499: /*
3500: * --- Loadable Driver Support
3501: */
3502:
3503: #ifdef MODULE
3504: Scsi_Host_Template driver_template = ADVANSYS;
3505: # include "scsi_module.c"
3506: #endif /* MODULE */
3507:
3508:
3509: /*
3510: * --- Miscellaneous Driver Functions
3511: */
3512:
3513: #ifdef LINUX_1_3
3514: /*
3515: * asc_proc_copy()
3516: *
3517: * Copy proc information to a read buffer considering the current read
3518: * offset in the file and the remaining space in the read buffer.
3519: */
3520: STATIC int
3521: asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
3522: char *cp, int cplen)
3523: {
3524: int cnt = 0;
3525:
3526: ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
3527: (unsigned) offset, (unsigned) advoffset, cplen);
3528: if (offset <= advoffset) {
3529: /* Read offset below current offset, copy everything. */
3530: cnt = min(cplen, leftlen);
3531: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
3532: (unsigned) curbuf, (unsigned) cp, cnt);
3533: memcpy(curbuf, cp, cnt);
3534: } else if (offset < advoffset + cplen) {
3535: /* Read offset within current range, partial copy. */
3536: cnt = (advoffset + cplen) - offset;
3537: cp = (cp + cplen) - cnt;
3538: cnt = min(cnt, leftlen);
3539: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
3540: (unsigned) curbuf, (unsigned) cp, cnt);
3541: memcpy(curbuf, cp, cnt);
3542: }
3543: return cnt;
3544: }
3545: #endif /* LINUX_1_3 */
3546:
3547: /*
3548: * First-level interrupt handler.
3549: */
3550: STATIC void
3551: advansys_interrupt(int irq, struct pt_regs *regs)
3552: {
3553: int i;
3554: int flags;
3555: Scsi_Cmnd *scp;
3556: Scsi_Cmnd *tscp;
3557:
3558: /* Disable interrupts, if the aren't already disabled. */
3559: save_flags(flags);
3560: cli();
3561:
3562: ASC_DBG(1, "advansys_interrupt: begin\n");
3563: ASC_STATS(interrupt);
3564: /*
3565: * Check for interrupts on all boards.
3566: * AscISR() will call asc_isr_callback().
3567: */
3568: for (i = 0; i < asc_board_count; i++) {
3569: while (AscIsIntPending(asc_host[i]->io_port)) {
3570: ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
3571: AscISR(&ASC_BOARD(asc_host[i])->board);
3572: }
3573: }
3574: ASC_DBG(1, "advansys_interrupt: end\n");
3575:
3576: /*
3577: * While interrupts are still disabled save the list of requests that
3578: * need their done function called. After re-enabling interrupts call
3579: * the done function which may re-enable interrupts anyway.
3580: */
3581: if ((scp = asc_scsi_done) != NULL) {
3582: asc_scsi_done = NULL;
3583: }
3584:
3585: /* Re-enable interrupts, if they were enabled on entry. */
3586: restore_flags(flags);
3587:
3588: while (scp) {
3589: tscp = (Scsi_Cmnd *) scp->host_scribble;
3590: scp->scsi_done(scp);
3591: scp = tscp;
3592: }
3593:
3594: return;
3595: }
3596:
3597: /*
3598: * Function used only with polled I/O requests that are initiated by
3599: * advansys_command().
3600: */
3601: STATIC void
3602: advansys_command_done(Scsi_Cmnd *scp)
3603: {
3604: ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
3605: scp->SCp.Status = 1;
3606: }
3607:
3608: /*
3609: * Execute a single 'Scsi_Cmnd'.
3610: *
3611: * The function 'done' is called when the request has been completed.
3612: *
3613: * Scsi_Cmnd:
3614: *
3615: * host - board controlling device
3616: * device - device to send command
3617: * target - target of device
3618: * lun - lun of device
3619: * cmd_len - length of SCSI CDB
3620: * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
3621: * use_sg - if non-zero indicates scatter-gather request with use_sg elements
3622: *
3623: * if (use_sg == 0)
3624: * request_buffer - buffer address for request
3625: * request_bufflen - length of request buffer
3626: * else
3627: * request_buffer - pointer to scatterlist structure
3628: *
3629: * sense_buffer - sense command buffer
3630: *
3631: * result (4 bytes of an int):
3632: * Byte Meaning
3633: * 0 SCSI Status Byte Code
3634: * 1 SCSI One Byte Message Code
3635: * 2 Host Error Code
3636: * 3 Mid-Level Error Code
3637: *
3638: * host driver fields:
3639: * SCp - Scsi_Pointer used for command processing status
3640: * scsi_done - used to save caller's done function
3641: * host_scribble - used for pointer to another Scsi_Cmnd
3642: *
3643: * If this function returns ASC_NOERROR or ASC_ERROR the done
3644: * function has been called. If ASC_BUSY is returned the request
3645: * must be enqueued by the caller and re-tried later.
3646: */
3647: STATIC int
3648: asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
3649: {
3650: ASC_DVC_VAR *boardp;
3651: ASC_SCSI_Q scsiq;
3652: ASC_SG_HEAD sghead;
3653: int ret;
3654:
3655: ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
3656: (unsigned) scp, (unsigned) scp->scsi_done);
3657:
3658: boardp = &ASC_BOARD(scp->host)->board;
3659:
3660: /*
3661: * If this is the first command, then initialize the device. If
3662: * no device is found set 'DID_BAD_TARGET' and return.
3663: */
3664: if ((ASC_BOARD(scp->host)->init_tidmask &
3665: ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
3666: if (asc_init_dev(boardp, scp) == ASC_FALSE) {
3667: scp->result = HOST_BYTE(DID_BAD_TARGET);
3668: scp->scsi_done(scp);
3669: return ASC_ERROR;
3670: }
3671: ASC_BOARD(scp->host)->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
3672: }
3673:
3674: memset(&scsiq, 0, sizeof(ASC_SCSI_Q));
3675:
3676: /*
3677: * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
3678: */
3679: scsiq.q2.srb_ptr = (ulong) scp;
3680:
3681: /*
3682: * Build the ASC_SCSI_Q request.
3683: */
3684: scsiq.cdbptr = &scp->cmnd[0];
3685: scsiq.q2.cdb_len = scp->cmd_len;
3686: scsiq.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
3687: scsiq.q1.target_lun = scp->lun;
3688: scsiq.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
3689: scsiq.q1.sense_addr = (ulong) &scp->sense_buffer[0];
3690: scsiq.q1.sense_len = sizeof(scp->sense_buffer);
3691: scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE;
3692:
3693: /*
3694: * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
3695: * buffer command.
3696: */
3697: if (scp->use_sg == 0) {
3698: /*
3699: * CDB request of single contiguous buffer.
3700: */
3701: ASC_STATS(cont_cnt);
3702: /* request_buffer is already a real address. */
3703: scsiq.q1.data_addr = (ulong) scp->request_buffer;
3704: scsiq.q1.data_cnt = scp->request_bufflen;
3705: ASC_STATS_ADD(cont_xfer, (scp->request_bufflen + 511) >> 9);
3706: scsiq.q1.sg_queue_cnt = 0;
3707: scsiq.sg_head = NULL;
3708: } else {
3709: /*
3710: * CDB scatter-gather request list.
3711: */
3712: int sgcnt;
3713: struct scatterlist *slp;
3714:
3715: if (scp->use_sg > ASC_MAX_SG_LIST) {
3716: ASC_DBG2(0, "asc_execute_scsi_cmnd: use_sg %d > %d\n",
3717: scp->use_sg, ASC_MAX_SG_LIST);
3718: scp->result = HOST_BYTE(DID_ERROR);
3719: scp->scsi_done(scp);
3720: return ASC_ERROR;
3721: }
3722:
3723: ASC_STATS(sg_cnt);
3724:
3725: /*
3726: * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q
3727: * to point to it.
3728: */
3729: memset(&sghead, 0, sizeof(ASC_SG_HEAD));
3730:
3731: scsiq.q1.cntl |= QC_SG_HEAD;
3732: scsiq.sg_head = &sghead;
3733: scsiq.q1.data_cnt = 0;
3734: scsiq.q1.data_addr = 0;
3735: sghead.entry_cnt = scsiq.q1.sg_queue_cnt = scp->use_sg;
3736: ASC_STATS_ADD(sg_elem, sghead.entry_cnt);
3737:
3738: /*
3739: * Convert scatter-gather list into ASC_SG_HEAD list.
3740: */
3741: slp = (struct scatterlist *) scp->request_buffer;
3742: for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
3743: sghead.sg_list[sgcnt].addr = (ulong) slp->address;
3744: sghead.sg_list[sgcnt].bytes = slp->length;
3745: ASC_STATS_ADD(sg_xfer, (slp->length + 511) >> 9);
3746: }
3747: }
3748:
3749: ASC_DBG_PRT_SCSI_Q(2, &scsiq);
3750: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
3751:
3752: switch (ret = AscExeScsiQueue(boardp, &scsiq)) {
3753: case ASC_NOERROR:
3754: ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_NOERROR\n");
3755: break;
3756: case ASC_BUSY:
3757: /* Caller must enqueue request and retry later. */
3758: break;
3759: case ASC_ERROR:
3760: ASC_DBG1(0,
3761: "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_ERROR err_code %x\n",
3762: boardp->err_code);
3763: ASC_STATS(error);
3764: scp->result = HOST_BYTE(DID_ERROR);
3765: scp->scsi_done(scp);
3766: break;
3767: }
3768:
3769: ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
3770: return ret;
3771: }
3772:
3773: /*
3774: * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
3775: */
3776: void
3777: asc_isr_callback(ASC_DVC_VAR *boardp, ASC_QDONE_INFO *qdonep)
3778: {
3779: Scsi_Cmnd *scp;
3780: struct Scsi_Host *shp;
3781: int flags;
3782: Scsi_Cmnd **scpp;
3783:
3784: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
3785: ASC_DBG2(1, "asc_isr_callback: boardp %x, qdonep %x\n",
3786: (unsigned) boardp, (unsigned) qdonep);
3787: ASC_STATS(callback);
3788: ASC_DBG_PRT_QDONE_INFO(2, qdonep);
3789:
3790: /*
3791: * Get the Scsi_Cmnd structure and Scsi_Host structure for the
3792: * command that has been completed.
3793: */
3794: scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
3795: ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
3796: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
3797:
3798: shp = scp->host;
3799: ASC_ASSERT(shp);
3800: ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
3801:
3802: /*
3803: * 'qdonep' contains the command's ending status.
3804: */
3805: switch (qdonep->d3.done_stat) {
3806: case QD_NO_ERROR:
3807: ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
3808: switch (qdonep->d3.host_stat) {
3809: case QHSTA_NO_ERROR:
3810: scp->result = 0;
3811: break;
3812: default:
3813: /* QHSTA error occurred */
3814: scp->result = HOST_BYTE(DID_ERROR);
3815: break;
3816: }
3817: break;
3818:
3819: case QD_WITH_ERROR:
3820: ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
3821: switch (qdonep->d3.host_stat) {
3822: case QHSTA_NO_ERROR:
3823: if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
3824: ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
3825: ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
3826: sizeof(scp->sense_buffer));
3827: /*
3828: * Note: The status_byte() macro used by target drivers
3829: * defined in scsi.h shifts the status byte returned by
3830: * host drivers right by 1 bit. This is why target drivers
3831: * also use left shifted status byte definitions. For instance
3832: * target drivers use CHECK_CONDITION, defined to 0x1, instead
3833: * of the SCSI defined check condition value of 0x2.
3834: */
3835: scp->result = DRIVER_BYTE(DRIVER_SENSE) |
3836: STATUS_BYTE(qdonep->d3.scsi_stat);
3837: } else {
3838: scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
3839: }
3840: break;
3841:
3842: default:
3843: /* QHSTA error occurred */
3844: ASC_DBG1(2, "asc_isr_callback: host_stat %x\n",
3845: qdonep->d3.host_stat);
3846: scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
3847: STATUS_BYTE(qdonep->d3.scsi_stat);
3848: break;
3849: }
3850: break;
3851:
3852: case QD_ABORTED_BY_HOST:
3853: ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
3854: scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
3855: STATUS_BYTE(qdonep->d3.scsi_stat);
3856: break;
3857:
3858: default:
3859: ASC_DBG1(0, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat );
3860: scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
3861: STATUS_BYTE(qdonep->d3.scsi_stat);
3862: break;
3863: }
3864:
3865: /*
3866: * Before calling 'scsi_done' for the current 'Scsi_Cmnd' and possibly
3867: * triggering more commands to be issued, try to start any pending
3868: * commands.
3869: */
3870: if (ASC_BOARD(shp)->pending_tidmask != 0) {
3871: /*
3872: * If there are any pending commands for this board before trying
3873: * to execute them, disable interrupts to preserve request ordering.
3874: */
3875: ASC_STATS(intr_disable);
3876: save_flags(flags);
3877: cli();
3878: ASC_DBG1(1, "asc_isr_callback: asc_execute_pending() %x\n",
3879: ASC_BOARD(shp)->pending_tidmask);
3880: asc_execute_pending(shp);
3881: restore_flags(flags);
3882: }
3883:
3884: /*
3885: * Because interrupts may be enabled by the 'Scsi_Cmnd' done function,
3886: * add the command to the end of the global done list. The done function
3887: * for the command will be called in advansys_interrupt().
3888: */
3889: for (scpp = &asc_scsi_done; *scpp;
3890: scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
3891: ;
3892: }
3893: *scpp = scp;
3894: scp->host_scribble = NULL;
3895: return;
3896: }
3897:
3898: /*
3899: * Execute as many pending requests as possible for the
3900: * board specified by 'Scsi_Host'.
3901: */
3902: STATIC void
3903: asc_execute_pending(struct Scsi_Host *shp)
3904: {
3905: ASC_SCSI_BIT_ID_TYPE scan_tidmask;
3906: Scsi_Cmnd *scp;
3907: int i;
3908:
3909: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
3910: /*
3911: * Execute pending commands for devices attached to
3912: * the current board in round-robin fashion.
3913: */
3914: scan_tidmask = ASC_BOARD(shp)->pending_tidmask;
3915: do {
3916: for (i = 0; i < ASC_MAX_TID; i++) {
3917: if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
3918: if ((scp = asc_dequeue(shp, i)) == NULL) {
3919: scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
3920: } else if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
3921: scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
3922: /* Put the request back at front of the list. */
3923: asc_enqueue(shp, scp, i, ASC_FRONT);
3924: }
3925: }
3926: }
3927: } while (scan_tidmask);
3928: return;
3929: }
3930:
3931: /*
3932: * asc_init_dev()
3933: *
3934: * Perform one-time initialization of a device.
3935: */
3936: STATIC int
3937: asc_init_dev(ASC_DVC_VAR *boardp, Scsi_Cmnd *scp)
3938: {
3939: ASC_SCSI_REQ_Q *scsireqq;
3940: ASC_CAP_INFO *cap_info;
3941: ASC_SCSI_INQUIRY *inquiry;
3942: int found;
3943: ASC_SCSI_BIT_ID_TYPE save_use_tagged_qng;
3944: ASC_SCSI_BIT_ID_TYPE save_can_tagged_qng;
3945: int ret;
3946: #ifdef ADVANSYS_DEBUG
3947: ASC_SCSI_BIT_ID_TYPE tidmask; /* target id bit mask: 1 - 128 */
3948: #endif /* ADVANSYS_DEBUG */
3949:
3950: ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target);
3951:
3952: /* Return true for the board's target id. */
3953: if (boardp->cfg->chip_scsi_id == scp->target) {
3954: return ASC_TRUE;
3955: }
3956:
3957: /*
3958: * XXX - Host drivers should not modify the timeout field.
3959: * But on the first command only add some extra time to
3960: * allow the driver to complete its initialization for the
3961: * device.
3962: */
3963: scp->timeout += 2000; /* Add 5 seconds to the request timeout. */
3964:
3965: /* Set-up AscInitPollTarget() arguments. */
3966: scsireqq = &ASC_BOARD(scp->host)->scsireqq;
3967: memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
3968: cap_info = &ASC_BOARD(scp->host)->cap_info;
3969: memset(cap_info, 0, sizeof(ASC_CAP_INFO));
3970: inquiry = &ASC_BOARD(scp->host)->inquiry;
3971: memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
3972:
3973: /*
3974: * XXX - AscInitPollBegin() re-initializes these fields to
3975: * zero. 'Or' in the new values and restore them before calling
3976: * AscInitPollEnd(). Normally all targets are initialized within
3977: * a call to AscInitPollBegin() and AscInitPollEnd().
3978: */
3979: save_use_tagged_qng = boardp->use_tagged_qng;
3980: save_can_tagged_qng = boardp->cfg->can_tagged_qng;
3981:
3982: ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
3983: if (AscInitPollBegin(boardp)) {
3984: ASC_DBG(0, "asc_init_dev: AscInitPollBegin() failed\n");
3985: return ASC_FALSE;
3986: }
3987:
3988: scsireqq->sense_ptr = &scsireqq->sense[0];
3989: scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
3990: scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
3991: scsireqq->r1.target_lun = 0;
3992: scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
3993:
3994: found = ASC_FALSE;
3995: ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
3996: switch (ret = AscInitPollTarget(boardp, scsireqq, inquiry, cap_info)) {
3997: case ASC_TRUE:
3998: found = ASC_TRUE;
3999: #ifdef ADVANSYS_DEBUG
4000: tidmask = ASC_TIX_TO_TARGET_ID(scp->target);
4001: ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
4002: cap_info->lba, cap_info->blk_size);
4003: ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
4004: inquiry->byte0.peri_dvc_type);
4005: if (boardp->use_tagged_qng & tidmask) {
4006: ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
4007: boardp->max_dvc_qng[scp->target]);
4008: } else {
4009: ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
4010: }
4011: if (boardp->init_sdtr & tidmask) {
4012: ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n");
4013: } else {
4014: ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n");
4015: }
4016: /* Set bit means fix disabled. */
4017: if (boardp->pci_fix_asyn_xfer & tidmask) {
4018: ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n");
4019: } else {
4020: ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n");
4021: }
4022: #endif /* ADVANSYS_DEBUG */
4023: break;
4024: case ASC_FALSE:
4025: ASC_DBG(1, "asc_init_dev: no device found\n");
4026: break;
4027: case ASC_ERROR:
4028: ASC_DBG(0, "asc_init_dev: AscInitPollTarget() ASC_ERROR\n");
4029: break;
4030: default:
4031: ASC_DBG1(0, "asc_init_dev: AscInitPollTarget() unknown ret %d\n", ret);
4032: break;
4033: }
4034:
4035: /* XXX - 'Or' in original tag bits. */
4036: boardp->use_tagged_qng |= save_use_tagged_qng;
4037: boardp->cfg->can_tagged_qng |= save_can_tagged_qng;
4038:
4039: ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
4040: AscInitPollEnd(boardp);
4041:
4042: #ifdef ASC_SET_CMD_PER_LUN
4043: /*
4044: * XXX - Refer to the comment in advansys_detect()
4045: * regarding cmd_per_lun.
4046: */
4047: for (i = 0; i <= ASC_MAX_TID; i++) {
4048: if (boardp->max_dvc_qng[i] < scp->host->cmd_per_lun) {
4049: scp->host->cmd_per_lun = boardp->max_dvc_qng[i];
4050: }
4051: }
4052: #endif /* ASC_SET_CMD_PER_LUN */
4053:
4054: return found;
4055: }
4056:
4057: /*
4058: * Search for an AdvanSys PCI device in the PCI configuration space.
4059: */
4060: STATIC int
4061: asc_srch_pci_dev(PCI_DEVICE *pciDevice)
4062: {
4063: int ret;
4064: static int scan = 1;
4065:
4066: ASC_DBG(2, "asc_srch_pci_dev: begin\n");
4067:
4068: if (scan) {
4069: pciDevice->type = asc_scan_method(pciDevice);
4070: scan = 0;
4071: ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
4072: }
4073: ret = asc_pci_find_dev(pciDevice);
4074: ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
4075: if (ret == PCI_DEVICE_FOUND) {
4076: pciDevice->slotNumber = pciDevice->slotFound + 1;
4077: pciDevice->startSlot = pciDevice->slotFound + 1;
4078: } else {
4079: if (pciDevice->bridge > pciDevice->busNumber) {
4080: ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
4081: pciDevice->bridge, pciDevice->busNumber);
4082: pciDevice->busNumber++;
4083: pciDevice->slotNumber = 0;
4084: pciDevice->startSlot = 0;
4085: pciDevice->endSlot = 0x0f;
4086: ret = asc_srch_pci_dev(pciDevice);
4087: ASC_DBG1(2, "asc_srch_pci_dev recursive call return %d\n", ret);
4088: }
4089: }
4090: ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
4091: return ret;
4092: }
4093:
4094: /*
4095: * Determine the access method to be used for 'pciDevice'.
4096: */
4097: STATIC uchar
4098: asc_scan_method(PCI_DEVICE *pciDevice)
4099: {
4100: ushort data;
4101: PCI_DATA pciData;
4102: uchar type;
4103: uchar slot;
4104:
4105: ASC_DBG(2, "asc_scan_method: begin\n");
4106: memset(&pciData, 0, sizeof(pciData));
4107: for (type = 1; type < 3; type++) {
4108: pciData.type = type;
4109: for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
4110: pciData.slot = slot;
4111: data = asc_get_cfg_word(&pciData);
4112: if ((data != 0xFFFF) && (data != 0x0000)) {
4113: ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
4114: return (type);
4115: }
4116: }
4117: }
4118: ASC_DBG1(4, "asc_scan_method: type %d\n", type);
4119: return (type);
4120: }
4121:
4122: /*
4123: * Check for an AdvanSys PCI device in 'pciDevice'.
4124: *
4125: * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
4126: */
4127: STATIC int
4128: asc_pci_find_dev(PCI_DEVICE *pciDevice)
4129: {
4130: PCI_DATA pciData;
4131: ushort vendorid, deviceid;
4132: uchar classcode, subclass;
4133: uchar lslot;
4134:
4135: ASC_DBG(3, "asc_pci_find_dev: begin\n");
4136: pciData.type = pciDevice->type;
4137: pciData.bus = pciDevice->busNumber;
4138: pciData.func = pciDevice->devFunc;
4139: lslot = pciDevice->startSlot;
4140: for (; lslot < pciDevice->endSlot; lslot++) {
4141: pciData.slot = lslot;
4142: pciData.offset = VENDORID_OFFSET;
4143: vendorid = asc_get_cfg_word(&pciData);
4144: ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
4145: if (vendorid != 0xffff) {
4146: pciData.offset = DEVICEID_OFFSET;
4147: deviceid = asc_get_cfg_word(&pciData);
4148: ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
4149: if ((vendorid == ASC_PCI_VENDORID) &&
4150: ((deviceid == ASC_PCI_DEVICE_ID_REV_A) ||
4151: (deviceid == ASC_PCI_DEVICE_ID_REV_B))) {
4152: pciDevice->slotFound = lslot;
4153: ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
4154: return PCI_DEVICE_FOUND;
4155: } else {
4156: pciData.offset = SUBCLASS_OFFSET;
4157: subclass = asc_get_cfg_byte(&pciData);
4158: pciData.offset = CLASSCODE_OFFSET;
4159: classcode = asc_get_cfg_byte(&pciData);
4160: if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
4161: (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
4162: pciDevice->bridge++;
4163: }
4164: ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
4165: subclass, classcode);
4166: }
4167: }
4168: }
4169: return PCI_DEVICE_NOT_FOUND;
4170: }
4171:
4172: /*
4173: * Read PCI configuration data into 'pciConfig'.
4174: */
4175: STATIC void
4176: asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
4177: {
4178: PCI_DATA pciData;
4179: uchar counter;
4180: uchar *localConfig;
4181:
4182: ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ",
4183: pciDevice->slotFound);
4184:
4185: pciData.type = pciDevice->type;
4186: pciData.bus = pciDevice->busNumber;
4187: pciData.slot = pciDevice->slotFound;
4188: pciData.func = pciDevice->devFunc;
4189: localConfig = (uchar *) pciConfig;
4190:
4191: for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
4192: pciData.offset = counter;
4193: *localConfig = asc_get_cfg_byte(&pciData);
4194: ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
4195: localConfig++;
4196: }
4197: ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
4198: }
4199:
4200: /*
4201: * Read a word (16 bits) from the PCI configuration space.
4202: *
4203: * The configuration mechanism is checked for the correct access method.
4204: */
4205: STATIC ushort
4206: asc_get_cfg_word(PCI_DATA *pciData)
4207: {
4208: ushort tmp;
4209: ulong address;
4210: ulong lbus = pciData->bus;
4211: ulong lslot = pciData->slot;
4212: ulong lfunc = pciData->func;
4213: uchar t2CFA, t2CF8;
4214: ushort t1CF8, t1CFA, t1CFC, t1CFE;
4215:
4216: ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
4217: pciData->type, lbus, lslot, lfunc);
4218:
4219: /*
4220: * check type of configuration mechanism
4221: */
4222: if (pciData->type == 2) {
4223: /*
4224: * save these registers so we can restore them after we are done
4225: */
4226: t2CFA = inp(0xCFA); /* save PCI bus register */
4227: t2CF8 = inp(0xCF8); /* save config space enable register */
4228:
4229: /*
4230: * go out and write the bus and enable registers
4231: */
4232: /* set for type 1 cycle, if needed */
4233: outp(0xCFA, pciData->bus);
4234: /* set the function number */
4235: outp(0xCF8, 0x10 | (pciData->func << 1)) ;
4236:
4237: /*
4238: * read the configuration space type 2 locations
4239: */
4240: tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
4241: } else {
4242: /*
4243: * type 1 configuration mechanism
4244: *
4245: * save the CONFIG_ADDRESS and CONFIG_DATA register values
4246: */
4247: t1CFC = inpw(0xCFC);
4248: t1CFE = inpw(0xCFE);
4249: t1CF8 = inpw(0xCF8);
4250: t1CFA = inpw(0xCFA);
4251:
4252: /*
4253: * enable <31>, bus = <23:16>, slot = <15:11>,
4254: * func = <10:8>, reg = <7:2>
4255: */
4256: address = (ulong) ((lbus << 16) | (lslot << 11) |
4257: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
4258:
4259: /*
4260: * write out the address to CONFIG_ADDRESS
4261: */
4262: outl(address, 0xCF8);
4263:
4264: /*
4265: * read in the word from CONFIG_DATA
4266: */
4267: tmp = (ushort) ((inl(0xCFC) >>
4268: ((pciData->offset & 2) * 8)) & 0xFFFF);
4269: }
4270: ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
4271: return tmp;
4272: }
4273:
4274: /*
4275: * Reads a byte from the PCI configuration space.
4276: *
4277: * The configuration mechanism is checked for the correct access method.
4278: */
4279: STATIC uchar
4280: asc_get_cfg_byte(PCI_DATA *pciData)
4281: {
4282: uchar tmp;
4283: ulong address;
4284: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
4285: uchar t2CFA, t2CF8;
4286: ushort t1CF8, t1CFA, t1CFC, t1CFE;
4287:
4288: ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
4289:
4290: /*
4291: * check type of configuration mechanism
4292: */
4293: if (pciData->type == 2) {
4294: /*
4295: * save these registers so we can restore them after we are done
4296: */
4297: t2CFA = inp(0xCFA); /* save PCI bus register */
4298: t2CF8 = inp(0xCF8); /* save config space enable register */
4299:
4300: /*
4301: * go out and write the bus and enable registers
4302: */
4303: /* set for type 1 cycle, if needed */
4304: outp(0xCFA, pciData->bus);
4305: /* set the function number */
4306: outp(0xCF8, 0x10 | (pciData->func << 1));
4307:
4308: /*
4309: * read the configuration space type 2 locations
4310: */
4311: tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
4312:
4313: /*
4314: * restore the registers used for our transaction
4315: */
4316: outp(0xCF8, t2CF8); /* restore the enable register */
4317: outp(0xCFA, t2CFA); /* restore PCI bus register */
4318: } else {
4319: /*
4320: * type 1 configuration mechanism
4321: *
4322: * save the CONFIG_ADDRESS and CONFIG_DATA register values
4323: */
4324: t1CFC = inpw(0xCFC);
4325: t1CFE = inpw(0xCFE);
4326: t1CF8 = inpw(0xCF8);
4327: t1CFA = inpw(0xCFA);
4328:
4329: /*
4330: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
4331: * reg = <7:2>
4332: */
4333: address = (ulong) ((lbus << 16) | (lslot << 11) |
4334: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
4335:
4336: /*
4337: * write out the address to CONFIG_ADDRESS
4338: */
4339: outl(address, 0xCF8);
4340:
4341: /*
4342: * read in the word from CONFIG_DATA
4343: */
4344: tmp = (uchar) ((inl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
4345: }
4346: ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
4347: return tmp;
4348: }
4349:
4350: /*
4351: * Add a 'Scsi_Cmnd' to the end of specified 'Scsi_Host'
4352: * target device pending command list. Set 'pending_tidmask'
4353: * to indicate a command is queued for the device.
4354: *
4355: * 'flag' may be either ASC_FRONT or ASC_BACK.
4356: *
4357: * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
4358: */
4359: STATIC void
4360: asc_enqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid, int flag)
4361: {
4362: Scsi_Cmnd **scpp;
4363:
4364: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
4365: ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
4366: ASC_STATS(enqueue);
4367: if (flag == ASC_FRONT) {
4368: scp->host_scribble = (unsigned char *) ASC_BOARD(shp)->pending[tid];
4369: ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp;
4370: } else { /* ASC_BACK */
4371: for (scpp = &ASC_BOARD(shp)->pending[tid]; *scpp;
4372: scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
4373: ;
4374: }
4375: *scpp = scp;
4376: scp->host_scribble = NULL;
4377: }
4378: ASC_BOARD(shp)->pending_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
4379: }
4380:
4381: /*
4382: * Return first pending 'Scsi_Cmnd' on the specified 'Scsi_Host'
4383: * for the specified target device. Clear the 'pending_tidmask'
4384: * bit for the device if no more commands are left queued for it.
4385: *
4386: * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
4387: */
4388: STATIC Scsi_Cmnd *
4389: asc_dequeue(struct Scsi_Host *shp, int tid)
4390: {
4391: Scsi_Cmnd *scp;
4392:
4393: ASC_STATS(dequeue);
4394: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
4395: if ((scp = ASC_BOARD(shp)->pending[tid]) != NULL) {
4396: ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp->host_scribble;
4397: }
4398: if (ASC_BOARD(shp)->pending[tid] == NULL) {
4399: ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
4400: }
4401: return scp;
4402: }
4403:
4404: /*
4405: * Remove the specified 'Scsi_Cmnd' from the specified 'Scsi_Host'
4406: * for the specified target device. Clear the 'pending_tidmask'
4407: * bit for the device if no more commands are left queued for it.
4408: *
4409: * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
4410: *
4411: * Return ASC_TRUE if the command was found and removed, otherwise
4412: * return ASC_FALSE if the command was not found.
4413: */
4414: STATIC int
4415: asc_rmqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid)
4416: {
4417: Scsi_Cmnd **scpp;
4418: int ret;
4419:
4420: ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
4421: ret = ASC_FALSE;
4422: for (scpp = &ASC_BOARD(shp)->pending[tid];
4423: *scpp; scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
4424: if (*scpp == scp) {
4425: *scpp = (Scsi_Cmnd *) scp->host_scribble;
4426: scp->host_scribble = NULL;
4427: ASC_STATS(rmqueue);
4428: ret = ASC_TRUE;
4429: }
4430: }
4431: if (ASC_BOARD(shp)->pending[tid] == NULL) {
4432: ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
4433: }
4434: return ret;
4435: }
4436:
4437:
4438: /*
4439: * --- Functions Required by the Asc Library
4440: */
4441:
4442: /*
4443: * Delay for 'n' milliseconds. Don't use the 'jiffies'
4444: * global variable which is incremented once every 5 ms
4445: * from a timer interrupt, because this function may be
4446: * called when interrupts are disabled.
4447: */
4448: void
4449: DvcSleepMilliSecond(ulong n)
4450: {
4451: ulong i;
4452:
4453: ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
4454: for (i = 0; i < n; i++) {
4455: udelay(1000);
4456: }
4457: }
4458:
4459: void
4460: DvcDisplayString(uchar *s)
4461: {
4462: printk(s);
4463: }
4464:
4465: int
4466: DvcEnterCritical(void)
4467: {
4468: int flags;
4469:
4470: save_flags(flags);
4471: cli();
4472: return flags;
4473: }
4474:
4475: void
4476: DvcLeaveCritical(int flags)
4477: {
4478: restore_flags(flags);
4479: }
4480:
4481: /*
4482: * Convert a virtual address to a virtual address.
4483: *
4484: * Apparently Linux is loaded V=R (virtual equals real). Just return
4485: * the virtual address.
4486: */
4487: ulong
4488: DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
4489: {
4490: ulong phys_addr;
4491:
4492: phys_addr = (ulong) buf_addr;
4493: return phys_addr;
4494: }
4495:
4496: ulong
4497: DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
4498: ASC_SG_HEAD *asc_sg_head_ptr)
4499: {
4500: ulong buf_size;
4501:
4502: buf_size = buf_len;
4503: asc_sg_head_ptr->entry_cnt = 1;
4504: asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
4505: asc_sg_head_ptr->sg_list[0].bytes = buf_size;
4506: return buf_size;
4507: }
4508:
4509: /*
4510: * void
4511: * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
4512: *
4513: * Calling/Exit State:
4514: * none
4515: *
4516: * Description:
4517: * Output an ASC_SCSI_Q structure to the chip
4518: */
4519: void
4520: DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
4521: {
4522: int i;
4523:
4524: ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
4525: AscSetChipLramAddr(iop_base, s_addr);
4526: for (i = 0; i < words; i++, outbuf++) {
4527: if (i == 2 || i == 10) {
4528: continue;
4529: }
4530: AscPutChipLramData(iop_base, *outbuf);
4531: }
4532: }
4533:
4534: /*
4535: * void
4536: * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
4537: *
4538: * Calling/Exit State:
4539: * none
4540: *
4541: * Description:
4542: * Input an ASC_QDONE_INFO structure from the chip
4543: */
4544: void
4545: DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
4546: {
4547: int i;
4548:
4549: AscSetChipLramAddr(iop_base, s_addr);
4550: for (i = 0; i < words; i++, inbuf++) {
4551: if (i == 5) {
4552: continue;
4553: }
4554: *inbuf = AscGetChipLramData(iop_base);
4555: }
4556: ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
4557: }
4558:
4559: /*
4560: * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
4561: *
4562: * Calling/Exit State:
4563: * none
4564: *
4565: * Description:
4566: * output a buffer to an i/o port address
4567: */
4568: void
4569: DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
4570: {
4571: int i;
4572:
4573: for (i = 0; i < words; i++, outbuf++)
4574: outpw(iop_base, *outbuf);
4575: }
4576:
4577: /*
4578: * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
4579: *
4580: * Calling/Exit State:
4581: * none
4582: *
4583: * Description:
4584: * input a buffer from an i/o port address
4585: */
4586: void
4587: DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
4588: {
4589: int i;
4590:
4591: for (i = 0; i < words; i++, inbuf++)
4592: *inbuf = inpw(iop_base);
4593: }
4594:
4595:
4596: /*
4597: * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
4598: *
4599: * Calling/Exit State:
4600: * none
4601: *
4602: * Description:
4603: * output a buffer of 32-bit integers to an i/o port address in
4604: * 16 bit integer units
4605: */
4606: void
4607: DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
4608: {
4609: int i;
4610: int words;
4611: ushort *pw;
4612:
4613: pw = (ushort *) pdw;
4614: words = dwords << 1;
4615: for(i = 0; i < words; i++, pw++) {
4616: outpw(port, *pw);
4617: }
4618: return;
4619: }
4620:
4621:
4622: /*
4623: * --- Tracing and Debugging Functions
4624: */
4625:
4626: #ifdef ADVANSYS_STATS
4627:
4628: #define ASC_PRT_STATS_NEXT() \
4629: if (cp) { \
4630: totlen += len; \
4631: leftlen -= len; \
4632: if (leftlen == 0) { \
4633: return totlen; \
4634: } \
4635: cp += len; \
4636: }
4637:
4638: /*
4639: * asc_prt_stats()
4640: *
4641: * Note: no single line should be greater than 160 characters, cf.
4642: * asc_prt_stats_line().
4643: *
4644: * Return the number of characters copied into 'cp'. No more than
4645: * 'cplen' characters will be copied to 'cp'.
4646: */
4647: STATIC int
4648: asc_prt_stats(char *cp, int cplen)
4649: {
4650: struct asc_stats *s;
4651: int leftlen;
4652: int totlen;
4653: int len;
4654:
4655: s = &asc_stats;
4656: leftlen = cplen;
4657: totlen = len = 0;
4658:
4659: len = asc_prt_stats_line(cp, leftlen,
4660: "\nAdvanSys SCSI Host Driver Statistics:\n");
4661: ASC_PRT_STATS_NEXT();
4662:
4663: len = asc_prt_stats_line(cp, leftlen,
4664: " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu,\n",
4665: s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
4666: ASC_PRT_STATS_NEXT();
4667:
4668: len = asc_prt_stats_line(cp, leftlen,
4669: " interrupt %lu, callback %lu, cmd_disable %lu, intr_disable %lu,\n",
4670: s->interrupt, s->callback, s->cmd_disable, s->intr_disable);
4671: ASC_PRT_STATS_NEXT();
4672:
4673: len = asc_prt_stats_line(cp, leftlen,
4674: " error %lu, enqueue %lu, dequeue %lu, rmqueue %lu,\n",
4675: s->error, s->enqueue, s->dequeue, s->rmqueue);
4676: ASC_PRT_STATS_NEXT();
4677:
4678: if (s->cont_cnt > 0) {
4679: len = asc_prt_stats_line(cp, leftlen,
4680: " cont_cnt %lu, cont_xfer %lu: avg_xfer=%lu kb\n",
4681: s->cont_cnt, s->cont_xfer, (s->cont_xfer/2)/s->cont_cnt);
4682: ASC_PRT_STATS_NEXT();
4683: }
4684:
4685: if (s->sg_cnt > 0) {
4686: len = asc_prt_stats_line(cp, leftlen,
4687: " sg_cnt %lu, sg_elem %lu, sg_xfer %lu: avg_elem=%lu, avg_size=%lu kb\n",
4688: s->sg_cnt, s->sg_elem, s->sg_xfer,
4689: s->sg_elem/s->sg_cnt, (s->sg_xfer/2)/s->sg_cnt);
4690: ASC_PRT_STATS_NEXT();
4691: }
4692:
4693: return totlen;
4694: }
4695:
4696: /*
4697: * asc_prt_stats_line()
4698: *
4699: * If 'cp' is NULL print to the console, otherwise print to a buffer.
4700: *
4701: * Return 0 if printing to the console, otherwise return the number of
4702: * bytes written to the buffer.
4703: *
4704: * Note: If any single line is greater than 160 bytes the stack
4705: * will be corrupted. 's[]' is defined to be 160 bytes.
4706: */
4707: int
4708: asc_prt_stats_line(char *buf, int buflen, char *fmt, ...)
4709: {
4710: va_list args;
4711: int ret;
4712: char s[160]; /* 2 lines */
4713:
4714: va_start(args, fmt);
4715: ret = vsprintf(s, fmt, args);
4716: if (buf == NULL) {
4717: (void) printk(s);
4718: ret = 0;
4719: } else {
4720: ret = min(buflen, ret);
4721: memcpy(buf, s, ret);
4722: }
4723: va_end(args);
4724: return ret;
4725: }
4726: #endif /* ADVANSYS_STATS */
4727:
4728: #ifdef ADVANSYS_DEBUG
4729: /*
4730: * asc_prt_scsi_host()
4731: */
4732: STATIC void
4733: asc_prt_scsi_host(struct Scsi_Host *s)
4734: {
4735: printk("Scsi_Host at addr %x\n", (unsigned) s);
4736: printk(
4737: " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
4738: (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
4739: s->last_reset);
4740:
4741: printk(
4742: " host_wait %x, host_queue %x, hostt %x, block %x,\n",
4743: (unsigned) s->host_wait, (unsigned) s->host_queue,
4744: (unsigned) s->hostt, (unsigned) s->block);
4745:
4746: printk(
4747: " wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
4748: s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
4749: s->irq, s->dma_channel);
4750:
4751: printk(
4752: " this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
4753:
4754: printk(
4755: " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
4756: s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
4757: s->loaded_as_module);
4758:
4759: printk("hostdata (struct asc_board)\n");
4760: asc_prt_dvc_var(&ASC_BOARD(s)->board);
4761: asc_prt_dvc_cfg(&ASC_BOARD(s)->cfg);
4762: printk(" overrun_buf %x\n", (unsigned) &ASC_BOARD(s)->overrun_buf[0]);
4763: }
4764:
4765: /*
4766: * asc_prt_dvc_var()
4767: */
4768: STATIC void
4769: asc_prt_dvc_var(ASC_DVC_VAR *h)
4770: {
4771: printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
4772:
4773: printk(
4774: " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
4775: h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
4776:
4777: printk(
4778: " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
4779: h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
4780: (unsigned) h->init_sdtr);
4781:
4782: printk(
4783: " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
4784: (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
4785: (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
4786:
4787: printk(
4788: " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
4789: (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
4790: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
4791:
4792: printk(
4793: " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
4794: (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
4795: (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
4796:
4797: printk(
4798: " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
4799: (unsigned) h->last_q_shortage, (unsigned) h->init_state,
4800: (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
4801:
4802: printk(
4803: " int_count %ld, req_count %ld, busy_count %ld, cfg %x, saved_ptr2func %x\n",
4804: h->int_count, h->req_count, h->busy_count, (unsigned) h->cfg,
4805: (unsigned) h->saved_ptr2func);
4806: }
4807:
4808: /*
4809: * asc_prt_dvc_cfg()
4810: */
4811: STATIC void
4812: asc_prt_dvc_cfg(ASC_DVC_CFG *h)
4813: {
4814: printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
4815:
4816: printk(
4817: " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n",
4818: h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res);
4819:
4820: printk(
4821: " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
4822: h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
4823: h->chip_version);
4824:
4825: printk(
4826: " pci_device_id %d, lib_serial_no %d, lib_version %d, mcode_date %d,\n",
4827: h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
4828:
4829: printk(
4830: " mcode_version %d, overrun_buf %x\n",
4831: h->mcode_version, (unsigned) h->overrun_buf);
4832: }
4833:
4834: /*
4835: * asc_prt_scsi_q()
4836: */
4837: STATIC void
4838: asc_prt_scsi_q(ASC_SCSI_Q *q)
4839: {
4840: ASC_SG_HEAD *sgp;
4841: int i;
4842:
4843: printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
4844:
4845: printk(
4846: " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
4847: q->q2.target_ix, q->q1.target_lun,
4848: (unsigned) q->q2.srb_ptr, q->q2.tag_code);
4849:
4850: printk(
4851: " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
4852: (unsigned) q->q1.data_addr, q->q1.data_cnt,
4853: (unsigned) q->q1.sense_addr, q->q1.sense_len);
4854:
4855: printk(
4856: " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
4857: (unsigned) q->cdbptr, q->q2.cdb_len,
4858: (unsigned) q->sg_head, q->q1.sg_queue_cnt);
4859:
4860: if (q->sg_head) {
4861: sgp = q->sg_head;
4862: printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
4863: printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
4864: for (i = 0; i < sgp->entry_cnt; i++) {
4865: printk(" [%u]: addr %x, bytes %lu\n",
4866: i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
4867: }
4868:
4869: }
4870: }
4871:
4872: /*
4873: * asc_prt_qdone_info()
4874: */
4875: STATIC void
4876: asc_prt_qdone_info(ASC_QDONE_INFO *q)
4877: {
4878: printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
4879: printk(
4880: " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
4881: (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
4882: q->d2.tag_code, q->d3.done_stat);
4883: printk(
4884: " host_stat %x, scsi_stat %x, scsi_msg %x\n",
4885: q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
4886: }
4887:
4888: /*
4889: * asc_prt_hex()
4890: *
4891: * Print hexadecimal output in 4 byte groupings 32 bytes
4892: * or 8 double-words per line.
4893: */
4894: STATIC void
4895: asc_prt_hex(char *f, uchar *s, int l)
4896: {
4897: int i;
4898: int j;
4899: int k;
4900: int m;
4901:
4902: printk("%s: (%d bytes)\n", f, l);
4903:
4904: for (i = 0; i < l; i += 32) {
4905:
4906: /* Display a maximum of 8 double-words per line. */
4907: if ((k = (l - i) / 4) >= 8) {
4908: k = 8;
4909: m = 0;
4910: } else {
4911: m = (l - i) % 4 ;
4912: }
4913:
4914: for (j = 0; j < k; j++) {
4915: printk(" %2.2X%2.2X%2.2X%2.2X",
4916: (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
4917: (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
4918: }
4919:
4920: switch (m) {
4921: case 0:
4922: default:
4923: break;
4924: case 1:
4925: printk(" %2.2X",
4926: (unsigned) s[i+(j*4)+4]);
4927: break;
4928: case 2:
4929: printk(" %2.2X%2.2X",
4930: (unsigned) s[i+(j*4)+4],
4931: (unsigned) s[i+(j*4)+5]);
4932: break;
4933: case 3:
4934: printk(" %2.2X%2.2X%2.2X",
4935: (unsigned) s[i+(j*4)+4],
4936: (unsigned) s[i+(j*4)+5],
4937: (unsigned) s[i+(j*4)+6]);
4938: break;
4939: }
4940:
4941: printk("\n");
4942: }
4943: }
4944:
4945: /*
4946: * interrupts_enabled()
4947: *
4948: * Return 1 if interrupts are enabled, otherwise return 0.
4949: */
4950: STATIC int
4951: interrupts_enabled(void)
4952: {
4953: int flags;
4954:
4955: save_flags(flags);
4956: if (flags & 0x0200) {
4957: return ASC_TRUE;
4958: } else {
4959: return ASC_FALSE;
4960: }
4961: }
4962:
4963: #endif /* ADVANSYS_DEBUG */
4964:
4965:
4966: /*
4967: * --- Asc Library Functions
4968: */
4969:
4970: ushort
4971: AscGetEisaChipCfg(
4972: PortAddr iop_base
4973: )
4974: {
4975: PortAddr eisa_cfg_iop;
4976:
4977: eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
4978: (PortAddr) (ASC_EISA_CFG_IOP_MASK);
4979: return (inpw(eisa_cfg_iop));
4980: }
4981:
4982: uchar
4983: AscSetChipScsiID(
4984: PortAddr iop_base,
4985: uchar new_host_id
4986: )
4987: {
4988: ushort cfg_lsw;
4989:
4990: if (AscGetChipScsiID(iop_base) == new_host_id) {
4991: return (new_host_id);
4992: }
4993: cfg_lsw = AscGetChipCfgLsw(iop_base);
4994: cfg_lsw &= 0xF8FF;
4995: cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
4996: AscSetChipCfgLsw(iop_base, cfg_lsw);
4997: return (AscGetChipScsiID(iop_base));
4998: }
4999:
5000: ushort
5001: AscGetChipBiosAddress(
5002: PortAddr iop_base,
5003: ushort bus_type
5004: )
5005: {
5006: ushort cfg_lsw;
5007: ushort bios_addr;
5008:
5009: if ((bus_type & ASC_IS_EISA) != 0) {
5010: cfg_lsw = AscGetEisaChipCfg(iop_base);
5011: cfg_lsw &= 0x000F;
5012: bios_addr = (ushort) (ASC_BIOS_MIN_ADDR +
5013: (cfg_lsw * ASC_BIOS_BANK_SIZE));
5014: return (bios_addr);
5015: }
5016: cfg_lsw = AscGetChipCfgLsw(iop_base);
5017: bios_addr = (ushort) (((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ASC_BIOS_MIN_ADDR);
5018: return (bios_addr);
5019: }
5020:
5021: uchar
5022: AscGetChipVersion(
5023: PortAddr iop_base,
5024: ushort bus_type
5025: )
5026: {
5027: if ((bus_type & ASC_IS_EISA) != 0) {
5028:
5029: PortAddr eisa_iop;
5030: uchar revision;
5031:
5032: eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
5033: (PortAddr) ASC_EISA_REV_IOP_MASK;
5034: revision = inp(eisa_iop);
5035: return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
5036: }
5037: return (AscGetChipVerNo(iop_base));
5038: }
5039:
5040: ushort
5041: AscGetChipBusType(
5042: PortAddr iop_base
5043: )
5044: {
5045: ushort chip_ver;
5046:
5047: chip_ver = AscGetChipVerNo(iop_base);
5048: if ((chip_ver >= ASC_CHIP_MIN_VER_VL) &&
5049: (chip_ver <= ASC_CHIP_MAX_VER_VL)) {
5050: if (((iop_base & 0x0C30) == 0x0C30) ||
5051: ((iop_base & 0x0C50) == 0x0C50)) {
5052: return (ASC_IS_EISA);
5053: }
5054: return (ASC_IS_VL);
5055: } else if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
5056: (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
5057: if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
5058: return (ASC_IS_ISAPNP);
5059: }
5060: return (ASC_IS_ISA);
5061: } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
5062: (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
5063: return (ASC_IS_PCI);
5064: } else {
5065: return (0);
5066: }
5067: }
5068:
5069: void
5070: AscEnableIsaDma(
5071: uchar dma_channel
5072: )
5073: {
5074: if (dma_channel < 4) {
5075: outp(0x000B, (ushort) (0xC0 | dma_channel));
5076: outp(0x000A, dma_channel);
5077: } else if (dma_channel < 8) {
5078:
5079: outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
5080: outp(0x00D4, (ushort) (dma_channel - 4));
5081: }
5082: return;
5083: }
5084:
5085: ulong
5086: AscLoadMicroCode(
5087: PortAddr iop_base,
5088: ushort s_addr,
5089: ushort dosfar * mcode_buf,
5090: ushort mcode_size
5091: )
5092: {
5093: ulong chksum;
5094: ushort mcode_word_size;
5095: ushort mcode_chksum;
5096:
5097: mcode_word_size = (ushort) (mcode_size >> 1);
5098: AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
5099: AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
5100:
5101: chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
5102: mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
5103: (ushort) ASC_CODE_SEC_BEG,
5104: (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
5105: AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
5106: AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
5107: return (chksum);
5108: }
5109:
5110: uchar _hextbl_[16] =
5111: {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5112: 'A', 'B', 'C', 'D', 'E', 'F'};
5113:
5114: uchar _isa_pnp_inited = 0;
5115:
5116: PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] =
5117: {
5118: 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
5119: ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
5120: };
5121:
5122: PortAddr
5123: AscSearchIOPortAddr(
5124: PortAddr iop_beg,
5125: ushort bus_type
5126: )
5127: {
5128: if (bus_type & ASC_IS_VL) {
5129: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
5130: if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
5131: return (iop_beg);
5132: }
5133: }
5134: return (0);
5135: }
5136: if (bus_type & ASC_IS_ISA) {
5137: if (_isa_pnp_inited == 0) {
5138: AscSetISAPNPWaitForKey();
5139: _isa_pnp_inited++;
5140: }
5141: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
5142: if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
5143: return (iop_beg);
5144: }
5145: }
5146: return (0);
5147: }
5148: if (bus_type & ASC_IS_EISA) {
5149: if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
5150: return (iop_beg);
5151: }
5152: return (0);
5153: }
5154: return (0);
5155: }
5156:
5157: PortAddr
5158: AscSearchIOPortAddr11(
5159: PortAddr s_addr
5160: )
5161: {
5162:
5163: int i;
5164: PortAddr iop_base;
5165:
5166: for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
5167: if (_asc_def_iop_base[i] > s_addr) {
5168: break;
5169: }
5170: }
5171: for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
5172: iop_base = _asc_def_iop_base[i];
5173: if (AscFindSignature(iop_base)) {
5174: return (iop_base);
5175: }
5176: }
5177: return (0);
5178: }
5179:
5180: int
5181: AscFindSignature(
5182: PortAddr iop_base
5183: )
5184: {
5185: ushort sig_word;
5186:
5187: if ((inp((PortAddr) (iop_base + 1)) & 0xFF) == (uchar) ASC_1000_ID1B) {
5188: sig_word = inpw(iop_base);
5189: if ((sig_word == (ushort) ASC_1000_ID0W) ||
5190: (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
5191: return (1);
5192: }
5193: }
5194: return (0);
5195: }
5196:
5197: void
5198: AscToggleIRQAct(
5199: PortAddr iop_base
5200: )
5201: {
5202: AscSetChipStatus(iop_base, CIW_IRQ_ACT);
5203: AscSetChipStatus(iop_base, 0);
5204: return;
5205: }
5206:
5207: #if CC_INIT_INQ_DISPLAY
5208:
5209: #endif
5210:
5211: void
5212: AscSetISAPNPWaitForKey(
5213: void)
5214: {
5215:
5216: outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
5217: outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
5218: return;
5219: }
5220:
5221: uchar
5222: AscGetChipIRQ(
5223: PortAddr iop_base,
5224: ushort bus_type
5225: )
5226: {
5227: ushort cfg_lsw;
5228: uchar chip_irq;
5229:
5230: if ((bus_type & ASC_IS_EISA) != 0) {
5231:
5232: cfg_lsw = AscGetEisaChipCfg(iop_base);
5233: chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
5234: if ((chip_irq == 13) || (chip_irq > 15)) {
5235:
5236: return (0);
5237: }
5238: return (chip_irq);
5239: } else {
5240:
5241: cfg_lsw = AscGetChipCfgLsw(iop_base);
5242:
5243: if ((bus_type & ASC_IS_VL) != 0) {
5244:
5245: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
5246: if ((chip_irq == 0) ||
5247: (chip_irq == 4) ||
5248: (chip_irq == 7)) {
5249: return (0);
5250: }
5251: return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
5252: }
5253: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
5254: if (chip_irq == 3)
5255: chip_irq += (uchar) 2;
5256: return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
5257: }
5258: }
5259:
5260: uchar
5261: AscSetChipIRQ(
5262: PortAddr iop_base,
5263: uchar irq_no,
5264: ushort bus_type
5265: )
5266: {
5267: ushort cfg_lsw;
5268:
5269: if ((bus_type & ASC_IS_VL) != 0) {
5270:
5271: if (irq_no != 0) {
5272: if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
5273: irq_no = 0;
5274: } else {
5275: irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
5276: }
5277: }
5278: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
5279: cfg_lsw |= (ushort) 0x0010;
5280: AscSetChipCfgLsw(iop_base, cfg_lsw);
5281: AscToggleIRQAct(iop_base);
5282:
5283: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
5284: cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
5285: AscSetChipCfgLsw(iop_base, cfg_lsw);
5286: AscToggleIRQAct(iop_base);
5287:
5288: return (AscGetChipIRQ(iop_base, bus_type));
5289:
5290: } else if ((bus_type & (ASC_IS_ISA)) != 0) {
5291:
5292: if (irq_no == 15)
5293: irq_no -= (uchar) 2;
5294: irq_no -= (uchar) ASC_MIN_IRQ_NO;
5295: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
5296: cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
5297: AscSetChipCfgLsw(iop_base, cfg_lsw);
5298: return (AscGetChipIRQ(iop_base, bus_type));
5299: } else {
5300:
5301: return (0);
5302: }
5303: }
5304:
5305: uchar
5306: AscGetChipScsiCtrl(
5307: PortAddr iop_base
5308: )
5309: {
5310: uchar sc;
5311:
5312: AscSetBank(iop_base, 1);
5313: sc = inp(iop_base + IOP_REG_SC);
5314: AscSetBank(iop_base, 0);
5315: return (sc);
5316: }
5317:
5318: extern uchar _sdtr_period_tbl_[];
5319:
5320: int
5321: AscIsrChipHalted(
5322: ASC_DVC_VAR asc_ptr_type * asc_dvc
5323: )
5324: {
5325: SDTR_XMSG sdtr_xmsg;
5326: SDTR_XMSG out_msg;
5327: ushort halt_q_addr;
5328: int sdtr_accept;
5329: ushort int_halt_code;
5330: ASC_SCSI_BIT_ID_TYPE scsi_busy;
5331: ASC_SCSI_BIT_ID_TYPE target_id;
5332: PortAddr iop_base;
5333: uchar tag_code;
5334: uchar q_status;
5335: uchar halt_qp;
5336: uchar sdtr_data;
5337: uchar target_ix;
5338: uchar q_cntl, tid_no;
5339: uchar cur_dvc_qng;
5340: uchar asyn_sdtr;
5341: uchar scsi_status;
5342:
5343: iop_base = asc_dvc->iop_base;
5344: int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
5345:
5346: halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
5347: halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
5348: target_ix = AscReadLramByte(iop_base,
5349: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
5350: q_cntl = AscReadLramByte(iop_base,
5351: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
5352: tid_no = ASC_TIX_TO_TID(target_ix);
5353: target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
5354: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
5355:
5356: asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
5357: } else {
5358: asyn_sdtr = 0;
5359: }
5360: if (int_halt_code == ASC_HALT_EXTMSG_IN) {
5361:
5362: AscMemWordCopyFromLram(iop_base,
5363: ASCV_MSGIN_BEG,
5364: (ushort dosfar *) & sdtr_xmsg,
5365: (ushort) (sizeof (SDTR_XMSG) >> 1));
5366: if ((sdtr_xmsg.msg_type == MS_EXTEND) &&
5367: (sdtr_xmsg.msg_len == MS_SDTR_LEN)) {
5368: sdtr_accept = TRUE;
5369: if (sdtr_xmsg.msg_req == MS_SDTR_CODE) {
5370: if (sdtr_xmsg.req_ack_offset > ASC_SYN_MAX_OFFSET) {
5371:
5372: sdtr_accept = FALSE;
5373: sdtr_xmsg.req_ack_offset = ASC_SYN_MAX_OFFSET;
5374: }
5375: sdtr_data = AscCalSDTRData(sdtr_xmsg.xfer_period,
5376: sdtr_xmsg.req_ack_offset);
5377: if (sdtr_xmsg.req_ack_offset == 0) {
5378:
5379: q_cntl &= ~QC_MSG_OUT;
5380: asc_dvc->init_sdtr &= ~target_id;
5381: asc_dvc->sdtr_done &= ~target_id;
5382: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
5383: } else if ((sdtr_data == 0xFF)) {
5384:
5385: q_cntl |= QC_MSG_OUT;
5386: asc_dvc->init_sdtr &= ~target_id;
5387: asc_dvc->sdtr_done &= ~target_id;
5388: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
5389: } else {
5390: if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
5391:
5392: q_cntl &= ~QC_MSG_OUT;
5393: asc_dvc->sdtr_done |= target_id;
5394: asc_dvc->init_sdtr |= target_id;
5395: asc_dvc->pci_fix_asyn_xfer &= ~target_id;
5396: AscSetChipSDTR(iop_base, sdtr_data, tid_no);
5397: } else {
5398:
5399: q_cntl |= QC_MSG_OUT;
5400:
5401: AscMsgOutSDTR(iop_base,
5402: sdtr_xmsg.xfer_period,
5403: sdtr_xmsg.req_ack_offset);
5404: asc_dvc->pci_fix_asyn_xfer &= ~target_id;
5405: AscSetChipSDTR(iop_base, sdtr_data, tid_no);
5406: asc_dvc->sdtr_done |= target_id;
5407: asc_dvc->init_sdtr |= target_id;
5408: }
5409: }
5410:
5411: AscWriteLramByte(iop_base,
5412: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
5413: q_cntl);
5414: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5415: return (0);
5416: }
5417: }
5418: } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
5419:
5420: q_cntl |= QC_REQ_SENSE;
5421: if (((asc_dvc->init_sdtr & target_id) != 0) &&
5422: ((asc_dvc->sdtr_done & target_id) != 0)) {
5423:
5424: sdtr_data = AscReadLramByte(iop_base,
5425: (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
5426: AscMsgOutSDTR(iop_base,
5427: _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
5428: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
5429: q_cntl |= QC_MSG_OUT;
5430: }
5431: AscWriteLramByte(iop_base,
5432: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
5433: q_cntl);
5434:
5435: tag_code = AscReadLramByte(iop_base,
5436: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
5437: tag_code &= 0xDC;
5438: AscWriteLramByte(iop_base,
5439: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
5440: tag_code);
5441:
5442: q_status = AscReadLramByte(iop_base,
5443: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
5444: q_status |= (QS_READY | QS_BUSY);
5445: AscWriteLramByte(iop_base,
5446: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
5447: q_status);
5448:
5449: scsi_busy = AscReadLramByte(iop_base,
5450: (ushort) ASCV_SCSIBUSY_B);
5451: scsi_busy &= ~target_id;
5452: AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
5453:
5454: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5455: return (0);
5456: } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
5457:
5458: AscMemWordCopyFromLram(iop_base,
5459: ASCV_MSGOUT_BEG,
5460: (ushort dosfar *) & out_msg,
5461: (ushort) (sizeof (SDTR_XMSG) >> 1));
5462:
5463: if ((out_msg.msg_type == MS_EXTEND) &&
5464: (out_msg.msg_len == MS_SDTR_LEN) &&
5465: (out_msg.msg_req == MS_SDTR_CODE)) {
5466:
5467: asc_dvc->init_sdtr &= ~target_id;
5468: asc_dvc->sdtr_done &= ~target_id;
5469: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
5470:
5471: } else {
5472:
5473: }
5474:
5475: q_cntl &= ~QC_MSG_OUT;
5476: AscWriteLramByte(iop_base,
5477: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
5478: q_cntl);
5479: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5480: return (0);
5481: } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
5482:
5483: scsi_status = AscReadLramByte(iop_base,
5484: (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
5485: cur_dvc_qng = AscReadLramByte(iop_base,
5486: (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
5487: if ((cur_dvc_qng > 0) &&
5488: (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
5489:
5490: scsi_busy = AscReadLramByte(iop_base,
5491: (ushort) ASCV_SCSIBUSY_B);
5492: scsi_busy |= target_id;
5493: AscWriteLramByte(iop_base,
5494: (ushort) ASCV_SCSIBUSY_B, scsi_busy);
5495: asc_dvc->queue_full_or_busy |= target_id;
5496:
5497: if (scsi_status == SS_QUEUE_FULL) {
5498: if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
5499: cur_dvc_qng -= 1;
5500: asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
5501:
5502: AscWriteLramByte(iop_base,
5503: (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no),
5504: cur_dvc_qng);
5505: }
5506: }
5507: }
5508: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
5509: return (0);
5510: }
5511: return (0);
5512: }
5513:
5514: uchar
5515: _AscCopyLramScsiDoneQ(
5516: PortAddr iop_base,
5517: ushort q_addr,
5518: ASC_QDONE_INFO dosfar * scsiq,
5519: ulong max_dma_count
5520: )
5521: {
5522: ushort _val;
5523: uchar sg_queue_cnt;
5524:
5525: DvcGetQinfo(iop_base,
5526: (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
5527: (ushort dosfar *) scsiq,
5528: (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
5529:
5530: #if !CC_LITTLE_ENDIAN_HOST
5531: AscAdjEndianQDoneInfo(scsiq);
5532: #endif
5533:
5534: _val = AscReadLramWord(iop_base,
5535: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
5536: scsiq->q_status = (uchar) _val;
5537: scsiq->q_no = (uchar) (_val >> 8);
5538:
5539: _val = AscReadLramWord(iop_base,
5540: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
5541: scsiq->cntl = (uchar) _val;
5542: sg_queue_cnt = (uchar) (_val >> 8);
5543:
5544: _val = AscReadLramWord(iop_base,
5545: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
5546: scsiq->sense_len = (uchar) _val;
5547: scsiq->user_def = (uchar) (_val >> 8);
5548:
5549: scsiq->remain_bytes = AscReadLramDWord(iop_base,
5550: (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
5551: scsiq->remain_bytes &= max_dma_count;
5552:
5553: return (sg_queue_cnt);
5554: }
5555:
5556: int
5557: AscIsrQDone(
5558: ASC_DVC_VAR asc_ptr_type * asc_dvc
5559: )
5560: {
5561: uchar next_qp;
5562: uchar i;
5563: uchar n_q_used;
5564: uchar sg_list_qp;
5565: uchar sg_queue_cnt;
5566: uchar done_q_tail;
5567:
5568: uchar tid_no;
5569: ASC_SCSI_BIT_ID_TYPE scsi_busy;
5570: ASC_SCSI_BIT_ID_TYPE target_id;
5571: PortAddr iop_base;
5572: ushort q_addr;
5573: ushort sg_q_addr;
5574: uchar cur_target_qng;
5575: ASC_QDONE_INFO scsiq_buf;
5576: ASC_QDONE_INFO dosfar *scsiq;
5577: int false_overrun;
5578: ASC_ISR_CALLBACK asc_isr_callback;
5579:
5580: uchar tag_code;
5581:
5582: #if CC_LINK_BUSY_Q
5583: ushort n_busy_q_done;
5584:
5585: #endif
5586:
5587: iop_base = asc_dvc->iop_base;
5588: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
5589:
5590: n_q_used = 1;
5591: scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
5592: done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
5593: q_addr = ASC_QNO_TO_QADDR(done_q_tail);
5594: next_qp = AscReadLramByte(iop_base,
5595: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
5596: if (next_qp != ASC_QLINK_END) {
5597:
5598: AscPutVarDoneQTail(iop_base, next_qp);
5599: q_addr = ASC_QNO_TO_QADDR(next_qp);
5600:
5601: sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
5602:
5603: AscWriteLramByte(iop_base,
5604: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
5605: (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
5606: tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
5607: target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
5608: if ((scsiq->cntl & QC_SG_HEAD) != 0) {
5609: sg_q_addr = q_addr;
5610: sg_list_qp = next_qp;
5611: for (i = 0; i < sg_queue_cnt; i++) {
5612: sg_list_qp = AscReadLramByte(iop_base,
5613: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
5614: sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
5615: if (sg_list_qp == ASC_QLINK_END) {
5616: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
5617: scsiq->d3.done_stat = QD_WITH_ERROR;
5618: scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
5619: goto FATAL_ERR_QDONE;
5620: }
5621: AscWriteLramByte(iop_base,
5622: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
5623: QS_FREE);
5624: }
5625:
5626: n_q_used = sg_queue_cnt + 1;
5627: AscPutVarDoneQTail(iop_base, sg_list_qp);
5628: }
5629: if (asc_dvc->queue_full_or_busy & target_id) {
5630:
5631: cur_target_qng = AscReadLramByte(iop_base,
5632: (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
5633: if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
5634: scsi_busy = AscReadLramByte(iop_base,
5635: (ushort) ASCV_SCSIBUSY_B);
5636: scsi_busy &= ~target_id;
5637: AscWriteLramByte(iop_base,
5638: (ushort) ASCV_SCSIBUSY_B, scsi_busy);
5639: asc_dvc->queue_full_or_busy &= ~target_id;
5640: }
5641: }
5642: if (asc_dvc->cur_total_qng >= n_q_used) {
5643: asc_dvc->cur_total_qng -= n_q_used;
5644: if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
5645: asc_dvc->cur_dvc_qng[tid_no]--;
5646: }
5647: } else {
5648: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
5649: scsiq->d3.done_stat = QD_WITH_ERROR;
5650: goto FATAL_ERR_QDONE;
5651: }
5652:
5653: if ((scsiq->d2.srb_ptr == 0UL) ||
5654: ((scsiq->q_status & QS_ABORTED) != 0)) {
5655:
5656: return (0x11);
5657: } else if (scsiq->q_status == QS_DONE) {
5658:
5659: false_overrun = FALSE;
5660:
5661: if (asc_dvc->bug_fix_cntl) {
5662: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
5663: tag_code = AscReadLramByte(iop_base,
5664: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
5665: if (tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) {
5666: if (scsiq->remain_bytes != 0UL) {
5667: scsiq->remain_bytes--;
5668: if (scsiq->remain_bytes == 0UL) {
5669: false_overrun = TRUE;
5670: }
5671: }
5672: }
5673: }
5674: }
5675: if ((scsiq->d3.done_stat == QD_WITH_ERROR) &&
5676: (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) {
5677: if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
5678: scsiq->d3.done_stat = QD_NO_ERROR;
5679: scsiq->d3.host_stat = QHSTA_NO_ERROR;
5680: } else if (false_overrun) {
5681: scsiq->d3.done_stat = QD_NO_ERROR;
5682: scsiq->d3.host_stat = QHSTA_NO_ERROR;
5683: }
5684: }
5685: #if CC_CLEAR_LRAM_SRB_PTR
5686: AscWriteLramDWord(iop_base,
5687: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
5688: asc_dvc->int_count);
5689: #endif
5690:
5691: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
5692: (*asc_isr_callback) (asc_dvc, scsiq);
5693: } else {
5694: if ((AscReadLramByte(iop_base,
5695: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
5696: SCSICMD_StartStopUnit)) {
5697:
5698: asc_dvc->unit_not_ready &= ~target_id;
5699: if (scsiq->d3.done_stat != QD_NO_ERROR) {
5700: asc_dvc->start_motor &= ~target_id;
5701: }
5702: }
5703: }
5704:
5705: #if CC_LINK_BUSY_Q
5706: n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, tid_no);
5707: if (n_busy_q_done == 0) {
5708:
5709: i = tid_no + 1;
5710: while (TRUE) {
5711: if (i > ASC_MAX_TID)
5712: i = 0;
5713: if (i == tid_no)
5714: break;
5715: n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, i);
5716: if (n_busy_q_done != 0)
5717: break;
5718: i++;
5719: }
5720: }
5721: if (n_busy_q_done == 0xFFFF)
5722: return (0x80);
5723: #endif
5724:
5725: return (1);
5726: } else {
5727:
5728: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
5729:
5730: FATAL_ERR_QDONE:
5731: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
5732: (*asc_isr_callback) (asc_dvc, scsiq);
5733: }
5734: return (0x80);
5735: }
5736: }
5737: return (0);
5738: }
5739:
5740: int
5741: AscISR(
5742: ASC_DVC_VAR asc_ptr_type * asc_dvc
5743: )
5744: {
5745: ASC_CS_TYPE chipstat;
5746: PortAddr iop_base;
5747: ushort saved_ram_addr;
5748: uchar ctrl_reg;
5749: uchar saved_ctrl_reg;
5750: int int_pending;
5751: int status;
5752: uchar host_flag;
5753:
5754: iop_base = asc_dvc->iop_base;
5755: int_pending = FALSE;
5756:
5757: asc_dvc->int_count++;
5758:
5759: if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) ||
5760: (asc_dvc->isr_callback == 0)) {
5761:
5762: return (ERR);
5763: }
5764: if (asc_dvc->in_critical_cnt != 0) {
5765: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
5766: return (ERR);
5767: }
5768: if (asc_dvc->is_in_int) {
5769: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
5770: asc_dvc->busy_count++;
5771: return (ERR);
5772: }
5773: asc_dvc->is_in_int = TRUE;
5774: ctrl_reg = AscGetChipControl(iop_base);
5775: saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
5776: CC_SINGLE_STEP | CC_DIAG | CC_TEST));
5777:
5778: if ((chipstat = AscGetChipStatus(iop_base)) & CSW_INT_PENDING) {
5779: int_pending = TRUE;
5780: AscAckInterrupt(iop_base);
5781:
5782: host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
5783: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
5784: (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
5785: saved_ram_addr = AscGetChipLramAddr(iop_base);
5786:
5787: if ((chipstat & CSW_HALTED) &&
5788: (ctrl_reg & CC_SINGLE_STEP)) {
5789: if (AscIsrChipHalted(asc_dvc) == ERR) {
5790:
5791: goto ISR_REPORT_QDONE_FATAL_ERROR;
5792:
5793: } else {
5794: saved_ctrl_reg &= ~CC_HALT;
5795: }
5796: } else {
5797: ISR_REPORT_QDONE_FATAL_ERROR:
5798: if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
5799: while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
5800:
5801: }
5802: } else {
5803: do {
5804: if ((status = AscIsrQDone(asc_dvc)) == 1) {
5805:
5806: break;
5807: }
5808: } while (status == 0x11);
5809: }
5810: if ((status & 0x80) != 0)
5811: int_pending = ERR;
5812: }
5813: AscSetChipLramAddr(iop_base, saved_ram_addr);
5814: if (AscGetChipLramAddr(iop_base) != saved_ram_addr) {
5815: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SET_LRAM_ADDR);
5816: }
5817: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
5818: }
5819: AscSetChipControl(iop_base, saved_ctrl_reg);
5820: asc_dvc->is_in_int = FALSE;
5821: return (int_pending);
5822: }
5823:
5824: int
5825: AscScsiSetupCmdQ(
5826: ASC_DVC_VAR asc_ptr_type * asc_dvc,
5827: ASC_SCSI_REQ_Q dosfar * scsiq,
5828: uchar dosfar * buf_addr,
5829: ulong buf_len
5830: )
5831: {
5832: ulong phy_addr;
5833:
5834: scsiq->r1.cntl = 0;
5835: scsiq->r1.sg_queue_cnt = 0;
5836: scsiq->r1.q_no = 0;
5837: scsiq->r1.user_def = 0;
5838: scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
5839: scsiq->r3.scsi_stat = 0;
5840: scsiq->r3.scsi_msg = 0;
5841: scsiq->r3.host_stat = 0;
5842: scsiq->r3.done_stat = 0;
5843: scsiq->r2.vm_id = 0;
5844: scsiq->r1.data_cnt = buf_len;
5845:
5846: scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
5847: scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
5848: scsiq->r2.srb_ptr = (ulong) scsiq;
5849: scsiq->r1.status = (uchar) QS_READY;
5850: scsiq->r1.data_addr = 0L;
5851:
5852: if (buf_len != 0L) {
5853: if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
5854: (uchar dosfar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
5855: return (ERR);
5856: }
5857: scsiq->r1.data_addr = phy_addr;
5858: }
5859: return (0);
5860: }
5861:
5862: uchar _mcode_buf[] =
5863: {
5864: 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5865: 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5866: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5867: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5868: 0x00, 0x00, 0x00, 0x00, 0xDD, 0x0A, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
5869: 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5870: 0x00, 0x00, 0x00, 0x23, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
5871: 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x88, 0x00, 0x00, 0x00, 0x00,
5872: 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC8, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
5873: 0xB6, 0x00, 0x36, 0x00, 0x06, 0xD6, 0x0D, 0xD2, 0x15, 0xDE, 0x12, 0xDA, 0x00, 0xA2, 0xC8, 0x00,
5874: 0x92, 0x80, 0xE0, 0x97, 0x50, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00,
5875: 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
5876: 0x80, 0x62, 0x92, 0x80, 0x00, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01,
5877: 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDC, 0x00, 0x68, 0x97, 0x7F, 0x23, 0x04, 0x61,
5878: 0x84, 0x01, 0xB2, 0x84, 0xCF, 0xC1, 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE8, 0x01,
5879: 0x68, 0x97, 0xD4, 0x81, 0x00, 0x33, 0x02, 0x00, 0x82, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01,
5880: 0x01, 0xA1, 0x08, 0x01, 0x4F, 0x00, 0x46, 0x97, 0x07, 0xA6, 0x12, 0x01, 0x00, 0x33, 0x03, 0x00,
5881: 0x82, 0x88, 0x03, 0x03, 0x03, 0xDE, 0x00, 0x33, 0x05, 0x00, 0x82, 0x88, 0xCE, 0x00, 0x69, 0x60,
5882: 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x86, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x32, 0x01,
5883: 0x86, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x42, 0x01, 0x00, 0x33, 0x04, 0x00,
5884: 0x82, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x2A, 0x98, 0x4D, 0x04, 0xD0, 0x84,
5885: 0x05, 0xD8, 0x0D, 0x23, 0x2A, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xB8, 0x88, 0xFB, 0x23, 0x02, 0x61,
5886: 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x70, 0x01, 0x00, 0x33, 0x0A, 0x00, 0x82, 0x88,
5887: 0x4E, 0x00, 0x07, 0xA3, 0x7C, 0x01, 0x00, 0x33, 0x0B, 0x00, 0x82, 0x88, 0xCD, 0x04, 0x36, 0x2D,
5888: 0x00, 0x33, 0x1A, 0x00, 0x82, 0x88, 0x50, 0x04, 0x96, 0x81, 0x06, 0xAB, 0x90, 0x01, 0x96, 0x81,
5889: 0x4E, 0x00, 0x07, 0xA3, 0xA0, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x4A, 0x01, 0x00, 0x05, 0x8A, 0x81,
5890: 0x08, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xCC, 0x81,
5891: 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xC2, 0x01,
5892: 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0x82, 0x88, 0x06, 0x23, 0x2A, 0x98,
5893: 0xCD, 0x04, 0xB2, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xE2, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE8, 0x01,
5894: 0xB2, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xB2, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2,
5895: 0x10, 0x02, 0x04, 0x01, 0x0D, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x46, 0x97, 0x0A, 0x82,
5896: 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x24, 0x97, 0x48, 0x04, 0xFF, 0x23, 0x84, 0x80,
5897: 0xB2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
5898: 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x66, 0xEB, 0x11, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0xFA, 0x80,
5899: 0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x3E, 0x02, 0x00, 0x33, 0x31, 0x00, 0x82, 0x88, 0x04, 0x01,
5900: 0x03, 0xD8, 0x74, 0x98, 0x02, 0x96, 0x50, 0x82, 0xA2, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
5901: 0xB6, 0x2D, 0x02, 0xA6, 0x7A, 0x02, 0x07, 0xA6, 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x03, 0xA6,
5902: 0x70, 0x02, 0x00, 0x33, 0x10, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x52, 0x82, 0xF8, 0x95, 0x52, 0x82,
5903: 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x16, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23,
5904: 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23,
5905: 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAC, 0x02, 0x07, 0xA6,
5906: 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x12, 0x00, 0x82, 0x88, 0x00, 0x0E, 0x80, 0x63,
5907: 0x00, 0x43, 0x00, 0xA0, 0x9A, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61,
5908: 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
5909: 0xEC, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE4, 0x02, 0x04, 0x01, 0x8E, 0xC8, 0x00, 0x33,
5910: 0x1F, 0x00, 0x82, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x40, 0x98, 0xB6, 0x2D,
5911: 0x01, 0xA6, 0x0E, 0x03, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x2A, 0x03, 0x06, 0xA6, 0x2E, 0x03,
5912: 0x03, 0xA6, 0xFA, 0x03, 0x02, 0xA6, 0x7A, 0x02, 0x00, 0x33, 0x33, 0x00, 0x82, 0x88, 0x08, 0x23,
5913: 0xB3, 0x01, 0x04, 0x01, 0x0E, 0xD0, 0x00, 0x33, 0x14, 0x00, 0x82, 0x88, 0x10, 0x23, 0xB3, 0x01,
5914: 0x04, 0x01, 0x07, 0xCC, 0x00, 0x33, 0x15, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xF0, 0x82, 0xF8, 0x95,
5915: 0xF0, 0x82, 0x44, 0x98, 0x80, 0x42, 0x40, 0x98, 0x48, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05,
5916: 0x07, 0x01, 0x00, 0xA2, 0x72, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x48, 0x98, 0x40, 0x98,
5917: 0x00, 0xA6, 0x34, 0x03, 0x07, 0xA6, 0x6A, 0x03, 0x03, 0xA6, 0x16, 0x04, 0x06, 0xA6, 0x6E, 0x03,
5918: 0x01, 0xA6, 0x34, 0x03, 0x00, 0x33, 0x25, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x50, 0x83, 0xF8, 0x95,
5919: 0x50, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0x82, 0x88, 0x00, 0x01,
5920: 0x05, 0x05, 0xFF, 0xA2, 0x90, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x4C, 0x83, 0x05, 0x05,
5921: 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0xAA, 0x03, 0xF0, 0x83, 0x68, 0x98, 0x80, 0x42, 0x01, 0xA6,
5922: 0x9A, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x2F, 0x00, 0x82, 0x88, 0x68, 0x98, 0x80, 0x42, 0x00, 0xA6,
5923: 0xAA, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x26, 0x00, 0x82, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36,
5924: 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0xF0, 0x83, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33,
5925: 0x20, 0x00, 0x82, 0x88, 0x03, 0xA6, 0xEE, 0x03, 0x07, 0xA6, 0xE6, 0x03, 0x06, 0xA6, 0xEA, 0x03,
5926: 0x00, 0x33, 0x17, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xD4, 0x83, 0xF8, 0x95, 0xD4, 0x83, 0xFA, 0x83,
5927: 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0x82, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x16, 0x04,
5928: 0x07, 0xA6, 0x0E, 0x04, 0x06, 0xA6, 0x12, 0x04, 0x00, 0x33, 0x30, 0x00, 0x82, 0x88, 0x4A, 0x95,
5929: 0xFA, 0x83, 0xF8, 0x95, 0xFA, 0x83, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x24, 0x04, 0x00, 0x33,
5930: 0x18, 0x00, 0x82, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x2E, 0x04, 0x23, 0x01,
5931: 0x00, 0xA2, 0x50, 0x04, 0x0A, 0xA0, 0x40, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0x82, 0x88,
5932: 0x0B, 0xA0, 0x4C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0x82, 0x88, 0x42, 0x23, 0xB8, 0x88,
5933: 0x00, 0x23, 0x22, 0xA3, 0xB2, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x6C, 0x04, 0x28, 0x23, 0x22, 0xA3,
5934: 0x78, 0x04, 0x02, 0x23, 0x22, 0xA3, 0x8E, 0x04, 0x42, 0x23, 0xB8, 0x88, 0x4A, 0x00, 0x06, 0x61,
5935: 0x00, 0xA0, 0x78, 0x04, 0x45, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0x00, 0xA2, 0x8A, 0x04, 0x74, 0x98,
5936: 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF6, 0x81, 0x47, 0x23, 0xB8, 0x88, 0x04, 0x01,
5937: 0x0C, 0xDE, 0x14, 0x01, 0x00, 0xA2, 0xA6, 0x04, 0xC6, 0x97, 0x74, 0x98, 0x00, 0x33, 0x00, 0x81,
5938: 0xC0, 0x20, 0x81, 0x62, 0x10, 0x82, 0x43, 0x23, 0xB8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23,
5939: 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xC0, 0x04, 0x00, 0x33, 0x27, 0x00, 0x82, 0x88,
5940: 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xC6, 0x97, 0xF4, 0x94,
5941: 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0xEE, 0x04, 0x00, 0x05, 0x76, 0x00,
5942: 0x06, 0x61, 0x00, 0xA2, 0xE8, 0x04, 0xD6, 0x84, 0x08, 0x97, 0xCD, 0x04, 0xF2, 0x84, 0x48, 0x04,
5943: 0xFF, 0x23, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x02, 0x85, 0x02, 0x23,
5944: 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 0x05, 0x1D, 0x01, 0x04, 0xD6, 0xFF, 0x23,
5945: 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, 0x04, 0x01,
5946: 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00,
5947: 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x2E, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00,
5948: 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xA0, 0x05, 0x03, 0x03,
5949: 0x02, 0xA0, 0x5C, 0x05, 0x9C, 0x85, 0x00, 0x33, 0x2D, 0x00, 0x82, 0x88, 0x04, 0xA0, 0x82, 0x05,
5950: 0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x6E, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23,
5951: 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x24, 0x97, 0xD0, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01,
5952: 0xD0, 0x84, 0x08, 0xA0, 0x88, 0x05, 0x9C, 0x85, 0x03, 0xA0, 0x8E, 0x05, 0x9C, 0x85, 0x01, 0xA0,
5953: 0x9A, 0x05, 0x88, 0x00, 0x80, 0x63, 0x78, 0x96, 0x4A, 0x85, 0x88, 0x86, 0x80, 0x63, 0x4A, 0x85,
5954: 0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xDE, 0x05, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23,
5955: 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xC0, 0x05, 0x00, 0x33, 0x37, 0x00, 0x82, 0x88,
5956: 0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xB8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
5957: 0xD8, 0x05, 0x00, 0x33, 0x38, 0x00, 0x82, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00,
5958: 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xF2, 0x05, 0xC0, 0x23, 0x07, 0x41,
5959: 0x00, 0x63, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63,
5960: 0x00, 0x63, 0x06, 0xA6, 0x14, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x02, 0xA6, 0xBC, 0x06, 0x00, 0x33,
5961: 0x39, 0x00, 0x82, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xD6, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
5962: 0x06, 0xA6, 0x28, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
5963: 0x01, 0x00, 0x06, 0xA6, 0x40, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3A, 0x00, 0x82, 0x88,
5964: 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x32, 0x06, 0x06, 0xA6, 0x58, 0x06, 0x07, 0xA6,
5965: 0x64, 0x06, 0x00, 0x33, 0x3B, 0x00, 0x82, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6,
5966: 0x64, 0x06, 0x00, 0x63, 0x03, 0x03, 0x80, 0x63, 0x88, 0x00, 0x01, 0xA2, 0x78, 0x06, 0x07, 0xA2,
5967: 0xBC, 0x06, 0x00, 0x33, 0x35, 0x00, 0x82, 0x88, 0x07, 0xA6, 0x82, 0x06, 0x00, 0x33, 0x2A, 0x00,
5968: 0x82, 0x88, 0x03, 0x03, 0x03, 0xA2, 0x8E, 0x06, 0x07, 0x23, 0x80, 0x00, 0xC8, 0x86, 0x80, 0x63,
5969: 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0x9E, 0x06, 0x00, 0x33, 0x29, 0x00, 0x82, 0x88, 0x00, 0x43,
5970: 0x00, 0xA2, 0xAA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0x94, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80,
5971: 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x00, 0x63, 0x80, 0x67, 0x00, 0x33,
5972: 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x20, 0x06,
5973: 0x00, 0x33, 0x2C, 0x00, 0x82, 0x88, 0x0C, 0xA2, 0xF0, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
5974: 0x06, 0xA6, 0xEE, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3D, 0x00, 0x82, 0x88, 0x00, 0x00,
5975: 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x06, 0x07, 0x07, 0xA6, 0x64, 0x06, 0xBF, 0x23,
5976: 0x04, 0x61, 0x84, 0x01, 0xB2, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01,
5977: 0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05,
5978: 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00,
5979: 0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00,
5980: 0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00,
5981: 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04,
5982: 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01,
5983: 0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0x86, 0x07,
5984: 0x00, 0x33, 0x07, 0x00, 0x82, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00,
5985: 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2,
5986: 0xA6, 0x07, 0x00, 0x05, 0x9C, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05,
5987: 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08,
5988: 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02,
5989: 0x00, 0xA0, 0xD6, 0x07, 0xD8, 0x87, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
5990: 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2,
5991: 0x06, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0xE6, 0x07,
5992: 0xC6, 0x97, 0xF4, 0x94, 0xE6, 0x87, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x1C, 0x88,
5993: 0x02, 0x01, 0x04, 0xD8, 0x08, 0x97, 0xC6, 0x97, 0xF4, 0x94, 0x0C, 0x88, 0x75, 0x00, 0x00, 0xA3,
5994: 0x26, 0x08, 0x00, 0x05, 0x10, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
5995: 0x38, 0x08, 0x00, 0x33, 0x3E, 0x00, 0x82, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63,
5996: 0x38, 0x2B, 0x5E, 0x88, 0x38, 0x2B, 0x54, 0x88, 0x32, 0x09, 0x31, 0x05, 0x54, 0x98, 0x05, 0x05,
5997: 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32,
5998: 0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A,
5999: 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0x74, 0x08, 0x5D, 0x00, 0xFE, 0xC3,
6000: 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
6001: 0x13, 0x23, 0xB8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01,
6002: 0x81, 0x62, 0xA2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2,
6003: 0xF1, 0xC7, 0x41, 0x23, 0xB8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xB2, 0x84,
6004:
6005: };
6006:
6007: ushort _mcode_size = sizeof (_mcode_buf);
6008: ulong _mcode_chksum = 0x012258FBUL;
6009:
6010: extern uchar _sdtr_period_tbl_[];
6011:
6012: int
6013: AscExeScsiQueue(
6014: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6015: ASC_SCSI_Q dosfar * scsiq
6016: )
6017: {
6018: PortAddr iop_base;
6019: int last_int_level;
6020: int sta;
6021: ulong addr;
6022: uchar sg_entry_cnt;
6023: uchar target_ix;
6024: int n_q_required;
6025: uchar sg_entry_cnt_minus_one;
6026: uchar tid_no;
6027: uchar sdtr_data;
6028: ASC_EXE_CALLBACK asc_exe_callback;
6029:
6030: #if CC_DEBUG_SG_LIST
6031: int i;
6032:
6033: #endif
6034: #if CC_LINK_BUSY_Q
6035: ASC_SCSI_Q dosfar *scsiq_tail;
6036: ASC_SCSI_Q dosfar *scsiq_next;
6037: ASC_SCSI_Q dosfar *scsiq_prev;
6038:
6039: #endif
6040:
6041: iop_base = asc_dvc->iop_base;
6042: asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
6043: if (asc_dvc->err_code != 0)
6044: return (ERR);
6045: if (scsiq == (ASC_SCSI_Q dosfar *) 0L) {
6046: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
6047: return (ERR);
6048: }
6049: scsiq->q1.q_no = 0;
6050: sta = 0;
6051: target_ix = scsiq->q2.target_ix;
6052: tid_no = ASC_TIX_TO_TID(target_ix);
6053:
6054: n_q_required = 1;
6055:
6056: if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
6057:
6058: if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
6059: ((asc_dvc->sdtr_done & scsiq->q1.target_id) != 0)) {
6060: sdtr_data = AscReadLramByte(iop_base,
6061: (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
6062: AscMsgOutSDTR(iop_base,
6063: _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
6064: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
6065: scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
6066: }
6067: }
6068: last_int_level = DvcEnterCritical();
6069: if (asc_dvc->in_critical_cnt != 0) {
6070: DvcLeaveCritical(last_int_level);
6071: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
6072: return (ERR);
6073: }
6074: asc_dvc->in_critical_cnt++;
6075:
6076: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
6077:
6078: if ((sg_entry_cnt = scsiq->sg_head->entry_cnt) == 0) {
6079: asc_dvc->in_critical_cnt--;
6080: DvcLeaveCritical(last_int_level);
6081: return (ERR);
6082: }
6083: if (sg_entry_cnt == 1) {
6084: scsiq->q1.data_addr = scsiq->sg_head->sg_list[0].addr;
6085: scsiq->q1.data_cnt = scsiq->sg_head->sg_list[0].bytes;
6086: scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
6087: goto NON_SG_LIST_REQ;
6088: }
6089: if (sg_entry_cnt > ASC_MAX_SG_LIST) {
6090:
6091: return (ERR);
6092: }
6093: sg_entry_cnt_minus_one = sg_entry_cnt - 1;
6094:
6095: #if CC_DEBUG_SG_LIST
6096: if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
6097: for (i = 0; i < sg_entry_cnt_minus_one; i++) {
6098:
6099: addr = scsiq->sg_head->sg_list[i].addr +
6100: scsiq->sg_head->sg_list[i].bytes;
6101:
6102: if (((ushort) addr & 0x0003) != 0) {
6103: asc_dvc->in_critical_cnt--;
6104: DvcLeaveCritical(last_int_level);
6105: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_LIST_ODD_ADDRESS);
6106: return (ERR);
6107: }
6108: }
6109: }
6110: #endif
6111:
6112: if (asc_dvc->bug_fix_cntl) {
6113: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
6114:
6115: addr = scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr +
6116: scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
6117: if (((ushort) addr & 0x0003) != 0) {
6118: if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
6119: (scsiq->cdbptr[0] == SCSICMD_Read10)) {
6120: if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
6121:
6122: scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes++;
6123: scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
6124: }
6125: }
6126: }
6127: }
6128: }
6129: scsiq->sg_head->entry_to_copy = scsiq->sg_head->entry_cnt;
6130: n_q_required = AscSgListToQueue(sg_entry_cnt);
6131:
6132: #if CC_LINK_BUSY_Q
6133: scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
6134: if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
6135: goto link_scisq_to_busy_list;
6136: }
6137: #endif
6138:
6139: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required)
6140: >= (uint) n_q_required) ||
6141: ((scsiq->q1.cntl & QC_URGENT) != 0)) {
6142: if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
6143: n_q_required)) == 1) {
6144:
6145: asc_dvc->in_critical_cnt--;
6146: if (asc_exe_callback != 0) {
6147: (*asc_exe_callback) (asc_dvc, scsiq);
6148: }
6149: DvcLeaveCritical(last_int_level);
6150: return (sta);
6151: }
6152: }
6153: } else {
6154:
6155: NON_SG_LIST_REQ:
6156:
6157: if (asc_dvc->bug_fix_cntl) {
6158: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
6159:
6160: addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
6161: if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
6162: (scsiq->cdbptr[0] == SCSICMD_Read10)) {
6163: if (((ushort) addr & 0x0003) != 0) {
6164: if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
6165:
6166: if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
6167:
6168: scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
6169: scsiq->q1.data_cnt++;
6170: }
6171: }
6172: }
6173: }
6174: }
6175: }
6176: n_q_required = 1;
6177:
6178: #if CC_LINK_BUSY_Q
6179: scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
6180: if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
6181: goto link_scisq_to_busy_list;
6182: }
6183: #endif
6184: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
6185: ((scsiq->q1.cntl & QC_URGENT) != 0)) {
6186: if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
6187: n_q_required)) == 1) {
6188:
6189: asc_dvc->in_critical_cnt--;
6190: if (asc_exe_callback != 0) {
6191: (*asc_exe_callback) (asc_dvc, scsiq);
6192: }
6193: DvcLeaveCritical(last_int_level);
6194: return (sta);
6195: }
6196: }
6197: }
6198:
6199: #if CC_LINK_BUSY_Q
6200: if (sta == 0) {
6201:
6202: link_scisq_to_busy_list:
6203: scsiq->ext.q_required = n_q_required;
6204: if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
6205: asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6206: asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6207: scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
6208: scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6209: scsiq->q1.status = QS_BUSY;
6210: sta = 1;
6211: } else {
6212: scsiq_tail = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_tail[tid_no];
6213: if (scsiq_tail->ext.next == (ASC_SCSI_Q dosfar *) 0L) {
6214: if ((scsiq->q1.cntl & QC_URGENT) != 0) {
6215:
6216: asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6217: scsiq->ext.next = scsiq_next;
6218: scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6219: } else {
6220: if (scsiq->ext.cntl & QCX_SORT) {
6221: do {
6222: scsiq_prev = scsiq_next;
6223: scsiq_next = scsiq_next->ext.next;
6224: if (scsiq->ext.lba < scsiq_prev->ext.lba)
6225: break;
6226: } while (scsiq_next != (ASC_SCSI_Q dosfar *) 0L);
6227:
6228: scsiq_prev->ext.next = scsiq;
6229: scsiq->ext.next = scsiq_next;
6230: if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
6231: asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6232: }
6233: scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6234: } else {
6235:
6236: scsiq_tail->ext.next = (ASC_SCSI_Q dosfar *) scsiq;
6237: asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
6238: scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
6239: scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
6240: }
6241: }
6242: scsiq->q1.status = QS_BUSY;
6243: sta = 1;
6244: } else {
6245:
6246: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_BAD_NEXT_PTR);
6247: sta = ERR;
6248: }
6249: }
6250: }
6251: #endif
6252: asc_dvc->in_critical_cnt--;
6253: DvcLeaveCritical(last_int_level);
6254: return (sta);
6255: }
6256:
6257: int
6258: AscSendScsiQueue(
6259: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6260: ASC_SCSI_Q dosfar * scsiq,
6261: uchar n_q_required
6262: )
6263: {
6264: PortAddr iop_base;
6265: uchar free_q_head;
6266: uchar next_qp;
6267: uchar tid_no;
6268: uchar target_ix;
6269: int sta;
6270:
6271: iop_base = asc_dvc->iop_base;
6272: target_ix = scsiq->q2.target_ix;
6273: tid_no = ASC_TIX_TO_TID(target_ix);
6274: sta = 0;
6275: free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
6276: if (n_q_required > 1) {
6277: if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
6278: free_q_head, (uchar) (n_q_required)))
6279: != (uchar) ASC_QLINK_END) {
6280: asc_dvc->last_q_shortage = 0;
6281: scsiq->sg_head->queue_cnt = n_q_required - 1;
6282: scsiq->q1.q_no = free_q_head;
6283:
6284: if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
6285: free_q_head)) == 1) {
6286:
6287: #if CC_WRITE_IO_COUNT
6288: asc_dvc->req_count++;
6289: #endif
6290:
6291: AscPutVarFreeQHead(iop_base, next_qp);
6292: asc_dvc->cur_total_qng += (uchar) (n_q_required);
6293: asc_dvc->cur_dvc_qng[tid_no]++;
6294: }
6295: return (sta);
6296: }
6297: } else if (n_q_required == 1) {
6298:
6299: if ((next_qp = AscAllocFreeQueue(iop_base,
6300: free_q_head)) != ASC_QLINK_END) {
6301:
6302: scsiq->q1.q_no = free_q_head;
6303: if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
6304: free_q_head)) == 1) {
6305:
6306: #if CC_WRITE_IO_COUNT
6307: asc_dvc->req_count++;
6308: #endif
6309:
6310: AscPutVarFreeQHead(iop_base, next_qp);
6311: asc_dvc->cur_total_qng++;
6312: asc_dvc->cur_dvc_qng[tid_no]++;
6313: }
6314: return (sta);
6315: }
6316: }
6317: return (sta);
6318: }
6319:
6320: int
6321: AscSgListToQueue(
6322: int sg_list
6323: )
6324: {
6325: int n_sg_list_qs;
6326:
6327: n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
6328: if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
6329: n_sg_list_qs++;
6330: return (n_sg_list_qs + 1);
6331: }
6332:
6333: uint
6334: AscGetNumOfFreeQueue(
6335: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6336: uchar target_ix, uchar n_qs
6337: )
6338: {
6339: uint cur_used_qs;
6340: uint cur_free_qs;
6341: ASC_SCSI_BIT_ID_TYPE target_id;
6342: uchar tid_no;
6343:
6344: target_id = ASC_TIX_TO_TARGET_ID(target_ix);
6345: tid_no = ASC_TIX_TO_TID(target_ix);
6346: if ((asc_dvc->unit_not_ready & target_id) ||
6347: (asc_dvc->queue_full_or_busy & target_id)) {
6348: return (0);
6349: }
6350: if (n_qs == 1) {
6351: cur_used_qs = (uint) asc_dvc->cur_total_qng +
6352: (uint) asc_dvc->last_q_shortage +
6353: (uint) ASC_MIN_FREE_Q;
6354: } else {
6355: cur_used_qs = (uint) asc_dvc->cur_total_qng +
6356: (uint) ASC_MIN_FREE_Q;
6357: }
6358:
6359: if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
6360: cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
6361: if (asc_dvc->cur_dvc_qng[tid_no] >=
6362: asc_dvc->max_dvc_qng[tid_no]) {
6363: return (0);
6364: }
6365: return (cur_free_qs);
6366: }
6367: if (n_qs > 1) {
6368: if (n_qs > asc_dvc->last_q_shortage) {
6369: asc_dvc->last_q_shortage = n_qs;
6370: }
6371: }
6372: return (0);
6373: }
6374:
6375: int
6376: AscPutReadyQueue(
6377: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6378: ASC_SCSI_Q dosfar * scsiq,
6379: uchar q_no
6380: )
6381: {
6382: ushort q_addr;
6383: uchar tid_no;
6384: uchar sdtr_data;
6385: uchar syn_period_ix;
6386: uchar syn_offset;
6387: PortAddr iop_base;
6388:
6389: iop_base = asc_dvc->iop_base;
6390:
6391: if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
6392: ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
6393:
6394: tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
6395:
6396: sdtr_data = AscReadLramByte(iop_base,
6397: (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
6398: syn_period_ix = (sdtr_data >> 4) & (ASC_SYN_XFER_NO - 1);
6399: syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
6400: AscMsgOutSDTR(iop_base,
6401: _sdtr_period_tbl_[syn_period_ix],
6402: syn_offset);
6403:
6404: scsiq->q1.cntl |= QC_MSG_OUT;
6405: }
6406: q_addr = ASC_QNO_TO_QADDR(q_no);
6407:
6408: if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
6409: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
6410: }
6411: scsiq->q1.status = QS_FREE;
6412:
6413: AscMemWordCopyToLram(iop_base,
6414: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
6415: (ushort dosfar *) scsiq->cdbptr,
6416: (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
6417:
6418: #if !CC_LITTLE_ENDIAN_HOST
6419: AscAdjEndianScsiQ(scsiq);
6420: #endif
6421:
6422: DvcPutScsiQ(iop_base,
6423: (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
6424: (ushort dosfar *) & scsiq->q1.cntl,
6425: (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
6426:
6427: #if CC_WRITE_IO_COUNT
6428: AscWriteLramWord(iop_base,
6429: (ushort) (q_addr + (ushort) ASC_SCSIQ_W_REQ_COUNT),
6430: (ushort) asc_dvc->req_count);
6431:
6432: #endif
6433:
6434: #if CC_VERIFY_LRAM_COPY
6435: if ((asc_dvc->dvc_cntl & ASC_CNTL_NO_VERIFY_COPY) == 0) {
6436:
6437: if (AscMemWordCmpToLram(iop_base,
6438: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
6439: (ushort dosfar *) scsiq->cdbptr,
6440: (ushort) (scsiq->q2.cdb_len >> 1)) != 0) {
6441: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
6442: return (ERR);
6443: }
6444: if (AscMemWordCmpToLram(iop_base,
6445: (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
6446: (ushort dosfar *) & scsiq->q1.cntl,
6447: (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))
6448: != 0) {
6449: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
6450: return (ERR);
6451: }
6452: }
6453: #endif
6454:
6455: #if CC_CLEAR_DMA_REMAIN
6456:
6457: AscWriteLramDWord(iop_base,
6458: (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_ADDR), 0UL);
6459: AscWriteLramDWord(iop_base,
6460: (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT), 0UL);
6461:
6462: #endif
6463:
6464: AscWriteLramWord(iop_base,
6465: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
6466: (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
6467: return (1);
6468: }
6469:
6470: int
6471: AscPutReadySgListQueue(
6472: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6473: ASC_SCSI_Q dosfar * scsiq,
6474: uchar q_no
6475: )
6476: {
6477: uchar sg_list_dwords;
6478: uchar sg_index, i;
6479: uchar sg_entry_cnt;
6480: uchar next_qp;
6481: ushort q_addr;
6482: int sta;
6483: ASC_SG_HEAD dosfar *sg_head;
6484: ASC_SG_LIST_Q scsi_sg_q;
6485: ulong saved_data_addr;
6486: ulong saved_data_cnt;
6487: PortAddr iop_base;
6488:
6489: iop_base = asc_dvc->iop_base;
6490:
6491: sg_head = scsiq->sg_head;
6492:
6493: saved_data_addr = scsiq->q1.data_addr;
6494: saved_data_cnt = scsiq->q1.data_cnt;
6495: scsiq->q1.data_addr = sg_head->sg_list[0].addr;
6496: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
6497: sg_entry_cnt = sg_head->entry_cnt - 1;
6498: if (sg_entry_cnt != 0) {
6499: scsiq->q1.cntl |= QC_SG_HEAD;
6500: q_addr = ASC_QNO_TO_QADDR(q_no);
6501: sg_index = 1;
6502: scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
6503: scsi_sg_q.sg_head_qp = q_no;
6504: scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
6505: for (i = 0; i < sg_head->queue_cnt; i++) {
6506: scsi_sg_q.seq_no = i + 1;
6507: if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
6508: sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
6509: sg_entry_cnt -= ASC_SG_LIST_PER_Q;
6510: if (i == 0) {
6511: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
6512: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
6513: } else {
6514: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
6515: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
6516: }
6517: } else {
6518:
6519: scsi_sg_q.cntl |= QCSG_SG_XFER_END;
6520: sg_list_dwords = sg_entry_cnt << 1;
6521: if (i == 0) {
6522: scsi_sg_q.sg_list_cnt = sg_entry_cnt;
6523: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
6524: } else {
6525: scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
6526: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
6527: }
6528: sg_entry_cnt = 0;
6529: }
6530: next_qp = AscReadLramByte(iop_base,
6531: (ushort) (q_addr + ASC_SCSIQ_B_FWD));
6532: scsi_sg_q.q_no = next_qp;
6533: q_addr = ASC_QNO_TO_QADDR(next_qp);
6534:
6535: AscMemWordCopyToLram(iop_base,
6536: (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
6537: (ushort dosfar *) & scsi_sg_q,
6538: (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
6539:
6540: AscMemDWordCopyToLram(iop_base,
6541: (ushort) (q_addr + ASC_SGQ_LIST_BEG),
6542: (ulong dosfar *) & sg_head->sg_list[sg_index],
6543: (ushort) sg_list_dwords);
6544:
6545: sg_index += ASC_SG_LIST_PER_Q;
6546: }
6547: } else {
6548:
6549: scsiq->q1.cntl &= ~QC_SG_HEAD;
6550: }
6551: sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
6552:
6553: scsiq->q1.data_addr = saved_data_addr;
6554: scsiq->q1.data_cnt = saved_data_cnt;
6555: return (sta);
6556: }
6557:
6558: int
6559: AscAbortSRB(
6560: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6561: ulong srb_ptr
6562: )
6563: {
6564: int sta;
6565: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
6566: PortAddr iop_base;
6567:
6568: iop_base = asc_dvc->iop_base;
6569: sta = ERR;
6570: saved_unit_not_ready = asc_dvc->unit_not_ready;
6571: asc_dvc->unit_not_ready = 0xFF;
6572: AscWaitISRDone(asc_dvc);
6573: if (AscStopQueueExe(iop_base) == 1) {
6574: if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
6575: sta = 1;
6576: AscCleanUpBusyQueue(iop_base);
6577: AscStartQueueExe(iop_base);
6578:
6579: } else {
6580: sta = 0;
6581: AscStartQueueExe(iop_base);
6582: }
6583: }
6584: asc_dvc->unit_not_ready = saved_unit_not_ready;
6585: return (sta);
6586: }
6587:
6588: int
6589: AscResetDevice(
6590: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6591: uchar target_ix
6592: )
6593: {
6594: PortAddr iop_base;
6595: int sta;
6596: uchar tid_no;
6597: ASC_SCSI_BIT_ID_TYPE target_id;
6598: int i;
6599: ASC_SCSI_REQ_Q scsiq_buf;
6600: ASC_SCSI_REQ_Q dosfar *scsiq;
6601: uchar dosfar *buf;
6602: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
6603:
6604: iop_base = asc_dvc->iop_base;
6605: tid_no = ASC_TIX_TO_TID(target_ix);
6606: target_id = ASC_TID_TO_TARGET_ID(tid_no);
6607: saved_unit_not_ready = asc_dvc->unit_not_ready;
6608: asc_dvc->unit_not_ready = target_id;
6609: sta = ERR;
6610: AscWaitTixISRDone(asc_dvc, target_ix);
6611: if (AscStopQueueExe(iop_base) == 1) {
6612: if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
6613:
6614: AscCleanUpBusyQueue(iop_base);
6615: AscStartQueueExe(iop_base);
6616:
6617: AscWaitTixISRDone(asc_dvc, target_ix);
6618:
6619: sta = TRUE;
6620: scsiq = (ASC_SCSI_REQ_Q dosfar *) & scsiq_buf;
6621: buf = (uchar dosfar *) & scsiq_buf;
6622: for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
6623: *buf++ = 0x00;
6624: }
6625:
6626: scsiq->r1.status = (uchar) QS_READY;
6627: scsiq->r2.cdb_len = 6;
6628: scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
6629: scsiq->r1.target_id = target_id;
6630:
6631: scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
6632: scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
6633:
6634: scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
6635: AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
6636: M1_BUS_DVC_RESET);
6637:
6638: asc_dvc->unit_not_ready &= ~target_id;
6639:
6640: asc_dvc->sdtr_done |= target_id;
6641:
6642: if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q dosfar *) scsiq)
6643: == 1) {
6644: asc_dvc->unit_not_ready = target_id;
6645: DvcSleepMilliSecond(1000);
6646: _AscWaitQDone(iop_base, (ASC_SCSI_Q dosfar *) scsiq);
6647: if (AscStopQueueExe(iop_base) == 1) {
6648:
6649: AscCleanUpDiscQueue(iop_base);
6650: AscStartQueueExe(iop_base);
6651: if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6652:
6653: AscSetRunChipSynRegAtID(iop_base, tid_no,
6654: ASYN_SDTR_DATA_FIX_PCI_REV_AB);
6655: }
6656: AscWaitTixISRDone(asc_dvc, target_ix);
6657: }
6658: } else {
6659:
6660: sta = 0;
6661: }
6662:
6663: asc_dvc->sdtr_done &= ~target_id;
6664: } else {
6665: sta = ERR;
6666: AscStartQueueExe(iop_base);
6667: }
6668: }
6669: asc_dvc->unit_not_ready = saved_unit_not_ready;
6670: return (sta);
6671: }
6672:
6673: int
6674: AscResetSB(
6675: ASC_DVC_VAR asc_ptr_type * asc_dvc
6676: )
6677: {
6678: int sta;
6679: int i;
6680: PortAddr iop_base;
6681:
6682: iop_base = asc_dvc->iop_base;
6683: asc_dvc->unit_not_ready = 0xFF;
6684: sta = TRUE;
6685: AscWaitISRDone(asc_dvc);
6686: AscStopQueueExe(iop_base);
6687:
6688: asc_dvc->sdtr_done = 0;
6689: AscResetChipAndScsiBus(iop_base);
6690:
6691: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
6692:
6693: #if CC_SCAM
6694: if (!(asc_dvc->dvc_cntl & ASC_CNTL_NO_SCAM)) {
6695: AscSCAM(asc_dvc);
6696: }
6697: #endif
6698: AscReInitLram(asc_dvc);
6699:
6700: for (i = 0; i <= ASC_MAX_TID; i++) {
6701: asc_dvc->cur_dvc_qng[i] = 0;
6702: if (asc_dvc->pci_fix_asyn_xfer & (0x01 << i)) {
6703:
6704: AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
6705: }
6706: }
6707:
6708: asc_dvc->err_code = 0;
6709:
6710: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
6711: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
6712: sta = ERR;
6713: }
6714: if (AscStartChip(iop_base) == 0) {
6715: sta = ERR;
6716: }
6717: AscStartQueueExe(iop_base);
6718: asc_dvc->unit_not_ready = 0;
6719: asc_dvc->queue_full_or_busy = 0;
6720: return (sta);
6721: }
6722:
6723: int
6724: AscSetRunChipSynRegAtID(
6725: PortAddr iop_base,
6726: uchar tid_no,
6727: uchar sdtr_data
6728: )
6729: {
6730: int sta = FALSE;
6731:
6732: if (AscHostReqRiscHalt(iop_base)) {
6733: sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
6734:
6735: AscStartChip(iop_base);
6736: return (sta);
6737: }
6738: return (sta);
6739: }
6740:
6741: int
6742: AscSetChipSynRegAtID(
6743: PortAddr iop_base,
6744: uchar id,
6745: uchar sdtr_data
6746: )
6747: {
6748: AscSetBank(iop_base, 1);
6749: AscWriteChipScsiID(iop_base, id);
6750: if (AscReadChipScsiID(iop_base) != (0x01 << id)) {
6751: return (FALSE);
6752: }
6753: AscSetBank(iop_base, 0);
6754: AscWriteChipSyn(iop_base, sdtr_data);
6755: if (AscReadChipSyn(iop_base) != sdtr_data) {
6756: return (FALSE);
6757: }
6758: return (TRUE);
6759: }
6760:
6761: int
6762: AscReInitLram(
6763: ASC_DVC_VAR asc_ptr_type * asc_dvc
6764: )
6765: {
6766: AscInitLram(asc_dvc);
6767: AscInitQLinkVar(asc_dvc);
6768: return (0);
6769: }
6770:
6771: ushort
6772: AscInitLram(
6773: ASC_DVC_VAR asc_ptr_type * asc_dvc)
6774: {
6775: uchar i;
6776: ushort s_addr;
6777: PortAddr iop_base;
6778: ushort warn_code;
6779:
6780: iop_base = asc_dvc->iop_base;
6781: warn_code = 0;
6782:
6783: AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
6784: (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
6785: );
6786:
6787: i = ASC_MIN_ACTIVE_QNO;
6788: s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
6789:
6790: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
6791: (uchar) (i + 1));
6792: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
6793: (uchar) (asc_dvc->max_total_qng));
6794: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
6795: (uchar) i);
6796: i++;
6797: s_addr += ASC_QBLK_SIZE;
6798: for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
6799: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
6800: (uchar) (i + 1));
6801: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
6802: (uchar) (i - 1));
6803: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
6804: (uchar) i);
6805: }
6806:
6807: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
6808: (uchar) ASC_QLINK_END);
6809: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
6810: (uchar) (asc_dvc->max_total_qng - 1));
6811: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
6812: (uchar) asc_dvc->max_total_qng);
6813: i++;
6814: s_addr += ASC_QBLK_SIZE;
6815:
6816: for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
6817: i++, s_addr += ASC_QBLK_SIZE) {
6818:
6819: AscWriteLramByte(iop_base,
6820: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
6821: AscWriteLramByte(iop_base,
6822: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
6823: AscWriteLramByte(iop_base,
6824: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
6825: }
6826:
6827: return (warn_code);
6828: }
6829:
6830: ushort
6831: AscInitQLinkVar(
6832: ASC_DVC_VAR asc_ptr_type * asc_dvc
6833: )
6834: {
6835: PortAddr iop_base;
6836: int i;
6837: ushort lram_addr;
6838:
6839: iop_base = asc_dvc->iop_base;
6840: AscPutRiscVarFreeQHead(iop_base, 1);
6841: AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6842:
6843: AscPutVarFreeQHead(iop_base, 1);
6844: AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
6845:
6846: AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
6847: (uchar) ((int) asc_dvc->max_total_qng + 1));
6848: AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
6849: (uchar) ((int) asc_dvc->max_total_qng + 2));
6850:
6851: AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
6852: asc_dvc->max_total_qng);
6853:
6854: AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
6855: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6856: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
6857: AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
6858: AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
6859:
6860: AscWriteLramByte(iop_base, (ushort) ASCV_CDBCNT_B, 0);
6861:
6862: lram_addr = ASC_QADR_BEG;
6863: for (i = 0; i < 32; i++, lram_addr += 2) {
6864: AscWriteLramWord(iop_base, lram_addr, 0);
6865: }
6866:
6867: return (0);
6868: }
6869:
6870: int
6871: AscSetLibErrorCode(
6872: ASC_DVC_VAR asc_ptr_type * asc_dvc,
6873: ushort err_code
6874: )
6875: {
6876: if (asc_dvc->err_code == 0) {
6877:
6878: asc_dvc->err_code = err_code;
6879: AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
6880: err_code);
6881: }
6882: return (err_code);
6883: }
6884:
6885: int
6886: _AscWaitQDone(
6887: PortAddr iop_base,
6888: ASC_SCSI_Q dosfar * scsiq
6889: )
6890: {
6891: ushort q_addr;
6892: uchar q_status;
6893: int count = 0;
6894:
6895: while (scsiq->q1.q_no == 0) ;
6896: q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
6897:
6898: do {
6899: q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
6900: DvcSleepMilliSecond(100L);
6901: if (count++ > 30) {
6902: return (0);
6903: }
6904: } while ((q_status & QS_READY) != 0);
6905: return (1);
6906: }
6907:
6908: uchar _sdtr_period_tbl_[ASC_SYN_XFER_NO] =
6909: {
6910: SYN_XFER_NS_0,
6911: SYN_XFER_NS_1,
6912: SYN_XFER_NS_2,
6913: SYN_XFER_NS_3,
6914: SYN_XFER_NS_4,
6915: SYN_XFER_NS_5,
6916: SYN_XFER_NS_6,
6917: SYN_XFER_NS_7};
6918:
6919: uchar
6920: AscMsgOutSDTR(
6921: PortAddr iop_base,
6922: uchar sdtr_period,
6923: uchar sdtr_offset
6924: )
6925: {
6926: SDTR_XMSG sdtr_buf;
6927: uchar sdtr_period_index;
6928:
6929: sdtr_buf.msg_type = MS_EXTEND;
6930: sdtr_buf.msg_len = MS_SDTR_LEN;
6931: sdtr_buf.msg_req = MS_SDTR_CODE;
6932: sdtr_buf.xfer_period = sdtr_period;
6933: sdtr_offset &= ASC_SYN_MAX_OFFSET;
6934: sdtr_buf.req_ack_offset = sdtr_offset;
6935: AscMemWordCopyToLram(iop_base, ASCV_MSGOUT_BEG,
6936: (ushort dosfar *) & sdtr_buf, SYN_XMSG_WLEN);
6937: if ((sdtr_period_index = AscGetSynPeriodIndex(sdtr_period)) <=
6938: ASC_MAX_SDTR_PERIOD_INDEX) {
6939: return ((sdtr_period_index << 4) | sdtr_offset);
6940: } else {
6941:
6942: return (0);
6943: }
6944: }
6945:
6946: uchar
6947: AscCalSDTRData(
6948: uchar sdtr_period,
6949: uchar syn_offset
6950: )
6951: {
6952: uchar byte;
6953: uchar sdtr_period_ix;
6954:
6955: sdtr_period_ix = AscGetSynPeriodIndex(sdtr_period);
6956: if ((sdtr_period_ix > ASC_MAX_SDTR_PERIOD_INDEX) ||
6957: (sdtr_period_ix > ASC_SDTR_PERIOD_IX_MIN)) {
6958: return (0xFF);
6959: }
6960: byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
6961: return (byte);
6962: }
6963:
6964: void
6965: AscSetChipSDTR(
6966: PortAddr iop_base,
6967: uchar sdtr_data,
6968: uchar tid_no
6969: )
6970: {
6971:
6972: AscWriteChipSyn(iop_base, sdtr_data);
6973: AscWriteLramByte(iop_base,
6974: (ushort) ((ushort) ASCV_SDTR_DONE_BEG + (ushort) tid_no),
6975: sdtr_data);
6976: return;
6977: }
6978:
6979: uchar
6980: AscGetSynPeriodIndex(
6981: uchar syn_time
6982: )
6983: {
6984: if ((syn_time >= SYN_XFER_NS_0) && (syn_time <= SYN_XFER_NS_7)) {
6985: if (syn_time <= SYN_XFER_NS_6) {
6986: if (syn_time <= SYN_XFER_NS_5) {
6987: if (syn_time <= SYN_XFER_NS_4) {
6988: if (syn_time <= SYN_XFER_NS_3) {
6989: if (syn_time <= SYN_XFER_NS_2) {
6990: if (syn_time <= SYN_XFER_NS_1) {
6991: if (syn_time <= SYN_XFER_NS_0) {
6992: return (0);
6993: } else
6994: return (1);
6995: } else {
6996: return (2);
6997: }
6998: } else {
6999: return (3);
7000: }
7001: } else {
7002: return (4);
7003: }
7004: } else {
7005: return (5);
7006: }
7007: } else {
7008: return (6);
7009: }
7010: } else {
7011: return (7);
7012: }
7013: } else {
7014:
7015: return (8);
7016: }
7017: }
7018:
7019: uchar
7020: AscAllocFreeQueue(
7021: PortAddr iop_base,
7022: uchar free_q_head
7023: )
7024: {
7025: ushort q_addr;
7026: uchar next_qp;
7027: uchar q_status;
7028:
7029: q_addr = ASC_QNO_TO_QADDR(free_q_head);
7030: q_status = (uchar) AscReadLramByte(iop_base,
7031: (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
7032: next_qp = AscReadLramByte(iop_base,
7033: (ushort) (q_addr + ASC_SCSIQ_B_FWD));
7034: if (((q_status & QS_READY) == 0) &&
7035: (next_qp != ASC_QLINK_END)) {
7036: return (next_qp);
7037: }
7038: return (ASC_QLINK_END);
7039: }
7040:
7041: uchar
7042: AscAllocMultipleFreeQueue(
7043: PortAddr iop_base,
7044: uchar free_q_head,
7045: uchar n_free_q
7046: )
7047: {
7048: uchar i;
7049:
7050: for (i = 0; i < n_free_q; i++) {
7051: if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
7052: == ASC_QLINK_END) {
7053: return (ASC_QLINK_END);
7054: }
7055: }
7056: return (free_q_head);
7057: }
7058:
7059: int
7060: AscRiscHaltedAbortSRB(
7061: ASC_DVC_VAR asc_ptr_type * asc_dvc,
7062: ulong srb_ptr
7063: )
7064: {
7065: PortAddr iop_base;
7066: ushort q_addr;
7067: uchar q_no;
7068: ASC_QDONE_INFO scsiq_buf;
7069: ASC_QDONE_INFO dosfar *scsiq;
7070: ASC_ISR_CALLBACK asc_isr_callback;
7071: int last_int_level;
7072:
7073: iop_base = asc_dvc->iop_base;
7074: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
7075: last_int_level = DvcEnterCritical();
7076: scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
7077:
7078: #if CC_LINK_BUSY_Q
7079: _AscAbortSrbBusyQueue(asc_dvc, scsiq, srb_ptr);
7080: #endif
7081:
7082: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
7083: q_no++) {
7084: q_addr = ASC_QNO_TO_QADDR(q_no);
7085: scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
7086: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
7087: if (scsiq->d2.srb_ptr == srb_ptr) {
7088: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
7089: if (((scsiq->q_status & QS_READY) != 0) &&
7090: ((scsiq->q_status & QS_ABORTED) == 0) &&
7091: ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
7092:
7093: scsiq->q_status |= QS_ABORTED;
7094: scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
7095: AscWriteLramDWord(iop_base,
7096: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
7097: 0L);
7098: AscWriteLramByte(iop_base,
7099: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
7100: scsiq->q_status);
7101: (*asc_isr_callback) (asc_dvc, scsiq);
7102: return (1);
7103: }
7104: }
7105: }
7106: DvcLeaveCritical(last_int_level);
7107: return (0);
7108: }
7109:
7110: int
7111: AscRiscHaltedAbortTIX(
7112: ASC_DVC_VAR asc_ptr_type * asc_dvc,
7113: uchar target_ix
7114: )
7115: {
7116: PortAddr iop_base;
7117: ushort q_addr;
7118: uchar q_no;
7119: ASC_QDONE_INFO scsiq_buf;
7120: ASC_QDONE_INFO dosfar *scsiq;
7121: ASC_ISR_CALLBACK asc_isr_callback;
7122: int last_int_level;
7123:
7124: #if CC_LINK_BUSY_Q
7125: uchar tid_no;
7126:
7127: #endif
7128:
7129: iop_base = asc_dvc->iop_base;
7130: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
7131: last_int_level = DvcEnterCritical();
7132: scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
7133:
7134: #if CC_LINK_BUSY_Q
7135:
7136: tid_no = ASC_TIX_TO_TID(target_ix);
7137: _AscAbortTidBusyQueue(asc_dvc, scsiq, tid_no);
7138:
7139: #endif
7140:
7141: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
7142: q_no++) {
7143: q_addr = ASC_QNO_TO_QADDR(q_no);
7144: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
7145: if (((scsiq->q_status & QS_READY) != 0) &&
7146: ((scsiq->q_status & QS_ABORTED) == 0) &&
7147: ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
7148: if (scsiq->d2.target_ix == target_ix) {
7149: scsiq->q_status |= QS_ABORTED;
7150: scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
7151:
7152: AscWriteLramDWord(iop_base,
7153: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
7154: 0L);
7155:
7156: AscWriteLramByte(iop_base,
7157: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
7158: scsiq->q_status);
7159: (*asc_isr_callback) (asc_dvc, scsiq);
7160: }
7161: }
7162: }
7163: DvcLeaveCritical(last_int_level);
7164: return (1);
7165: }
7166:
7167: #if CC_LINK_BUSY_Q
7168:
7169: #endif
7170:
7171: int
7172: AscHostReqRiscHalt(
7173: PortAddr iop_base
7174: )
7175: {
7176: int count = 0;
7177: int sta = 0;
7178: uchar saved_stop_code;
7179:
7180: if (AscIsChipHalted(iop_base))
7181: return (1);
7182: saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
7183:
7184: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7185: ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
7186: );
7187: do {
7188: if (AscIsChipHalted(iop_base)) {
7189: sta = 1;
7190: break;
7191: }
7192: DvcSleepMilliSecond(100);
7193: } while (count++ < 20);
7194:
7195: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
7196: return (sta);
7197: }
7198:
7199: int
7200: AscStopQueueExe(
7201: PortAddr iop_base
7202: )
7203: {
7204: int count;
7205:
7206: count = 0;
7207: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
7208: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7209: ASC_STOP_REQ_RISC_STOP);
7210: do {
7211: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
7212: ASC_STOP_ACK_RISC_STOP) {
7213: return (1);
7214: }
7215: DvcSleepMilliSecond(100);
7216: } while (count++ < 20);
7217: }
7218: return (0);
7219: }
7220:
7221: int
7222: AscStartQueueExe(
7223: PortAddr iop_base
7224: )
7225: {
7226: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
7227: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
7228: }
7229: return (1);
7230: }
7231:
7232: int
7233: AscCleanUpBusyQueue(
7234: PortAddr iop_base
7235: )
7236: {
7237: int count;
7238: uchar stop_code;
7239:
7240: count = 0;
7241: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
7242: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7243: ASC_STOP_CLEAN_UP_BUSY_Q);
7244: do {
7245: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
7246: if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
7247: break;
7248: DvcSleepMilliSecond(100);
7249: } while (count++ < 20);
7250: }
7251: return (1);
7252: }
7253:
7254: int
7255: AscCleanUpDiscQueue(
7256: PortAddr iop_base
7257: )
7258: {
7259: int count;
7260: uchar stop_code;
7261:
7262: count = 0;
7263: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
7264: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
7265: ASC_STOP_CLEAN_UP_DISC_Q);
7266: do {
7267: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
7268: if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
7269: break;
7270: DvcSleepMilliSecond(100);
7271: } while (count++ < 20);
7272: }
7273: return (1);
7274: }
7275:
7276: int
7277: AscWaitTixISRDone(
7278: ASC_DVC_VAR asc_ptr_type * asc_dvc,
7279: uchar target_ix
7280: )
7281: {
7282: uchar cur_req;
7283: uchar tid_no;
7284:
7285: tid_no = ASC_TIX_TO_TID(target_ix);
7286: while (TRUE) {
7287: if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
7288: break;
7289: }
7290: DvcSleepMilliSecond(1000L);
7291: if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
7292: break;
7293: }
7294: }
7295: return (1);
7296: }
7297:
7298: int
7299: AscWaitISRDone(
7300: ASC_DVC_VAR asc_ptr_type * asc_dvc
7301: )
7302: {
7303: int tid;
7304:
7305: for (tid = 0; tid <= ASC_MAX_TID; tid++) {
7306: AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
7307: }
7308: return (1);
7309: }
7310:
7311: ulong
7312: AscGetOnePhyAddr(
7313: ASC_DVC_VAR asc_ptr_type * asc_dvc,
7314: uchar dosfar * buf_addr,
7315: ulong buf_size
7316: )
7317: {
7318: ASC_MIN_SG_HEAD sg_head;
7319:
7320: sg_head.entry_cnt = ASC_MIN_SG_LIST;
7321: if (DvcGetSGList(asc_dvc, (uchar dosfar *) buf_addr,
7322: buf_size, (ASC_SG_HEAD dosfar *) & sg_head) != buf_size) {
7323: return (0L);
7324: }
7325: if (sg_head.entry_cnt > 1) {
7326: return (0L);
7327: }
7328: return (sg_head.sg_list[0].addr);
7329: }
7330:
7331: ulong
7332: AscGetEisaProductID(
7333: PortAddr iop_base
7334: )
7335: {
7336: PortAddr eisa_iop;
7337: ushort product_id_high, product_id_low;
7338: ulong product_id;
7339:
7340: eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
7341: product_id_low = inpw(eisa_iop);
7342: product_id_high = inpw(eisa_iop + 2);
7343: product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
7344: return (product_id);
7345: }
7346:
7347: PortAddr
7348: AscSearchIOPortAddrEISA(
7349: PortAddr iop_base
7350: )
7351: {
7352: ulong eisa_product_id;
7353:
7354: if (iop_base == 0) {
7355: iop_base = ASC_EISA_MIN_IOP_ADDR;
7356: } else {
7357: if (iop_base == ASC_EISA_MAX_IOP_ADDR)
7358: return (0);
7359: if ((iop_base & 0x0050) == 0x0050) {
7360: iop_base += ASC_EISA_BIG_IOP_GAP;
7361: } else {
7362: iop_base += ASC_EISA_SMALL_IOP_GAP;
7363: }
7364: }
7365: while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
7366:
7367: eisa_product_id = AscGetEisaProductID(iop_base);
7368: if ((eisa_product_id == ASC_EISA_ID_740) ||
7369: (eisa_product_id == ASC_EISA_ID_750)) {
7370: if (AscFindSignature(iop_base)) {
7371:
7372: inpw(iop_base + 4);
7373: return (iop_base);
7374: }
7375: }
7376: if (iop_base == ASC_EISA_MAX_IOP_ADDR)
7377: return (0);
7378: if ((iop_base & 0x0050) == 0x0050) {
7379: iop_base += ASC_EISA_BIG_IOP_GAP;
7380: } else {
7381: iop_base += ASC_EISA_SMALL_IOP_GAP;
7382: }
7383: }
7384: return (0);
7385: }
7386:
7387: int
7388: AscStartChip(
7389: PortAddr iop_base
7390: )
7391: {
7392: AscSetChipControl(iop_base, 0);
7393: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
7394: return (0);
7395: }
7396: return (1);
7397: }
7398:
7399: int
7400: AscStopChip(
7401: PortAddr iop_base
7402: )
7403: {
7404: uchar cc_val;
7405:
7406: cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
7407: AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
7408: AscSetChipIH(iop_base, INS_HALT);
7409: AscSetChipIH(iop_base, INS_RFLAG_WTM);
7410: if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
7411: return (0);
7412: }
7413: return (1);
7414: }
7415:
7416: int
7417: AscIsChipHalted(
7418: PortAddr iop_base
7419: )
7420: {
7421:
7422: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
7423: if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
7424: return (1);
7425: }
7426: }
7427: return (0);
7428: }
7429:
7430: void
7431: AscSetChipIH(
7432: PortAddr iop_base,
7433: ushort ins_code
7434: )
7435: {
7436: AscSetBank(iop_base, 1);
7437: AscWriteChipIH(iop_base, ins_code);
7438: AscSetBank(iop_base, 0);
7439: return;
7440: }
7441:
7442: void
7443: AscAckInterrupt(
7444: PortAddr iop_base
7445: )
7446: {
7447:
7448: uchar host_flag;
7449: uchar risc_flag;
7450: ushort loop;
7451:
7452: loop = 0;
7453: do {
7454: risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
7455: if (loop++ > 0x7FFF) {
7456: break;
7457: }
7458: } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
7459:
7460: host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
7461: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7462: (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
7463:
7464: AscSetChipStatus(iop_base, CIW_INT_ACK);
7465: loop = 0;
7466: while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
7467:
7468: AscSetChipStatus(iop_base, CIW_INT_ACK);
7469: if (loop++ > 3) {
7470: break;
7471: }
7472: }
7473:
7474: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7475: return;
7476: }
7477:
7478: void
7479: AscDisableInterrupt(
7480: PortAddr iop_base
7481: )
7482: {
7483: ushort cfg;
7484:
7485: cfg = AscGetChipCfgLsw(iop_base);
7486: AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
7487: return;
7488: }
7489:
7490: void
7491: AscEnableInterrupt(
7492: PortAddr iop_base
7493: )
7494: {
7495: ushort cfg;
7496:
7497: cfg = AscGetChipCfgLsw(iop_base);
7498: AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
7499: return;
7500: }
7501:
7502: void
7503: AscSetBank(
7504: PortAddr iop_base,
7505: uchar bank
7506: )
7507: {
7508: uchar val;
7509:
7510: val = AscGetChipControl(iop_base) &
7511: (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
7512: if (bank == 1) {
7513: val |= CC_BANK_ONE;
7514: } else if (bank == 2) {
7515: val |= CC_DIAG | CC_BANK_ONE;
7516: } else {
7517: val &= ~CC_BANK_ONE;
7518: }
7519: AscSetChipControl(iop_base, val);
7520: return;
7521: }
7522:
7523: int
7524: AscResetChipAndScsiBus(
7525: PortAddr iop_base
7526: )
7527: {
7528: AscStopChip(iop_base);
7529: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
7530: DvcSleepMilliSecond(200);
7531:
7532: AscSetChipIH(iop_base, INS_RFLAG_WTM);
7533: AscSetChipIH(iop_base, INS_HALT);
7534:
7535: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
7536: AscSetChipControl(iop_base, CC_HALT);
7537: DvcSleepMilliSecond(200);
7538: return (AscIsChipHalted(iop_base));
7539: }
7540:
7541: ushort
7542: AscGetIsaDmaChannel(
7543: PortAddr iop_base
7544: )
7545: {
7546: ushort channel;
7547:
7548: channel = AscGetChipCfgLsw(iop_base) & 0x0003;
7549: if (channel == 0x03)
7550: return (0);
7551: else if (channel == 0x00)
7552: return (7);
7553: return (channel + 4);
7554: }
7555:
7556: ushort
7557: AscSetIsaDmaChannel(
7558: PortAddr iop_base,
7559: ushort dma_channel
7560: )
7561: {
7562: ushort cfg_lsw;
7563: uchar value;
7564:
7565: if ((dma_channel >= 5) && (dma_channel <= 7)) {
7566:
7567: if (dma_channel == 7)
7568: value = 0x00;
7569: else
7570: value = dma_channel - 4;
7571: cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
7572: cfg_lsw |= value;
7573: AscSetChipCfgLsw(iop_base, cfg_lsw);
7574: return (AscGetIsaDmaChannel(iop_base));
7575: }
7576: return (0);
7577: }
7578:
7579: uchar
7580: AscSetIsaDmaSpeed(
7581: PortAddr iop_base,
7582: uchar speed_value
7583: )
7584: {
7585: speed_value &= 0x07;
7586: AscSetBank(iop_base, 1);
7587: AscSetChipDmaSpeed(iop_base, speed_value);
7588: AscSetBank(iop_base, 0);
7589: return (AscGetIsaDmaSpeed(iop_base));
7590: }
7591:
7592: uchar
7593: AscGetIsaDmaSpeed(
7594: PortAddr iop_base
7595: )
7596: {
7597: uchar speed_value;
7598:
7599: AscSetBank(iop_base, 1);
7600: speed_value = AscGetChipDmaSpeed(iop_base);
7601: speed_value &= 0x07;
7602: AscSetBank(iop_base, 0);
7603: return (speed_value);
7604: }
7605:
7606: ulong
7607: AscGetMaxDmaCount(
7608: ushort bus_type
7609: )
7610: {
7611: if (bus_type & ASC_IS_ISA)
7612: return (ASC_MAX_ISA_DMA_COUNT);
7613: else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
7614: return (ASC_MAX_VL_DMA_COUNT);
7615: return (ASC_MAX_PCI_DMA_COUNT);
7616: }
7617:
7618: ushort
7619: AscInitGetConfig(
7620: ASC_DVC_VAR asc_ptr_type * asc_dvc
7621: )
7622: {
7623: ushort warn_code;
7624:
7625: warn_code = 0;
7626: asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
7627: if (asc_dvc->err_code != 0)
7628: return (UW_ERR);
7629: if (AscFindSignature(asc_dvc->iop_base)) {
7630: warn_code |= AscInitAscDvcVar(asc_dvc);
7631: warn_code |= AscInitFromEEP(asc_dvc);
7632: asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
7633:
7634: if (asc_dvc->scsi_reset_wait > 10)
7635: asc_dvc->scsi_reset_wait = 10;
7636:
7637: } else {
7638: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
7639: }
7640: return (warn_code);
7641: }
7642:
7643: ushort
7644: AscInitSetConfig(
7645: ASC_DVC_VAR asc_ptr_type * asc_dvc
7646: )
7647: {
7648: ushort warn_code;
7649:
7650: warn_code = 0;
7651: asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
7652: if (asc_dvc->err_code != 0)
7653: return (UW_ERR);
7654: if (AscFindSignature(asc_dvc->iop_base)) {
7655: warn_code |= AscInitFromAscDvcVar(asc_dvc);
7656: asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
7657: } else {
7658: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
7659: }
7660: return (warn_code);
7661: }
7662:
7663: ushort
7664: AscInitAsc1000Driver(
7665: ASC_DVC_VAR asc_ptr_type * asc_dvc
7666: )
7667: {
7668: ushort warn_code;
7669: PortAddr iop_base;
7670:
7671: extern ushort _mcode_size;
7672: extern ulong _mcode_chksum;
7673: extern uchar _mcode_buf[];
7674:
7675: ASC_DBG(3, "AscInitAsc1000Driver: begin\n");
7676: iop_base = asc_dvc->iop_base;
7677: warn_code = 0;
7678:
7679: if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
7680: !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
7681:
7682: ASC_DBG(3, "AscInitAsc1000Driver: AscResetChipAndScsiBus()\n");
7683: AscResetChipAndScsiBus(iop_base);
7684: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
7685: }
7686: asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
7687: if (asc_dvc->err_code != 0)
7688: return (UW_ERR);
7689: ASC_DBG(3, "AscInitAsc1000Driver: AscFindSignature()\n");
7690: if (!AscFindSignature(asc_dvc->iop_base)) {
7691: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
7692: return (warn_code);
7693: }
7694: ASC_DBG(3, "AscInitAsc1000Driver: AscDisableInterrupt()\n");
7695: AscDisableInterrupt(iop_base);
7696:
7697: ASC_DBG(3, "AscInitAsc1000Driver: AscInitLram()\n");
7698: warn_code |= AscInitLram(asc_dvc);
7699: if (asc_dvc->err_code != 0)
7700: return (UW_ERR);
7701: ASC_DBG(3, "AscInitAsc1000Driver: AscLoadMicroCode()\n");
7702: if (AscLoadMicroCode(iop_base, 0, (ushort dosfar *) _mcode_buf,
7703: _mcode_size) != _mcode_chksum) {
7704: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
7705: return (warn_code);
7706: }
7707: ASC_DBG(3, "AscInitAsc1000Driver: AscInitMicroCodeVar()\n");
7708: warn_code |= AscInitMicroCodeVar(asc_dvc);
7709: asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
7710: ASC_DBG(3, "AscInitAsc1000Driver: AscEnableInterrupt()\n");
7711: AscEnableInterrupt(iop_base);
7712: return (warn_code);
7713: }
7714:
7715: ushort
7716: AscInitAscDvcVar(
7717: ASC_DVC_VAR asc_ptr_type * asc_dvc
7718: )
7719: {
7720: int i;
7721: PortAddr iop_base;
7722: ushort warn_code;
7723:
7724: iop_base = asc_dvc->iop_base;
7725: warn_code = 0;
7726: asc_dvc->err_code = 0;
7727:
7728: if ((asc_dvc->bus_type &
7729: (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
7730: asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
7731: }
7732: #if CC_LINK_BUSY_Q
7733: for (i = 0; i <= ASC_MAX_TID; i++) {
7734: asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
7735: asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
7736: }
7737: #endif
7738:
7739: asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
7740: asc_dvc->bug_fix_cntl = 0;
7741: asc_dvc->pci_fix_asyn_xfer = 0;
7742: asc_dvc->init_sdtr = 0;
7743: asc_dvc->sdtr_done = 0;
7744: asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
7745: asc_dvc->cur_total_qng = 0;
7746: asc_dvc->is_in_int = 0;
7747: asc_dvc->scsi_reset_wait = 3;
7748: asc_dvc->in_critical_cnt = 0;
7749:
7750: asc_dvc->last_q_shortage = 0;
7751: asc_dvc->use_tagged_qng = 0;
7752: asc_dvc->cfg->can_tagged_qng = 0;
7753: asc_dvc->no_scam = 0;
7754: asc_dvc->irq_no = 10;
7755: asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
7756: asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
7757: asc_dvc->cfg->cmd_qng_enabled = ASC_SCSI_WIDTH_BIT_SET;
7758: asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
7759: asc_dvc->cfg->chip_version = AscGetChipVersion(iop_base,
7760: asc_dvc->bus_type);
7761: if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
7762:
7763: AscPutChipIFC(iop_base, IFC_INIT_DEFAULT);
7764: asc_dvc->bus_type = ASC_IS_ISAPNP;
7765: }
7766: asc_dvc->unit_not_ready = 0;
7767: asc_dvc->queue_full_or_busy = 0;
7768:
7769: if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
7770: asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
7771: asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
7772: }
7773: asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
7774: asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
7775: ASC_LIB_VERSION_MINOR;
7776: asc_dvc->int_count = 0L;
7777: asc_dvc->req_count = 0L;
7778: asc_dvc->busy_count = 0L;
7779: asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
7780:
7781: for (i = 0; i <= ASC_MAX_TID; i++) {
7782: asc_dvc->cfg->sdtr_data[i] =
7783: (uchar) (ASC_DEF_SDTR_OFFSET | (ASC_DEF_SDTR_INDEX << 4));
7784: asc_dvc->cur_dvc_qng[i] = 0;
7785: asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
7786: asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
7787: asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
7788: }
7789: return (warn_code);
7790: }
7791:
7792: ushort
7793: AscInitFromAscDvcVar(
7794: ASC_DVC_VAR asc_ptr_type * asc_dvc
7795: )
7796: {
7797: PortAddr iop_base;
7798: ushort cfg_msw;
7799: ushort warn_code;
7800:
7801: iop_base = asc_dvc->iop_base;
7802: warn_code = 0;
7803:
7804: cfg_msw = AscGetChipCfgMsw(iop_base);
7805:
7806: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
7807: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
7808: warn_code |= ASC_WARN_CFG_MSW_RECOVER;
7809: AscSetChipCfgMsw(iop_base, cfg_msw);
7810: }
7811: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
7812: warn_code |= ASC_WARN_AUTO_CONFIG;
7813:
7814: }
7815: if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
7816: asc_dvc->cfg->cmd_qng_enabled) {
7817: asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
7818: warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
7819: }
7820: if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
7821:
7822: if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
7823: != asc_dvc->irq_no) {
7824: asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
7825: }
7826: }
7827: if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
7828: asc_dvc->cfg->chip_scsi_id) {
7829: asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
7830: }
7831: if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
7832: AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
7833: AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
7834: }
7835: return (warn_code);
7836: }
7837:
7838: ushort
7839: AscInitFromEEP(
7840: ASC_DVC_VAR asc_ptr_type * asc_dvc
7841: )
7842: {
7843: ASCEEP_CONFIG eep_config_buf;
7844: ASCEEP_CONFIG dosfar *eep_config;
7845: PortAddr iop_base;
7846: ushort chksum;
7847: ushort warn_code;
7848: ushort cfg_msw, cfg_lsw;
7849: uchar i;
7850:
7851: iop_base = asc_dvc->iop_base;
7852: warn_code = 0;
7853:
7854: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
7855:
7856: AscStopQueueExe(iop_base);
7857: if ((AscStopChip(iop_base) == FALSE) ||
7858: (AscGetChipScsiCtrl(iop_base) != 0)) {
7859: asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
7860: AscResetChipAndScsiBus(iop_base);
7861: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
7862: }
7863: if (AscIsChipHalted(iop_base) == FALSE) {
7864: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
7865: return (warn_code);
7866: }
7867: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
7868: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
7869: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
7870: return (warn_code);
7871: }
7872: eep_config = (ASCEEP_CONFIG dosfar *) & eep_config_buf;
7873:
7874: cfg_msw = AscGetChipCfgMsw(iop_base);
7875: cfg_lsw = AscGetChipCfgLsw(iop_base);
7876:
7877: if (asc_dvc->bus_type & ASC_IS_PCI) {
7878: #if CC_DISABLE_PCI_PARITY_INT
7879: cfg_msw &= 0xFFC0;
7880: AscSetChipCfgMsw(iop_base, cfg_msw);
7881: #endif
7882: if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) {
7883: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE;
7884: }
7885: }
7886: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
7887: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
7888: warn_code |= ASC_WARN_CFG_MSW_RECOVER;
7889: AscSetChipCfgMsw(iop_base, cfg_msw);
7890: }
7891: chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
7892:
7893: eep_config->cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
7894:
7895: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
7896: warn_code |= ASC_WARN_AUTO_CONFIG;
7897:
7898: if (asc_dvc->cfg->chip_version == 3) {
7899:
7900: if (eep_config->cfg_lsw != cfg_lsw) {
7901: warn_code |= ASC_WARN_EEPROM_RECOVER;
7902: eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
7903: }
7904: if (eep_config->cfg_msw != cfg_msw) {
7905: warn_code |= ASC_WARN_EEPROM_RECOVER;
7906: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
7907: }
7908: }
7909: }
7910: eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
7911: if (chksum != eep_config->chksum) {
7912: warn_code |= ASC_WARN_EEPROM_CHKSUM;
7913: }
7914: asc_dvc->init_sdtr = eep_config->init_sdtr;
7915: asc_dvc->cfg->disc_enable = eep_config->disc_enable;
7916:
7917: asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
7918: asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
7919: asc_dvc->start_motor = eep_config->start_motor;
7920: asc_dvc->dvc_cntl = eep_config->cntl;
7921: asc_dvc->no_scam = eep_config->no_scam;
7922:
7923: if ((asc_dvc->bus_type & ASC_IS_PCI) &&
7924: !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) {
7925: if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
7926: (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
7927: asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
7928: }
7929: } else if (asc_dvc->bus_type & ASC_IS_ISAPNP) {
7930:
7931: if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
7932: == ASC_CHIP_VER_ASYN_BUG) {
7933: asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
7934: }
7935: }
7936: if (!AscTestExternalLram(asc_dvc)) {
7937: if (asc_dvc->bus_type & ASC_IS_PCI) {
7938: eep_config->cfg_msw |= 0x0800;
7939: cfg_msw |= 0x0800;
7940: AscSetChipCfgMsw(iop_base, cfg_msw);
7941: eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
7942: eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
7943: }
7944: } else {
7945: #if CC_TEST_RW_LRAM
7946: asc_dvc->err_code |= AscTestLramEndian(iop_base);
7947: #endif
7948: }
7949: if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
7950: eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
7951: }
7952: if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
7953: eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
7954: }
7955: if (eep_config->max_tag_qng > eep_config->max_total_qng) {
7956: eep_config->max_tag_qng = eep_config->max_total_qng;
7957: }
7958: if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
7959: eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
7960: }
7961: asc_dvc->max_total_qng = eep_config->max_total_qng;
7962:
7963: if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
7964: eep_config->use_cmd_qng) {
7965: eep_config->disc_enable = eep_config->use_cmd_qng;
7966: warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
7967: }
7968: asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
7969: eep_config->chip_scsi_id &= ASC_MAX_TID;
7970: asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
7971:
7972: for (i = 0; i <= ASC_MAX_TID; i++) {
7973: asc_dvc->cfg->sdtr_data[i] = eep_config->sdtr_data[i];
7974: asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
7975: }
7976:
7977: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
7978: if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) {
7979: asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM;
7980: }
7981: return (warn_code);
7982: }
7983:
7984: ushort
7985: AscInitMicroCodeVar(
7986: ASC_DVC_VAR asc_ptr_type * asc_dvc
7987: )
7988: {
7989: int i;
7990: ushort warn_code;
7991: PortAddr iop_base;
7992: ulong phy_addr;
7993:
7994: iop_base = asc_dvc->iop_base;
7995: warn_code = 0;
7996: for (i = 0; i <= ASC_MAX_TID; i++) {
7997: AscWriteLramByte(iop_base, (ushort) (ASCV_SDTR_DATA_BEG + i),
7998: asc_dvc->cfg->sdtr_data[i]);
7999: }
8000:
8001: AscInitQLinkVar(asc_dvc);
8002:
8003: AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
8004: asc_dvc->cfg->disc_enable);
8005: AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
8006: ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
8007: if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
8008: (uchar dosfar *) asc_dvc->cfg->overrun_buf,
8009: ASC_OVERRUN_BSIZE)) == 0L) {
8010: asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
8011: } else {
8012:
8013: phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
8014: AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
8015: AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
8016: ASC_OVERRUN_BSIZE - 8);
8017: }
8018:
8019: asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
8020: (ushort) ASCV_MC_DATE_W);
8021: asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
8022: (ushort) ASCV_MC_VER_W);
8023: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8024: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8025: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8026: return (warn_code);
8027: }
8028: if (AscStartChip(iop_base) != 1) {
8029: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8030: return (warn_code);
8031: }
8032: return (warn_code);
8033: }
8034:
8035: void dosfar
8036: AscInitPollIsrCallBack(
8037: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8038: ASC_QDONE_INFO dosfar * scsi_done_q
8039: )
8040: {
8041: ASC_SCSI_REQ_Q dosfar *scsiq_req;
8042: ASC_ISR_CALLBACK asc_isr_callback;
8043: uchar cp_sen_len;
8044: uchar i;
8045:
8046: if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
8047: scsiq_req = (ASC_SCSI_REQ_Q dosfar *) scsi_done_q->d2.srb_ptr;
8048: ASC_DBG2(3, "AscInitPollIsrCallBack: done_stat %x, host_stat %x\n",
8049: scsiq_req->r3.done_stat, scsiq_req->r3.host_stat);
8050: scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat;
8051: scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
8052: scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
8053: scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
8054: if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
8055: (scsi_done_q->d3.host_stat == 0)) {
8056: cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
8057: if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) {
8058: cp_sen_len = (uchar) scsiq_req->r1.sense_len;
8059: }
8060: for (i = 0; i < cp_sen_len; i++) {
8061: scsiq_req->sense[i] = scsiq_req->sense_ptr[i];
8062: }
8063: }
8064: } else {
8065: ASC_DBG1(3, "AscInitPollIsrCallBack: isr_callback %x\n",
8066: (unsigned) asc_dvc->isr_callback);
8067: if (asc_dvc->isr_callback != 0) {
8068: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
8069: (*asc_isr_callback) (asc_dvc, scsi_done_q);
8070: }
8071: }
8072: return;
8073: }
8074:
8075: int
8076: AscTestExternalLram(
8077: ASC_DVC_VAR asc_ptr_type * asc_dvc
8078: )
8079: {
8080: PortAddr iop_base;
8081: ushort q_addr;
8082: ushort saved_word;
8083: int sta;
8084:
8085: iop_base = asc_dvc->iop_base;
8086: sta = 0;
8087:
8088: q_addr = ASC_QNO_TO_QADDR(241);
8089: saved_word = AscReadLramWord(iop_base, q_addr);
8090: if (AscVerWriteLramWord(iop_base, q_addr, 0x55AA) == 0) {
8091: sta = 1;
8092: AscWriteLramWord(iop_base, q_addr, saved_word);
8093: }
8094: return (sta);
8095: }
8096:
8097: #if CC_TEST_LRAM_ENDIAN
8098:
8099: #endif
8100:
8101: int
8102: AscWriteEEPCmdReg(
8103: PortAddr iop_base,
8104: uchar cmd_reg
8105: )
8106: {
8107: uchar read_back;
8108: int retry;
8109:
8110: retry = 0;
8111: while (TRUE) {
8112: AscSetChipEEPCmd(iop_base, cmd_reg);
8113: DvcSleepMilliSecond(1);
8114: read_back = AscGetChipEEPCmd(iop_base);
8115: if (read_back == cmd_reg) {
8116: return (1);
8117: }
8118: if (retry++ > ASC_EEP_MAX_RETRY) {
8119: return (0);
8120: }
8121: }
8122: }
8123:
8124: int
8125: AscWriteEEPDataReg(
8126: PortAddr iop_base,
8127: ushort data_reg
8128: )
8129: {
8130: ushort read_back;
8131: int retry;
8132:
8133: retry = 0;
8134: while (TRUE) {
8135: AscSetChipEEPData(iop_base, data_reg);
8136: DvcSleepMilliSecond(1);
8137: read_back = AscGetChipEEPData(iop_base);
8138: if (read_back == data_reg) {
8139: return (1);
8140: }
8141: if (retry++ > ASC_EEP_MAX_RETRY) {
8142: return (0);
8143: }
8144: }
8145: }
8146:
8147: void
8148: AscWaitEEPRead(
8149: void
8150: )
8151: {
8152: DvcSleepMilliSecond(1);
8153: return;
8154: }
8155:
8156: void
8157: AscWaitEEPWrite(
8158: void
8159: )
8160: {
8161: DvcSleepMilliSecond(20);
8162: return;
8163: }
8164:
8165: ushort
8166: AscReadEEPWord(
8167: PortAddr iop_base,
8168: uchar addr
8169: )
8170: {
8171: ushort read_wval;
8172: uchar cmd_reg;
8173:
8174: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
8175: AscWaitEEPRead();
8176: cmd_reg = addr | ASC_EEP_CMD_READ;
8177: AscWriteEEPCmdReg(iop_base, cmd_reg);
8178: AscWaitEEPRead();
8179: read_wval = AscGetChipEEPData(iop_base);
8180: AscWaitEEPRead();
8181: return (read_wval);
8182: }
8183:
8184: ushort
8185: AscWriteEEPWord(
8186: PortAddr iop_base,
8187: uchar addr,
8188: ushort word_val
8189: )
8190: {
8191: ushort read_wval;
8192:
8193: read_wval = AscReadEEPWord(iop_base, addr);
8194: if (read_wval != word_val) {
8195: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
8196: AscWaitEEPRead();
8197:
8198: AscWriteEEPDataReg(iop_base, word_val);
8199: AscWaitEEPRead();
8200:
8201: AscWriteEEPCmdReg(iop_base,
8202: (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
8203: AscWaitEEPWrite();
8204:
8205: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
8206: AscWaitEEPRead();
8207: return (AscReadEEPWord(iop_base, addr));
8208: }
8209: return (read_wval);
8210: }
8211:
8212: ushort
8213: AscGetEEPConfig(
8214: PortAddr iop_base,
8215: ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
8216: )
8217: {
8218: ushort wval;
8219: ushort sum;
8220: ushort dosfar *wbuf;
8221: int cfg_beg;
8222: int cfg_end;
8223: int s_addr;
8224: int isa_pnp_wsize;
8225:
8226: wbuf = (ushort dosfar *) cfg_buf;
8227: sum = 0;
8228:
8229: isa_pnp_wsize = 0;
8230: for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
8231: wval = AscReadEEPWord(iop_base, (uchar) s_addr);
8232: sum += wval;
8233: *wbuf = wval;
8234: }
8235:
8236: if (bus_type & ASC_IS_VL) {
8237: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
8238: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
8239: } else {
8240: cfg_beg = ASC_EEP_DVC_CFG_BEG;
8241: cfg_end = ASC_EEP_MAX_DVC_ADDR;
8242: }
8243:
8244: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
8245: s_addr++, wbuf++) {
8246: wval = AscReadEEPWord(iop_base, (uchar) s_addr);
8247: sum += wval;
8248: *wbuf = wval;
8249: }
8250: *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
8251: return (sum);
8252: }
8253:
8254: int
8255: AscSetEEPConfigOnce(
8256: PortAddr iop_base,
8257: ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
8258: )
8259: {
8260: int n_error;
8261: ushort dosfar *wbuf;
8262: ushort sum;
8263: int s_addr;
8264: int cfg_beg;
8265: int cfg_end;
8266:
8267: wbuf = (ushort dosfar *) cfg_buf;
8268: n_error = 0;
8269: sum = 0;
8270: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
8271: sum += *wbuf;
8272: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
8273: n_error++;
8274: }
8275: }
8276: if (bus_type & ASC_IS_VL) {
8277: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
8278: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
8279: } else {
8280: cfg_beg = ASC_EEP_DVC_CFG_BEG;
8281: cfg_end = ASC_EEP_MAX_DVC_ADDR;
8282: }
8283: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
8284: s_addr++, wbuf++) {
8285: sum += *wbuf;
8286: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
8287: n_error++;
8288: }
8289: }
8290: *wbuf = sum;
8291: if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
8292: n_error++;
8293: }
8294: wbuf = (ushort dosfar *) cfg_buf;
8295: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
8296: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
8297: n_error++;
8298: }
8299: }
8300: for (s_addr = cfg_beg; s_addr <= cfg_end;
8301: s_addr++, wbuf++) {
8302: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
8303: n_error++;
8304: }
8305: }
8306: return (n_error);
8307: }
8308:
8309: int
8310: AscSetEEPConfig(
8311: PortAddr iop_base,
8312: ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
8313: )
8314: {
8315: int retry;
8316: int n_error;
8317:
8318: retry = 0;
8319: while (TRUE) {
8320: if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
8321: bus_type)) == 0) {
8322: break;
8323: }
8324: if (++retry > ASC_EEP_MAX_RETRY) {
8325: break;
8326: }
8327: }
8328: return (n_error);
8329: }
8330:
8331: int
8332: AscInitPollBegin(
8333: ASC_DVC_VAR asc_ptr_type * asc_dvc
8334: )
8335: {
8336: PortAddr iop_base;
8337:
8338: iop_base = asc_dvc->iop_base;
8339:
8340: #if CC_INIT_INQ_DISPLAY
8341: DvcDisplayString((uchar dosfar *) "\r\n");
8342: #endif
8343:
8344: AscDisableInterrupt(iop_base);
8345:
8346: asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY;
8347:
8348: AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00);
8349: asc_dvc->use_tagged_qng = 0;
8350: asc_dvc->cfg->can_tagged_qng = 0;
8351: asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback;
8352: asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack);
8353: return (0);
8354: }
8355:
8356: int
8357: AscInitPollEnd(
8358: ASC_DVC_VAR asc_ptr_type * asc_dvc
8359: )
8360: {
8361: PortAddr iop_base;
8362: int i;
8363:
8364: iop_base = asc_dvc->iop_base;
8365: asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func;
8366: AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
8367: asc_dvc->cfg->disc_enable);
8368: AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B,
8369: asc_dvc->use_tagged_qng);
8370: AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B,
8371: asc_dvc->cfg->can_tagged_qng);
8372:
8373: for (i = 0; i <= ASC_MAX_TID; i++) {
8374: AscWriteLramByte(iop_base,
8375: (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i),
8376: asc_dvc->max_dvc_qng[i]);
8377: }
8378:
8379: AscEnableInterrupt(iop_base);
8380:
8381: #if CC_INIT_INQ_DISPLAY
8382: DvcDisplayString((uchar dosfar *) "\r\n");
8383: #endif
8384: asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
8385:
8386: return (0);
8387: }
8388:
8389: int _asc_wait_slow_device_ = FALSE;
8390:
8391: int
8392: AscInitPollTarget(
8393: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8394: ASC_SCSI_REQ_Q dosfar * scsiq,
8395: ASC_SCSI_INQUIRY dosfar * inq,
8396: ASC_CAP_INFO dosfar * cap_info
8397: )
8398: {
8399: uchar tid_no, lun;
8400: uchar dvc_type;
8401: ASC_SCSI_BIT_ID_TYPE tid_bits;
8402: int dvc_found;
8403: int support_read_cap;
8404: int tmp_disable_init_sdtr;
8405: ulong phy_addr;
8406:
8407: dvc_found = 0;
8408: tmp_disable_init_sdtr = FALSE;
8409: tid_bits = scsiq->r1.target_id;
8410: lun = scsiq->r1.target_lun;
8411: tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
8412: if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
8413: (uchar dosfar *) scsiq->sense_ptr,
8414: (ulong) scsiq->r1.sense_len)) == 0L) {
8415: return (ERR);
8416: }
8417: scsiq->r1.sense_addr = phy_addr;
8418: if (((asc_dvc->init_sdtr & tid_bits) != 0) &&
8419: ((asc_dvc->sdtr_done & tid_bits) == 0)) {
8420:
8421: asc_dvc->init_sdtr &= ~tid_bits;
8422: tmp_disable_init_sdtr = TRUE;
8423: }
8424: ASC_DBG(3, "AscInitPollTarget: PollScsiInquiry()\n");
8425: if (PollScsiInquiry(asc_dvc, scsiq, (uchar dosfar *) inq,
8426: sizeof (ASC_SCSI_INQUIRY)) == 1) {
8427: dvc_found = 1;
8428: support_read_cap = TRUE;
8429: dvc_type = inq->byte0.peri_dvc_type;
8430: if (dvc_type != SCSI_TYPE_UNKNOWN) {
8431: if ((dvc_type != SCSI_TYPE_DASD) &&
8432: (dvc_type != SCSI_TYPE_WORM) &&
8433: (dvc_type != SCSI_TYPE_CDROM) &&
8434: (dvc_type != SCSI_TYPE_OPTMEM)) {
8435: asc_dvc->start_motor &= ~tid_bits;
8436: support_read_cap = FALSE;
8437: }
8438: if ((dvc_type != SCSI_TYPE_DASD) ||
8439: inq->byte1.rmb) {
8440:
8441: if (!_asc_wait_slow_device_) {
8442: DvcSleepMilliSecond(3000 - ((int) tid_no * 250));
8443: _asc_wait_slow_device_ = TRUE;
8444: }
8445: }
8446: #if CC_INIT_INQ_DISPLAY
8447: AscDispInquiry(tid_no, lun, inq);
8448: #endif
8449:
8450: if (lun == 0) {
8451:
8452: if ((inq->byte3.rsp_data_fmt >= 2) ||
8453: (inq->byte2.ansi_apr_ver >= 2)) {
8454:
8455: if (inq->byte7.CmdQue) {
8456: asc_dvc->cfg->can_tagged_qng |= tid_bits;
8457: if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) {
8458: asc_dvc->use_tagged_qng |= tid_bits;
8459: asc_dvc->max_dvc_qng[tid_no] =
8460: asc_dvc->cfg->max_tag_qng[tid_no];
8461: }
8462: }
8463: if (!inq->byte7.Sync) {
8464:
8465: asc_dvc->init_sdtr &= ~tid_bits;
8466: asc_dvc->sdtr_done &= ~tid_bits;
8467: } else if (tmp_disable_init_sdtr) {
8468:
8469: asc_dvc->init_sdtr |= tid_bits;
8470: }
8471: } else {
8472:
8473: asc_dvc->init_sdtr &= ~tid_bits;
8474: asc_dvc->sdtr_done &= ~tid_bits;
8475: asc_dvc->use_tagged_qng &= ~tid_bits;
8476: }
8477: }
8478: if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
8479: if (!(asc_dvc->init_sdtr & tid_bits)) {
8480:
8481: AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
8482: ASYN_SDTR_DATA_FIX_PCI_REV_AB);
8483: }
8484: }
8485: ASC_DBG(3, "AscInitPollTarget: InitTestUnitReady()\n");
8486: if (InitTestUnitReady(asc_dvc, scsiq) != 1) {
8487:
8488: } else {
8489: if ((cap_info != 0L) && support_read_cap) {
8490: ASC_DBG(3, "AscInitPollTarget: PollScsiReadCapacity()\n");
8491: if (PollScsiReadCapacity(asc_dvc, scsiq,
8492: cap_info) != 1) {
8493: cap_info->lba = 0L;
8494: cap_info->blk_size = 0x0000;
8495: } else {
8496:
8497: }
8498: }
8499: }
8500: } else {
8501: asc_dvc->start_motor &= ~tid_bits;
8502: }
8503: } else {
8504:
8505: }
8506: return (dvc_found);
8507: }
8508:
8509: int
8510: PollQueueDone(
8511: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8512: ASC_SCSI_REQ_Q dosfar * scsiq,
8513: int timeout_sec
8514: )
8515: {
8516: int status;
8517: int retry;
8518:
8519: retry = 0;
8520: do {
8521: ASC_DBG(3, "PollQueueDone: AscExeScsiQueue()\n");
8522: if ((status = AscExeScsiQueue(asc_dvc,
8523: (ASC_SCSI_Q dosfar *) scsiq)) == 1) {
8524: ASC_DBG(3, "PollQueueDone: AscPollQDone()\n");
8525: if ((status = AscPollQDone(asc_dvc, scsiq,
8526: timeout_sec)) != 1) {
8527: ASC_DBG1(3, "PollQueueDone: AscPollQDone() status %x\n", status);
8528: if (status == 0x80) {
8529: if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
8530: break;
8531: }
8532: scsiq->r3.done_stat = 0;
8533: scsiq->r3.host_stat = 0;
8534: scsiq->r3.scsi_stat = 0;
8535: scsiq->r3.scsi_msg = 0;
8536: DvcSleepMilliSecond(100);
8537: continue;
8538: }
8539: scsiq->r3.done_stat = 0;
8540: scsiq->r3.host_stat = 0;
8541: scsiq->r3.scsi_stat = 0;
8542: scsiq->r3.scsi_msg = 0;
8543: ASC_DBG1(3, "PollQueueDone: AscAbortSRB() scsiq %x\n",
8544: (unsigned) scsiq);
8545:
8546: AscAbortSRB(asc_dvc, (ulong) scsiq);
8547: }
8548: ASC_DBG1(3, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
8549: return (scsiq->r3.done_stat);
8550: }
8551: } while ((status == 0) || (status == 0x80));
8552: ASC_DBG(3, "PollQueueDone: done_stat QD_WITH_ERROR\n");
8553: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8554: }
8555:
8556: int
8557: PollScsiInquiry(
8558: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8559: ASC_SCSI_REQ_Q dosfar * scsiq,
8560: uchar dosfar * buf,
8561: int buf_len
8562: )
8563: {
8564: if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
8565: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8566: }
8567: return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 4));
8568: }
8569:
8570: int
8571: PollScsiReadCapacity(
8572: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8573: ASC_SCSI_REQ_Q dosfar * scsiq,
8574: ASC_CAP_INFO dosfar * cap_info
8575: )
8576: {
8577: ASC_CAP_INFO scsi_cap_info;
8578: int status;
8579:
8580: if (AscScsiReadCapacity(asc_dvc, scsiq,
8581: (uchar dosfar *) & scsi_cap_info) == ERR) {
8582: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8583: }
8584: status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 8);
8585: if (status == 1) {
8586: #if CC_LITTLE_ENDIAN_HOST
8587: cap_info->lba = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.lba);
8588: cap_info->blk_size = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.blk_size);
8589: #else
8590: cap_info->lba = scsi_cap_info.lba;
8591: cap_info->blk_size = scsi_cap_info.blk_size;
8592: #endif
8593: return (scsiq->r3.done_stat);
8594: }
8595: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8596: }
8597:
8598: ulong dosfar *
8599: swapfarbuf4(
8600: uchar dosfar * buf
8601: )
8602: {
8603: uchar tmp;
8604:
8605: tmp = buf[3];
8606: buf[3] = buf[0];
8607: buf[0] = tmp;
8608:
8609: tmp = buf[1];
8610: buf[1] = buf[2];
8611: buf[2] = tmp;
8612:
8613: return ((ulong dosfar *) buf);
8614: }
8615:
8616: int
8617: PollScsiTestUnitReady(
8618: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8619: ASC_SCSI_REQ_Q dosfar * scsiq
8620: )
8621: {
8622: if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
8623: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8624: }
8625: return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 12));
8626: }
8627:
8628: int
8629: PollScsiStartUnit(
8630: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8631: ASC_SCSI_REQ_Q dosfar * scsiq
8632: )
8633: {
8634: if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
8635: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8636: }
8637: return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 40));
8638: }
8639:
8640: int
8641: InitTestUnitReady(
8642: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8643: ASC_SCSI_REQ_Q dosfar * scsiq
8644: )
8645: {
8646: ASC_SCSI_BIT_ID_TYPE tid_bits;
8647: int retry;
8648: ASC_REQ_SENSE dosfar *sen;
8649:
8650: retry = 0;
8651: tid_bits = scsiq->r1.target_id;
8652: while (retry++ < 2) {
8653: ASC_DBG(3, "InitTestUnitReady: PollScsiTestUnitReady()\n");
8654: PollScsiTestUnitReady(asc_dvc, scsiq);
8655: ASC_DBG1(3, "InitTestUnitReady: done_stat %x\n", scsiq->r3.done_stat);
8656: if (scsiq->r3.done_stat == 0x01) {
8657: return (1);
8658: } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
8659: DvcSleepMilliSecond(100);
8660:
8661: sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr;
8662:
8663: if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
8664: ((sen->err_code & 0x70) != 0)) {
8665:
8666: if (sen->sense_key == SCSI_SENKEY_NOT_READY) {
8667:
8668: if (asc_dvc->start_motor & tid_bits) {
8669: if (PollScsiStartUnit(asc_dvc, scsiq) == 1) {
8670: retry = 0;
8671: continue;
8672: } else {
8673: asc_dvc->start_motor &= ~tid_bits;
8674: break;
8675: }
8676: } else {
8677: DvcSleepMilliSecond(100);
8678: }
8679: } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) {
8680: DvcSleepMilliSecond(100);
8681: } else {
8682: break;
8683: }
8684: } else {
8685: break;
8686: }
8687: } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
8688: break;
8689: } else {
8690: break;
8691: }
8692: }
8693: return (0);
8694: }
8695:
8696: #if CC_INIT_INQ_DISPLAY
8697:
8698: #endif
8699:
8700: int
8701: AscPollQDone(
8702: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8703: ASC_SCSI_REQ_Q dosfar * scsiq,
8704: int timeout_sec
8705: )
8706: {
8707: int loop, loop_end;
8708: int sta;
8709: PortAddr iop_base;
8710:
8711: iop_base = asc_dvc->iop_base;
8712: loop = 0;
8713: loop_end = timeout_sec * 100;
8714: sta = 1;
8715:
8716: while (TRUE) {
8717: ASC_DBG4(3,
8718: "AscPollQDone: loop %d, err_code %x, done_stat %x, scsi_stat %x\n",
8719: loop, asc_dvc->err_code, scsiq->r3.done_stat, scsiq->r3.scsi_stat);
8720: if (asc_dvc->err_code != 0) {
8721: scsiq->r3.done_stat = QD_WITH_ERROR;
8722: sta = ERR;
8723: break;
8724: }
8725: if (scsiq->r3.done_stat != QD_IN_PROGRESS) {
8726: if ((scsiq->r3.done_stat == QD_WITH_ERROR) &&
8727: (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) {
8728: sta = 0x80;
8729: break;
8730: }
8731: break;
8732: }
8733: DvcSleepMilliSecond(10);
8734: if (loop++ > loop_end) {
8735: sta = 0;
8736: break;
8737: }
8738: if (AscIsChipHalted(iop_base)) {
8739: AscISR(asc_dvc);
8740: loop = 0;
8741: } else {
8742: ASC_DBG(3, "AscPollQDone: AscIsIntPending()\n");
8743: if (AscIsIntPending(iop_base)) {
8744: ASC_DBG(3, "AscPollQDone: AscISR()\n");
8745: AscISR(asc_dvc);
8746: }
8747: }
8748: }
8749: ASC_DBG1(3, "AscPollQDone: sta %x\n", sta);
8750: return (sta);
8751: }
8752:
8753: uchar
8754: AscReadLramByte(
8755: PortAddr iop_base,
8756: ushort addr
8757: )
8758: {
8759: uchar byte_data;
8760: ushort word_data;
8761:
8762: if (isodd_word(addr)) {
8763: AscSetChipLramAddr(iop_base, addr - 1);
8764: word_data = AscGetChipLramData(iop_base);
8765:
8766: #if CC_LITTLE_ENDIAN_HOST
8767: byte_data = (uchar) ((word_data >> 8) & 0xFF);
8768: #else
8769: byte_data = (uchar) (word_data & 0xFF);
8770: #endif
8771:
8772: } else {
8773: AscSetChipLramAddr(iop_base, addr);
8774: word_data = AscGetChipLramData(iop_base);
8775:
8776: #if CC_LITTLE_ENDIAN_HOST
8777: byte_data = (uchar) (word_data & 0xFF);
8778: #else
8779: byte_data = (uchar) ((word_data >> 8) & 0xFF);
8780: #endif
8781:
8782: }
8783: return (byte_data);
8784: }
8785:
8786: ushort
8787: AscReadLramWord(
8788: PortAddr iop_base,
8789: ushort addr
8790: )
8791: {
8792: ushort word_data;
8793:
8794: AscSetChipLramAddr(iop_base, addr);
8795: word_data = AscGetChipLramData(iop_base);
8796: return (word_data);
8797: }
8798:
8799: ulong
8800: AscReadLramDWord(
8801: PortAddr iop_base,
8802: ushort addr
8803: )
8804: {
8805: ushort val_low, val_high;
8806: ulong dword_data;
8807:
8808: AscSetChipLramAddr(iop_base, addr);
8809:
8810: #if CC_LITTLE_ENDIAN_HOST
8811: val_low = AscGetChipLramData(iop_base);
8812:
8813: val_high = AscGetChipLramData(iop_base);
8814: #else
8815: val_high = AscGetChipLramData(iop_base);
8816: val_low = AscGetChipLramData(iop_base);
8817: #endif
8818:
8819: dword_data = ((ulong) val_high << 16) | (ulong) val_low;
8820: return (dword_data);
8821: }
8822:
8823: void
8824: AscWriteLramWord(
8825: PortAddr iop_base,
8826: ushort addr,
8827: ushort word_val
8828: )
8829: {
8830: AscSetChipLramAddr(iop_base, addr);
8831: AscPutChipLramData(iop_base, word_val);
8832: return;
8833: }
8834:
8835: void
8836: AscWriteLramDWord(
8837: PortAddr iop_base,
8838: ushort addr,
8839: ulong dword_val
8840: )
8841: {
8842: ushort word_val;
8843:
8844: AscSetChipLramAddr(iop_base, addr);
8845:
8846: #if CC_LITTLE_ENDIAN_HOST
8847: word_val = (ushort) dword_val;
8848: AscPutChipLramData(iop_base, word_val);
8849: word_val = (ushort) (dword_val >> 16);
8850: AscPutChipLramData(iop_base, word_val);
8851: #else
8852: word_val = (ushort) (dword_val >> 16);
8853: AscPutChipLramData(iop_base, word_val);
8854: word_val = (ushort) dword_val;
8855: AscPutChipLramData(iop_base, word_val);
8856: #endif
8857: return;
8858: }
8859:
8860: void
8861: AscWriteLramByte(
8862: PortAddr iop_base,
8863: ushort addr,
8864: uchar byte_val
8865: )
8866: {
8867: ushort word_data;
8868:
8869: if (isodd_word(addr)) {
8870: addr--;
8871: word_data = AscReadLramWord(iop_base, addr);
8872: word_data &= 0x00FF;
8873: word_data |= (((ushort) byte_val << 8) & 0xFF00);
8874: } else {
8875: word_data = AscReadLramWord(iop_base, addr);
8876: word_data &= 0xFF00;
8877: word_data |= ((ushort) byte_val & 0x00FF);
8878: }
8879: AscWriteLramWord(iop_base, addr, word_data);
8880: return;
8881: }
8882:
8883: int
8884: AscVerWriteLramWord(
8885: PortAddr iop_base,
8886: ushort addr,
8887: ushort word_val
8888: )
8889: {
8890: int sta;
8891:
8892: sta = 0;
8893: AscSetChipLramAddr(iop_base, addr);
8894: AscPutChipLramData(iop_base, word_val);
8895: AscSetChipLramAddr(iop_base, addr);
8896: if (word_val != AscGetChipLramData(iop_base)) {
8897: sta = ERR;
8898: }
8899: return (sta);
8900: }
8901:
8902: void
8903: AscMemWordCopyToLram(
8904: PortAddr iop_base,
8905: ushort s_addr,
8906: ushort dosfar * s_buffer,
8907: int words
8908: )
8909: {
8910: AscSetChipLramAddr(iop_base, s_addr);
8911: DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
8912: return;
8913: }
8914:
8915: void
8916: AscMemDWordCopyToLram(
8917: PortAddr iop_base,
8918: ushort s_addr,
8919: ulong dosfar * s_buffer,
8920: int dwords
8921: )
8922: {
8923: AscSetChipLramAddr(iop_base, s_addr);
8924: DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
8925: return;
8926: }
8927:
8928: void
8929: AscMemWordCopyFromLram(
8930: PortAddr iop_base,
8931: ushort s_addr,
8932: ushort dosfar * d_buffer,
8933: int words
8934: )
8935: {
8936: AscSetChipLramAddr(iop_base, s_addr);
8937: DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
8938: return;
8939: }
8940:
8941: ulong
8942: AscMemSumLramWord(
8943: PortAddr iop_base,
8944: ushort s_addr,
8945: rint words
8946: )
8947: {
8948: ulong sum;
8949: int i;
8950:
8951: sum = 0L;
8952: for (i = 0; i < words; i++, s_addr += 2) {
8953: sum += AscReadLramWord(iop_base, s_addr);
8954: }
8955: return (sum);
8956: }
8957:
8958: void
8959: AscMemWordSetLram(
8960: PortAddr iop_base,
8961: ushort s_addr,
8962: ushort set_wval,
8963: rint words
8964: )
8965: {
8966: rint i;
8967:
8968: AscSetChipLramAddr(iop_base, s_addr);
8969: for (i = 0; i < words; i++) {
8970: AscPutChipLramData(iop_base, set_wval);
8971: }
8972: return;
8973: }
8974:
8975: int
8976: AscScsiInquiry(
8977: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8978: ASC_SCSI_REQ_Q dosfar * scsiq,
8979: uchar dosfar * buf, int buf_len
8980: )
8981: {
8982: if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
8983: (ulong) buf_len) == ERR) {
8984: return (scsiq->r3.done_stat = QD_WITH_ERROR);
8985: }
8986: scsiq->cdb[0] = (uchar) SCSICMD_Inquiry;
8987: scsiq->cdb[1] = scsiq->r1.target_lun << 5;
8988: scsiq->cdb[2] = 0;
8989: scsiq->cdb[3] = 0;
8990: scsiq->cdb[4] = buf_len;
8991: scsiq->cdb[5] = 0;
8992: scsiq->r2.cdb_len = 6;
8993: return (0);
8994: }
8995:
8996: int
8997: AscScsiReadCapacity(
8998: ASC_DVC_VAR asc_ptr_type * asc_dvc,
8999: ASC_SCSI_REQ_Q dosfar * scsiq,
9000: uchar dosfar * info
9001: )
9002: {
9003: if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) {
9004: return (scsiq->r3.done_stat = QD_WITH_ERROR);
9005: }
9006: scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity;
9007: scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9008: scsiq->cdb[2] = 0;
9009: scsiq->cdb[3] = 0;
9010: scsiq->cdb[4] = 0;
9011: scsiq->cdb[5] = 0;
9012: scsiq->cdb[6] = 0;
9013: scsiq->cdb[7] = 0;
9014: scsiq->cdb[8] = 0;
9015: scsiq->cdb[9] = 0;
9016: scsiq->r2.cdb_len = 10;
9017: return (0);
9018: }
9019:
9020: int
9021: AscScsiTestUnitReady(
9022: ASC_DVC_VAR asc_ptr_type * asc_dvc,
9023: ASC_SCSI_REQ_Q dosfar * scsiq
9024: )
9025: {
9026: if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR,
9027: (ulong) 0L) == ERR) {
9028: return (scsiq->r3.done_stat = QD_WITH_ERROR);
9029: }
9030: scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
9031: scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady;
9032: scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9033: scsiq->cdb[2] = 0;
9034: scsiq->cdb[3] = 0;
9035: scsiq->cdb[4] = 0;
9036: scsiq->cdb[5] = 0;
9037: scsiq->r2.cdb_len = 6;
9038: return (0);
9039: }
9040:
9041: int
9042: AscScsiStartStopUnit(
9043: ASC_DVC_VAR asc_ptr_type * asc_dvc,
9044: ASC_SCSI_REQ_Q dosfar * scsiq,
9045: uchar op_mode
9046: )
9047: {
9048: if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) {
9049: return (scsiq->r3.done_stat = QD_WITH_ERROR);
9050: }
9051: scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
9052: scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit;
9053: scsiq->cdb[1] = scsiq->r1.target_lun << 5;
9054: scsiq->cdb[2] = 0;
9055: scsiq->cdb[3] = 0;
9056: scsiq->cdb[4] = op_mode;
9057:
9058: scsiq->cdb[5] = 0;
9059: scsiq->r2.cdb_len = 6;
9060: return (0);
9061: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.