patch-1.3.58 linux/drivers/scsi/advansys.c

Next file: linux/drivers/scsi/advansys.h
Previous file: linux/drivers/scsi/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
@@ -0,0 +1,9061 @@
+/* $Id: advansys.c,v 1.11 1996/01/16 22:39:19 bobf Exp bobf $ */
+/*
+ * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
+ * 
+ * Copyright (c) 1995-1996 Advanced System Products, Inc.
+ * All Rights Reserved.
+ *
+ * This driver may be modified and freely distributed provided that
+ * the above copyright message and this comment are included in the
+ * distribution. The latest version of this driver is available at
+ * the AdvanSys FTP and BBS sites listed below.
+ *
+ * Please send questions, comments, bug reports to:
+ * bobf@advansys.com (Bob Frey)
+ */
+
+/* The driver has been tested with Linux 1.2.1 and 1.3.57 kernels. */
+#define ASC_VERSION "1.2"	/* AdvanSys Driver Version */
+
+/*
+
+  Documentation for the AdvanSys Driver
+
+  A. Adapters Supported by this Driver
+  B. Linux 1.2.X - Directions for Adding the AdvanSys Driver
+  C. Linux 1.3.X - Directions for Adding the AdvanSys Driver
+  D. Source Comments
+  E. Driver Compile Time Options and Debugging
+  F. Driver LILO Option
+  G. Release History
+  H. Known Problems or Issues
+  I. Credits
+  J. AdvanSys Contact Information
+
+
+  A. Adapters Supported by this Driver
+ 
+     AdvanSys (Advanced System Products, Inc.) manufactures the following
+     Bus-Mastering SCSI-2 Host Adapters for the ISA, EISA, VL, and PCI
+     buses. This Linux driver supports all of these adapters.
+     
+     The CDB counts below indicate the number of SCSI CDB (Command
+     Descriptor Block) requests that can be stored in the RISC chip
+     cache and board LRAM. The driver detect routine will display the
+     number of CDBs available for each adapter detected. This value
+     can be lowered in the BIOS by changing the 'Host Queue Size'
+     adapter setting.
+
+     Connectivity Products:
+       ABP920 - Bus-Master PCI 16 CDB
+       ABP930 - Bus-Master PCI 16 CDB
+       ABP5140 - Bus-Master PnP ISA 16 CDB
+   
+     Single Channel Products:
+       ABP542 - Bus-Master ISA 240 CDB
+       ABP5150 - Bus-Master ISA 240 CDB *
+       ABP742 - Bus-Master EISA 240 CDB
+       ABP842 - Bus-Master VL 240 CDB
+       ABP940 - Bus-Master PCI 240 CDB
+   
+     Dual Channel Products:
+       ABP950 - Dual Channel Bus-Master PCI 240 CDB Per Channel
+       ABP852 - Dual Channel Bus-Master VL 240 CDB Per Channel
+       ABP752 - Dual Channel Bus-Master EISA 240 CDB Per Channel
+
+     * This board is shipped by HP with the 4020i CD-R drive. It has
+       no BIOS so it cannot control a boot device, but it can control
+       any secondary devices.
+ 
+  B. Linux 1.2.X - Directions for Adding the AdvanSys Driver
+ 
+     There are two source files: advansys.h and advansys.c. Copy
+     both of these files to the directory /usr/src/linux/drivers/scsi.
+    
+     1. Add the following line to /usr/src/linux/arch/i386/config.in
+        after "comment 'SCSI low-level drivers'":
+    
+          bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
+    
+     2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
+        after "#include "hosts.h"":
+    
+          #ifdef CONFIG_SCSI_ADVANSYS
+          #include "advansys.h"
+          #endif
+    
+        and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
+    
+          #ifdef CONFIG_SCSI_ADVANSYS
+          ADVANSYS,
+          #endif
+    
+     3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
+    
+          ifdef CONFIG_SCSI_ADVANSYS
+          SCSI_SRCS := $(SCSI_SRCS) advansys.c
+          SCSI_OBJS := $(SCSI_OBJS) advansys.o
+          else
+          SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
+          endif
+
+     4. (Optional) If you would like to enable the LILO command line
+        and /etc/lilo.conf 'advansys' option, make the following changes.
+        This option can be used to disable I/O port scanning or to limit
+        I/O port scanning to specific addresses. Refer to the 'Driver
+        LILO Option' section below. Add the following lines to
+        /usr/src/linux/init/main.c in the prototype section:
+
+          extern void advansys_setup(char *str, int *ints);
+
+        and add the following lines to the bootsetups[] array.
+
+          #ifdef CONFIG_SCSI_ADVANSYS
+             { "advansys=", advansys_setup },
+          #endif
+
+     5. If you have the HP 4020i CD-R driver and Linux 1.2.X you should
+        add a fix to the CD-ROM target driver. This fix will allow
+        you to mount CDs with the iso9660 file system. Linux 1.3.X
+        already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
+        and function get_sectorsize() after the line:
+
+        if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
+
+        add the following line:
+
+        if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
+
+     6. In the directory /usr/src/linux run 'make config' to configure
+        the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
+        make the kernel. If the AdvanSys driver is not configured, then
+        a loadable module can be built by running 'make modules' and
+        'make modules_install'. Use 'insmod' and 'rmmod' to install
+        and remove advansys.o.
+ 
+  C. Linux 1.3.X - Directions for Adding the AdvanSys Driver
+
+     There are two source files: advansys.h and advansys.c. Copy
+     both of these files to the directory /usr/src/linux/drivers/scsi.
+   
+     1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
+        after "comment 'SCSI low-level drivers'":
+   
+          dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
+   
+     2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
+        after "#include "hosts.h"":
+   
+          #ifdef CONFIG_SCSI_ADVANSYS
+          #include "advansys.h"
+          #endif
+   
+        and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
+   
+          #ifdef CONFIG_SCSI_ADVANSYS
+          ADVANSYS,
+          #endif
+   
+     3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
+   
+          ifeq ($(CONFIG_SCSI_ADVANSYS),y)
+          L_OBJS += advansys.o
+          else
+            ifeq ($(CONFIG_SCSI_ADVANSYS),m)
+            M_OBJS += advansys.o
+            endif
+          endif
+   
+     4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
+        in the enum scsi_directory_inos array:
+   
+          PROC_SCSI_ADVANSYS,
+   
+     5. (Optional) If you would like to enable the LILO command line
+        and /etc/lilo.conf 'advansys' option, make the following changes.
+        This option can be used to disable I/O port scanning or to limit
+        I/O port scanning to specific addresses. Refer to the 'Driver
+        LILO Option' section below. Add the following lines to
+        /usr/src/linux/init/main.c in the prototype section:
+   
+          extern void advansys_setup(char *str, int *ints);
+   
+        and add the following lines to the bootsetups[] array.
+   
+          #ifdef CONFIG_SCSI_ADVANSYS
+             { "advansys=", advansys_setup },
+          #endif
+   
+     6. In the directory /usr/src/linux run 'make config' to configure
+        the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
+        make the kernel. If the AdvanSys driver is not configured, then
+        a loadable module can be built by running 'make modules' and
+        'make modules_install'. Use 'insmod' and 'rmmod' to install
+        and remove advansys.o.
+
+  D. Source Comments
+ 
+     1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
+ 
+     2. This driver should be maintained in multiple files. But to make
+        it easier to include with Linux and to follow Linux conventions,
+        the whole driver is maintained in the source files advansys.h and
+        advansys.c. In this file logical sections of the driver begin with
+        a comment that contains '---'. The following are the logical sections
+        of the driver below.
+ 
+           --- Linux Version
+           --- Linux Include Files 
+           --- Driver Options
+           --- Asc Library Constants and Macros
+           --- Debugging Header
+           --- Driver Constants
+           --- Driver Macros
+           --- Driver Structures
+           --- Driver Data
+           --- Driver Function Prototypes
+           --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
+           --- Loadable Driver Support
+           --- Miscellaneous Driver Functions
+           --- Functions Required by the Asc Library
+           --- Tracing and Debugging Functions
+           --- Asc Library Functions
+ 
+     3. The string 'XXX' is used to flag code that needs to be re-written
+        or that contains a problem that needs to be addressed.
+ 
+     4. I have stripped comments from and reformatted the source for the
+        Asc Library which is included in this file. I haven't done this
+        to obfuscate the code. Actually I have done this to deobfuscate
+        the code. The Asc Library source can be found under the following
+        headings.
+ 
+           --- Asc Library Constants and Macros
+           --- Asc Library Functions
+ 
+  E. Driver Compile Time Options and Debugging
+ 
+     In this source file the following constants can be defined. They are
+     defined in the source below. Both of these options are enabled by
+     default.
+ 
+     1. ADVANSYS_DEBUG - enable for debugging and assertions
+ 
+        The amount of debugging output can be controlled with the global
+        variable 'asc_dbglvl'. The higher the number the more output. By
+        default the debug level is 0.
+        
+        If the driver is loaded at boot time and the LILO Driver Option
+        is included in the system, the debug level can be changed by
+        specifying a 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. The
+        first three hex digits of the pseudo I/O Port must be set to
+        'deb' and the fourth hex digit specifies the debug level: 0 - F.
+        The following command line will look for an adapter at 0x330
+        and set the debug level to 2.
+
+           linux advansys=0x330,0x0,0x0,0x0,0xdeb2
+
+        If the driver is built as a loadable module this variable can be
+        defined when the driver is loaded. The following insmod command
+        will set the debug level to one.
+  
+           insmod advansys.o asc_dbglvl=1
+ 
+ 
+        Debugging Message Levels:
+           0: Errors Only
+           1: High-Level Tracing
+           2-N: Verbose Tracing
+ 
+        I don't know the approved way for turning on printk()s to the
+        console. Here's a program I use to do this. Debug output is
+        logged in /var/adm/messages.
+ 
+          main()
+          {
+                  syscall(103, 7, 0, 0);
+          }
+ 
+        I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
+        prevents most level 1 debug messages from being lost.
+ 
+     2. ADVANSYS_STATS - enable statistics and tracing
+ 
+        For Linux 1.2.X if ADVANSYS_STATS_1_2_PRINT is defined every
+        10,000 I/O operations the driver will print statistics to the
+        console. This value can be changed by modifying the constant
+        used in advansys_queuecommand(). ADVANSYS_STATS_1_2_PRINT is
+        off by default.
+
+        For Linux 1.3.X statistics can be accessed by reading the
+        /proc/scsi/advansys/[0-9] files.
+
+        Note: these statistics are currently maintained on a global driver
+        basis and not per board.
+
+  F. Driver LILO Option
+ 
+     If init/main.c is modified as described in the 'Directions for Adding
+     the AdvanSys Driver to Linux' section (B.4.) above, the driver will
+     recognize the 'advansys' LILO command line and /etc/lilo.conf option.
+     This option can be used to either disable I/O port scanning or to limit
+     scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and
+     PCI boards will still be searched for and detected. This option only
+     affects searching for ISA and VL boards.
+
+     Examples:
+       1. Eliminate I/O port scanning:
+            boot: linux advansys=
+              or
+            boot: linux advansys=0x0
+       2. Limit I/O port scanning to one I/O port:
+            boot: linux advansys=0x110
+       3. Limit I/O port scanning to four I/O ports:
+            boot: linux advansys=0x110,0x210,0x230,0x330
+
+     For a loadable module the same effect can be achieved by setting
+     the 'asc_iopflag' variable and 'asc_ioport' array when loading
+     the driver, e.g.
+
+           insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
+
+     If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 1)
+     I/O Port may be added to specify the driver debug level. Refer to
+     the 'Driver Compile Time Options and Debugging' section above for
+     more information.
+
+  G. Release History
+
+     12/23/95 BETA-1.0:
+         First Release
+
+     12/28/95 BETA-1.1:
+         1. Prevent advansys_detect() from being called twice.
+         2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
+
+     1/12/96 1.2:
+         1. Prevent re-entrancy in the interrupt handler which
+            resulted in the driver hanging Linux.
+         2. Fix problem that prevented ABP-940 cards from being
+            recognized on some PCI motherboards.
+         3. Add support for the ABP-5140 PnP ISA card.
+         4. Fix check condition return status.
+         5. Add conditionally compiled code for Linux 1.3.X.
+        
+  H. Known Problems or Issues
+
+     1. The setting for 'cmd_per_lun' needs to be changed. It is currently
+        less then what the AdvanSys boards can queue. Because the target and
+        mid-level Linux drivers base memory allocation on 'cmd_per_lun' (as
+        well as 'sg_tablesize') memory use gets out of hand with a large
+        'cmd_per_lun'. 'cmd_per_lun' should be per device instead of per
+        adapter. When the driver is compiled as a loadable module both
+        'cmd_per_lun' and 'sg_tablesize' are tuned down to try to prevent
+        memory allocation errors.
+
+     2. For the first scsi command sent to a device the driver increases
+        the timeout value. This gives the driver more time to perform
+        its own initialization for the board and each device. The timeout
+        value is only changed on the first scsi command for each device
+        and never thereafter.
+
+  I. Credits
+
+     Nathan Hartwell (mage@cdc3.cdc.net) provided the directions and
+     and basis for the Linux 1.3.X changes which were included in the
+     1.2 release.
+
+  J. AdvanSys Contact Information
+ 
+     Mail:                   Advanced System Products, Inc.
+                             1150 Ringwood Court
+                             San Jose, CA 95131 USA
+     Operator:               1-408-383-9400
+     FAX:                    1-408-383-9612
+     Tech Support:           1-800-525-7440
+     BBS:                    1-408-383-9540 (9600,N,8,1)
+     Interactive FAX:        1-408-383-9753
+     Customer Direct Sales:  1-800-883-1099
+     Tech Support E-Mail:    support@advansys.com
+     Linux Support E-Mail:   bobf@advansys.com
+     FTP Site:               ftp.advansys.com (login: anonymous)
+     Web Site:               http://www.advansys.com
+
+*/
+
+
+/*
+ * --- Linux Version
+ */
+
+/*
+ * The driver can be used in Linux 1.2.X or 1.3.X.
+ */
+#if !defined(LINUX_1_2) && !defined(LINUX_1_3)
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif /* LINUX_VERSION_CODE */
+#if LINUX_VERSION_CODE > 65536 + 3 * 256
+#define LINUX_1_3
+#else /* LINUX_VERSION_CODE */
+#define LINUX_1_2
+#endif /* LINUX_VERSION_CODE */
+#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */
+
+
+/*
+ * --- Linux Include Files 
+ */
+
+#ifdef MODULE
+#ifdef LINUX_1_3
+#include <linux/autoconf.h>
+#endif /* LINUX_1_3 */ 
+#include <linux/module.h>
+#endif /* MODULE */
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/config.h>
+#ifdef LINUX_1_3
+#include <linux/proc_fs.h>
+#endif /* LINUX_1_3 */ 
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#ifdef LINUX_1_2
+#include "../block/blk.h"
+#else /* LINUX_1_3 */ 
+#include <linux/blk.h>
+#include <linux/stat.h>
+#endif /* LINUX_1_3 */ 
+#include "scsi.h"
+#include "hosts.h"
+#include "sd.h"
+#include "advansys.h"
+
+
+/*
+ * --- Driver Options
+ */
+#define ADVANSYS_DEBUG /* Enable for debugging and assertions. */
+#define ADVANSYS_STATS /* Enable for statistics and tracing. */
+#ifdef LINUX_1_2
+#undef ADVANSYS_STATS_1_2_PRINT /* Enable to print statistics to console. */
+#endif /* LINUX_1_2 */
+
+
+/*
+ * --- Asc Library Constants and Macros
+ */
+
+#define ASC_LIB_VERSION_MAJOR  1
+#define ASC_LIB_VERSION_MINOR  16
+#define ASC_LIB_SERIAL_NUMBER  53
+
+typedef unsigned char uchar;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+typedef int         BOOL;
+
+#ifndef NULL
+#define NULL     (0)
+#endif
+
+#ifndef TRUE
+#define TRUE     (1)
+#endif
+
+#ifndef FALSE
+#define FALSE    (0)
+#endif
+
+#define  REG     register
+
+#define rchar    REG char
+#define rshort   REG short
+#define rint     REG int
+#define rlong    REG long
+
+#define ruchar   REG uchar
+#define rushort  REG ushort
+#define ruint    REG uint
+#define rulong   REG ulong
+
+#define NULLPTR   ( void *)0
+#define FNULLPTR  ( void dosfar *)0UL
+#define EOF      (-1)
+#define EOS      '\0'
+#define ERR      (-1)
+#define UB_ERR   (uchar)(0xFF)
+#define UW_ERR   (uint)(0xFFFF)
+#define UL_ERR   (ulong)(0xFFFFFFFFUL)
+
+#define iseven_word( val )  ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 )
+#define isodd_word( val )   ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 )
+#define toeven_word( val )  ( ( ( uint )val ) & ( uint )0xFFFE )
+
+#define biton( val, bits )   ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 )
+#define bitoff( val, bits )  ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 )
+#define lbiton( val, bits )  ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 )
+#define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 )
+
+#define  absh( val )    ( ( val ) < 0 ? -( val ) : ( val ) )
+
+#define  swapbyte( ch )  ( ( ( (ch) << 4 ) | ( (ch) >> 4 ) ) )
+
+#ifndef GBYTE
+#define GBYTE       (0x40000000UL)
+#endif
+
+#ifndef MBYTE
+#define MBYTE       (0x100000UL)
+#endif
+
+#ifndef KBYTE
+#define KBYTE       (0x400)
+#endif
+
+#define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) )
+#define LO_BYTE(x) ( *( ( BYTE *)&x ) )
+
+#define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) )
+#define LO_WORD(x) ( *( ( WORD *)&x ) )
+
+#ifndef MAKEWORD
+#define MAKEWORD(lo, hi)    ((WORD) (((WORD) lo) | ((WORD) hi << 8)))
+#endif
+
+#ifndef MAKELONG
+#define MAKELONG(lo, hi)    ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16)))
+#endif
+
+#define SwapWords(dWord)        ((DWORD) ((dWord >> 16) | (dWord << 16)))
+#define SwapBytes(word)         ((WORD) ((word >> 8) | (word << 8)))
+
+#define BigToLittle(dWord) \
+    ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
+#define LittleToBig(dWord)      BigToLittle(dWord)
+
+#define Lptr
+#define dosfar
+#define far
+#define PortAddr			unsigned short
+#define Ptr2Func        	ulong
+
+#define inp(port)        	inb(port)
+#define inpw(port)       	inw(port)
+#define outp(port, byte)    outb((byte), (port))
+#define outpw(port, word)   outw((word), (port))
+
+#define ASC_MAX_SG_QUEUE	5
+#define ASC_MAX_SG_LIST		(1 + ((ASC_SG_LIST_PER_Q) * (ASC_MAX_SG_QUEUE)))
+
+#define CC_INIT_INQ_DISPLAY     FALSE
+
+#define CC_CLEAR_LRAM_SRB_PTR   FALSE
+#define CC_VERIFY_LRAM_COPY     FALSE
+
+#define CC_DEBUG_SG_LIST        FALSE
+#define CC_FAST_STRING_IO       FALSE
+
+#define CC_WRITE_IO_COUNT       FALSE
+#define CC_CLEAR_DMA_REMAIN     FALSE
+
+#define CC_DISABLE_PCI_PARITY_INT TRUE
+
+#define CC_LINK_BUSY_Q         FALSE
+
+#define CC_TARGET_MODE         FALSE
+
+#define CC_SCAM                FALSE
+
+#define CC_LITTLE_ENDIAN_HOST  TRUE
+
+#ifndef CC_TEST_LRAM_ENDIAN
+
+#if CC_LITTLE_ENDIAN_HOST
+#define CC_TEST_LRAM_ENDIAN     FALSE
+#else
+#define CC_TEST_LRAM_ENDIAN     TRUE
+#endif
+
+#endif
+
+#define CC_STRUCT_ALIGNED      TRUE
+
+#define CC_MEMORY_MAPPED_IO    FALSE
+
+#ifndef CC_TARGET_MODE
+#define CC_TARGET_MODE         FALSE
+#endif
+
+#ifndef CC_STRUCT_ALIGNED
+#define CC_STRUCT_ALIGNED      FALSE
+#endif
+
+#ifndef CC_LITTLE_ENDIAN_HOST
+#define CC_LITTLE_ENDIAN_HOST  TRUE
+#endif
+
+#if !CC_LITTLE_ENDIAN_HOST
+
+#ifndef CC_TEST_LRAM_ENDIAN
+#define CC_TEST_LRAM_ENDIAN    TRUE
+#endif
+
+#endif
+
+#ifndef CC_MEMORY_MAPPED_IO
+#define CC_MEMORY_MAPPED_IO    FALSE
+#endif
+
+#ifndef CC_WRITE_IO_COUNT
+#define CC_WRITE_IO_COUNT      FALSE
+#endif
+
+#ifndef CC_CLEAR_DMA_REMAIN
+#define CC_CLEAR_DMA_REMAIN    FALSE
+#endif
+
+#define ASC_CS_TYPE  unsigned short
+
+#ifndef asc_ptr_type
+#define asc_ptr_type
+#endif
+
+#ifndef CC_SCAM
+#define CC_SCAM  FALSE
+#endif
+
+#ifndef ASC_GET_PTR2FUNC
+#define ASC_GET_PTR2FUNC( fun )  ( Ptr2Func )( fun )
+#endif
+
+#define FLIP_BYTE_NIBBLE( x )    ( ((x<<4)& 0xFF) | (x>>4) )
+
+#define ASC_IS_ISA          (0x0001)
+#define ASC_IS_ISAPNP       (0x0081)
+#define ASC_IS_EISA         (0x0002)
+#define ASC_IS_PCI          (0x0004)
+#define ASC_IS_PCMCIA       (0x0008)
+#define ASC_IS_PNP          (0x0010)
+#define ASC_IS_MCA          (0x0020)
+#define ASC_IS_VL           (0x0040)
+
+#define ASC_ISA_PNP_PORT_ADDR  (0x279)
+#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
+
+#define ASC_IS_WIDESCSI_16  (0x0100)
+#define ASC_IS_WIDESCSI_32  (0x0200)
+
+#define ASC_IS_BIG_ENDIAN   (0x8000)
+
+#define ASC_CHIP_MIN_VER_VL      (0x01)
+#define ASC_CHIP_MAX_VER_VL      (0x07)
+
+#define ASC_CHIP_MIN_VER_PCI     (0x09)
+#define ASC_CHIP_MAX_VER_PCI     (0x0F)
+#define ASC_CHIP_VER_PCI_BIT     (0x08)
+
+#define ASC_CHIP_MIN_VER_ISA     (0x11)
+#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
+#define ASC_CHIP_MAX_VER_ISA     (0x27)
+#define ASC_CHIP_VER_ISA_BIT     (0x30)
+#define ASC_CHIP_VER_ISAPNP_BIT  (0x20)
+
+#define ASC_CHIP_VER_ASYN_BUG    (0x21)
+
+#define ASC_CHIP_MIN_VER_EISA (0x41)
+#define ASC_CHIP_MAX_VER_EISA (0x47)
+#define ASC_CHIP_VER_EISA_BIT (0x40)
+
+#define ASC_MAX_VL_DMA_ADDR     (0x07FFFFFFL)
+#define ASC_MAX_VL_DMA_COUNT    (0x07FFFFFFL)
+
+#define ASC_MAX_PCI_DMA_ADDR    (0xFFFFFFFFL)
+#define ASC_MAX_PCI_DMA_COUNT   (0xFFFFFFFFL)
+
+#define ASC_MAX_ISA_DMA_ADDR    (0x00FFFFFFL)
+#define ASC_MAX_ISA_DMA_COUNT   (0x00FFFFFFL)
+
+#define ASC_MAX_EISA_DMA_ADDR   (0x07FFFFFFL)
+#define ASC_MAX_EISA_DMA_COUNT  (0x07FFFFFFL)
+
+#if !CC_STRUCT_ALIGNED
+
+#define DvcGetQinfo( iop_base, s_addr, outbuf, words)  \
+        AscMemWordCopyFromLram( iop_base, s_addr, outbuf, words)
+
+#define DvcPutScsiQ( iop_base, s_addr, outbuf, words) \
+        AscMemWordCopyToLram( iop_base, s_addr, outbuf, words)
+
+#endif
+
+#define ASC_SCSI_ID_BITS  3
+#define ASC_SCSI_TIX_TYPE     uchar
+#define ASC_ALL_DEVICE_BIT_SET  0xFF
+
+#ifdef ASC_WIDESCSI_16
+
+#undef  ASC_SCSI_ID_BITS
+#define ASC_SCSI_ID_BITS  4
+#define ASC_ALL_DEVICE_BIT_SET  0xFFFF
+
+#endif
+
+#ifdef ASC_WIDESCSI_32
+
+#undef  ASC_SCSI_ID_BITS
+#define ASC_SCSI_ID_BITS  5
+#define ASC_ALL_DEVICE_BIT_SET  0xFFFFFFFFL
+
+#endif
+
+#if ASC_SCSI_ID_BITS == 3
+
+#define ASC_SCSI_BIT_ID_TYPE  uchar
+#define ASC_MAX_TID       7
+#define ASC_MAX_LUN       7
+#define ASC_SCSI_WIDTH_BIT_SET  0xFF
+
+#elif ASC_SCSI_ID_BITS == 4
+
+#define ASC_SCSI_BIT_ID_TYPE   ushort
+#define ASC_MAX_TID         15
+#define ASC_MAX_LUN         7
+#define ASC_SCSI_WIDTH_BIT_SET  0xFFFF
+
+#elif ASC_SCSI_ID_BITS == 5
+
+#define ASC_SCSI_BIT_ID_TYPE    ulong
+#define ASC_MAX_TID         31
+#define ASC_MAX_LUN         7
+#define ASC_SCSI_WIDTH_BIT_SET  0xFFFFFFFF
+
+#else
+
+#error  ASC_SCSI_ID_BITS definition is wrong
+
+#endif
+
+#define ASC_MAX_SENSE_LEN   32
+#define ASC_MIN_SENSE_LEN   14
+
+#define ASC_MAX_CDB_LEN     12
+
+#define SCSICMD_TestUnitReady     0x00
+#define SCSICMD_Rewind            0x01
+#define SCSICMD_Rezero            0x01
+#define SCSICMD_RequestSense      0x03
+#define SCSICMD_Format            0x04
+#define SCSICMD_FormatUnit        0x04
+#define SCSICMD_Read6             0x08
+#define SCSICMD_Write6            0x0A
+#define SCSICMD_Seek6             0x0B
+#define SCSICMD_Inquiry           0x12
+#define SCSICMD_Verify6           0x13
+#define SCSICMD_ModeSelect6       0x15
+#define SCSICMD_ModeSense6        0x1A
+
+#define SCSICMD_StartStopUnit     0x1B
+#define SCSICMD_LoadUnloadTape    0x1B
+#define SCSICMD_ReadCapacity      0x25
+#define SCSICMD_Read10            0x28
+#define SCSICMD_Write10           0x2A
+#define SCSICMD_Seek10            0x2B
+#define SCSICMD_Erase10           0x2C
+#define SCSICMD_WriteAndVerify10  0x2E
+#define SCSICMD_Verify10          0x2F
+
+#define SCSICMD_ModeSelect10      0x55
+#define SCSICMD_ModeSense10       0x5A
+
+#define SCSI_TYPE_DASD     0x00
+#define SCSI_TYPE_SASD     0x01
+#define SCSI_TYPE_PRN      0x02
+#define SCSI_TYPE_PROC     0x03
+
+#define SCSI_TYPE_WORM     0x04
+#define SCSI_TYPE_CDROM    0x05
+#define SCSI_TYPE_SCANNER  0x06
+#define SCSI_TYPE_OPTMEM   0x07
+#define SCSI_TYPE_MED_CHG  0x08
+#define SCSI_TYPE_COMM     0x09
+#define SCSI_TYPE_UNKNOWN  0x1F
+#define SCSI_TYPE_NO_DVC   0xFF
+
+#define ASC_SCSIDIR_NOCHK    0x00
+
+#define ASC_SCSIDIR_T2H      0x08
+
+#define ASC_SCSIDIR_H2T      0x10
+
+#define ASC_SCSIDIR_NODATA   0x18
+
+#define SCSI_SENKEY_NO_SENSE      0x00
+#define SCSI_SENKEY_UNDEFINED     0x01
+#define SCSI_SENKEY_NOT_READY     0x02
+#define SCSI_SENKEY_MEDIUM_ERR    0x03
+#define SCSI_SENKEY_HW_ERR        0x04
+#define SCSI_SENKEY_ILLEGAL       0x05
+#define SCSI_SENKEY_ATTENSION     0x06
+#define SCSI_SENKEY_PROTECTED     0x07
+#define SCSI_SENKEY_BLANK         0x08
+#define SCSI_SENKEY_V_UNIQUE      0x09
+#define SCSI_SENKEY_CPY_ABORT     0x0A
+#define SCSI_SENKEY_ABORT         0x0B
+#define SCSI_SENKEY_EQUAL         0x0C
+#define SCSI_SENKEY_VOL_OVERFLOW  0x0D
+#define SCSI_SENKEY_MISCOMP       0x0E
+#define SCSI_SENKEY_RESERVED      0x0F
+
+#define ASC_SRB_HOST( x )  ( ( uchar )( ( uchar )( x ) >> 4 ) )
+#define ASC_SRB_TID( x )   ( ( uchar )( ( uchar )( x ) & ( uchar )0x0F ) )
+
+#define ASC_SRB_LUN( x )   ( ( uchar )( ( uint )( x ) >> 13 ) )
+
+#define PUT_CDB1( x )   ( ( uchar )( ( uint )( x ) >> 8 ) )
+
+#define SS_GOOD              0x00
+#define SS_CHK_CONDITION     0x02
+#define SS_CONDITION_MET     0x04
+#define SS_TARGET_BUSY       0x08
+#define SS_INTERMID          0x10
+#define SS_INTERMID_COND_MET 0x14
+
+#define SS_RSERV_CONFLICT    0x18
+#define SS_CMD_TERMINATED    0x22
+
+#define SS_QUEUE_FULL        0x28
+
+#define MS_CMD_DONE    0x00
+#define MS_EXTEND      0x01
+#define MS_SDTR_LEN    0x03
+#define MS_SDTR_CODE   0x01
+
+#define M1_SAVE_DATA_PTR        0x02
+#define M1_RESTORE_PTRS         0x03
+#define M1_DISCONNECT           0x04
+#define M1_INIT_DETECTED_ERR    0x05
+#define M1_ABORT                0x06
+#define M1_MSG_REJECT           0x07
+#define M1_NO_OP                0x08
+#define M1_MSG_PARITY_ERR       0x09
+#define M1_LINK_CMD_DONE        0x0A
+#define M1_LINK_CMD_DONE_WFLAG  0x0B
+#define M1_BUS_DVC_RESET        0x0C
+#define M1_ABORT_TAG            0x0D
+#define M1_CLR_QUEUE            0x0E
+#define M1_INIT_RECOVERY        0x0F
+#define M1_RELEASE_RECOVERY     0x10
+#define M1_KILL_IO_PROC         0x11
+
+#define M2_QTAG_MSG_SIMPLE      0x20
+#define M2_QTAG_MSG_HEAD        0x21
+#define M2_QTAG_MSG_ORDERED     0x22
+#define M2_IGNORE_WIDE_RESIDUE  0x23
+
+typedef struct {
+	uchar               peri_dvc_type:5;
+	uchar               peri_qualifier:3;
+} ASC_SCSI_INQ0;
+
+typedef struct {
+	uchar               dvc_type_modifier:7;
+	uchar               rmb:1;
+} ASC_SCSI_INQ1;
+
+typedef struct {
+	uchar               ansi_apr_ver:3;
+	uchar               ecma_ver:3;
+	uchar               iso_ver:2;
+} ASC_SCSI_INQ2;
+
+typedef struct {
+	uchar               rsp_data_fmt:4;
+
+	uchar               res:2;
+	uchar               TemIOP:1;
+	uchar               aenc:1;
+} ASC_SCSI_INQ3;
+
+typedef struct {
+	uchar               StfRe:1;
+	uchar               CmdQue:1;
+	uchar               Reserved:1;
+	uchar               Linked:1;
+	uchar               Sync:1;
+	uchar               WBus16:1;
+	uchar               WBus32:1;
+	uchar               RelAdr:1;
+} ASC_SCSI_INQ7;
+
+typedef struct {
+	ASC_SCSI_INQ0       byte0;
+	ASC_SCSI_INQ1       byte1;
+	ASC_SCSI_INQ2       byte2;
+	ASC_SCSI_INQ3       byte3;
+	uchar               add_len;
+	uchar               res1;
+	uchar               res2;
+	ASC_SCSI_INQ7       byte7;
+	uchar               vendor_id[8];
+	uchar               product_id[16];
+	uchar               product_rev_level[4];
+} ASC_SCSI_INQUIRY;
+
+typedef struct asc_req_sense {
+	uchar               err_code:7;
+	uchar               info_valid:1;
+	uchar               segment_no;
+	uchar               sense_key:4;
+	uchar               reserved_bit:1;
+	uchar               sense_ILI:1;
+	uchar               sense_EOM:1;
+	uchar               file_mark:1;
+	uchar               info1[4];
+	uchar               add_sense_len;
+	uchar               cmd_sp_info[4];
+	uchar               asc;
+	uchar               ascq;
+
+	uchar               fruc;
+	uchar               sks_byte0:7;
+	uchar               sks_valid:1;
+	uchar               sks_bytes[2];
+	uchar               notused[2];
+	uchar               ex_sense_code;
+	uchar               info2[4];
+} ASC_REQ_SENSE;
+
+#define ASC_SG_LIST_PER_Q   7
+
+#define QS_FREE        0x00
+#define QS_READY       0x01
+#define QS_DISC1       0x02
+#define QS_DISC2       0x04
+#define QS_BUSY        0x08
+
+#define QS_ABORTED     0x40
+#define QS_DONE        0x80
+
+#define QC_NO_CALLBACK   0x01
+
+#define QC_SG_SWAP_QUEUE 0x02
+#define QC_SG_HEAD       0x04
+#define QC_DATA_IN       0x08
+#define QC_DATA_OUT      0x10
+
+#define QC_URGENT        0x20
+#define QC_MSG_OUT       0x40
+#define QC_REQ_SENSE     0x80
+
+#define QCSG_SG_XFER_LIST  0x02
+#define QCSG_SG_XFER_MORE  0x04
+#define QCSG_SG_XFER_END   0x08
+
+#define QD_IN_PROGRESS       0x00
+#define QD_NO_ERROR          0x01
+#define QD_ABORTED_BY_HOST   0x02
+#define QD_WITH_ERROR        0x04
+#define QD_INVALID_REQUEST   0x80
+#define QD_INVALID_HOST_NUM  0x81
+#define QD_INVALID_DEVICE    0x82
+#define QD_ERR_INTERNAL      0xFF
+
+#define QHSTA_NO_ERROR               0x00
+#define QHSTA_M_SEL_TIMEOUT          0x11
+#define QHSTA_M_DATA_OVER_RUN        0x12
+#define QHSTA_M_DATA_UNDER_RUN       0x12
+#define QHSTA_M_UNEXPECTED_BUS_FREE  0x13
+#define QHSTA_M_BAD_BUS_PHASE_SEQ    0x14
+
+#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
+#define QHSTA_D_ASC_DVC_ERROR_CODE_SET  0x22
+#define QHSTA_D_HOST_ABORT_FAILED       0x23
+#define QHSTA_D_EXE_SCSI_Q_FAILED       0x24
+#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
+
+#define QHSTA_D_ASPI_NO_BUF_POOL        0x26
+
+#define QHSTA_M_WTM_TIMEOUT         0x41
+#define QHSTA_M_BAD_CMPL_STATUS_IN  0x42
+#define QHSTA_M_NO_AUTO_REQ_SENSE   0x43
+#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
+#define QHSTA_M_TARGET_STATUS_BUSY  0x45
+#define QHSTA_M_BAD_TAG_CODE        0x46
+
+#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY  0x47
+
+#define QHSTA_D_LRAM_CMP_ERROR        0x81
+#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
+
+#define ASC_FLAG_SCSIQ_REQ        0x01
+#define ASC_FLAG_BIOS_SCSIQ_REQ   0x02
+#define ASC_FLAG_BIOS_ASYNC_IO    0x04
+#define ASC_FLAG_SRB_LINEAR_ADDR  0x08
+
+#define ASC_FLAG_WIN16            0x10
+#define ASC_FLAG_WIN32            0x20
+
+#define ASC_FLAG_DOS_VM_CALLBACK  0x80
+
+#define ASC_TAG_FLAG_ADD_ONE_BYTE     0x10
+#define ASC_TAG_FLAG_ISAPNP_ADD_BYTES 0x40
+
+#define ASC_SCSIQ_CPY_BEG              4
+#define ASC_SCSIQ_SGHD_CPY_BEG         2
+
+#define ASC_SCSIQ_B_FWD                0
+#define ASC_SCSIQ_B_BWD                1
+
+#define ASC_SCSIQ_B_STATUS             2
+#define ASC_SCSIQ_B_QNO                3
+
+#define ASC_SCSIQ_B_CNTL               4
+#define ASC_SCSIQ_B_SG_QUEUE_CNT       5
+
+#define ASC_SCSIQ_D_DATA_ADDR          8
+#define ASC_SCSIQ_D_DATA_CNT          12
+#define ASC_SCSIQ_B_SENSE_LEN         20
+#define ASC_SCSIQ_DONE_INFO_BEG       22
+#define ASC_SCSIQ_D_SRBPTR            22
+#define ASC_SCSIQ_B_TARGET_IX         26
+#define ASC_SCSIQ_B_CDB_LEN           28
+#define ASC_SCSIQ_B_TAG_CODE          29
+#define ASC_SCSIQ_W_VM_ID             30
+#define ASC_SCSIQ_DONE_STATUS         32
+#define ASC_SCSIQ_HOST_STATUS         33
+#define ASC_SCSIQ_SCSI_STATUS         34
+#define ASC_SCSIQ_CDB_BEG             36
+#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
+#define ASC_SCSIQ_DW_REMAIN_XFER_CNT  60
+#define ASC_SCSIQ_B_SG_WK_QP          49
+#define ASC_SCSIQ_B_SG_WK_IX          50
+#define ASC_SCSIQ_W_REQ_COUNT         52
+#define ASC_SCSIQ_B_LIST_CNT          6
+#define ASC_SCSIQ_B_CUR_LIST_CNT      7
+
+#define ASC_SGQ_B_SG_CNTL             4
+#define ASC_SGQ_B_SG_HEAD_QP          5
+#define ASC_SGQ_B_SG_LIST_CNT         6
+#define ASC_SGQ_B_SG_CUR_LIST_CNT     7
+#define ASC_SGQ_LIST_BEG              8
+
+#define ASC_DEF_SCSI1_QNG    2
+#define ASC_MAX_SCSI1_QNG    2
+#define ASC_DEF_SCSI2_QNG    16
+#define ASC_MAX_SCSI2_QNG    32
+
+#define ASC_TAG_CODE_MASK    0x23
+
+#define ASC_STOP_REQ_RISC_STOP      0x01
+
+#define ASC_STOP_ACK_RISC_STOP      0x03
+
+#define ASC_STOP_CLEAN_UP_BUSY_Q    0x10
+#define ASC_STOP_CLEAN_UP_DISC_Q    0x20
+#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
+#define ASC_STOP_SEND_INT_TO_HOST   0x80
+
+#define ASC_TIDLUN_TO_IX( tid, lun )  ( ASC_SCSI_TIX_TYPE )( (tid) + ((lun)<<ASC_SCSI_ID_BITS) )
+
+#define ASC_TID_TO_TARGET_ID( tid )   ( ASC_SCSI_BIT_ID_TYPE )( 0x01 << (tid) )
+#define ASC_TIX_TO_TARGET_ID( tix )   ( 0x01 << ( (tix) & ASC_MAX_TID ) )
+#define ASC_TIX_TO_TID( tix )  ( (tix) & ASC_MAX_TID )
+#define ASC_TID_TO_TIX( tid )  ( (tid) & ASC_MAX_TID )
+#define ASC_TIX_TO_LUN( tix )  ( ( (tix) >> ASC_SCSI_ID_BITS ) & ASC_MAX_LUN )
+
+#define ASC_QNO_TO_QADDR( q_no )      ( (ASC_QADR_BEG)+( ( int )(q_no) << 6 ) )
+
+typedef struct asc_scisq_1 {
+	uchar               status;
+	uchar               q_no;
+	uchar               cntl;
+	uchar               sg_queue_cnt;
+
+	uchar               target_id;
+	uchar               target_lun;
+
+	ulong               data_addr;
+	ulong               data_cnt;
+	ulong               sense_addr;
+	uchar               sense_len;
+	uchar               user_def;
+} ASC_SCSIQ_1;
+
+typedef struct asc_scisq_2 {
+	ulong               srb_ptr;
+	uchar               target_ix;
+
+	uchar               flag;
+	uchar               cdb_len;
+	uchar               tag_code;
+
+	ushort              vm_id;
+} ASC_SCSIQ_2;
+
+typedef struct asc_scsiq_3 {
+	uchar               done_stat;
+	uchar               host_stat;
+	uchar               scsi_stat;
+	uchar               scsi_msg;
+} ASC_SCSIQ_3;
+
+typedef struct asc_scsiq_4 {
+	uchar               cdb[ASC_MAX_CDB_LEN];
+	uchar               y_first_sg_list_qp;
+	uchar               y_working_sg_qp;
+	uchar               y_working_sg_ix;
+	uchar               y_cntl;
+	ushort              x_req_count;
+	ushort              x_reconnect_rtn;
+	ulong               x_saved_data_addr;
+	ulong               x_saved_data_cnt;
+} ASC_SCSIQ_4;
+
+typedef struct asc_q_done_info {
+	ASC_SCSIQ_2         d2;
+	ASC_SCSIQ_3         d3;
+	uchar               q_status;
+	uchar               q_no;
+	uchar               cntl;
+	uchar               sense_len;
+	uchar               user_def;
+	uchar               res;
+	ulong               remain_bytes;
+} ASC_QDONE_INFO;
+
+typedef struct asc_sg_list {
+	ulong               addr;
+	ulong               bytes;
+} ASC_SG_LIST;
+
+typedef struct asc_sg_head {
+	uchar               entry_cnt;
+
+	uchar               queue_cnt;
+
+	uchar               entry_to_copy;
+	uchar               res;
+	ASC_SG_LIST         sg_list[ASC_MAX_SG_LIST];
+} ASC_SG_HEAD;
+
+#define ASC_MIN_SG_LIST   2
+
+typedef struct asc_min_sg_head {
+	uchar               entry_cnt;
+
+	uchar               queue_cnt;
+
+	uchar               entry_to_copy;
+	uchar               res;
+	ASC_SG_LIST         sg_list[ASC_MIN_SG_LIST];
+} ASC_MIN_SG_HEAD;
+
+#define QCX_SORT        (0x0001)
+#define QCX_COALEASE    (0x0002)
+
+#if CC_LINK_BUSY_Q
+typedef struct asc_ext_scsi_q {
+	ulong               lba;
+	ushort              lba_len;
+	struct asc_scsi_q dosfar *next;
+	struct asc_scsi_q dosfar *join;
+	ushort              cntl;
+	ushort              buffer_id;
+	uchar               q_required;
+	uchar               res;
+} ASC_EXT_SCSI_Q;
+
+#endif
+
+typedef struct asc_scsi_q {
+	ASC_SCSIQ_1         q1;
+	ASC_SCSIQ_2         q2;
+	uchar dosfar       *cdbptr;
+
+	ASC_SG_HEAD dosfar *sg_head;
+
+#if CC_LINK_BUSY_Q
+	ASC_EXT_SCSI_Q      ext;
+#endif
+
+} ASC_SCSI_Q;
+
+typedef struct asc_scsi_req_q {
+	ASC_SCSIQ_1         r1;
+	ASC_SCSIQ_2         r2;
+	uchar dosfar       *cdbptr;
+	ASC_SG_HEAD dosfar *sg_head;
+
+#if CC_LINK_BUSY_Q
+	ASC_EXT_SCSI_Q      ext;
+#endif
+
+	uchar dosfar       *sense_ptr;
+
+	ASC_SCSIQ_3         r3;
+	uchar               cdb[ASC_MAX_CDB_LEN];
+	uchar               sense[ASC_MIN_SENSE_LEN];
+} ASC_SCSI_REQ_Q;
+
+typedef struct asc_risc_q {
+	uchar               fwd;
+	uchar               bwd;
+	ASC_SCSIQ_1         i1;
+	ASC_SCSIQ_2         i2;
+	ASC_SCSIQ_3         i3;
+	ASC_SCSIQ_4         i4;
+} ASC_RISC_Q;
+
+typedef struct asc_sg_list_q {
+
+	uchar               seq_no;
+	uchar               q_no;
+	uchar               cntl;
+	uchar               sg_head_qp;
+	uchar               sg_list_cnt;
+	uchar               sg_cur_list_cnt;
+
+} ASC_SG_LIST_Q;
+
+typedef struct asc_risc_sg_list_q {
+	uchar               fwd;
+	uchar               bwd;
+	ASC_SG_LIST_Q       sg;
+	ASC_SG_LIST         sg_list[7];
+} ASC_RISC_SG_LIST_Q;
+
+#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP  0x1000000UL
+#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP  1024
+
+#define ASCQ_ERR_NO_ERROR             0
+#define ASCQ_ERR_IO_NOT_FOUND         1
+#define ASCQ_ERR_LOCAL_MEM            2
+#define ASCQ_ERR_CHKSUM               3
+#define ASCQ_ERR_START_CHIP           4
+#define ASCQ_ERR_INT_TARGET_ID        5
+#define ASCQ_ERR_INT_LOCAL_MEM        6
+#define ASCQ_ERR_HALT_RISC            7
+#define ASCQ_ERR_GET_ASPI_ENTRY       8
+#define ASCQ_ERR_CLOSE_ASPI           9
+#define ASCQ_ERR_HOST_INQUIRY         0x0A
+#define ASCQ_ERR_SAVED_SRB_BAD        0x0B
+#define ASCQ_ERR_QCNTL_SG_LIST        0x0C
+#define ASCQ_ERR_Q_STATUS             0x0D
+#define ASCQ_ERR_WR_SCSIQ             0x0E
+#define ASCQ_ERR_PC_ADDR              0x0F
+#define ASCQ_ERR_SYN_OFFSET           0x10
+#define ASCQ_ERR_SYN_XFER_TIME        0x11
+#define ASCQ_ERR_LOCK_DMA             0x12
+#define ASCQ_ERR_UNLOCK_DMA           0x13
+#define ASCQ_ERR_VDS_CHK_INSTALL      0x14
+#define ASCQ_ERR_MICRO_CODE_HALT      0x15
+#define ASCQ_ERR_SET_LRAM_ADDR        0x16
+#define ASCQ_ERR_CUR_QNG              0x17
+#define ASCQ_ERR_SG_Q_LINKS           0x18
+#define ASCQ_ERR_SCSIQ_PTR            0x19
+#define ASCQ_ERR_ISR_RE_ENTRY         0x1A
+#define ASCQ_ERR_CRITICAL_RE_ENTRY    0x1B
+#define ASCQ_ERR_ISR_ON_CRITICAL      0x1C
+#define ASCQ_ERR_SG_LIST_ODD_ADDRESS  0x1D
+#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
+#define ASCQ_ERR_SCSIQ_NULL_PTR       0x1F
+#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR   0x20
+#define ASCQ_ERR_GET_NUM_OF_FREE_Q    0x21
+#define ASCQ_ERR_SEND_SCSI_Q          0x22
+#define ASCQ_ERR_HOST_REQ_RISC_HALT   0x23
+#define ASCQ_ERR_RESET_SDTR           0x24
+
+#define ASC_WARN_NO_ERROR             0x0000
+#define ASC_WARN_IO_PORT_ROTATE       0x0001
+#define ASC_WARN_EEPROM_CHKSUM        0x0002
+#define ASC_WARN_IRQ_MODIFIED         0x0004
+#define ASC_WARN_AUTO_CONFIG          0x0008
+#define ASC_WARN_CMD_QNG_CONFLICT     0x0010
+
+#define ASC_WARN_EEPROM_RECOVER       0x0020
+#define ASC_WARN_CFG_MSW_RECOVER      0x0040
+
+#define ASC_IERR_WRITE_EEPROM         0x0001
+#define ASC_IERR_MCODE_CHKSUM         0x0002
+#define ASC_IERR_SET_PC_ADDR          0x0004
+#define ASC_IERR_START_STOP_CHIP      0x0008
+
+#define ASC_IERR_IRQ_NO               0x0010
+
+#define ASC_IERR_SET_IRQ_NO           0x0020
+#define ASC_IERR_CHIP_VERSION         0x0040
+#define ASC_IERR_SET_SCSI_ID          0x0080
+#define ASC_IERR_GET_PHY_ADDR         0x0100
+#define ASC_IERR_BAD_SIGNATURE        0x0200
+#define ASC_IERR_NO_BUS_TYPE          0x0400
+#define ASC_IERR_SCAM                 0x0800
+#define ASC_IERR_SET_SDTR             0x1000
+#define ASC_IERR_RW_LRAM              0x8000
+
+#define ASC_DEF_IRQ_NO  10
+#define ASC_MAX_IRQ_NO  15
+#define ASC_MIN_IRQ_NO  10
+
+#define ASC_MIN_REMAIN_Q        (0x02)
+#define ASC_DEF_MAX_TOTAL_QNG   (0x40)
+
+#define ASC_MIN_TAG_Q_PER_DVC   (0x04)
+#define ASC_DEF_TAG_Q_PER_DVC   (0x04)
+
+#define ASC_MIN_FREE_Q        ASC_MIN_REMAIN_Q
+
+#define ASC_MIN_TOTAL_QNG     (( ASC_MAX_SG_QUEUE )+( ASC_MIN_FREE_Q ))
+
+#define ASC_MAX_TOTAL_QNG 240
+#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
+
+#define ASC_MAX_INRAM_TAG_QNG   16
+
+typedef struct asc_dvc_cfg {
+	ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
+
+	ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
+	ASC_SCSI_BIT_ID_TYPE disc_enable;
+	uchar               res;
+	uchar               chip_scsi_id:4;
+
+	uchar               isa_dma_speed:4;
+
+	uchar               isa_dma_channel;
+	uchar               chip_version;
+	ushort              pci_device_id;
+	ushort              lib_serial_no;
+	ushort              lib_version;
+	ushort              mcode_date;
+	ushort              mcode_version;
+	uchar               sdtr_data[ASC_MAX_TID + 1];
+	uchar               max_tag_qng[ASC_MAX_TID + 1];
+	uchar dosfar       *overrun_buf;
+
+} ASC_DVC_CFG;
+
+#define ASC_DEF_DVC_CNTL       0xFFFF
+#define ASC_DEF_CHIP_SCSI_ID   7
+#define ASC_DEF_ISA_DMA_SPEED  4
+
+#define ASC_INIT_STATE_NULL          0x0000
+#define ASC_INIT_STATE_BEG_GET_CFG   0x0001
+#define ASC_INIT_STATE_END_GET_CFG   0x0002
+#define ASC_INIT_STATE_BEG_SET_CFG   0x0004
+#define ASC_INIT_STATE_END_SET_CFG   0x0008
+#define ASC_INIT_STATE_BEG_LOAD_MC   0x0010
+#define ASC_INIT_STATE_END_LOAD_MC   0x0020
+#define ASC_INIT_STATE_BEG_INQUIRY   0x0040
+#define ASC_INIT_STATE_END_INQUIRY   0x0080
+#define ASC_INIT_RESET_SCSI_DONE     0x0100
+
+#define ASC_PCI_DEVICE_ID_REV_A      0x1100
+#define ASC_PCI_DEVICE_ID_REV_B      0x1200
+
+#define ASC_BUG_FIX_ADD_ONE_BYTE     0x0001
+
+#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
+
+#define ASC_MIN_TAGGED_CMD  7
+
+typedef struct asc_dvc_var {
+	PortAddr            iop_base;
+	ushort              err_code;
+	ushort              dvc_cntl;
+	ushort              bug_fix_cntl;
+	ushort              bus_type;
+	Ptr2Func            isr_callback;
+	Ptr2Func            exe_callback;
+
+	ASC_SCSI_BIT_ID_TYPE init_sdtr;
+
+	ASC_SCSI_BIT_ID_TYPE sdtr_done;
+
+	ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
+
+	ASC_SCSI_BIT_ID_TYPE unit_not_ready;
+
+	ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
+
+	ASC_SCSI_BIT_ID_TYPE start_motor;
+	uchar               scsi_reset_wait;
+	uchar               chip_no;
+
+	char                is_in_int;
+	uchar               max_total_qng;
+
+	uchar               cur_total_qng;
+
+	uchar               in_critical_cnt;
+
+	uchar               irq_no;
+	uchar               last_q_shortage;
+
+	ushort              init_state;
+	uchar               cur_dvc_qng[ASC_MAX_TID + 1];
+	uchar               max_dvc_qng[ASC_MAX_TID + 1];
+
+	ASC_SCSI_Q dosfar  *scsiq_busy_head[ASC_MAX_TID + 1];
+	ASC_SCSI_Q dosfar  *scsiq_busy_tail[ASC_MAX_TID + 1];
+
+	ulong               int_count;
+	ulong               req_count;
+	ulong               busy_count;
+
+	ASC_DVC_CFG dosfar *cfg;
+	Ptr2Func            saved_ptr2func;
+	ulong               reserved2;
+	ulong               reserved3;
+	ulong               max_dma_count;
+	ASC_SCSI_BIT_ID_TYPE no_scam;
+	ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
+} ASC_DVC_VAR;
+
+typedef int         (dosfar * ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO dosfar *);
+typedef int         (dosfar * ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+
+typedef struct asc_dvc_inq_info {
+	uchar               type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
+} ASC_DVC_INQ_INFO;
+
+typedef struct asc_cap_info {
+	ulong               lba;
+	ulong               blk_size;
+} ASC_CAP_INFO;
+
+typedef struct asc_cap_info_array {
+	ASC_CAP_INFO        cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
+} ASC_CAP_INFO_ARRAY;
+
+#define ASC_IOADR_TABLE_MAX_IX  11
+#define ASC_IOADR_GAP   0x10
+#define ASC_SEARCH_IOP_GAP 0x10
+#define ASC_MIN_IOP_ADDR   ( PortAddr )0x0100
+#define ASC_MAX_IOP_ADDR   ( PortAddr )0x3F0
+
+#define ASC_IOADR_1     ( PortAddr )0x0110
+#define ASC_IOADR_2     ( PortAddr )0x0130
+#define ASC_IOADR_3     ( PortAddr )0x0150
+#define ASC_IOADR_4     ( PortAddr )0x0190
+#define ASC_IOADR_5     ( PortAddr )0x0210
+#define ASC_IOADR_6     ( PortAddr )0x0230
+#define ASC_IOADR_7     ( PortAddr )0x0250
+#define ASC_IOADR_8     ( PortAddr )0x0330
+#define ASC_IOADR_DEF   ASC_IOADR_8
+
+#define ASC_SYN_XFER_NO   8
+#define ASC_MAX_SDTR_PERIOD_INDEX  7
+#define ASC_SYN_MAX_OFFSET   0x0F
+#define ASC_DEF_SDTR_OFFSET  0x0F
+#define ASC_DEF_SDTR_INDEX   0x00
+
+#define SYN_XFER_NS_0  25
+#define SYN_XFER_NS_1  30
+#define SYN_XFER_NS_2  35
+#define SYN_XFER_NS_3  40
+#define SYN_XFER_NS_4  50
+#define SYN_XFER_NS_5  60
+#define SYN_XFER_NS_6  70
+#define SYN_XFER_NS_7  85
+
+#define ASC_SDTR_PERIOD_IX_MIN  7
+
+#define SYN_XMSG_WLEN  3
+
+typedef struct sdtr_xmsg {
+	uchar               msg_type;
+	uchar               msg_len;
+	uchar               msg_req;
+	uchar               xfer_period;
+	uchar               req_ack_offset;
+	uchar               res;
+} SDTR_XMSG;
+
+#define ASC_MCNTL_NO_SEL_TIMEOUT  ( ushort )0x0001
+#define ASC_MCNTL_NULL_TARGET     ( ushort )0x0002
+
+#define ASC_CNTL_INITIATOR         ( ushort )0x0001
+#define ASC_CNTL_BIOS_GT_1GB       ( ushort )0x0002
+#define ASC_CNTL_BIOS_GT_2_DISK    ( ushort )0x0004
+#define ASC_CNTL_BIOS_REMOVABLE    ( ushort )0x0008
+#define ASC_CNTL_NO_SCAM           ( ushort )0x0010
+#define ASC_CNTL_NO_PCI_FIX_ASYN_XFER ( ushort )0x0020
+
+#define ASC_CNTL_INT_MULTI_Q       ( ushort )0x0080
+
+#define ASC_CNTL_NO_LUN_SUPPORT    ( ushort )0x0040
+
+#define ASC_CNTL_NO_VERIFY_COPY    ( ushort )0x0100
+#define ASC_CNTL_RESET_SCSI        ( ushort )0x0200
+#define ASC_CNTL_INIT_INQUIRY      ( ushort )0x0400
+#define ASC_CNTL_INIT_VERBOSE      ( ushort )0x0800
+
+#define ASC_CNTL_SCSI_PARITY       ( ushort )0x1000
+#define ASC_CNTL_BURST_MODE        ( ushort )0x2000
+
+#define ASC_CNTL_USE_8_IOP_BASE    ( ushort )0x4000
+
+#define ASC_EEP_DVC_CFG_BEG_VL    2
+#define ASC_EEP_MAX_DVC_ADDR_VL   15
+
+#define ASC_EEP_DVC_CFG_BEG      32
+#define ASC_EEP_MAX_DVC_ADDR     45
+
+#define ASC_EEP_DEFINED_WORDS    10
+#define ASC_EEP_MAX_ADDR         63
+#define ASC_EEP_RES_WORDS         0
+#define ASC_EEP_MAX_RETRY        20
+#define ASC_MAX_INIT_BUSY_RETRY   8
+
+#define ASC_EEP_ISA_PNP_WSIZE    16
+
+typedef struct asceep_config {
+	ushort              cfg_lsw;
+	ushort              cfg_msw;
+
+	uchar               init_sdtr;
+	uchar               disc_enable;
+
+	uchar               use_cmd_qng;
+
+	uchar               start_motor;
+	uchar               max_total_qng;
+	uchar               max_tag_qng;
+	uchar               bios_scan;
+
+	uchar               power_up_wait;
+
+	uchar               no_scam;
+	uchar               chip_scsi_id:4;
+
+	uchar               isa_dma_speed:4;
+
+	uchar               sdtr_data[ASC_MAX_TID + 1];
+
+	uchar               adapter_info[6];
+
+	ushort              cntl;
+
+	ushort              chksum;
+} ASCEEP_CONFIG;
+
+#define ASC_EEP_CMD_READ          0x80
+#define ASC_EEP_CMD_WRITE         0x40
+#define ASC_EEP_CMD_WRITE_ABLE    0x30
+#define ASC_EEP_CMD_WRITE_DISABLE 0x00
+
+#define ASC_OVERRUN_BSIZE  0x00000048UL
+
+#define ASCV_MSGOUT_BEG         0x0000
+#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
+#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
+
+#define ASCV_MSGIN_BEG          (ASCV_MSGOUT_BEG+8)
+#define ASCV_MSGIN_SDTR_PERIOD  (ASCV_MSGIN_BEG+3)
+#define ASCV_MSGIN_SDTR_OFFSET  (ASCV_MSGIN_BEG+4)
+
+#define ASCV_SDTR_DATA_BEG      (ASCV_MSGIN_BEG+8)
+#define ASCV_SDTR_DONE_BEG      (ASCV_SDTR_DATA_BEG+8)
+#define ASCV_MAX_DVC_QNG_BEG    ( ushort )0x0020
+
+#define ASCV_ASCDVC_ERR_CODE_W  ( ushort )0x0030
+#define ASCV_MCODE_CHKSUM_W   ( ushort )0x0032
+#define ASCV_MCODE_SIZE_W     ( ushort )0x0034
+#define ASCV_STOP_CODE_B      ( ushort )0x0036
+#define ASCV_DVC_ERR_CODE_B   ( ushort )0x0037
+
+#define ASCV_OVERRUN_PADDR_D  ( ushort )0x0038
+#define ASCV_OVERRUN_BSIZE_D  ( ushort )0x003C
+
+#define ASCV_HALTCODE_W       ( ushort )0x0040
+#define ASCV_CHKSUM_W         ( ushort )0x0042
+#define ASCV_MC_DATE_W        ( ushort )0x0044
+#define ASCV_MC_VER_W         ( ushort )0x0046
+#define ASCV_NEXTRDY_B        ( ushort )0x0048
+#define ASCV_DONENEXT_B       ( ushort )0x0049
+#define ASCV_USE_TAGGED_QNG_B ( ushort )0x004A
+#define ASCV_SCSIBUSY_B       ( ushort )0x004B
+#define ASCV_CDBCNT_B         ( ushort )0x004C
+#define ASCV_CURCDB_B         ( ushort )0x004D
+#define ASCV_RCLUN_B          ( ushort )0x004E
+#define ASCV_BUSY_QHEAD_B     ( ushort )0x004F
+#define ASCV_DISC1_QHEAD_B    ( ushort )0x0050
+
+#define ASCV_DISC_ENABLE_B    ( ushort )0x0052
+#define ASCV_CAN_TAGGED_QNG_B ( ushort )0x0053
+#define ASCV_HOSTSCSI_ID_B    ( ushort )0x0055
+#define ASCV_MCODE_CNTL_B     ( ushort )0x0056
+#define ASCV_NULL_TARGET_B    ( ushort )0x0057
+
+#define ASCV_FREE_Q_HEAD_W    ( ushort )0x0058
+#define ASCV_DONE_Q_TAIL_W    ( ushort )0x005A
+#define ASCV_FREE_Q_HEAD_B    ( ushort )(ASCV_FREE_Q_HEAD_W+1)
+#define ASCV_DONE_Q_TAIL_B    ( ushort )(ASCV_DONE_Q_TAIL_W+1)
+
+#define ASCV_HOST_FLAG_B      ( ushort )0x005D
+
+#define ASCV_TOTAL_READY_Q_B  ( ushort )0x0064
+#define ASCV_VER_SERIAL_B     ( ushort )0x0065
+#define ASCV_HALTCODE_SAVED_W ( ushort )0x0066
+#define ASCV_WTM_FLAG_B       ( ushort )0x0068
+#define ASCV_RISC_FLAG_B      ( ushort )0x006A
+#define ASCV_REQ_SG_LIST_QP   ( ushort )0x006B
+
+#define ASC_HOST_FLAG_IN_ISR        0x01
+#define ASC_HOST_FLAG_ACK_INT       0x02
+
+#define ASC_RISC_FLAG_GEN_INT      0x01
+#define ASC_RISC_FLAG_REQ_SG_LIST  0x02
+
+#define IOP_CTRL         (0x0F)
+#define IOP_STATUS       (0x0E)
+#define IOP_INT_ACK      IOP_STATUS
+
+#define IOP_REG_IFC      (0x0D)
+
+#define IOP_SYN_OFFSET   (0x0B)
+#define IOP_REG_PC       (0x0C)
+#define IOP_RAM_ADDR     (0x0A)
+#define IOP_RAM_DATA     (0x08)
+#define IOP_EEP_DATA     (0x06)
+#define IOP_EEP_CMD      (0x07)
+
+#define IOP_VERSION      (0x03)
+#define IOP_CONFIG_HIGH  (0x04)
+#define IOP_CONFIG_LOW   (0x02)
+#define IOP_ASPI_ID_LOW  (0x01)
+#define IOP_ASPI_ID_HIGH (0x00)
+
+#define IOP_REG_DC1      (0x0E)
+#define IOP_REG_DC0      (0x0C)
+#define IOP_REG_SB       (0x0B)
+#define IOP_REG_DA1      (0x0A)
+#define IOP_REG_DA0      (0x08)
+#define IOP_REG_SC       (0x09)
+#define IOP_DMA_SPEED    (0x07)
+#define IOP_REG_FLAG     (0x07)
+#define IOP_FIFO_H       (0x06)
+#define IOP_FIFO_L       (0x04)
+#define IOP_REG_ID       (0x05)
+#define IOP_REG_QP       (0x03)
+#define IOP_REG_IH       (0x02)
+#define IOP_REG_IX       (0x01)
+#define IOP_REG_AX       (0x00)
+
+#define IFC_REG_LOCK      (0x00)
+#define IFC_REG_UNLOCK    (0x09)
+
+#define IFC_WR_EN_FILTER  (0x10)
+#define IFC_RD_NO_EEPROM  (0x10)
+#define IFC_SLEW_RATE     (0x20)
+#define IFC_ACT_NEG       (0x40)
+#define IFC_INP_FILTER    (0x80)
+
+#define IFC_INIT_DEFAULT  ( IFC_ACT_NEG | IFC_REG_UNLOCK )
+
+#define SC_SEL   (0x80)
+#define SC_BSY   (0x40)
+#define SC_ACK   (0x20)
+#define SC_REQ   (0x10)
+#define SC_ATN   (0x08)
+#define SC_IO    (0x04)
+#define SC_CD    (0x02)
+#define SC_MSG   (0x01)
+
+#define AscGetVarFreeQHead( port )       AscReadLramWord( port, ASCV_FREE_Q_HEAD_W )
+#define AscGetVarDoneQTail( port )       AscReadLramWord( port, ASCV_DONE_Q_TAIL_W )
+#define AscPutVarFreeQHead( port, val )  AscWriteLramWord( port, ASCV_FREE_Q_HEAD_W, val )
+#define AscPutVarDoneQTail( port, val )  AscWriteLramWord( port, ASCV_DONE_Q_TAIL_W, val )
+
+#define AscGetRiscVarFreeQHead( port )        AscReadLramByte( port, ASCV_NEXTRDY_B )
+#define AscGetRiscVarDoneQTail( port )        AscReadLramByte( port, ASCV_DONENEXT_B )
+#define AscPutRiscVarFreeQHead( port, val )   AscWriteLramByte( port, ASCV_NEXTRDY_B, val )
+#define AscPutRiscVarDoneQTail( port, val )   AscWriteLramByte( port, ASCV_DONENEXT_B, val )
+
+#define AscGetChipIFC( port )               inp( (port)+IOP_REG_IFC )
+#define AscPutChipIFC( port, data )         outp( (port)+IOP_REG_IFC, data )
+
+#define AscGetChipLramAddr( port )          ( ushort )inpw( ( PortAddr )((port)+IOP_RAM_ADDR) )
+#define AscSetChipLramAddr( port, addr )    outpw( ( PortAddr )( (port)+IOP_RAM_ADDR ), addr )
+#define AscPutChipLramData( port, data )    outpw( (port)+IOP_RAM_DATA, data )
+#define AscGetChipLramData( port )          inpw( (port)+IOP_RAM_DATA )
+
+#define AscWriteChipSyn( port, data )       outp( (port)+IOP_SYN_OFFSET, data )
+#define AscReadChipSyn( port )              inp( (port)+IOP_SYN_OFFSET )
+
+#define AscWriteChipIH( port, data )        outpw( (port)+IOP_REG_IH, data )
+#define AscReadChipIH( port )               inpw( (port)+IOP_REG_IH )
+
+#define AscWriteChipScsiID( port, data )    outp( (port)+IOP_REG_ID, data )
+#define AscReadChipScsiID( port )           inp( (port)+IOP_REG_ID )
+
+#define AscGetChipDmaSpeed( port )         ( uchar )inp( (port)+IOP_DMA_SPEED )
+#define AscSetChipDmaSpeed( port, data )   outp( (port)+IOP_DMA_SPEED, data )
+#define AscGetChipQP( port )               ( uchar )inp( (port)+IOP_REG_QP )
+#define AscSetPCAddr( port, data )         outpw( (port)+IOP_REG_PC, data )
+#define AscGetPCAddr( port )               inpw( (port)+IOP_REG_PC )
+#define AscGetChipVerNo( port )            ( uchar )inp( (port)+IOP_VERSION )
+
+#define AscGetChipEEPCmd( port )           ( uchar )inp( (port)+IOP_EEP_CMD )
+#define AscSetChipEEPCmd( port, data )     outp( (port)+IOP_EEP_CMD, data )
+#define AscGetChipEEPData( port )          inpw( (port)+IOP_EEP_DATA )
+#define AscSetChipEEPData( port, data )    outpw( (port)+IOP_EEP_DATA, data )
+
+#define AscGetChipControl( port )          ( uchar )inp( (port)+IOP_CTRL )
+#define AscSetChipControl( port, cc_val )  outp( (port)+IOP_CTRL, cc_val )
+
+#define AscGetChipStatus( port )           ( ASC_CS_TYPE )inpw( (port)+IOP_STATUS )
+#define AscSetChipStatus( port, cs_val )   outpw( (port)+IOP_STATUS, cs_val )
+
+#define AscGetChipCfgLsw( port )           ( ushort )inpw( (port)+IOP_CONFIG_LOW )
+#define AscGetChipCfgMsw( port )           ( ushort )inpw( (port)+IOP_CONFIG_HIGH )
+#define AscSetChipCfgLsw( port, data )     outpw( (port)+IOP_CONFIG_LOW, data )
+#define AscSetChipCfgMsw( port, data )     outpw( (port)+IOP_CONFIG_HIGH, data )
+
+#define AscIsIntPending( port )           ( AscGetChipStatus( port ) & CSW_INT_PENDING )
+#define AscGetChipScsiID( port )          ( ( AscGetChipCfgLsw( port ) >> 8 ) & ASC_MAX_TID )
+
+#define ASC_HALT_EXTMSG_IN     ( ushort )0x8000
+#define ASC_HALT_CHK_CONDITION ( ushort )0x8100
+#define ASC_HALT_SS_QUEUE_FULL ( ushort )0x8200
+#define ASC_HALT_SDTR_REJECTED ( ushort )0x4000
+
+#define ASC_MAX_QNO        0xF8
+#define ASC_DATA_SEC_BEG   ( ushort )0x0080
+#define ASC_DATA_SEC_END   ( ushort )0x0080
+#define ASC_CODE_SEC_BEG   ( ushort )0x0080
+#define ASC_CODE_SEC_END   ( ushort )0x0080
+#define ASC_QADR_BEG       (0x4000)
+#define ASC_QADR_USED      ( ushort )( ASC_MAX_QNO * 64 )
+#define ASC_QADR_END       ( ushort )0x7FFF
+#define ASC_QLAST_ADR      ( ushort )0x7FC0
+#define ASC_QBLK_SIZE      0x40
+#define ASC_BIOS_DATA_QBEG 0xF8
+
+#define ASC_MIN_ACTIVE_QNO 0x01
+
+#define ASC_QLINK_END      0xFF
+#define ASC_EEPROM_WORDS   0x10
+#define ASC_MAX_MGS_LEN    0x10
+
+#define ASC_BIOS_ADDR_DEF  0xDC00
+#define ASC_BIOS_SIZE      0x3800
+#define ASC_BIOS_RAM_OFF   0x3800
+#define ASC_BIOS_RAM_SIZE  0x800
+#define ASC_BIOS_MIN_ADDR  0xC000
+#define ASC_BIOS_MAX_ADDR  0xEC00
+#define ASC_BIOS_BANK_SIZE 0x0400
+
+#define ASC_MCODE_START_ADDR  0x0080
+
+#define ASC_CFG0_HOST_INT_ON    0x0020
+#define ASC_CFG0_BIOS_ON        0x0040
+#define ASC_CFG0_VERA_BURST_ON  0x0080
+#define ASC_CFG0_SCSI_PARITY_ON 0x0800
+
+#define ASC_CFG1_SCSI_TARGET_ON 0x0080
+#define ASC_CFG1_LRAM_8BITS_ON  0x0800
+
+#define ASC_CFG_MSW_CLR_MASK    0xF0C0
+
+#define CSW_TEST1             ( ASC_CS_TYPE )0x8000
+#define CSW_AUTO_CONFIG       ( ASC_CS_TYPE )0x4000
+#define CSW_RESERVED1         ( ASC_CS_TYPE )0x2000
+#define CSW_IRQ_WRITTEN       ( ASC_CS_TYPE )0x1000
+#define CSW_33MHZ_SELECTED    ( ASC_CS_TYPE )0x0800
+#define CSW_TEST2             ( ASC_CS_TYPE )0x0400
+#define CSW_TEST3             ( ASC_CS_TYPE )0x0200
+#define CSW_RESERVED2         ( ASC_CS_TYPE )0x0100
+#define CSW_DMA_DONE          ( ASC_CS_TYPE )0x0080
+#define CSW_FIFO_RDY          ( ASC_CS_TYPE )0x0040
+
+#define CSW_EEP_READ_DONE     ( ASC_CS_TYPE )0x0020
+
+#define CSW_HALTED            ( ASC_CS_TYPE )0x0010
+#define CSW_SCSI_RESET_ACTIVE ( ASC_CS_TYPE )0x0008
+
+#define CSW_PARITY_ERR        ( ASC_CS_TYPE )0x0004
+#define CSW_SCSI_RESET_LATCH  ( ASC_CS_TYPE )0x0002
+
+#define CSW_INT_PENDING       ( ASC_CS_TYPE )0x0001
+
+#define CIW_INT_ACK      ( ASC_CS_TYPE )0x0100
+#define CIW_TEST1        ( ASC_CS_TYPE )0x0200
+#define CIW_TEST2        ( ASC_CS_TYPE )0x0400
+#define CIW_SEL_33MHZ    ( ASC_CS_TYPE )0x0800
+
+#define CIW_IRQ_ACT      ( ASC_CS_TYPE )0x1000
+
+#define CC_CHIP_RESET   ( uchar )0x80
+#define CC_SCSI_RESET   ( uchar )0x40
+#define CC_HALT         ( uchar )0x20
+#define CC_SINGLE_STEP  ( uchar )0x10
+#define CC_DMA_ABLE     ( uchar )0x08
+#define CC_TEST         ( uchar )0x04
+#define CC_BANK_ONE     ( uchar )0x02
+#define CC_DIAG         ( uchar )0x01
+
+#define ASC_1000_ID0W      0x04C1
+#define ASC_1000_ID0W_FIX  0x00C1
+#define ASC_1000_ID1B      0x25
+
+#define ASC_EISA_BIG_IOP_GAP   (0x1C30-0x0C50)
+#define ASC_EISA_SMALL_IOP_GAP (0x0020)
+#define ASC_EISA_MIN_IOP_ADDR  (0x0C30)
+#define ASC_EISA_MAX_IOP_ADDR  (0xFC50)
+#define ASC_EISA_REV_IOP_MASK  (0x0C83)
+#define ASC_EISA_PID_IOP_MASK  (0x0C80)
+#define ASC_EISA_CFG_IOP_MASK  (0x0C86)
+
+#define ASC_GET_EISA_SLOT( iop )  ( PortAddr )( (iop) & 0xF000 )
+
+#define ASC_EISA_ID_740    0x01745004UL
+#define ASC_EISA_ID_750    0x01755004UL
+
+#define INS_HALTINT        ( ushort )0x6281
+#define INS_HALT           ( ushort )0x6280
+#define INS_SINT           ( ushort )0x6200
+#define INS_RFLAG_WTM      ( ushort )0x7380
+
+#define ASC_MC_SAVE_CODE_WSIZE  0x500
+#define ASC_MC_SAVE_DATA_WSIZE  0x40
+
+typedef struct asc_mc_saved {
+	ushort              data[ASC_MC_SAVE_DATA_WSIZE];
+	ushort              code[ASC_MC_SAVE_CODE_WSIZE];
+} ASC_MC_SAVED;
+
+int                 AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
+int                 AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
+void                AscWaitEEPRead(void);
+void                AscWaitEEPWrite(void);
+ushort              AscReadEEPWord(PortAddr, uchar);
+ushort              AscWriteEEPWord(PortAddr, uchar, ushort);
+ushort              AscGetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
+int                 AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
+int                 AscSetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
+ushort              AscEEPSum(PortAddr, uchar, uchar);
+
+int                 AscStartChip(PortAddr);
+int                 AscStopChip(PortAddr);
+void                AscSetChipIH(PortAddr, ushort);
+int                 AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
+
+int                 AscIsChipHalted(PortAddr);
+
+void                AscSetChipCfgDword(PortAddr, ulong);
+ulong               AscGetChipCfgDword(PortAddr);
+
+void                AscAckInterrupt(PortAddr);
+void                AscDisableInterrupt(PortAddr);
+void                AscEnableInterrupt(PortAddr);
+void                AscSetBank(PortAddr, uchar);
+uchar               AscGetBank(PortAddr);
+int                 AscResetChipAndScsiBus(PortAddr);
+ushort              AscGetIsaDmaChannel(PortAddr);
+ushort              AscSetIsaDmaChannel(PortAddr, ushort);
+uchar               AscSetIsaDmaSpeed(PortAddr, uchar);
+uchar               AscGetIsaDmaSpeed(PortAddr);
+
+uchar               AscReadLramByte(PortAddr, ushort);
+ushort              AscReadLramWord(PortAddr, ushort);
+ulong               AscReadLramDWord(PortAddr, ushort);
+void                AscWriteLramWord(PortAddr, ushort, ushort);
+void                AscWriteLramDWord(PortAddr, ushort, ulong);
+void                AscWriteLramByte(PortAddr, ushort, uchar);
+int                 AscVerWriteLramDWord(PortAddr, ushort, ulong);
+int                 AscVerWriteLramWord(PortAddr, ushort, ushort);
+int                 AscVerWriteLramByte(PortAddr, ushort, uchar);
+
+ulong               AscMemSumLramWord(PortAddr, ushort, int);
+void                AscMemWordSetLram(PortAddr, ushort, ushort, int);
+void                AscMemWordCopyToLram(PortAddr, ushort, ushort dosfar *, int);
+void                AscMemDWordCopyToLram(PortAddr, ushort, ulong dosfar *, int);
+void                AscMemWordCopyFromLram(PortAddr, ushort, ushort dosfar *, int);
+int                 AscMemWordCmpToLram(PortAddr, ushort, ushort dosfar *, int);
+
+ushort              AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
+ulong               AscLoadMicroCode(PortAddr, ushort,
+									 ushort dosfar *, ushort);
+ushort              AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
+
+void dosfar         AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *,
+										   ASC_QDONE_INFO dosfar *);
+int                 AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscTestLramEndian(PortAddr);
+
+uchar               AscMsgOutSDTR(PortAddr, uchar, uchar);
+
+uchar               AscCalSDTRData(uchar, uchar);
+void                AscSetChipSDTR(PortAddr, uchar, uchar);
+int                 AscInitChipAllSynReg(ASC_DVC_VAR asc_ptr_type *, uchar);
+uchar               AscGetSynPeriodIndex(uchar);
+uchar               AscSynIndexToPeriod(uchar);
+uchar               AscAllocFreeQueue(PortAddr, uchar);
+uchar               AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
+int                 AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
+int                 AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscRiscHaltedAbortALL(ASC_DVC_VAR asc_ptr_type *);
+int                 AscHostReqRiscHalt(PortAddr);
+int                 AscStopQueueExe(PortAddr);
+int                 AscStartQueueExe(PortAddr);
+int                 AscCleanUpDiscQueue(PortAddr);
+int                 AscCleanUpBusyQueue(PortAddr);
+int                 _AscAbortTidBusyQueue(ASC_DVC_VAR asc_ptr_type *,
+										  ASC_QDONE_INFO dosfar *, uchar);
+int                 _AscAbortSrbBusyQueue(ASC_DVC_VAR asc_ptr_type *,
+										  ASC_QDONE_INFO dosfar *, ulong);
+int                 AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
+ulong               AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong);
+
+int                 AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
+									 ASC_SCSI_Q dosfar * scsiq,
+									 uchar n_q_required);
+int                 AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *, uchar);
+int                 AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
+										   ASC_SCSI_Q dosfar *, uchar);
+int                 AscAbortScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+void                AscExeScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+int                 AscSetChipSynRegAtID(PortAddr, uchar, uchar);
+int                 AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
+ushort              AscInitLram(ASC_DVC_VAR asc_ptr_type *);
+int                 AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
+int                 AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
+int                 _AscWaitQDone(PortAddr, ASC_SCSI_Q dosfar *);
+
+int                 AscEnterCritical(void);
+void                AscLeaveCritical(int);
+
+int                 AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
+uchar               _AscCopyLramScsiDoneQ(PortAddr, ushort,
+										  ASC_QDONE_INFO dosfar *, ulong);
+int                 AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscIsrExeBusyQueue(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
+									 uchar dosfar *, ulong);
+
+int                 AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
+								   uchar dosfar *, int);
+int                 AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *);
+int                 AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *,
+										 ASC_SCSI_REQ_Q dosfar *, uchar);
+int                 AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
+										ASC_SCSI_REQ_Q dosfar *,
+										uchar dosfar *);
+
+ulong dosfar       *swapfarbuf4(uchar dosfar *);
+int                 PollQueueDone(ASC_DVC_VAR asc_ptr_type *,
+								  ASC_SCSI_REQ_Q dosfar *,
+								  int);
+int                 PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
+										 ASC_SCSI_REQ_Q dosfar *,
+										 ASC_CAP_INFO dosfar *);
+int                 PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
+									uchar dosfar *, int);
+int                 PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
+										  ASC_SCSI_REQ_Q dosfar *);
+int                 PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *,
+									  ASC_SCSI_REQ_Q dosfar *);
+int                 InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
+									  ASC_SCSI_REQ_Q dosfar *);
+void                AscDispInquiry(uchar, uchar, ASC_SCSI_INQUIRY dosfar *);
+int                 AscPollQDone(ASC_DVC_VAR asc_ptr_type *,
+								 ASC_SCSI_REQ_Q dosfar *, int);
+
+int                 AscSetBIOSBank(PortAddr, int, ushort);
+int                 AscSetVlBIOSBank(PortAddr, int);
+int                 AscSetEisaBIOSBank(PortAddr, int);
+int                 AscSetIsaBIOSBank(PortAddr, int);
+
+int                 AscIsBiosEnabled(PortAddr, ushort);
+void                AscResetScsiBus(PortAddr);
+void                AscClrResetScsiBus(PortAddr);
+
+void                AscSingleStepChip(PortAddr);
+uchar               AscSetChipScsiID(PortAddr, uchar);
+ushort              AscGetChipBiosAddress(PortAddr, ushort);
+ushort              AscSetChipBiosAddress(PortAddr, ushort, ushort);
+uchar               AscGetChipVersion(PortAddr, ushort);
+ushort              AscGetChipBusType(PortAddr);
+
+PortAddr            AscSearchIOPortAddr11(PortAddr);
+PortAddr            AscSearchIOPortAddr100(PortAddr);
+int                 AscFindSignature(PortAddr);
+void                AscToggleIRQAct(PortAddr);
+int                 AscResetChip(PortAddr);
+void                AscClrResetChip(PortAddr);
+
+short               itos(ushort, uchar dosfar *, short, short);
+int                 insnchar(uchar dosfar *, short, short, ruchar, short);
+void                itoh(ushort, ruchar dosfar *);
+void                btoh(uchar, ruchar dosfar *);
+void                ltoh(ulong, ruchar dosfar *);
+uchar dosfar       *todstr(ushort, uchar dosfar *);
+uchar dosfar       *tohstr(ushort, uchar dosfar *);
+uchar dosfar       *tobhstr(uchar, uchar dosfar *);
+uchar dosfar       *tolhstr(ulong, uchar dosfar *);
+
+void                AscSetISAPNPWaitForKey(void);
+uchar               AscGetChipIRQ(PortAddr, ushort);
+uchar               AscSetChipIRQ(PortAddr, uchar, ushort);
+uchar               AscGetChipScsiCtrl(PortAddr);
+
+ushort              AscGetEisaChipCfg(PortAddr);
+ushort              AscGetEisaChipGpReg(PortAddr);
+ushort              AscSetEisaChipCfg(PortAddr, ushort);
+ushort              AscSetEisaChipGpReg(PortAddr, ushort);
+
+ulong               AscGetEisaProductID(PortAddr);
+PortAddr            AscSearchIOPortAddrEISA(PortAddr);
+
+int                 AscPollQTailSync(PortAddr);
+int                 AscPollQHeadSync(PortAddr);
+int                 AscWaitQTailSync(PortAddr);
+
+int                 _AscRestoreMicroCode(PortAddr, ASC_MC_SAVED dosfar *);
+
+int                 AscSCAM(ASC_DVC_VAR asc_ptr_type *);
+
+ushort              SwapByteOfWord(ushort word_val);
+ulong               SwapWordOfDWord(ulong dword_val);
+ulong               AdjEndianDword(ulong dword_val);
+
+int                 AscAdjEndianScsiQ(ASC_SCSI_Q dosfar *);
+int                 AscAdjEndianQDoneInfo(ASC_QDONE_INFO dosfar *);
+
+extern int          DvcEnterCritical(void);
+extern void         DvcLeaveCritical(int);
+
+extern void         DvcInPortWords(PortAddr, ushort dosfar *, int);
+extern void         DvcOutPortWords(PortAddr, ushort dosfar *, int);
+extern void         DvcOutPortDWords(PortAddr, ulong dosfar *, int);
+
+extern void         DvcSleepMilliSecond(ulong);
+extern void         DvcDisplayString(uchar dosfar *);
+extern ulong        DvcGetPhyAddr(uchar dosfar * buf_addr, ulong buf_len);
+extern ulong        DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong,
+								 ASC_SG_HEAD dosfar *);
+
+extern void         DvcSCAMDelayMS(ulong);
+extern int          DvcDisableCPUInterrupt(void);
+extern void         DvcRestoreCPUInterrupt(int);
+
+void                DvcPutScsiQ(PortAddr, ushort, ushort dosfar *, int);
+void                DvcGetQinfo(PortAddr, ushort, ushort dosfar *, int);
+
+PortAddr            AscSearchIOPortAddr(PortAddr, ushort);
+ushort              AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
+int                 AscInitScsiTarget(ASC_DVC_VAR asc_ptr_type *,
+									  ASC_DVC_INQ_INFO dosfar *,
+									  uchar dosfar *,
+									  ASC_CAP_INFO_ARRAY dosfar *,
+									  ushort);
+int                 AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *);
+int                 AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *);
+int                 AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *,
+									  ASC_SCSI_REQ_Q dosfar *,
+									  ASC_SCSI_INQUIRY dosfar *,
+									  ASC_CAP_INFO dosfar *);
+int                 AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+
+int                 AscISR(ASC_DVC_VAR asc_ptr_type *);
+void                AscISR_AckInterrupt(ASC_DVC_VAR asc_ptr_type *);
+int                 AscISR_CheckQDone(ASC_DVC_VAR asc_ptr_type *,
+									  ASC_QDONE_INFO dosfar *,
+									  uchar dosfar *);
+
+int                 AscStartUnit(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_TIX_TYPE);
+int                 AscStopUnit(
+								   ASC_DVC_VAR asc_ptr_type * asc_dvc,
+								   ASC_SCSI_TIX_TYPE target_ix
+);
+
+uint                AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
+int                 AscSgListToQueue(int);
+int                 AscQueueToSgList(int);
+int                 AscSetDvcErrorCode(ASC_DVC_VAR asc_ptr_type *, uchar);
+
+int                 AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
+int                 AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscResetSB(ASC_DVC_VAR asc_ptr_type *);
+
+void                AscEnableIsaDma(uchar);
+void                AscDisableIsaDma(uchar);
+
+ulong               AscGetMaxDmaAddress(ushort);
+ulong               AscGetMaxDmaCount(ushort);
+
+int                 AscSaveMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
+int                 AscRestoreOldMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
+int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
+
+/*
+ * --- Debugging Header
+ */
+
+#ifdef ADVANSYS_DEBUG
+#define STATIC
+#else /* ADVANSYS_DEBUG */
+#define STATIC static
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Driver Constants and Macros
+ */
+
+#define ASC_NUM_BOARD_SUPPORTED 4
+#define ASC_NUM_BUS				4
+
+/* Reference Scsi_Host hostdata */
+#define ASC_BOARD(host) ((struct asc_board *) &(host)->hostdata)
+
+#define NO_ISA_DMA	0xff		/* No ISA DMA Channel Used */
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* min */
+
+/* Asc Library return codes */
+#define ASC_TRUE		1
+#define ASC_FALSE		0
+#define ASC_NOERROR		1
+#define ASC_BUSY		0
+#define ASC_ERROR		(-1)
+
+/* Scsi_Cmnd function return codes */
+#define STATUS_BYTE(byte)	(byte)
+#define MSG_BYTE(byte)		((byte) << 8)
+#define HOST_BYTE(byte)		((byte) << 16)
+#define DRIVER_BYTE(byte)	((byte) << 24)
+
+/* asc_enqueue() flags */
+#define ASC_FRONT		1
+#define ASC_BACK		2
+
+/* PCI configuration declarations */
+
+#define ASC_PCI_REV_A_INIT		0x01
+#define ASC_PCI_REV_A_DONE		0x02
+#define ASC_PCI_REV_B_INIT		0x04
+#define ASC_PCI_REV_B_DONE		0x08
+
+#define PCI_BASE_CLASS_PREDEFINED			0x00
+#define PCI_BASE_CLASS_MASS_STORAGE			0x01
+#define PCI_BASE_CLASS_NETWORK				0x02
+#define PCI_BASE_CLASS_DISPLAY				0x03
+#define PCI_BASE_CLASS_MULTIMEDIA			0x04
+#define PCI_BASE_CLASS_MEMORY_CONTROLLER	0x05
+#define PCI_BASE_CLASS_BRIDGE_DEVICE		0x06
+
+/* MASS STORAGE */
+#define PCI_SUB_CLASS_SCSI_CONTROLLER			0x00
+#define PCI_SUB_CLASS_IDE_CONTROLLER			0x01
+#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER	0x02
+#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER		0x03
+#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER		0x80
+
+/* NETWORK CONTROLLER */
+#define PCI_SUB_CLASS_ETHERNET_CONTROLLER		0x00
+#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER		0x01
+#define PCI_SUB_CLASS_FDDI_CONTROLLER			0x02
+#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER	0x80
+
+/* DISPLAY CONTROLLER */
+#define PCI_SUB_CLASS_VGA_CONTROLLER			0x00
+#define PCI_SUB_CLASS_XGA_CONTROLLER			0x01
+#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER	0x80
+
+/* MULTIMEDIA CONTROLLER */
+#define PCI_SUB_CLASS_VIDEO_DEVICE				0x00
+#define PCI_SUB_CLASS_AUDIO_DEVICE				0x01
+#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE	0x80
+
+/* MEMORY CONTROLLER */
+#define PCI_SUB_CLASS_RAM_CONTROLLER			0x00
+#define PCI_SUB_CLASS_FLASH_CONTROLLER			0x01
+#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER	0x80
+
+/* BRIDGE CONTROLLER */
+#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER		0x00
+#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER			0x01
+#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER		0x02
+#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER			0x03
+#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER	0x04
+#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER		0x05
+#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER		0x80
+
+#define PCI_MAX_SLOT			0x1F
+#define PCI_MAX_BUS				0xFF
+#define ASC_PCI_VENDORID		0x10CD
+#define PCI_IOADDRESS_MASK		0xFFFE
+
+/* PCI IO Port Addresses to generate special cycle */
+
+#define PCI_CONFIG_ADDRESS_MECH1		0x0CF8
+#define PCI_CONFIG_DATA_MECH1			0x0CFC
+
+#define PCI_CONFIG_FORWARD_REGISTER		0x0CFA	/* 0=type 0; 1=type 1; */
+
+#define PCI_CONFIG_BUS_NUMBER_MASK		0x00FF0000
+#define PCI_CONFIG_DEVICE_FUNCTION_MASK	0x0000FF00
+#define PCI_CONFIG_REGISTER_NUMBER_MASK	0x000000F8
+
+#define PCI_DEVICE_FOUND				0x0000
+#define PCI_DEVICE_NOT_FOUND			0xffff
+
+#define SUBCLASS_OFFSET 	0x0A
+#define CLASSCODE_OFFSET	0x0B
+#define VENDORID_OFFSET		0x00
+#define DEVICEID_OFFSET		0x02
+
+/*
+ * --- Driver Macros
+ */
+
+#ifndef ADVANSYS_STATS
+#define ASC_STATS(counter)
+#define ASC_STATS_ADD(counter, count)
+#else /* ADVANSYS_STATS */
+#define ASC_STATS(counter)				asc_stats.counter++
+#define ASC_STATS_ADD(counter, count)	asc_stats.counter += (count)
+#endif /* ADVANSYS_STATS */
+
+#ifndef ADVANSYS_DEBUG
+
+#define	ASC_DBG(lvl, s)
+#define	ASC_DBG1(lvl, s, a1)
+#define	ASC_DBG2(lvl, s, a1, a2)
+#define	ASC_DBG3(lvl, s, a1, a2, a3)
+#define	ASC_DBG4(lvl, s, a1, a2, a3, a4)
+#define	ASC_DBG_PRT_SCSI_HOST(lvl, s)
+#define	ASC_DBG_PRT_DVC_VAR(lvl, v)
+#define	ASC_DBG_PRT_DVC_CFG(lvl, c)
+#define	ASC_DBG_PRT_SCSI_Q(lvl, scsiqp)
+#define	ASC_DBG_PRT_QDONE_INFO(lvl, qdone)
+#define	ASC_DBG_PRT_HEX(lvl, name, start, length)
+#define	ASC_DBG_PRT_CDB(lvl, cdb, len)
+#define	ASC_DBG_PRT_SENSE(lvl, sense, len)
+#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
+#define ASC_ASSERT(a)
+
+#else /* ADVANSYS_DEBUG */
+
+/*
+ * Debugging Message Levels:
+ * 0: Errors Only
+ * 1: High-Level Tracing
+ * 2-N: Verbose Tracing
+ */
+
+#define	ASC_DBG(lvl, s) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			printk(s); \
+		} \
+	}
+
+#define	ASC_DBG1(lvl, s, a1) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			printk((s), (a1)); \
+		} \
+	}
+
+#define	ASC_DBG2(lvl, s, a1, a2) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			printk((s), (a1), (a2)); \
+		} \
+	}
+
+#define	ASC_DBG3(lvl, s, a1, a2, a3) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			printk((s), (a1), (a2), (a3)); \
+		} \
+	}
+
+#define	ASC_DBG4(lvl, s, a1, a2, a3, a4) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			printk((s), (a1), (a2), (a3), (a4)); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_SCSI_HOST(lvl, s) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			asc_prt_scsi_host(s); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_DVC_VAR(lvl, v) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			asc_prt_dvc_var(v); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_DVC_CFG(lvl, c) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			asc_prt_dvc_cfg(c); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			asc_prt_scsi_q(scsiqp); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			asc_prt_qdone_info(qdone); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_HEX(lvl, name, start, length) \
+	{ \
+		if (asc_dbglvl >= (lvl)) { \
+			asc_prt_hex((name), (start), (length)); \
+		} \
+	}
+
+#define	ASC_DBG_PRT_CDB(lvl, cdb, len) \
+		ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
+
+#define	ASC_DBG_PRT_SENSE(lvl, sense, len) \
+		ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
+
+#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
+		ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
+
+#define ASC_ASSERT(a) \
+	{ \
+		if (!(a)) { \
+			printk("ASC_ASSERT() Failure: file %s, line %d\n", \
+				__FILE__, __LINE__); \
+		} \
+	}
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Driver Structures
+ */
+
+/*
+ * Structure allocated for each board.
+ *
+ * This structure is allocated by scsi_register() at the end
+ * of the 'Scsi_Host' structure starting at the 'hostdata'
+ * field. It is guaranteed to be allocated from DMA-able memory.
+ */
+struct asc_board {
+	/* Asc Library */
+	ASC_DVC_VAR			 board;					/* Board configuration */
+	ASC_DVC_CFG			 cfg;					/* Device configuration */
+	uchar				 overrun_buf[ASC_OVERRUN_BSIZE];
+	/* Queued Commands */
+	ASC_SCSI_BIT_ID_TYPE pending_tidmask;		/* Pending command mask */
+	Scsi_Cmnd			 *pending[ASC_MAX_TID];
+	/* Target Initialization */
+	ASC_SCSI_BIT_ID_TYPE init_tidmask;			/* Target initialized mask */
+	ASC_SCSI_REQ_Q		 scsireqq;
+	ASC_CAP_INFO		 cap_info;
+	ASC_SCSI_INQUIRY	 inquiry;
+};
+
+/*
+ * PCI configuration structures
+ */
+typedef struct _PCI_DATA_
+{
+	uchar	type;
+	uchar	bus;
+	uchar	slot;
+	uchar	func;
+	uchar	offset;
+} PCI_DATA;
+
+typedef struct _PCI_DEVICE_
+{
+	ushort	vendorID;
+	ushort	deviceID;
+	ushort	slotNumber;
+	ushort	slotFound;
+	uchar	busNumber;
+	uchar	maxBusNumber;
+	uchar	devFunc;
+	ushort	startSlot;
+	ushort	endSlot;
+	uchar	bridge;
+	uchar	type;
+} PCI_DEVICE;
+
+typedef struct _PCI_CONFIG_SPACE_
+{
+	ushort	vendorID;
+	ushort	deviceID;
+	ushort	command;
+	ushort	status;
+	uchar	revision;
+	uchar	classCode[3];
+	uchar	cacheSize;
+	uchar	latencyTimer;
+	uchar	headerType;
+	uchar	bist;
+	ulong	baseAddress[6];
+	ushort	reserved[4];
+	ulong	optionRomAddr;
+	ushort	reserved2[4];
+	uchar	irqLine;
+	uchar	irqPin;
+	uchar	minGnt;
+	uchar	maxLatency;
+} PCI_CONFIG_SPACE;
+
+#ifdef ADVANSYS_STATS
+struct asc_stats {
+	ulong 	command;		/* # calls to advansys_command() */
+	ulong 	queuecommand;	/* # calls to advansys_queuecommand() */
+	ulong 	abort;			/* # calls to advansys_abort() */
+	ulong 	reset;			/* # calls to advansys_reset() */
+	ulong 	biosparam;		/* # calls to advansys_biosparam() */
+	ulong 	interrupt;		/* # calls to advansys_interrupt() */
+	ulong 	callback;		/* # calls asc_isr_callback() */
+	ulong 	cont_cnt;		/* # non-scatter-gather I/O requests received */
+	ulong 	cont_xfer;		/* contiguous transfer total (512 byte units) */
+	ulong 	sg_cnt;			/* # scatter-gather I/O requests received */
+	ulong 	sg_elem;		/* scatter-gather element total */
+	ulong 	sg_xfer;		/* scatter-gather tranfer total (512 byte units) */
+	ulong 	error;			/* # AscExeScsiQueue() ASC_ERROR returns. */
+	/*
+	 * Number of times interrupts disabled in advansys_queuecommand() and
+	 * asc_isr_callback(), respectively. For the former indicates how many
+	 * times commands were pending when a new command was received.
+	 */
+	ulong 	cmd_disable;
+	ulong 	intr_disable;
+	/*
+	 * Number of times asc_enqueue() called. Indicates how many ASC_BUSY
+	 * returns have occurred.
+	 */
+	ulong 	enqueue;
+	ulong 	dequeue;		/* # calls to asc_dequeue(). */
+	/*
+	 * Number of times asc_rmqueue() called and the specified command
+	 * was found and removed.
+	 */
+	ulong 	rmqueue;
+} asc_stats;
+#endif /* ADVANSYS_STATS */
+
+
+/*
+ * --- Driver Data
+ */
+
+#ifdef LINUX_1_3
+struct proc_dir_entry proc_scsi_advansys =
+{
+	PROC_SCSI_ADVANSYS,				/* unsigned short low_ino */
+	8,								/* unsigned short namelen */
+	"advansys",						/* const char *name */
+	S_IFDIR | S_IRUGO | S_IXUGO,	/* mode_t mode */
+	2								/* nlink_t nlink */
+};
+#endif /* LINUX_1_3 */
+
+STATIC int asc_board_count; /* Number of boards detected in system. */
+STATIC struct Scsi_Host	*asc_host[ASC_NUM_BOARD_SUPPORTED];
+STATIC Scsi_Cmnd *asc_scsi_done; /* Commands needing done function call. */
+
+STATIC ushort asc_bus[ASC_NUM_BUS] = {
+	ASC_IS_ISA,
+	ASC_IS_VL,
+	ASC_IS_EISA,
+	ASC_IS_PCI,
+};
+
+/*
+ * Used with the LILO 'advansys' option to eliminate or
+ * limit I/O port probing at boot time, cf. advansys_setup().
+ */
+int asc_iopflag = ASC_FALSE;
+int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 };
+
+#ifdef ADVANSYS_DEBUG
+char *
+asc_bus_name[ASC_NUM_BUS] = {
+	"ASC_IS_ISA",
+	"ASC_IS_VL",
+	"ASC_IS_EISA",
+	"ASC_IS_PCI",
+};
+
+int		asc_dbglvl = 0;
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Driver Function Prototypes
+ *
+ * advansys.h contains function prototypes for functions global to Linux.
+ */
+
+#ifdef LINUX_1_3
+STATIC int			asc_proc_copy(off_t, off_t, char *, int , char *, int);
+#endif /* LINUX_1_3 */
+STATIC void 		advansys_interrupt(int, struct pt_regs *);
+STATIC void 		advansys_command_done(Scsi_Cmnd *);
+STATIC int 			asc_execute_scsi_cmnd(Scsi_Cmnd *);
+STATIC void 		asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
+STATIC void			asc_execute_pending(struct Scsi_Host *);
+STATIC int 			asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
+STATIC int 			asc_srch_pci_dev(PCI_DEVICE *);
+STATIC uchar 		asc_scan_method(PCI_DEVICE *);
+STATIC int 			asc_pci_find_dev(PCI_DEVICE *);
+STATIC void 		asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
+STATIC ushort 		asc_get_cfg_word(PCI_DATA *);
+STATIC uchar 		asc_get_cfg_byte(PCI_DATA *);
+STATIC void			asc_enqueue(struct Scsi_Host *, Scsi_Cmnd *, int, int);
+STATIC Scsi_Cmnd 	*asc_dequeue(struct Scsi_Host *, int);
+STATIC int 			asc_rmqueue(struct Scsi_Host *, Scsi_Cmnd *, int);
+
+/* XXX - Asc Library Routines not supposed to be used directly */
+ushort 			AscGetChipBiosAddress(PortAddr, ushort);
+int             AscFindSignature(PortAddr);
+
+#ifdef ADVANSYS_STATS
+STATIC int		asc_prt_stats(char *, int);
+STATIC int		asc_prt_stats_line(char *, int, char *fmt, ...);
+#endif /* ADVANSYS_STATS */
+#ifdef ADVANSYS_DEBUG
+STATIC void 	asc_prt_scsi_host(struct Scsi_Host *);
+STATIC void 	asc_prt_dvc_cfg(ASC_DVC_CFG *);
+STATIC void 	asc_prt_dvc_var(ASC_DVC_VAR *);
+STATIC void 	asc_prt_scsi_q(ASC_SCSI_Q *);
+STATIC void 	asc_prt_qdone_info(ASC_QDONE_INFO *);
+STATIC void 	asc_prt_hex(char *f, uchar *, int);
+STATIC int 		interrupts_enabled(void);
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
+ */
+
+#ifdef LINUX_1_3
+/*
+ * advansys_proc_info() - /proc/scsi/advansys/[0-ASC_NUM_BOARD_SUPPORTED]
+ *
+ * *buffer: I/O buffer
+ * **start: if inout == FALSE pointer into buffer where user read should start
+ * offset: current offset into /proc/scsi/advansys file
+ * length: length of buffer
+ * hostno: Scsi_Host host_no
+ * inout: TRUE - user is writing; FALSE - user is reading
+ *
+ * Return the number of bytes read from or written to
+ * /proc/scsi/advansys file.
+ */
+int
+advansys_proc_info(char *buffer, char **start, off_t offset, int length, 
+				   int hostno, int inout)
+{
+	struct Scsi_Host	*shp;
+	int					i;
+	char				*cp;
+	int					cplen;
+	int					cnt;
+	int					totcnt;
+	int					leftlen;
+	char				*curbuf;
+	off_t				advoffset;
+    Scsi_Device			*scd;
+	char				prtbuf[480];	/* 6 lines */
+
+	ASC_DBG(1, "advansys_proc_info: begin\n");
+
+	/*
+	 * User write not supported.
+	 */
+	if (inout == TRUE) {
+		return(-ENOSYS);
+	}
+
+	/*
+	 * User read of /proc/scsi/advansys file.
+	 */
+
+	/* Find the specified board. */
+	for (i = 0; i < asc_board_count; i++) {
+		if (asc_host[i]->host_no == hostno) {
+			break;
+		}
+	}
+	if (i == asc_board_count) {
+		return(-ENOENT);
+	}
+	shp = asc_host[i];
+
+	/* Always copy read data to the beginning of the buffer. */
+	*start = buffer;
+
+	curbuf = buffer;
+	advoffset = 0;
+	totcnt = 0;
+	leftlen = length;
+
+	/* Get board information. */
+	cp = (char *) advansys_info(shp);
+	strcat(cp, "\n");
+	cplen = strlen(cp);
+
+	/* Copy board information. */
+	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+	totcnt += cnt;
+	leftlen -= cnt;
+	if (leftlen == 0) {
+		ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+		return totcnt;
+	}
+	advoffset += cplen;
+	curbuf += cnt;
+
+	/*
+	 * Get and copy information for each device attached to the board.
+	 */
+	cp = &prtbuf[0];
+	sprintf(cp, "\nDevices attached to SCSI Host %d:\n", shp->host_no);
+	cplen = strlen(cp);
+	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+	totcnt += cnt;
+	leftlen -= cnt;
+	if (leftlen == 0) {
+		ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+		return totcnt;
+	}
+	advoffset += cplen;
+	curbuf += cnt;
+
+	cp = &prtbuf[0];
+    for (scd = scsi_devices; scd; scd = scd->next) {
+		if (scd->host == shp) {
+	    	proc_print_scsidevice(scd, cp, &cplen, 0);
+			cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+			totcnt += cnt;
+			leftlen -= cnt;
+			if (leftlen == 0) {
+				ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+				return totcnt;
+			}
+			advoffset += cplen;
+			curbuf += cnt;
+		}
+    }
+    
+#ifdef ADVANSYS_STATS
+	/*
+	 * prtbuf[] has about 6 lines worth of space. If the statistics ever
+	 * get longer than 6 lines, prtbuf[] should be increased in size. If
+	 * prtbuf[] is too small it will not be overwritten. Instead the user
+	 * just won't get all of the available statistics.
+	 */
+	cp = &prtbuf[0];
+	cplen = asc_prt_stats(cp, sizeof(prtbuf));
+	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+	totcnt += cnt;
+	leftlen -= cnt;
+	if (leftlen == 0) {
+		ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+		return totcnt;
+	}
+	advoffset += cplen;
+	curbuf += cnt;
+#endif /* ADVANSYS_STATS */
+
+	ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+
+	return totcnt;
+}
+#endif /* LINUX_1_3 */
+
+
+/*
+ * advansys_detect()
+ *
+ * Detect function for AdvanSys adapters.
+ *
+ * Argument is a pointer to the host driver's scsi_hosts entry.
+ *
+ * Return number of adapters found.
+ *
+ * Note: Because this function is called during system initialization
+ * it must not call SCSI mid-level functions including scsi_malloc()
+ * and scsi_free().
+ */
+int
+advansys_detect(Scsi_Host_Template *tpnt)
+{
+	static int			detect_called = ASC_FALSE;
+	int					iop;
+	int					bus;
+	struct Scsi_Host	*shp;
+	ASC_DVC_VAR			*boardp;
+	int					ioport = 0;
+	PCI_DEVICE			pciDevice;
+	PCI_CONFIG_SPACE	pciConfig;
+	int					ret;
+	extern PortAddr		_asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX];
+
+
+	if (detect_called == ASC_FALSE) {
+		detect_called = ASC_TRUE;
+	} else {
+		printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n");
+		return 0;
+	}
+
+	ASC_DBG(1, "advansys_detect: begin\n");
+
+#ifdef LINUX_1_3
+	tpnt->proc_dir = &proc_scsi_advansys;
+#endif /* LINUX_1_3 */
+
+#ifdef ADVANSYS_STATS
+	memset(&asc_stats, 0, sizeof(asc_stats));
+#endif /* ADVANSYS_STATS */
+
+	asc_board_count = 0;
+
+	/*
+	 * If I/O port probing has been modified, then verify and
+	 * clean-up the 'asc_ioport' list.
+	 */
+	if (asc_iopflag == ASC_TRUE) {
+		for (ioport = 0; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
+			ASC_DBG2(1, "asdvansys_detect: asc_ioport[%d] %x\n",
+				ioport, asc_ioport[ioport]);
+			if (asc_ioport[ioport] != 0) {
+				for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
+					if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
+						break;
+					}
+				}
+				if (iop == ASC_IOADR_TABLE_MAX_IX) {
+					printk("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
+						asc_ioport[ioport]);
+					asc_ioport[ioport] = 0;
+				}
+			}
+		}
+		ioport = 0;
+	}
+
+	memset(&pciDevice, 0, sizeof(PCI_DEVICE));
+	memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
+	pciDevice.maxBusNumber = PCI_MAX_BUS;
+	pciDevice.endSlot = PCI_MAX_SLOT;
+
+	for (bus = 0; bus < ASC_NUM_BUS; bus++) {
+
+		ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
+			bus, asc_bus_name[bus]);
+		iop = 0;
+
+		while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
+
+			ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
+				asc_board_count);
+
+			switch (asc_bus[bus]) {
+			case ASC_IS_ISA:
+			case ASC_IS_VL:
+				if (asc_iopflag == ASC_FALSE) {
+					iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
+				} else {
+					/*
+					 * ISA and VL I/O port scanning has either been
+					 * eliminated or limited to selected ports on
+					 * the LILO command line, /etc/lilo.conf, or
+					 * by setting variables when the module was loaded.
+					 */
+					ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
+				ioport_try_again:
+					iop = 0;
+					for (; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
+						if ((iop = asc_ioport[ioport]) != 0) {
+							break;
+						}
+					}
+					if (iop) {
+						ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
+							iop);
+						if (check_region(iop, ASC_IOADR_GAP) != 0) {
+							printk("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
+							/* Don't try this I/O port twice. */
+							asc_ioport[ioport] = 0;
+							goto ioport_try_again;
+						} else if (AscFindSignature(iop) == ASC_FALSE) {
+							printk("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
+							/* Don't try this I/O port twice. */
+							asc_ioport[ioport] = 0;
+							goto ioport_try_again;
+						} else {
+							/*
+							 * If this isn't an ISA board, then it must be
+							 * a VL board. If currently looking an ISA
+							 * board is being looked for then try for
+							 * another ISA board in 'asc_ioport'.
+							 */
+							if (asc_bus[bus] == ASC_IS_ISA &&
+							    (AscGetChipVersion(iop, ASC_IS_ISA) &
+								 ASC_CHIP_VER_ISA_BIT) == 0) {
+							 	/*
+								 * Don't clear 'asc_ioport[ioport]'. Try
+								 * this board again for VL. Increment
+								 * 'ioport' past this board.
+								 */
+								 ioport++;
+								 goto ioport_try_again;
+							}
+						}
+						/*
+						 * This board appears good, don't try the I/O port
+						 * again by clearing its value. Increment 'ioport'
+						 * for the next iteration.
+						 */
+						asc_ioport[ioport++] = 0;
+					}
+				}
+				break;
+
+			case ASC_IS_EISA:
+				iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
+				break;
+
+			case ASC_IS_PCI:
+					if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
+						iop = 0;
+					} else {
+						ASC_DBG2(2,
+							"advansys_detect: slotFound %d, busNumber %d\n",
+							pciDevice.slotFound, pciDevice.busNumber);
+						asc_get_pci_cfg(&pciDevice, &pciConfig);
+						iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
+						ASC_DBG2(2, "advansys_detect: iop %x, irqLine %d\n",
+							iop, pciConfig.irqLine);
+					}
+				break;
+
+			default:
+				ASC_DBG(0, "advansys_detect: unknown bus type\n");
+				break;
+			}
+			ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
+
+			/*
+			 * Adapter not found, try next bus type.
+			 */
+			if (iop == 0) {
+				break;
+			}
+
+			/*
+			 * Adapter found.
+			 *
+			 * Register the adapter, get its configuration, and
+			 * initialize it.
+			 */
+			ASC_DBG(2, "advansys_detect: scsi_register()\n");
+			shp = scsi_register(tpnt, sizeof(struct asc_board));
+
+			/* Save a pointer to the Scsi_host of each found board. */
+			asc_host[asc_board_count++] = shp;
+
+			/* Initialize private per board data */
+			memset(ASC_BOARD(shp), 0, sizeof(struct asc_board));
+			boardp = &ASC_BOARD(shp)->board;
+			boardp->cfg = &ASC_BOARD(shp)->cfg;
+			boardp->cfg->overrun_buf = &ASC_BOARD(shp)->overrun_buf[0];
+			boardp->iop_base = iop;
+
+			/*
+			 * Set the board bus type and PCI IRQ for AscInitGetConfig().
+			 */
+			boardp->bus_type = asc_bus[bus];
+			switch (boardp->bus_type) {
+			case ASC_IS_ISA:
+				shp->unchecked_isa_dma = TRUE;
+				break;
+			case ASC_IS_EISA:
+				shp->unchecked_isa_dma = FALSE;
+				break;
+			case ASC_IS_VL:
+				shp->unchecked_isa_dma = FALSE;
+				break;
+			case ASC_IS_PCI:
+				shp->irq = boardp->irq_no = pciConfig.irqLine;
+				boardp->cfg->pci_device_id = pciConfig.deviceID;
+				shp->unchecked_isa_dma = FALSE;
+				break;
+			default:
+				ASC_DBG(0, "advansys_detect: unknown adapter type");
+				shp->unchecked_isa_dma = TRUE;
+				break;
+			}
+
+			/*
+			 * Get the board configuration.  AscInitGetConfig() may change
+			 * the board's bus_type value. The asc_bus[bus] value should no
+			 * longer be used.
+			 */
+			ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
+			switch(ret = AscInitGetConfig(boardp)) {
+			case 0:	/* No error */
+				break;
+			case ASC_WARN_IO_PORT_ROTATE:
+				ASC_DBG(0, "AscInitGetConfig: I/O port address modified\n");
+				break;
+			case ASC_WARN_EEPROM_CHKSUM:
+				ASC_DBG(0, "AscInitGetConfig: EEPROM checksum error\n");
+				break;
+			case ASC_WARN_IRQ_MODIFIED:
+				ASC_DBG(0, "AscInitGetConfig: IRQ modified\n");
+				break;
+			case ASC_WARN_CMD_QNG_CONFLICT:
+				ASC_DBG(0,
+					"AscInitGetConfig: Tag queuing enabled w/o disconnects\n");
+				break;
+			default:
+				ASC_DBG1(0, "AscInitGetConfig: Unknown warning: %x\n", ret);
+				break;
+			}
+			if (boardp->err_code != 0) {
+				ASC_DBG2(0,
+					"AscInitGetConfig: error: init_state %x, err_code %x\n",
+					boardp->init_state, boardp->err_code);
+				scsi_unregister(shp);
+				asc_board_count--;
+				continue;
+			}
+
+			/*
+			 * Modify board configuration.
+			 */
+			boardp->isr_callback = (Ptr2Func) asc_isr_callback;
+			boardp->exe_callback = (Ptr2Func) NULL;
+
+			ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
+			switch (ret = AscInitSetConfig(boardp)) {
+			case 0:	/* No error. */
+				break;
+			case ASC_WARN_IO_PORT_ROTATE:
+				ASC_DBG(0, "AscInitSetConfig: I/O port address modified\n");
+				break;
+			case ASC_WARN_EEPROM_CHKSUM:
+				ASC_DBG(0, "AscInitSetConfig: EEPROM checksum error\n");
+				break;
+			case ASC_WARN_IRQ_MODIFIED:
+				ASC_DBG(0, "AscInitSetConfig: IRQ modified\n");
+				break;
+			case ASC_WARN_CMD_QNG_CONFLICT:
+				ASC_DBG(0, "AscInitSetConfig: Tag queuing w/o disconnects\n");
+				break;
+			default:
+				ASC_DBG1(0, "AscInitSetConfig: Unknown warning: %x\n", ret);
+				break;
+			}
+			if (boardp->err_code != 0) {
+				ASC_DBG2(0,
+					"AscInitSetConfig: error: init_state %x, err_code %x\n",
+					boardp->init_state, boardp->err_code);
+				scsi_unregister(shp);
+				asc_board_count--;
+				continue;
+			}
+
+			/*
+			 * Finish initializing the 'Scsi_Host' structure.
+			 */
+
+			/* AscInitSetConfig() will set the IRQ for non-PCI boards. */
+			if (boardp->bus_type != ASC_IS_PCI) {
+				shp->irq = boardp->irq_no;
+			}
+
+			shp->io_port = boardp->iop_base;
+			shp->n_io_port = ASC_IOADR_GAP;
+			shp->this_id = boardp->cfg->chip_scsi_id;
+
+			/* Maximum number of queues this adapter can handle. */
+			shp->can_queue = boardp->max_total_qng;
+
+			/*
+			 * XXX - Command queuing limits are maintained per target
+			 * by AdvanSys adapters. Set 'cmd_per_lun' to the minimum
+			 * value of the all the target settings for the adapter.
+			 *
+			 * For now set 'cmd_per_lun' to 'max_total_qng'. This
+			 * value should be adjusted every time a new device is
+			 * found in asc_init_dev().
+			 *
+			 * XXX - memory allocation is done by the mid-level scsi
+			 * driver based on 'cmd_per_lun'. If 'sg_tablesize' is too large
+			 * allocation failures can occur in scsi_register_host().
+			 * A 'Scsi_Cmnd' structure is pre-allocated for each command
+			 * also DMA memory is reserved. Set it artificially low for now.
+			 *
+			 * shp->cmd_per_lun = boardp->max_total_qng;
+			 */
+#ifdef MODULE
+			shp->cmd_per_lun = 1;
+#else /* MODULE */
+			shp->cmd_per_lun = 4;
+#endif /* MODULE */
+			ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
+			
+			/* Maximum number of scatter-gather elements adapter can handle. */
+			/*
+			 * XXX - memory allocation is done by the mid-level scsi
+			 * driver based on sg_tablesize. If 'sg_tablesize' is too large
+			 * allocation failures can occur in scsi_register_host().
+			 */
+#ifdef MODULE
+			shp->sg_tablesize = 8;
+#else /* MODULE */
+			shp->sg_tablesize = ASC_MAX_SG_LIST;
+#endif /* MODULE */
+			ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
+				shp->sg_tablesize);
+
+			/* BIOS start address. */
+			shp->base = (char *) ((ulong) AscGetChipBiosAddress(
+												boardp->iop_base,
+												boardp->bus_type));
+
+			/*
+			 * Register Board Resources - I/O Port, DMA, IRQ
+			 */
+
+			/* Register I/O port range */
+			ASC_DBG(2, "advansys_detect: request_region()\n");
+			request_region(shp->io_port, shp->n_io_port, "advansys");
+
+			/* Register DMA channel for ISA bus. */
+			if ((boardp->bus_type & ASC_IS_ISA) == 0) {
+				shp->dma_channel = NO_ISA_DMA;
+			} else {
+				shp->dma_channel = boardp->cfg->isa_dma_channel;
+				if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) {
+					ASC_DBG2(0, "advansys_detect: request_dma() %d failed %d\n",
+						shp->dma_channel, ret);
+					release_region(shp->io_port, shp->n_io_port);
+					scsi_unregister(shp);
+					asc_board_count--;
+					continue;
+				}
+				AscEnableIsaDma(shp->dma_channel);
+			}
+
+			/* Register IRQ Number. */
+			ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
+			if ((ret = request_irq(shp->irq, advansys_interrupt,
+								SA_INTERRUPT, "advansys")) != 0) {
+				ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret);
+				release_region(shp->io_port, shp->n_io_port);
+				if (shp->dma_channel != NO_ISA_DMA) {
+					free_dma(shp->dma_channel);
+				}
+				scsi_unregister(shp);
+				asc_board_count--;
+				continue;
+			}
+
+			/*
+			 * Initialize board RISC chip and enable interrupts.
+			 */
+			ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
+			if (AscInitAsc1000Driver(boardp)) {
+				ASC_DBG2(0,
+					"AscInitAsc1000Driver: error: init_state %x, err_code %x\n",
+					boardp->init_state, boardp->err_code);
+				release_region(shp->io_port, shp->n_io_port);
+				if (shp->dma_channel != NO_ISA_DMA) {
+					free_dma(shp->dma_channel);
+				}
+				free_irq(shp->irq);
+				scsi_unregister(shp);
+				asc_board_count--;
+				continue;
+			}
+			ASC_DBG_PRT_SCSI_HOST(2, shp);
+		}
+	}
+
+	ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
+	return asc_board_count;
+}
+
+/*
+ * advansys_release()
+ *
+ * Release resources allocated for a single AdvanSys adapter.
+ */
+int
+advansys_release(struct Scsi_Host *shp)
+{
+	ASC_DBG(1, "advansys_release: begin\n");
+	free_irq(shp->irq);
+	if (shp->dma_channel != NO_ISA_DMA) {
+		ASC_DBG(1, "advansys_release: free_dma()\n");
+		free_dma(shp->dma_channel);
+	}
+	release_region(shp->io_port, shp->n_io_port);
+	scsi_unregister(shp);
+	ASC_DBG(1, "advansys_release: end\n");
+	return 0;
+}
+
+/*
+ * advansys_info()
+ *
+ * Return suitable for printing on the console with the argument
+ * adapter's configuration information.
+ */
+const char *
+advansys_info(struct Scsi_Host *shp)
+{
+	static char 	info[128];
+	ASC_DVC_VAR		*boardp;
+	char			*busname;
+
+	boardp = &ASC_BOARD(shp)->board;
+	ASC_DBG(1, "advansys_info: begin\n");
+	if (boardp->bus_type & ASC_IS_ISA) {
+		sprintf(info,
+			"AdvanSys SCSI %s: ISA (%u CDB): BIOS %X, IO %X-%X, IRQ %u, DMA %u",
+			ASC_VERSION, ASC_BOARD(shp)->board.max_total_qng,
+			(unsigned) shp->base, shp->io_port,
+			shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
+	} else {
+		switch (boardp->bus_type) {
+		case ASC_IS_EISA:
+			busname = "EISA";
+			break;
+		case ASC_IS_VL:
+			busname = "VL";
+			break;
+		case ASC_IS_PCI:
+			busname = "PCI";
+			break;
+		default:
+			busname = "?";
+			ASC_DBG1(0, "advansys_info: unknown bus type %d\n",
+				boardp->bus_type);
+			break;
+		}
+		/* No DMA channel for non-ISA busses. */
+		sprintf(info,
+			"AdvanSys SCSI %s: %s (%u CDB): BIOS %X, IO %X-%X, IRQ %u",
+			ASC_VERSION, busname, ASC_BOARD(shp)->board.max_total_qng,
+			(unsigned) shp->base, shp->io_port,
+			shp->io_port + (shp->n_io_port - 1), shp->irq);
+	}
+	ASC_DBG(1, "advansys_info: end\n");
+	return info;
+}
+
+/*
+ * advansys_command()
+ *
+ * Polled-I/O. Apparently host driver shouldn't return until
+ * command is finished.
+ *
+ * XXX - Can host driver block here instead of spinning on command status?
+ */
+int
+advansys_command(Scsi_Cmnd *scp)
+{
+	ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
+	ASC_STATS(command);
+	scp->SCp.Status = 0; /* Set to a known state */
+	advansys_queuecommand(scp, advansys_command_done);
+	while (scp->SCp.Status == 0) {
+		continue;
+	}
+	ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
+	return scp->result;
+}
+
+/*
+ * advansys_queuecommand()
+ *
+ * This function always returns 0. Command return status is saved
+ * in the 'scp' result field.
+ */
+int
+advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
+{
+	struct Scsi_Host		*shp;
+	int						flags = 0;
+	int						interrupts_disabled;
+
+	ASC_STATS(queuecommand);
+	shp = scp->host;
+
+#ifdef LINUX_1_2
+	/*
+	 * For LINUX_1_3, if statistics are enabled they can be accessed
+	 * by reading /proc/scsi/advansys/[0-9].
+	 */
+#ifdef ADVANSYS_STATS_1_2_PRINT
+	/* Display statistics every 10000 commands. */
+	if ((asc_stats.queuecommand % 10000) == 0) {
+		printk("\n");
+		(void) asc_prt_stats(NULL, 0);
+		printk("\n");
+	}
+#endif /* ADVANSYS_STATS_1_2_PRINT */
+#endif /* LINUX_1_2 */
+
+	/*
+	 * If there are any pending commands for this board before trying
+	 * to execute them, disable interrupts to preserve request ordering.
+	 *
+	 * The typical case will be no pending commands and interrupts
+	 * not disabled.
+	 */
+	if (ASC_BOARD(shp)->pending_tidmask == 0) {
+		interrupts_disabled = ASC_FALSE;
+	} else {
+		ASC_STATS(cmd_disable);
+		/* Disable interrupts */
+		interrupts_disabled = ASC_TRUE;
+		save_flags(flags);
+		cli();
+		ASC_DBG1(1, "advansys_queuecommand: asc_execute_pending() %x\n",
+			ASC_BOARD(shp)->pending_tidmask);
+		asc_execute_pending(shp);
+	}
+
+	/*
+	 * Save the function pointer to Linux mid-level 'done' function and
+	 * execute the command.
+	 */
+	scp->scsi_done = done;
+	if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
+		if (interrupts_disabled == ASC_FALSE) {
+			save_flags(flags);
+			cli();
+			interrupts_disabled = ASC_TRUE;
+		}
+		asc_enqueue(shp, scp, scp->target, ASC_BACK);
+	}
+
+	if (interrupts_disabled == ASC_TRUE) {
+		restore_flags(flags);
+	}
+
+	return 0;
+}
+
+/*
+ * advansys_abort()
+ *
+ * Abort the specified command and reset the device
+ * associated with the command 'scp'.
+ */
+int
+advansys_abort(Scsi_Cmnd *scp)
+{
+	ASC_DVC_VAR		*boardp;
+	int				flags;
+	int				ret;
+
+	ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+	save_flags(flags);
+	cli();
+	ASC_STATS(abort);
+	if (scp->host == NULL) {
+		scp->result = HOST_BYTE(DID_ERROR);
+		ret = SCSI_ABORT_ERROR;
+	} else if (asc_rmqueue(scp->host, scp, scp->target) == ASC_TRUE) {
+		scp->result = HOST_BYTE(DID_ABORT);
+		ret = SCSI_ABORT_SUCCESS;
+		(void) AscResetDevice(&ASC_BOARD(scp->host)->board, scp->target);
+	} else {
+		/* Must enable interrupts for AscAbortSRB() */
+		sti();
+		boardp = &ASC_BOARD(scp->host)->board;
+		scp->result = HOST_BYTE(DID_ABORT);
+		switch (AscAbortSRB(boardp, (ulong) scp)) {
+		case ASC_TRUE:
+			/* asc_isr_callback() will be called */
+			ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
+			ret = SCSI_ABORT_PENDING;
+			break;
+		case ASC_FALSE:
+			/* Request has apparently already completed. */
+			ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
+			ret = SCSI_ABORT_NOT_RUNNING;
+			break;
+		case ASC_ERROR:
+		default:
+			ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
+			ret = SCSI_ABORT_ERROR;
+			break;
+		}
+		(void) AscResetDevice(boardp, scp->target);
+	}
+	restore_flags(flags);
+	ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
+	return ret;
+}
+
+/*
+ * advansys_reset()
+ *
+ * Reset all devices and the SCSI bus for the board
+ * associated with 'scp'.
+ */
+int
+advansys_reset(Scsi_Cmnd *scp)
+{
+	ASC_DVC_VAR		*boardp;
+	int				flags;
+	Scsi_Cmnd		*tscp;
+	int				i;
+	int				ret;
+
+	ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+	save_flags(flags);
+	cli();
+	ASC_STATS(reset);
+	if (scp->host == NULL) {
+		scp->result = HOST_BYTE(DID_ERROR);
+		ret = SCSI_RESET_ERROR;
+	} else {
+		/* Remove any pending commands, set DID_RESET, and done them.  */
+		for (i = 0; i < ASC_MAX_TID; i++) {
+			while ((tscp = asc_dequeue(scp->host, i)) != NULL) {
+				tscp->result = HOST_BYTE(DID_RESET);
+				tscp->scsi_done(tscp);
+			}
+		}
+		/* Must enable interrupts for AscResetSB() */
+		sti();
+		boardp = &ASC_BOARD(scp->host)->board;
+		scp->result = HOST_BYTE(DID_RESET);
+		switch (AscResetSB(boardp)) {
+		case ASC_TRUE:
+			ASC_DBG(1, "advansys_abort: AscResetSB() TRUE\n");
+			ret = SCSI_RESET_SUCCESS;
+			break;
+		case ASC_ERROR:
+		default:
+			ASC_DBG(1, "advansys_abort: AscResetSB() ERROR\n");
+			ret = SCSI_RESET_ERROR;
+			break;
+		}
+	}
+	restore_flags(flags);
+	ASC_DBG1(1, "advansys_reset: ret %d", ret);
+	return ret;
+}
+
+/*
+ * advansys_biosparam()
+ *
+ * Translate disk drive geometry if the "BIOS greater than 1 GB"
+ * support is enabled for a drive.
+ *
+ * ip (information pointer) is an int array with the following definition:
+ * ip[0]: heads
+ * ip[1]: sectors
+ * ip[2]: cylinders
+ */
+int
+#ifdef LINUX_1_2
+advansys_biosparam(Disk *dp, int dep, int ip[])
+#else /* LINUX_1_3 */
+advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
+#endif /* LINUX_1_3 */
+{
+	ASC_DBG(1, "advansys_biosparam: begin\n");
+	ASC_STATS(biosparam);
+	if ((ASC_BOARD(dp->device->host)->board.dvc_cntl & ASC_CNTL_BIOS_GT_1GB) &&
+		dp->capacity > 0x200000) {
+			ip[0] = 255;
+			ip[1] = 64;
+	} else {
+			ip[0] = 64;
+			ip[1] = 32;
+	}
+	ip[2] = dp->capacity / (ip[0] * ip[1]);
+	ASC_DBG(1, "advansys_biosparam: end\n");
+	return 0;
+}
+
+/*
+ * advansys_setup()
+ *
+ * This function is called from init/main.c at boot time.
+ * It it passed LILO parameters that can be set from the
+ * LILO command line or in /etc/lilo.conf.
+ *
+ * It is used by the AdvanSys driver to either disable I/O
+ * port scanning or to limit scanning to 1 - 4 I/O ports.
+ * Regardless of the option setting EISA and PCI boards
+ * will still be searched for and detected. This option
+ * only affects searching for ISA and VL boards.
+ *
+ * If ADVANSYS_DEBUG is defined the driver debug level may
+ * be set using the 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port.
+ *
+ * Examples:
+ * 1. Eliminate I/O port scanning:
+ * 		boot: linux advansys=
+ *       or
+ * 		boot: linux advansys=0x0
+ * 2. Limit I/O port scanning to one I/O port:
+ *		boot: linux advansys=0x110
+ * 3. Limit I/O port scanning to four I/O ports:
+ *		boot: linux advansys=0x110,0x210,0x230,0x330
+ * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
+ *    set the driver debug level to 2.
+ *		boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
+ *
+ * ints[0] - number of arguments
+ * ints[1] - first argument
+ * ints[2] - second argument
+ * ...
+ */
+void
+advansys_setup(char *str, int *ints)
+{
+	int	i;
+
+	if (asc_iopflag == ASC_TRUE) {
+		printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
+		return;
+	}
+
+	asc_iopflag = ASC_TRUE;
+
+	if (ints[0] > ASC_NUM_BOARD_SUPPORTED) {
+#ifdef ADVANSYS_DEBUG
+		if ((ints[0] == ASC_NUM_BOARD_SUPPORTED + 1) &&
+		    (ints[ASC_NUM_BOARD_SUPPORTED + 1] >> 4 == 0xdeb)) {
+			asc_dbglvl = ints[ASC_NUM_BOARD_SUPPORTED + 1] & 0xf;
+		} else {
+#endif /* ADVANSYS_DEBUG */
+			printk("AdvanSys SCSI: only %d I/O ports accepted\n",
+				ASC_NUM_BOARD_SUPPORTED);
+#ifdef ADVANSYS_DEBUG
+		}
+#endif /* ADVANSYS_DEBUG */
+	}
+
+#ifdef ADVANSYS_DEBUG
+	ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
+	for (i = 1; i < ints[0]; i++) {
+		ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
+	}
+	ASC_DBG(1, "\n");
+#endif /* ADVANSYS_DEBUG */
+
+	for (i = 1; i <= ints[0] && i <= ASC_NUM_BOARD_SUPPORTED; i++) {
+		asc_ioport[i-1] = ints[i];
+		ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
+			i - 1, asc_ioport[i-1]);
+	}
+}
+
+
+/*
+ * --- Loadable Driver Support
+ */
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = ADVANSYS;
+# include "scsi_module.c"
+#endif /* MODULE */
+
+
+/*
+ * --- Miscellaneous Driver Functions
+ */
+
+#ifdef LINUX_1_3
+/*
+ * asc_proc_copy() 
+ *
+ * Copy proc information to a read buffer considering the current read
+ * offset in the file and the remaining space in the read buffer.
+ */
+STATIC int
+asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
+			  char *cp, int cplen)
+{
+	int cnt = 0;
+	
+	ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
+			(unsigned) offset, (unsigned) advoffset, cplen);
+	if (offset <= advoffset) {
+		/* Read offset below current offset, copy everything. */
+		cnt = min(cplen, leftlen);
+		ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
+				(unsigned) curbuf, (unsigned) cp, cnt);
+		memcpy(curbuf, cp, cnt);
+	} else if (offset < advoffset + cplen) {
+		/* Read offset within current range, partial copy. */
+		cnt = (advoffset + cplen) - offset;
+		cp = (cp + cplen) - cnt;
+		cnt = min(cnt, leftlen);
+		ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
+				(unsigned) curbuf, (unsigned) cp, cnt);
+		memcpy(curbuf, cp, cnt);
+	}
+	return cnt;
+}
+#endif /* LINUX_1_3 */
+
+/*
+ * First-level interrupt handler.
+ */
+STATIC void
+advansys_interrupt(int irq, struct pt_regs *regs)
+{
+	int			i;
+	int			flags;
+	Scsi_Cmnd	*scp;
+	Scsi_Cmnd	*tscp;
+
+	/* Disable interrupts, if the aren't already disabled. */
+	save_flags(flags);
+	cli();
+
+	ASC_DBG(1, "advansys_interrupt: begin\n");
+	ASC_STATS(interrupt);
+	/*
+	 * Check for interrupts on all boards.
+	 * AscISR() will call asc_isr_callback().
+	 */
+	for (i = 0; i < asc_board_count; i++) {
+		while (AscIsIntPending(asc_host[i]->io_port)) {
+			ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
+			AscISR(&ASC_BOARD(asc_host[i])->board);
+		}
+	}
+	ASC_DBG(1, "advansys_interrupt: end\n");
+
+	/*
+	 * While interrupts are still disabled save the list of requests that
+	 * need their done function called. After re-enabling interrupts call
+	 * the done function which may re-enable interrupts anyway.
+	 */
+	if ((scp = asc_scsi_done) != NULL) {
+		asc_scsi_done = NULL;
+	}
+
+	/* Re-enable interrupts, if they were enabled on entry. */
+	restore_flags(flags);
+
+	while (scp) {
+		tscp = (Scsi_Cmnd *) scp->host_scribble;
+		scp->scsi_done(scp);
+		scp = tscp;
+	}
+
+	return;
+}
+
+/*
+ * Function used only with polled I/O requests that are initiated by
+ * advansys_command().
+ */
+STATIC void
+advansys_command_done(Scsi_Cmnd *scp)
+{
+	ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
+	scp->SCp.Status = 1;
+}
+
+/*
+ * Execute a single 'Scsi_Cmnd'.
+ *
+ * The function 'done' is called when the request has been completed.
+ *
+ * Scsi_Cmnd:
+ *
+ *  host - board controlling device
+ *  device - device to send command
+ *  target - target of device
+ *  lun - lun of device
+ *  cmd_len - length of SCSI CDB
+ *	cmnd - buffer for SCSI 8, 10, or 12 byte CDB
+ *  use_sg - if non-zero indicates scatter-gather request with use_sg elements
+ *
+ *  if (use_sg == 0)
+ *		request_buffer - buffer address for request
+ *		request_bufflen - length of request buffer
+ *  else
+ *		request_buffer - pointer to scatterlist structure
+ *
+ *  sense_buffer - sense command buffer
+ *
+ *  result (4 bytes of an int):
+ *   Byte Meaning
+ *   0	  SCSI Status Byte Code
+ *   1	  SCSI One Byte Message Code
+ *   2 	  Host Error Code
+ *   3	  Mid-Level Error Code
+ *
+ *  host driver fields:
+ *  SCp - Scsi_Pointer used for command processing status
+ *  scsi_done - used to save caller's done function
+ * 	host_scribble - used for pointer to another Scsi_Cmnd
+ *
+ * If this function returns ASC_NOERROR or ASC_ERROR the done
+ * function has been called. If ASC_BUSY is returned the request
+ * must be enqueued by the caller and re-tried later.
+ */
+STATIC int
+asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
+{
+	ASC_DVC_VAR		*boardp;
+	ASC_SCSI_Q		scsiq;
+	ASC_SG_HEAD		sghead;
+	int				ret;
+
+	ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
+		(unsigned) scp, (unsigned) scp->scsi_done);
+
+	boardp = &ASC_BOARD(scp->host)->board;
+
+	/*
+	 * If this is the first command, then initialize the device. If
+	 * no device is found set 'DID_BAD_TARGET' and return.
+	 */
+	if ((ASC_BOARD(scp->host)->init_tidmask &
+		 ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
+		if (asc_init_dev(boardp, scp) == ASC_FALSE) {
+			scp->result = HOST_BYTE(DID_BAD_TARGET);
+			scp->scsi_done(scp);
+			return ASC_ERROR;
+		}
+		ASC_BOARD(scp->host)->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
+	}
+
+	memset(&scsiq, 0, sizeof(ASC_SCSI_Q));
+
+	/*
+	 * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
+	 */
+	scsiq.q2.srb_ptr = (ulong) scp;
+
+	/*
+	 * Build the ASC_SCSI_Q request.
+	 */
+	scsiq.cdbptr = &scp->cmnd[0];
+	scsiq.q2.cdb_len = scp->cmd_len;
+	scsiq.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+	scsiq.q1.target_lun = scp->lun;
+	scsiq.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
+	scsiq.q1.sense_addr = (ulong) &scp->sense_buffer[0];
+	scsiq.q1.sense_len = sizeof(scp->sense_buffer);
+	scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+
+	/*
+	 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
+	 * buffer command.
+	 */
+	if (scp->use_sg == 0) {
+		/*
+		 * CDB request of single contiguous buffer.
+		 */
+		ASC_STATS(cont_cnt);
+ 		/* request_buffer is already a real address. */
+		scsiq.q1.data_addr = (ulong) scp->request_buffer;
+		scsiq.q1.data_cnt = scp->request_bufflen;
+		ASC_STATS_ADD(cont_xfer, (scp->request_bufflen + 511) >> 9);
+		scsiq.q1.sg_queue_cnt = 0;
+		scsiq.sg_head = NULL;
+	} else {
+		/*
+		 * CDB scatter-gather request list.
+		 */
+		int					sgcnt;
+		struct scatterlist	*slp;
+
+		if (scp->use_sg > ASC_MAX_SG_LIST) {
+			ASC_DBG2(0, "asc_execute_scsi_cmnd: use_sg %d > %d\n",
+				scp->use_sg, ASC_MAX_SG_LIST);
+			scp->result = HOST_BYTE(DID_ERROR);
+			scp->scsi_done(scp);
+			return ASC_ERROR;
+		}
+
+		ASC_STATS(sg_cnt);
+
+		/*
+		 * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q
+		 * to point to it.
+		 */
+		memset(&sghead, 0, sizeof(ASC_SG_HEAD));
+
+		scsiq.q1.cntl |= QC_SG_HEAD;
+		scsiq.sg_head = &sghead;
+		scsiq.q1.data_cnt = 0;
+		scsiq.q1.data_addr = 0;
+		sghead.entry_cnt = scsiq.q1.sg_queue_cnt = scp->use_sg;
+		ASC_STATS_ADD(sg_elem, sghead.entry_cnt);
+
+		/*
+		 * Convert scatter-gather list into ASC_SG_HEAD list.
+		 */
+		slp = (struct scatterlist *) scp->request_buffer;
+		for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
+			sghead.sg_list[sgcnt].addr = (ulong) slp->address;
+			sghead.sg_list[sgcnt].bytes = slp->length;
+			ASC_STATS_ADD(sg_xfer, (slp->length + 511) >> 9);
+		}
+	}
+
+	ASC_DBG_PRT_SCSI_Q(2, &scsiq);
+	ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
+
+	switch (ret = AscExeScsiQueue(boardp, &scsiq)) {
+	case ASC_NOERROR:
+		ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_NOERROR\n");
+		break;
+	case ASC_BUSY:
+		/* Caller must enqueue request and retry later. */
+		break;
+	case ASC_ERROR:
+		ASC_DBG1(0,
+			"asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_ERROR err_code %x\n",
+			boardp->err_code);
+		ASC_STATS(error);
+		scp->result = HOST_BYTE(DID_ERROR);
+		scp->scsi_done(scp);
+		break;
+	}
+
+	ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
+	return ret;
+}
+
+/*
+ * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
+ */
+void
+asc_isr_callback(ASC_DVC_VAR *boardp, ASC_QDONE_INFO *qdonep)
+{
+	Scsi_Cmnd			*scp;
+	struct Scsi_Host	*shp;
+	int					flags;
+	Scsi_Cmnd			**scpp;
+
+	ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+	ASC_DBG2(1, "asc_isr_callback: boardp %x, qdonep %x\n",
+		(unsigned) boardp, (unsigned) qdonep);
+	ASC_STATS(callback);
+	ASC_DBG_PRT_QDONE_INFO(2, qdonep);
+
+	/*
+	 * Get the Scsi_Cmnd structure and Scsi_Host structure for the
+	 * command that has been completed.
+	 */
+	scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
+	ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
+	ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
+
+	shp = scp->host;
+	ASC_ASSERT(shp);
+	ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
+
+	/*
+	 * 'qdonep' contains the command's ending status.
+	 */
+	switch (qdonep->d3.done_stat) {
+	case QD_NO_ERROR:
+		ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
+		switch (qdonep->d3.host_stat) {
+		case QHSTA_NO_ERROR:
+			scp->result = 0;
+			break;
+		default:
+			/* QHSTA error occurred */
+			scp->result = HOST_BYTE(DID_ERROR);
+			break;
+		}
+		break;
+
+	case QD_WITH_ERROR:
+		ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
+		switch (qdonep->d3.host_stat) {
+		case QHSTA_NO_ERROR:
+			if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
+				ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
+				ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
+					sizeof(scp->sense_buffer));
+				/*
+				 * Note: The status_byte() macro used by target drivers
+				 * defined in scsi.h shifts the status byte returned by
+				 * host drivers right by 1 bit. This is why target drivers
+				 * also use left shifted status byte definitions. For instance
+				 * target drivers use CHECK_CONDITION, defined to 0x1, instead
+				 * of the SCSI defined check condition value of 0x2.
+				 */
+				scp->result = DRIVER_BYTE(DRIVER_SENSE) |
+					STATUS_BYTE(qdonep->d3.scsi_stat); 
+			} else {
+				scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); 
+			}
+			break;
+
+		default:
+			/* QHSTA error occurred */
+			ASC_DBG1(2, "asc_isr_callback: host_stat %x\n",
+				qdonep->d3.host_stat);
+			scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
+				STATUS_BYTE(qdonep->d3.scsi_stat);
+			break;
+		}
+		break;
+
+	case QD_ABORTED_BY_HOST:
+		ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
+		scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
+				STATUS_BYTE(qdonep->d3.scsi_stat);
+		break;
+
+	default:
+		ASC_DBG1(0, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat );
+		scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
+				STATUS_BYTE(qdonep->d3.scsi_stat);
+		break;
+	}
+
+	/*
+	 * Before calling 'scsi_done' for the current 'Scsi_Cmnd' and possibly
+	 * triggering more commands to be issued, try to start any pending
+	 * commands.
+	 */
+	if (ASC_BOARD(shp)->pending_tidmask != 0) {
+	 	/*
+		 * If there are any pending commands for this board before trying
+	 	 * to execute them, disable interrupts to preserve request ordering.
+		 */
+		ASC_STATS(intr_disable);
+		save_flags(flags);
+		cli();
+		ASC_DBG1(1, "asc_isr_callback: asc_execute_pending() %x\n",
+			ASC_BOARD(shp)->pending_tidmask);
+		asc_execute_pending(shp);
+		restore_flags(flags);
+	}
+
+	/* 
+	 * Because interrupts may be enabled by the 'Scsi_Cmnd' done function,
+	 * add the command to the end of the global done list. The done function
+	 * for the command will be called in advansys_interrupt().
+	 */
+	for (scpp = &asc_scsi_done; *scpp;
+	     scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
+		;
+	}
+	*scpp = scp;
+	scp->host_scribble = NULL;
+	return;
+}
+
+/*
+ * Execute as many pending requests as possible for the
+ * board specified by 'Scsi_Host'.
+ */
+STATIC void
+asc_execute_pending(struct Scsi_Host *shp)
+{
+	ASC_SCSI_BIT_ID_TYPE	scan_tidmask;
+	Scsi_Cmnd				*scp;
+	int						i;
+
+	ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+	/*
+	 * Execute pending commands for devices attached to
+	 * the current board in round-robin fashion.
+	 */
+	scan_tidmask = ASC_BOARD(shp)->pending_tidmask;
+	do {
+		for (i = 0; i < ASC_MAX_TID; i++) {
+			if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
+				if ((scp = asc_dequeue(shp, i)) == NULL) {
+					scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
+				} else if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
+					scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
+					/* Put the request back at front of the list. */
+					asc_enqueue(shp, scp, i, ASC_FRONT);
+				}
+			}
+		}
+	} while (scan_tidmask);
+	return;
+}
+
+/*
+ * asc_init_dev()
+ *
+ * Perform one-time initialization of a device.
+ */
+STATIC int
+asc_init_dev(ASC_DVC_VAR *boardp, Scsi_Cmnd *scp)
+{
+	ASC_SCSI_REQ_Q			*scsireqq;
+	ASC_CAP_INFO			*cap_info;
+	ASC_SCSI_INQUIRY		*inquiry;
+	int						found;
+	ASC_SCSI_BIT_ID_TYPE	save_use_tagged_qng;
+	ASC_SCSI_BIT_ID_TYPE	save_can_tagged_qng;
+	int						ret;
+#ifdef ADVANSYS_DEBUG
+	ASC_SCSI_BIT_ID_TYPE	tidmask; /* target id bit mask: 1 - 128 */
+#endif /* ADVANSYS_DEBUG */
+
+	ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target);
+
+	/* Return true for the board's target id. */
+	if (boardp->cfg->chip_scsi_id == scp->target) {
+		return ASC_TRUE;
+	}
+
+	/*
+	 * XXX - Host drivers should not modify the timeout field.
+	 * But on the first command only add some extra time to
+	 * allow the driver to complete its initialization for the
+	 * device.
+	 */
+	scp->timeout += 2000;	/* Add 5 seconds to the request timeout. */
+
+	/* Set-up AscInitPollTarget() arguments. */
+	scsireqq = &ASC_BOARD(scp->host)->scsireqq;
+	memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
+	cap_info = &ASC_BOARD(scp->host)->cap_info;
+	memset(cap_info, 0, sizeof(ASC_CAP_INFO));
+	inquiry = &ASC_BOARD(scp->host)->inquiry;
+	memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
+
+	/*
+	 * XXX - AscInitPollBegin() re-initializes these fields to
+	 * zero. 'Or' in the new values and restore them before calling 
+	 * AscInitPollEnd(). Normally all targets are initialized within
+	 * a call to AscInitPollBegin() and AscInitPollEnd().
+	 */
+	save_use_tagged_qng = boardp->use_tagged_qng;
+    save_can_tagged_qng = boardp->cfg->can_tagged_qng;
+
+	ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
+	if (AscInitPollBegin(boardp)) {
+		ASC_DBG(0, "asc_init_dev: AscInitPollBegin() failed\n");
+		return ASC_FALSE;
+	}
+
+	scsireqq->sense_ptr = &scsireqq->sense[0];
+	scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
+	scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+	scsireqq->r1.target_lun = 0;
+	scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
+
+	found = ASC_FALSE;
+	ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
+	switch (ret = AscInitPollTarget(boardp, scsireqq, inquiry, cap_info)) {
+	case ASC_TRUE:
+		found = ASC_TRUE;
+#ifdef ADVANSYS_DEBUG
+		tidmask = ASC_TIX_TO_TARGET_ID(scp->target);
+		ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
+			cap_info->lba, cap_info->blk_size);
+		ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
+			inquiry->byte0.peri_dvc_type);
+		if (boardp->use_tagged_qng & tidmask) {
+			ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
+				boardp->max_dvc_qng[scp->target]);
+		} else {
+			ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
+		}
+		if (boardp->init_sdtr & tidmask) {
+			ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n");
+		} else {
+			ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n");
+		}
+		/* Set bit means fix disabled. */
+		if (boardp->pci_fix_asyn_xfer & tidmask) {
+			ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n");
+		} else {
+			ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n");
+		}
+#endif /* ADVANSYS_DEBUG */
+		break;
+	case ASC_FALSE:
+		ASC_DBG(1, "asc_init_dev: no device found\n");
+		break;
+	case ASC_ERROR:
+		ASC_DBG(0, "asc_init_dev: AscInitPollTarget() ASC_ERROR\n");
+		break;
+	default:
+		ASC_DBG1(0, "asc_init_dev: AscInitPollTarget() unknown ret %d\n", ret);
+		break;
+	}
+
+	/* XXX - 'Or' in original tag bits. */
+	boardp->use_tagged_qng |= save_use_tagged_qng;
+	boardp->cfg->can_tagged_qng |= save_can_tagged_qng;
+
+	ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
+	AscInitPollEnd(boardp);
+
+#ifdef ASC_SET_CMD_PER_LUN
+	/*
+	 * XXX - Refer to the comment in advansys_detect()
+	 * regarding cmd_per_lun.
+	 */
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		if (boardp->max_dvc_qng[i] < scp->host->cmd_per_lun) {
+			scp->host->cmd_per_lun = boardp->max_dvc_qng[i];
+		}
+	}
+#endif /* ASC_SET_CMD_PER_LUN */
+
+	return found;
+}
+
+/*
+ * Search for an AdvanSys PCI device in the PCI configuration space.
+ */
+STATIC int
+asc_srch_pci_dev(PCI_DEVICE *pciDevice)
+{
+	int ret;
+	static int scan = 1;
+
+	ASC_DBG(2, "asc_srch_pci_dev: begin\n");
+
+	if (scan) {
+		pciDevice->type = asc_scan_method(pciDevice);
+		scan = 0;
+		ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
+	}
+	ret = asc_pci_find_dev(pciDevice);
+	ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
+	if (ret == PCI_DEVICE_FOUND) {
+		pciDevice->slotNumber = pciDevice->slotFound + 1;
+		pciDevice->startSlot = pciDevice->slotFound + 1;
+	} else {
+		if (pciDevice->bridge > pciDevice->busNumber) {
+			ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
+				pciDevice->bridge, pciDevice->busNumber);
+			pciDevice->busNumber++;
+			pciDevice->slotNumber = 0;
+			pciDevice->startSlot = 0;
+			pciDevice->endSlot = 0x0f;
+			ret = asc_srch_pci_dev(pciDevice);
+			ASC_DBG1(2, "asc_srch_pci_dev recursive call return %d\n", ret);
+		}
+	}
+	ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
+	return ret;
+}
+
+/*
+ * Determine the access method to be used for 'pciDevice'.
+ */
+STATIC uchar
+asc_scan_method(PCI_DEVICE *pciDevice)
+{
+	ushort data;
+	PCI_DATA pciData;
+	uchar type;
+	uchar slot;
+
+	ASC_DBG(2, "asc_scan_method: begin\n");
+	memset(&pciData, 0, sizeof(pciData));
+	for (type = 1; type < 3; type++) {
+		pciData.type = type;
+		for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
+			pciData.slot = slot;
+			data = asc_get_cfg_word(&pciData);
+			if ((data != 0xFFFF) && (data != 0x0000)) {
+				ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
+				return (type);
+			}
+		}
+	}
+	ASC_DBG1(4, "asc_scan_method: type %d\n", type);
+	return (type);
+}
+
+/*
+ * Check for an AdvanSys PCI device in 'pciDevice'.
+ *
+ * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
+ */
+STATIC int
+asc_pci_find_dev(PCI_DEVICE *pciDevice)
+{
+	PCI_DATA pciData;
+	ushort vendorid, deviceid;
+	uchar classcode, subclass;
+	uchar lslot;
+
+	ASC_DBG(3, "asc_pci_find_dev: begin\n");
+	pciData.type = pciDevice->type;
+	pciData.bus = pciDevice->busNumber;
+	pciData.func = pciDevice->devFunc;
+	lslot = pciDevice->startSlot;
+	for (; lslot < pciDevice->endSlot; lslot++) {
+		pciData.slot = lslot;
+		pciData.offset = VENDORID_OFFSET;
+		vendorid = asc_get_cfg_word(&pciData);
+		ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
+		if (vendorid != 0xffff) {
+			pciData.offset = DEVICEID_OFFSET;
+			deviceid = asc_get_cfg_word(&pciData);
+			ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
+			if ((vendorid == ASC_PCI_VENDORID) &&
+				((deviceid == ASC_PCI_DEVICE_ID_REV_A) ||
+				(deviceid == ASC_PCI_DEVICE_ID_REV_B))) {
+				pciDevice->slotFound = lslot;
+				ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
+				return PCI_DEVICE_FOUND;
+			} else {
+				pciData.offset = SUBCLASS_OFFSET;
+				subclass = asc_get_cfg_byte(&pciData);
+				pciData.offset = CLASSCODE_OFFSET;
+				classcode = asc_get_cfg_byte(&pciData);
+				if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
+					(subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
+					pciDevice->bridge++;
+				}
+				ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
+					subclass, classcode);
+			}
+		}
+	}
+	return PCI_DEVICE_NOT_FOUND;
+}
+
+/*
+ * Read PCI configuration data into 'pciConfig'.
+ */
+STATIC void
+asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
+{
+	PCI_DATA pciData;
+	uchar counter;
+	uchar *localConfig;
+
+	ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ",
+		pciDevice->slotFound);
+
+	pciData.type = pciDevice->type;
+	pciData.bus = pciDevice->busNumber;
+	pciData.slot = pciDevice->slotFound;
+	pciData.func = pciDevice->devFunc;
+	localConfig = (uchar *) pciConfig;
+
+	for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
+		pciData.offset = counter;
+		*localConfig = asc_get_cfg_byte(&pciData);
+		ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
+		localConfig++;
+	}
+	ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
+}
+
+/*
+ * Read a word (16 bits) from the PCI configuration space.
+ *
+ * The configuration mechanism is checked for the correct access method.
+ */
+STATIC ushort
+asc_get_cfg_word(PCI_DATA *pciData)
+{
+	ushort tmp;
+	ulong address;
+	ulong lbus = pciData->bus;
+	ulong lslot = pciData->slot;
+	ulong lfunc = pciData->func;
+	uchar t2CFA, t2CF8;
+	ushort t1CF8, t1CFA, t1CFC, t1CFE;
+
+	ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
+		pciData->type, lbus, lslot, lfunc);
+
+	/*
+	 * check type of configuration mechanism
+	 */
+	if (pciData->type == 2) {
+		/*
+		 * save these registers so we can restore them after we are done
+		 */
+		t2CFA = inp(0xCFA);	/* save PCI bus register */
+		t2CF8 = inp(0xCF8);	/* save config space enable register */
+
+		/*
+		 * go out and write the bus and enable registers
+		 */
+		/* set for type 1 cycle, if needed */
+		outp(0xCFA, pciData->bus);
+		/* set the function number */
+		outp(0xCF8, 0x10 | (pciData->func << 1)) ;
+
+		/*
+		 * read the configuration space type 2 locations
+		 */
+		tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
+	} else {
+		/*
+		 * type 1 configuration mechanism
+		 *
+		 * save the CONFIG_ADDRESS and CONFIG_DATA register values
+		 */
+		t1CFC = inpw(0xCFC);
+		t1CFE = inpw(0xCFE);
+		t1CF8 = inpw(0xCF8);
+		t1CFA = inpw(0xCFA);
+
+		/*
+		 * enable <31>, bus = <23:16>, slot = <15:11>,
+		 * func = <10:8>, reg = <7:2>
+		 */
+		address = (ulong) ((lbus << 16) | (lslot << 11) |
+			(lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
+
+		/*
+		 * write out the address to CONFIG_ADDRESS
+		 */
+		outl(address, 0xCF8);
+
+		/*
+		 * read in the word from CONFIG_DATA
+		 */
+		tmp = (ushort) ((inl(0xCFC) >>
+				 ((pciData->offset & 2) * 8)) & 0xFFFF);
+	}
+	ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
+	return tmp;
+}
+
+/*
+ * Reads a byte from the PCI configuration space.
+ *
+ * The configuration mechanism is checked for the correct access method.
+ */
+STATIC uchar
+asc_get_cfg_byte(PCI_DATA *pciData)
+{
+	uchar tmp;
+	ulong address;
+	ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
+	uchar t2CFA, t2CF8;
+	ushort t1CF8, t1CFA, t1CFC, t1CFE;
+
+	ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
+
+	/*
+	 * check type of configuration mechanism
+	 */
+	if (pciData->type == 2) {
+		/*
+		 * save these registers so we can restore them after we are done
+		 */
+		t2CFA = inp(0xCFA);	/* save PCI bus register */
+		t2CF8 = inp(0xCF8);	/* save config space enable register */
+
+		/*
+		 * go out and write the bus and enable registers
+		 */
+		/* set for type 1 cycle, if needed */
+		outp(0xCFA, pciData->bus);
+		/* set the function number */
+		outp(0xCF8, 0x10 | (pciData->func << 1));
+
+		/*
+		 * read the configuration space type 2 locations
+		 */
+		tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
+
+		/*
+		 * restore the registers used for our transaction
+		 */
+		outp(0xCF8, t2CF8);	/* restore the enable register */
+		outp(0xCFA, t2CFA);	/* restore PCI bus register */
+	} else {
+		/*
+		 * type 1 configuration mechanism
+		 *
+		 * save the CONFIG_ADDRESS and CONFIG_DATA register values
+		 */
+		t1CFC = inpw(0xCFC);
+		t1CFE = inpw(0xCFE);
+		t1CF8 = inpw(0xCF8);
+		t1CFA = inpw(0xCFA);
+
+		/*
+		 * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
+		 * reg = <7:2>
+		 */
+		address = (ulong) ((lbus << 16) | (lslot << 11) |
+			(lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
+
+		/*
+		 * write out the address to CONFIG_ADDRESS
+		 */
+		outl(address, 0xCF8);
+
+		/*
+		 * read in the word from CONFIG_DATA
+		 */
+		tmp = (uchar) ((inl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
+	}
+	ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
+	return tmp;
+}
+
+/*
+ * Add a 'Scsi_Cmnd' to the end of specified 'Scsi_Host' 
+ * target device pending command list. Set 'pending_tidmask'
+ * to indicate a command is queued for the device.
+ *
+ * 'flag' may be either ASC_FRONT or ASC_BACK.
+ *
+ * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
+ */
+STATIC void
+asc_enqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid, int flag)
+{
+	Scsi_Cmnd	**scpp;
+
+	ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+	ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
+	ASC_STATS(enqueue);
+	if (flag == ASC_FRONT) {
+		scp->host_scribble = (unsigned char *) ASC_BOARD(shp)->pending[tid];
+		ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp;
+	} else { /* ASC_BACK */
+		for (scpp = &ASC_BOARD(shp)->pending[tid]; *scpp;
+			 scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
+			;
+		}
+		*scpp = scp;
+		scp->host_scribble = NULL;
+	}
+	ASC_BOARD(shp)->pending_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
+}
+
+/*
+ * Return first pending 'Scsi_Cmnd' on the specified 'Scsi_Host'
+ * for the specified target device. Clear the 'pending_tidmask'
+ * bit for the device if no more commands are left queued for it.
+ *
+ * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
+ */
+STATIC Scsi_Cmnd *
+asc_dequeue(struct Scsi_Host *shp, int tid)
+{
+	Scsi_Cmnd	*scp;
+
+	ASC_STATS(dequeue);
+	ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+	if ((scp = ASC_BOARD(shp)->pending[tid]) != NULL) {
+		ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp->host_scribble;
+	}
+	if (ASC_BOARD(shp)->pending[tid] == NULL) {
+		ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
+	}
+	return scp;
+}
+
+/*
+ * Remove the specified 'Scsi_Cmnd' from the specified 'Scsi_Host'
+ * for the specified target device. Clear the 'pending_tidmask'
+ * bit for the device if no more commands are left queued for it.
+ *
+ * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
+ *
+ * Return ASC_TRUE if the command was found and removed, otherwise
+ * return ASC_FALSE if the command was not found.
+ */
+STATIC int
+asc_rmqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid)
+{
+	Scsi_Cmnd	**scpp;
+	int			ret;
+
+	ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+	ret = ASC_FALSE;
+	for (scpp = &ASC_BOARD(shp)->pending[tid];
+	     *scpp; scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
+		if (*scpp == scp) {
+			*scpp = (Scsi_Cmnd *) scp->host_scribble;	
+			scp->host_scribble = NULL;
+			ASC_STATS(rmqueue);
+			ret = ASC_TRUE;
+		}
+	}
+	if (ASC_BOARD(shp)->pending[tid] == NULL) {
+		ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
+	}
+	return ret;
+}
+
+
+/*
+ * --- Functions Required by the Asc Library
+ */
+
+/*
+ * Delay for 'n' milliseconds. Don't use the 'jiffies'
+ * global variable which is incremented once every 5 ms
+ * from a timer interrupt, because this function may be
+ * called when interrupts are disabled.
+ */
+void
+DvcSleepMilliSecond(ulong n)
+{
+	ulong i;
+
+	ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
+	for (i = 0; i < n; i++) {
+		udelay(1000);
+	}
+}
+
+void
+DvcDisplayString(uchar *s)
+{
+	printk(s);
+}
+
+int
+DvcEnterCritical(void)
+{
+	int	flags;
+
+	save_flags(flags);
+	cli();
+	return flags;
+}
+
+void
+DvcLeaveCritical(int flags)
+{
+	restore_flags(flags);
+}
+
+/*
+ * Convert a virtual address to a virtual address.
+ *
+ * Apparently Linux is loaded V=R (virtual equals real). Just return
+ * the virtual address.
+ */
+ulong
+DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
+{
+	ulong phys_addr;
+
+	phys_addr = (ulong) buf_addr;
+	return phys_addr;
+}
+
+ulong
+DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
+			 ASC_SG_HEAD *asc_sg_head_ptr)
+{
+	ulong buf_size;
+
+	buf_size = buf_len;
+	asc_sg_head_ptr->entry_cnt = 1;
+	asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
+	asc_sg_head_ptr->sg_list[0].bytes = buf_size;
+	return buf_size;
+}
+
+/*
+ * void
+ * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
+ *
+ * Calling/Exit State:
+ *	none
+ *
+ * Description:
+ * 	Output an ASC_SCSI_Q structure to the chip
+ */
+void
+DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
+{
+	int	i;
+
+	ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
+	AscSetChipLramAddr(iop_base, s_addr);
+	for (i = 0; i < words; i++, outbuf++) {
+		if (i == 2 || i == 10) {
+			continue;
+		}
+		AscPutChipLramData(iop_base, *outbuf);
+	}
+}
+
+/*
+ * void
+ * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
+ *
+ * Calling/Exit State:
+ *	none
+ *
+ * Description:
+ * 	Input an ASC_QDONE_INFO structure from the chip
+ */
+void
+DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
+{
+	int	i;
+
+	AscSetChipLramAddr(iop_base, s_addr);
+	for (i = 0; i < words; i++, inbuf++) {
+		if (i == 5) {
+			continue;
+		}
+		*inbuf = AscGetChipLramData(iop_base);
+	}
+	ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
+}
+
+/*
+ * void	DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
+ *
+ * Calling/Exit State:
+ *	none
+ *
+ * Description:
+ * 	output a buffer to an i/o port address
+ */
+void
+DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
+{
+	int	i;
+
+	for (i = 0; i < words; i++, outbuf++)
+		outpw(iop_base, *outbuf);
+}
+
+/*
+ * void	DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
+ *
+ * Calling/Exit State:
+ *	none
+ *
+ * Description:
+ * 	input a buffer from an i/o port address
+ */
+void
+DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
+{
+	int	i;
+
+	for (i = 0; i < words; i++, inbuf++)
+		*inbuf = inpw(iop_base);
+}
+
+
+/*
+ * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
+ *
+ * Calling/Exit State:
+ *	none
+ *
+ * Description:
+ * 	output a buffer of 32-bit integers to an i/o port address in
+ *  16 bit integer units
+ */
+void  
+DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
+{
+	int		i;
+	int		words;
+	ushort	*pw;
+
+	pw = (ushort *) pdw;
+	words = dwords << 1;
+	for(i = 0; i < words; i++, pw++) {
+		outpw(port, *pw);
+	}
+	return;
+}
+
+
+/*
+ * --- Tracing and Debugging Functions
+ */
+
+#ifdef ADVANSYS_STATS
+
+#define ASC_PRT_STATS_NEXT() \
+	if (cp) { \
+		totlen += len; \
+		leftlen -= len; \
+		if (leftlen == 0) { \
+			return totlen; \
+		} \
+		cp += len; \
+	}
+
+/*
+ * asc_prt_stats()
+ *
+ * Note: no single line should be greater than 160 characters, cf.
+ * asc_prt_stats_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
+STATIC int
+asc_prt_stats(char *cp, int cplen)
+{
+ 	struct asc_stats	*s;
+	int					leftlen;
+	int					totlen;
+	int					len;
+
+ 	s = &asc_stats;
+	leftlen = cplen;
+	totlen = len = 0;
+
+	len = asc_prt_stats_line(cp, leftlen,
+"\nAdvanSys SCSI Host Driver Statistics:\n");
+	ASC_PRT_STATS_NEXT();
+	
+	len = asc_prt_stats_line(cp, leftlen,
+" command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu,\n",
+		s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
+	ASC_PRT_STATS_NEXT();
+
+	len = asc_prt_stats_line(cp, leftlen,
+" interrupt %lu, callback %lu, cmd_disable %lu, intr_disable %lu,\n",
+		s->interrupt, s->callback, s->cmd_disable, s->intr_disable);
+	ASC_PRT_STATS_NEXT();
+
+	len = asc_prt_stats_line(cp, leftlen,
+" error %lu, enqueue %lu, dequeue %lu, rmqueue %lu,\n",
+		s->error, s->enqueue, s->dequeue, s->rmqueue);
+	ASC_PRT_STATS_NEXT();
+
+	if (s->cont_cnt > 0) {
+		len = asc_prt_stats_line(cp, leftlen,
+" cont_cnt %lu, cont_xfer %lu: avg_xfer=%lu kb\n",
+			s->cont_cnt, s->cont_xfer, (s->cont_xfer/2)/s->cont_cnt);
+		ASC_PRT_STATS_NEXT();
+	}
+
+	if (s->sg_cnt > 0) {
+		len = asc_prt_stats_line(cp, leftlen,
+" sg_cnt %lu, sg_elem %lu, sg_xfer %lu: avg_elem=%lu, avg_size=%lu kb\n",
+			s->sg_cnt, s->sg_elem, s->sg_xfer,
+			s->sg_elem/s->sg_cnt, (s->sg_xfer/2)/s->sg_cnt);
+		ASC_PRT_STATS_NEXT();
+	}
+
+ 	return totlen;
+}
+
+/*
+ * asc_prt_stats_line()
+ *
+ * If 'cp' is NULL print to the console, otherwise print to a buffer.
+ *
+ * Return 0 if printing to the console, otherwise return the number of
+ * bytes written to the buffer.
+ *
+ * Note: If any single line is greater than 160 bytes the stack
+ * will be corrupted. 's[]' is defined to be 160 bytes.
+ */
+int
+asc_prt_stats_line(char *buf, int buflen, char *fmt, ...)
+{
+	va_list		args;
+	int			ret;
+	char		s[160];		/* 2 lines */
+
+	va_start(args, fmt);
+	ret = vsprintf(s, fmt, args);
+	if (buf == NULL) {
+		(void) printk(s);
+		ret = 0;
+	} else {
+		ret = min(buflen, ret);
+		memcpy(buf, s, ret);
+	}
+	va_end(args);
+	return ret;
+}
+#endif /* ADVANSYS_STATS */
+
+#ifdef ADVANSYS_DEBUG
+/*
+ * asc_prt_scsi_host()
+ */
+STATIC void 
+asc_prt_scsi_host(struct Scsi_Host *s)
+{
+	printk("Scsi_Host at addr %x\n", (unsigned) s);
+	printk(
+" next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
+		(unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
+		s->last_reset);
+
+	printk(
+" host_wait %x, host_queue %x, hostt %x, block %x,\n",
+		(unsigned) s->host_wait, (unsigned) s->host_queue,
+		(unsigned) s->hostt, (unsigned) s->block);
+
+	printk(
+" wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
+		s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
+		s->irq, s->dma_channel);
+
+	printk(
+" this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
+
+	printk(
+" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
+		s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
+		s->loaded_as_module);
+
+	printk("hostdata (struct asc_board)\n");
+	asc_prt_dvc_var(&ASC_BOARD(s)->board);
+	asc_prt_dvc_cfg(&ASC_BOARD(s)->cfg);
+	printk(" overrun_buf %x\n", (unsigned) &ASC_BOARD(s)->overrun_buf[0]);
+}
+
+/*
+ * asc_prt_dvc_var()
+ */
+STATIC void 
+asc_prt_dvc_var(ASC_DVC_VAR *h)
+{
+	printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
+
+	printk(
+" iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
+		h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
+
+	printk(
+" bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
+		h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
+		(unsigned) h->init_sdtr);
+
+	printk(
+" sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
+		(unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
+		(unsigned) h->unit_not_ready, (unsigned) h->chip_no);
+		
+	printk(
+" queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
+		(unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
+		(unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
+
+	printk(
+" is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
+		(unsigned) h->is_in_int, (unsigned) h->max_total_qng,
+		(unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
+
+	printk(
+" last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
+		(unsigned) h->last_q_shortage, (unsigned) h->init_state,
+		(unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
+
+	printk(
+" int_count %ld, req_count %ld, busy_count %ld, cfg %x, saved_ptr2func %x\n",
+		h->int_count, h->req_count, h->busy_count, (unsigned) h->cfg,
+		(unsigned) h->saved_ptr2func);
+}
+
+/*
+ * asc_prt_dvc_cfg()
+ */
+STATIC void 
+asc_prt_dvc_cfg(ASC_DVC_CFG *h)
+{
+	printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
+
+	printk(
+" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n",
+			h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res);
+
+	printk(
+" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
+			 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
+			 h->chip_version);
+
+	printk(
+" pci_device_id %d, lib_serial_no %d, lib_version %d, mcode_date %d,\n",
+		  h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
+
+	printk(
+" mcode_version %d, overrun_buf %x\n",
+			h->mcode_version, (unsigned) h->overrun_buf);
+}
+
+/*
+ * asc_prt_scsi_q()
+ */
+STATIC void 
+asc_prt_scsi_q(ASC_SCSI_Q *q)
+{
+	ASC_SG_HEAD	*sgp;
+	int i;
+
+	printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
+
+	printk(
+" target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
+			q->q2.target_ix, q->q1.target_lun,
+			(unsigned) q->q2.srb_ptr, q->q2.tag_code);
+
+	printk(
+" data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
+			(unsigned) q->q1.data_addr, q->q1.data_cnt,
+			(unsigned) q->q1.sense_addr, q->q1.sense_len);
+
+	printk(
+" cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
+			(unsigned) q->cdbptr, q->q2.cdb_len,
+			(unsigned) q->sg_head, q->q1.sg_queue_cnt);
+
+	if (q->sg_head) {
+		sgp = q->sg_head;
+		printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
+		printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
+		for (i = 0; i < sgp->entry_cnt; i++) {
+			printk(" [%u]: addr %x, bytes %lu\n",
+				i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
+		}
+
+	}
+}
+
+/*
+ * asc_prt_qdone_info()
+ */
+STATIC void 
+asc_prt_qdone_info(ASC_QDONE_INFO *q)
+{
+	printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
+	printk(
+" srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
+			(unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
+			q->d2.tag_code, q->d3.done_stat);
+	printk(
+" host_stat %x, scsi_stat %x, scsi_msg %x\n",
+			q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
+}
+
+/*
+ * asc_prt_hex()
+ *
+ * Print hexadecimal output in 4 byte groupings 32 bytes 
+ * or 8 double-words per line.
+ */
+STATIC void 
+asc_prt_hex(char *f, uchar *s, int l)
+{
+	int			i;
+	int			j;
+	int			k;
+	int			m;
+
+	printk("%s: (%d bytes)\n", f, l);
+
+	for (i = 0; i < l; i += 32) {
+		
+		/* Display a maximum of 8 double-words per line. */
+		if ((k = (l - i) / 4) >= 8) {
+			k = 8;
+			m = 0;
+		} else {
+			m = (l - i) % 4 ;
+		}
+
+		for (j = 0; j < k; j++) {
+			printk(" %2.2X%2.2X%2.2X%2.2X",
+				(unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
+				(unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
+		}
+
+		switch (m) {
+		case 0:
+		default:
+			break;
+		case 1:
+			printk(" %2.2X",
+				(unsigned) s[i+(j*4)+4]);
+			break;
+		case 2:
+			printk(" %2.2X%2.2X",
+				(unsigned) s[i+(j*4)+4],
+				(unsigned) s[i+(j*4)+5]);
+			break;
+		case 3:
+			printk(" %2.2X%2.2X%2.2X",
+				(unsigned) s[i+(j*4)+4],
+				(unsigned) s[i+(j*4)+5],
+				(unsigned) s[i+(j*4)+6]);
+			break;
+		}
+
+		printk("\n");
+	}
+}
+
+/*
+ * interrupts_enabled()
+ *
+ * Return 1 if interrupts are enabled, otherwise return 0.
+ */
+STATIC int
+interrupts_enabled(void)
+{
+	int flags;
+
+	save_flags(flags);
+	if (flags & 0x0200) {
+		return ASC_TRUE;
+	} else {
+		return ASC_FALSE;
+	}
+}
+
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Asc Library Functions
+ */
+
+ushort
+AscGetEisaChipCfg(
+					 PortAddr iop_base
+)
+{
+	PortAddr            eisa_cfg_iop;
+
+	eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
+	  (PortAddr) (ASC_EISA_CFG_IOP_MASK);
+	return (inpw(eisa_cfg_iop));
+}
+
+uchar
+AscSetChipScsiID(
+					PortAddr iop_base,
+					uchar new_host_id
+)
+{
+	ushort              cfg_lsw;
+
+	if (AscGetChipScsiID(iop_base) == new_host_id) {
+		return (new_host_id);
+	}
+	cfg_lsw = AscGetChipCfgLsw(iop_base);
+	cfg_lsw &= 0xF8FF;
+	cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
+	AscSetChipCfgLsw(iop_base, cfg_lsw);
+	return (AscGetChipScsiID(iop_base));
+}
+
+ushort
+AscGetChipBiosAddress(
+						 PortAddr iop_base,
+						 ushort bus_type
+)
+{
+	ushort              cfg_lsw;
+	ushort              bios_addr;
+
+	if ((bus_type & ASC_IS_EISA) != 0) {
+		cfg_lsw = AscGetEisaChipCfg(iop_base);
+		cfg_lsw &= 0x000F;
+		bios_addr = (ushort) (ASC_BIOS_MIN_ADDR +
+							  (cfg_lsw * ASC_BIOS_BANK_SIZE));
+		return (bios_addr);
+	}
+	cfg_lsw = AscGetChipCfgLsw(iop_base);
+	bios_addr = (ushort) (((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ASC_BIOS_MIN_ADDR);
+	return (bios_addr);
+}
+
+uchar
+AscGetChipVersion(
+					 PortAddr iop_base,
+					 ushort bus_type
+)
+{
+	if ((bus_type & ASC_IS_EISA) != 0) {
+
+		PortAddr            eisa_iop;
+		uchar               revision;
+
+		eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
+		  (PortAddr) ASC_EISA_REV_IOP_MASK;
+		revision = inp(eisa_iop);
+		return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
+	}
+	return (AscGetChipVerNo(iop_base));
+}
+
+ushort
+AscGetChipBusType(
+					 PortAddr iop_base
+)
+{
+	ushort              chip_ver;
+
+	chip_ver = AscGetChipVerNo(iop_base);
+	if ((chip_ver >= ASC_CHIP_MIN_VER_VL) &&
+		(chip_ver <= ASC_CHIP_MAX_VER_VL)) {
+		if (((iop_base & 0x0C30) == 0x0C30) ||
+			((iop_base & 0x0C50) == 0x0C50)) {
+			return (ASC_IS_EISA);
+		}
+		return (ASC_IS_VL);
+	} else if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
+			   (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
+		if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
+			return (ASC_IS_ISAPNP);
+		}
+		return (ASC_IS_ISA);
+	} else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
+			   (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
+		return (ASC_IS_PCI);
+	} else {
+		return (0);
+	}
+}
+
+void
+AscEnableIsaDma(
+				   uchar dma_channel
+)
+{
+	if (dma_channel < 4) {
+		outp(0x000B, (ushort) (0xC0 | dma_channel));
+		outp(0x000A, dma_channel);
+	} else if (dma_channel < 8) {
+
+		outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
+		outp(0x00D4, (ushort) (dma_channel - 4));
+	}
+	return;
+}
+
+ulong
+AscLoadMicroCode(
+					PortAddr iop_base,
+					ushort s_addr,
+					ushort dosfar * mcode_buf,
+					ushort mcode_size
+)
+{
+	ulong               chksum;
+	ushort              mcode_word_size;
+	ushort              mcode_chksum;
+
+	mcode_word_size = (ushort) (mcode_size >> 1);
+	AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
+	AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
+
+	chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
+	mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
+											  (ushort) ASC_CODE_SEC_BEG,
+		  (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
+	AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
+	AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
+	return (chksum);
+}
+
+uchar               _hextbl_[16] =
+{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'};
+
+uchar               _isa_pnp_inited = 0;
+
+PortAddr            _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] =
+{
+	0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
+	ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
+};
+
+PortAddr
+AscSearchIOPortAddr(
+					   PortAddr iop_beg,
+					   ushort bus_type
+)
+{
+	if (bus_type & ASC_IS_VL) {
+		while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
+			if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
+				return (iop_beg);
+			}
+		}
+		return (0);
+	}
+	if (bus_type & ASC_IS_ISA) {
+		if (_isa_pnp_inited == 0) {
+			AscSetISAPNPWaitForKey();
+			_isa_pnp_inited++;
+		}
+		while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
+			if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
+				return (iop_beg);
+			}
+		}
+		return (0);
+	}
+	if (bus_type & ASC_IS_EISA) {
+		if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
+			return (iop_beg);
+		}
+		return (0);
+	}
+	return (0);
+}
+
+PortAddr
+AscSearchIOPortAddr11(
+						 PortAddr s_addr
+)
+{
+
+	int                 i;
+	PortAddr            iop_base;
+
+	for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
+		if (_asc_def_iop_base[i] > s_addr) {
+			break;
+		}
+	}
+	for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
+		iop_base = _asc_def_iop_base[i];
+		if (AscFindSignature(iop_base)) {
+			return (iop_base);
+		}
+	}
+	return (0);
+}
+
+int
+AscFindSignature(
+					PortAddr iop_base
+)
+{
+	ushort              sig_word;
+
+	if ((inp((PortAddr) (iop_base + 1)) & 0xFF) == (uchar) ASC_1000_ID1B) {
+		sig_word = inpw(iop_base);
+		if ((sig_word == (ushort) ASC_1000_ID0W) ||
+			(sig_word == (ushort) ASC_1000_ID0W_FIX)) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+void
+AscToggleIRQAct(
+				   PortAddr iop_base
+)
+{
+	AscSetChipStatus(iop_base, CIW_IRQ_ACT);
+	AscSetChipStatus(iop_base, 0);
+	return;
+}
+
+#if CC_INIT_INQ_DISPLAY
+
+#endif
+
+void
+AscSetISAPNPWaitForKey(
+						  void)
+{
+
+	outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
+	outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
+	return;
+}
+
+uchar
+AscGetChipIRQ(
+				 PortAddr iop_base,
+				 ushort bus_type
+)
+{
+	ushort              cfg_lsw;
+	uchar               chip_irq;
+
+	if ((bus_type & ASC_IS_EISA) != 0) {
+
+		cfg_lsw = AscGetEisaChipCfg(iop_base);
+		chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
+		if ((chip_irq == 13) || (chip_irq > 15)) {
+
+			return (0);
+		}
+		return (chip_irq);
+	} else {
+
+		cfg_lsw = AscGetChipCfgLsw(iop_base);
+
+		if ((bus_type & ASC_IS_VL) != 0) {
+
+			chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
+			if ((chip_irq == 0) ||
+				(chip_irq == 4) ||
+				(chip_irq == 7)) {
+				return (0);
+			}
+			return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
+		}
+		chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
+		if (chip_irq == 3)
+			chip_irq += (uchar) 2;
+		return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
+	}
+}
+
+uchar
+AscSetChipIRQ(
+				 PortAddr iop_base,
+				 uchar irq_no,
+				 ushort bus_type
+)
+{
+	ushort              cfg_lsw;
+
+	if ((bus_type & ASC_IS_VL) != 0) {
+
+		if (irq_no != 0) {
+			if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
+				irq_no = 0;
+			} else {
+				irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
+			}
+		}
+		cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
+		cfg_lsw |= (ushort) 0x0010;
+		AscSetChipCfgLsw(iop_base, cfg_lsw);
+		AscToggleIRQAct(iop_base);
+
+		cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
+		cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
+		AscSetChipCfgLsw(iop_base, cfg_lsw);
+		AscToggleIRQAct(iop_base);
+
+		return (AscGetChipIRQ(iop_base, bus_type));
+
+	} else if ((bus_type & (ASC_IS_ISA)) != 0) {
+
+		if (irq_no == 15)
+			irq_no -= (uchar) 2;
+		irq_no -= (uchar) ASC_MIN_IRQ_NO;
+		cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
+		cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
+		AscSetChipCfgLsw(iop_base, cfg_lsw);
+		return (AscGetChipIRQ(iop_base, bus_type));
+	} else {
+
+		return (0);
+	}
+}
+
+uchar
+AscGetChipScsiCtrl(
+					  PortAddr iop_base
+)
+{
+	uchar               sc;
+
+	AscSetBank(iop_base, 1);
+	sc = inp(iop_base + IOP_REG_SC);
+	AscSetBank(iop_base, 0);
+	return (sc);
+}
+
+extern uchar        _sdtr_period_tbl_[];
+
+int
+AscIsrChipHalted(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	SDTR_XMSG           sdtr_xmsg;
+	SDTR_XMSG           out_msg;
+	ushort              halt_q_addr;
+	int                 sdtr_accept;
+	ushort              int_halt_code;
+	ASC_SCSI_BIT_ID_TYPE scsi_busy;
+	ASC_SCSI_BIT_ID_TYPE target_id;
+	PortAddr            iop_base;
+	uchar               tag_code;
+	uchar               q_status;
+	uchar               halt_qp;
+	uchar               sdtr_data;
+	uchar               target_ix;
+	uchar               q_cntl, tid_no;
+	uchar               cur_dvc_qng;
+	uchar               asyn_sdtr;
+	uchar               scsi_status;
+
+	iop_base = asc_dvc->iop_base;
+	int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
+
+	halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
+	halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
+	target_ix = AscReadLramByte(iop_base,
+				   (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
+	q_cntl = AscReadLramByte(iop_base,
+						(ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
+	tid_no = ASC_TIX_TO_TID(target_ix);
+	target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
+	if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+
+		asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
+	} else {
+		asyn_sdtr = 0;
+	}
+	if (int_halt_code == ASC_HALT_EXTMSG_IN) {
+
+		AscMemWordCopyFromLram(iop_base,
+							   ASCV_MSGIN_BEG,
+							   (ushort dosfar *) & sdtr_xmsg,
+							   (ushort) (sizeof (SDTR_XMSG) >> 1));
+		if ((sdtr_xmsg.msg_type == MS_EXTEND) &&
+			(sdtr_xmsg.msg_len == MS_SDTR_LEN)) {
+			sdtr_accept = TRUE;
+			if (sdtr_xmsg.msg_req == MS_SDTR_CODE) {
+				if (sdtr_xmsg.req_ack_offset > ASC_SYN_MAX_OFFSET) {
+
+					sdtr_accept = FALSE;
+					sdtr_xmsg.req_ack_offset = ASC_SYN_MAX_OFFSET;
+				}
+				sdtr_data = AscCalSDTRData(sdtr_xmsg.xfer_period,
+										   sdtr_xmsg.req_ack_offset);
+				if (sdtr_xmsg.req_ack_offset == 0) {
+
+					q_cntl &= ~QC_MSG_OUT;
+					asc_dvc->init_sdtr &= ~target_id;
+					asc_dvc->sdtr_done &= ~target_id;
+					AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+				} else if ((sdtr_data == 0xFF)) {
+
+					q_cntl |= QC_MSG_OUT;
+					asc_dvc->init_sdtr &= ~target_id;
+					asc_dvc->sdtr_done &= ~target_id;
+					AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+				} else {
+					if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
+
+						q_cntl &= ~QC_MSG_OUT;
+						asc_dvc->sdtr_done |= target_id;
+						asc_dvc->init_sdtr |= target_id;
+						asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+						AscSetChipSDTR(iop_base, sdtr_data, tid_no);
+					} else {
+
+						q_cntl |= QC_MSG_OUT;
+
+						AscMsgOutSDTR(iop_base,
+									  sdtr_xmsg.xfer_period,
+									  sdtr_xmsg.req_ack_offset);
+						asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+						AscSetChipSDTR(iop_base, sdtr_data, tid_no);
+						asc_dvc->sdtr_done |= target_id;
+						asc_dvc->init_sdtr |= target_id;
+					}
+				}
+
+				AscWriteLramByte(iop_base,
+						 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+								 q_cntl);
+				AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+				return (0);
+			}
+		}
+	} else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
+
+		q_cntl |= QC_REQ_SENSE;
+		if (((asc_dvc->init_sdtr & target_id) != 0) &&
+			((asc_dvc->sdtr_done & target_id) != 0)) {
+
+			sdtr_data = AscReadLramByte(iop_base,
+				  (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
+			AscMsgOutSDTR(iop_base,
+						  _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
+						  (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
+			q_cntl |= QC_MSG_OUT;
+		}
+		AscWriteLramByte(iop_base,
+						 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+						 q_cntl);
+
+		tag_code = AscReadLramByte(iop_base,
+					(ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
+		tag_code &= 0xDC;
+		AscWriteLramByte(iop_base,
+					 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
+						 tag_code);
+
+		q_status = AscReadLramByte(iop_base,
+					  (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
+		q_status |= (QS_READY | QS_BUSY);
+		AscWriteLramByte(iop_base,
+					   (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+						 q_status);
+
+		scsi_busy = AscReadLramByte(iop_base,
+									(ushort) ASCV_SCSIBUSY_B);
+		scsi_busy &= ~target_id;
+		AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+
+		AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+		return (0);
+	} else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
+
+		AscMemWordCopyFromLram(iop_base,
+							   ASCV_MSGOUT_BEG,
+							   (ushort dosfar *) & out_msg,
+							   (ushort) (sizeof (SDTR_XMSG) >> 1));
+
+		if ((out_msg.msg_type == MS_EXTEND) &&
+			(out_msg.msg_len == MS_SDTR_LEN) &&
+			(out_msg.msg_req == MS_SDTR_CODE)) {
+
+			asc_dvc->init_sdtr &= ~target_id;
+			asc_dvc->sdtr_done &= ~target_id;
+			AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+
+		} else {
+
+		}
+
+		q_cntl &= ~QC_MSG_OUT;
+		AscWriteLramByte(iop_base,
+						 (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+						 q_cntl);
+		AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+		return (0);
+	} else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
+
+		scsi_status = AscReadLramByte(iop_base,
+		  (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
+		cur_dvc_qng = AscReadLramByte(iop_base,
+					 (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
+		if ((cur_dvc_qng > 0) &&
+			(asc_dvc->cur_dvc_qng[tid_no] > 0)) {
+
+			scsi_busy = AscReadLramByte(iop_base,
+										(ushort) ASCV_SCSIBUSY_B);
+			scsi_busy |= target_id;
+			AscWriteLramByte(iop_base,
+							 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+			asc_dvc->queue_full_or_busy |= target_id;
+
+			if (scsi_status == SS_QUEUE_FULL) {
+				if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
+					cur_dvc_qng -= 1;
+					asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
+
+					AscWriteLramByte(iop_base,
+									 (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no),
+									 cur_dvc_qng);
+				}
+			}
+		}
+		AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+		return (0);
+	}
+	return (0);
+}
+
+uchar
+_AscCopyLramScsiDoneQ(
+						 PortAddr iop_base,
+						 ushort q_addr,
+						 ASC_QDONE_INFO dosfar * scsiq,
+						 ulong max_dma_count
+)
+{
+	ushort              _val;
+	uchar               sg_queue_cnt;
+
+	DvcGetQinfo(iop_base,
+				(ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
+				(ushort dosfar *) scsiq,
+			  (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
+
+#if !CC_LITTLE_ENDIAN_HOST
+	AscAdjEndianQDoneInfo(scsiq);
+#endif
+
+	_val = AscReadLramWord(iop_base,
+						   (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
+	scsiq->q_status = (uchar) _val;
+	scsiq->q_no = (uchar) (_val >> 8);
+
+	_val = AscReadLramWord(iop_base,
+						   (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
+	scsiq->cntl = (uchar) _val;
+	sg_queue_cnt = (uchar) (_val >> 8);
+
+	_val = AscReadLramWord(iop_base,
+						(ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
+	scsiq->sense_len = (uchar) _val;
+	scsiq->user_def = (uchar) (_val >> 8);
+
+	scsiq->remain_bytes = AscReadLramDWord(iop_base,
+				 (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
+	scsiq->remain_bytes &= max_dma_count;
+
+	return (sg_queue_cnt);
+}
+
+int
+AscIsrQDone(
+			   ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	uchar               next_qp;
+	uchar               i;
+	uchar               n_q_used;
+	uchar               sg_list_qp;
+	uchar               sg_queue_cnt;
+	uchar               done_q_tail;
+
+	uchar               tid_no;
+	ASC_SCSI_BIT_ID_TYPE scsi_busy;
+	ASC_SCSI_BIT_ID_TYPE target_id;
+	PortAddr            iop_base;
+	ushort              q_addr;
+	ushort              sg_q_addr;
+	uchar               cur_target_qng;
+	ASC_QDONE_INFO      scsiq_buf;
+	ASC_QDONE_INFO dosfar *scsiq;
+	int                 false_overrun;
+	ASC_ISR_CALLBACK    asc_isr_callback;
+
+	uchar               tag_code;
+
+#if CC_LINK_BUSY_Q
+	ushort              n_busy_q_done;
+
+#endif
+
+	iop_base = asc_dvc->iop_base;
+	asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+
+	n_q_used = 1;
+	scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
+	done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
+	q_addr = ASC_QNO_TO_QADDR(done_q_tail);
+	next_qp = AscReadLramByte(iop_base,
+							  (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
+	if (next_qp != ASC_QLINK_END) {
+
+		AscPutVarDoneQTail(iop_base, next_qp);
+		q_addr = ASC_QNO_TO_QADDR(next_qp);
+
+		sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
+
+		AscWriteLramByte(iop_base,
+						 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+			 (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
+		tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
+		target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
+		if ((scsiq->cntl & QC_SG_HEAD) != 0) {
+			sg_q_addr = q_addr;
+			sg_list_qp = next_qp;
+			for (i = 0; i < sg_queue_cnt; i++) {
+				sg_list_qp = AscReadLramByte(iop_base,
+						   (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
+				sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
+				if (sg_list_qp == ASC_QLINK_END) {
+					AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
+					scsiq->d3.done_stat = QD_WITH_ERROR;
+					scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
+					goto FATAL_ERR_QDONE;
+				}
+				AscWriteLramByte(iop_base,
+						 (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+								 QS_FREE);
+			}
+
+			n_q_used = sg_queue_cnt + 1;
+			AscPutVarDoneQTail(iop_base, sg_list_qp);
+		}
+		if (asc_dvc->queue_full_or_busy & target_id) {
+
+			cur_target_qng = AscReadLramByte(iop_base,
+			(ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
+			if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
+				scsi_busy = AscReadLramByte(iop_base,
+											(ushort) ASCV_SCSIBUSY_B);
+				scsi_busy &= ~target_id;
+				AscWriteLramByte(iop_base,
+								 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+				asc_dvc->queue_full_or_busy &= ~target_id;
+			}
+		}
+		if (asc_dvc->cur_total_qng >= n_q_used) {
+			asc_dvc->cur_total_qng -= n_q_used;
+			if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
+				asc_dvc->cur_dvc_qng[tid_no]--;
+			}
+		} else {
+			AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
+			scsiq->d3.done_stat = QD_WITH_ERROR;
+			goto FATAL_ERR_QDONE;
+		}
+
+		if ((scsiq->d2.srb_ptr == 0UL) ||
+			((scsiq->q_status & QS_ABORTED) != 0)) {
+
+			return (0x11);
+		} else if (scsiq->q_status == QS_DONE) {
+
+			false_overrun = FALSE;
+
+			if (asc_dvc->bug_fix_cntl) {
+				if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
+					tag_code = AscReadLramByte(iop_base,
+						 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
+					if (tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) {
+						if (scsiq->remain_bytes != 0UL) {
+							scsiq->remain_bytes--;
+							if (scsiq->remain_bytes == 0UL) {
+								false_overrun = TRUE;
+							}
+						}
+					}
+				}
+			}
+			if ((scsiq->d3.done_stat == QD_WITH_ERROR) &&
+				(scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) {
+				if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
+					scsiq->d3.done_stat = QD_NO_ERROR;
+					scsiq->d3.host_stat = QHSTA_NO_ERROR;
+				} else if (false_overrun) {
+					scsiq->d3.done_stat = QD_NO_ERROR;
+					scsiq->d3.host_stat = QHSTA_NO_ERROR;
+				}
+			}
+#if CC_CLEAR_LRAM_SRB_PTR
+			AscWriteLramDWord(iop_base,
+							(ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
+							  asc_dvc->int_count);
+#endif
+
+			if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
+				(*asc_isr_callback) (asc_dvc, scsiq);
+			} else {
+				if ((AscReadLramByte(iop_base,
+						  (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
+					 SCSICMD_StartStopUnit)) {
+
+					asc_dvc->unit_not_ready &= ~target_id;
+					if (scsiq->d3.done_stat != QD_NO_ERROR) {
+						asc_dvc->start_motor &= ~target_id;
+					}
+				}
+			}
+
+#if CC_LINK_BUSY_Q
+			n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, tid_no);
+			if (n_busy_q_done == 0) {
+
+				i = tid_no + 1;
+				while (TRUE) {
+					if (i > ASC_MAX_TID)
+						i = 0;
+					if (i == tid_no)
+						break;
+					n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, i);
+					if (n_busy_q_done != 0)
+						break;
+					i++;
+				}
+			}
+			if (n_busy_q_done == 0xFFFF)
+				return (0x80);
+#endif
+
+			return (1);
+		} else {
+
+			AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
+
+		  FATAL_ERR_QDONE:
+			if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
+				(*asc_isr_callback) (asc_dvc, scsiq);
+			}
+			return (0x80);
+		}
+	}
+	return (0);
+}
+
+int
+AscISR(
+		  ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	ASC_CS_TYPE         chipstat;
+	PortAddr            iop_base;
+	ushort              saved_ram_addr;
+	uchar               ctrl_reg;
+	uchar               saved_ctrl_reg;
+	int                 int_pending;
+	int                 status;
+	uchar               host_flag;
+
+	iop_base = asc_dvc->iop_base;
+	int_pending = FALSE;
+
+	asc_dvc->int_count++;
+
+	if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) ||
+		(asc_dvc->isr_callback == 0)) {
+
+		return (ERR);
+	}
+	if (asc_dvc->in_critical_cnt != 0) {
+		AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
+		return (ERR);
+	}
+	if (asc_dvc->is_in_int) {
+		AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
+		asc_dvc->busy_count++;
+		return (ERR);
+	}
+	asc_dvc->is_in_int = TRUE;
+	ctrl_reg = AscGetChipControl(iop_base);
+	saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
+								   CC_SINGLE_STEP | CC_DIAG | CC_TEST));
+
+	if ((chipstat = AscGetChipStatus(iop_base)) & CSW_INT_PENDING) {
+		int_pending = TRUE;
+		AscAckInterrupt(iop_base);
+
+		host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
+		AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
+						 (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
+		saved_ram_addr = AscGetChipLramAddr(iop_base);
+
+		if ((chipstat & CSW_HALTED) &&
+			(ctrl_reg & CC_SINGLE_STEP)) {
+			if (AscIsrChipHalted(asc_dvc) == ERR) {
+
+				goto ISR_REPORT_QDONE_FATAL_ERROR;
+
+			} else {
+				saved_ctrl_reg &= ~CC_HALT;
+			}
+		} else {
+		  ISR_REPORT_QDONE_FATAL_ERROR:
+			if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
+				while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
+
+				}
+			} else {
+				do {
+					if ((status = AscIsrQDone(asc_dvc)) == 1) {
+
+						break;
+					}
+				} while (status == 0x11);
+			}
+			if ((status & 0x80) != 0)
+				int_pending = ERR;
+		}
+		AscSetChipLramAddr(iop_base, saved_ram_addr);
+		if (AscGetChipLramAddr(iop_base) != saved_ram_addr) {
+			AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SET_LRAM_ADDR);
+		}
+		AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
+	}
+	AscSetChipControl(iop_base, saved_ctrl_reg);
+	asc_dvc->is_in_int = FALSE;
+	return (int_pending);
+}
+
+int
+AscScsiSetupCmdQ(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					ASC_SCSI_REQ_Q dosfar * scsiq,
+					uchar dosfar * buf_addr,
+					ulong buf_len
+)
+{
+	ulong               phy_addr;
+
+	scsiq->r1.cntl = 0;
+	scsiq->r1.sg_queue_cnt = 0;
+	scsiq->r1.q_no = 0;
+	scsiq->r1.user_def = 0;
+	scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
+	scsiq->r3.scsi_stat = 0;
+	scsiq->r3.scsi_msg = 0;
+	scsiq->r3.host_stat = 0;
+	scsiq->r3.done_stat = 0;
+	scsiq->r2.vm_id = 0;
+	scsiq->r1.data_cnt = buf_len;
+
+	scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
+	scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
+	scsiq->r2.srb_ptr = (ulong) scsiq;
+	scsiq->r1.status = (uchar) QS_READY;
+	scsiq->r1.data_addr = 0L;
+
+	if (buf_len != 0L) {
+		if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+					(uchar dosfar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
+			return (ERR);
+		}
+		scsiq->r1.data_addr = phy_addr;
+	}
+	return (0);
+}
+
+uchar               _mcode_buf[] =
+{
+	0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xDD, 0x0A, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x23, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+	0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x88, 0x00, 0x00, 0x00, 0x00,
+	0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC8, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
+	0xB6, 0x00, 0x36, 0x00, 0x06, 0xD6, 0x0D, 0xD2, 0x15, 0xDE, 0x12, 0xDA, 0x00, 0xA2, 0xC8, 0x00,
+	0x92, 0x80, 0xE0, 0x97, 0x50, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00,
+	0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
+	0x80, 0x62, 0x92, 0x80, 0x00, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01,
+	0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDC, 0x00, 0x68, 0x97, 0x7F, 0x23, 0x04, 0x61,
+	0x84, 0x01, 0xB2, 0x84, 0xCF, 0xC1, 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE8, 0x01,
+	0x68, 0x97, 0xD4, 0x81, 0x00, 0x33, 0x02, 0x00, 0x82, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01,
+	0x01, 0xA1, 0x08, 0x01, 0x4F, 0x00, 0x46, 0x97, 0x07, 0xA6, 0x12, 0x01, 0x00, 0x33, 0x03, 0x00,
+	0x82, 0x88, 0x03, 0x03, 0x03, 0xDE, 0x00, 0x33, 0x05, 0x00, 0x82, 0x88, 0xCE, 0x00, 0x69, 0x60,
+	0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x86, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x32, 0x01,
+	0x86, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x42, 0x01, 0x00, 0x33, 0x04, 0x00,
+	0x82, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x2A, 0x98, 0x4D, 0x04, 0xD0, 0x84,
+	0x05, 0xD8, 0x0D, 0x23, 0x2A, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xB8, 0x88, 0xFB, 0x23, 0x02, 0x61,
+	0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x70, 0x01, 0x00, 0x33, 0x0A, 0x00, 0x82, 0x88,
+	0x4E, 0x00, 0x07, 0xA3, 0x7C, 0x01, 0x00, 0x33, 0x0B, 0x00, 0x82, 0x88, 0xCD, 0x04, 0x36, 0x2D,
+	0x00, 0x33, 0x1A, 0x00, 0x82, 0x88, 0x50, 0x04, 0x96, 0x81, 0x06, 0xAB, 0x90, 0x01, 0x96, 0x81,
+	0x4E, 0x00, 0x07, 0xA3, 0xA0, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x4A, 0x01, 0x00, 0x05, 0x8A, 0x81,
+	0x08, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xCC, 0x81,
+	0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xC2, 0x01,
+	0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0x82, 0x88, 0x06, 0x23, 0x2A, 0x98,
+	0xCD, 0x04, 0xB2, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xE2, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE8, 0x01,
+	0xB2, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xB2, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2,
+	0x10, 0x02, 0x04, 0x01, 0x0D, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x46, 0x97, 0x0A, 0x82,
+	0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x24, 0x97, 0x48, 0x04, 0xFF, 0x23, 0x84, 0x80,
+	0xB2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
+	0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x66, 0xEB, 0x11, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0xFA, 0x80,
+	0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x3E, 0x02, 0x00, 0x33, 0x31, 0x00, 0x82, 0x88, 0x04, 0x01,
+	0x03, 0xD8, 0x74, 0x98, 0x02, 0x96, 0x50, 0x82, 0xA2, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
+	0xB6, 0x2D, 0x02, 0xA6, 0x7A, 0x02, 0x07, 0xA6, 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x03, 0xA6,
+	0x70, 0x02, 0x00, 0x33, 0x10, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x52, 0x82, 0xF8, 0x95, 0x52, 0x82,
+	0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x16, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23,
+	0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23,
+	0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAC, 0x02, 0x07, 0xA6,
+	0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x12, 0x00, 0x82, 0x88, 0x00, 0x0E, 0x80, 0x63,
+	0x00, 0x43, 0x00, 0xA0, 0x9A, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61,
+	0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
+	0xEC, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE4, 0x02, 0x04, 0x01, 0x8E, 0xC8, 0x00, 0x33,
+	0x1F, 0x00, 0x82, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x40, 0x98, 0xB6, 0x2D,
+	0x01, 0xA6, 0x0E, 0x03, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x2A, 0x03, 0x06, 0xA6, 0x2E, 0x03,
+	0x03, 0xA6, 0xFA, 0x03, 0x02, 0xA6, 0x7A, 0x02, 0x00, 0x33, 0x33, 0x00, 0x82, 0x88, 0x08, 0x23,
+	0xB3, 0x01, 0x04, 0x01, 0x0E, 0xD0, 0x00, 0x33, 0x14, 0x00, 0x82, 0x88, 0x10, 0x23, 0xB3, 0x01,
+	0x04, 0x01, 0x07, 0xCC, 0x00, 0x33, 0x15, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xF0, 0x82, 0xF8, 0x95,
+	0xF0, 0x82, 0x44, 0x98, 0x80, 0x42, 0x40, 0x98, 0x48, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05,
+	0x07, 0x01, 0x00, 0xA2, 0x72, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x48, 0x98, 0x40, 0x98,
+	0x00, 0xA6, 0x34, 0x03, 0x07, 0xA6, 0x6A, 0x03, 0x03, 0xA6, 0x16, 0x04, 0x06, 0xA6, 0x6E, 0x03,
+	0x01, 0xA6, 0x34, 0x03, 0x00, 0x33, 0x25, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x50, 0x83, 0xF8, 0x95,
+	0x50, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0x82, 0x88, 0x00, 0x01,
+	0x05, 0x05, 0xFF, 0xA2, 0x90, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x4C, 0x83, 0x05, 0x05,
+	0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0xAA, 0x03, 0xF0, 0x83, 0x68, 0x98, 0x80, 0x42, 0x01, 0xA6,
+	0x9A, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x2F, 0x00, 0x82, 0x88, 0x68, 0x98, 0x80, 0x42, 0x00, 0xA6,
+	0xAA, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x26, 0x00, 0x82, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36,
+	0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0xF0, 0x83, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33,
+	0x20, 0x00, 0x82, 0x88, 0x03, 0xA6, 0xEE, 0x03, 0x07, 0xA6, 0xE6, 0x03, 0x06, 0xA6, 0xEA, 0x03,
+	0x00, 0x33, 0x17, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xD4, 0x83, 0xF8, 0x95, 0xD4, 0x83, 0xFA, 0x83,
+	0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0x82, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x16, 0x04,
+	0x07, 0xA6, 0x0E, 0x04, 0x06, 0xA6, 0x12, 0x04, 0x00, 0x33, 0x30, 0x00, 0x82, 0x88, 0x4A, 0x95,
+	0xFA, 0x83, 0xF8, 0x95, 0xFA, 0x83, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x24, 0x04, 0x00, 0x33,
+	0x18, 0x00, 0x82, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x2E, 0x04, 0x23, 0x01,
+	0x00, 0xA2, 0x50, 0x04, 0x0A, 0xA0, 0x40, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0x82, 0x88,
+	0x0B, 0xA0, 0x4C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0x82, 0x88, 0x42, 0x23, 0xB8, 0x88,
+	0x00, 0x23, 0x22, 0xA3, 0xB2, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x6C, 0x04, 0x28, 0x23, 0x22, 0xA3,
+	0x78, 0x04, 0x02, 0x23, 0x22, 0xA3, 0x8E, 0x04, 0x42, 0x23, 0xB8, 0x88, 0x4A, 0x00, 0x06, 0x61,
+	0x00, 0xA0, 0x78, 0x04, 0x45, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0x00, 0xA2, 0x8A, 0x04, 0x74, 0x98,
+	0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF6, 0x81, 0x47, 0x23, 0xB8, 0x88, 0x04, 0x01,
+	0x0C, 0xDE, 0x14, 0x01, 0x00, 0xA2, 0xA6, 0x04, 0xC6, 0x97, 0x74, 0x98, 0x00, 0x33, 0x00, 0x81,
+	0xC0, 0x20, 0x81, 0x62, 0x10, 0x82, 0x43, 0x23, 0xB8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23,
+	0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xC0, 0x04, 0x00, 0x33, 0x27, 0x00, 0x82, 0x88,
+	0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xC6, 0x97, 0xF4, 0x94,
+	0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0xEE, 0x04, 0x00, 0x05, 0x76, 0x00,
+	0x06, 0x61, 0x00, 0xA2, 0xE8, 0x04, 0xD6, 0x84, 0x08, 0x97, 0xCD, 0x04, 0xF2, 0x84, 0x48, 0x04,
+	0xFF, 0x23, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x02, 0x85, 0x02, 0x23,
+	0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 0x05, 0x1D, 0x01, 0x04, 0xD6, 0xFF, 0x23,
+	0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, 0x04, 0x01,
+	0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00,
+	0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x2E, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00,
+	0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xA0, 0x05, 0x03, 0x03,
+	0x02, 0xA0, 0x5C, 0x05, 0x9C, 0x85, 0x00, 0x33, 0x2D, 0x00, 0x82, 0x88, 0x04, 0xA0, 0x82, 0x05,
+	0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x6E, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23,
+	0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x24, 0x97, 0xD0, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01,
+	0xD0, 0x84, 0x08, 0xA0, 0x88, 0x05, 0x9C, 0x85, 0x03, 0xA0, 0x8E, 0x05, 0x9C, 0x85, 0x01, 0xA0,
+	0x9A, 0x05, 0x88, 0x00, 0x80, 0x63, 0x78, 0x96, 0x4A, 0x85, 0x88, 0x86, 0x80, 0x63, 0x4A, 0x85,
+	0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xDE, 0x05, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23,
+	0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xC0, 0x05, 0x00, 0x33, 0x37, 0x00, 0x82, 0x88,
+	0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xB8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
+	0xD8, 0x05, 0x00, 0x33, 0x38, 0x00, 0x82, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00,
+	0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xF2, 0x05, 0xC0, 0x23, 0x07, 0x41,
+	0x00, 0x63, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63,
+	0x00, 0x63, 0x06, 0xA6, 0x14, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x02, 0xA6, 0xBC, 0x06, 0x00, 0x33,
+	0x39, 0x00, 0x82, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xD6, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
+	0x06, 0xA6, 0x28, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
+	0x01, 0x00, 0x06, 0xA6, 0x40, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3A, 0x00, 0x82, 0x88,
+	0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x32, 0x06, 0x06, 0xA6, 0x58, 0x06, 0x07, 0xA6,
+	0x64, 0x06, 0x00, 0x33, 0x3B, 0x00, 0x82, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6,
+	0x64, 0x06, 0x00, 0x63, 0x03, 0x03, 0x80, 0x63, 0x88, 0x00, 0x01, 0xA2, 0x78, 0x06, 0x07, 0xA2,
+	0xBC, 0x06, 0x00, 0x33, 0x35, 0x00, 0x82, 0x88, 0x07, 0xA6, 0x82, 0x06, 0x00, 0x33, 0x2A, 0x00,
+	0x82, 0x88, 0x03, 0x03, 0x03, 0xA2, 0x8E, 0x06, 0x07, 0x23, 0x80, 0x00, 0xC8, 0x86, 0x80, 0x63,
+	0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0x9E, 0x06, 0x00, 0x33, 0x29, 0x00, 0x82, 0x88, 0x00, 0x43,
+	0x00, 0xA2, 0xAA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0x94, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80,
+	0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x00, 0x63, 0x80, 0x67, 0x00, 0x33,
+	0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x20, 0x06,
+	0x00, 0x33, 0x2C, 0x00, 0x82, 0x88, 0x0C, 0xA2, 0xF0, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
+	0x06, 0xA6, 0xEE, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3D, 0x00, 0x82, 0x88, 0x00, 0x00,
+	0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x06, 0x07, 0x07, 0xA6, 0x64, 0x06, 0xBF, 0x23,
+	0x04, 0x61, 0x84, 0x01, 0xB2, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01,
+	0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05,
+	0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00,
+	0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00,
+	0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00,
+	0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04,
+	0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01,
+	0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0x86, 0x07,
+	0x00, 0x33, 0x07, 0x00, 0x82, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00,
+	0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2,
+	0xA6, 0x07, 0x00, 0x05, 0x9C, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05,
+	0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08,
+	0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02,
+	0x00, 0xA0, 0xD6, 0x07, 0xD8, 0x87, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
+	0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2,
+	0x06, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0xE6, 0x07,
+	0xC6, 0x97, 0xF4, 0x94, 0xE6, 0x87, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x1C, 0x88,
+	0x02, 0x01, 0x04, 0xD8, 0x08, 0x97, 0xC6, 0x97, 0xF4, 0x94, 0x0C, 0x88, 0x75, 0x00, 0x00, 0xA3,
+	0x26, 0x08, 0x00, 0x05, 0x10, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
+	0x38, 0x08, 0x00, 0x33, 0x3E, 0x00, 0x82, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63,
+	0x38, 0x2B, 0x5E, 0x88, 0x38, 0x2B, 0x54, 0x88, 0x32, 0x09, 0x31, 0x05, 0x54, 0x98, 0x05, 0x05,
+	0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32,
+	0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A,
+	0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0x74, 0x08, 0x5D, 0x00, 0xFE, 0xC3,
+	0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
+	0x13, 0x23, 0xB8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01,
+	0x81, 0x62, 0xA2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2,
+	0xF1, 0xC7, 0x41, 0x23, 0xB8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xB2, 0x84,
+
+};
+
+ushort              _mcode_size = sizeof (_mcode_buf);
+ulong               _mcode_chksum = 0x012258FBUL;
+
+extern uchar        _sdtr_period_tbl_[];
+
+int
+AscExeScsiQueue(
+				   ASC_DVC_VAR asc_ptr_type * asc_dvc,
+				   ASC_SCSI_Q dosfar * scsiq
+)
+{
+	PortAddr            iop_base;
+	int                 last_int_level;
+	int                 sta;
+	ulong               addr;
+	uchar               sg_entry_cnt;
+	uchar               target_ix;
+	int                 n_q_required;
+	uchar               sg_entry_cnt_minus_one;
+	uchar               tid_no;
+	uchar               sdtr_data;
+	ASC_EXE_CALLBACK    asc_exe_callback;
+
+#if CC_DEBUG_SG_LIST
+	int                 i;
+
+#endif
+#if CC_LINK_BUSY_Q
+	ASC_SCSI_Q dosfar  *scsiq_tail;
+	ASC_SCSI_Q dosfar  *scsiq_next;
+	ASC_SCSI_Q dosfar  *scsiq_prev;
+
+#endif
+
+	iop_base = asc_dvc->iop_base;
+	asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
+	if (asc_dvc->err_code != 0)
+		return (ERR);
+	if (scsiq == (ASC_SCSI_Q dosfar *) 0L) {
+		AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
+		return (ERR);
+	}
+	scsiq->q1.q_no = 0;
+	sta = 0;
+	target_ix = scsiq->q2.target_ix;
+	tid_no = ASC_TIX_TO_TID(target_ix);
+
+	n_q_required = 1;
+
+	if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
+
+		if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
+			((asc_dvc->sdtr_done & scsiq->q1.target_id) != 0)) {
+			sdtr_data = AscReadLramByte(iop_base,
+				  (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
+			AscMsgOutSDTR(iop_base,
+						  _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
+						  (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
+			scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
+		}
+	}
+	last_int_level = DvcEnterCritical();
+	if (asc_dvc->in_critical_cnt != 0) {
+		DvcLeaveCritical(last_int_level);
+		AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
+		return (ERR);
+	}
+	asc_dvc->in_critical_cnt++;
+
+	if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
+
+		if ((sg_entry_cnt = scsiq->sg_head->entry_cnt) == 0) {
+			asc_dvc->in_critical_cnt--;
+			DvcLeaveCritical(last_int_level);
+			return (ERR);
+		}
+		if (sg_entry_cnt == 1) {
+			scsiq->q1.data_addr = scsiq->sg_head->sg_list[0].addr;
+			scsiq->q1.data_cnt = scsiq->sg_head->sg_list[0].bytes;
+			scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
+			goto NON_SG_LIST_REQ;
+		}
+		if (sg_entry_cnt > ASC_MAX_SG_LIST) {
+
+			return (ERR);
+		}
+		sg_entry_cnt_minus_one = sg_entry_cnt - 1;
+
+#if CC_DEBUG_SG_LIST
+		if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
+			for (i = 0; i < sg_entry_cnt_minus_one; i++) {
+
+				addr = scsiq->sg_head->sg_list[i].addr +
+				  scsiq->sg_head->sg_list[i].bytes;
+
+				if (((ushort) addr & 0x0003) != 0) {
+					asc_dvc->in_critical_cnt--;
+					DvcLeaveCritical(last_int_level);
+					AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_LIST_ODD_ADDRESS);
+					return (ERR);
+				}
+			}
+		}
+#endif
+
+		if (asc_dvc->bug_fix_cntl) {
+			if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
+
+				addr = scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr +
+				  scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
+				if (((ushort) addr & 0x0003) != 0) {
+					if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
+						(scsiq->cdbptr[0] == SCSICMD_Read10)) {
+						if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
+
+							scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes++;
+							scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
+						}
+					}
+				}
+			}
+		}
+		scsiq->sg_head->entry_to_copy = scsiq->sg_head->entry_cnt;
+		n_q_required = AscSgListToQueue(sg_entry_cnt);
+
+#if CC_LINK_BUSY_Q
+		scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
+		if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
+			goto link_scisq_to_busy_list;
+		}
+#endif
+
+		if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required)
+			 >= (uint) n_q_required) ||
+			((scsiq->q1.cntl & QC_URGENT) != 0)) {
+			if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
+										n_q_required)) == 1) {
+
+				asc_dvc->in_critical_cnt--;
+				if (asc_exe_callback != 0) {
+					(*asc_exe_callback) (asc_dvc, scsiq);
+				}
+				DvcLeaveCritical(last_int_level);
+				return (sta);
+			}
+		}
+	} else {
+
+	  NON_SG_LIST_REQ:
+
+		if (asc_dvc->bug_fix_cntl) {
+			if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
+
+				addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
+				if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
+					(scsiq->cdbptr[0] == SCSICMD_Read10)) {
+					if (((ushort) addr & 0x0003) != 0) {
+						if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
+
+							if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
+
+								scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
+								scsiq->q1.data_cnt++;
+							}
+						}
+					}
+				}
+			}
+		}
+		n_q_required = 1;
+
+#if CC_LINK_BUSY_Q
+		scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
+		if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
+			goto link_scisq_to_busy_list;
+		}
+#endif
+		if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
+			((scsiq->q1.cntl & QC_URGENT) != 0)) {
+			if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
+										n_q_required)) == 1) {
+
+				asc_dvc->in_critical_cnt--;
+				if (asc_exe_callback != 0) {
+					(*asc_exe_callback) (asc_dvc, scsiq);
+				}
+				DvcLeaveCritical(last_int_level);
+				return (sta);
+			}
+		}
+	}
+
+#if CC_LINK_BUSY_Q
+	if (sta == 0) {
+
+	  link_scisq_to_busy_list:
+		scsiq->ext.q_required = n_q_required;
+		if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
+			asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+			asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+			scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
+			scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+			scsiq->q1.status = QS_BUSY;
+			sta = 1;
+		} else {
+			scsiq_tail = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_tail[tid_no];
+			if (scsiq_tail->ext.next == (ASC_SCSI_Q dosfar *) 0L) {
+				if ((scsiq->q1.cntl & QC_URGENT) != 0) {
+
+					asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+					scsiq->ext.next = scsiq_next;
+					scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+				} else {
+					if (scsiq->ext.cntl & QCX_SORT) {
+						do {
+							scsiq_prev = scsiq_next;
+							scsiq_next = scsiq_next->ext.next;
+							if (scsiq->ext.lba < scsiq_prev->ext.lba)
+								break;
+						} while (scsiq_next != (ASC_SCSI_Q dosfar *) 0L);
+
+						scsiq_prev->ext.next = scsiq;
+						scsiq->ext.next = scsiq_next;
+						if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
+							asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+						}
+						scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+					} else {
+
+						scsiq_tail->ext.next = (ASC_SCSI_Q dosfar *) scsiq;
+						asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+						scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
+						scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+					}
+				}
+				scsiq->q1.status = QS_BUSY;
+				sta = 1;
+			} else {
+
+				AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_BAD_NEXT_PTR);
+				sta = ERR;
+			}
+		}
+	}
+#endif
+	asc_dvc->in_critical_cnt--;
+	DvcLeaveCritical(last_int_level);
+	return (sta);
+}
+
+int
+AscSendScsiQueue(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					ASC_SCSI_Q dosfar * scsiq,
+					uchar n_q_required
+)
+{
+	PortAddr            iop_base;
+	uchar               free_q_head;
+	uchar               next_qp;
+	uchar               tid_no;
+	uchar               target_ix;
+	int                 sta;
+
+	iop_base = asc_dvc->iop_base;
+	target_ix = scsiq->q2.target_ix;
+	tid_no = ASC_TIX_TO_TID(target_ix);
+	sta = 0;
+	free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
+	if (n_q_required > 1) {
+		if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
+									   free_q_head, (uchar) (n_q_required)))
+			!= (uchar) ASC_QLINK_END) {
+			asc_dvc->last_q_shortage = 0;
+			scsiq->sg_head->queue_cnt = n_q_required - 1;
+			scsiq->q1.q_no = free_q_head;
+
+			if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
+											  free_q_head)) == 1) {
+
+#if CC_WRITE_IO_COUNT
+				asc_dvc->req_count++;
+#endif
+
+				AscPutVarFreeQHead(iop_base, next_qp);
+				asc_dvc->cur_total_qng += (uchar) (n_q_required);
+				asc_dvc->cur_dvc_qng[tid_no]++;
+			}
+			return (sta);
+		}
+	} else if (n_q_required == 1) {
+
+		if ((next_qp = AscAllocFreeQueue(iop_base,
+										 free_q_head)) != ASC_QLINK_END) {
+
+			scsiq->q1.q_no = free_q_head;
+			if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
+										free_q_head)) == 1) {
+
+#if CC_WRITE_IO_COUNT
+				asc_dvc->req_count++;
+#endif
+
+				AscPutVarFreeQHead(iop_base, next_qp);
+				asc_dvc->cur_total_qng++;
+				asc_dvc->cur_dvc_qng[tid_no]++;
+			}
+			return (sta);
+		}
+	}
+	return (sta);
+}
+
+int
+AscSgListToQueue(
+					int sg_list
+)
+{
+	int                 n_sg_list_qs;
+
+	n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
+	if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
+		n_sg_list_qs++;
+	return (n_sg_list_qs + 1);
+}
+
+uint
+AscGetNumOfFreeQueue(
+						ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						uchar target_ix, uchar n_qs
+)
+{
+	uint                cur_used_qs;
+	uint                cur_free_qs;
+	ASC_SCSI_BIT_ID_TYPE target_id;
+	uchar               tid_no;
+
+	target_id = ASC_TIX_TO_TARGET_ID(target_ix);
+	tid_no = ASC_TIX_TO_TID(target_ix);
+	if ((asc_dvc->unit_not_ready & target_id) ||
+		(asc_dvc->queue_full_or_busy & target_id)) {
+		return (0);
+	}
+	if (n_qs == 1) {
+		cur_used_qs = (uint) asc_dvc->cur_total_qng +
+		  (uint) asc_dvc->last_q_shortage +
+		  (uint) ASC_MIN_FREE_Q;
+	} else {
+		cur_used_qs = (uint) asc_dvc->cur_total_qng +
+		  (uint) ASC_MIN_FREE_Q;
+	}
+
+	if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
+		cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
+		if (asc_dvc->cur_dvc_qng[tid_no] >=
+			asc_dvc->max_dvc_qng[tid_no]) {
+			return (0);
+		}
+		return (cur_free_qs);
+	}
+	if (n_qs > 1) {
+		if (n_qs > asc_dvc->last_q_shortage) {
+			asc_dvc->last_q_shortage = n_qs;
+		}
+	}
+	return (0);
+}
+
+int
+AscPutReadyQueue(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					ASC_SCSI_Q dosfar * scsiq,
+					uchar q_no
+)
+{
+	ushort              q_addr;
+	uchar               tid_no;
+	uchar               sdtr_data;
+	uchar               syn_period_ix;
+	uchar               syn_offset;
+	PortAddr            iop_base;
+
+	iop_base = asc_dvc->iop_base;
+
+	if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
+		((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
+
+		tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
+
+		sdtr_data = AscReadLramByte(iop_base,
+				  (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
+		syn_period_ix = (sdtr_data >> 4) & (ASC_SYN_XFER_NO - 1);
+		syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
+		AscMsgOutSDTR(iop_base,
+					  _sdtr_period_tbl_[syn_period_ix],
+					  syn_offset);
+
+		scsiq->q1.cntl |= QC_MSG_OUT;
+	}
+	q_addr = ASC_QNO_TO_QADDR(q_no);
+
+	if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
+		scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
+	}
+	scsiq->q1.status = QS_FREE;
+
+	AscMemWordCopyToLram(iop_base,
+						 (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
+						 (ushort dosfar *) scsiq->cdbptr,
+						 (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
+
+#if !CC_LITTLE_ENDIAN_HOST
+	AscAdjEndianScsiQ(scsiq);
+#endif
+
+	DvcPutScsiQ(iop_base,
+				(ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
+				(ushort dosfar *) & scsiq->q1.cntl,
+	  (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
+
+#if CC_WRITE_IO_COUNT
+	AscWriteLramWord(iop_base,
+					 (ushort) (q_addr + (ushort) ASC_SCSIQ_W_REQ_COUNT),
+					 (ushort) asc_dvc->req_count);
+
+#endif
+
+#if CC_VERIFY_LRAM_COPY
+	if ((asc_dvc->dvc_cntl & ASC_CNTL_NO_VERIFY_COPY) == 0) {
+
+		if (AscMemWordCmpToLram(iop_base,
+							 (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
+								(ushort dosfar *) scsiq->cdbptr,
+								(ushort) (scsiq->q2.cdb_len >> 1)) != 0) {
+			AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
+			return (ERR);
+		}
+		if (AscMemWordCmpToLram(iop_base,
+							 (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
+								(ushort dosfar *) & scsiq->q1.cntl,
+		 (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))
+			!= 0) {
+			AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
+			return (ERR);
+		}
+	}
+#endif
+
+#if CC_CLEAR_DMA_REMAIN
+
+	AscWriteLramDWord(iop_base,
+		   (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_ADDR), 0UL);
+	AscWriteLramDWord(iop_base,
+			(ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT), 0UL);
+
+#endif
+
+	AscWriteLramWord(iop_base,
+					 (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+			 (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
+	return (1);
+}
+
+int
+AscPutReadySgListQueue(
+						  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						  ASC_SCSI_Q dosfar * scsiq,
+						  uchar q_no
+)
+{
+	uchar               sg_list_dwords;
+	uchar               sg_index, i;
+	uchar               sg_entry_cnt;
+	uchar               next_qp;
+	ushort              q_addr;
+	int                 sta;
+	ASC_SG_HEAD dosfar *sg_head;
+	ASC_SG_LIST_Q       scsi_sg_q;
+	ulong               saved_data_addr;
+	ulong               saved_data_cnt;
+	PortAddr            iop_base;
+
+	iop_base = asc_dvc->iop_base;
+
+	sg_head = scsiq->sg_head;
+
+	saved_data_addr = scsiq->q1.data_addr;
+	saved_data_cnt = scsiq->q1.data_cnt;
+	scsiq->q1.data_addr = sg_head->sg_list[0].addr;
+	scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
+	sg_entry_cnt = sg_head->entry_cnt - 1;
+	if (sg_entry_cnt != 0) {
+		scsiq->q1.cntl |= QC_SG_HEAD;
+		q_addr = ASC_QNO_TO_QADDR(q_no);
+		sg_index = 1;
+		scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
+		scsi_sg_q.sg_head_qp = q_no;
+		scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
+		for (i = 0; i < sg_head->queue_cnt; i++) {
+			scsi_sg_q.seq_no = i + 1;
+			if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
+				sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
+				sg_entry_cnt -= ASC_SG_LIST_PER_Q;
+				if (i == 0) {
+					scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
+					scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
+				} else {
+					scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
+					scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
+				}
+			} else {
+
+				scsi_sg_q.cntl |= QCSG_SG_XFER_END;
+				sg_list_dwords = sg_entry_cnt << 1;
+				if (i == 0) {
+					scsi_sg_q.sg_list_cnt = sg_entry_cnt;
+					scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
+				} else {
+					scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
+					scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
+				}
+				sg_entry_cnt = 0;
+			}
+			next_qp = AscReadLramByte(iop_base,
+									  (ushort) (q_addr + ASC_SCSIQ_B_FWD));
+			scsi_sg_q.q_no = next_qp;
+			q_addr = ASC_QNO_TO_QADDR(next_qp);
+
+			AscMemWordCopyToLram(iop_base,
+								 (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
+								 (ushort dosfar *) & scsi_sg_q,
+								 (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
+
+			AscMemDWordCopyToLram(iop_base,
+								  (ushort) (q_addr + ASC_SGQ_LIST_BEG),
+							  (ulong dosfar *) & sg_head->sg_list[sg_index],
+								  (ushort) sg_list_dwords);
+
+			sg_index += ASC_SG_LIST_PER_Q;
+		}
+	} else {
+
+		scsiq->q1.cntl &= ~QC_SG_HEAD;
+	}
+	sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
+
+	scsiq->q1.data_addr = saved_data_addr;
+	scsiq->q1.data_cnt = saved_data_cnt;
+	return (sta);
+}
+
+int
+AscAbortSRB(
+			   ASC_DVC_VAR asc_ptr_type * asc_dvc,
+			   ulong srb_ptr
+)
+{
+	int                 sta;
+	ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
+	PortAddr            iop_base;
+
+	iop_base = asc_dvc->iop_base;
+	sta = ERR;
+	saved_unit_not_ready = asc_dvc->unit_not_ready;
+	asc_dvc->unit_not_ready = 0xFF;
+	AscWaitISRDone(asc_dvc);
+	if (AscStopQueueExe(iop_base) == 1) {
+		if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
+			sta = 1;
+			AscCleanUpBusyQueue(iop_base);
+			AscStartQueueExe(iop_base);
+
+		} else {
+			sta = 0;
+			AscStartQueueExe(iop_base);
+		}
+	}
+	asc_dvc->unit_not_ready = saved_unit_not_ready;
+	return (sta);
+}
+
+int
+AscResetDevice(
+				  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+				  uchar target_ix
+)
+{
+	PortAddr            iop_base;
+	int                 sta;
+	uchar               tid_no;
+	ASC_SCSI_BIT_ID_TYPE target_id;
+	int                 i;
+	ASC_SCSI_REQ_Q      scsiq_buf;
+	ASC_SCSI_REQ_Q dosfar *scsiq;
+	uchar dosfar       *buf;
+	ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
+
+	iop_base = asc_dvc->iop_base;
+	tid_no = ASC_TIX_TO_TID(target_ix);
+	target_id = ASC_TID_TO_TARGET_ID(tid_no);
+	saved_unit_not_ready = asc_dvc->unit_not_ready;
+	asc_dvc->unit_not_ready = target_id;
+	sta = ERR;
+	AscWaitTixISRDone(asc_dvc, target_ix);
+	if (AscStopQueueExe(iop_base) == 1) {
+		if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
+
+			AscCleanUpBusyQueue(iop_base);
+			AscStartQueueExe(iop_base);
+
+			AscWaitTixISRDone(asc_dvc, target_ix);
+
+			sta = TRUE;
+			scsiq = (ASC_SCSI_REQ_Q dosfar *) & scsiq_buf;
+			buf = (uchar dosfar *) & scsiq_buf;
+			for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
+				*buf++ = 0x00;
+			}
+
+			scsiq->r1.status = (uchar) QS_READY;
+			scsiq->r2.cdb_len = 6;
+			scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
+			scsiq->r1.target_id = target_id;
+
+			scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
+			scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
+
+			scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
+			AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
+							 M1_BUS_DVC_RESET);
+
+			asc_dvc->unit_not_ready &= ~target_id;
+
+			asc_dvc->sdtr_done |= target_id;
+
+			if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q dosfar *) scsiq)
+				== 1) {
+				asc_dvc->unit_not_ready = target_id;
+				DvcSleepMilliSecond(1000);
+				_AscWaitQDone(iop_base, (ASC_SCSI_Q dosfar *) scsiq);
+				if (AscStopQueueExe(iop_base) == 1) {
+
+					AscCleanUpDiscQueue(iop_base);
+					AscStartQueueExe(iop_base);
+					if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+
+						AscSetRunChipSynRegAtID(iop_base, tid_no,
+											 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+					}
+					AscWaitTixISRDone(asc_dvc, target_ix);
+				}
+			} else {
+
+				sta = 0;
+			}
+
+			asc_dvc->sdtr_done &= ~target_id;
+		} else {
+			sta = ERR;
+			AscStartQueueExe(iop_base);
+		}
+	}
+	asc_dvc->unit_not_ready = saved_unit_not_ready;
+	return (sta);
+}
+
+int
+AscResetSB(
+			  ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	int                 sta;
+	int                 i;
+	PortAddr            iop_base;
+
+	iop_base = asc_dvc->iop_base;
+	asc_dvc->unit_not_ready = 0xFF;
+	sta = TRUE;
+	AscWaitISRDone(asc_dvc);
+	AscStopQueueExe(iop_base);
+
+	asc_dvc->sdtr_done = 0;
+	AscResetChipAndScsiBus(iop_base);
+
+	DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+
+#if CC_SCAM
+	if (!(asc_dvc->dvc_cntl & ASC_CNTL_NO_SCAM)) {
+		AscSCAM(asc_dvc);
+	}
+#endif
+	AscReInitLram(asc_dvc);
+
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		asc_dvc->cur_dvc_qng[i] = 0;
+		if (asc_dvc->pci_fix_asyn_xfer & (0x01 << i)) {
+
+			AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+		}
+	}
+
+	asc_dvc->err_code = 0;
+
+	AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
+	if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
+		sta = ERR;
+	}
+	if (AscStartChip(iop_base) == 0) {
+		sta = ERR;
+	}
+	AscStartQueueExe(iop_base);
+	asc_dvc->unit_not_ready = 0;
+	asc_dvc->queue_full_or_busy = 0;
+	return (sta);
+}
+
+int
+AscSetRunChipSynRegAtID(
+						   PortAddr iop_base,
+						   uchar tid_no,
+						   uchar sdtr_data
+)
+{
+	int                 sta = FALSE;
+
+	if (AscHostReqRiscHalt(iop_base)) {
+		sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
+
+		AscStartChip(iop_base);
+		return (sta);
+	}
+	return (sta);
+}
+
+int
+AscSetChipSynRegAtID(
+						PortAddr iop_base,
+						uchar id,
+						uchar sdtr_data
+)
+{
+	AscSetBank(iop_base, 1);
+	AscWriteChipScsiID(iop_base, id);
+	if (AscReadChipScsiID(iop_base) != (0x01 << id)) {
+		return (FALSE);
+	}
+	AscSetBank(iop_base, 0);
+	AscWriteChipSyn(iop_base, sdtr_data);
+	if (AscReadChipSyn(iop_base) != sdtr_data) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+int
+AscReInitLram(
+				 ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	AscInitLram(asc_dvc);
+	AscInitQLinkVar(asc_dvc);
+	return (0);
+}
+
+ushort
+AscInitLram(
+			   ASC_DVC_VAR asc_ptr_type * asc_dvc)
+{
+	uchar               i;
+	ushort              s_addr;
+	PortAddr            iop_base;
+	ushort              warn_code;
+
+	iop_base = asc_dvc->iop_base;
+	warn_code = 0;
+
+	AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
+			   (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
+	  );
+
+	i = ASC_MIN_ACTIVE_QNO;
+	s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
+
+	AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
+					 (uchar) (i + 1));
+	AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
+					 (uchar) (asc_dvc->max_total_qng));
+	AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
+					 (uchar) i);
+	i++;
+	s_addr += ASC_QBLK_SIZE;
+	for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
+		AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
+						 (uchar) (i + 1));
+		AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
+						 (uchar) (i - 1));
+		AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
+						 (uchar) i);
+	}
+
+	AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
+					 (uchar) ASC_QLINK_END);
+	AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
+					 (uchar) (asc_dvc->max_total_qng - 1));
+	AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
+					 (uchar) asc_dvc->max_total_qng);
+	i++;
+	s_addr += ASC_QBLK_SIZE;
+
+	for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
+		 i++, s_addr += ASC_QBLK_SIZE) {
+
+		AscWriteLramByte(iop_base,
+						 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
+		AscWriteLramByte(iop_base,
+						 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
+		AscWriteLramByte(iop_base,
+						 (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
+	}
+
+	return (warn_code);
+}
+
+ushort
+AscInitQLinkVar(
+				   ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	PortAddr            iop_base;
+	int                 i;
+	ushort              lram_addr;
+
+	iop_base = asc_dvc->iop_base;
+	AscPutRiscVarFreeQHead(iop_base, 1);
+	AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
+
+	AscPutVarFreeQHead(iop_base, 1);
+	AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
+
+	AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
+					 (uchar) ((int) asc_dvc->max_total_qng + 1));
+	AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
+					 (uchar) ((int) asc_dvc->max_total_qng + 2));
+
+	AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
+					 asc_dvc->max_total_qng);
+
+	AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
+	AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+	AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
+	AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
+	AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
+
+	AscWriteLramByte(iop_base, (ushort) ASCV_CDBCNT_B, 0);
+
+	lram_addr = ASC_QADR_BEG;
+	for (i = 0; i < 32; i++, lram_addr += 2) {
+		AscWriteLramWord(iop_base, lram_addr, 0);
+	}
+
+	return (0);
+}
+
+int
+AscSetLibErrorCode(
+					  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					  ushort err_code
+)
+{
+	if (asc_dvc->err_code == 0) {
+
+		asc_dvc->err_code = err_code;
+		AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
+						 err_code);
+	}
+	return (err_code);
+}
+
+int
+_AscWaitQDone(
+				 PortAddr iop_base,
+				 ASC_SCSI_Q dosfar * scsiq
+)
+{
+	ushort              q_addr;
+	uchar               q_status;
+	int                 count = 0;
+
+	while (scsiq->q1.q_no == 0) ;
+	q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
+
+	do {
+		q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
+		DvcSleepMilliSecond(100L);
+		if (count++ > 30) {
+			return (0);
+		}
+	} while ((q_status & QS_READY) != 0);
+	return (1);
+}
+
+uchar               _sdtr_period_tbl_[ASC_SYN_XFER_NO] =
+{
+	SYN_XFER_NS_0,
+	SYN_XFER_NS_1,
+	SYN_XFER_NS_2,
+	SYN_XFER_NS_3,
+	SYN_XFER_NS_4,
+	SYN_XFER_NS_5,
+	SYN_XFER_NS_6,
+	SYN_XFER_NS_7};
+
+uchar
+AscMsgOutSDTR(
+				 PortAddr iop_base,
+				 uchar sdtr_period,
+				 uchar sdtr_offset
+)
+{
+	SDTR_XMSG           sdtr_buf;
+	uchar               sdtr_period_index;
+
+	sdtr_buf.msg_type = MS_EXTEND;
+	sdtr_buf.msg_len = MS_SDTR_LEN;
+	sdtr_buf.msg_req = MS_SDTR_CODE;
+	sdtr_buf.xfer_period = sdtr_period;
+	sdtr_offset &= ASC_SYN_MAX_OFFSET;
+	sdtr_buf.req_ack_offset = sdtr_offset;
+	AscMemWordCopyToLram(iop_base, ASCV_MSGOUT_BEG,
+						 (ushort dosfar *) & sdtr_buf, SYN_XMSG_WLEN);
+	if ((sdtr_period_index = AscGetSynPeriodIndex(sdtr_period)) <=
+		ASC_MAX_SDTR_PERIOD_INDEX) {
+		return ((sdtr_period_index << 4) | sdtr_offset);
+	} else {
+
+		return (0);
+	}
+}
+
+uchar
+AscCalSDTRData(
+				  uchar sdtr_period,
+				  uchar syn_offset
+)
+{
+	uchar               byte;
+	uchar               sdtr_period_ix;
+
+	sdtr_period_ix = AscGetSynPeriodIndex(sdtr_period);
+	if ((sdtr_period_ix > ASC_MAX_SDTR_PERIOD_INDEX) ||
+		(sdtr_period_ix > ASC_SDTR_PERIOD_IX_MIN)) {
+		return (0xFF);
+	}
+	byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
+	return (byte);
+}
+
+void
+AscSetChipSDTR(
+				  PortAddr iop_base,
+				  uchar sdtr_data,
+				  uchar tid_no
+)
+{
+
+	AscWriteChipSyn(iop_base, sdtr_data);
+	AscWriteLramByte(iop_base,
+				   (ushort) ((ushort) ASCV_SDTR_DONE_BEG + (ushort) tid_no),
+					 sdtr_data);
+	return;
+}
+
+uchar
+AscGetSynPeriodIndex(
+						uchar syn_time
+)
+{
+	if ((syn_time >= SYN_XFER_NS_0) && (syn_time <= SYN_XFER_NS_7)) {
+		if (syn_time <= SYN_XFER_NS_6) {
+			if (syn_time <= SYN_XFER_NS_5) {
+				if (syn_time <= SYN_XFER_NS_4) {
+					if (syn_time <= SYN_XFER_NS_3) {
+						if (syn_time <= SYN_XFER_NS_2) {
+							if (syn_time <= SYN_XFER_NS_1) {
+								if (syn_time <= SYN_XFER_NS_0) {
+									return (0);
+								} else
+									return (1);
+							} else {
+								return (2);
+							}
+						} else {
+							return (3);
+						}
+					} else {
+						return (4);
+					}
+				} else {
+					return (5);
+				}
+			} else {
+				return (6);
+			}
+		} else {
+			return (7);
+		}
+	} else {
+
+		return (8);
+	}
+}
+
+uchar
+AscAllocFreeQueue(
+					 PortAddr iop_base,
+					 uchar free_q_head
+)
+{
+	ushort              q_addr;
+	uchar               next_qp;
+	uchar               q_status;
+
+	q_addr = ASC_QNO_TO_QADDR(free_q_head);
+	q_status = (uchar) AscReadLramByte(iop_base,
+									(ushort) (q_addr + ASC_SCSIQ_B_STATUS));
+	next_qp = AscReadLramByte(iop_base,
+							  (ushort) (q_addr + ASC_SCSIQ_B_FWD));
+	if (((q_status & QS_READY) == 0) &&
+		(next_qp != ASC_QLINK_END)) {
+		return (next_qp);
+	}
+	return (ASC_QLINK_END);
+}
+
+uchar
+AscAllocMultipleFreeQueue(
+							 PortAddr iop_base,
+							 uchar free_q_head,
+							 uchar n_free_q
+)
+{
+	uchar               i;
+
+	for (i = 0; i < n_free_q; i++) {
+		if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
+			== ASC_QLINK_END) {
+			return (ASC_QLINK_END);
+		}
+	}
+	return (free_q_head);
+}
+
+int
+AscRiscHaltedAbortSRB(
+						 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						 ulong srb_ptr
+)
+{
+	PortAddr            iop_base;
+	ushort              q_addr;
+	uchar               q_no;
+	ASC_QDONE_INFO      scsiq_buf;
+	ASC_QDONE_INFO dosfar *scsiq;
+	ASC_ISR_CALLBACK    asc_isr_callback;
+	int                 last_int_level;
+
+	iop_base = asc_dvc->iop_base;
+	asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+	last_int_level = DvcEnterCritical();
+	scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
+
+#if CC_LINK_BUSY_Q
+	_AscAbortSrbBusyQueue(asc_dvc, scsiq, srb_ptr);
+#endif
+
+	for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
+		 q_no++) {
+		q_addr = ASC_QNO_TO_QADDR(q_no);
+		scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
+						   (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
+		if (scsiq->d2.srb_ptr == srb_ptr) {
+			_AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
+			if (((scsiq->q_status & QS_READY) != 0) &&
+				((scsiq->q_status & QS_ABORTED) == 0) &&
+				((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
+
+				scsiq->q_status |= QS_ABORTED;
+				scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
+				AscWriteLramDWord(iop_base,
+							(ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
+								  0L);
+				AscWriteLramByte(iop_base,
+							(ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+								 scsiq->q_status);
+				(*asc_isr_callback) (asc_dvc, scsiq);
+				return (1);
+			}
+		}
+	}
+	DvcLeaveCritical(last_int_level);
+	return (0);
+}
+
+int
+AscRiscHaltedAbortTIX(
+						 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						 uchar target_ix
+)
+{
+	PortAddr            iop_base;
+	ushort              q_addr;
+	uchar               q_no;
+	ASC_QDONE_INFO      scsiq_buf;
+	ASC_QDONE_INFO dosfar *scsiq;
+	ASC_ISR_CALLBACK    asc_isr_callback;
+	int                 last_int_level;
+
+#if CC_LINK_BUSY_Q
+	uchar               tid_no;
+
+#endif
+
+	iop_base = asc_dvc->iop_base;
+	asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+	last_int_level = DvcEnterCritical();
+	scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
+
+#if CC_LINK_BUSY_Q
+
+	tid_no = ASC_TIX_TO_TID(target_ix);
+	_AscAbortTidBusyQueue(asc_dvc, scsiq, tid_no);
+
+#endif
+
+	for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
+		 q_no++) {
+		q_addr = ASC_QNO_TO_QADDR(q_no);
+		_AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
+		if (((scsiq->q_status & QS_READY) != 0) &&
+			((scsiq->q_status & QS_ABORTED) == 0) &&
+			((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
+			if (scsiq->d2.target_ix == target_ix) {
+				scsiq->q_status |= QS_ABORTED;
+				scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
+
+				AscWriteLramDWord(iop_base,
+							(ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
+								  0L);
+
+				AscWriteLramByte(iop_base,
+							(ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+								 scsiq->q_status);
+				(*asc_isr_callback) (asc_dvc, scsiq);
+			}
+		}
+	}
+	DvcLeaveCritical(last_int_level);
+	return (1);
+}
+
+#if CC_LINK_BUSY_Q
+
+#endif
+
+int
+AscHostReqRiscHalt(
+					  PortAddr iop_base
+)
+{
+	int                 count = 0;
+	int                 sta = 0;
+	uchar               saved_stop_code;
+
+	if (AscIsChipHalted(iop_base))
+		return (1);
+	saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
+
+	AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+					 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
+	  );
+	do {
+		if (AscIsChipHalted(iop_base)) {
+			sta = 1;
+			break;
+		}
+		DvcSleepMilliSecond(100);
+	} while (count++ < 20);
+
+	AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
+	return (sta);
+}
+
+int
+AscStopQueueExe(
+				   PortAddr iop_base
+)
+{
+	int                 count;
+
+	count = 0;
+	if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
+		AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+						 ASC_STOP_REQ_RISC_STOP);
+		do {
+			if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
+				ASC_STOP_ACK_RISC_STOP) {
+				return (1);
+			}
+			DvcSleepMilliSecond(100);
+		} while (count++ < 20);
+	}
+	return (0);
+}
+
+int
+AscStartQueueExe(
+					PortAddr iop_base
+)
+{
+	if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+		AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
+	}
+	return (1);
+}
+
+int
+AscCleanUpBusyQueue(
+					   PortAddr iop_base
+)
+{
+	int                 count;
+	uchar               stop_code;
+
+	count = 0;
+	if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+		AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+						 ASC_STOP_CLEAN_UP_BUSY_Q);
+		do {
+			stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
+			if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
+				break;
+			DvcSleepMilliSecond(100);
+		} while (count++ < 20);
+	}
+	return (1);
+}
+
+int
+AscCleanUpDiscQueue(
+					   PortAddr iop_base
+)
+{
+	int                 count;
+	uchar               stop_code;
+
+	count = 0;
+	if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+		AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+						 ASC_STOP_CLEAN_UP_DISC_Q);
+		do {
+			stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
+			if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
+				break;
+			DvcSleepMilliSecond(100);
+		} while (count++ < 20);
+	}
+	return (1);
+}
+
+int
+AscWaitTixISRDone(
+					 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					 uchar target_ix
+)
+{
+	uchar               cur_req;
+	uchar               tid_no;
+
+	tid_no = ASC_TIX_TO_TID(target_ix);
+	while (TRUE) {
+		if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
+			break;
+		}
+		DvcSleepMilliSecond(1000L);
+		if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
+			break;
+		}
+	}
+	return (1);
+}
+
+int
+AscWaitISRDone(
+				  ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	int                 tid;
+
+	for (tid = 0; tid <= ASC_MAX_TID; tid++) {
+		AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
+	}
+	return (1);
+}
+
+ulong
+AscGetOnePhyAddr(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					uchar dosfar * buf_addr,
+					ulong buf_size
+)
+{
+	ASC_MIN_SG_HEAD     sg_head;
+
+	sg_head.entry_cnt = ASC_MIN_SG_LIST;
+	if (DvcGetSGList(asc_dvc, (uchar dosfar *) buf_addr,
+				  buf_size, (ASC_SG_HEAD dosfar *) & sg_head) != buf_size) {
+		return (0L);
+	}
+	if (sg_head.entry_cnt > 1) {
+		return (0L);
+	}
+	return (sg_head.sg_list[0].addr);
+}
+
+ulong
+AscGetEisaProductID(
+					   PortAddr iop_base
+)
+{
+	PortAddr            eisa_iop;
+	ushort              product_id_high, product_id_low;
+	ulong               product_id;
+
+	eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
+	product_id_low = inpw(eisa_iop);
+	product_id_high = inpw(eisa_iop + 2);
+	product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
+	return (product_id);
+}
+
+PortAddr
+AscSearchIOPortAddrEISA(
+						   PortAddr iop_base
+)
+{
+	ulong               eisa_product_id;
+
+	if (iop_base == 0) {
+		iop_base = ASC_EISA_MIN_IOP_ADDR;
+	} else {
+		if (iop_base == ASC_EISA_MAX_IOP_ADDR)
+			return (0);
+		if ((iop_base & 0x0050) == 0x0050) {
+			iop_base += ASC_EISA_BIG_IOP_GAP;
+		} else {
+			iop_base += ASC_EISA_SMALL_IOP_GAP;
+		}
+	}
+	while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
+
+		eisa_product_id = AscGetEisaProductID(iop_base);
+		if ((eisa_product_id == ASC_EISA_ID_740) ||
+			(eisa_product_id == ASC_EISA_ID_750)) {
+			if (AscFindSignature(iop_base)) {
+
+				inpw(iop_base + 4);
+				return (iop_base);
+			}
+		}
+		if (iop_base == ASC_EISA_MAX_IOP_ADDR)
+			return (0);
+		if ((iop_base & 0x0050) == 0x0050) {
+			iop_base += ASC_EISA_BIG_IOP_GAP;
+		} else {
+			iop_base += ASC_EISA_SMALL_IOP_GAP;
+		}
+	}
+	return (0);
+}
+
+int
+AscStartChip(
+				PortAddr iop_base
+)
+{
+	AscSetChipControl(iop_base, 0);
+	if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+		return (0);
+	}
+	return (1);
+}
+
+int
+AscStopChip(
+			   PortAddr iop_base
+)
+{
+	uchar               cc_val;
+
+	cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
+	AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
+	AscSetChipIH(iop_base, INS_HALT);
+	AscSetChipIH(iop_base, INS_RFLAG_WTM);
+	if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
+		return (0);
+	}
+	return (1);
+}
+
+int
+AscIsChipHalted(
+				   PortAddr iop_base
+)
+{
+
+	if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+		if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+void
+AscSetChipIH(
+				PortAddr iop_base,
+				ushort ins_code
+)
+{
+	AscSetBank(iop_base, 1);
+	AscWriteChipIH(iop_base, ins_code);
+	AscSetBank(iop_base, 0);
+	return;
+}
+
+void
+AscAckInterrupt(
+				   PortAddr iop_base
+)
+{
+
+	uchar               host_flag;
+	uchar               risc_flag;
+	ushort              loop;
+
+	loop = 0;
+	do {
+		risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
+		if (loop++ > 0x7FFF) {
+			break;
+		}
+	} while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
+
+	host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
+	AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
+					 (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
+
+	AscSetChipStatus(iop_base, CIW_INT_ACK);
+	loop = 0;
+	while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
+
+		AscSetChipStatus(iop_base, CIW_INT_ACK);
+		if (loop++ > 3) {
+			break;
+		}
+	}
+
+	AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
+	return;
+}
+
+void
+AscDisableInterrupt(
+					   PortAddr iop_base
+)
+{
+	ushort              cfg;
+
+	cfg = AscGetChipCfgLsw(iop_base);
+	AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
+	return;
+}
+
+void
+AscEnableInterrupt(
+					  PortAddr iop_base
+)
+{
+	ushort              cfg;
+
+	cfg = AscGetChipCfgLsw(iop_base);
+	AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
+	return;
+}
+
+void
+AscSetBank(
+			  PortAddr iop_base,
+			  uchar bank
+)
+{
+	uchar               val;
+
+	val = AscGetChipControl(iop_base) &
+	  (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
+	if (bank == 1) {
+		val |= CC_BANK_ONE;
+	} else if (bank == 2) {
+		val |= CC_DIAG | CC_BANK_ONE;
+	} else {
+		val &= ~CC_BANK_ONE;
+	}
+	AscSetChipControl(iop_base, val);
+	return;
+}
+
+int
+AscResetChipAndScsiBus(
+						  PortAddr iop_base
+)
+{
+	AscStopChip(iop_base);
+	AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
+	DvcSleepMilliSecond(200);
+
+	AscSetChipIH(iop_base, INS_RFLAG_WTM);
+	AscSetChipIH(iop_base, INS_HALT);
+
+	AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
+	AscSetChipControl(iop_base, CC_HALT);
+	DvcSleepMilliSecond(200);
+	return (AscIsChipHalted(iop_base));
+}
+
+ushort
+AscGetIsaDmaChannel(
+					   PortAddr iop_base
+)
+{
+	ushort              channel;
+
+	channel = AscGetChipCfgLsw(iop_base) & 0x0003;
+	if (channel == 0x03)
+		return (0);
+	else if (channel == 0x00)
+		return (7);
+	return (channel + 4);
+}
+
+ushort
+AscSetIsaDmaChannel(
+					   PortAddr iop_base,
+					   ushort dma_channel
+)
+{
+	ushort              cfg_lsw;
+	uchar               value;
+
+	if ((dma_channel >= 5) && (dma_channel <= 7)) {
+
+		if (dma_channel == 7)
+			value = 0x00;
+		else
+			value = dma_channel - 4;
+		cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
+		cfg_lsw |= value;
+		AscSetChipCfgLsw(iop_base, cfg_lsw);
+		return (AscGetIsaDmaChannel(iop_base));
+	}
+	return (0);
+}
+
+uchar
+AscSetIsaDmaSpeed(
+					 PortAddr iop_base,
+					 uchar speed_value
+)
+{
+	speed_value &= 0x07;
+	AscSetBank(iop_base, 1);
+	AscSetChipDmaSpeed(iop_base, speed_value);
+	AscSetBank(iop_base, 0);
+	return (AscGetIsaDmaSpeed(iop_base));
+}
+
+uchar
+AscGetIsaDmaSpeed(
+					 PortAddr iop_base
+)
+{
+	uchar               speed_value;
+
+	AscSetBank(iop_base, 1);
+	speed_value = AscGetChipDmaSpeed(iop_base);
+	speed_value &= 0x07;
+	AscSetBank(iop_base, 0);
+	return (speed_value);
+}
+
+ulong
+AscGetMaxDmaCount(
+					 ushort bus_type
+)
+{
+	if (bus_type & ASC_IS_ISA)
+		return (ASC_MAX_ISA_DMA_COUNT);
+	else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
+		return (ASC_MAX_VL_DMA_COUNT);
+	return (ASC_MAX_PCI_DMA_COUNT);
+}
+
+ushort
+AscInitGetConfig(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	ushort              warn_code;
+
+	warn_code = 0;
+	asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
+	if (asc_dvc->err_code != 0)
+		return (UW_ERR);
+	if (AscFindSignature(asc_dvc->iop_base)) {
+		warn_code |= AscInitAscDvcVar(asc_dvc);
+		warn_code |= AscInitFromEEP(asc_dvc);
+		asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
+
+		if (asc_dvc->scsi_reset_wait > 10)
+			asc_dvc->scsi_reset_wait = 10;
+
+	} else {
+		asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+	}
+	return (warn_code);
+}
+
+ushort
+AscInitSetConfig(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	ushort              warn_code;
+
+	warn_code = 0;
+	asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
+	if (asc_dvc->err_code != 0)
+		return (UW_ERR);
+	if (AscFindSignature(asc_dvc->iop_base)) {
+		warn_code |= AscInitFromAscDvcVar(asc_dvc);
+		asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
+	} else {
+		asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+	}
+	return (warn_code);
+}
+
+ushort
+AscInitAsc1000Driver(
+						ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	ushort              warn_code;
+	PortAddr            iop_base;
+
+	extern ushort       _mcode_size;
+	extern ulong        _mcode_chksum;
+	extern uchar        _mcode_buf[];
+
+	ASC_DBG(3, "AscInitAsc1000Driver: begin\n");
+	iop_base = asc_dvc->iop_base;
+	warn_code = 0;
+
+	if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
+		!(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
+
+		ASC_DBG(3, "AscInitAsc1000Driver: AscResetChipAndScsiBus()\n");
+		AscResetChipAndScsiBus(iop_base);
+		DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+	}
+	asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
+	if (asc_dvc->err_code != 0)
+		return (UW_ERR);
+	ASC_DBG(3, "AscInitAsc1000Driver: AscFindSignature()\n");
+	if (!AscFindSignature(asc_dvc->iop_base)) {
+		asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+		return (warn_code);
+	}
+	ASC_DBG(3, "AscInitAsc1000Driver: AscDisableInterrupt()\n");
+	AscDisableInterrupt(iop_base);
+
+	ASC_DBG(3, "AscInitAsc1000Driver: AscInitLram()\n");
+	warn_code |= AscInitLram(asc_dvc);
+	if (asc_dvc->err_code != 0)
+		return (UW_ERR);
+	ASC_DBG(3, "AscInitAsc1000Driver: AscLoadMicroCode()\n");
+	if (AscLoadMicroCode(iop_base, 0, (ushort dosfar *) _mcode_buf,
+						 _mcode_size) != _mcode_chksum) {
+		asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+		return (warn_code);
+	}
+	ASC_DBG(3, "AscInitAsc1000Driver: AscInitMicroCodeVar()\n");
+	warn_code |= AscInitMicroCodeVar(asc_dvc);
+	asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
+	ASC_DBG(3, "AscInitAsc1000Driver: AscEnableInterrupt()\n");
+	AscEnableInterrupt(iop_base);
+	return (warn_code);
+}
+
+ushort
+AscInitAscDvcVar(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	int                 i;
+	PortAddr            iop_base;
+	ushort              warn_code;
+
+	iop_base = asc_dvc->iop_base;
+	warn_code = 0;
+	asc_dvc->err_code = 0;
+
+	if ((asc_dvc->bus_type &
+		 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
+		asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
+	}
+#if CC_LINK_BUSY_Q
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
+		asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
+	}
+#endif
+
+	asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
+	asc_dvc->bug_fix_cntl = 0;
+	asc_dvc->pci_fix_asyn_xfer = 0;
+	asc_dvc->init_sdtr = 0;
+	asc_dvc->sdtr_done = 0;
+	asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
+	asc_dvc->cur_total_qng = 0;
+	asc_dvc->is_in_int = 0;
+	asc_dvc->scsi_reset_wait = 3;
+	asc_dvc->in_critical_cnt = 0;
+
+	asc_dvc->last_q_shortage = 0;
+	asc_dvc->use_tagged_qng = 0;
+	asc_dvc->cfg->can_tagged_qng = 0;
+	asc_dvc->no_scam = 0;
+	asc_dvc->irq_no = 10;
+	asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
+	asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
+	asc_dvc->cfg->cmd_qng_enabled = ASC_SCSI_WIDTH_BIT_SET;
+	asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
+	asc_dvc->cfg->chip_version = AscGetChipVersion(iop_base,
+												   asc_dvc->bus_type);
+	if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
+
+		AscPutChipIFC(iop_base, IFC_INIT_DEFAULT);
+		asc_dvc->bus_type = ASC_IS_ISAPNP;
+	}
+	asc_dvc->unit_not_ready = 0;
+	asc_dvc->queue_full_or_busy = 0;
+
+	if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
+		asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
+		asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
+	}
+	asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
+	asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
+	  ASC_LIB_VERSION_MINOR;
+	asc_dvc->int_count = 0L;
+	asc_dvc->req_count = 0L;
+	asc_dvc->busy_count = 0L;
+	asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
+
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		asc_dvc->cfg->sdtr_data[i] =
+		  (uchar) (ASC_DEF_SDTR_OFFSET | (ASC_DEF_SDTR_INDEX << 4));
+		asc_dvc->cur_dvc_qng[i] = 0;
+		asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
+		asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
+		asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
+	}
+	return (warn_code);
+}
+
+ushort
+AscInitFromAscDvcVar(
+						ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	PortAddr            iop_base;
+	ushort              cfg_msw;
+	ushort              warn_code;
+
+	iop_base = asc_dvc->iop_base;
+	warn_code = 0;
+
+	cfg_msw = AscGetChipCfgMsw(iop_base);
+
+	if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
+		cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
+		warn_code |= ASC_WARN_CFG_MSW_RECOVER;
+		AscSetChipCfgMsw(iop_base, cfg_msw);
+	}
+	if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
+		warn_code |= ASC_WARN_AUTO_CONFIG;
+
+	}
+	if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
+		asc_dvc->cfg->cmd_qng_enabled) {
+		asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
+		warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
+	}
+	if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
+
+		if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
+			!= asc_dvc->irq_no) {
+			asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
+		}
+	}
+	if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
+		asc_dvc->cfg->chip_scsi_id) {
+		asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
+	}
+	if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
+		AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
+		AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
+	}
+	return (warn_code);
+}
+
+ushort
+AscInitFromEEP(
+				  ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	ASCEEP_CONFIG       eep_config_buf;
+	ASCEEP_CONFIG dosfar *eep_config;
+	PortAddr            iop_base;
+	ushort              chksum;
+	ushort              warn_code;
+	ushort              cfg_msw, cfg_lsw;
+	uchar               i;
+
+	iop_base = asc_dvc->iop_base;
+	warn_code = 0;
+
+	AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
+
+	AscStopQueueExe(iop_base);
+	if ((AscStopChip(iop_base) == FALSE) ||
+		(AscGetChipScsiCtrl(iop_base) != 0)) {
+		asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
+		AscResetChipAndScsiBus(iop_base);
+		DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+	}
+	if (AscIsChipHalted(iop_base) == FALSE) {
+		asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
+		return (warn_code);
+	}
+	AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
+	if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
+		asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
+		return (warn_code);
+	}
+	eep_config = (ASCEEP_CONFIG dosfar *) & eep_config_buf;
+
+	cfg_msw = AscGetChipCfgMsw(iop_base);
+	cfg_lsw = AscGetChipCfgLsw(iop_base);
+
+	if (asc_dvc->bus_type & ASC_IS_PCI) {
+#if CC_DISABLE_PCI_PARITY_INT
+		cfg_msw &= 0xFFC0;
+		AscSetChipCfgMsw(iop_base, cfg_msw);
+#endif
+		if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) {
+			asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE;
+		}
+	}
+	if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
+		cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
+		warn_code |= ASC_WARN_CFG_MSW_RECOVER;
+		AscSetChipCfgMsw(iop_base, cfg_msw);
+	}
+	chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
+
+	eep_config->cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
+
+	if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
+		warn_code |= ASC_WARN_AUTO_CONFIG;
+
+		if (asc_dvc->cfg->chip_version == 3) {
+
+			if (eep_config->cfg_lsw != cfg_lsw) {
+				warn_code |= ASC_WARN_EEPROM_RECOVER;
+				eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
+			}
+			if (eep_config->cfg_msw != cfg_msw) {
+				warn_code |= ASC_WARN_EEPROM_RECOVER;
+				eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+			}
+		}
+	}
+	eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
+	if (chksum != eep_config->chksum) {
+		warn_code |= ASC_WARN_EEPROM_CHKSUM;
+	}
+	asc_dvc->init_sdtr = eep_config->init_sdtr;
+	asc_dvc->cfg->disc_enable = eep_config->disc_enable;
+
+	asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
+	asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
+	asc_dvc->start_motor = eep_config->start_motor;
+	asc_dvc->dvc_cntl = eep_config->cntl;
+	asc_dvc->no_scam = eep_config->no_scam;
+
+	if ((asc_dvc->bus_type & ASC_IS_PCI) &&
+		!(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) {
+		if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
+			(asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
+			asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
+		}
+	} else if (asc_dvc->bus_type & ASC_IS_ISAPNP) {
+
+		if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
+			== ASC_CHIP_VER_ASYN_BUG) {
+			asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
+		}
+	}
+	if (!AscTestExternalLram(asc_dvc)) {
+		if (asc_dvc->bus_type & ASC_IS_PCI) {
+			eep_config->cfg_msw |= 0x0800;
+			cfg_msw |= 0x0800;
+			AscSetChipCfgMsw(iop_base, cfg_msw);
+			eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
+			eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
+		}
+	} else {
+#if CC_TEST_RW_LRAM
+		asc_dvc->err_code |= AscTestLramEndian(iop_base);
+#endif
+	}
+	if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
+		eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
+	}
+	if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
+		eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
+	}
+	if (eep_config->max_tag_qng > eep_config->max_total_qng) {
+		eep_config->max_tag_qng = eep_config->max_total_qng;
+	}
+	if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
+		eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
+	}
+	asc_dvc->max_total_qng = eep_config->max_total_qng;
+
+	if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
+		eep_config->use_cmd_qng) {
+		eep_config->disc_enable = eep_config->use_cmd_qng;
+		warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
+	}
+	asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
+	eep_config->chip_scsi_id &= ASC_MAX_TID;
+	asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
+
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		asc_dvc->cfg->sdtr_data[i] = eep_config->sdtr_data[i];
+		asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
+	}
+
+	eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+	if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) {
+		asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM;
+	}
+	return (warn_code);
+}
+
+ushort
+AscInitMicroCodeVar(
+					   ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	int                 i;
+	ushort              warn_code;
+	PortAddr            iop_base;
+	ulong               phy_addr;
+
+	iop_base = asc_dvc->iop_base;
+	warn_code = 0;
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		AscWriteLramByte(iop_base, (ushort) (ASCV_SDTR_DATA_BEG + i),
+						 asc_dvc->cfg->sdtr_data[i]);
+	}
+
+	AscInitQLinkVar(asc_dvc);
+
+	AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
+					 asc_dvc->cfg->disc_enable);
+	AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
+					 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
+	if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+								 (uchar dosfar *) asc_dvc->cfg->overrun_buf,
+									 ASC_OVERRUN_BSIZE)) == 0L) {
+		asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
+	} else {
+
+		phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
+		AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
+		AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
+						  ASC_OVERRUN_BSIZE - 8);
+	}
+
+	asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
+											   (ushort) ASCV_MC_DATE_W);
+	asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
+												  (ushort) ASCV_MC_VER_W);
+	AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
+	if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
+		asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
+		return (warn_code);
+	}
+	if (AscStartChip(iop_base) != 1) {
+		asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
+		return (warn_code);
+	}
+	return (warn_code);
+}
+
+void                dosfar
+AscInitPollIsrCallBack(
+						  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						  ASC_QDONE_INFO dosfar * scsi_done_q
+)
+{
+	ASC_SCSI_REQ_Q dosfar *scsiq_req;
+	ASC_ISR_CALLBACK    asc_isr_callback;
+	uchar               cp_sen_len;
+	uchar               i;
+
+	if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
+		scsiq_req = (ASC_SCSI_REQ_Q dosfar *) scsi_done_q->d2.srb_ptr;
+		ASC_DBG2(3, "AscInitPollIsrCallBack: done_stat %x, host_stat %x\n",
+				 scsiq_req->r3.done_stat, scsiq_req->r3.host_stat);
+		scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat;
+		scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
+		scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
+		scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
+		if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
+			(scsi_done_q->d3.host_stat == 0)) {
+			cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
+			if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) {
+				cp_sen_len = (uchar) scsiq_req->r1.sense_len;
+			}
+			for (i = 0; i < cp_sen_len; i++) {
+				scsiq_req->sense[i] = scsiq_req->sense_ptr[i];
+			}
+		}
+	} else {
+		ASC_DBG1(3, "AscInitPollIsrCallBack: isr_callback %x\n",
+				 (unsigned) asc_dvc->isr_callback);
+		if (asc_dvc->isr_callback != 0) {
+			asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+			(*asc_isr_callback) (asc_dvc, scsi_done_q);
+		}
+	}
+	return;
+}
+
+int
+AscTestExternalLram(
+					   ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	PortAddr            iop_base;
+	ushort              q_addr;
+	ushort              saved_word;
+	int                 sta;
+
+	iop_base = asc_dvc->iop_base;
+	sta = 0;
+
+	q_addr = ASC_QNO_TO_QADDR(241);
+	saved_word = AscReadLramWord(iop_base, q_addr);
+	if (AscVerWriteLramWord(iop_base, q_addr, 0x55AA) == 0) {
+		sta = 1;
+		AscWriteLramWord(iop_base, q_addr, saved_word);
+	}
+	return (sta);
+}
+
+#if CC_TEST_LRAM_ENDIAN
+
+#endif
+
+int
+AscWriteEEPCmdReg(
+					 PortAddr iop_base,
+					 uchar cmd_reg
+)
+{
+	uchar               read_back;
+	int                 retry;
+
+	retry = 0;
+	while (TRUE) {
+		AscSetChipEEPCmd(iop_base, cmd_reg);
+		DvcSleepMilliSecond(1);
+		read_back = AscGetChipEEPCmd(iop_base);
+		if (read_back == cmd_reg) {
+			return (1);
+		}
+		if (retry++ > ASC_EEP_MAX_RETRY) {
+			return (0);
+		}
+	}
+}
+
+int
+AscWriteEEPDataReg(
+					  PortAddr iop_base,
+					  ushort data_reg
+)
+{
+	ushort              read_back;
+	int                 retry;
+
+	retry = 0;
+	while (TRUE) {
+		AscSetChipEEPData(iop_base, data_reg);
+		DvcSleepMilliSecond(1);
+		read_back = AscGetChipEEPData(iop_base);
+		if (read_back == data_reg) {
+			return (1);
+		}
+		if (retry++ > ASC_EEP_MAX_RETRY) {
+			return (0);
+		}
+	}
+}
+
+void
+AscWaitEEPRead(
+				  void
+)
+{
+	DvcSleepMilliSecond(1);
+	return;
+}
+
+void
+AscWaitEEPWrite(
+				   void
+)
+{
+	DvcSleepMilliSecond(20);
+	return;
+}
+
+ushort
+AscReadEEPWord(
+				  PortAddr iop_base,
+				  uchar addr
+)
+{
+	ushort              read_wval;
+	uchar               cmd_reg;
+
+	AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
+	AscWaitEEPRead();
+	cmd_reg = addr | ASC_EEP_CMD_READ;
+	AscWriteEEPCmdReg(iop_base, cmd_reg);
+	AscWaitEEPRead();
+	read_wval = AscGetChipEEPData(iop_base);
+	AscWaitEEPRead();
+	return (read_wval);
+}
+
+ushort
+AscWriteEEPWord(
+				   PortAddr iop_base,
+				   uchar addr,
+				   ushort word_val
+)
+{
+	ushort              read_wval;
+
+	read_wval = AscReadEEPWord(iop_base, addr);
+	if (read_wval != word_val) {
+		AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
+		AscWaitEEPRead();
+
+		AscWriteEEPDataReg(iop_base, word_val);
+		AscWaitEEPRead();
+
+		AscWriteEEPCmdReg(iop_base,
+						  (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
+		AscWaitEEPWrite();
+
+		AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
+		AscWaitEEPRead();
+		return (AscReadEEPWord(iop_base, addr));
+	}
+	return (read_wval);
+}
+
+ushort
+AscGetEEPConfig(
+				   PortAddr iop_base,
+				   ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
+)
+{
+	ushort              wval;
+	ushort              sum;
+	ushort dosfar      *wbuf;
+	int                 cfg_beg;
+	int                 cfg_end;
+	int                 s_addr;
+	int                 isa_pnp_wsize;
+
+	wbuf = (ushort dosfar *) cfg_buf;
+	sum = 0;
+
+	isa_pnp_wsize = 0;
+	for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
+		wval = AscReadEEPWord(iop_base, (uchar) s_addr);
+		sum += wval;
+		*wbuf = wval;
+	}
+
+	if (bus_type & ASC_IS_VL) {
+		cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
+		cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
+	} else {
+		cfg_beg = ASC_EEP_DVC_CFG_BEG;
+		cfg_end = ASC_EEP_MAX_DVC_ADDR;
+	}
+
+	for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
+		 s_addr++, wbuf++) {
+		wval = AscReadEEPWord(iop_base, (uchar) s_addr);
+		sum += wval;
+		*wbuf = wval;
+	}
+	*wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
+	return (sum);
+}
+
+int
+AscSetEEPConfigOnce(
+					   PortAddr iop_base,
+					   ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
+)
+{
+	int                 n_error;
+	ushort dosfar      *wbuf;
+	ushort              sum;
+	int                 s_addr;
+	int                 cfg_beg;
+	int                 cfg_end;
+
+	wbuf = (ushort dosfar *) cfg_buf;
+	n_error = 0;
+	sum = 0;
+	for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+		sum += *wbuf;
+		if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
+			n_error++;
+		}
+	}
+	if (bus_type & ASC_IS_VL) {
+		cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
+		cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
+	} else {
+		cfg_beg = ASC_EEP_DVC_CFG_BEG;
+		cfg_end = ASC_EEP_MAX_DVC_ADDR;
+	}
+	for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
+		 s_addr++, wbuf++) {
+		sum += *wbuf;
+		if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
+			n_error++;
+		}
+	}
+	*wbuf = sum;
+	if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
+		n_error++;
+	}
+	wbuf = (ushort dosfar *) cfg_buf;
+	for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+		if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
+			n_error++;
+		}
+	}
+	for (s_addr = cfg_beg; s_addr <= cfg_end;
+		 s_addr++, wbuf++) {
+		if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
+			n_error++;
+		}
+	}
+	return (n_error);
+}
+
+int
+AscSetEEPConfig(
+				   PortAddr iop_base,
+				   ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
+)
+{
+	int                 retry;
+	int                 n_error;
+
+	retry = 0;
+	while (TRUE) {
+		if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
+										   bus_type)) == 0) {
+			break;
+		}
+		if (++retry > ASC_EEP_MAX_RETRY) {
+			break;
+		}
+	}
+	return (n_error);
+}
+
+int
+AscInitPollBegin(
+					ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	PortAddr            iop_base;
+
+	iop_base = asc_dvc->iop_base;
+
+#if CC_INIT_INQ_DISPLAY
+	DvcDisplayString((uchar dosfar *) "\r\n");
+#endif
+
+	AscDisableInterrupt(iop_base);
+
+	asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY;
+
+	AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00);
+	asc_dvc->use_tagged_qng = 0;
+	asc_dvc->cfg->can_tagged_qng = 0;
+	asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback;
+	asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack);
+	return (0);
+}
+
+int
+AscInitPollEnd(
+				  ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+	PortAddr            iop_base;
+	int                 i;
+
+	iop_base = asc_dvc->iop_base;
+	asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func;
+	AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
+					 asc_dvc->cfg->disc_enable);
+	AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B,
+					 asc_dvc->use_tagged_qng);
+	AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B,
+					 asc_dvc->cfg->can_tagged_qng);
+
+	for (i = 0; i <= ASC_MAX_TID; i++) {
+		AscWriteLramByte(iop_base,
+					  (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i),
+						 asc_dvc->max_dvc_qng[i]);
+	}
+
+	AscEnableInterrupt(iop_base);
+
+#if CC_INIT_INQ_DISPLAY
+	DvcDisplayString((uchar dosfar *) "\r\n");
+#endif
+	asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
+
+	return (0);
+}
+
+int                 _asc_wait_slow_device_ = FALSE;
+
+int
+AscInitPollTarget(
+					 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					 ASC_SCSI_REQ_Q dosfar * scsiq,
+					 ASC_SCSI_INQUIRY dosfar * inq,
+					 ASC_CAP_INFO dosfar * cap_info
+)
+{
+	uchar               tid_no, lun;
+	uchar               dvc_type;
+	ASC_SCSI_BIT_ID_TYPE tid_bits;
+	int                 dvc_found;
+	int                 support_read_cap;
+	int                 tmp_disable_init_sdtr;
+	ulong               phy_addr;
+
+	dvc_found = 0;
+	tmp_disable_init_sdtr = FALSE;
+	tid_bits = scsiq->r1.target_id;
+	lun = scsiq->r1.target_lun;
+	tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
+	if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+									 (uchar dosfar *) scsiq->sense_ptr,
+									 (ulong) scsiq->r1.sense_len)) == 0L) {
+		return (ERR);
+	}
+	scsiq->r1.sense_addr = phy_addr;
+	if (((asc_dvc->init_sdtr & tid_bits) != 0) &&
+		((asc_dvc->sdtr_done & tid_bits) == 0)) {
+
+		asc_dvc->init_sdtr &= ~tid_bits;
+		tmp_disable_init_sdtr = TRUE;
+	}
+	ASC_DBG(3, "AscInitPollTarget: PollScsiInquiry()\n");
+	if (PollScsiInquiry(asc_dvc, scsiq, (uchar dosfar *) inq,
+						sizeof (ASC_SCSI_INQUIRY)) == 1) {
+		dvc_found = 1;
+		support_read_cap = TRUE;
+		dvc_type = inq->byte0.peri_dvc_type;
+		if (dvc_type != SCSI_TYPE_UNKNOWN) {
+			if ((dvc_type != SCSI_TYPE_DASD) &&
+				(dvc_type != SCSI_TYPE_WORM) &&
+				(dvc_type != SCSI_TYPE_CDROM) &&
+				(dvc_type != SCSI_TYPE_OPTMEM)) {
+				asc_dvc->start_motor &= ~tid_bits;
+				support_read_cap = FALSE;
+			}
+			if ((dvc_type != SCSI_TYPE_DASD) ||
+				inq->byte1.rmb) {
+
+				if (!_asc_wait_slow_device_) {
+					DvcSleepMilliSecond(3000 - ((int) tid_no * 250));
+					_asc_wait_slow_device_ = TRUE;
+				}
+			}
+#if CC_INIT_INQ_DISPLAY
+			AscDispInquiry(tid_no, lun, inq);
+#endif
+
+			if (lun == 0) {
+
+				if ((inq->byte3.rsp_data_fmt >= 2) ||
+					(inq->byte2.ansi_apr_ver >= 2)) {
+
+					if (inq->byte7.CmdQue) {
+						asc_dvc->cfg->can_tagged_qng |= tid_bits;
+						if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) {
+							asc_dvc->use_tagged_qng |= tid_bits;
+							asc_dvc->max_dvc_qng[tid_no] =
+							  asc_dvc->cfg->max_tag_qng[tid_no];
+						}
+					}
+					if (!inq->byte7.Sync) {
+
+						asc_dvc->init_sdtr &= ~tid_bits;
+						asc_dvc->sdtr_done &= ~tid_bits;
+					} else if (tmp_disable_init_sdtr) {
+
+						asc_dvc->init_sdtr |= tid_bits;
+					}
+				} else {
+
+					asc_dvc->init_sdtr &= ~tid_bits;
+					asc_dvc->sdtr_done &= ~tid_bits;
+					asc_dvc->use_tagged_qng &= ~tid_bits;
+				}
+			}
+			if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
+				if (!(asc_dvc->init_sdtr & tid_bits)) {
+
+					AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
+											ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+				}
+			}
+			ASC_DBG(3, "AscInitPollTarget: InitTestUnitReady()\n");
+			if (InitTestUnitReady(asc_dvc, scsiq) != 1) {
+
+			} else {
+				if ((cap_info != 0L) && support_read_cap) {
+					ASC_DBG(3, "AscInitPollTarget: PollScsiReadCapacity()\n");
+					if (PollScsiReadCapacity(asc_dvc, scsiq,
+											 cap_info) != 1) {
+						cap_info->lba = 0L;
+						cap_info->blk_size = 0x0000;
+					} else {
+
+					}
+				}
+			}
+		} else {
+			asc_dvc->start_motor &= ~tid_bits;
+		}
+	} else {
+
+	}
+	return (dvc_found);
+}
+
+int
+PollQueueDone(
+				 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+				 ASC_SCSI_REQ_Q dosfar * scsiq,
+				 int timeout_sec
+)
+{
+	int                 status;
+	int                 retry;
+
+	retry = 0;
+	do {
+		ASC_DBG(3, "PollQueueDone: AscExeScsiQueue()\n");
+		if ((status = AscExeScsiQueue(asc_dvc,
+									  (ASC_SCSI_Q dosfar *) scsiq)) == 1) {
+			ASC_DBG(3, "PollQueueDone: AscPollQDone()\n");
+			if ((status = AscPollQDone(asc_dvc, scsiq,
+									   timeout_sec)) != 1) {
+				ASC_DBG1(3, "PollQueueDone: AscPollQDone() status %x\n", status);
+				if (status == 0x80) {
+					if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
+						break;
+					}
+					scsiq->r3.done_stat = 0;
+					scsiq->r3.host_stat = 0;
+					scsiq->r3.scsi_stat = 0;
+					scsiq->r3.scsi_msg = 0;
+					DvcSleepMilliSecond(100);
+					continue;
+				}
+				scsiq->r3.done_stat = 0;
+				scsiq->r3.host_stat = 0;
+				scsiq->r3.scsi_stat = 0;
+				scsiq->r3.scsi_msg = 0;
+				ASC_DBG1(3, "PollQueueDone: AscAbortSRB() scsiq %x\n",
+						 (unsigned) scsiq);
+
+				AscAbortSRB(asc_dvc, (ulong) scsiq);
+			}
+			ASC_DBG1(3, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
+			return (scsiq->r3.done_stat);
+		}
+	} while ((status == 0) || (status == 0x80));
+	ASC_DBG(3, "PollQueueDone: done_stat QD_WITH_ERROR\n");
+	return (scsiq->r3.done_stat = QD_WITH_ERROR);
+}
+
+int
+PollScsiInquiry(
+				   ASC_DVC_VAR asc_ptr_type * asc_dvc,
+				   ASC_SCSI_REQ_Q dosfar * scsiq,
+				   uchar dosfar * buf,
+				   int buf_len
+)
+{
+	if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 4));
+}
+
+int
+PollScsiReadCapacity(
+						ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						ASC_SCSI_REQ_Q dosfar * scsiq,
+						ASC_CAP_INFO dosfar * cap_info
+)
+{
+	ASC_CAP_INFO        scsi_cap_info;
+	int                 status;
+
+	if (AscScsiReadCapacity(asc_dvc, scsiq,
+							(uchar dosfar *) & scsi_cap_info) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 8);
+	if (status == 1) {
+#if CC_LITTLE_ENDIAN_HOST
+		cap_info->lba = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.lba);
+		cap_info->blk_size = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.blk_size);
+#else
+		cap_info->lba = scsi_cap_info.lba;
+		cap_info->blk_size = scsi_cap_info.blk_size;
+#endif
+		return (scsiq->r3.done_stat);
+	}
+	return (scsiq->r3.done_stat = QD_WITH_ERROR);
+}
+
+ulong dosfar       *
+swapfarbuf4(
+			   uchar dosfar * buf
+)
+{
+	uchar               tmp;
+
+	tmp = buf[3];
+	buf[3] = buf[0];
+	buf[0] = tmp;
+
+	tmp = buf[1];
+	buf[1] = buf[2];
+	buf[2] = tmp;
+
+	return ((ulong dosfar *) buf);
+}
+
+int
+PollScsiTestUnitReady(
+						 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						 ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+	if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 12));
+}
+
+int
+PollScsiStartUnit(
+					 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					 ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+	if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 40));
+}
+
+int
+InitTestUnitReady(
+					 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					 ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+	ASC_SCSI_BIT_ID_TYPE tid_bits;
+	int                 retry;
+	ASC_REQ_SENSE dosfar *sen;
+
+	retry = 0;
+	tid_bits = scsiq->r1.target_id;
+	while (retry++ < 2) {
+		ASC_DBG(3, "InitTestUnitReady: PollScsiTestUnitReady()\n");
+		PollScsiTestUnitReady(asc_dvc, scsiq);
+		ASC_DBG1(3, "InitTestUnitReady: done_stat %x\n", scsiq->r3.done_stat);
+		if (scsiq->r3.done_stat == 0x01) {
+			return (1);
+		} else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
+			DvcSleepMilliSecond(100);
+
+			sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr;
+
+			if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
+				((sen->err_code & 0x70) != 0)) {
+
+				if (sen->sense_key == SCSI_SENKEY_NOT_READY) {
+
+					if (asc_dvc->start_motor & tid_bits) {
+						if (PollScsiStartUnit(asc_dvc, scsiq) == 1) {
+							retry = 0;
+							continue;
+						} else {
+							asc_dvc->start_motor &= ~tid_bits;
+							break;
+						}
+					} else {
+						DvcSleepMilliSecond(100);
+					}
+				} else if (sen->sense_key == SCSI_SENKEY_ATTENSION) {
+					DvcSleepMilliSecond(100);
+				} else {
+					break;
+				}
+			} else {
+				break;
+			}
+		} else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
+			break;
+		} else {
+			break;
+		}
+	}
+	return (0);
+}
+
+#if CC_INIT_INQ_DISPLAY
+
+#endif
+
+int
+AscPollQDone(
+				ASC_DVC_VAR asc_ptr_type * asc_dvc,
+				ASC_SCSI_REQ_Q dosfar * scsiq,
+				int timeout_sec
+)
+{
+	int                 loop, loop_end;
+	int                 sta;
+	PortAddr            iop_base;
+
+	iop_base = asc_dvc->iop_base;
+	loop = 0;
+	loop_end = timeout_sec * 100;
+	sta = 1;
+
+	while (TRUE) {
+		ASC_DBG4(3,
+		 "AscPollQDone: loop %d, err_code %x, done_stat %x, scsi_stat %x\n",
+		 loop, asc_dvc->err_code, scsiq->r3.done_stat, scsiq->r3.scsi_stat);
+		if (asc_dvc->err_code != 0) {
+			scsiq->r3.done_stat = QD_WITH_ERROR;
+			sta = ERR;
+			break;
+		}
+		if (scsiq->r3.done_stat != QD_IN_PROGRESS) {
+			if ((scsiq->r3.done_stat == QD_WITH_ERROR) &&
+				(scsiq->r3.scsi_stat == SS_TARGET_BUSY)) {
+				sta = 0x80;
+				break;
+			}
+			break;
+		}
+		DvcSleepMilliSecond(10);
+		if (loop++ > loop_end) {
+			sta = 0;
+			break;
+		}
+		if (AscIsChipHalted(iop_base)) {
+			AscISR(asc_dvc);
+			loop = 0;
+		} else {
+			ASC_DBG(3, "AscPollQDone: AscIsIntPending()\n");
+			if (AscIsIntPending(iop_base)) {
+				ASC_DBG(3, "AscPollQDone: AscISR()\n");
+				AscISR(asc_dvc);
+			}
+		}
+	}
+	ASC_DBG1(3, "AscPollQDone: sta %x\n", sta);
+	return (sta);
+}
+
+uchar
+AscReadLramByte(
+				   PortAddr iop_base,
+				   ushort addr
+)
+{
+	uchar               byte_data;
+	ushort              word_data;
+
+	if (isodd_word(addr)) {
+		AscSetChipLramAddr(iop_base, addr - 1);
+		word_data = AscGetChipLramData(iop_base);
+
+#if CC_LITTLE_ENDIAN_HOST
+		byte_data = (uchar) ((word_data >> 8) & 0xFF);
+#else
+		byte_data = (uchar) (word_data & 0xFF);
+#endif
+
+	} else {
+		AscSetChipLramAddr(iop_base, addr);
+		word_data = AscGetChipLramData(iop_base);
+
+#if CC_LITTLE_ENDIAN_HOST
+		byte_data = (uchar) (word_data & 0xFF);
+#else
+		byte_data = (uchar) ((word_data >> 8) & 0xFF);
+#endif
+
+	}
+	return (byte_data);
+}
+
+ushort
+AscReadLramWord(
+				   PortAddr iop_base,
+				   ushort addr
+)
+{
+	ushort              word_data;
+
+	AscSetChipLramAddr(iop_base, addr);
+	word_data = AscGetChipLramData(iop_base);
+	return (word_data);
+}
+
+ulong
+AscReadLramDWord(
+					PortAddr iop_base,
+					ushort addr
+)
+{
+	ushort              val_low, val_high;
+	ulong               dword_data;
+
+	AscSetChipLramAddr(iop_base, addr);
+
+#if CC_LITTLE_ENDIAN_HOST
+	val_low = AscGetChipLramData(iop_base);
+
+	val_high = AscGetChipLramData(iop_base);
+#else
+	val_high = AscGetChipLramData(iop_base);
+	val_low = AscGetChipLramData(iop_base);
+#endif
+
+	dword_data = ((ulong) val_high << 16) | (ulong) val_low;
+	return (dword_data);
+}
+
+void
+AscWriteLramWord(
+					PortAddr iop_base,
+					ushort addr,
+					ushort word_val
+)
+{
+	AscSetChipLramAddr(iop_base, addr);
+	AscPutChipLramData(iop_base, word_val);
+	return;
+}
+
+void
+AscWriteLramDWord(
+					 PortAddr iop_base,
+					 ushort addr,
+					 ulong dword_val
+)
+{
+	ushort              word_val;
+
+	AscSetChipLramAddr(iop_base, addr);
+
+#if CC_LITTLE_ENDIAN_HOST
+	word_val = (ushort) dword_val;
+	AscPutChipLramData(iop_base, word_val);
+	word_val = (ushort) (dword_val >> 16);
+	AscPutChipLramData(iop_base, word_val);
+#else
+	word_val = (ushort) (dword_val >> 16);
+	AscPutChipLramData(iop_base, word_val);
+	word_val = (ushort) dword_val;
+	AscPutChipLramData(iop_base, word_val);
+#endif
+	return;
+}
+
+void
+AscWriteLramByte(
+					PortAddr iop_base,
+					ushort addr,
+					uchar byte_val
+)
+{
+	ushort              word_data;
+
+	if (isodd_word(addr)) {
+		addr--;
+		word_data = AscReadLramWord(iop_base, addr);
+		word_data &= 0x00FF;
+		word_data |= (((ushort) byte_val << 8) & 0xFF00);
+	} else {
+		word_data = AscReadLramWord(iop_base, addr);
+		word_data &= 0xFF00;
+		word_data |= ((ushort) byte_val & 0x00FF);
+	}
+	AscWriteLramWord(iop_base, addr, word_data);
+	return;
+}
+
+int
+AscVerWriteLramWord(
+					   PortAddr iop_base,
+					   ushort addr,
+					   ushort word_val
+)
+{
+	int                 sta;
+
+	sta = 0;
+	AscSetChipLramAddr(iop_base, addr);
+	AscPutChipLramData(iop_base, word_val);
+	AscSetChipLramAddr(iop_base, addr);
+	if (word_val != AscGetChipLramData(iop_base)) {
+		sta = ERR;
+	}
+	return (sta);
+}
+
+void
+AscMemWordCopyToLram(
+						PortAddr iop_base,
+						ushort s_addr,
+						ushort dosfar * s_buffer,
+						int words
+)
+{
+	AscSetChipLramAddr(iop_base, s_addr);
+	DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
+	return;
+}
+
+void
+AscMemDWordCopyToLram(
+						 PortAddr iop_base,
+						 ushort s_addr,
+						 ulong dosfar * s_buffer,
+						 int dwords
+)
+{
+	AscSetChipLramAddr(iop_base, s_addr);
+	DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
+	return;
+}
+
+void
+AscMemWordCopyFromLram(
+						  PortAddr iop_base,
+						  ushort s_addr,
+						  ushort dosfar * d_buffer,
+						  int words
+)
+{
+	AscSetChipLramAddr(iop_base, s_addr);
+	DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
+	return;
+}
+
+ulong
+AscMemSumLramWord(
+					 PortAddr iop_base,
+					 ushort s_addr,
+					 rint words
+)
+{
+	ulong               sum;
+	int                 i;
+
+	sum = 0L;
+	for (i = 0; i < words; i++, s_addr += 2) {
+		sum += AscReadLramWord(iop_base, s_addr);
+	}
+	return (sum);
+}
+
+void
+AscMemWordSetLram(
+					 PortAddr iop_base,
+					 ushort s_addr,
+					 ushort set_wval,
+					 rint words
+)
+{
+	rint                i;
+
+	AscSetChipLramAddr(iop_base, s_addr);
+	for (i = 0; i < words; i++) {
+		AscPutChipLramData(iop_base, set_wval);
+	}
+	return;
+}
+
+int
+AscScsiInquiry(
+				  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+				  ASC_SCSI_REQ_Q dosfar * scsiq,
+				  uchar dosfar * buf, int buf_len
+)
+{
+	if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
+						 (ulong) buf_len) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	scsiq->cdb[0] = (uchar) SCSICMD_Inquiry;
+	scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+	scsiq->cdb[2] = 0;
+	scsiq->cdb[3] = 0;
+	scsiq->cdb[4] = buf_len;
+	scsiq->cdb[5] = 0;
+	scsiq->r2.cdb_len = 6;
+	return (0);
+}
+
+int
+AscScsiReadCapacity(
+					   ASC_DVC_VAR asc_ptr_type * asc_dvc,
+					   ASC_SCSI_REQ_Q dosfar * scsiq,
+					   uchar dosfar * info
+)
+{
+	if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity;
+	scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+	scsiq->cdb[2] = 0;
+	scsiq->cdb[3] = 0;
+	scsiq->cdb[4] = 0;
+	scsiq->cdb[5] = 0;
+	scsiq->cdb[6] = 0;
+	scsiq->cdb[7] = 0;
+	scsiq->cdb[8] = 0;
+	scsiq->cdb[9] = 0;
+	scsiq->r2.cdb_len = 10;
+	return (0);
+}
+
+int
+AscScsiTestUnitReady(
+						ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+	if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR,
+						 (ulong) 0L) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
+	scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady;
+	scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+	scsiq->cdb[2] = 0;
+	scsiq->cdb[3] = 0;
+	scsiq->cdb[4] = 0;
+	scsiq->cdb[5] = 0;
+	scsiq->r2.cdb_len = 6;
+	return (0);
+}
+
+int
+AscScsiStartStopUnit(
+						ASC_DVC_VAR asc_ptr_type * asc_dvc,
+						ASC_SCSI_REQ_Q dosfar * scsiq,
+						uchar op_mode
+)
+{
+	if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) {
+		return (scsiq->r3.done_stat = QD_WITH_ERROR);
+	}
+	scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
+	scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit;
+	scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+	scsiq->cdb[2] = 0;
+	scsiq->cdb[3] = 0;
+	scsiq->cdb[4] = op_mode;
+
+	scsiq->cdb[5] = 0;
+	scsiq->r2.cdb_len = 6;
+	return (0);
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this