]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 15 Oct 2007 15:19:33 +0000 (08:19 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 15 Oct 2007 15:19:33 +0000 (08:19 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (207 commits)
  [SCSI] gdth: fix CONFIG_ISA build failure
  [SCSI] esp_scsi: remove __dev{init,exit}
  [SCSI] gdth: !use_sg cleanup and use of scsi accessors
  [SCSI] gdth: Move members from SCp to gdth_cmndinfo, stage 2
  [SCSI] gdth: Setup proper per-command private data
  [SCSI] gdth: Remove gdth_ctr_tab[]
  [SCSI] gdth: switch to modern scsi host registration
  [SCSI] gdth: gdth_interrupt() gdth_get_status() & gdth_wait() fixes
  [SCSI] gdth: clean up host private data
  [SCSI] gdth: Remove virt hosts
  [SCSI] gdth: Reorder scsi_host_template intitializers
  [SCSI] gdth: kill gdth_{read,write}[bwl] wrappers
  [SCSI] gdth: Remove 2.4.x support, in-kernel changelog
  [SCSI] gdth: split out pci probing
  [SCSI] gdth: split out eisa probing
  [SCSI] gdth: split out isa probing
  gdth: Make one abuse of scsi_cmnd less obvious
  [SCSI] NCR5380: Use scsi_eh API for REQUEST_SENSE invocation
  [SCSI] usb storage: use scsi_eh API in REQUEST_SENSE execution
  [SCSI] scsi_error: Refactoring scsi_error to facilitate in synchronous REQUEST_SENSE
  ...

168 files changed:
Documentation/scsi/00-INDEX
Documentation/scsi/ChangeLog.arcmsr
Documentation/scsi/aacraid.txt
Documentation/scsi/advansys.txt [new file with mode: 0644]
MAINTAINERS
arch/ia64/hp/sim/simscsi.c
drivers/fc4/fc.c
drivers/infiniband/ulp/srp/Kconfig
drivers/infiniband/ulp/srp/ib_srp.c
drivers/message/fusion/Kconfig
drivers/message/fusion/lsi/mpi.h
drivers/message/fusion/lsi/mpi_cnfg.h
drivers/message/fusion/lsi/mpi_fc.h
drivers/message/fusion/lsi/mpi_history.txt
drivers/message/fusion/lsi/mpi_init.h
drivers/message/fusion/lsi/mpi_ioc.h
drivers/message/fusion/lsi/mpi_lan.h
drivers/message/fusion/lsi/mpi_log_fc.h
drivers/message/fusion/lsi/mpi_log_sas.h
drivers/message/fusion/lsi/mpi_raid.h
drivers/message/fusion/lsi/mpi_sas.h
drivers/message/fusion/lsi/mpi_targ.h
drivers/message/fusion/lsi/mpi_tool.h
drivers/message/fusion/lsi/mpi_type.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptctl.h
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptlan.h
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptsas.h [new file with mode: 0644]
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs_unit.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.h
drivers/scsi/NCR53C9x.c
drivers/scsi/NCR_D700.c
drivers/scsi/a4000t.c
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commsup.c
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aic7xxx_old.c
drivers/scsi/aic94xx/aic94xx_hwi.h
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/arcmsr/arcmsr.h
drivers/scsi/arcmsr/arcmsr_attr.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/bvme6000_scsi.c
drivers/scsi/constants.c
drivers/scsi/dc395x.c
drivers/scsi/dpt_i2o.c
drivers/scsi/dtc.c
drivers/scsi/eata.c
drivers/scsi/eata_pio.c
drivers/scsi/esp_scsi.c
drivers/scsi/fdomain.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/gdth.h
drivers/scsi/gdth_kcompat.h [deleted file]
drivers/scsi/gdth_proc.c
drivers/scsi/gdth_proc.h
drivers/scsi/hosts.c
drivers/scsi/hptiop.c
drivers/scsi/hptiop.h
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/Makefile
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ibmvscsi/iseries_vscsi.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/ide-scsi.c
drivers/scsi/imm.c
drivers/scsi/in2000.c
drivers/scsi/ips.c
drivers/scsi/ips.h
drivers/scsi/libsrp.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/megaraid.c
drivers/scsi/mvme16x_scsi.c
drivers/scsi/ncr53c8xx.c
drivers/scsi/ncr53c8xx.h
drivers/scsi/osst.c
drivers/scsi/osst.h
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/nsp_cs.h
drivers/scsi/pluto.c
drivers/scsi/ps3rom.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qlogicfas.c
drivers/scsi/qlogicpti.c
drivers/scsi/qlogicpti.h
drivers/scsi/scsi.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_tgt_if.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/scsi_tgt_priv.h
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_fc_internal.h [new file with mode: 0644]
drivers/scsi/scsi_transport_srp.c [new file with mode: 0644]
drivers/scsi/scsi_transport_srp_internal.h [new file with mode: 0644]
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/sun3_NCR5380.c
drivers/scsi/tmscsim.c
drivers/scsi/u14-34f.c
drivers/scsi/wd33c93.c
drivers/scsi/zorro7xx.c
drivers/usb/image/microtek.c
drivers/usb/storage/transport.c
include/linux/pci_ids.h
include/scsi/libsrp.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_dbg.h
include/scsi/scsi_driver.h
include/scsi/scsi_eh.h
include/scsi/scsi_host.h
include/scsi/scsi_tgt.h
include/scsi/scsi_tgt_if.h
include/scsi/scsi_transport.h
include/scsi/scsi_transport_fc.h
include/scsi/scsi_transport_iscsi.h
include/scsi/scsi_transport_srp.h [new file with mode: 0644]
include/scsi/sd.h

index 12354830c6b02d8742c19860bdf1c9a1d88ab70c..aa1f7e927834bf8ad7557b9a98eb40e28e3f69b7 100644 (file)
@@ -2,14 +2,20 @@
        - this file
 53c700.txt
        - info on driver for 53c700 based adapters
-AM53C974.txt
-       - info on driver for AM53c974 based adapters
 BusLogic.txt
        - info on driver for adapters with BusLogic chips
-ChangeLog
+ChangeLog.1992-1997
        - Changes to scsi files, if not listed elsewhere
+ChangeLog.arcmsr
+       - Changes to driver for ARECA's SATA RAID controller cards
 ChangeLog.ips
        - IBM ServeRAID driver Changelog
+ChangeLog.lpfc
+       - Changes to lpfc driver
+ChangeLog.megaraid
+       - Changes to LSI megaraid controller.
+ChangeLog.megaraid_sas
+       - Changes to serial attached scsi version of LSI megaraid controller.
 ChangeLog.ncr53c8xx
        - Changes to ncr53c8xx driver
 ChangeLog.sym53c8xx
@@ -20,26 +26,44 @@ FlashPoint.txt
        - info on driver for BusLogic FlashPoint adapters
 LICENSE.FlashPoint
        - Licence of the Flashpoint driver
+LICENSE.qla2xxx
+       - License for QLogic Linux Fibre Channel HBA Driver firmware.
 Mylex.txt
        - info on driver for Mylex adapters
 NinjaSCSI.txt
        - info on WorkBiT NinjaSCSI-32/32Bi driver
+aacraid.txt
+       - Driver supporting Adaptec RAID controllers
 aha152x.txt
        - info on driver for Adaptec AHA152x based adapters
+aic79xx.txt
+       - Adaptec Ultra320 SCSI host adapters
 aic7xxx.txt
        - info on driver for Adaptec controllers
 aic7xxx_old.txt
        - info on driver for Adaptec controllers, old generation
+arcmsr_spec.txt
+       - ARECA FIRMWARE SPEC (for IOP331 adapter)
+dc395x.txt
+       - README file for the dc395x SCSI driver
 dpti.txt
        - info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters
 dtc3x80.txt
        - info on driver for DTC 2x80 based adapters
 g_NCR5380.txt
        - info on driver for NCR5380 and NCR53c400 based adapters
+hptiop.txt
+       - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
 ibmmca.txt
        - info on driver for IBM adapters with MCA bus
 in2000.txt
        - info on in2000 driver
+libsas.txt
+       - Serial Attached SCSI management layer.
+lpfc.txt
+       - LPFC driver release notes
+megaraid.txt
+       - Common Management Module, shared code handling ioctls for LSI drivers
 ncr53c7xx.txt
        - info on driver for NCR53c7xx based adapters
 ncr53c8xx.txt
@@ -50,6 +74,8 @@ ppa.txt
        - info on driver for IOmega zip drive
 qlogicfas.txt
        - info on driver for QLogic FASxxx based adapters
+scsi-changer.txt
+       - README for the SCSI media changer driver
 scsi-generic.txt
        - info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
 scsi.txt
@@ -58,6 +84,8 @@ scsi_mid_low_api.txt
        - info on API between SCSI layer and low level drivers
 scsi_eh.txt
        - info on SCSI midlayer error handling infrastructure
+scsi_fc_transport.txt
+       - SCSI Fiber Channel Tansport
 st.txt
        - info on scsi tape driver
 sym53c500_cs.txt
index 162c47fdf45f47cff4c1efb01098b045284b286e..cd8403a33ee64ad118000bbfe816611ae39dfeb6 100644 (file)
 **                                             for linux standard list
 **                                             enable usage of pci message signal interrupt
 **                                             follow Randy.Danlup kindness suggestion cleanup this code
-**************************************************************************
\ No newline at end of file
+** 1.20.00.14   05/02/2007      Erich Chen & Nick Cheng
+**                                             1.implement PCI-Express error recovery function and AER capability
+**                                             2.implement the selection of ARCMSR_MAX_XFER_SECTORS_B=4096
+**                                             if firmware version is newer than 1.42
+**                                             3.modify arcmsr_iop_reset to improve the ability
+**                                             4.modify the ISR, arcmsr_interrupt routine,to prevent the
+**                                             inconsistency with sg_mod driver if application directly calls
+**                                             the arcmsr driver w/o passing through scsi mid layer
+**                                             specially thanks to Yanmin Zhang's openhanded help about AER
+** 1.20.00.15   08/30/2007      Erich Chen & Nick Cheng
+**                                             1. support ARC1200/1201/1202 SATA RAID adapter, which is named
+**                                             ACB_ADAPTER_TYPE_B
+**                                             2. modify the arcmsr_pci_slot_reset function
+**                                             3. modify the arcmsr_pci_ers_disconnect_forepart function
+**                                             4. modify the arcmsr_pci_ers_need_reset_forepart function
+**************************************************************************
index cc12b55d4b3dfc8a544ed8232fa82760b0fecd67..a8257840695ae870828514813cf109f2aa767e5f 100644 (file)
@@ -38,10 +38,8 @@ Supported Cards/Chipsets
        9005:0286:9005:02ac     Adaptec 1800 (Typhoon44)
        9005:0285:9005:02b5     Adaptec 5445 (Voodoo44)
        9005:0285:15d9:02b5     SMC     AOC-USAS-S4i
-       9005:0285:15d9:02c9     SMC     AOC-USAS-S4iR
        9005:0285:9005:02b6     Adaptec 5805 (Voodoo80)
        9005:0285:15d9:02b6     SMC     AOC-USAS-S8i
-       9005:0285:15d9:02ca     SMC     AOC-USAS-S8iR
        9005:0285:9005:02b7     Adaptec 5085 (Voodoo08)
        9005:0285:9005:02bb     Adaptec 3405 (Marauder40LP)
        9005:0285:9005:02bc     Adaptec 3805 (Marauder80LP)
@@ -50,9 +48,14 @@ Supported Cards/Chipsets
        9005:0285:9005:02be     Adaptec 31605 (Marauder160)
        9005:0285:9005:02c3     Adaptec 51205 (Voodoo120)
        9005:0285:9005:02c4     Adaptec 51605 (Voodoo160)
+       9005:0285:15d9:02c9     SMC     AOC-USAS-S4iR
+       9005:0285:15d9:02ca     SMC     AOC-USAS-S8iR
        9005:0285:9005:02ce     Adaptec 51245 (Voodoo124)
        9005:0285:9005:02cf     Adaptec 51645 (Voodoo164)
        9005:0285:9005:02d0     Adaptec 52445 (Voodoo244)
+       9005:0285:9005:02d1     Adaptec 5405 (Voodoo40)
+       9005:0285:15d9:02d2     SMC     AOC-USAS-S8i-LP
+       9005:0285:15d9:02d3     SMC     AOC-USAS-S8iR-LP
        1011:0046:9005:0364     Adaptec 5400S (Mustang)
        9005:0287:9005:0800     Adaptec Themisto (Jupiter)
        9005:0200:9005:0200     Adaptec Themisto (Jupiter)
@@ -103,6 +106,7 @@ Supported Cards/Chipsets
        9005:0285:108e:7aac     SUN     STK RAID REM (Voodoo44 Coyote)
        9005:0285:108e:0286     SUN     STK RAID INT (Cougar)
        9005:0285:108e:0287     SUN     STK RAID EXT (Prometheus)
+       9005:0285:108e:7aae     SUN     STK RAID EM (Narvi)
 
 People
 -------------------------
diff --git a/Documentation/scsi/advansys.txt b/Documentation/scsi/advansys.txt
new file mode 100644 (file)
index 0000000..4a3db62
--- /dev/null
@@ -0,0 +1,243 @@
+AdvanSys (Advanced System Products, Inc.) manufactures the following
+RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
+(8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
+buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
+transfer) SCSI Host Adapters for the PCI bus.
+
+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. A CDB is a single SCSI command. The driver
+detect routine will display the number of CDBs available for each
+adapter detected. The number of CDBs used by the driver can be
+lowered in the BIOS by changing the 'Host Queue Size' adapter setting.
+
+Laptop Products:
+   ABP-480 - Bus-Master CardBus (16 CDB)
+
+Connectivity Products:
+   ABP510/5150 - Bus-Master ISA (240 CDB)
+   ABP5140 - Bus-Master ISA PnP (16 CDB)
+   ABP5142 - Bus-Master ISA PnP with floppy (16 CDB)
+   ABP902/3902 - Bus-Master PCI (16 CDB)
+   ABP3905 - Bus-Master PCI (16 CDB)
+   ABP915 - Bus-Master PCI (16 CDB)
+   ABP920 - Bus-Master PCI (16 CDB)
+   ABP3922 - Bus-Master PCI (16 CDB)
+   ABP3925 - Bus-Master PCI (16 CDB)
+   ABP930 - Bus-Master PCI (16 CDB)
+   ABP930U - Bus-Master PCI Ultra (16 CDB)
+   ABP930UA - Bus-Master PCI Ultra (16 CDB)
+   ABP960 - Bus-Master PCI MAC/PC (16 CDB)
+   ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
+
+Single Channel Products:
+   ABP542 - Bus-Master ISA with floppy (240 CDB)
+   ABP742 - Bus-Master EISA (240 CDB)
+   ABP842 - Bus-Master VL (240 CDB)
+   ABP940 - Bus-Master PCI (240 CDB)
+   ABP940U - Bus-Master PCI Ultra (240 CDB)
+   ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB)
+   ABP970 - Bus-Master PCI MAC/PC (240 CDB)
+   ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
+   ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB)
+   ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB)
+   ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB)
+   ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB)
+
+Multi-Channel Products:
+   ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
+   ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
+   ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
+   ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel)
+   ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
+   ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
+   ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.)
+   ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB)
+   ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB)
+
+Driver Compile Time Options and Debugging
+
+The following constants can be defined in the source file.
+
+1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled)
+
+   Enabling this option adds assertion logic statements to the
+   driver. If an assertion fails a message will be displayed to
+   the console, but the system will continue to operate. Any
+   assertions encountered should be reported to the person
+   responsible for the driver. Assertion statements may proactively
+   detect problems with the driver and facilitate fixing these
+   problems. Enabling assertions will add a small overhead to the
+   execution of the driver.
+
+2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled)
+
+   Enabling this option adds tracing functions to the driver and the
+   ability to set a driver tracing level at boot time.  This option is
+   very useful for debugging the driver, but it will add to the size
+   of the driver execution image and add overhead to the execution of
+   the driver.
+
+   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_IOPORT_PROBE + 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,0,0,0,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
+
+   To enable debug output to console, please make sure that:
+
+   a. System and kernel logging is enabled (syslogd, klogd running).
+   b. Kernel messages are routed to console output. Check
+      /etc/syslog.conf for an entry similar to this:
+
+           kern.*                  /dev/console
+
+   c. klogd is started with the appropriate -c parameter
+      (e.g. klogd -c 8)
+
+   This will cause printk() messages to be be displayed on the
+   current console. Refer to the klogd(8) and syslogd(8) man pages
+   for details.
+
+   Alternatively you can enable printk() to console with this
+   program. However, this is not the 'official' way to do this.
+   Debug output is logged in /var/log/messages.
+
+     main()
+     {
+             syscall(103, 7, 0, 0);
+     }
+
+   Increasing LOG_BUF_LEN in kernel/printk.c to something like
+   40960 allows more debug messages to be buffered in the kernel
+   and written to the console or log file.
+
+3. ADVANSYS_STATS - Enable statistics (Def: Enabled)
+
+   Enabling this option adds statistics collection and display
+   through /proc to the driver. The information is useful for
+   monitoring driver and device performance. It will add to the
+   size of the driver execution image and add minor overhead to
+   the execution of the driver.
+
+   Statistics are maintained on a per adapter basis. Driver entry
+   point call counts and transfer size counts are maintained.
+   Statistics are only available for kernels greater than or equal
+   to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured.
+
+   AdvanSys SCSI adapter files have the following path name format:
+
+      /proc/scsi/advansys/{0,1,2,3,...}
+
+   This information can be displayed with cat. For example:
+
+      cat /proc/scsi/advansys/0
+
+   When ADVANSYS_STATS is not defined the AdvanSys /proc files only
+   contain adapter and device configuration information.
+
+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_IOPORT_PROBE + 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.
+
+Credits (Chronological Order)
+
+Bob Frey <bfrey@turbolinux.com.cn> wrote the AdvanSys SCSI driver
+and maintained it up to 3.3F. He continues to answer questions
+and help maintain the driver.
+
+Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
+basis for the Linux v1.3.X changes which were included in the
+1.2 release.
+
+Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug
+in advansys_biosparam() which was fixed in the 1.3 release.
+
+Erik Ratcliffe <erik@caldera.com> has done testing of the
+AdvanSys driver in the Caldera releases.
+
+Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
+AscWaitTixISRDone() which he found necessary to make the
+driver work with a SCSI-1 disk.
+
+Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide
+support in the 3.1A driver.
+
+Doug Gilbert <dgilbert@interlog.com> has made changes and
+suggestions to improve the driver and done a lot of testing.
+
+Ken Mort <ken@mort.net> reported a DEBUG compile bug fixed
+in 3.2K.
+
+Tom Rini <trini@kernel.crashing.org> provided the CONFIG_ISA
+patch and helped with PowerPC wide and narrow board support.
+
+Philip Blundell <philb@gnu.org> provided an
+advansys_interrupts_enabled patch.
+
+Dave Jones <dave@denial.force9.co.uk> reported the compiler
+warnings generated when CONFIG_PROC_FS was not defined in
+the 3.2M driver.
+
+Jerry Quinn <jlquinn@us.ibm.com> fixed PowerPC support (endian
+problems) for wide cards.
+
+Bryan Henderson <bryanh@giraffe-data.com> helped debug narrow
+card error handling.
+
+Manuel Veloso <veloso@pobox.com> worked hard on PowerPC narrow
+board support and fixed a bug in AscGetEEPConfig().
+
+Arnaldo Carvalho de Melo <acme@conectiva.com.br> made
+save_flags/restore_flags changes.
+
+Andy Kellner <AKellner@connectcom.net> continued the Advansys SCSI
+driver development for ConnectCom (Version > 3.3F).
+
+Ken Witherow for extensive testing during the development of version 3.4.
index 012fa837845d1e8a21f9ec1c829a074be8b37493..12cee3da2625f48ad5564892026c7873c9123184 100644 (file)
@@ -297,6 +297,12 @@ P: Colin Leroy
 M:     colin@colino.net
 S:     Maintained
 
+ADVANSYS SCSI DRIVER
+P:     Matthew Wilcox
+M:     matthew@wil.cx
+L:     linux-scsi@vger.kernel.org
+S:     Maintained
+
 AEDSP16 DRIVER
 P:     Riccardo Facchetti
 M:     fizban@tin.it
@@ -1889,6 +1895,11 @@ M:       Gadi Oxman <gadio@netvision.net.il>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+IDE-SCSI DRIVER
+L:     linux-ide@vger.kernel.org
+L:     linux-scsi@vger.kernel.org
+S:     Orphan
+
 IEEE 1394 SUBSYSTEM
 P:     Ben Collins
 M:     ben.collins@ubuntu.com
@@ -2404,7 +2415,7 @@ LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
 P:     Eric Moore
 M:     Eric.Moore@lsi.com
 M:     support@lsi.com
-L:     mpt_linux_developer@lsi.com
+L:     DL-MPTFusionLinux@lsi.com
 L:     linux-scsi@vger.kernel.org
 W:     http://www.lsilogic.com/support
 S:     Supported
index 4552a1cf5b338f5a7aa2f03175a07a6cd5f35959..d62fa76e5a7d05680a3fcf2d1dc75faee35e88dc 100644 (file)
@@ -372,8 +372,13 @@ simscsi_init(void)
                return -ENOMEM;
 
        error = scsi_add_host(host, NULL);
-       if (!error)
-               scsi_scan_host(host);
+       if (error)
+               goto free_host;
+       scsi_scan_host(host);
+       return 0;
+
+ free_host:
+       scsi_host_put(host);
        return error;
 }
 
index 22b62b3cd14e5538f3b8e273c525c5586154b784..82de9e1adb1eaf80f4ece0410baafc0755dae519 100644 (file)
@@ -427,15 +427,10 @@ static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hd
                        memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len);
                }
                
-               if (fcmd->data) {
-                       if (SCpnt->use_sg)
-                               dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->request_buffer,
-                                               SCpnt->use_sg,
-                                               SCpnt->sc_data_direction);
-                       else
-                               dma_unmap_single(fc->dev, fcmd->data, SCpnt->request_bufflen,
-                                                SCpnt->sc_data_direction);
-               }
+               if (fcmd->data)
+                       dma_unmap_sg(fc->dev, scsi_sglist(SCpnt),
+                                    scsi_sg_count(SCpnt),
+                                    SCpnt->sc_data_direction);
                break;
        default:
                host_status=DID_ERROR; /* FIXME */
@@ -793,10 +788,14 @@ static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt,
                                fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
                } else
                        fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
-               if (!SCpnt->request_bufflen && !SCpnt->use_sg) {
+
+               if (!scsi_bufflen(SCpnt)) {
                        cmd->fcp_cntl = fcp_cntl;
                        fcmd->data = (dma_addr_t)NULL;
                } else {
+                       struct scatterlist *sg;
+                       int nents;
+
                        switch (SCpnt->cmnd[0]) {
                        case WRITE_6:
                        case WRITE_10:
@@ -805,22 +804,12 @@ static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt,
                        default:
                                cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break;
                        }
-                       if (!SCpnt->use_sg) {
-                               cmd->fcp_data_len = SCpnt->request_bufflen;
-                               fcmd->data = dma_map_single (fc->dev, (char *)SCpnt->request_buffer,
-                                                            SCpnt->request_bufflen,
-                                                            SCpnt->sc_data_direction);
-                       } else {
-                               struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
-                               int nents;
-
-                               FCD(("XXX: Use_sg %d %d\n", SCpnt->use_sg, sg->length))
-                               nents = dma_map_sg (fc->dev, sg, SCpnt->use_sg,
-                                                   SCpnt->sc_data_direction);
-                               if (nents > 1) printk ("%s: SG for nents %d (use_sg %d) not handled yet\n", fc->name, nents, SCpnt->use_sg);
-                               fcmd->data = sg_dma_address(sg);
-                               cmd->fcp_data_len = sg_dma_len(sg);
-                       }
+
+                       sg = scsi_sglist(SCpnt);
+                       nents = dma_map_sg(fc->dev, sg, scsi_sg_count(SCpnt),
+                                          SCpnt->sc_data_direction);
+                       fcmd->data = sg_dma_address(sg);
+                       cmd->fcp_data_len = sg_dma_len(sg);
                }
                memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
                memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
index 3432dce29520a6df599c7a9e7614027257236913..c74ee9633041d7a566dc1c2d9febf676c5bd744d 100644 (file)
@@ -1,6 +1,7 @@
 config INFINIBAND_SRP
        tristate "InfiniBand SCSI RDMA Protocol"
        depends on SCSI
+       select SCSI_SRP_ATTRS
        ---help---
          Support for the SCSI RDMA Protocol over InfiniBand.  This
          allows you to access storage devices that speak SRP over
index 9ccc63886d92904911a46a1630747478df12693d..950228fb009f29c1ccebd3f9453ee2c731a9a4c9 100644 (file)
@@ -47,6 +47,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/srp.h>
+#include <scsi/scsi_transport_srp.h>
 
 #include <rdma/ib_cache.h>
 
@@ -86,6 +87,8 @@ static void srp_remove_one(struct ib_device *device);
 static void srp_completion(struct ib_cq *cq, void *target_ptr);
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
 
+static struct scsi_transport_template *ib_srp_transport_template;
+
 static struct ib_client srp_client = {
        .name   = "srp",
        .add    = srp_add_one,
@@ -420,6 +423,7 @@ static void srp_remove_work(struct work_struct *work)
        list_del(&target->list);
        spin_unlock(&target->srp_host->target_lock);
 
+       srp_remove_host(target->scsi_host);
        scsi_remove_host(target->scsi_host);
        ib_destroy_cm_id(target->cm_id);
        srp_free_target_ib(target);
@@ -1544,12 +1548,24 @@ static struct scsi_host_template srp_template = {
 
 static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
 {
+       struct srp_rport_identifiers ids;
+       struct srp_rport *rport;
+
        sprintf(target->target_name, "SRP.T10:%016llX",
                 (unsigned long long) be64_to_cpu(target->id_ext));
 
        if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
                return -ENODEV;
 
+       memcpy(ids.port_id, &target->id_ext, 8);
+       memcpy(ids.port_id + 8, &target->ioc_guid, 8);
+       ids.roles = SRP_RPORT_ROLE_TARGET;
+       rport = srp_rport_add(target->scsi_host, &ids);
+       if (IS_ERR(rport)) {
+               scsi_remove_host(target->scsi_host);
+               return PTR_ERR(rport);
+       }
+
        spin_lock(&host->target_lock);
        list_add_tail(&target->list, &host->target_list);
        spin_unlock(&host->target_lock);
@@ -1775,6 +1791,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
        if (!target_host)
                return -ENOMEM;
 
+       target_host->transportt = ib_srp_transport_template;
        target_host->max_lun     = SRP_MAX_LUN;
        target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
 
@@ -2054,10 +2071,18 @@ static void srp_remove_one(struct ib_device *device)
        kfree(srp_dev);
 }
 
+static struct srp_function_template ib_srp_transport_functions = {
+};
+
 static int __init srp_init_module(void)
 {
        int ret;
 
+       ib_srp_transport_template =
+               srp_attach_transport(&ib_srp_transport_functions);
+       if (!ib_srp_transport_template)
+               return -ENOMEM;
+
        srp_template.sg_tablesize = srp_sg_tablesize;
        srp_max_iu_len = (sizeof (struct srp_cmd) +
                          sizeof (struct srp_indirect_buf) +
@@ -2066,6 +2091,7 @@ static int __init srp_init_module(void)
        ret = class_register(&srp_class);
        if (ret) {
                printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
+               srp_release_transport(ib_srp_transport_template);
                return ret;
        }
 
@@ -2074,6 +2100,7 @@ static int __init srp_init_module(void)
        ret = ib_register_client(&srp_client);
        if (ret) {
                printk(KERN_ERR PFX "couldn't register IB client\n");
+               srp_release_transport(ib_srp_transport_template);
                ib_sa_unregister_client(&srp_sa_client);
                class_unregister(&srp_class);
                return ret;
@@ -2087,6 +2114,7 @@ static void __exit srp_cleanup_module(void)
        ib_unregister_client(&srp_client);
        ib_sa_unregister_client(&srp_sa_client);
        class_unregister(&srp_class);
+       srp_release_transport(ib_srp_transport_template);
 }
 
 module_init(srp_init_module);
index f55cc03a75c9a8a5135a670ad3ad7f320b9b7a1f..a34a11d2fef2dff5d8b76d062ae1d3d401d29053 100644 (file)
@@ -1,15 +1,19 @@
 
-menu "Fusion MPT device support"
+menuconfig FUSION
+       bool "Fusion MPT device support"
        depends on PCI
+       ---help---
+       Say Y here to get to see options for Fusion Message
+       Passing Technology (MPT) drivers.
+       This option alone does not add any kernel code.
+
+       If you say N, all options in this submenu will be skipped and disabled.
 
-config FUSION
-       bool
-       default n
+if FUSION
 
 config FUSION_SPI
        tristate "Fusion MPT ScsiHost drivers for SPI"
        depends on PCI && SCSI
-       select FUSION
        select SCSI_SPI_ATTRS
        ---help---
          SCSI HOST support for a parallel SCSI host adapters.
@@ -20,11 +24,11 @@ config FUSION_SPI
          LSI53C1020A
          LSI53C1030
          LSI53C1035
+         ATTO UL4D
 
 config FUSION_FC
        tristate "Fusion MPT ScsiHost drivers for FC"
        depends on PCI && SCSI
-       select FUSION
        select SCSI_FC_ATTRS
        ---help---
          SCSI HOST support for a Fiber Channel host adapters.
@@ -37,12 +41,13 @@ config FUSION_FC
          LSIFC929
          LSIFC929X
          LSIFC929XL
+         LSIFC949X
+         LSIFC949E
          Brocade FC 410/420
 
 config FUSION_SAS
        tristate "Fusion MPT ScsiHost drivers for SAS"
        depends on PCI && SCSI
-       select FUSION
        select SCSI_SAS_ATTRS
        ---help---
          SCSI HOST support for a SAS host adapters.
@@ -53,10 +58,10 @@ config FUSION_SAS
          LSISAS1068
          LSISAS1064E
          LSISAS1068E
+         LSISAS1078
 
 config FUSION_MAX_SGE
        int "Maximum number of scatter gather entries (16 - 128)"
-       depends on FUSION
        default "128"
        range 16 128
        help
@@ -104,7 +109,6 @@ config FUSION_LAN
 
 config FUSION_LOGGING
        bool "Fusion MPT logging facility"
-       depends on FUSION
        ---help---
          This turns on a logging facility that can be used to debug a number
          of Fusion MPT related problems.
@@ -113,7 +117,7 @@ config FUSION_LOGGING
 
          echo [level] > /sys/class/scsi_host/host#/debug_level
 
-         There are various debug levels that an be found in the source:
+         There are various debug levels that can be found in the source:
          file:drivers/message/fusion/mptdebug.h
 
-endmenu
+endif # FUSION
index 6a92e3d118fed008fd6c93bcb37794b97d25cc21..1acbdd61b670e421c7f410e44c56c16821589362 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *           Name:  mpi.h
index eda769730e39d3e6f789906f4ce27d95d6648e56..2bd8adae0f002f0a01f3b052be8da4898bff2ac2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *           Name:  mpi_cnfg.h
index 51a6aeb990ba0bc5c8580b38dad8b72d4ab4bb0f..627acfbb86231fc7ea07fb6b95d2b5e83629382f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *           Name:  mpi_fc.h
index a1f479057ea3ad1c3d0eabcc4ab907dae391518b..241592ab13adb6bc8ceddb9e3c9beec78c6c6f18 100644 (file)
@@ -3,7 +3,7 @@
  MPI Header File Change History
  ==============================
 
- Copyright (c) 2000-2007 LSI Logic Corporation.
+ Copyright (c) 2000-2007 LSI Corporation.
 
  ---------------------------------------
  Header Set Release Version:    01.05.16
index 3a02615f12d6f501eeead8a30e12efc0fe18c473..a9e3693601a7e57daeea38128256020328490b27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *           Name:  mpi_init.h
index b1893d185bc43d9d15916c335e41e5cd8cbfa135..5cbb6bd048e146ae2e508661edfe9272b82ae31c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *           Name:  mpi_ioc.h
index dc0b52ae83ddae767d8920adc839fcb72b415a28..03253b53b7855d8b7a7d279bf677653ab5d3ab16 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *           Name:  mpi_lan.h
index dc98d46f9071159d0af811f20c05a7127a857fb6..e4dafcefeecde600d951ea8e95445e875f489352 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *  Copyright (c) 2000-2001 LSI Corporation. All rights reserved.
  *
  *  NAME:           fc_log.h
  *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
index 635bbe04513e44ac04893c5b0a3609fdd63d3e9c..6be1f6b65777a07208da7ad26eb084c7c8308b7e 100644 (file)
@@ -1,6 +1,6 @@
 /***************************************************************************
  *                                                                         *
- *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
+ *  Copyright 2003 LSI Corporation.  All rights reserved.            *
  *                                                                         *
  * Description                                                             *
  * ------------                                                            *
index 32819b1ec8ec5f7f40c36c15c9010282bc5ea2cd..2856108421d71fa1b88d73a45e7f38765cf012d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2001-2007 LSI Logic Corporation.
+ *  Copyright (c) 2001-2007 LSI Corporation.
  *
  *
  *           Name:  mpi_raid.h
index 8e990a0fa7a214287e17eef7ad60adc79739cadd..33fca83cefc24f86286712979c4102d4ea71a3cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2004-2006 LSI Logic Corporation.
+ *  Copyright (c) 2004-2006 LSI Corporation.
  *
  *
  *           Name:  mpi_sas.h
index 20b66731577334746b83a1ee643346850d955ab3..ff8c37d3fdcb8e6a4fd660dddcaa70942cbb5186 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *           Name:  mpi_targ.h
index aa9053da1f58c580b767410b508db6a41a7dd679..8834ae6ce0f2b7cd66691729032829c5147f0f8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2001-2005 LSI Logic Corporation.
+ *  Copyright (c) 2001-2005 LSI Corporation.
  *
  *
  *           Name:  mpi_tool.h
index 32cc9b1151b8b2bdfdb5294463c8388e95322db0..08dad9c1e4465e9bd3db4c03fe4c16bfeb0df621 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *           Name:  mpi_type.h
index 414c109f4cf5f8ef92ac17cd56790574d760cf3d..52fb216dfe7448ee0c5dbdfdac3db24c4787db2f 100644 (file)
@@ -2,10 +2,10 @@
  *  linux/drivers/message/fusion/mptbase.c
  *      This is the Fusion MPT base driver which supports multiple
  *      (SCSI + LAN) specialized protocol drivers.
- *      For use with LSI Logic PCI chip/adapter(s)
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI PCI chip/adapter(s)
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -102,8 +102,6 @@ static int mfcounter = 0;
 /*
  *  Public data...
  */
-int mpt_lan_index = -1;
-int mpt_stm_index = -1;
 
 struct proc_dir_entry *mpt_proc_root_dir;
 
@@ -125,11 +123,14 @@ static MPT_EVHANDLER               MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 static MPT_RESETHANDLER                 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 static struct mpt_pci_driver   *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 
-static int     mpt_base_index = -1;
-static int     last_drv_idx = -1;
-
 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
 
+/*
+ *  Driver Callback Index's
+ */
+static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
+static u8 last_drv_idx;
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Forward protos...
@@ -235,6 +236,23 @@ static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
        return 0;
 }
 
+/**
+ *     mpt_get_cb_idx - obtain cb_idx for registered driver
+ *     @dclass: class driver enum
+ *
+ *     Returns cb_idx, or zero means it wasn't found
+ **/
+static u8
+mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
+{
+       u8 cb_idx;
+
+       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
+               if (MptDriverClass[cb_idx] == dclass)
+                       return cb_idx;
+       return 0;
+}
+
 /*
  *  Process turbo (context) reply...
  */
@@ -243,8 +261,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
 {
        MPT_FRAME_HDR *mf = NULL;
        MPT_FRAME_HDR *mr = NULL;
-       int req_idx = 0;
-       int cb_idx;
+       u16 req_idx = 0;
+       u8 cb_idx;
 
        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
                                ioc->name, pa));
@@ -256,7 +274,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
                mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
                break;
        case MPI_CONTEXT_REPLY_TYPE_LAN:
-               cb_idx = mpt_lan_index;
+               cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
                /*
                 *  Blind set of mf to NULL here was fatal
                 *  after lan_reply says "freeme"
@@ -277,7 +295,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
                mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
                break;
        case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
-               cb_idx = mpt_stm_index;
+               cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
                mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
                break;
        default:
@@ -286,8 +304,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
        }
 
        /*  Check for (valid) IO callback!  */
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
-                       MptCallbacks[cb_idx] == NULL) {
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+               MptCallbacks[cb_idx] == NULL) {
                printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
                                __FUNCTION__, ioc->name, cb_idx);
                goto out;
@@ -304,8 +322,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 {
        MPT_FRAME_HDR   *mf;
        MPT_FRAME_HDR   *mr;
-       int              req_idx;
-       int              cb_idx;
+       u16              req_idx;
+       u8               cb_idx;
        int              freeme;
 
        u32 reply_dma_low;
@@ -331,7 +349,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 
        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
                        ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
-       DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr)
+       DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
 
         /*  Check/log IOC log info
         */
@@ -350,8 +368,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
                mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
 
        /*  Check for (valid) IO callback!  */
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
-                       MptCallbacks[cb_idx] == NULL) {
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+               MptCallbacks[cb_idx] == NULL) {
                printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
                                __FUNCTION__, ioc->name, cb_idx);
                freeme = 0;
@@ -433,8 +451,9 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 #ifdef CONFIG_FUSION_LOGGING
        if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
                        !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
-               dmfprintk(ioc, printk(KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
-               DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf)
+               dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
+                   ioc->name, mf));
+               DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
        }
 #endif
 
@@ -499,8 +518,8 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
                                u16              status;
 
                                status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-                               dcprintk(ioc, printk(KERN_NOTICE "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
-                                    status, le32_to_cpu(pReply->IOCLogInfo)));
+                               dcprintk(ioc, printk(MYIOC_s_NOTE_FMT "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
+                                    ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
 
                                pCfg->status = status;
                                if (status == MPI_IOCSTATUS_SUCCESS) {
@@ -563,28 +582,27 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
  *     in order to register separate callbacks; one for "normal" SCSI IO;
  *     one for MptScsiTaskMgmt requests; one for Scan/DV requests.
  *
- *     Returns a positive integer valued "handle" in the
- *     range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
- *     Any non-positive return value (including zero!) should be considered
- *     an error by the caller.
+ *     Returns u8 valued "handle" in the range (and S.O.D. order)
+ *     {N,...,7,6,5,...,1} if successful.
+ *     A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
+ *     considered an error by the caller.
  */
-int
+u8
 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
 {
-       int i;
-
-       last_drv_idx = -1;
+       u8 cb_idx;
+       last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
 
        /*
         *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
         *  (slot/handle 0 is reserved!)
         */
-       for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
-               if (MptCallbacks[i] == NULL) {
-                       MptCallbacks[i] = cbfunc;
-                       MptDriverClass[i] = dclass;
-                       MptEvHandlers[i] = NULL;
-                       last_drv_idx = i;
+       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+               if (MptCallbacks[cb_idx] == NULL) {
+                       MptCallbacks[cb_idx] = cbfunc;
+                       MptDriverClass[cb_idx] = dclass;
+                       MptEvHandlers[cb_idx] = NULL;
+                       last_drv_idx = cb_idx;
                        break;
                }
        }
@@ -601,9 +619,9 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
  *     module is unloaded.
  */
 void
-mpt_deregister(int cb_idx)
+mpt_deregister(u8 cb_idx)
 {
-       if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
+       if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
                MptCallbacks[cb_idx] = NULL;
                MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
                MptEvHandlers[cb_idx] = NULL;
@@ -625,9 +643,9 @@ mpt_deregister(int cb_idx)
  *     Returns 0 for success.
  */
 int
-mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
+mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
 {
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return -1;
 
        MptEvHandlers[cb_idx] = ev_cbfunc;
@@ -645,9 +663,9 @@ mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
  *     or when its module is unloaded.
  */
 void
-mpt_event_deregister(int cb_idx)
+mpt_event_deregister(u8 cb_idx)
 {
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return;
 
        MptEvHandlers[cb_idx] = NULL;
@@ -665,9 +683,9 @@ mpt_event_deregister(int cb_idx)
  *     Returns 0 for success.
  */
 int
-mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
+mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
 {
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return -1;
 
        MptResetHandlers[cb_idx] = reset_func;
@@ -684,9 +702,9 @@ mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
  *     or when its module is unloaded.
  */
 void
-mpt_reset_deregister(int cb_idx)
+mpt_reset_deregister(u8 cb_idx)
 {
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return;
 
        MptResetHandlers[cb_idx] = NULL;
@@ -699,12 +717,12 @@ mpt_reset_deregister(int cb_idx)
  *     @cb_idx: MPT protocol driver index
  */
 int
-mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
+mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
 {
        MPT_ADAPTER     *ioc;
        const struct pci_device_id *id;
 
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return -EINVAL;
 
        MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
@@ -726,12 +744,12 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
  *     @cb_idx: MPT protocol driver index
  */
 void
-mpt_device_driver_deregister(int cb_idx)
+mpt_device_driver_deregister(u8 cb_idx)
 {
        struct mpt_pci_driver *dd_cbfunc;
        MPT_ADAPTER     *ioc;
 
-       if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+       if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
                return;
 
        dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
@@ -749,14 +767,14 @@ mpt_device_driver_deregister(int cb_idx)
 /**
  *     mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
  *     allocated per MPT adapter.
- *     @handle: Handle of registered MPT protocol driver
+ *     @cb_idx: Handle of registered MPT protocol driver
  *     @ioc: Pointer to MPT adapter structure
  *
  *     Returns pointer to a MPT request frame or %NULL if none are available
  *     or IOC is not active.
  */
 MPT_FRAME_HDR*
-mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
+mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
 {
        MPT_FRAME_HDR *mf;
        unsigned long flags;
@@ -766,7 +784,8 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 
 #ifdef MFCNT
        if (!ioc->active)
-               printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
+               printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
+                   "returning NULL!\n", ioc->name);
 #endif
 
        /* If interrupts are not attached, do not return a request frame */
@@ -781,13 +800,14 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
                                u.frame.linkage.list);
                list_del(&mf->u.frame.linkage.list);
                mf->u.frame.linkage.arg1 = 0;
-               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;  /* byte */
+               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;  /* byte */
                req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
                                                                /* u16! */
                req_idx = req_offset / ioc->req_sz;
                mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
                mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
-               ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
+               /* Default, will be changed if necessary in SG generation */
+               ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
 #ifdef MFCNT
                ioc->mfcnt++;
 #endif
@@ -798,14 +818,17 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 
 #ifdef MFCNT
        if (mf == NULL)
-               printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
+               printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
+                   "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
+                   ioc->req_depth);
        mfcounter++;
        if (mfcounter == PRINT_MF_COUNT)
-               printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
+               printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
+                   ioc->mfcnt, ioc->req_depth);
 #endif
 
-       dmfprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
-                       ioc->name, handle, ioc->id, mf));
+       dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
+           ioc->name, cb_idx, ioc->id, mf));
        return mf;
 }
 
@@ -813,7 +836,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 /**
  *     mpt_put_msg_frame - Send a protocol specific MPT request frame
  *     to a IOC.
- *     @handle: Handle of registered MPT protocol driver
+ *     @cb_idx: Handle of registered MPT protocol driver
  *     @ioc: Pointer to MPT adapter structure
  *     @mf: Pointer to MPT request frame
  *
@@ -821,14 +844,14 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
  *     specific MPT adapter.
  */
 void
-mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
+mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
        u32 mf_dma_addr;
        int req_offset;
        u16      req_idx;       /* Request index */
 
        /* ensure values are reset properly! */
-       mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;          /* byte */
+       mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;          /* byte */
        req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
                                                                /* u16! */
        req_idx = req_offset / ioc->req_sz;
@@ -838,10 +861,44 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
        DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
 
        mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
-       dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
+       dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
+           "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
+           ioc->RequestNB[req_idx]));
        CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
 }
 
+/**
+ *     mpt_put_msg_frame_hi_pri - Send a protocol specific MPT request frame
+ *     to a IOC using hi priority request queue.
+ *     @cb_idx: Handle of registered MPT protocol driver
+ *     @ioc: Pointer to MPT adapter structure
+ *     @mf: Pointer to MPT request frame
+ *
+ *     This routine posts a MPT request frame to the request post FIFO of a
+ *     specific MPT adapter.
+ **/
+void
+mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
+{
+       u32 mf_dma_addr;
+       int req_offset;
+       u16      req_idx;       /* Request index */
+
+       /* ensure values are reset properly! */
+       mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
+       req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
+       req_idx = req_offset / ioc->req_sz;
+       mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
+       mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+
+       DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
+
+       mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
+       dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
+               ioc->name, mf_dma_addr, req_idx));
+       CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_free_msg_frame - Place MPT request frame back on FreeQ.
@@ -899,7 +956,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_send_handshake_request - Send MPT request via doorbell handshake method.
- *     @handle: Handle of registered MPT protocol driver
+ *     @cb_idx: Handle of registered MPT protocol driver
  *     @ioc: Pointer to MPT adapter structure
  *     @reqBytes: Size of the request in bytes
  *     @req: Pointer to MPT request frame
@@ -914,7 +971,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
  *     Returns 0 for success, non-zero for failure.
  */
 int
-mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
+mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
 {
        int     r = 0;
        u8      *req_as_bytes;
@@ -934,7 +991,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
        if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
                MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
                mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
-               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
+               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
        }
 
        /* Make sure there are no doorbells */
@@ -953,7 +1010,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
        if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
                return -5;
 
-       dhsprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
+       dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
                ioc->name, ii));
 
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
@@ -1395,11 +1452,13 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        MPT_ADAPTER     *ioc;
        u8              __iomem *mem;
+       u8              __iomem *pmem;
        unsigned long    mem_phys;
        unsigned long    port;
        u32              msize;
        u32              psize;
        int              ii;
+       u8               cb_idx;
        int              r = -ENODEV;
        u8               revision;
        u8               pcixcmd;
@@ -1408,35 +1467,39 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        struct proc_dir_entry *dent, *ent;
 #endif
 
+       if (mpt_debug_level)
+               printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level);
+
+       if (pci_enable_device(pdev))
+               return r;
+
        ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
        if (ioc == NULL) {
                printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
                return -ENOMEM;
        }
-
        ioc->debug_level = mpt_debug_level;
-       if (mpt_debug_level)
-               printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level);
-
-       if (pci_enable_device(pdev))
-               return r;
+       ioc->id = mpt_ids++;
+       sprintf(ioc->name, "ioc%d", ioc->id);
 
-       dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
 
        if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-               dprintk(ioc, printk(KERN_INFO MYNAM
-                       ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
+               dprintk(ioc, printk(MYIOC_s_INFO_FMT
+                       ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", ioc->name));
        } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
-               printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
+               printk(MYIOC_s_WARN_FMT ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n",
+                   ioc->name);
+               kfree(ioc);
                return r;
        }
 
        if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
-               dprintk(ioc, printk(KERN_INFO MYNAM
-                       ": Using 64 bit consistent mask\n"));
+               dprintk(ioc, printk(MYIOC_s_INFO_FMT
+                       ": Using 64 bit consistent mask\n", ioc->name));
        } else {
-               dprintk(ioc, printk(KERN_INFO MYNAM
-                       ": Not using 64 bit consistent mask\n"));
+               dprintk(ioc, printk(MYIOC_s_INFO_FMT
+                       ": Not using 64 bit consistent mask\n", ioc->name));
        }
 
        ioc->alloc_total = sizeof(MPT_ADAPTER);
@@ -1475,7 +1538,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* Find lookup slot. */
        INIT_LIST_HEAD(&ioc->list);
-       ioc->id = mpt_ids++;
 
        mem_phys = msize = 0;
        port = psize = 0;
@@ -1501,25 +1563,23 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        /*mem = ioremap(mem_phys, msize);*/
        mem = ioremap(mem_phys, msize);
        if (mem == NULL) {
-               printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
+               printk(MYIOC_s_ERR_FMT "Unable to map adapter memory!\n", ioc->name);
                kfree(ioc);
                return -EINVAL;
        }
        ioc->memmap = mem;
-       dinitprintk(ioc, printk(KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n", ioc->name, mem, mem_phys));
 
-       dinitprintk(ioc, printk(KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
-                       &ioc->facts, &ioc->pfacts[0]));
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
+           ioc->name, &ioc->facts, &ioc->pfacts[0]));
 
        ioc->mem_phys = mem_phys;
        ioc->chip = (SYSIF_REGS __iomem *)mem;
 
        /* Save Port IO values in case we need to do downloadboot */
-       {
-               u8 *pmem = (u8*)port;
-               ioc->pio_mem_phys = port;
-               ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
-       }
+       ioc->pio_mem_phys = port;
+       pmem = (u8 __iomem *)port;
+       ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
 
        pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
        mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
@@ -1591,8 +1651,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        if (ioc->errata_flag_1064)
                pci_disable_io_access(pdev);
 
-       sprintf(ioc->name, "ioc%d", ioc->id);
-
        spin_lock_init(&ioc->FreeQlock);
 
        /* Disable all! */
@@ -1609,9 +1667,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 
        if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
            CAN_SLEEP)) != 0){
-               printk(KERN_WARNING MYNAM
-                 ": WARNING - %s did not initialize properly! (%d)\n",
-                 ioc->name, r);
+               printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
+                   ioc->name, r);
 
                list_del(&ioc->list);
                if (ioc->alt_ioc)
@@ -1623,10 +1680,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* call per device driver probe entry point */
-       for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-               if(MptDeviceDriverHandlers[ii] &&
-                 MptDeviceDriverHandlers[ii]->probe) {
-                       MptDeviceDriverHandlers[ii]->probe(pdev,id);
+       for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
+               if(MptDeviceDriverHandlers[cb_idx] &&
+                 MptDeviceDriverHandlers[cb_idx]->probe) {
+                       MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
                }
        }
 
@@ -1663,7 +1720,7 @@ mpt_detach(struct pci_dev *pdev)
 {
        MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
        char pname[32];
-       int ii;
+       u8 cb_idx;
 
        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
        remove_proc_entry(pname, NULL);
@@ -1673,10 +1730,10 @@ mpt_detach(struct pci_dev *pdev)
        remove_proc_entry(pname, NULL);
 
        /* call per device driver remove entry point */
-       for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-               if(MptDeviceDriverHandlers[ii] &&
-                 MptDeviceDriverHandlers[ii]->remove) {
-                       MptDeviceDriverHandlers[ii]->remove(pdev);
+       for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
+               if(MptDeviceDriverHandlers[cb_idx] &&
+                 MptDeviceDriverHandlers[cb_idx]->remove) {
+                       MptDeviceDriverHandlers[cb_idx]->remove(pdev);
                }
        }
 
@@ -1788,7 +1845,7 @@ mpt_resume(struct pci_dev *pdev)
 #endif
 
 static int
-mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
+mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
 {
        if ((MptDriverClass[index] == MPTSPI_DRIVER &&
             ioc->bus_type != SPI) ||
@@ -1830,14 +1887,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
        int      hard;
        int      rc=0;
        int      ii;
+       u8       cb_idx;
        int      handlers;
        int      ret = 0;
        int      reset_alt_ioc_active = 0;
        int      irq_allocated = 0;
        u8      *a;
 
-       printk(KERN_INFO MYNAM ": Initiating %s %s\n",
-                       ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
+       printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
+           reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
 
        /* Disable reply interrupts (also blocks FreeQ) */
        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
@@ -1858,21 +1916,19 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 
        if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
                if (hard_reset_done == -4) {
-                       printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
-                                       ioc->name);
+                       printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
+                           ioc->name);
 
                        if (reset_alt_ioc_active && ioc->alt_ioc) {
                                /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
-                               dprintk(ioc, printk(KERN_INFO MYNAM
-                                       ": alt-%s reply irq re-enabled\n",
-                                               ioc->alt_ioc->name));
+                               dprintk(ioc, printk(MYIOC_s_INFO_FMT
+                                   "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
                                CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
                                ioc->alt_ioc->active = 1;
                        }
 
                } else {
-                       printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
-                                       ioc->name);
+                       printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
                }
                return -1;
        }
@@ -1884,9 +1940,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
                        alt_ioc_ready = 1;
                else
-                       printk(KERN_WARNING MYNAM
-                                       ": alt-%s: Not ready WARNING!\n",
-                                       ioc->alt_ioc->name);
+                       printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
        }
 
        for (ii=0; ii<5; ii++) {
@@ -1897,7 +1951,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 
 
        if (ii == 5) {
-               dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
+               dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "Retry IocFacts failed rc=%x\n", ioc->name, rc));
                ret = -2;
        } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
                MptDisplayIocCapabilities(ioc);
@@ -1906,14 +1961,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
        if (alt_ioc_ready) {
                if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                               "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
+                           "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
                        /* Retry - alt IOC was initialized once
                         */
                        rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
                }
                if (rc) {
                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                               "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
+                           "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
                        alt_ioc_ready = 0;
                        reset_alt_ioc_active = 0;
                } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
@@ -1931,13 +1986,12 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                if (ioc->pcidev->irq) {
                        if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
                                printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
-                                       ioc->name);
+                                   ioc->name);
                        rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
-                                       IRQF_SHARED, ioc->name, ioc);
+                           IRQF_SHARED, ioc->name, ioc);
                        if (rc < 0) {
                                printk(MYIOC_s_ERR_FMT "Unable to allocate "
-                                       "interrupt %d!\n", ioc->name,
-                                       ioc->pcidev->irq);
+                                   "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
                                if (mpt_msi_enable)
                                        pci_disable_msi(ioc->pcidev);
                                return -EBUSY;
@@ -1946,8 +2000,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                        ioc->pci_irq = ioc->pcidev->irq;
                        pci_set_master(ioc->pcidev);            /* ?? */
                        pci_set_drvdata(ioc->pcidev, ioc);
-                       dprintk(ioc, printk(KERN_INFO MYNAM ": %s installed at interrupt "
-                               "%d\n", ioc->name, ioc->pcidev->irq));
+                       dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
+                           "%d\n", ioc->name, ioc->pcidev->irq));
                }
        }
 
@@ -1966,8 +2020,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                ret = -4;
 // NEW!
        if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
-               printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
-                               ioc->alt_ioc->name, rc);
+               printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
+                   ioc->alt_ioc->name, rc);
                alt_ioc_ready = 0;
                reset_alt_ioc_active = 0;
        }
@@ -1976,16 +2030,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
                        alt_ioc_ready = 0;
                        reset_alt_ioc_active = 0;
-                       printk(KERN_WARNING MYNAM
-                               ": alt-%s: (%d) init failure WARNING!\n",
-                                       ioc->alt_ioc->name, rc);
+                       printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
+                           ioc->alt_ioc->name, rc);
                }
        }
 
        if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
                if (ioc->upload_fw) {
                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                               "firmware upload required!\n", ioc->name));
+                           "firmware upload required!\n", ioc->name));
 
                        /* Controller is not operational, cannot do upload
                         */
@@ -2001,12 +2054,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                                                 * mpt_diag_reset)
                                                 */
                                                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                                       ": mpt_upload:  alt_%s has cached_fw=%p \n",
-                                                       ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
+                                                   "mpt_upload:  alt_%s has cached_fw=%p \n",
+                                                   ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
                                                ioc->alt_ioc->cached_fw = NULL;
                                        }
                                } else {
-                                       printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+                                       printk(MYIOC_s_WARN_FMT
+                                           "firmware upload failure!\n", ioc->name);
                                        ret = -5;
                                }
                        }
@@ -2021,8 +2075,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 
        if (reset_alt_ioc_active && ioc->alt_ioc) {
                /* (re)Enable alt-IOC! (reply interrupt) */
-               dinitprintk(ioc, printk(KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
-                               ioc->alt_ioc->name));
+               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
+                   ioc->alt_ioc->name));
                CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
                ioc->alt_ioc->active = 1;
        }
@@ -2075,10 +2129,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                                (void) GetLanConfigPages(ioc);
                                a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                       "LanAddr = %02X:%02X:%02X:"
-                                       "%02X:%02X:%02X\n",
-                                       ioc->name, a[5], a[4],
-                                       a[3], a[2], a[1], a[0] ));
+                                   "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+                                   ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
 
                        }
                } else {
@@ -2114,20 +2166,20 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
         */
        if (hard_reset_done) {
                rc = handlers = 0;
-               for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
-                       if ((ret == 0) && MptResetHandlers[ii]) {
+               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+                       if ((ret == 0) && MptResetHandlers[cb_idx]) {
                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                       "Calling IOC post_reset handler #%d\n",
-                                       ioc->name, ii));
-                               rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
+                                   "Calling IOC post_reset handler #%d\n",
+                                   ioc->name, cb_idx));
+                               rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
                                handlers++;
                        }
 
-                       if (alt_ioc_ready && MptResetHandlers[ii]) {
+                       if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
                                drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                       "Calling alt-%s post_reset handler #%d\n",
-                                       ioc->name, ioc->alt_ioc->name, ii));
-                               rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
+                                   "Calling IOC post_reset handler #%d\n",
+                                   ioc->alt_ioc->name, cb_idx));
+                               rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
                                handlers++;
                        }
                }
@@ -2166,8 +2218,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
 
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
            " searching for devfn match on %x or %x\n",
-               ioc->name, pci_name(pdev), pdev->bus->number,
-               pdev->devfn, func-1, func+1));
+           ioc->name, pci_name(pdev), pdev->bus->number,
+           pdev->devfn, func-1, func+1));
 
        peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
        if (!peer) {
@@ -2181,15 +2233,15 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
                if (_pcidev == peer) {
                        /* Paranoia checks */
                        if (ioc->alt_ioc != NULL) {
-                               printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
+                               printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
                                        ioc->name, ioc->alt_ioc->name);
                                break;
                        } else if (ioc_srch->alt_ioc != NULL) {
-                               printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
+                               printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
                                        ioc_srch->name, ioc_srch->alt_ioc->name);
                                break;
                        }
-                       dprintk(ioc, printk(KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
+                       dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
                                ioc->name, ioc_srch->name));
                        ioc_srch->alt_ioc = ioc;
                        ioc->alt_ioc = ioc_srch;
@@ -2210,10 +2262,11 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
        int ret;
 
        if (ioc->cached_fw != NULL) {
-               ddlprintk(ioc, printk(KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
+               ddlprintk(ioc, printk(MYIOC_s_INFO_FMT
+                   "mpt_adapter_disable: Pushing FW onto adapter\n", ioc->name));
                if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
-                       printk(KERN_WARNING MYNAM
-                               ": firmware downloadboot failure (%d)!\n", ret);
+                       printk(MYIOC_s_WARN_FMT "firmware downloadboot failure (%d)!\n",
+                           ioc->name, ret);
                }
        }
 
@@ -2225,8 +2278,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 
        if (ioc->alloc != NULL) {
                sz = ioc->alloc_sz;
-               dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s.free  @ %p, sz=%d bytes\n",
-                       ioc->name, ioc->alloc, ioc->alloc_sz));
+               dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free  @ %p, sz=%d bytes\n",
+                   ioc->name, ioc->alloc, ioc->alloc_sz));
                pci_free_consistent(ioc->pcidev, sz,
                                ioc->alloc, ioc->alloc_dma);
                ioc->reply_frames = NULL;
@@ -2286,15 +2339,14 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
        if (ioc->HostPageBuffer != NULL) {
                if((ret = mpt_host_page_access_control(ioc,
                    MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
-                       printk(KERN_ERR MYNAM
-                          ": %s: host page buffers free failed (%d)!\n",
-                           __FUNCTION__, ret);
+                       printk(MYIOC_s_ERR_FMT
+                          "host page buffers free failed (%d)!\n",
+                           ioc->name, ret);
                }
-               dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s HostPageBuffer free  @ %p, sz=%d bytes\n",
+               dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free  @ %p, sz=%d bytes\n",
                        ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
                pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
-                               ioc->HostPageBuffer,
-                               ioc->HostPageBuffer_dma);
+                   ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
                ioc->HostPageBuffer = NULL;
                ioc->HostPageBuffer_sz = 0;
                ioc->alloc_total -= ioc->HostPageBuffer_sz;
@@ -2336,7 +2388,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
 #if defined(CONFIG_MTRR) && 0
        if (ioc->mtrr_reg > 0) {
                mtrr_del(ioc->mtrr_reg, 0, 0);
-               dprintk(ioc, printk(KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
+               dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
        }
 #endif
 
@@ -2344,8 +2396,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
        list_del(&ioc->list);
 
        sz_last = ioc->alloc_total;
-       dprintk(ioc, printk(KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
-                       ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+       dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
+           ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
 
        if (ioc->alt_ioc)
                ioc->alt_ioc->alt_ioc = NULL;
@@ -2424,7 +2476,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
 
        /* Get current [raw] IOC state  */
        ioc_state = mpt_GetIocState(ioc, 0);
-       dhsprintk(ioc, printk(KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
+       dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
 
        /*
         *      Check to see if IOC got left/stuck in doorbell handshake
@@ -2446,9 +2498,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
        if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
                statefault = 2;
                printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
-                               ioc->name);
-               printk(KERN_WARNING "           FAULT code = %04xh\n",
-                               ioc_state & MPI_DOORBELL_DATA_MASK);
+                   ioc->name);
+               printk(MYIOC_s_WARN_FMT "           FAULT code = %04xh\n",
+                   ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
        }
 
        /*
@@ -2464,9 +2516,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
                 * Else, fall through to KickStart case
                 */
                whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
-               dinitprintk(ioc, printk(KERN_INFO MYNAM
-                       "whoinit 0x%x statefault %d force %d\n",
-                       whoinit, statefault, force));
+               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+                       "whoinit 0x%x statefault %d force %d\n",
+                       ioc->name, whoinit, statefault, force));
                if (whoinit == MPI_WHOINIT_PCI_PEER)
                        return -4;
                else {
@@ -2549,7 +2601,6 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
 
        /*  Get!  */
        s = CHIPREG_READ32(&ioc->chip->Doorbell);
-//     dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
        sc = s & MPI_IOC_STATE_MASK;
 
        /*  Save!  */
@@ -2581,9 +2632,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 
        /* IOC *must* NOT be in RESET state! */
        if (ioc->last_state == MPI_IOC_STATE_RESET) {
-               printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
-                               ioc->name,
-                               ioc->last_state );
+               printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
+                   ioc->name, ioc->last_state );
                return -44;
        }
 
@@ -2703,8 +2753,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
                }
                ioc->NBShiftFactor  = shiftFactor;
                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                       "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
-                       ioc->name, vv, shiftFactor, r));
+                   "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+                   ioc->name, vv, shiftFactor, r));
 
                if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
                        /*
@@ -2757,9 +2807,8 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 
        /* IOC *must* NOT be in RESET state! */
        if (ioc->last_state == MPI_IOC_STATE_RESET) {
-               printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
-                               ioc->name,
-                               ioc->last_state );
+               printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
+                   ioc->name, ioc->last_state );
                return -4;
        }
 
@@ -2934,7 +2983,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
                state = mpt_GetIocState(ioc, 1);
                count++;
        }
-       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
                        ioc->name, count));
 
        ioc->aen_event_read_flag=0;
@@ -3027,10 +3076,9 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
        int sz;
 
        sz = ioc->facts.FWImageSize;
-       dinitprintk(ioc, printk(KERN_INFO MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
-                ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
-       pci_free_consistent(ioc->pcidev, sz,
-                       ioc->cached_fw, ioc->cached_fw_dma);
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+           ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+       pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
        ioc->cached_fw = NULL;
 
        return;
@@ -3054,7 +3102,6 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
 static int
 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 {
-       u8                       request[ioc->req_sz];
        u8                       reply[sizeof(FWUploadReply_t)];
        FWUpload_t              *prequest;
        FWUploadReply_t         *preply;
@@ -3071,8 +3118,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 
        mpt_alloc_fw_memory(ioc, sz);
 
-       dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
-                ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+           ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
 
        if (ioc->cached_fw == NULL) {
                /* Major Failure.
@@ -3080,11 +3127,16 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
                return -ENOMEM;
        }
 
-       prequest = (FWUpload_t *)&request;
-       preply = (FWUploadReply_t *)&reply;
+       prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
+           kzalloc(ioc->req_sz, GFP_KERNEL);
+       if (!prequest) {
+               dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
+                   "while allocating memory \n", ioc->name));
+               mpt_free_fw_memory(ioc);
+               return -ENOMEM;
+       }
 
-       /*  Destination...  */
-       memset(prequest, 0, ioc->req_sz);
+       preply = (FWUploadReply_t *)&reply;
 
        reply_sz = sizeof(reply);
        memset(preply, 0, reply_sz);
@@ -3096,21 +3148,22 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
        ptcsge->DetailsLength = 12;
        ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
        ptcsge->ImageSize = cpu_to_le32(sz);
+       ptcsge++;
 
        sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
 
        flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
-       mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
+       mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
 
        sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-       dinitprintk(ioc, printk(KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
-                       prequest, sgeoffset));
-       DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest)
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
+           ioc->name, prequest, sgeoffset));
+       DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
 
        ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
                                reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
 
-       dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
 
        cmdStatus = -EFAULT;
        if (ii == 0) {
@@ -3135,6 +3188,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
                        ioc->name));
                mpt_free_fw_memory(ioc);
        }
+       kfree(prequest);
 
        return cmdStatus;
 }
@@ -3381,7 +3435,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
        u32 ioc_state=0;
        int cnt,cntdn;
 
-       dinitprintk(ioc, printk(KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
+       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
        if (ioc->bus_type == SPI) {
                /* Always issue a Msg Unit Reset first. This will clear some
                 * SCSI bus hang conditions.
@@ -3400,7 +3454,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
                return hard_reset_done;
 
        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
-                       ioc->name));
+               ioc->name));
 
        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;     /* 2 seconds */
        for (cnt=0; cnt<cntdn; cnt++) {
@@ -3417,8 +3471,8 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
                }
        }
 
-       printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
-                       ioc->name, ioc_state);
+       dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
+               ioc->name, mpt_GetIocState(ioc, 0)));
        return -1;
 }
 
@@ -3560,20 +3614,20 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                 * MptResetHandlers[] registered yet.
                 */
                {
-                       int      ii;
+                       u8       cb_idx;
                        int      r = 0;
 
-                       for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
-                               if (MptResetHandlers[ii]) {
+                       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+                               if (MptResetHandlers[cb_idx]) {
                                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                                                "Calling IOC pre_reset handler #%d\n",
-                                               ioc->name, ii));
-                                       r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
+                                               ioc->name, cb_idx));
+                                       r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
                                        if (ioc->alt_ioc) {
                                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                                                        "Calling alt-%s pre_reset handler #%d\n",
-                                                       ioc->name, ioc->alt_ioc->name, ii));
-                                               r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
+                                                       ioc->name, ioc->alt_ioc->name, cb_idx));
+                                               r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
                                        }
                                }
                        }
@@ -3606,8 +3660,8 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                        }
                        if ((count = mpt_downloadboot(ioc,
                                (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
-                               printk(KERN_WARNING MYNAM
-                                       ": firmware downloadboot failure (%d)!\n", count);
+                               printk(MYIOC_s_WARN_FMT
+                                       "firmware downloadboot failure (%d)!\n", ioc->name, count);
                        }
 
                } else {
@@ -3750,8 +3804,8 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
                        if (sleepFlag != CAN_SLEEP)
                                count *= 10;
 
-                       printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
-                                       ioc->name, (int)((count+5)/HZ));
+                       printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
+                           ioc->name, (int)((count+5)/HZ));
                        return -ETIME;
                }
 
@@ -4144,7 +4198,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
                }
 
                dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
-               DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req)
+               DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
 
                dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
                                ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
@@ -4349,7 +4403,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 #endif
 
        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
-       DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply)
+       DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
 
        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
                        ioc->name, t, u16cnt/2));
@@ -4824,8 +4878,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
 
                                if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
                                        ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
-                                       ddvprintk(ioc, printk(KERN_INFO MYNAM
-                                               " :%s noQas due to Capabilities=%x\n",
+                                       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                                               "noQas due to Capabilities=%x\n",
                                                ioc->name, pPP0->Capabilities));
                                }
                                ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
@@ -4888,6 +4942,38 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
                                /* Nvram data is left with INVALID mark
                                 */
                                rc = 1;
+                       } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
+
+                               /* This is an ATTO adapter, read Page2 accordingly
+                               */
+                               ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t  *) pbuf;
+                               ATTODeviceInfo_t *pdevice = NULL;
+                               u16 ATTOFlags;
+
+                               /* Save the Port Page 2 data
+                                * (reformat into a 32bit quantity)
+                                */
+                               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+                                 pdevice = &pPP2->DeviceSettings[ii];
+                                 ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
+                                 data = 0;
+
+                                 /* Translate ATTO device flags to LSI format
+                                  */
+                                 if (ATTOFlags & ATTOFLAG_DISC)
+                                   data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
+                                 if (ATTOFlags & ATTOFLAG_ID_ENB)
+                                   data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
+                                 if (ATTOFlags & ATTOFLAG_LUN_ENB)
+                                   data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
+                                 if (ATTOFlags & ATTOFLAG_TAGGED)
+                                   data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
+                                 if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
+                                   data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
+
+                                 data = (data << 16) | (pdevice->Period << 8) | 10;
+                                 ioc->spi_data.nvram[ii] = data;
+                               }
                        } else {
                                SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
                                MpiDeviceInfo_t *pdevice = NULL;
@@ -5701,10 +5787,10 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        CONFIGPARMS *pCfg;
        unsigned long flags;
 
-       dprintk(ioc, printk(KERN_DEBUG MYNAM
-                       ": IOC %s_reset routed to MPT base driver!\n",
-                       reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-                       reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
+       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           ": IOC %s_reset routed to MPT base driver!\n",
+           ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
+           reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 
        if (reset_phase == MPT_IOC_SETUP_RESET) {
                ;
@@ -5843,7 +5929,7 @@ procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eo
 static int
 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
 {
-       int      ii;
+       u8       cb_idx;
        int      scsi, fc, sas, lan, ctl, targ, dmp;
        char    *drvname;
        int      len;
@@ -5852,10 +5938,10 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo
        len += sprintf(buf+len, "  Fusion MPT base driver\n");
 
        scsi = fc = sas = lan = ctl = targ = dmp = 0;
-       for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
                drvname = NULL;
-               if (MptCallbacks[ii]) {
-                       switch (MptDriverClass[ii]) {
+               if (MptCallbacks[cb_idx]) {
+                       switch (MptDriverClass[cb_idx]) {
                        case MPTSPI_DRIVER:
                                if (!scsi++) drvname = "SPI host";
                                break;
@@ -6099,26 +6185,25 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
         * For all other protocol drivers, this is a no-op.
         */
        {
-               int      ii;
+               u8       cb_idx;
                int      r = 0;
 
-               for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
-                       if (MptResetHandlers[ii]) {
+               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+                       if (MptResetHandlers[cb_idx]) {
                                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
-                                               ioc->name, ii));
-                               r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
+                                               ioc->name, cb_idx));
+                               r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
                                if (ioc->alt_ioc) {
                                        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
-                                                       ioc->name, ioc->alt_ioc->name, ii));
-                                       r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
+                                                       ioc->name, ioc->alt_ioc->name, cb_idx));
+                                       r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
                                }
                        }
                }
        }
 
        if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
-               printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
-                       rc, ioc->name);
+               printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
        }
        ioc->reload_fw = 0;
        if (ioc->alt_ioc)
@@ -6515,6 +6600,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        u32 evData0 = 0;
 //     u32 evCtx;
        int ii;
+       u8 cb_idx;
        int r = 0;
        int handlers = 0;
        char evStr[EVENT_DESCR_STR_SZ];
@@ -6537,12 +6623,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
                        evStr));
 
 #ifdef CONFIG_FUSION_LOGGING
-       devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
-           ": Event data:\n"));
+       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           ": Event data:\n", ioc->name));
        for (ii = 0; ii < evDataLen; ii++)
                devtverboseprintk(ioc, printk(" %08x",
                    le32_to_cpu(pEventReply->Data[ii])));
-       devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
+       devtverboseprintk(ioc, printk("\n"));
 #endif
 
        /*
@@ -6595,11 +6681,11 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        /*
         *  Call each currently registered protocol event handler.
         */
-       for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
-               if (MptEvHandlers[ii]) {
+       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+               if (MptEvHandlers[cb_idx]) {
                        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
-                                       ioc->name, ii));
-                       r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
+                                       ioc->name, cb_idx));
+                       r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
                        handlers++;
                }
        }
@@ -7034,8 +7120,8 @@ mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
        if (!desc)
                return;
 
-       printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
-           ioc->name, ioc_status, desc, extend_desc);
+       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
+           ioc->name, ioc_status, desc, extend_desc));
 }
 
 /**
@@ -7261,7 +7347,8 @@ mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
        if (!desc)
                return;
 
-       printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc);
+       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
+           ioc->name, status, desc));
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -7283,14 +7370,13 @@ EXPORT_SYMBOL(mpt_device_driver_register);
 EXPORT_SYMBOL(mpt_device_driver_deregister);
 EXPORT_SYMBOL(mpt_get_msg_frame);
 EXPORT_SYMBOL(mpt_put_msg_frame);
+EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
 EXPORT_SYMBOL(mpt_free_msg_frame);
 EXPORT_SYMBOL(mpt_add_sge);
 EXPORT_SYMBOL(mpt_send_handshake_request);
 EXPORT_SYMBOL(mpt_verify_adapter);
 EXPORT_SYMBOL(mpt_GetIocState);
 EXPORT_SYMBOL(mpt_print_ioc_summary);
-EXPORT_SYMBOL(mpt_lan_index);
-EXPORT_SYMBOL(mpt_stm_index);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_config);
 EXPORT_SYMBOL(mpt_findImVolumes);
@@ -7308,16 +7394,16 @@ EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
 static int __init
 fusion_init(void)
 {
-       int i;
+       u8 cb_idx;
 
        show_mptmod_ver(my_NAME, my_VERSION);
        printk(KERN_INFO COPYRIGHT "\n");
 
-       for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
-               MptCallbacks[i] = NULL;
-               MptDriverClass[i] = MPTUNKNOWN_DRIVER;
-               MptEvHandlers[i] = NULL;
-               MptResetHandlers[i] = NULL;
+       for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
+               MptCallbacks[cb_idx] = NULL;
+               MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
+               MptEvHandlers[cb_idx] = NULL;
+               MptResetHandlers[cb_idx] = NULL;
        }
 
        /*  Register ourselves (mptbase) in order to facilitate
index 15ff22645844ace62cfe016d93b6efef0cf242d2..d7682e083f590c8ca39a49a346797300cff02f7e 100644 (file)
@@ -3,9 +3,9 @@
  *      High performance SCSI + LAN / Fibre Channel device drivers.
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 #ifndef MODULEAUTHOR
-#define MODULEAUTHOR   "LSI Logic Corporation"
+#define MODULEAUTHOR   "LSI Corporation"
 #endif
 
 #ifndef COPYRIGHT
 #define COPYRIGHT      "Copyright (c) 1999-2007 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.04.05"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.05"
+#define MPT_LINUX_VERSION_COMMON       "3.04.06"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.06"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
  * MPT drivers.  NOTE: Users of these macro defs must
  * themselves define their own MYNAM.
  */
+#define MYIOC_s_FMT                    MYNAM ": %s: "
 #define MYIOC_s_DEBUG_FMT              KERN_DEBUG MYNAM ": %s: "
 #define MYIOC_s_INFO_FMT               KERN_INFO MYNAM ": %s: "
 #define MYIOC_s_NOTE_FMT               KERN_NOTICE MYNAM ": %s: "
 #define MYIOC_s_WARN_FMT               KERN_WARNING MYNAM ": %s: WARNING - "
 #define MYIOC_s_ERR_FMT                        KERN_ERR MYNAM ": %s: ERROR - "
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *  ATTO UL4D associated structures and defines
+ */
+#define ATTOFLAG_DISC     0x0001
+#define ATTOFLAG_TAGGED   0x0002
+#define ATTOFLAG_WIDE_ENB 0x0008
+#define ATTOFLAG_ID_ENB   0x0010
+#define ATTOFLAG_LUN_ENB  0x0060
+
+typedef struct _ATTO_DEVICE_INFO
+{
+       u8      Offset;                                 /* 00h */
+       u8      Period;                                 /* 01h */
+       u16     ATTOFlags;                              /* 02h */
+} ATTO_DEVICE_INFO, MPI_POINTER PTR_ATTO_DEVICE_INFO,
+  ATTODeviceInfo_t, MPI_POINTER pATTODeviceInfo_t;
+
+typedef struct _ATTO_CONFIG_PAGE_SCSI_PORT_2
+{
+       CONFIG_PAGE_HEADER      Header;                 /* 00h */
+       u16                     PortFlags;              /* 04h */
+       u16                     Unused1;                /* 06h */
+       u32                     Unused2;                /* 08h */
+       ATTO_DEVICE_INFO        DeviceSettings[16];     /* 0Ch */
+} fATTO_CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_ATTO_CONFIG_PAGE_SCSI_PORT_2,
+  ATTO_SCSIPortPage2_t, MPI_POINTER pATTO_SCSIPortPage2_t;
+
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  MPT protocol driver defs...
@@ -307,7 +337,8 @@ typedef struct _SYSIF_REGS
        u32     Reserved2[2];   /* 38-3F  reserved for future use    */
        u32     RequestFifo;    /* 40     Request Post/Free FIFO     */
        u32     ReplyFifo;      /* 44     Reply   Post/Free FIFO     */
-       u32     Reserved3[2];   /* 48-4F  reserved for future use    */
+       u32     RequestHiPriFifo; /* 48   Hi Priority Request FIFO   */
+       u32     Reserved3;      /* 4C-4F  reserved for future use    */
        u32     HostIndex;      /* 50     Host Index register        */
        u32     Reserved4[15];  /* 54-8F                             */
        u32     Fubar;          /* 90     For Fubar usage            */
@@ -649,9 +680,9 @@ typedef struct _MPT_ADAPTER
        u8                       reload_fw;     /* Force a FW Reload on next reset */
        u8                       NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
        u8                       pad1[4];
-       int                      DoneCtx;
-       int                      TaskCtx;
-       int                      InternalCtx;
+       u8                       DoneCtx;
+       u8                       TaskCtx;
+       u8                       InternalCtx;
        spinlock_t               initializing_hba_lock;
        int                      initializing_hba_lock_flag;
        struct list_head         list;
@@ -668,10 +699,14 @@ typedef struct _MPT_ADAPTER
 
        struct work_struct       fc_setup_reset_work;
        struct list_head         fc_rports;
+       struct work_struct       fc_lsc_work;
+       u8                       fc_link_speed[2];
        spinlock_t               fc_rescan_work_lock;
        struct work_struct       fc_rescan_work;
        char                     fc_rescan_work_q_name[KOBJ_NAME_LEN];
        struct workqueue_struct *fc_rescan_work_q;
+       struct scsi_cmnd        **ScsiLookup;
+       spinlock_t                scsi_lookup_lock;
 } MPT_ADAPTER;
 
 /*
@@ -785,7 +820,6 @@ typedef struct _MPT_SCSI_HOST {
        MPT_ADAPTER              *ioc;
        int                       port;
        u32                       pad0;
-       struct scsi_cmnd        **ScsiLookup;
        MPT_LOCAL_REPLY          *pLocal;               /* used for internal commands */
        struct timer_list         timer;
                /* Pool of memory for holding SCpnts before doing
@@ -853,20 +887,21 @@ extern void        mpt_detach(struct pci_dev *pdev);
 extern int      mpt_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int      mpt_resume(struct pci_dev *pdev);
 #endif
-extern int      mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass);
-extern void     mpt_deregister(int cb_idx);
-extern int      mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc);
-extern void     mpt_event_deregister(int cb_idx);
-extern int      mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func);
-extern void     mpt_reset_deregister(int cb_idx);
-extern int      mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx);
-extern void     mpt_device_driver_deregister(int cb_idx);
-extern MPT_FRAME_HDR   *mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc);
+extern u8       mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass);
+extern void     mpt_deregister(u8 cb_idx);
+extern int      mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc);
+extern void     mpt_event_deregister(u8 cb_idx);
+extern int      mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func);
+extern void     mpt_reset_deregister(u8 cb_idx);
+extern int      mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx);
+extern void     mpt_device_driver_deregister(u8 cb_idx);
+extern MPT_FRAME_HDR   *mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc);
 extern void     mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
-extern void     mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
+extern void     mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
+extern void     mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void     mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
 
-extern int      mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
+extern int      mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
 extern int      mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
 extern u32      mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
 extern void     mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
@@ -884,9 +919,6 @@ extern int   mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhys
 extern struct list_head          ioc_list;
 extern struct proc_dir_entry   *mpt_proc_root_dir;
 
-extern int               mpt_lan_index;        /* needed by mptlan.c */
-extern int               mpt_stm_index;        /* needed by mptstm.c */
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #endif         /* } __KERNEL__ */
 
index 89695e705bdc936b72df4dca3a98b3364ee58f3b..6029509702d35e02b92f76fc1546007c39ee5299 100644 (file)
@@ -1,10 +1,10 @@
 /*
  *  linux/drivers/message/fusion/mptctl.c
  *      mpt Ioctl driver.
- *      For use with LSI Logic PCI chip/adapters
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI PCI chip/adapters
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -66,8 +66,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-#define COPYRIGHT      "Copyright (c) 1999-2007 LSI Logic Corporation"
-#define MODULEAUTHOR   "LSI Logic Corporation"
+#define COPYRIGHT      "Copyright (c) 1999-2007 LSI Corporation"
+#define MODULEAUTHOR   "LSI Corporation"
 #include "mptbase.h"
 #include "mptctl.h"
 
@@ -83,7 +83,7 @@ MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-static int mptctl_id = -1;
+static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
 
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
@@ -181,7 +181,6 @@ static inline int
 mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
 {
        int rc = 0;
-//     dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
 
        if (nonblock) {
                if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
@@ -190,7 +189,6 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
                if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
                        rc = -ERESTARTSYS;
        }
-//     dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down return %d\n", rc));
        return rc;
 }
 
@@ -342,7 +340,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
        SCSITaskMgmt_t  *pScsiTm;
        MPT_SCSI_HOST   *hd;
        int              ii;
-       int              retval;
+       int              retval=0;
 
 
        ioctl->reset &= ~MPTCTL_RESET_OK;
@@ -350,7 +348,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
        if (ioctl->ioc->sh == NULL)
                return -EPERM;
 
-       hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata;
+       hd = shost_priv(ioctl->ioc->sh);
        if (hd == NULL)
                return -EPERM;
 
@@ -395,12 +393,19 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
        DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf);
 
        ioctl->wait_done=0;
-       if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
-            sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
-               dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!"
-                       " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
-                       hd->ioc, mf));
-               goto mptctl_bus_reset_done;
+
+       if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
+           (ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05))
+               mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf);
+       else {
+               retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
+                       sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
+               if (retval != 0) {
+                       dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+                               " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+                               hd->ioc, mf));
+                       goto mptctl_bus_reset_done;
+               }
        }
 
        /* Now wait for the command to complete */
@@ -444,7 +449,7 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
        MPT_SCSI_HOST * hd;
        unsigned long flags;
 
-       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+       hd = shost_priv(ioc->sh);
        if (hd == NULL)
                return;
 
@@ -468,7 +473,7 @@ static int
 mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
        MPT_IOCTL *ioctl = ioc->ioctl;
-       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": IOC %s_reset routed to IOCTL driver!\n",ioc->name,
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC %s_reset routed to IOCTL driver!\n", ioc->name,
                reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
                reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 
@@ -574,7 +579,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        MPT_ADAPTER *iocp = NULL;
 
        if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
-               printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
+               printk(KERN_ERR MYNAM "%s::mptctl_ioctl() @%d - "
                                "Unable to copy mpt_ioctl_header data @ %p\n",
                                __FILE__, __LINE__, uhdr);
                return -EFAULT;
@@ -587,13 +592,13 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        iocnumX = khdr.iocnum & 0xFF;
        if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
            (iocp == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnumX);
                return -ENODEV;
        }
 
        if (!iocp->active) {
-               printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - Controller disabled.\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n",
                                __FILE__, __LINE__);
                return -EFAULT;
        }
@@ -660,14 +665,14 @@ static int mptctl_do_reset(unsigned long arg)
        MPT_ADAPTER             *iocp;
 
        if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
-               printk(KERN_ERR "%s@%d::mptctl_do_reset - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
                                "Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
                                __FILE__, __LINE__, urinfo);
                return -EFAULT;
        }
 
        if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
-               printk(KERN_DEBUG "%s@%d::mptctl_do_reset - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
                                __FILE__, __LINE__, krinfo.hdr.iocnum);
                return -ENODEV; /* (-6) No such device or address */
        }
@@ -676,8 +681,8 @@ static int mptctl_do_reset(unsigned long arg)
            iocp->name));
 
        if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) {
-               printk (KERN_ERR "%s@%d::mptctl_do_reset - reset failed.\n",
-                       __FILE__, __LINE__);
+               printk (MYIOC_s_ERR_FMT "%s@%d::mptctl_do_reset - reset failed.\n",
+                       iocp->name, __FILE__, __LINE__);
                return -1;
        }
 
@@ -708,7 +713,7 @@ mptctl_fw_download(unsigned long arg)
        struct mpt_fw_xfer       kfwdl;
 
        if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
-               printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+               printk(KERN_ERR MYNAM "%s@%d::_ioctl_fwdl - "
                                "Unable to copy mpt_fw_xfer struct @ %p\n",
                                __FILE__, __LINE__, ufwdl);
                return -EFAULT;
@@ -756,7 +761,8 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
        pFWDownloadReply_t       ReplyMsg = NULL;
 
        if (mpt_verify_adapter(ioc, &iocp) < 0) {
-               printk(KERN_DEBUG "ioctl_fwdl - ioc%d not found!\n",                             ioc);
+               printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
+                                ioc);
                return -ENODEV; /* (-6) No such device or address */
        } else {
 
@@ -868,9 +874,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
                        mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
                        n++;
                        if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
-                               printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
-                                               "Unable to copy f/w buffer hunk#%d @ %p\n",
-                                               __FILE__, __LINE__, n, ufwbuf);
+                               printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - "
+                                       "Unable to copy f/w buffer hunk#%d @ %p\n",
+                                       iocp->name, __FILE__, __LINE__, n, ufwbuf);
                                goto fwdl_out;
                        }
                        fw_bytes_copied += bl->len;
@@ -906,21 +912,22 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
        ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
        iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
        if (iocstat == MPI_IOCSTATUS_SUCCESS) {
-               printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
+               printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name);
                return 0;
        } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
-               printk(KERN_WARNING MYNAM ": ?Hmmm...  %s says it doesn't support F/W download!?!\n",
-                               iocp->name);
-               printk(KERN_WARNING MYNAM ": (time to go bang on somebodies door)\n");
+               printk(MYIOC_s_WARN_FMT "Hmmm...  F/W download not supported!?!\n",
+                       iocp->name);
+               printk(MYIOC_s_WARN_FMT "(time to go bang on somebodies door)\n",
+                       iocp->name);
                return -EBADRQC;
        } else if (iocstat == MPI_IOCSTATUS_BUSY) {
-               printk(KERN_WARNING MYNAM ": Warning!  %s says: IOC_BUSY!\n", iocp->name);
-               printk(KERN_WARNING MYNAM ": (try again later?)\n");
+               printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name);
+               printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name);
                return -EBUSY;
        } else {
-               printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",
-                                   iocp->name, iocstat);
-               printk(KERN_WARNING MYNAM ": (bad VooDoo)\n");
+               printk(MYIOC_s_WARN_FMT "ioctl_fwdl() returned [bad] status = %04xh\n",
+                       iocp->name, iocstat);
+               printk(MYIOC_s_WARN_FMT "(bad VooDoo)\n", iocp->name);
                return -ENOMSG;
        }
        return 0;
@@ -970,10 +977,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
         * structures for the SG elements.
         */
        i = MAX_SGL_BYTES / 8;
-       buflist = kmalloc(i, GFP_USER);
-       if (buflist == NULL)
+       buflist = kzalloc(i, GFP_USER);
+       if (!buflist)
                return NULL;
-       memset(buflist, 0, i);
        buflist_ent = 0;
 
        /* Allocate a single block of memory to store the sg elements and
@@ -1008,10 +1014,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
                if (buflist[buflist_ent].kptr == NULL) {
                        alloc_sz = alloc_sz / 2;
                        if (alloc_sz == 0) {
-                               printk(KERN_WARNING MYNAM "-SG: No can do - "
-                                                   "not enough memory!   :-(\n");
-                               printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
-                                                   numfrags);
+                               printk(MYIOC_s_WARN_FMT "-SG: No can do - "
+                                   "not enough memory!   :-(\n", ioc->name);
+                               printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",
+                                       ioc->name, numfrags);
                                goto free_and_fail;
                        }
                        continue;
@@ -1034,18 +1040,19 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
 
                /* Need to chain? */
                if (fragcnt == sg_spill) {
-                       printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required!   :-(\n");
-                       printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags);
+                       printk(MYIOC_s_WARN_FMT
+                           "-SG: No can do - " "Chain required!   :-(\n", ioc->name);
+                       printk(MYIOC_s_WARN_FMT "(freeing %d frags)\n", ioc->name, numfrags);
                        goto free_and_fail;
                }
 
                /* overflow check... */
                if (numfrags*8 > MAX_SGL_BYTES){
                        /* GRRRRR... */
-                       printk(KERN_WARNING MYNAM "-SG: No can do - "
-                                           "too many SG frags!   :-(\n");
-                       printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
-                                           numfrags);
+                       printk(MYIOC_s_WARN_FMT "-SG: No can do - "
+                               "too many SG frags!   :-(\n", ioc->name);
+                       printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",
+                               ioc->name, numfrags);
                        goto free_and_fail;
                }
        }
@@ -1066,8 +1073,6 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
 
 free_and_fail:
        if (sglbuf != NULL) {
-               int i;
-
                for (i = 0; i < numfrags; i++) {
                        dma_addr_t dma_addr;
                        u8 *kptr;
@@ -1170,7 +1175,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        int                     cim_rev;
        u8                      revision;
        struct scsi_device      *sdev;
-       VirtDevice              *vdev;
+       VirtDevice              *vdevice;
 
        /* Add of PCI INFO results in unaligned access for
         * IA64 and Sparc. Reset long to int. Return no PCI
@@ -1189,13 +1194,13 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 
        karg = kmalloc(data_size, GFP_KERNEL);
        if (karg == NULL) {
-               printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
+               printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
                                __FILE__, __LINE__);
                return -ENOMEM;
        }
 
        if (copy_from_user(karg, uarg, data_size)) {
-               printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - "
                        "Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                kfree(karg);
@@ -1204,7 +1209,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 
        if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                kfree(karg);
                return -ENODEV;
@@ -1212,9 +1217,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 
        /* Verify the data transfer size is correct. */
        if (karg->hdr.maxDataSize != data_size) {
-               printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
                        "Structure size mismatch. Command not completed.\n",
-                               __FILE__, __LINE__);
+                       ioc->name, __FILE__, __LINE__);
                kfree(karg);
                return -EFAULT;
        }
@@ -1265,8 +1270,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        karg->numDevices = 0;
        if (ioc->sh) {
                shost_for_each_device(sdev, ioc->sh) {
-                       vdev = sdev->hostdata;
-                       if (vdev->vtarget->tflags &
+                       vdevice = sdev->hostdata;
+                       if (vdevice->vtarget->tflags &
                            MPT_TARGET_FLAGS_RAID_COMPONENT)
                                continue;
                        karg->numDevices++;
@@ -1290,9 +1295,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        /* Copy the data from kernel memory to user memory
         */
        if (copy_to_user((char __user *)arg, karg, data_size)) {
-               printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
                        "Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
-                               __FILE__, __LINE__, uarg);
+                       ioc->name, __FILE__, __LINE__, uarg);
                kfree(karg);
                return -EFAULT;
        }
@@ -1317,7 +1322,7 @@ mptctl_gettargetinfo (unsigned long arg)
        struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
        struct mpt_ioctl_targetinfo karg;
        MPT_ADAPTER             *ioc;
-       VirtDevice              *vdev;
+       VirtDevice              *vdevice;
        char                    *pmem;
        int                     *pdata;
        int                     iocnum;
@@ -1329,7 +1334,7 @@ mptctl_gettargetinfo (unsigned long arg)
        struct scsi_device      *sdev;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
-               printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_gettargetinfo - "
                        "Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1337,7 +1342,7 @@ mptctl_gettargetinfo (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1353,8 +1358,8 @@ mptctl_gettargetinfo (unsigned long arg)
        port = karg.hdr.port;
 
        if (maxWordsLeft <= 0) {
-               printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
-                               __FILE__, __LINE__);
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",
+                       ioc->name, __FILE__, __LINE__);
                return -ENOMEM;
        }
 
@@ -1372,13 +1377,12 @@ mptctl_gettargetinfo (unsigned long arg)
         *      15- 8: Bus Number
         *       7- 0: Target ID
         */
-       pmem = kmalloc(numBytes, GFP_KERNEL);
-       if (pmem == NULL) {
-               printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
-                               __FILE__, __LINE__);
+       pmem = kzalloc(numBytes, GFP_KERNEL);
+       if (!pmem) {
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",
+                       ioc->name, __FILE__, __LINE__);
                return -ENOMEM;
        }
-       memset(pmem, 0, numBytes);
        pdata =  (int *) pmem;
 
        /* Get number of devices
@@ -1387,13 +1391,13 @@ mptctl_gettargetinfo (unsigned long arg)
                shost_for_each_device(sdev, ioc->sh) {
                        if (!maxWordsLeft)
                                continue;
-                       vdev = sdev->hostdata;
-                       if (vdev->vtarget->tflags &
+                       vdevice = sdev->hostdata;
+                       if (vdevice->vtarget->tflags &
                            MPT_TARGET_FLAGS_RAID_COMPONENT)
                                continue;
-                       lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
-                       *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
-                           (vdev->vtarget->id ));
+                       lun = (vdevice->vtarget->raidVolume) ? 0x80 : vdevice->lun;
+                       *pdata = (((u8)lun << 16) + (vdevice->vtarget->channel << 8) +
+                           (vdevice->vtarget->id ));
                        pdata++;
                        numDevices++;
                        --maxWordsLeft;
@@ -1405,9 +1409,9 @@ mptctl_gettargetinfo (unsigned long arg)
         */
        if (copy_to_user((char __user *)arg, &karg,
                                sizeof(struct mpt_ioctl_targetinfo))) {
-               printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo - "
                        "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, uarg);
+                       ioc->name, __FILE__, __LINE__, uarg);
                kfree(pmem);
                return -EFAULT;
        }
@@ -1415,9 +1419,9 @@ mptctl_gettargetinfo (unsigned long arg)
        /* Copy the remaining data from kernel memory to user memory
         */
        if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
-               printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo - "
                        "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, pdata);
+                       ioc->name, __FILE__, __LINE__, pdata);
                kfree(pmem);
                return -EFAULT;
        }
@@ -1444,7 +1448,7 @@ mptctl_readtest (unsigned long arg)
        int iocnum;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
-               printk(KERN_ERR "%s@%d::mptctl_readtest - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
                        "Unable to read in mpt_ioctl_test struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1452,7 +1456,7 @@ mptctl_readtest (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_readtest() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1476,9 +1480,9 @@ mptctl_readtest (unsigned long arg)
        /* Copy the data from kernel memory to user memory
         */
        if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
-               printk(KERN_ERR "%s@%d::mptctl_readtest - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_readtest - "
                        "Unable to write out mpt_ioctl_test struct @ %p\n",
-                               __FILE__, __LINE__, uarg);
+                       ioc->name, __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1505,7 +1509,7 @@ mptctl_eventquery (unsigned long arg)
        int iocnum;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
-               printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
                        "Unable to read in mpt_ioctl_eventquery struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1513,7 +1517,7 @@ mptctl_eventquery (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1526,9 +1530,9 @@ mptctl_eventquery (unsigned long arg)
        /* Copy the data from kernel memory to user memory
         */
        if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
-               printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_eventquery - "
                        "Unable to write out mpt_ioctl_eventquery struct @ %p\n",
-                               __FILE__, __LINE__, uarg);
+                       ioc->name, __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
        return 0;
@@ -1544,7 +1548,7 @@ mptctl_eventenable (unsigned long arg)
        int iocnum;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
-               printk(KERN_ERR "%s@%d::mptctl_eventenable - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
                        "Unable to read in mpt_ioctl_eventenable struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1552,7 +1556,7 @@ mptctl_eventenable (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1563,12 +1567,13 @@ mptctl_eventenable (unsigned long arg)
                /* Have not yet allocated memory - do so now.
                 */
                int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
-               ioc->events = kmalloc(sz, GFP_KERNEL);
-               if (ioc->events == NULL) {
-                       printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
+               ioc->events = kzalloc(sz, GFP_KERNEL);
+               if (!ioc->events) {
+                       printk(MYIOC_s_ERR_FMT
+                           ": ERROR - Insufficient memory to add adapter!\n",
+                           ioc->name);
                        return -ENOMEM;
                }
-               memset(ioc->events, 0, sz);
                ioc->alloc_total += sz;
 
                ioc->eventContext = 0;
@@ -1592,7 +1597,7 @@ mptctl_eventreport (unsigned long arg)
        int                      numBytes, maxEvents, max;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
-               printk(KERN_ERR "%s@%d::mptctl_eventreport - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_eventreport - "
                        "Unable to read in mpt_ioctl_eventreport struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1600,7 +1605,7 @@ mptctl_eventreport (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1626,9 +1631,9 @@ mptctl_eventreport (unsigned long arg)
         */
        numBytes = max * sizeof(MPT_IOCTL_EVENTS);
        if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
-               printk(KERN_ERR "%s@%d::mptctl_eventreport - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_eventreport - "
                        "Unable to write out mpt_ioctl_eventreport struct @ %p\n",
-                               __FILE__, __LINE__, ioc->events);
+                       ioc->name, __FILE__, __LINE__, ioc->events);
                return -EFAULT;
        }
 
@@ -1646,7 +1651,7 @@ mptctl_replace_fw (unsigned long arg)
        int                      newFwSize;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
-               printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_replace_fw - "
                        "Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1654,7 +1659,7 @@ mptctl_replace_fw (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1684,9 +1689,9 @@ mptctl_replace_fw (unsigned long arg)
        /* Copy the data from user memory to kernel space
         */
        if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
-               printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_replace_fw - "
                                "Unable to read in mpt_ioctl_replace_fw image "
-                               "@ %p\n", __FILE__, __LINE__, uarg);
+                               "@ %p\n", ioc->name, __FILE__, __LINE__, uarg);
                mpt_free_fw_memory(ioc);
                return -EFAULT;
        }
@@ -1720,7 +1725,7 @@ mptctl_mpt_command (unsigned long arg)
 
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
-               printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_mpt_command - "
                        "Unable to read in mpt_ioctl_command struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -1728,7 +1733,7 @@ mptctl_mpt_command (unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -1769,21 +1774,24 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        ulong           timeout;
        struct scsi_device *sdev;
 
+       /* bufIn and bufOut are used for user to kernel space transfers
+        */
        bufIn.kptr = bufOut.kptr = NULL;
+       bufIn.len = bufOut.len = 0;
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
        if (!ioc->ioctl) {
-               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
                        "No memory available during driver init.\n",
                                __FILE__, __LINE__);
                return -ENOMEM;
        } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
-               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
                        "Busy with IOC Reset \n", __FILE__, __LINE__);
                return -EBUSY;
        }
@@ -1797,9 +1805,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                sz += sizeof(dma_addr_t) + sizeof(u32);
 
        if (sz > ioc->req_sz) {
-               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                        "Request frame too large (%d) maximum (%d)\n",
-                               __FILE__, __LINE__, sz, ioc->req_sz);
+                       ioc->name, __FILE__, __LINE__, sz, ioc->req_sz);
                return -EFAULT;
        }
 
@@ -1817,9 +1825,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
         * Request frame in user space
         */
        if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
-               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                        "Unable to read MF from mpt_ioctl_command struct @ %p\n",
-                       __FILE__, __LINE__, mfPtr);
+                       ioc->name, __FILE__, __LINE__, mfPtr);
                rc = -EFAULT;
                goto done_free_mem;
        }
@@ -1870,17 +1878,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
                        id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
                        if (pScsiReq->TargetID > id) {
-                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                        "Target ID out of bounds. \n",
-                                       __FILE__, __LINE__);
+                                       ioc->name, __FILE__, __LINE__);
                                rc = -ENODEV;
                                goto done_free_mem;
                        }
 
                        if (pScsiReq->Bus >= ioc->number_of_buses) {
-                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                        "Target Bus out of bounds. \n",
-                                       __FILE__, __LINE__);
+                                       ioc->name, __FILE__, __LINE__);
                                rc = -ENODEV;
                                goto done_free_mem;
                        }
@@ -1932,9 +1940,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        ioc->ioctl->id = pScsiReq->TargetID;
 
                } else {
-                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                "SCSI driver is not loaded. \n",
-                                       __FILE__, __LINE__);
+                               ioc->name, __FILE__, __LINE__);
                        rc = -EFAULT;
                        goto done_free_mem;
                }
@@ -1951,9 +1959,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
        case MPI_FUNCTION_SATA_PASSTHROUGH:
                if (!ioc->sh) {
-                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                "SCSI driver is not loaded. \n",
-                                       __FILE__, __LINE__);
+                               ioc->name, __FILE__, __LINE__);
                        rc = -EFAULT;
                        goto done_free_mem;
                }
@@ -2010,9 +2018,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        ioc->ioctl->reset = MPTCTL_RESET_OK;
                        ioc->ioctl->id = pScsiReq->TargetID;
                } else {
-                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                "SCSI driver is not loaded. \n",
-                                       __FILE__, __LINE__);
+                               ioc->name, __FILE__, __LINE__);
                        rc = -EFAULT;
                        goto done_free_mem;
                }
@@ -2021,10 +2029,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        case MPI_FUNCTION_SCSI_TASK_MGMT:
                {
                        MPT_SCSI_HOST *hd = NULL;
-                       if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) {
-                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) {
+                               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                        "SCSI driver not loaded or SCSI host not found. \n",
-                                       __FILE__, __LINE__);
+                                       ioc->name, __FILE__, __LINE__);
                                rc = -EFAULT;
                                goto done_free_mem;
                        } else if (mptctl_set_tm_flags(hd) != 0) {
@@ -2055,9 +2063,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
                                (pInit->HostMfaHighAddr != high_addr) ||
                                (pInit->SenseBufferHighAddr != sense_high)) {
-                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                        "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",
-                                       __FILE__, __LINE__);
+                                       ioc->name, __FILE__, __LINE__);
                                rc = -EFAULT;
                                goto done_free_mem;
                        }
@@ -2088,9 +2096,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        MPI_FUNCTION_LAN_RESET
                */
 
-               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                        "Illegal request (function 0x%x) \n",
-                       __FILE__, __LINE__, hdr->Function);
+                       ioc->name, __FILE__, __LINE__, hdr->Function);
                rc = -EFAULT;
                goto done_free_mem;
        }
@@ -2103,11 +2111,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        psge = (char *) (((int *) mf) + karg.dataSgeOffset);
        flagsLength = 0;
 
-       /* bufIn and bufOut are used for user to kernel space transfers
-        */
-       bufIn.kptr = bufOut.kptr = NULL;
-       bufIn.len = bufOut.len = 0;
-
        if (karg.dataOutSize > 0)
                sgSize ++;
 
@@ -2147,11 +2150,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                if (copy_from_user(bufOut.kptr,
                                                karg.dataOutBufPtr,
                                                bufOut.len)) {
-                                       printk(KERN_ERR
+                                       printk(MYIOC_s_ERR_FMT
                                                "%s@%d::mptctl_do_mpt_command - Unable "
                                                "to read user data "
                                                "struct @ %p\n",
-                                               __FILE__, __LINE__,karg.dataOutBufPtr);
+                                               ioc->name, __FILE__, __LINE__,karg.dataOutBufPtr);
                                        rc =  -EFAULT;
                                        goto done_free_mem;
                                }
@@ -2187,15 +2190,20 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
                DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
 
-               if (mpt_send_handshake_request(mptctl_id, ioc,
-                       sizeof(SCSITaskMgmt_t), (u32*)mf,
-                       CAN_SLEEP) != 0) {
-                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!"
-                               " (ioc %p, mf %p) \n", ioc->name,
-                               ioc, mf));
-                       mptctl_free_tm_flags(ioc);
-                       rc = -ENODATA;
-                       goto done_free_mem;
+               if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
+                   (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
+                       mpt_put_msg_frame_hi_pri(mptctl_id, ioc, mf);
+               else {
+                       rc =mpt_send_handshake_request(mptctl_id, ioc,
+                               sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
+                       if (rc != 0) {
+                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+                                   "_send_handshake FAILED! (ioc %p, mf %p)\n",
+                                   ioc->name, ioc, mf));
+                               mptctl_free_tm_flags(ioc);
+                               rc = -ENODATA;
+                               goto done_free_mem;
+                       }
                }
 
        } else
@@ -2233,10 +2241,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                if (sz > 0) {
                        if (copy_to_user(karg.replyFrameBufPtr,
                                 &ioc->ioctl->ReplyFrame, sz)){
-                                printk(KERN_ERR
+                                printk(MYIOC_s_ERR_FMT
                                     "%s@%d::mptctl_do_mpt_command - "
                                 "Unable to write out reply frame %p\n",
-                                __FILE__, __LINE__, karg.replyFrameBufPtr);
+                                ioc->name, __FILE__, __LINE__, karg.replyFrameBufPtr);
                                 rc =  -ENODATA;
                                 goto done_free_mem;
                        }
@@ -2249,9 +2257,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
                if (sz > 0) {
                        if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
-                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                "Unable to write sense data to user %p\n",
-                               __FILE__, __LINE__,
+                               ioc->name, __FILE__, __LINE__,
                                karg.senseDataPtr);
                                rc =  -ENODATA;
                                goto done_free_mem;
@@ -2267,9 +2275,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
                if (copy_to_user(karg.dataInBufPtr,
                                 bufIn.kptr, karg.dataInSize)) {
-                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
                                "Unable to write data to user %p\n",
-                               __FILE__, __LINE__,
+                               ioc->name, __FILE__, __LINE__,
                                karg.dataInBufPtr);
                        rc =  -ENODATA;
                }
@@ -2340,7 +2348,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
                return -EFAULT;
 
        if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
-               printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_hp_host_info - "
                        "Unable to read in hp_host_info struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -2348,7 +2356,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
@@ -2456,7 +2464,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
        karg.soft_resets = 0;
        karg.timeouts = 0;
        if (ioc->sh != NULL) {
-               MPT_SCSI_HOST *hd =  (MPT_SCSI_HOST *)ioc->sh->hostdata;
+               MPT_SCSI_HOST *hd =  shost_priv(ioc->sh);
 
                if (hd && (cim_rev == 1)) {
                        karg.hard_resets = hd->hard_resets;
@@ -2529,9 +2537,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
        /* Copy the data from kernel memory to user memory
         */
        if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
-               printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_hpgethostinfo - "
                        "Unable to write out hp_host_info @ %p\n",
-                               __FILE__, __LINE__, uarg);
+                       ioc->name, __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -2567,7 +2575,7 @@ mptctl_hp_targetinfo(unsigned long arg)
        int                     tmp, np, rc = 0;
 
        if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
-               printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_hp_targetinfo - "
                        "Unable to read in hp_host_targetinfo struct @ %p\n",
                                __FILE__, __LINE__, uarg);
                return -EFAULT;
@@ -2575,11 +2583,11 @@ mptctl_hp_targetinfo(unsigned long arg)
 
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
                (ioc == NULL)) {
-               printk(KERN_DEBUG "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
+               printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum);
                return -ENODEV;
        }
-       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
            ioc->name));
 
        /*  There is nothing to do for FCP parts.
@@ -2673,16 +2681,16 @@ mptctl_hp_targetinfo(unsigned long arg)
                        pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma);
                }
        }
-       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+       hd = shost_priv(ioc->sh);
        if (hd != NULL)
                karg.select_timeouts = hd->sel_timeout[karg.hdr.id];
 
        /* Copy the data from kernel memory to user memory
         */
        if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
-               printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_hp_target_info - "
                        "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, uarg);
+                       ioc->name, __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -2732,7 +2740,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
        if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
            (iocp == NULL)) {
                printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
-                               __LINE__, iocnumX);
+                       __LINE__, iocnumX);
                return -ENODEV;
        }
 
@@ -2772,7 +2780,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
        if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
            (iocp == NULL)) {
                printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
-                               __LINE__, iocnumX);
+                       __LINE__, iocnumX);
                return -ENODEV;
        }
 
@@ -2853,31 +2861,22 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a
 static int
 mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-       int err;
-       int sz;
-       u8 *mem;
+       MPT_IOCTL *mem;
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
        /*
         * Allocate and inite a MPT_IOCTL structure
        */
-       sz = sizeof (MPT_IOCTL);
-       mem = kmalloc(sz, GFP_KERNEL);
-       if (mem == NULL) {
-               err = -ENOMEM;
-               goto out_fail;
+       mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL);
+       if (!mem) {
+               mptctl_remove(pdev);
+               return -ENOMEM;
        }
 
-       memset(mem, 0, sz);
-       ioc->ioctl = (MPT_IOCTL *) mem;
+       ioc->ioctl = mem;
        ioc->ioctl->ioc = ioc;
        mutex_init(&ioc->ioctl->ioctl_mutex);
        return 0;
-
-out_fail:
-
-       mptctl_remove(pdev);
-       return err;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2924,7 +2923,8 @@ static int __init mptctl_init(void)
         *  Install our handler
         */
        ++where;
-       if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) < 0) {
+       mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER);
+       if (!mptctl_id || mptctl_id >= MPT_MAX_PROTOCOL_DRIVERS) {
                printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
                misc_deregister(&mptctl_miscdev);
                err = -EBUSY;
index 180b3c156247fc158a8b2b80b466239dbdf2e77a..2c1890127e155d18e2053a414ab26926c6e71d44 100644 (file)
@@ -3,9 +3,9 @@
  *      Fusion MPT misc device (ioctl) driver.
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
index 8422c25e4a3e7f71f8ecc26e95a16b416a5c15ac..3cdd4e9621150bcfae62c741deadb179040561ff 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/message/fusion/mptfc.c
- *      For use with LSI Logic PCI chip/adapter(s)
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI PCI chip/adapter(s)
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -90,9 +90,9 @@ static int max_lun = MPTFC_MAX_LUN;
 module_param(max_lun, int, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 
-static int     mptfcDoneCtx = -1;
-static int     mptfcTaskCtx = -1;
-static int     mptfcInternalCtx = -1; /* Used only for internal commands */
+static u8      mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8      mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8      mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
 
 static int mptfc_target_alloc(struct scsi_target *starget);
 static int mptfc_slave_alloc(struct scsi_device *sdev);
@@ -194,37 +194,36 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
        struct fc_rport         *rport = starget_to_rport(scsi_target(sdev));
        unsigned long           flags;
        int                     ready;
+       MPT_ADAPTER             *ioc;
 
-       hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+       hd = shost_priv(SCpnt->device->host);
+       ioc = hd->ioc;
        spin_lock_irqsave(shost->host_lock, flags);
        while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
                spin_unlock_irqrestore(shost->host_lock, flags);
-               dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+               dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
                        "mptfc_block_error_handler.%d: %d:%d, port status is "
                        "DID_IMM_RETRY, deferring %s recovery.\n",
-                       ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
-                       ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
-                       SCpnt->device->id,SCpnt->device->lun,caller));
+                       ioc->name, ioc->sh->host_no,
+                       SCpnt->device->id, SCpnt->device->lun, caller));
                msleep(1000);
                spin_lock_irqsave(shost->host_lock, flags);
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
 
        if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
-               dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+               dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
                        "%s.%d: %d:%d, failing recovery, "
-                       "port state %d, vdev %p.\n", caller,
-                       ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
-                       ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
-                       SCpnt->device->id,SCpnt->device->lun,ready,
+                       "port state %d, vdevice %p.\n", caller,
+                       ioc->name, ioc->sh->host_no,
+                       SCpnt->device->id, SCpnt->device->lun, ready,
                        SCpnt->device->hostdata));
                return FAILED;
        }
-       dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+       dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
                "%s.%d: %d:%d, executing recovery.\n", caller,
-               ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
-               ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
-               SCpnt->device->id,SCpnt->device->lun));
+               ioc->name, ioc->sh->host_no,
+               SCpnt->device->id, SCpnt->device->lun));
        return (*func)(SCpnt);
 }
 
@@ -470,7 +469,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                        /*
                         * if already mapped, remap here.  If not mapped,
                         * target_alloc will allocate vtarget and map,
-                        * slave_alloc will fill in vdev from vtarget.
+                        * slave_alloc will fill in vdevice from vtarget.
                         */
                        if (ri->starget) {
                                vtarget = ri->starget->hostdata;
@@ -602,10 +601,10 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 {
        MPT_SCSI_HOST           *hd;
        VirtTarget              *vtarget;
-       VirtDevice              *vdev;
+       VirtDevice              *vdevice;
        struct scsi_target      *starget;
        struct fc_rport         *rport;
-
+       MPT_ADAPTER             *ioc;
 
        starget = scsi_target(sdev);
        rport = starget_to_rport(starget);
@@ -613,31 +612,32 @@ mptfc_slave_alloc(struct scsi_device *sdev)
        if (!rport || fc_remote_port_chkready(rport))
                return -ENXIO;
 
-       hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+       hd = shost_priv(sdev->host);
+       ioc = hd->ioc;
 
-       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
-       if (!vdev) {
+       vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!vdevice) {
                printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
-                               hd->ioc->name, sizeof(VirtDevice));
+                               ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
 
 
-       sdev->hostdata = vdev;
+       sdev->hostdata = vdevice;
        vtarget = starget->hostdata;
 
        if (vtarget->num_luns == 0) {
-               vtarget->ioc_id = hd->ioc->id;
+               vtarget->ioc_id = ioc->id;
                vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
        }
 
-       vdev->vtarget = vtarget;
-       vdev->lun = sdev->lun;
+       vdevice->vtarget = vtarget;
+       vdevice->lun = sdev->lun;
 
        vtarget->num_luns++;
 
 
-       mptfc_dump_lun_info(hd->ioc, rport, sdev, vtarget);
+       mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
 
        return 0;
 }
@@ -648,9 +648,9 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        struct mptfc_rport_info *ri;
        struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
        int             err;
-       VirtDevice      *vdev = SCpnt->device->hostdata;
+       VirtDevice      *vdevice = SCpnt->device->hostdata;
 
-       if (!vdev || !vdev->vtarget) {
+       if (!vdevice || !vdevice->vtarget) {
                SCpnt->result = DID_NO_CONNECT << 16;
                done(SCpnt);
                return 0;
@@ -674,6 +674,50 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        return mptscsih_qcmd(SCpnt,done);
 }
 
+/*
+ *     mptfc_display_port_link_speed - displaying link speed
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @portnum: IOC Port number
+ *     @pp0dest: port page0 data payload
+ *
+ */
+static void
+mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest)
+{
+       u8      old_speed, new_speed, state;
+       char    *old, *new;
+
+       if (portnum >= 2)
+               return;
+
+       old_speed = ioc->fc_link_speed[portnum];
+       new_speed = pp0dest->CurrentSpeed;
+       state = pp0dest->PortState;
+
+       if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
+           new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) {
+
+               old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
+                      old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
+                       old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
+                        "Unknown";
+               new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
+                      new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
+                       new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
+                        "Unknown";
+               if (old_speed == 0)
+                       printk(MYIOC_s_NOTE_FMT
+                               "FC Link Established, Speed = %s\n",
+                               ioc->name, new);
+               else if (old_speed != new_speed)
+                       printk(MYIOC_s_WARN_FMT
+                               "FC Link Speed Change, Old Speed = %s, New Speed = %s\n",
+                               ioc->name, old, new);
+
+               ioc->fc_link_speed[portnum] = new_speed;
+       }
+}
+
 /*
  *     mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
  *     @ioc: Pointer to MPT_ADAPTER structure
@@ -773,6 +817,7 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
                                                        " complete.\n",
                                                ioc->name);
                        }
+                       mptfc_display_port_link_speed(ioc, portnum, pp0dest);
                }
 
                pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -1022,6 +1067,18 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
 
 }
 
+static void
+mptfc_link_status_change(struct work_struct *work)
+{
+       MPT_ADAPTER             *ioc =
+               container_of(work, MPT_ADAPTER, fc_rescan_work);
+       int ii;
+
+       for (ii=0; ii < ioc->facts.NumberOfPorts; ii++)
+               (void) mptfc_GetFcPortPage0(ioc, ii);
+
+}
+
 static void
 mptfc_setup_reset(struct work_struct *work)
 {
@@ -1163,6 +1220,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        spin_lock_init(&ioc->fc_rescan_work_lock);
        INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
        INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
+       INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change);
 
        spin_lock_irqsave(&ioc->FreeQlock, flags);
 
@@ -1218,20 +1276,21 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
-       hd = (MPT_SCSI_HOST *) sh->hostdata;
+       hd = shost_priv(sh);
        hd->ioc = ioc;
 
        /* SCSI needs scsi_cmnd lookup table!
         * (with size equal to req_depth*PtrSz!)
         */
-       hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
-       if (!hd->ScsiLookup) {
+       ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+       if (!ioc->ScsiLookup) {
                error = -ENOMEM;
                goto out_mptfc_probe;
        }
+       spin_lock_init(&ioc->scsi_lookup_lock);
 
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
-                ioc->name, hd->ScsiLookup));
+                ioc->name, ioc->ScsiLookup));
 
        /* Clear the TM flags
         */
@@ -1262,8 +1321,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        sh->transportt = mptfc_transport_template;
        error = scsi_add_host (sh, &ioc->pcidev->dev);
        if(error) {
-               dprintk(ioc, printk(KERN_ERR MYNAM
-                 "scsi_add_host failed\n"));
+               dprintk(ioc, printk(MYIOC_s_ERR_FMT
+                 "scsi_add_host failed\n", ioc->name));
                goto out_mptfc_probe;
        }
 
@@ -1325,7 +1384,7 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                        ioc->name, event));
 
        if (ioc->sh == NULL ||
-               ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+               ((hd = shost_priv(ioc->sh)) == NULL))
                return 1;
 
        switch (event) {
@@ -1337,6 +1396,14 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                }
                spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
                break;
+       case MPI_EVENT_LINK_STATUS_CHANGE:
+               spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+               if (ioc->fc_rescan_work_q) {
+                       queue_work(ioc->fc_rescan_work_q,
+                                  &ioc->fc_lsc_work);
+               }
+               spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+               break;
        default:
                rc = mptscsih_event_process(ioc,pEvReply);
                break;
index 3da4c37846ecc91f5bbc0f7b709e272fe014c7c6..7950fc678ed17c281e826529b290c76efa8cca11 100644 (file)
@@ -1,10 +1,10 @@
 /*
  *  linux/drivers/message/fusion/mptlan.c
  *      IP Over Fibre Channel device driver.
- *      For use with LSI Logic Fibre Channel PCI chip/adapters
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI Fibre Channel PCI chip/adapters
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 2000-2007 LSI Logic Corporation
+ *  Copyright (c) 2000-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -154,7 +154,7 @@ static unsigned short mpt_lan_type_trans(struct sk_buff *skb,
 /*
  *  Fusion MPT LAN private data
  */
-static int LanCtx = -1;
+static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS;
 
 static u32 max_buckets_out = 127;
 static u32 tx_max_out_p = 127 - 16;
@@ -164,12 +164,6 @@ static struct NAA_Hosed *mpt_bad_naa = NULL;
 DEFINE_RWLOCK(bad_naa_lock);
 #endif
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Fusion MPT LAN external data
- */
-extern int mpt_lan_index;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     lan_reply - Handle all data sent from the hardware.
@@ -1230,6 +1224,8 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
                }
                pRecvReq = (LANReceivePostRequest_t *) mf;
 
+               i = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+               mpt_dev->RequestNB[i] = 0;
                count = buckets;
                if (count > max)
                        count = max;
@@ -1351,10 +1347,11 @@ mpt_lan_post_receive_buckets_work(struct work_struct *work)
 static struct net_device *
 mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
 {
-       struct net_device *dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
-       struct mpt_lan_priv *priv = NULL;
+       struct net_device *dev;
+       struct mpt_lan_priv *priv;
        u8 HWaddr[FC_ALEN], *a;
 
+       dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
        if (!dev)
                return NULL;
 
@@ -1366,7 +1363,6 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
        priv->mpt_dev = mpt_dev;
        priv->pnum = pnum;
 
-       memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task));
        INIT_DELAYED_WORK(&priv->post_buckets_task,
                          mpt_lan_post_receive_buckets_work);
        priv->post_buckets_active = 0;
@@ -1391,8 +1387,6 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
        spin_lock_init(&priv->txfidx_lock);
        spin_lock_init(&priv->rxfidx_lock);
 
-       memset(&priv->stats, 0, sizeof(priv->stats));
-
        /*  Grab pre-fetched LANPage1 stuff. :-) */
        a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow;
 
@@ -1508,9 +1502,6 @@ static int __init mpt_lan_init (void)
                return -EBUSY;
        }
 
-       /* Set the callback index to be used by driver core for turbo replies */
-       mpt_lan_index = LanCtx;
-
        dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
 
        if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) {
@@ -1531,10 +1522,9 @@ static void __exit mpt_lan_exit(void)
        mpt_device_driver_deregister(MPTLAN_DRIVER);
        mpt_reset_deregister(LanCtx);
 
-       if (LanCtx >= 0) {
+       if (LanCtx) {
                mpt_deregister(LanCtx);
-               LanCtx = -1;
-               mpt_lan_index = 0;
+               LanCtx = MPT_MAX_PROTOCOL_DRIVERS;
        }
 }
 
index 8d08c2bed24a49c228611af7d866767e45f92016..bafb67fc81813d4ccfbceaa8ca70fb06234995a2 100644 (file)
@@ -1,10 +1,10 @@
 /*
  *  linux/drivers/message/fusion/mptlan.h
  *      IP Over Fibre Channel device driver.
- *      For use with LSI Logic Fibre Channel PCI chip/adapters
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI Fibre Channel PCI chip/adapters
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 2000-2007 LSI Logic Corporation
+ *  Copyright (c) 2000-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -75,7 +75,7 @@
 #include <asm/io.h>
 
     /* Override mptbase.h by pre-defining these! */
-#define MODULEAUTHOR   "LSI Logic Corporation"
+#define MODULEAUTHOR   "LSI Corporation"
 
 #include "mptbase.h"
 
index b9c69bff218caed8ac8dd2057157d7c72aa31818..e4c94f93de16a98462518419c923bb24f24d9414 100644 (file)
@@ -1,11 +1,10 @@
 /*
  *  linux/drivers/message/fusion/mptsas.c
- *      For use with LSI Logic PCI chip/adapter(s)
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI PCI chip/adapter(s)
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
- *  Copyright (c) 2005-2007 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -61,6 +60,7 @@
 
 #include "mptbase.h"
 #include "mptscsih.h"
+#include "mptsas.h"
 
 
 #define my_NAME                "Fusion MPT SAS Host driver"
@@ -89,134 +89,35 @@ static int max_lun = MPTSAS_MAX_LUN;
 module_param(max_lun, int, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 
-static int     mptsasDoneCtx = -1;
-static int     mptsasTaskCtx = -1;
-static int     mptsasInternalCtx = -1; /* Used only for internal commands */
-static int     mptsasMgmtCtx = -1;
+static u8      mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8      mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8      mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
+static u8      mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
 
 static void mptsas_hotplug_work(struct work_struct *work);
 
-struct mptsas_target_reset_event {
-       struct list_head        list;
-       EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
-       u8      target_reset_issued;
-};
-
-enum mptsas_hotplug_action {
-       MPTSAS_ADD_DEVICE,
-       MPTSAS_DEL_DEVICE,
-       MPTSAS_ADD_RAID,
-       MPTSAS_DEL_RAID,
-       MPTSAS_ADD_INACTIVE_VOLUME,
-       MPTSAS_IGNORE_EVENT,
-};
-
-struct mptsas_hotplug_event {
-       struct work_struct      work;
-       MPT_ADAPTER             *ioc;
-       enum mptsas_hotplug_action event_type;
-       u64                     sas_address;
-       u8                      channel;
-       u8                      id;
-       u32                     device_info;
-       u16                     handle;
-       u16                     parent_handle;
-       u8                      phy_id;
-       u8                      phys_disk_num_valid;    /* hrc (hidden raid component) */
-       u8                      phys_disk_num;          /* hrc - unique index*/
-       u8                      hidden_raid_component;  /* hrc - don't expose*/
-};
-
-struct mptsas_discovery_event {
-       struct work_struct      work;
-       MPT_ADAPTER             *ioc;
-};
-
-/*
- * SAS topology structures
- *
- * The MPT Fusion firmware interface spreads information about the
- * SAS topology over many manufacture pages, thus we need some data
- * structure to collect it and process it for the SAS transport class.
- */
-
-struct mptsas_devinfo {
-       u16     handle;         /* unique id to address this device */
-       u16     handle_parent;  /* unique id to address parent device */
-       u16     handle_enclosure; /* enclosure identifier of the enclosure */
-       u16     slot;           /* physical slot in enclosure */
-       u8      phy_id;         /* phy number of parent device */
-       u8      port_id;        /* sas physical port this device
-                                  is assoc'd with */
-       u8      id;             /* logical target id of this device */
-       u32     phys_disk_num;  /* phys disk id, for csmi-ioctls */
-       u8      channel;        /* logical bus number of this device */
-       u64     sas_address;    /* WWN of this device,
-                                  SATA is assigned by HBA,expander */
-       u32     device_info;    /* bitfield detailed info about this device */
-};
-
-/*
- * Specific details on ports, wide/narrow
- */
-struct mptsas_portinfo_details{
-       u16     num_phys;       /* number of phys belong to this port */
-       u64     phy_bitmask;    /* TODO, extend support for 255 phys */
-       struct sas_rphy *rphy;  /* transport layer rphy object */
-       struct sas_port *port;  /* transport layer port object */
-       struct scsi_target *starget;
-       struct mptsas_portinfo *port_info;
-};
-
-struct mptsas_phyinfo {
-       u16     handle;                 /* unique id to address this */
-       u8      phy_id;                 /* phy index */
-       u8      port_id;                /* firmware port identifier */
-       u8      negotiated_link_rate;   /* nego'd link rate for this phy */
-       u8      hw_link_rate;           /* hardware max/min phys link rate */
-       u8      programmed_link_rate;   /* programmed max/min phy link rate */
-       u8      sas_port_add_phy;       /* flag to request sas_port_add_phy*/
-       struct mptsas_devinfo identify; /* point to phy device info */
-       struct mptsas_devinfo attached; /* point to attached device info */
-       struct sas_phy *phy;            /* transport layer phy object */
-       struct mptsas_portinfo *portinfo;
-       struct mptsas_portinfo_details * port_details;
-};
-
-struct mptsas_portinfo {
-       struct list_head list;
-       u16             num_phys;       /* number of phys */
-       struct mptsas_phyinfo *phy_info;
-};
-
-struct mptsas_enclosure {
-       u64     enclosure_logical_id;   /* The WWN for the enclosure */
-       u16     enclosure_handle;       /* unique id to address this */
-       u16     flags;                  /* details enclosure management */
-       u16     num_slot;               /* num slots */
-       u16     start_slot;             /* first slot */
-       u8      start_id;               /* starting logical target id */
-       u8      start_channel;          /* starting logical channel id */
-       u8      sep_id;                 /* SEP device logical target id */
-       u8      sep_channel;            /* SEP channel logical channel id */
-};
-
 static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
                                        MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
 {
-       dsasprintk(ioc, printk(KERN_DEBUG "---- IO UNIT PAGE 0 ------------\n"));
-       dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n",
-               le16_to_cpu(phy_data->AttachedDeviceHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Controller Handle=0x%X\n",
-               le16_to_cpu(phy_data->ControllerDevHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Port=0x%X\n", phy_data->Port));
-       dsasprintk(ioc, printk(KERN_DEBUG "Port Flags=0x%X\n", phy_data->PortFlags));
-       dsasprintk(ioc, printk(KERN_DEBUG "PHY Flags=0x%X\n", phy_data->PhyFlags));
-       dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate));
-       dsasprintk(ioc, printk(KERN_DEBUG "Controller PHY Device Info=0x%X\n",
-               le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
-       dsasprintk(ioc, printk(KERN_DEBUG "DiscoveryStatus=0x%X\n\n",
-               le32_to_cpu(phy_data->DiscoveryStatus)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "---- IO UNIT PAGE 0 ------------\n", ioc->name));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
+           ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
+           ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
+           ioc->name, phy_data->Port));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
+           ioc->name, phy_data->PortFlags));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
+           ioc->name, phy_data->PhyFlags));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
+           ioc->name, phy_data->NegotiatedLinkRate));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "Controller PHY Device Info=0x%X\n", ioc->name,
+           le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
+           ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
 }
 
 static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
@@ -225,27 +126,41 @@ static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
 
        memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
 
-       dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 0 ------------\n"));
-       dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n",
-                       le16_to_cpu(pg0->AttachedDevHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n",
-                       (unsigned long long)le64_to_cpu(sas_address)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier));
-       dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Info=0x%X\n",
-                       le32_to_cpu(pg0->AttachedDeviceInfo)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate));
-       dsasprintk(ioc, printk(KERN_DEBUG "Change Count=0x%X\n", pg0->ChangeCount));
-       dsasprintk(ioc, printk(KERN_DEBUG "PHY Info=0x%X\n\n", le32_to_cpu(pg0->PhyInfo)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "---- SAS PHY PAGE 0 ------------\n", ioc->name));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "Attached Device Handle=0x%X\n", ioc->name,
+           le16_to_cpu(pg0->AttachedDevHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
+           ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "Attached PHY Identifier=0x%X\n", ioc->name,
+           pg0->AttachedPhyIdentifier));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
+           ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
+           ioc->name,  pg0->ProgrammedLinkRate));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
+           ioc->name, pg0->ChangeCount));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
+           ioc->name, le32_to_cpu(pg0->PhyInfo)));
 }
 
 static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
 {
-       dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 1 ------------\n"));
-       dsasprintk(ioc, printk(KERN_DEBUG "Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount));
-       dsasprintk(ioc, printk(KERN_DEBUG "Running Disparity Error Count=0x%x\n",
-                       pg1->RunningDisparityErrorCount));
-       dsasprintk(ioc, printk(KERN_DEBUG "Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount));
-       dsasprintk(ioc, printk(KERN_DEBUG "PHY Reset Problem Count=0x%x\n\n", pg1->PhyResetProblemCount));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "---- SAS PHY PAGE 1 ------------\n", ioc->name));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
+           ioc->name,  pg1->InvalidDwordCount));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "Running Disparity Error Count=0x%x\n", ioc->name,
+           pg1->RunningDisparityErrorCount));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "Loss Dword Synch Count=0x%x\n", ioc->name,
+           pg1->LossDwordSynchCount));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "PHY Reset Problem Count=0x%x\n\n", ioc->name,
+           pg1->PhyResetProblemCount));
 }
 
 static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
@@ -254,37 +169,53 @@ static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
 
        memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
 
-       dsasprintk(ioc, printk(KERN_DEBUG "---- SAS DEVICE PAGE 0 ---------\n"));
-       dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Slot=0x%X\n", le16_to_cpu(pg0->Slot)));
-       dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n", (unsigned long long)
-           le64_to_cpu(sas_address)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Target ID=0x%X\n", pg0->TargetID));
-       dsasprintk(ioc, printk(KERN_DEBUG "Bus=0x%X\n", pg0->Bus));
-       /* The PhyNum field specifies the PHY number of the parent
-        * device this device is linked to
-        */
-       dsasprintk(ioc, printk(KERN_DEBUG "Parent Phy Num=0x%X\n", pg0->PhyNum));
-       dsasprintk(ioc, printk(KERN_DEBUG "Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Flags=0x%X\n", le16_to_cpu(pg0->Flags)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n\n", pg0->PhysicalPort));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
+           ioc->name, le16_to_cpu(pg0->DevHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
+           ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
+           ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
+           ioc->name, le16_to_cpu(pg0->Slot)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
+           ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
+           ioc->name, pg0->TargetID));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
+           ioc->name, pg0->Bus));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
+           ioc->name, pg0->PhyNum));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
+           ioc->name, le16_to_cpu(pg0->AccessStatus)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
+           ioc->name, le32_to_cpu(pg0->DeviceInfo)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
+           ioc->name, le16_to_cpu(pg0->Flags)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
+           ioc->name, pg0->PhysicalPort));
 }
 
 static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
 {
-       dsasprintk(ioc, printk(KERN_DEBUG "---- SAS EXPANDER PAGE 1 ------------\n"));
-       dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n", pg1->PhysicalPort));
-       dsasprintk(ioc, printk(KERN_DEBUG "PHY Identifier=0x%X\n", pg1->PhyIdentifier));
-       dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate));
-       dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate));
-       dsasprintk(ioc, printk(KERN_DEBUG "Hardware Link Rate=0x%X\n", pg1->HwLinkRate));
-       dsasprintk(ioc, printk(KERN_DEBUG "Owner Device Handle=0x%X\n",
-                       le16_to_cpu(pg1->OwnerDevHandle)));
-       dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n\n",
-                       le16_to_cpu(pg1->AttachedDevHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
+           ioc->name, pg1->PhysicalPort));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
+           ioc->name, pg1->PhyIdentifier));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
+           ioc->name, pg1->NegotiatedLinkRate));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
+           ioc->name, pg1->ProgrammedLinkRate));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
+           ioc->name, pg1->HwLinkRate));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
+           ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
+       dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           "Attached Device Handle=0x%X\n\n", ioc->name,
+           le16_to_cpu(pg1->AttachedDevHandle)));
 }
 
 static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
@@ -354,8 +285,8 @@ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_detai
        port_info = port_details->port_info;
        phy_info = port_info->phy_info;
 
-       dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: num_phys=%02d "
-           "bitmask=0x%016llX\n", __FUNCTION__, port_details,
+       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
+           "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details,
            port_details->num_phys, (unsigned long long)
            port_details->phy_bitmask));
 
@@ -382,14 +313,15 @@ mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rp
 {
        if (phy_info->port_details) {
                phy_info->port_details->rphy = rphy;
-               dsaswideprintk(ioc, printk(KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
+                   ioc->name, rphy));
        }
 
        if (rphy) {
                dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
-                   &rphy->dev, "add:"));
-               dsaswideprintk(ioc, printk(KERN_DEBUG "rphy=%p release=%p\n",
-                       rphy, rphy->dev.release));
+                   &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
+                   ioc->name, rphy, rphy->dev.release));
        }
 }
 
@@ -410,9 +342,9 @@ mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_po
 
        if (port) {
                dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
-                   &port->dev, "add:"));
-               dsaswideprintk(ioc, printk(KERN_DEBUG "port=%p release=%p\n",
-                       port, port->dev.release));
+                   &port->dev, MYIOC_s_FMT "add:", ioc->name));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
+                   ioc->name, port, port->dev.release));
        }
 }
 
@@ -463,9 +395,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                 * Removing a phy from a port, letting the last
                 * phy be removed by firmware events.
                 */
-               dsaswideprintk(ioc, printk(KERN_DEBUG
-                       "%s: [%p]: deleting phy = %d\n",
-                       __FUNCTION__, port_details, i));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "%s: [%p]: deleting phy = %d\n",
+                   ioc->name, __FUNCTION__, port_details, i));
                port_details->num_phys--;
                port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
                memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
@@ -479,8 +411,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
        phy_info = port_info->phy_info;
        for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
                sas_address = phy_info->attached.sas_address;
-               dsaswideprintk(ioc, printk(KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
-                   i, (unsigned long long)sas_address));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
+                   ioc->name, i, (unsigned long long)sas_address));
                if (!sas_address)
                        continue;
                port_details = phy_info->port_details;
@@ -498,9 +430,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                                port_details->phy_bitmask |=
                                    (1 << phy_info->phy_id);
                        phy_info->sas_port_add_phy=1;
-                       dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tForming port\n\t\t"
+                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
                            "phy_id=%d sas_address=0x%018llX\n",
-                           i, (unsigned long long)sas_address));
+                           ioc->name, i, (unsigned long long)sas_address));
                        phy_info->port_details = port_details;
                }
 
@@ -515,9 +447,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                                continue;
                        if (phy_info_cmp->port_details == port_details )
                                continue;
-                       dsaswideprintk(ioc, printk(KERN_DEBUG
+                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                            "\t\tphy_id=%d sas_address=0x%018llX\n",
-                           j, (unsigned long long)
+                           ioc->name, j, (unsigned long long)
                            phy_info_cmp->attached.sas_address));
                        if (phy_info_cmp->port_details) {
                                port_details->rphy =
@@ -549,15 +481,15 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                port_details = port_info->phy_info[i].port_details;
                if (!port_details)
                        continue;
-               dsaswideprintk(ioc, printk(KERN_DEBUG
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "%s: [%p]: phy_id=%02d num_phys=%02d "
-                   "bitmask=0x%016llX\n", __FUNCTION__,
+                   "bitmask=0x%016llX\n", ioc->name, __FUNCTION__,
                    port_details, i, port_details->num_phys,
                    (unsigned long long)port_details->phy_bitmask));
-               dsaswideprintk(ioc, printk(KERN_DEBUG"\t\tport = %p rphy=%p\n",
-                       port_details->port, port_details->rphy));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
+                   ioc->name, port_details->port, port_details->rphy));
        }
-       dsaswideprintk(ioc, printk(KERN_DEBUG"\n"));
+       dsaswideprintk(ioc, printk("\n"));
        mutex_unlock(&ioc->sas_topology_mutex);
 }
 
@@ -573,15 +505,15 @@ static VirtTarget *
 mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
        struct scsi_device              *sdev;
-       VirtDevice                      *vdev;
+       VirtDevice                      *vdevice;
        VirtTarget                      *vtarget = NULL;
 
        shost_for_each_device(sdev, ioc->sh) {
-               if ((vdev = sdev->hostdata) == NULL)
+               if ((vdevice = sdev->hostdata) == NULL)
                        continue;
-               if (vdev->vtarget->id == id &&
-                   vdev->vtarget->channel == channel)
-                       vtarget = vdev->vtarget;
+               if (vdevice->vtarget->id == id &&
+                   vdevice->vtarget->channel == channel)
+                       vtarget = vdevice->vtarget;
        }
        return vtarget;
 }
@@ -623,13 +555,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
 
        DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
 
-       if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
-           sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) {
-               mpt_free_msg_frame(ioc, mf);
-               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
-                   ioc->name,__FUNCTION__, __LINE__));
-               return 0;
-       }
+       mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
 
        return 1;
 }
@@ -649,7 +575,7 @@ static void
 mptsas_target_reset_queue(MPT_ADAPTER *ioc,
     EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
 {
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
        VirtTarget *vtarget = NULL;
        struct mptsas_target_reset_event *target_reset_list;
        u8              id, channel;
@@ -696,7 +622,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
 static void
 mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
 {
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
         struct list_head *head = &hd->target_reset_list;
        struct mptsas_target_reset_event *target_reset_list;
        struct mptsas_hotplug_event *ev;
@@ -813,7 +739,7 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
        if (!ioc->sh || !ioc->sh->hostdata)
                goto out;
-       hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+       hd = shost_priv(ioc->sh);
        if (!hd->ioc)
                goto out;
 
@@ -913,19 +839,20 @@ static int
 mptsas_target_alloc(struct scsi_target *starget)
 {
        struct Scsi_Host *host = dev_to_shost(&starget->dev);
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST           *hd = shost_priv(host);
        VirtTarget              *vtarget;
        u8                      id, channel;
        struct sas_rphy         *rphy;
        struct mptsas_portinfo  *p;
        int                      i;
+       MPT_ADAPTER             *ioc = hd->ioc;
 
        vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
        if (!vtarget)
                return -ENOMEM;
 
        vtarget->starget = starget;
-       vtarget->ioc_id = hd->ioc->id;
+       vtarget->ioc_id = ioc->id;
        vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
        id = starget->id;
        channel = 0;
@@ -934,15 +861,15 @@ mptsas_target_alloc(struct scsi_target *starget)
         * RAID volumes placed beyond the last expected port.
         */
        if (starget->channel == MPTSAS_RAID_CHANNEL) {
-               for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
-                       if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
-                               channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
+               for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
+                       if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
+                               channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
                goto out;
        }
 
        rphy = dev_to_rphy(starget->dev.parent);
-       mutex_lock(&hd->ioc->sas_topology_mutex);
-       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry(p, &ioc->sas_topology, list) {
                for (i = 0; i < p->num_phys; i++) {
                        if (p->phy_info[i].attached.sas_address !=
                                        rphy->identify.sas_address)
@@ -954,18 +881,18 @@ mptsas_target_alloc(struct scsi_target *starget)
                        /*
                         * Exposing hidden raid components
                         */
-                       if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
-                               id = mptscsih_raid_id_to_num(hd->ioc,
+                       if (mptscsih_is_phys_disk(ioc, channel, id)) {
+                               id = mptscsih_raid_id_to_num(ioc,
                                                channel, id);
                                vtarget->tflags |=
                                    MPT_TARGET_FLAGS_RAID_COMPONENT;
                                p->phy_info[i].attached.phys_disk_num = id;
                        }
-                       mutex_unlock(&hd->ioc->sas_topology_mutex);
+                       mutex_unlock(&ioc->sas_topology_mutex);
                        goto out;
                }
        }
-       mutex_unlock(&hd->ioc->sas_topology_mutex);
+       mutex_unlock(&ioc->sas_topology_mutex);
 
        kfree(vtarget);
        return -ENXIO;
@@ -981,10 +908,11 @@ static void
 mptsas_target_destroy(struct scsi_target *starget)
 {
        struct Scsi_Host *host = dev_to_shost(&starget->dev);
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST           *hd = shost_priv(host);
        struct sas_rphy         *rphy;
        struct mptsas_portinfo  *p;
        int                      i;
+       MPT_ADAPTER *ioc = hd->ioc;
 
        if (!starget->hostdata)
                return;
@@ -993,7 +921,7 @@ mptsas_target_destroy(struct scsi_target *starget)
                goto out;
 
        rphy = dev_to_rphy(starget->dev.parent);
-       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+       list_for_each_entry(p, &ioc->sas_topology, list) {
                for (i = 0; i < p->num_phys; i++) {
                        if (p->phy_info[i].attached.sas_address !=
                                        rphy->identify.sas_address)
@@ -1013,61 +941,62 @@ static int
 mptsas_slave_alloc(struct scsi_device *sdev)
 {
        struct Scsi_Host        *host = sdev->host;
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST           *hd = shost_priv(host);
        struct sas_rphy         *rphy;
        struct mptsas_portinfo  *p;
-       VirtDevice              *vdev;
+       VirtDevice              *vdevice;
        struct scsi_target      *starget;
        int                     i;
+       MPT_ADAPTER *ioc = hd->ioc;
 
-       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
-       if (!vdev) {
+       vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!vdevice) {
                printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
-                               hd->ioc->name, sizeof(VirtDevice));
+                               ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
        starget = scsi_target(sdev);
-       vdev->vtarget = starget->hostdata;
+       vdevice->vtarget = starget->hostdata;
 
        if (sdev->channel == MPTSAS_RAID_CHANNEL)
                goto out;
 
        rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
-       mutex_lock(&hd->ioc->sas_topology_mutex);
-       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry(p, &ioc->sas_topology, list) {
                for (i = 0; i < p->num_phys; i++) {
                        if (p->phy_info[i].attached.sas_address !=
                                        rphy->identify.sas_address)
                                continue;
-                       vdev->lun = sdev->lun;
+                       vdevice->lun = sdev->lun;
                        /*
                         * Exposing hidden raid components
                         */
-                       if (mptscsih_is_phys_disk(hd->ioc,
+                       if (mptscsih_is_phys_disk(ioc,
                            p->phy_info[i].attached.channel,
                            p->phy_info[i].attached.id))
                                sdev->no_uld_attach = 1;
-                       mutex_unlock(&hd->ioc->sas_topology_mutex);
+                       mutex_unlock(&ioc->sas_topology_mutex);
                        goto out;
                }
        }
-       mutex_unlock(&hd->ioc->sas_topology_mutex);
+       mutex_unlock(&ioc->sas_topology_mutex);
 
-       kfree(vdev);
+       kfree(vdevice);
        return -ENXIO;
 
  out:
-       vdev->vtarget->num_luns++;
-       sdev->hostdata = vdev;
+       vdevice->vtarget->num_luns++;
+       sdev->hostdata = vdevice;
        return 0;
 }
 
 static int
 mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
-       VirtDevice      *vdev = SCpnt->device->hostdata;
+       VirtDevice      *vdevice = SCpnt->device->hostdata;
 
-       if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
+       if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
                SCpnt->result = DID_NO_CONNECT << 16;
                done(SCpnt);
                return 0;
@@ -1239,10 +1168,8 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
        /* process the completed Reply Message Frame */
        reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
        if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
-               printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
-                   __FUNCTION__,
-                   reply->IOCStatus,
-                   reply->IOCLogInfo);
+               printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+                   ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);
                error = -ENXIO;
                goto out_unlock;
        }
@@ -1328,16 +1255,16 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        u64 sas_address = 0;
 
        if (!rsp) {
-               printk(KERN_ERR "%s: the smp response space is missing\n",
-                      __FUNCTION__);
+               printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
+                   ioc->name, __FUNCTION__);
                return -EINVAL;
        }
 
        /* do we need to support multiple segments? */
        if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
-               printk(KERN_ERR "%s: multiple segments req %u %u, rsp %u %u\n",
-                      __FUNCTION__, req->bio->bi_vcnt, req->data_len,
-                      rsp->bio->bi_vcnt, rsp->data_len);
+               printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
+                   ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len,
+                   rsp->bio->bi_vcnt, rsp->data_len);
                return -EINVAL;
        }
 
@@ -1402,7 +1329,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
        if (!timeleft) {
-               printk(KERN_ERR "%s: smp timeout!\n", __FUNCTION__);
+               printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);
                /* On timeout reset the board */
                mpt_HardResetHandler(ioc, CAN_SLEEP);
                ret = -ETIMEDOUT;
@@ -1417,8 +1344,8 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                memcpy(req->sense, smprep, sizeof(*smprep));
                req->sense_len = sizeof(*smprep);
        } else {
-               printk(KERN_ERR "%s: smp passthru reply failed to be returned\n",
-                      __FUNCTION__);
+               printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
+                   ioc->name, __FUNCTION__);
                ret = -ENXIO;
        }
 unmap:
@@ -2062,12 +1989,12 @@ static int mptsas_probe_one_phy(struct device *dev,
                                goto out;
                        }
                        mptsas_set_port(ioc, phy_info, port);
-                       dsaswideprintk(ioc, printk(KERN_DEBUG
+                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                            "sas_port_alloc: port=%p dev=%p port_id=%d\n",
-                           port, dev, port->port_identifier));
+                           ioc->name, port, dev, port->port_identifier));
                }
-               dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
-                   phy_info->phy_id));
+               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
+                   ioc->name, phy_info->phy_id));
                sas_port_add_phy(port, phy_info->phy);
                phy_info->sas_port_add_phy = 0;
        }
@@ -2369,8 +2296,9 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
                                        expander_sas_address)
                                        continue;
                                dsaswideprintk(ioc,
-                                       dev_printk(KERN_DEBUG, &port->dev,
-                                       "delete port (%d)\n", port->port_identifier));
+                                   dev_printk(KERN_DEBUG, &port->dev,
+                                   MYIOC_s_FMT "delete port (%d)\n", ioc->name,
+                                   port->port_identifier));
                                sas_port_delete(port);
                                mptsas_port_delete(ioc, phy_info->port_details);
                        }
@@ -2613,7 +2541,7 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
 
                ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
                if (!ev) {
-                       printk(KERN_WARNING "mptsas: lost hotplug event\n");
+                       printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
                        goto out;
                }
 
@@ -2754,8 +2682,8 @@ mptsas_hotplug_work(struct work_struct *work)
                printk(MYIOC_s_INFO_FMT
                       "removing %s device, channel %d, id %d, phy %d\n",
                       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
-               dev_printk(KERN_DEBUG, &port->dev,
-                   "delete port (%d)\n", port->port_identifier);
+               dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
+                   "delete port (%d)\n", ioc->name, port->port_identifier);
                sas_port_delete(port);
                mptsas_port_delete(ioc, phy_info->port_details);
                break;
@@ -2796,8 +2724,8 @@ mptsas_hotplug_work(struct work_struct *work)
 
                        if (!vtarget) {
                                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-                                       "%s: exit at line=%d\n", ioc->name,
-                                       __FUNCTION__, __LINE__));
+                                   "%s: exit at line=%d\n", ioc->name,
+                                   __FUNCTION__, __LINE__));
                                break;
                        }
                        /*
@@ -2930,7 +2858,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
        case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
                ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
                if (!ev) {
-                       printk(KERN_WARNING "mptsas: lost hotplug event\n");
+                       printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
                        break;
                }
 
@@ -2989,7 +2917,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
 
        ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
        if (!ev) {
-               printk(KERN_WARNING "mptsas: lost hotplug event\n");
+               printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
                return;
        }
 
@@ -3288,20 +3216,22 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                sh->sg_tablesize = numSGE;
        }
 
-       hd = (MPT_SCSI_HOST *) sh->hostdata;
+       hd = shost_priv(sh);
        hd->ioc = ioc;
 
        /* SCSI needs scsi_cmnd lookup table!
         * (with size equal to req_depth*PtrSz!)
         */
-       hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
-       if (!hd->ScsiLookup) {
+       ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+       if (!ioc->ScsiLookup) {
                error = -ENOMEM;
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
                goto out_mptsas_probe;
        }
+       spin_lock_init(&ioc->scsi_lookup_lock);
 
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
-                ioc->name, hd->ScsiLookup));
+                ioc->name, ioc->ScsiLookup));
 
        /* Clear the TM flags
         */
@@ -3340,8 +3270,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        error = scsi_add_host(sh, &ioc->pcidev->dev);
        if (error) {
-               dprintk(ioc, printk(KERN_ERR MYNAM
-                 "scsi_add_host failed\n"));
+               dprintk(ioc, printk(MYIOC_s_ERR_FMT
+                 "scsi_add_host failed\n", ioc->name));
                goto out_mptsas_probe;
        }
 
diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h
new file mode 100644 (file)
index 0000000..7c150f5
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *  linux/drivers/message/fusion/mptsas.h
+ *      High performance SCSI + LAN / Fibre Channel device drivers.
+ *      For use with PCI chip/adapter(s):
+ *          LSIFC9xx/LSI409xx Fibre Channel
+ *      running LSI MPT (Message Passing Technology) firmware.
+ *
+ *  Copyright (c) 1999-2007 LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; version 2 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MPTSAS_H_INCLUDED
+#define MPTSAS_H_INCLUDED
+/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+struct mptsas_target_reset_event {
+       struct list_head        list;
+       EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
+       u8      target_reset_issued;
+};
+
+enum mptsas_hotplug_action {
+       MPTSAS_ADD_DEVICE,
+       MPTSAS_DEL_DEVICE,
+       MPTSAS_ADD_RAID,
+       MPTSAS_DEL_RAID,
+       MPTSAS_ADD_INACTIVE_VOLUME,
+       MPTSAS_IGNORE_EVENT,
+};
+
+struct mptsas_hotplug_event {
+       struct work_struct      work;
+       MPT_ADAPTER             *ioc;
+       enum mptsas_hotplug_action event_type;
+       u64                     sas_address;
+       u8                      channel;
+       u8                      id;
+       u32                     device_info;
+       u16                     handle;
+       u16                     parent_handle;
+       u8                      phy_id;
+       u8                      phys_disk_num_valid;    /* hrc (hidden raid component) */
+       u8                      phys_disk_num;          /* hrc - unique index*/
+       u8                      hidden_raid_component;  /* hrc - don't expose*/
+};
+
+struct mptsas_discovery_event {
+       struct work_struct      work;
+       MPT_ADAPTER             *ioc;
+};
+
+/*
+ * SAS topology structures
+ *
+ * The MPT Fusion firmware interface spreads information about the
+ * SAS topology over many manufacture pages, thus we need some data
+ * structure to collect it and process it for the SAS transport class.
+ */
+
+struct mptsas_devinfo {
+       u16     handle;         /* unique id to address this device */
+       u16     handle_parent;  /* unique id to address parent device */
+       u16     handle_enclosure; /* enclosure identifier of the enclosure */
+       u16     slot;           /* physical slot in enclosure */
+       u8      phy_id;         /* phy number of parent device */
+       u8      port_id;        /* sas physical port this device
+                                  is assoc'd with */
+       u8      id;             /* logical target id of this device */
+       u32     phys_disk_num;  /* phys disk id, for csmi-ioctls */
+       u8      channel;        /* logical bus number of this device */
+       u64     sas_address;    /* WWN of this device,
+                                  SATA is assigned by HBA,expander */
+       u32     device_info;    /* bitfield detailed info about this device */
+};
+
+/*
+ * Specific details on ports, wide/narrow
+ */
+struct mptsas_portinfo_details{
+       u16     num_phys;       /* number of phys belong to this port */
+       u64     phy_bitmask;    /* TODO, extend support for 255 phys */
+       struct sas_rphy *rphy;  /* transport layer rphy object */
+       struct sas_port *port;  /* transport layer port object */
+       struct scsi_target *starget;
+       struct mptsas_portinfo *port_info;
+};
+
+struct mptsas_phyinfo {
+       u16     handle;                 /* unique id to address this */
+       u8      phy_id;                 /* phy index */
+       u8      port_id;                /* firmware port identifier */
+       u8      negotiated_link_rate;   /* nego'd link rate for this phy */
+       u8      hw_link_rate;           /* hardware max/min phys link rate */
+       u8      programmed_link_rate;   /* programmed max/min phy link rate */
+       u8      sas_port_add_phy;       /* flag to request sas_port_add_phy*/
+       struct mptsas_devinfo identify; /* point to phy device info */
+       struct mptsas_devinfo attached; /* point to attached device info */
+       struct sas_phy *phy;            /* transport layer phy object */
+       struct mptsas_portinfo *portinfo;
+       struct mptsas_portinfo_details * port_details;
+};
+
+struct mptsas_portinfo {
+       struct list_head list;
+       u16             num_phys;       /* number of phys */
+       struct mptsas_phyinfo *phy_info;
+};
+
+struct mptsas_enclosure {
+       u64     enclosure_logical_id;   /* The WWN for the enclosure */
+       u16     enclosure_handle;       /* unique id to address this */
+       u16     flags;                  /* details enclosure management */
+       u16     num_slot;               /* num slots */
+       u16     start_slot;             /* first slot */
+       u8      start_id;               /* starting logical target id */
+       u8      start_channel;          /* starting logical channel id */
+       u8      sep_id;                 /* SEP device logical target id */
+       u8      sep_channel;            /* SEP channel logical channel id */
+};
+
+/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#endif
index 5431529741ad28380442e3b5618d799b988bdecd..bdff950a54a19103195e893ada00b76f187f251e 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/message/fusion/mptscsih.c
- *      For use with LSI Logic PCI chip/adapter(s)
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI PCI chip/adapter(s)
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -80,6 +80,10 @@ MODULE_VERSION(my_VERSION);
 /*
  *  Other private/forward protos...
  */
+static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
+static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
+static void    mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
+static int     SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
 int            mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static void    mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
 int            mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
@@ -90,7 +94,6 @@ static void   mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
 static void    mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int     mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 static int     mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
-static int     SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
 
 static int     mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
 
@@ -192,7 +195,7 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
        int chain_idx;
 
        dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
-                       ioc->name));
+           ioc->name));
        spin_lock_irqsave(&ioc->FreeQlock, flags);
        if (!list_empty(&ioc->FreeChainQ)) {
                int offset;
@@ -203,13 +206,14 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
                offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
                chain_idx = offset / ioc->req_sz;
                rc = SUCCESS;
-               dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
-                       ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
+               dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
+                   ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
        } else {
                rc = FAILED;
                chain_idx = MPT_HOST_NO_CHAIN;
-               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer failed\n",
-                       ioc->name));
+               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
+                   ioc->name));
        }
        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
@@ -419,8 +423,8 @@ nextSGEset:
                 *   out the Address and Flags fields.
                 */
                chainSge = (char *) psge;
-               dsgprintk(ioc, printk(KERN_DEBUG "  Current buff @ %p (index 0x%x)",
-                               psge, req_idx));
+               dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "  Current buff @ %p (index 0x%x)",
+                   ioc->name, psge, req_idx));
 
                /* Start the SGE for the next buffer
                 */
@@ -428,8 +432,8 @@ nextSGEset:
                sgeOffset = 0;
                sg_done = 0;
 
-               dsgprintk(ioc, printk(KERN_DEBUG "  Chain buff @ %p (index 0x%x)\n",
-                               psge, chain_idx));
+               dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "  Chain buff @ %p (index 0x%x)\n",
+                   ioc->name, psge, chain_idx));
 
                /* Start the SGE for the next buffer
                 */
@@ -588,18 +592,17 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc
        }
 
        scsi_print_command(sc);
-       printk(KERN_DEBUG "\tfw_channel = %d, fw_id = %d\n",
-           pScsiReply->Bus, pScsiReply->TargetID);
-       printk(KERN_DEBUG "\trequest_len = %d, underflow = %d, resid = %d\n",
-           scsi_bufflen(sc), sc->underflow, scsi_get_resid(sc));
-       printk(KERN_DEBUG "\ttag = %d, transfer_count = %d, sc->result = %08X\n",
-           le16_to_cpu(pScsiReply->TaskTag),
+       printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",
+           ioc->name, pScsiReply->Bus, pScsiReply->TargetID);
+       printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
+           "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
+           scsi_get_resid(sc));
+       printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
+           "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
            le32_to_cpu(pScsiReply->TransferCount), sc->result);
-
-       printk(KERN_DEBUG "\tiocstatus = %s (0x%04x), "
+       printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
            "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
-           desc, ioc_status,
-           desc1, pScsiReply->SCSIStatus,
+           ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
            pScsiReply->SCSIState);
 
        if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -607,9 +610,8 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc
                asc = sc->sense_buffer[12];
                ascq = sc->sense_buffer[13];
 
-               printk(KERN_DEBUG "\t[sense_key,asc,ascq]: "
-                   "[0x%02x,0x%02x,0x%02x]\n",
-                   skey, asc, ascq);
+               printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: "
+                   "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq);
        }
 
        /*
@@ -617,8 +619,8 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc
         */
        if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
            pScsiReply->ResponseInfo)
-               printk(KERN_DEBUG "response_info = %08xh\n",
-                   le32_to_cpu(pScsiReply->ResponseInfo));
+               printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n",
+                   ioc->name, le32_to_cpu(pScsiReply->ResponseInfo));
 }
 #endif
 
@@ -645,11 +647,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        SCSIIORequest_t *pScsiReq;
        SCSIIOReply_t   *pScsiReply;
        u16              req_idx, req_idx_MR;
-       VirtDevice       *vdev;
+       VirtDevice       *vdevice;
        VirtTarget       *vtarget;
 
-       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-
+       hd = shost_priv(ioc->sh);
        req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
        req_idx_MR = (mr != NULL) ?
            le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
@@ -660,12 +661,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                printk (MYIOC_s_ERR_FMT
                    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
                    ioc->name, req_idx, req_idx_MR, mf, mr,
-                   hd->ScsiLookup[req_idx_MR]);
+                   mptscsih_get_scsi_lookup(ioc, req_idx_MR));
                return 0;
        }
 
-       sc = hd->ScsiLookup[req_idx];
-       hd->ScsiLookup[req_idx] = NULL;
+       sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
        if (sc == NULL) {
                MPIHeader_t *hdr = (MPIHeader_t *)mf;
 
@@ -738,8 +738,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                 */
                if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
                    pScsiReply->ResponseInfo) {
-                       printk(KERN_NOTICE "[%d:%d:%d:%d] "
-                       "FCP_ResponseInfo=%08xh\n",
+                       printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
+                       "FCP_ResponseInfo=%08xh\n", ioc->name,
                        sc->device->host->host_no, sc->device->channel,
                        sc->device->id, sc->device->lun,
                        le32_to_cpu(pScsiReply->ResponseInfo));
@@ -771,10 +771,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
                                hd->sel_timeout[pScsiReq->TargetID]++;
 
-                       vdev = sc->device->hostdata;
-                       if (!vdev)
+                       vdevice = sc->device->hostdata;
+                       if (!vdevice)
                                break;
-                       vtarget = vdev->vtarget;
+                       vtarget = vdevice->vtarget;
                        if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
                                mptscsih_issue_sep_command(ioc, vtarget,
                                    MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
@@ -824,9 +824,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                sc->result=DID_SOFT_ERROR << 16;
                        else /* Sufficient data transfer occurred */
                                sc->result = (DID_OK << 16) | scsi_status;
-                       dreplyprintk(ioc, printk(KERN_DEBUG
+                       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                            "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
-                           sc->result, sc->device->channel, sc->device->id));
+                           ioc->name, sc->result, sc->device->channel, sc->device->id));
                        break;
 
                case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
@@ -858,9 +858,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        }
 
 
-                       dreplyprintk(ioc, printk(KERN_DEBUG "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
-                                       sc->underflow));
-                       dreplyprintk(ioc, printk(KERN_DEBUG "  ActBytesXferd=%02xh\n", xfer_cnt));
+                       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                           "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
+                           ioc->name, sc->underflow));
+                       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                           "  ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
 
                        /* Report Queue Full
                         */
@@ -969,48 +971,32 @@ static void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
        MPT_ADAPTER *ioc = hd->ioc;
-       struct scsi_cmnd        *SCpnt;
-       MPT_FRAME_HDR   *mf;
+       struct scsi_cmnd *sc;
+       SCSIIORequest_t *mf = NULL;
        int              ii;
-       int              max = ioc->req_depth;
-
-       dprintk(ioc, printk(KERN_DEBUG MYNAM ": flush_ScsiLookup called\n"));
-       for (ii= 0; ii < max; ii++) {
-               if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
-
-                       /* Command found.
-                        */
-
-                       /* Null ScsiLookup index
-                        */
-                       hd->ScsiLookup[ii] = NULL;
-
-                       mf = MPT_INDEX_2_MFPTR(ioc, ii);
-                       dmfprintk(ioc, printk(KERN_DEBUG MYNAM ": flush: ScsiDone (mf=%p,sc=%p)\n",
-                                       mf, SCpnt));
-
-                       /* Free Chain buffers */
-                       mptscsih_freeChainBuffers(ioc, ii);
-
-                       /* Free Message frames */
-                       mpt_free_msg_frame(ioc, mf);
-
-                       if ((unsigned char *)mf != SCpnt->host_scribble)
-                               continue;
-
-                       /* Set status, free OS resources (SG DMA buffers)
-                        * Do OS callback
-                        */
-                       scsi_dma_unmap(SCpnt);
-
-                       SCpnt->result = DID_RESET << 16;
-                       SCpnt->host_scribble = NULL;
+       int              channel, id;
 
-                       SCpnt->scsi_done(SCpnt);        /* Issue the command callback */
-               }
+       for (ii= 0; ii < ioc->req_depth; ii++) {
+               sc = mptscsih_getclear_scsi_lookup(ioc, ii);
+               if (!sc)
+                       continue;
+               mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
+               if (!mf)
+                       continue;
+               channel = mf->Bus;
+               id = mf->TargetID;
+               mptscsih_freeChainBuffers(ioc, ii);
+               mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
+               if ((unsigned char *)mf != sc->host_scribble)
+                       continue;
+               scsi_dma_unmap(sc);
+               sc->result = DID_RESET << 16;
+               sc->host_scribble = NULL;
+               sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
+                   "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
+                   " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
+               sc->scsi_done(sc);
        }
-
-       return;
 }
 
 /*
@@ -1032,17 +1018,16 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 {
        SCSIIORequest_t *mf = NULL;
        int              ii;
-       int              max = hd->ioc->req_depth;
        struct scsi_cmnd *sc;
        struct scsi_lun  lun;
+       MPT_ADAPTER *ioc = hd->ioc;
+       unsigned long   flags;
 
-       dsprintk(hd->ioc, printk(KERN_DEBUG MYNAM ": search_running channel %d id %d lun %d max %d\n",
-           vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
-
-       for (ii=0; ii < max; ii++) {
-               if ((sc = hd->ScsiLookup[ii]) != NULL) {
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       for (ii = 0; ii < ioc->req_depth; ii++) {
+               if ((sc = ioc->ScsiLookup[ii]) != NULL) {
 
-                       mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
+                       mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
                        if (mf == NULL)
                                continue;
                        /* If the device is a hidden raid component, then its
@@ -1059,22 +1044,23 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
                            memcmp(lun.scsi_lun, mf->LUN, 8))
                                continue;
 
-                       /* Cleanup
-                        */
-                       hd->ScsiLookup[ii] = NULL;
-                       mptscsih_freeChainBuffers(hd->ioc, ii);
-                       mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
                        if ((unsigned char *)mf != sc->host_scribble)
                                continue;
+                       ioc->ScsiLookup[ii] = NULL;
+                       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+                       mptscsih_freeChainBuffers(ioc, ii);
+                       mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
                        scsi_dma_unmap(sc);
                        sc->host_scribble = NULL;
                        sc->result = DID_NO_CONNECT << 16;
-                       sdev_printk(KERN_INFO, sc->device, "completing cmds: fw_channel %d,"
-                          "fw_id %d, sc=%p, mf = %p, idx=%x\n", vdevice->vtarget->channel,
+                       sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d,"
+                          "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
                           vdevice->vtarget->id, sc, mf, ii);
                        sc->scsi_done(sc);
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
                }
        }
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
        return;
 }
 
@@ -1097,17 +1083,18 @@ mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSI
 {
        long time = jiffies;
        MPT_SCSI_HOST           *hd;
+       MPT_ADAPTER     *ioc;
 
        if (sc->device == NULL)
                return;
        if (sc->device->host == NULL)
                return;
-       if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
+       if ((hd = shost_priv(sc->device->host)) == NULL)
                return;
-
+       ioc = hd->ioc;
        if (time - hd->last_queue_full > 10 * HZ) {
-               dprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
-                               hd->ioc->name, 0, sc->device->id, sc->device->lun));
+               dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
+                               ioc->name, 0, sc->device->id, sc->device->lun));
                hd->last_queue_full = time;
        }
 }
@@ -1134,28 +1121,28 @@ mptscsih_remove(struct pci_dev *pdev)
 
        scsi_remove_host(host);
 
-       if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
+       if((hd = shost_priv(host)) == NULL)
                return;
 
        mptscsih_shutdown(pdev);
 
        sz1=0;
 
-       if (hd->ScsiLookup != NULL) {
-               sz1 = hd->ioc->req_depth * sizeof(void *);
-               kfree(hd->ScsiLookup);
-               hd->ScsiLookup = NULL;
+       if (ioc->ScsiLookup != NULL) {
+               sz1 = ioc->req_depth * sizeof(void *);
+               kfree(ioc->ScsiLookup);
+               ioc->ScsiLookup = NULL;
        }
 
-       dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
+       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
            "Free'd ScsiLookup (%d) memory\n",
-           hd->ioc->name, sz1));
+           ioc->name, sz1));
 
        kfree(hd->info_kbuf);
 
        /* NULL the Scsi_Host pointer
         */
-       hd->ioc->sh = NULL;
+       ioc->sh = NULL;
 
        scsi_host_put(host);
 
@@ -1171,15 +1158,6 @@ mptscsih_remove(struct pci_dev *pdev)
 void
 mptscsih_shutdown(struct pci_dev *pdev)
 {
-       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
-       struct Scsi_Host        *host = ioc->sh;
-       MPT_SCSI_HOST           *hd;
-
-       if(!host)
-               return;
-
-       hd = (MPT_SCSI_HOST *)host->hostdata;
-
 }
 
 #ifdef CONFIG_PM
@@ -1225,7 +1203,7 @@ mptscsih_info(struct Scsi_Host *SChost)
        MPT_SCSI_HOST *h;
        int size = 0;
 
-       h = (MPT_SCSI_HOST *)SChost->hostdata;
+       h = shost_priv(SChost);
 
        if (h) {
                if (h->info_kbuf == NULL)
@@ -1319,7 +1297,7 @@ int
 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
                        int length, int func)
 {
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER     *ioc = hd->ioc;
        int size = 0;
 
@@ -1358,7 +1336,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        MPT_SCSI_HOST           *hd;
        MPT_FRAME_HDR           *mf;
        SCSIIORequest_t         *pScsiReq;
-       VirtDevice              *vdev = SCpnt->device->hostdata;
+       VirtDevice              *vdevice = SCpnt->device->hostdata;
        int      lun;
        u32      datalen;
        u32      scsictl;
@@ -1368,7 +1346,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        int      ii;
        MPT_ADAPTER *ioc;
 
-       hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+       hd = shost_priv(SCpnt->device->host);
        ioc = hd->ioc;
        lun = SCpnt->device->lun;
        SCpnt->scsi_done = done;
@@ -1385,7 +1363,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        /*
         *  Put together a MPT SCSI request...
         */
-       if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
+       if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
                dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
                                ioc->name));
                return SCSI_MLQUEUE_HOST_BUSY;
@@ -1415,8 +1393,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        /* Default to untagged. Once a target structure has been allocated,
         * use the Inquiry data to determine if device supports tagged.
         */
-       if (vdev
-           && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+       if (vdevice
+           && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
            && (SCpnt->device->tagged_supported)) {
                scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
        } else {
@@ -1425,10 +1403,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
        /* Use the above information to set up the message frame
         */
-       pScsiReq->TargetID = (u8) vdev->vtarget->id;
-       pScsiReq->Bus = vdev->vtarget->channel;
+       pScsiReq->TargetID = (u8) vdevice->vtarget->id;
+       pScsiReq->Bus = vdevice->vtarget->channel;
        pScsiReq->ChainOffset = 0;
-       if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
+       if (vdevice->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
                pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
        else
                pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
@@ -1453,7 +1431,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
        pScsiReq->DataLength = cpu_to_le32(datalen);
 
        /* SenseBuffer low address */
-       pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
+       pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
                                           + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
        /* Now add the SG list
@@ -1465,23 +1443,22 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
                        (dma_addr_t) -1);
        } else {
                /* Add a 32 or 64 bit SGE */
-               if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
+               if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
                        goto fail;
        }
 
        SCpnt->host_scribble = (unsigned char *)mf;
-       hd->ScsiLookup[my_idx] = SCpnt;
+       mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
 
-       mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
+       mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
                        ioc->name, SCpnt, mf, my_idx));
-       DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf)
+       DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
        return 0;
 
  fail:
-       hd->ScsiLookup[my_idx] = NULL;
-       mptscsih_freeChainBuffers(hd->ioc, my_idx);
-       mpt_free_msg_frame(hd->ioc, mf);
+       mptscsih_freeChainBuffers(ioc, my_idx);
+       mpt_free_msg_frame(ioc, mf);
        return SCSI_MLQUEUE_HOST_BUSY;
 }
 
@@ -1590,38 +1567,38 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
         */
        if (mptscsih_tm_pending_wait(hd) == FAILED) {
                if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
-                       dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler abort: "
+                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "
                           "Timed out waiting for last TM (%d) to complete! \n",
                           ioc->name, hd->tmPending));
                        return FAILED;
                } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
-                       dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler target "
+                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "
                                "reset: Timed out waiting for last TM (%d) "
                                "to complete! \n", ioc->name,
                                hd->tmPending));
                        return FAILED;
                } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
-                       dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler bus reset: "
+                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "
                           "Timed out waiting for last TM (%d) to complete! \n",
                          ioc->name, hd->tmPending));
                        return FAILED;
                }
        } else {
-               spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+               spin_lock_irqsave(&ioc->FreeQlock, flags);
                hd->tmPending |=  (1 << type);
-               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
        }
 
-       ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
+       ioc_raw_state = mpt_GetIocState(ioc, 0);
 
        if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
                printk(MYIOC_s_WARN_FMT
                        "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
                        ioc->name, type, ioc_raw_state);
-               printk(KERN_WARNING " Issuing HardReset!!\n");
+               printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);
                if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
-                       printk((KERN_WARNING "TMHandler: HardReset "
-                               "FAILED!!\n"));
+                       printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "
+                           "FAILED!!\n", ioc->name);
                return FAILED;
        }
 
@@ -1680,16 +1657,17 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i
        SCSITaskMgmt_t  *pScsiTm;
        int              ii;
        int              retval;
+       MPT_ADAPTER     *ioc = hd->ioc;
 
        /* Return Fail to calling function if no message frames available.
         */
-       if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
-               dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
-                               hd->ioc->name));
+       if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
+               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
+                               ioc->name));
                return FAILED;
        }
-       dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
-                       hd->ioc->name, mf));
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
+                       ioc->name, mf));
 
        /* Format the Request
         */
@@ -1712,28 +1690,34 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i
 
        pScsiTm->TaskMsgContext = ctx2abort;
 
-       dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
-               "type=%d\n", hd->ioc->name, ctx2abort, type));
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
+               "type=%d\n", ioc->name, ctx2abort, type));
 
        DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
 
-       if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
-               sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
-               dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
-                       " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
-                       hd->ioc, mf, retval));
-               goto fail_out;
+       if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
+           (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
+               mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
+       else {
+               retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
+                       sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
+               if (retval) {
+                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
+                       " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd,
+                       ioc, mf, retval));
+                       goto fail_out;
+               }
        }
 
        if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
-               dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
-                       " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
-                       hd->ioc, mf));
-               dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
-                        hd->ioc->name));
-               retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
-               dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
-                        hd->ioc->name, retval));
+               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
+                       " (hd %p, ioc %p, mf %p) \n", ioc->name, hd,
+                       ioc, mf));
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
+                        ioc->name));
+               retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
+                        ioc->name, retval));
                goto fail_out;
        }
 
@@ -1754,7 +1738,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i
        /*
         * Free task managment mf, and corresponding tm flags
         */
-       mpt_free_msg_frame(hd->ioc, mf);
+       mpt_free_msg_frame(ioc, mf);
        hd->tmPending = 0;
        hd->tmState = TM_STATE_NONE;
        return FAILED;
@@ -1797,11 +1781,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
+       if ((hd = shost_priv(SCpnt->device->host)) == NULL) {
                SCpnt->result = DID_RESET << 16;
                SCpnt->scsi_done(SCpnt);
-               printk(KERN_DEBUG MYNAM ": mptscsih_abort: Can't locate "
-                   "host! (sc=%p)\n", SCpnt);
+               printk(KERN_ERR MYNAM ": task abort: "
+                   "can't locate host! (sc=%p)\n", SCpnt);
                return FAILED;
        }
 
@@ -1812,8 +1796,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        vdevice = SCpnt->device->hostdata;
        if (!vdevice || !vdevice->vtarget) {
-               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: device has been "
-                   "deleted (sc=%p)\n", ioc->name, SCpnt));
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "task abort: device has been deleted (sc=%p)\n",
+                   ioc->name, SCpnt));
                SCpnt->result = DID_NO_CONNECT << 16;
                SCpnt->scsi_done(SCpnt);
                retval = 0;
@@ -1823,8 +1808,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        /* Task aborts are not supported for hidden raid components.
         */
        if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: hidden raid "
-                   "component (sc=%p)\n", ioc->name, SCpnt));
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "task abort: hidden raid component (sc=%p)\n",
+                   ioc->name, SCpnt));
                SCpnt->result = DID_RESET << 16;
                retval = FAILED;
                goto out;
@@ -1832,12 +1818,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
        /* Find this command
         */
-       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
+       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
                /* Cmd not found in ScsiLookup.
                 * Do OS callback.
                 */
                SCpnt->result = DID_RESET << 16;
-               dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: mptscsih_abort: "
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
                   "Command not in the active list! (sc=%p)\n", ioc->name,
                   SCpnt));
                retval = 0;
@@ -1859,7 +1845,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
         *       swap it here either.  It is an opaque cookie to
         *       the controller, so it does not matter. -DaveM
         */
-       mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
+       mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
        ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
 
        hd->abortSCpnt = SCpnt;
@@ -1868,7 +1854,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
            vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
            ctx2abort, mptscsih_get_tm_timeout(ioc));
 
-       if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+       if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
            SCpnt->serial_number == sn)
                retval = FAILED;
 
@@ -1901,9 +1887,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               printk(KERN_DEBUG MYNAM ": mptscsih_dev_reset: Can't "
-                   "locate host! (sc=%p)\n", SCpnt);
+       if ((hd = shost_priv(SCpnt->device->host)) == NULL){
+               printk(KERN_ERR MYNAM ": target reset: "
+                  "Can't locate host! (sc=%p)\n", SCpnt);
                return FAILED;
        }
 
@@ -1959,14 +1945,14 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
        int              retval;
-       VirtDevice       *vdev;
+       VirtDevice       *vdevice;
        MPT_ADAPTER     *ioc;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               printk(KERN_DEBUG MYNAM ": mptscsih_bus_reset: Can't "
-                   "locate host! (sc=%p)\n", SCpnt );
+       if ((hd = shost_priv(SCpnt->device->host)) == NULL){
+               printk(KERN_ERR MYNAM ": bus reset: "
+                  "Can't locate host! (sc=%p)\n", SCpnt);
                return FAILED;
        }
 
@@ -1978,9 +1964,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
        if (hd->timeouts < -1)
                hd->timeouts++;
 
-       vdev = SCpnt->device->hostdata;
+       vdevice = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-           vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
+           vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
 
        printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
            ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2008,9 +1994,9 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
        MPT_ADAPTER     *ioc;
 
        /*  If we can't locate the host to reset, then we failed. */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               printk( KERN_DEBUG MYNAM ": mptscsih_host_reset: Can't "
-                   "locate host! (sc=%p)\n", SCpnt);
+       if ((hd = shost_priv(SCpnt->device->host)) == NULL){
+               printk(KERN_ERR MYNAM ": host reset: "
+                   "Can't locate host! (sc=%p)\n", SCpnt);
                return FAILED;
        }
 
@@ -2021,7 +2007,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
        /*  If our attempts to reset the host failed, then return a failed
         *  status.  The host will be taken off line by the SCSI mid-layer.
         */
-       if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
+       if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) {
                retval = FAILED;
        } else {
                /*  Make sure TM pending is cleared and TM state is set to
@@ -2051,17 +2037,18 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
        unsigned long  flags;
        int            loop_count = 4 * 10;  /* Wait 10 seconds */
        int            status = FAILED;
+       MPT_ADAPTER     *ioc = hd->ioc;
 
        do {
-               spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+               spin_lock_irqsave(&ioc->FreeQlock, flags);
                if (hd->tmState == TM_STATE_NONE) {
                        hd->tmState = TM_STATE_IN_PROGRESS;
                        hd->tmPending = 1;
-                       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+                       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
                        status = SUCCESS;
                        break;
                }
-               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
                msleep(250);
        } while (--loop_count);
 
@@ -2082,15 +2069,16 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
        unsigned long  flags;
        int            loop_count = 4 * timeout;
        int            status = FAILED;
+       MPT_ADAPTER     *ioc = hd->ioc;
 
        do {
-               spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+               spin_lock_irqsave(&ioc->FreeQlock, flags);
                if(hd->tmPending == 0) {
                        status = SUCCESS;
-                       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+                       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
                        break;
                }
-               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
                msleep(250);
        } while (--loop_count);
 
@@ -2172,7 +2160,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                return 1;
        }
 
-       hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+       hd = shost_priv(ioc->sh);
        pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
        pScsiTmReq = (SCSITaskMgmt_t*)mf;
        tmType = pScsiTmReq->TaskType;
@@ -2223,7 +2211,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
                    hd->cmdPtr)
                        if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
-                               printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
+                               printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name);
                break;
 
        case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2366,7 +2354,7 @@ void
 mptscsih_slave_destroy(struct scsi_device *sdev)
 {
        struct Scsi_Host        *host = sdev->host;
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST           *hd = shost_priv(host);
        VirtTarget              *vtarget;
        VirtDevice              *vdevice;
        struct scsi_target      *starget;
@@ -2393,16 +2381,17 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
 int
 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+       MPT_SCSI_HOST           *hd = shost_priv(sdev->host);
        VirtTarget              *vtarget;
        struct scsi_target      *starget;
        int                     max_depth;
        int                     tagged;
+       MPT_ADAPTER             *ioc = hd->ioc;
 
        starget = scsi_target(sdev);
        vtarget = starget->hostdata;
 
-       if (hd->ioc->bus_type == SPI) {
+       if (ioc->bus_type == SPI) {
                if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
                        max_depth = 1;
                else if (sdev->type == TYPE_DISK &&
@@ -2437,19 +2426,20 @@ mptscsih_slave_configure(struct scsi_device *sdev)
        VirtTarget              *vtarget;
        VirtDevice              *vdevice;
        struct scsi_target      *starget;
-       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
+       MPT_SCSI_HOST           *hd = shost_priv(sh);
+       MPT_ADAPTER             *ioc = hd->ioc;
 
        starget = scsi_target(sdev);
        vtarget = starget->hostdata;
        vdevice = sdev->hostdata;
 
-       dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
+       dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                "device @ %p, channel=%d, id=%d, lun=%d\n",
-               hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
-       if (hd->ioc->bus_type == SPI)
-               dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
+               ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
+       if (ioc->bus_type == SPI)
+               dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "sdtr %d wdtr %d ppr %d inq length=%d\n",
-                   hd->ioc->name, sdev->sdtr, sdev->wdtr,
+                   ioc->name, sdev->sdtr, sdev->wdtr,
                    sdev->ppr, sdev->inquiry_len));
 
        if (sdev->id > sh->max_id) {
@@ -2461,21 +2451,21 @@ mptscsih_slave_configure(struct scsi_device *sdev)
        vdevice->configured_lun = 1;
        mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
-       dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
+       dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                "Queue depth=%d, tflags=%x\n",
-               hd->ioc->name, sdev->queue_depth, vtarget->tflags));
+               ioc->name, sdev->queue_depth, vtarget->tflags));
 
-       if (hd->ioc->bus_type == SPI)
-               dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
+       if (ioc->bus_type == SPI)
+               dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
-                   hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+                   ioc->name, vtarget->negoFlags, vtarget->maxOffset,
                    vtarget->minSyncFactor));
 
 slave_configure_exit:
 
-       dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
+       dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                "tagged %d, simple %d, ordered %d\n",
-               hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
+               ioc->name,sdev->tagged_supported, sdev->simple_tags,
                sdev->ordered_tags));
 
        return 0;
@@ -2494,14 +2484,15 @@ slave_configure_exit:
 static void
 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
 {
-       VirtDevice      *vdev;
+       VirtDevice      *vdevice;
        SCSIIORequest_t *pReq;
        u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
+       MPT_ADAPTER     *ioc = hd->ioc;
 
        /* Get target structure
         */
        pReq = (SCSIIORequest_t *) mf;
-       vdev = sc->device->hostdata;
+       vdevice = sc->device->hostdata;
 
        if (sense_count) {
                u8 *sense_data;
@@ -2509,15 +2500,14 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
 
                /* Copy the sense received into the scsi command block. */
                req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-               sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
+               sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
                memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
 
                /* Log SMART data (asc = 0x5D, non-IM case only) if required.
                 */
-               if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
-                       if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
+               if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
+                       if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
                                int idx;
-                               MPT_ADAPTER *ioc = hd->ioc;
 
                                idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
                                ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
@@ -2530,36 +2520,116 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
                                ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
 
                                ioc->eventContext++;
-                               if (hd->ioc->pcidev->vendor ==
+                               if (ioc->pcidev->vendor ==
                                    PCI_VENDOR_ID_IBM) {
-                                       mptscsih_issue_sep_command(hd->ioc,
-                                           vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
-                                       vdev->vtarget->tflags |=
+                                       mptscsih_issue_sep_command(ioc,
+                                           vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+                                       vdevice->vtarget->tflags |=
                                            MPT_TARGET_FLAGS_LED_ON;
                                }
                        }
                }
        } else {
-               dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
-                               hd->ioc->name));
+               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
+                               ioc->name));
        }
 }
 
-static int
-SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
+/**
+ * mptscsih_get_scsi_lookup
+ *
+ * retrieves scmd entry from ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @i: index into the array
+ *
+ * Returns the scsi_cmd pointer
+ *
+ **/
+static struct scsi_cmnd *
+mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
 {
-       MPT_SCSI_HOST *hd;
-       int i;
+       unsigned long   flags;
+       struct scsi_cmnd *scmd;
 
-       hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       scmd = ioc->ScsiLookup[i];
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+       return scmd;
+}
+
+/**
+ * mptscsih_getclear_scsi_lookup
+ *
+ * retrieves and clears scmd entry from ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @i: index into the array
+ *
+ * Returns the scsi_cmd pointer
+ *
+ **/
+static struct scsi_cmnd *
+mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
+{
+       unsigned long   flags;
+       struct scsi_cmnd *scmd;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       scmd = ioc->ScsiLookup[i];
+       ioc->ScsiLookup[i] = NULL;
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+       return scmd;
+}
 
-       for (i = 0; i < hd->ioc->req_depth; i++) {
-               if (hd->ScsiLookup[i] == sc) {
-                       return i;
+/**
+ * mptscsih_set_scsi_lookup
+ *
+ * writes a scmd entry into the ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @i: index into the array
+ * @scmd: scsi_cmnd pointer
+ *
+ **/
+static void
+mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
+{
+       unsigned long   flags;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       ioc->ScsiLookup[i] = scmd;
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+}
+
+/**
+ * SCPNT_TO_LOOKUP_IDX
+ *
+ * search's for a given scmd in the ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @scmd: scsi_cmnd pointer
+ *
+ **/
+static int
+SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
+{
+       unsigned long   flags;
+       int i, index=-1;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       for (i = 0; i < ioc->req_depth; i++) {
+               if (ioc->ScsiLookup[i] == sc) {
+                       index = i;
+                       goto out;
                }
        }
 
-       return -1;
+ out:
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return index;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2568,21 +2638,20 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
        MPT_SCSI_HOST   *hd;
        unsigned long    flags;
-       int             ii;
 
-       dtmprintk(ioc, printk(KERN_DEBUG MYNAM
-                       ": IOC %s_reset routed to SCSI host driver!\n",
-                       reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-                       reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+           ": IOC %s_reset routed to SCSI host driver!\n",
+           ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
+           reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 
        /* If a FW reload request arrives after base installed but
         * before all scsi hosts have been attached, then an alt_ioc
         * may have a NULL sh pointer.
         */
-       if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
+       if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
                return 0;
        else
-               hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+               hd = shost_priv(ioc->sh);
 
        if (reset_phase == MPT_IOC_SETUP_RESET) {
                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
@@ -2624,11 +2693,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                 * Init all control structures.
                 */
 
-               /* ScsiLookup initialization
-                */
-               for (ii=0; ii < hd->ioc->req_depth; ii++)
-                       hd->ScsiLookup[ii] = NULL;
-
                /* 2. Chain Buffer initialization
                 */
 
@@ -2675,7 +2739,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                        ioc->name, event));
 
        if (ioc->sh == NULL ||
-               ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+               ((hd = shost_priv(ioc->sh)) == NULL))
                return 1;
 
        switch (event) {
@@ -2713,7 +2777,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        case MPI_EVENT_STATE_CHANGE:                    /* 02 */
        case MPI_EVENT_EVENT_CHANGE:                    /* 0A */
        default:
-               dprintk(ioc, printk(KERN_DEBUG MYNAM ": Ignoring event (=%02Xh)\n", event));
+               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n",
+                   ioc->name, event));
                break;
        }
 
@@ -2753,7 +2818,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        int              completionCode;
        u16              req_idx;
 
-       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+       hd = shost_priv(ioc->sh);
 
        if ((mf == NULL) ||
            (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
@@ -2765,17 +2830,17 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
        del_timer(&hd->timer);
        req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-       hd->ScsiLookup[req_idx] = NULL;
+       mptscsih_set_scsi_lookup(ioc, req_idx, NULL);
        pReq = (SCSIIORequest_t *) mf;
 
        if (mf != hd->cmdPtr) {
                printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
-                               hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
+                               ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
        }
        hd->cmdPtr = NULL;
 
        ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
-                       hd->ioc->name, mf, mr, req_idx));
+                       ioc->name, mf, mr, req_idx));
 
        hd->pLocal = &hd->localReply;
        hd->pLocal->scsiStatus = 0;
@@ -2839,15 +2904,15 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                 */
                                completionCode = MPT_SCANDV_SENSE;
                                hd->pLocal->scsiStatus = scsi_status;
-                               sense_data = ((u8 *)hd->ioc->sense_buf_pool +
+                               sense_data = ((u8 *)ioc->sense_buf_pool +
                                        (req_idx * MPT_SENSE_BUFFER_ALLOC));
 
                                sz = min_t(int, pReq->SenseBufferLength,
                                                        SCSI_STD_SENSE_BYTES);
                                memcpy(hd->pLocal->sense, sense_data, sz);
 
-                               ddvprintk(ioc, printk(KERN_DEBUG "  Check Condition, sense ptr %p\n",
-                                               sense_data));
+                               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "  Check Condition, sense ptr %p\n",
+                                   ioc->name, sense_data));
                        } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
                                if (pReq->CDB[0] == INQUIRY)
                                        completionCode = MPT_SCANDV_ISSUE_SENSE;
@@ -2906,8 +2971,9 @@ void
 mptscsih_timer_expired(unsigned long data)
 {
        MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
+       MPT_ADAPTER     *ioc = hd->ioc;
 
-       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
+       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr));
 
        if (hd->cmdPtr) {
                MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
@@ -2921,13 +2987,13 @@ mptscsih_timer_expired(unsigned long data)
                         */
                } else {
                        /* Perform a FW reload */
-                       if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
-                               printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
+                       if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
+                               printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
                        }
                }
        } else {
                /* This should NEVER happen */
-               printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
+               printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name);
        }
 
        /* No more processing.
@@ -2935,7 +3001,7 @@ mptscsih_timer_expired(unsigned long data)
         * The FW will reply to all outstanding commands, callback will finish cleanup.
         * Hard reset clean-up will free all resources.
         */
-       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name));
+       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name));
 
        return;
 }
@@ -2973,11 +3039,12 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        char             cmdLen;
        char             CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        char             cmd = io->cmd;
+       MPT_ADAPTER     *ioc = hd->ioc;
 
        in_isr = in_interrupt();
        if (in_isr) {
-               dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
-                                       hd->ioc->name));
+               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
+                                       ioc->name));
                return -EPERM;
        }
 
@@ -3078,9 +3145,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
        /* Get and Populate a free Frame
         */
-       if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
-               ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "No msg frames!\n",
-                                       hd->ioc->name));
+       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
+               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n",
+                   ioc->name));
                return -EBUSY;
        }
 
@@ -3119,19 +3186,19 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
        if (cmd == REQUEST_SENSE) {
                pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
-               ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
-                       hd->ioc->name, cmd));
+               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
+                       ioc->name, cmd));
        }
 
        for (ii=0; ii < 16; ii++)
                pScsiReq->CDB[ii] = CDB[ii];
 
        pScsiReq->DataLength = cpu_to_le32(io->size);
-       pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
+       pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
                                           + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
-       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
-                       hd->ioc->name, cmd, io->channel, io->id, io->lun));
+       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
+                       ioc->name, cmd, io->channel, io->id, io->lun));
 
        if (dir == MPI_SCSIIO_CONTROL_READ) {
                mpt_add_sge((char *) &pScsiReq->SGL,
@@ -3166,7 +3233,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        hd->cmdPtr = mf;
 
        add_timer(&hd->timer);
-       mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+       mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
        wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
        if (hd->pLocal) {
@@ -3182,8 +3249,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        } else {
                rc = -EFAULT;
                /* This should never happen. */
-               ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
-                               hd->ioc->name));
+               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
+                               ioc->name));
        }
 
        return rc;
@@ -3235,7 +3302,7 @@ static ssize_t
 mptscsih_version_fw_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
@@ -3250,7 +3317,7 @@ static ssize_t
 mptscsih_version_bios_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
@@ -3265,7 +3332,7 @@ static ssize_t
 mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
@@ -3276,7 +3343,7 @@ static ssize_t
 mptscsih_version_product_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
@@ -3288,7 +3355,7 @@ static ssize_t
 mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%02xh\n",
@@ -3301,7 +3368,7 @@ static ssize_t
 mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
@@ -3313,7 +3380,7 @@ static ssize_t
 mptscsih_board_name_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
@@ -3324,7 +3391,7 @@ static ssize_t
 mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
@@ -3336,7 +3403,7 @@ static ssize_t
 mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
@@ -3348,7 +3415,7 @@ static ssize_t
 mptscsih_io_delay_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
@@ -3360,7 +3427,7 @@ static ssize_t
 mptscsih_device_delay_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
@@ -3372,7 +3439,7 @@ static ssize_t
 mptscsih_debug_level_show(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
 
        return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
@@ -3382,7 +3449,7 @@ mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
                                                                size_t count)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
-       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_SCSI_HOST   *hd = shost_priv(host);
        MPT_ADAPTER *ioc = hd->ioc;
        int val = 0;
 
index 67b088db2f109c2831afe3356108f23c4323f6b4..d289e97cfe8b2b781734454fee76ee8426ac3050 100644 (file)
@@ -3,9 +3,9 @@
  *      High performance SCSI / Fibre Channel SCSI Host device driver.
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
index 8c98420640a5eccaccaecfc3bff15f219a4e8707..25bcfcf36f2e365bbdebf0afc06b261ab2be8a36 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/message/fusion/mptspi.c
- *      For use with LSI Logic PCI chip/adapter(s)
- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *      For use with LSI PCI chip/adapter(s)
+ *      running LSI Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
@@ -90,9 +90,9 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *,
 
 static struct scsi_transport_template *mptspi_transport_template = NULL;
 
-static int     mptspiDoneCtx = -1;
-static int     mptspiTaskCtx = -1;
-static int     mptspiInternalCtx = -1; /* Used only for internal commands */
+static u8      mptspiDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8      mptspiTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8      mptspiInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
 
 /**
  *     mptspi_setTargetNegoParms  - Update the target negotiation parameters
@@ -107,7 +107,8 @@ static void
 mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
                            struct scsi_device *sdev)
 {
-       SpiCfgData *pspi_data = &hd->ioc->spi_data;
+       MPT_ADAPTER *ioc = hd->ioc;
+       SpiCfgData *pspi_data = &ioc->spi_data;
        int  id = (int) target->id;
        int  nvram;
        u8 width = MPT_NARROW;
@@ -138,9 +139,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
                                else {
                                        factor = MPT_ULTRA320;
                                        if (scsi_device_qas(sdev)) {
-                                               ddvprintk(hd->ioc,
-                                               printk(KERN_DEBUG "Enabling QAS due to "
-                                               "byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
+                                               ddvprintk(ioc,
+                                               printk(MYIOC_s_DEBUG_FMT "Enabling QAS due to "
+                                               "byte56=%02x on id=%d!\n", ioc->name,
+                                               scsi_device_qas(sdev), id));
                                                noQas = 0;
                                        }
                                        if (sdev->type == TYPE_TAPE &&
@@ -227,8 +229,8 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
                /* Disable QAS in a mixed configuration case
                 */
 
-               ddvprintk(hd->ioc, printk(KERN_DEBUG
-                       "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                       "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id));
        }
 }
 
@@ -302,7 +304,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
 
        ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
-                       ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
+               ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
 
        mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 
@@ -374,14 +376,15 @@ static int
 mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
 {
        int i, rc = 0;
+       MPT_ADAPTER *ioc = hd->ioc;
 
-       if (!hd->ioc->raid_data.pIocPg2)
+       if (!ioc->raid_data.pIocPg2)
                goto out;
 
-       if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
+       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
                goto out;
-       for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
-               if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
+       for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+               if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
                        rc = 1;
                        goto out;
                }
@@ -394,17 +397,19 @@ mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
 static int mptspi_target_alloc(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(shost);
        VirtTarget              *vtarget;
+       MPT_ADAPTER *ioc;
 
        if (hd == NULL)
                return -ENODEV;
 
+       ioc = hd->ioc;
        vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
        if (!vtarget)
                return -ENOMEM;
 
-       vtarget->ioc_id = hd->ioc->id;
+       vtarget->ioc_id = ioc->id;
        vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
        vtarget->id = (u8)starget->id;
        vtarget->channel = (u8)starget->channel;
@@ -412,34 +417,34 @@ static int mptspi_target_alloc(struct scsi_target *starget)
        starget->hostdata = vtarget;
 
        if (starget->channel == 1) {
-               if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
+               if (mptscsih_is_phys_disk(ioc, 0, starget->id) == 0)
                        return 0;
                vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
                /* The real channel for this device is zero */
                vtarget->channel = 0;
                /* The actual physdisknum (for RAID passthrough) */
-               vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
+               vtarget->id = mptscsih_raid_id_to_num(ioc, 0,
                    starget->id);
        }
 
        if (starget->channel == 0 &&
            mptspi_is_raid(hd, starget->id)) {
                vtarget->raidVolume = 1;
-               ddvprintk(hd->ioc, printk(KERN_DEBUG
-                   "RAID Volume @ channel=%d id=%d\n", starget->channel,
+               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "RAID Volume @ channel=%d id=%d\n", ioc->name, starget->channel,
                    starget->id));
        }
 
-       if (hd->ioc->spi_data.nvram &&
-           hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
-               u32 nvram = hd->ioc->spi_data.nvram[starget->id];
+       if (ioc->spi_data.nvram &&
+           ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
+               u32 nvram = ioc->spi_data.nvram[starget->id];
                spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
                spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
        } else {
-               spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
-               spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
+               spi_min_period(starget) = ioc->spi_data.minSyncFactor;
+               spi_max_width(starget) = ioc->spi_data.maxBusWidth;
        }
-       spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
+       spi_max_offset(starget) = ioc->spi_data.maxSyncOffset;
 
        spi_offset(starget) = 0;
        mptspi_write_width(starget, 0);
@@ -509,10 +514,10 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
                             struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(shost);
        struct _MPT_ADAPTER *ioc = hd->ioc;
-       struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
-       dma_addr_t pg0_dma;
+       struct _CONFIG_PAGE_SCSI_DEVICE_0 *spi_dev_pg0;
+       dma_addr_t spi_dev_pg0_dma;
        int size;
        struct _x_config_parms cfg;
        struct _CONFIG_PAGE_HEADER hdr;
@@ -530,9 +535,10 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
        size += 2048;
        */
 
-       pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
-       if (pg0 == NULL) {
-               starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
+       spi_dev_pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &spi_dev_pg0_dma, GFP_KERNEL);
+       if (spi_dev_pg0 == NULL) {
+               starget_printk(KERN_ERR, starget, MYIOC_s_FMT
+                   "dma_alloc_coherent for parameters failed\n", ioc->name);
                return -EINVAL;
        }
 
@@ -546,22 +552,22 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
        memset(&cfg, 0, sizeof(cfg));
 
        cfg.cfghdr.hdr = &hdr;
-       cfg.physAddr = pg0_dma;
+       cfg.physAddr = spi_dev_pg0_dma;
        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
        cfg.dir = 0;
        cfg.pageAddr = starget->id;
 
        if (mpt_config(ioc, &cfg)) {
-               starget_printk(KERN_ERR, starget, "mpt_config failed\n");
+               starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name);
                goto out_free;
        }
        err = 0;
-       memcpy(pass_pg0, pg0, size);
+       memcpy(pass_pg0, spi_dev_pg0, size);
 
-       mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters));
+       mptspi_print_read_nego(hd, starget, le32_to_cpu(spi_dev_pg0->NegotiatedParameters));
 
  out_free:
-       dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
+       dma_free_coherent(&ioc->pcidev->dev, size, spi_dev_pg0, spi_dev_pg0_dma);
        return err;
 }
 
@@ -588,11 +594,11 @@ static u32 mptspi_getRP(struct scsi_target *starget)
 static void mptspi_read_parameters(struct scsi_target *starget)
 {
        int nego;
-       struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
+       struct _CONFIG_PAGE_SCSI_DEVICE_0 spi_dev_pg0;
 
-       mptspi_read_spi_device_pg0(starget, &pg0);
+       mptspi_read_spi_device_pg0(starget, &spi_dev_pg0);
 
-       nego = le32_to_cpu(pg0.NegotiatedParameters);
+       nego = le32_to_cpu(spi_dev_pg0.NegotiatedParameters);
 
        spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
        spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
@@ -612,12 +618,13 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
 {
        MpiRaidActionRequest_t  *pReq;
        MPT_FRAME_HDR           *mf;
+       MPT_ADAPTER *ioc = hd->ioc;
 
        /* Get and Populate a free Frame
         */
-       if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
-               ddvprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
-                                       hd->ioc->name));
+       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
+               ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
+                                       ioc->name));
                return -EAGAIN;
        }
        pReq = (MpiRaidActionRequest_t *)mf;
@@ -638,8 +645,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
        mpt_add_sge((char *)&pReq->ActionDataSGE,
                MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
 
-       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
-                       hd->ioc->name, pReq->Action, channel, id));
+       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
+                       ioc->name, pReq->Action, channel, id));
 
        hd->pLocal = NULL;
        hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
@@ -651,7 +658,7 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
        hd->cmdPtr = mf;
 
        add_timer(&hd->timer);
-       mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+       mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
        wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
        if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
@@ -664,6 +671,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
                             struct scsi_device *sdev)
 {
        VirtTarget *vtarget = scsi_target(sdev)->hostdata;
+       MPT_ADAPTER *ioc = hd->ioc;
 
        /* no DV on RAID devices */
        if (sdev->channel == 0 &&
@@ -673,8 +681,8 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
        /* If this is a piece of a RAID, then quiesce first */
        if (sdev->channel == 1 &&
            mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
-               starget_printk(KERN_ERR, scsi_target(sdev),
-                              "Integrated RAID quiesce failed\n");
+               starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT
+                   "Integrated RAID quiesce failed\n", ioc->name);
                return;
        }
 
@@ -684,8 +692,8 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
 
        if (sdev->channel == 1 &&
            mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
-               starget_printk(KERN_ERR, scsi_target(sdev),
-                              "Integrated RAID resume failed\n");
+               starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT
+                   "Integrated RAID resume failed\n", ioc->name);
 
        mptspi_read_parameters(sdev->sdev_target);
        spi_display_xfer_agreement(sdev->sdev_target);
@@ -694,28 +702,29 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
 
 static int mptspi_slave_alloc(struct scsi_device *sdev)
 {
-       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+       MPT_SCSI_HOST *hd = shost_priv(sdev->host);
        VirtTarget              *vtarget;
-       VirtDevice              *vdev;
+       VirtDevice              *vdevice;
        struct scsi_target      *starget;
+       MPT_ADAPTER *ioc = hd->ioc;
 
        if (sdev->channel == 1 &&
-               mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
+               mptscsih_is_phys_disk(ioc, 0, sdev->id) == 0)
                        return -ENXIO;
 
-       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
-       if (!vdev) {
+       vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!vdevice) {
                printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
-                               hd->ioc->name, sizeof(VirtDevice));
+                               ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
 
-       vdev->lun = sdev->lun;
-       sdev->hostdata = vdev;
+       vdevice->lun = sdev->lun;
+       sdev->hostdata = vdevice;
 
        starget = scsi_target(sdev);
        vtarget = starget->hostdata;
-       vdev->vtarget = vtarget;
+       vdevice->vtarget = vtarget;
        vtarget->num_luns++;
 
        if (sdev->channel == 1)
@@ -726,8 +735,7 @@ static int mptspi_slave_alloc(struct scsi_device *sdev)
 
 static int mptspi_slave_configure(struct scsi_device *sdev)
 {
-       struct _MPT_SCSI_HOST *hd =
-               (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(sdev->host);
        VirtTarget *vtarget = scsi_target(sdev)->hostdata;
        int ret;
 
@@ -755,24 +763,25 @@ static int mptspi_slave_configure(struct scsi_device *sdev)
 static int
 mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
-       struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
-       VirtDevice      *vdev = SCpnt->device->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host);
+       VirtDevice      *vdevice = SCpnt->device->hostdata;
+       MPT_ADAPTER *ioc = hd->ioc;
 
-       if (!vdev || !vdev->vtarget) {
+       if (!vdevice || !vdevice->vtarget) {
                SCpnt->result = DID_NO_CONNECT << 16;
                done(SCpnt);
                return 0;
        }
 
        if (SCpnt->device->channel == 1 &&
-               mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
+               mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) {
                SCpnt->result = DID_NO_CONNECT << 16;
                done(SCpnt);
                return 0;
        }
 
        if (spi_dv_pending(scsi_target(SCpnt->device)))
-               ddvprintk(hd->ioc, scsi_print_command(SCpnt));
+               ddvprintk(ioc, scsi_print_command(SCpnt));
 
        return mptscsih_qcmd(SCpnt,done);
 }
@@ -829,7 +838,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
                               struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(shost);
        struct _MPT_ADAPTER *ioc = hd->ioc;
        struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
        dma_addr_t pg1_dma;
@@ -847,7 +856,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
 
        pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
        if (pg1 == NULL) {
-               starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
+               starget_printk(KERN_ERR, starget, MYIOC_s_FMT
+                   "dma_alloc_coherent for parameters failed\n", ioc->name);
                return -EINVAL;
        }
 
@@ -876,7 +886,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
        mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
 
        if (mpt_config(ioc, &cfg)) {
-               starget_printk(KERN_ERR, starget, "mpt_config failed\n");
+               starget_printk(KERN_ERR, starget, MYIOC_s_FMT
+                   "mpt_config failed\n", ioc->name);
                goto out_free;
        }
        err = 0;
@@ -1015,7 +1026,7 @@ static void mptspi_write_qas(struct scsi_target *starget, int qas)
 {
        struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(shost);
        VirtTarget *vtarget = starget->hostdata;
        u32 nego;
 
@@ -1067,15 +1078,16 @@ static void mpt_work_wrapper(struct work_struct *work)
        struct work_queue_wrapper *wqw =
                container_of(work, struct work_queue_wrapper, work);
        struct _MPT_SCSI_HOST *hd = wqw->hd;
-       struct Scsi_Host *shost = hd->ioc->sh;
+       MPT_ADAPTER *ioc = hd->ioc;
+       struct Scsi_Host *shost = ioc->sh;
        struct scsi_device *sdev;
        int disk = wqw->disk;
        struct _CONFIG_PAGE_IOC_3 *pg3;
 
        kfree(wqw);
 
-       mpt_findImVolumes(hd->ioc);
-       pg3 = hd->ioc->raid_data.pIocPg3;
+       mpt_findImVolumes(ioc);
+       pg3 = ioc->raid_data.pIocPg3;
        if (!pg3)
                return;
 
@@ -1092,24 +1104,25 @@ static void mpt_work_wrapper(struct work_struct *work)
                if(vtarget->id != disk)
                        continue;
 
-               starget_printk(KERN_INFO, vtarget->starget,
-                              "Integrated RAID requests DV of new device\n");
+               starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT
+                   "Integrated RAID requests DV of new device\n", ioc->name);
                mptspi_dv_device(hd, sdev);
        }
-       shost_printk(KERN_INFO, shost,
-                    "Integrated RAID detects new device %d\n", disk);
-       scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
+       shost_printk(KERN_INFO, shost, MYIOC_s_FMT
+           "Integrated RAID detects new device %d\n", ioc->name, disk);
+       scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1);
 }
 
 
 static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
 {
        struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+       MPT_ADAPTER *ioc = hd->ioc;
 
        if (!wqw) {
-               shost_printk(KERN_ERR, hd->ioc->sh,
-                            "Failed to act on RAID event for physical disk %d\n",
-                          disk);
+               shost_printk(KERN_ERR, ioc->sh, MYIOC_s_FMT
+                   "Failed to act on RAID event for physical disk %d\n",
+                   ioc->name, disk);
                return;
        }
        INIT_WORK(&wqw->work, mpt_work_wrapper);
@@ -1123,7 +1136,7 @@ static int
 mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
 
        if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {
                int reason
@@ -1190,6 +1203,8 @@ static struct spi_function_template mptspi_transport_functions = {
 static struct pci_device_id mptspi_pci_table[] = {
        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
                PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_ATTO, MPI_MANUFACTPAGE_DEVID_53C1030,
+               PCI_ANY_ID, PCI_ANY_ID },
        { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
                PCI_ANY_ID, PCI_ANY_ID },
        {0}     /* Terminating entry */
@@ -1210,11 +1225,12 @@ mptspi_dv_renegotiate_work(struct work_struct *work)
        struct scsi_target *starget;
        struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
        u32 nego;
+       MPT_ADAPTER *ioc = hd->ioc;
 
        kfree(wqw);
 
        if (hd->spi_pending) {
-               shost_for_each_device(sdev, hd->ioc->sh) {
+               shost_for_each_device(sdev, ioc->sh) {
                        if  (hd->spi_pending & (1 << sdev->id))
                                continue;
                        starget = scsi_target(sdev);
@@ -1225,7 +1241,7 @@ mptspi_dv_renegotiate_work(struct work_struct *work)
                        mptspi_write_spi_device_pg1(starget, &pg1);
                }
        } else {
-               shost_for_each_device(sdev, hd->ioc->sh)
+               shost_for_each_device(sdev, ioc->sh)
                        mptspi_dv_device(hd, sdev);
        }
 }
@@ -1250,7 +1266,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
 static int
 mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
        int rc;
 
        rc = mptscsih_ioc_reset(ioc, reset_phase);
@@ -1269,7 +1285,7 @@ static int
 mptspi_resume(struct pci_dev *pdev)
 {
        MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
-       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+       struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
        int rc;
 
        rc = mptscsih_resume(pdev);
@@ -1416,7 +1432,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        if (numSGE < sh->sg_tablesize) {
                /* Reset this value */
-               dprintk(ioc, printk(MYIOC_s_INFO_FMT
+               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                  "Resetting sg_tablesize to %d from %d\n",
                  ioc->name, numSGE, sh->sg_tablesize));
                sh->sg_tablesize = numSGE;
@@ -1424,20 +1440,21 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
-       hd = (MPT_SCSI_HOST *) sh->hostdata;
+       hd = shost_priv(sh);
        hd->ioc = ioc;
 
        /* SCSI needs scsi_cmnd lookup table!
         * (with size equal to req_depth*PtrSz!)
         */
-       hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
-       if (!hd->ScsiLookup) {
+       ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+       if (!ioc->ScsiLookup) {
                error = -ENOMEM;
                goto out_mptspi_probe;
        }
+       spin_lock_init(&ioc->scsi_lookup_lock);
 
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
-                ioc->name, hd->ScsiLookup));
+                ioc->name, ioc->ScsiLookup));
 
        /* Clear the TM flags
         */
@@ -1477,13 +1494,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* Some versions of the firmware don't support page 0; without
         * that we can't get the parameters */
-       if (hd->ioc->spi_data.sdp0length != 0)
+       if (ioc->spi_data.sdp0length != 0)
                sh->transportt = mptspi_transport_template;
 
        error = scsi_add_host (sh, &ioc->pcidev->dev);
        if(error) {
-               dprintk(ioc, printk(KERN_ERR MYNAM
-                 "scsi_add_host failed\n"));
+               dprintk(ioc, printk(MYIOC_s_ERR_FMT
+                 "scsi_add_host failed\n", ioc->name));
                goto out_mptspi_probe;
        }
 
index 90aa53fc4f3e40cfb4fadee0e7f72e176ec45265..7507067351bd83b0ff00b20d890ae7a4671a5ed2 100644 (file)
@@ -891,7 +891,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit)
 /*
  * Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI
  * commands.
- * It also genrates fcp-nameserver request/response buffer and unsolicited 
+ * It also genrates fcp-nameserver request/response buffer and unsolicited
  * status read fsf_req buffers.
  *
  * locks:       must only be called with zfcp_data.config_sema taken
@@ -982,7 +982,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        struct zfcp_adapter *adapter;
 
        /*
-        * Note: It is safe to release the list_lock, as any list changes 
+        * Note: It is safe to release the list_lock, as any list changes
         * are protected by the config_sema, which must be held to get here
         */
 
@@ -1038,6 +1038,10 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        spin_lock_init(&adapter->san_dbf_lock);
        spin_lock_init(&adapter->scsi_dbf_lock);
 
+       retval = zfcp_adapter_debug_register(adapter);
+       if (retval)
+               goto debug_register_failed;
+
        /* initialize error recovery stuff */
 
        rwlock_init(&adapter->erp_lock);
@@ -1058,7 +1062,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        /* mark adapter unusable as long as sysfs registration is not complete */
        atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
 
-       adapter->ccw_device = ccw_device;
        dev_set_drvdata(&ccw_device->dev, adapter);
 
        if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
@@ -1085,6 +1088,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
  generic_services_failed:
        zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
  sysfs_failed:
+       zfcp_adapter_debug_unregister(adapter);
+ debug_register_failed:
        dev_set_drvdata(&ccw_device->dev, NULL);
        zfcp_reqlist_free(adapter);
  failed_low_mem_buffers:
@@ -1130,6 +1135,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
                goto out;
        }
 
+       zfcp_adapter_debug_unregister(adapter);
+
        /* remove specified adapter data structure from list */
        write_lock_irq(&zfcp_data.config_lock);
        list_del(&adapter->list);
index c0d1c0eb32099f225a8d972cc164d1a19d3ae25b..e01cbf152a81d3622a5d4a607b103ab472e607d0 100644 (file)
@@ -148,15 +148,12 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
        down(&zfcp_data.config_sema);
        adapter = dev_get_drvdata(&ccw_device->dev);
 
-       retval = zfcp_adapter_debug_register(adapter);
-       if (retval)
-               goto out;
        retval = zfcp_erp_thread_setup(adapter);
        if (retval) {
                ZFCP_LOG_INFO("error: start of error recovery thread for "
                              "adapter %s failed\n",
                              zfcp_get_busid_by_adapter(adapter));
-               goto out_erp_thread;
+               goto out;
        }
 
        retval = zfcp_adapter_scsi_register(adapter);
@@ -175,8 +172,6 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
 
  out_scsi_register:
        zfcp_erp_thread_kill(adapter);
- out_erp_thread:
-       zfcp_adapter_debug_unregister(adapter);
  out:
        up(&zfcp_data.config_sema);
        return retval;
@@ -199,7 +194,6 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
        zfcp_erp_adapter_shutdown(adapter, 0);
        zfcp_erp_wait(adapter);
        zfcp_erp_thread_kill(adapter);
-       zfcp_adapter_debug_unregister(adapter);
        up(&zfcp_data.config_sema);
        return 0;
 }
index b36dfc40d9fa26b41ee3aca598eabe3a9c999bd0..16e5563e0c651959aad3bd4e7cf7c90aacf0bfaf 100644 (file)
@@ -1,23 +1,23 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  *
  * (C) Copyright IBM Corp. 2002, 2006
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License as published by 
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version. 
- * 
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- */ 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 #ifndef ZFCP_DEF_H
 #define ZFCP_DEF_H
@@ -90,7 +90,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list)
 #define ZFCP_DEVICE_TYPE        0x1732
 #define ZFCP_DEVICE_MODEL       0x03
 #define ZFCP_DEVICE_MODEL_PRIV 0x04
+
 /* allow as many chained SBALs as are supported by hardware */
 #define ZFCP_MAX_SBALS_PER_REQ         FSF_MAX_SBALS_PER_REQ
 #define ZFCP_MAX_SBALS_PER_CT_REQ      FSF_MAX_SBALS_PER_REQ
@@ -508,7 +508,7 @@ struct zfcp_rc_entry {
 
 /*
  * this allows removal of logging code by the preprocessor
- * (the most detailed log level still to be compiled in is specified, 
+ * (the most detailed log level still to be compiled in is specified,
  * higher log levels are removed)
  */
 #define ZFCP_LOG_LEVEL_LIMIT   ZFCP_LOG_LEVEL_TRACE
@@ -546,7 +546,7 @@ do { \
        if (ZFCP_LOG_CHECK(level)) \
                _ZFCP_LOG(fmt, ##args); \
 } while (0)
-       
+
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
 # define ZFCP_LOG_NORMAL(fmt, args...) do { } while (0)
 #else
@@ -583,8 +583,8 @@ do { \
 
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
 
-/* 
- * Note, the leftmost status byte is common among adapter, port 
+/*
+ * Note, the leftmost status byte is common among adapter, port
  * and unit
  */
 #define ZFCP_COMMON_FLAGS                      0xfff00000
@@ -1007,8 +1007,8 @@ struct zfcp_fsf_req {
        u32                    fsf_command;    /* FSF Command copy */
        struct fsf_qtcb        *qtcb;          /* address of associated QTCB */
        u32                    seq_no;         /* Sequence number of request */
-        unsigned long          data;           /* private data of request */ 
-       struct timer_list      timer;          /* used for erp or scsi er */
+       unsigned long          data;           /* private data of request */
+       struct timer_list     timer;           /* used for erp or scsi er */
        struct zfcp_erp_action *erp_action;    /* used if this request is
                                                  issued on behalf of erp */
        mempool_t              *pool;          /* used if request was alloacted
index 16b4418ab257460069342c8518fa3d6fc6ed438d..a6475a2bb8a7df713343ce615a1c10ec2442fc11 100644 (file)
@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  *
  * (C) Copyright IBM Corp. 2002, 2006
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License as published by 
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version. 
- * 
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_ERP
@@ -191,7 +191,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    called if an adapter failed,
  *             initiates adapter recovery which is done
@@ -228,7 +228,7 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    Wrappper for zfcp_erp_adapter_reopen_internal
  *              used to ensure the correct locking
@@ -476,7 +476,7 @@ zfcp_test_link(struct zfcp_port *port)
 
 
 /*
- * function:   
+ * function:
  *
  * purpose:    called if a port failed to be opened normally
  *             initiates Forced Reopen recovery which is done
@@ -517,7 +517,7 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    Wrappper for zfcp_erp_port_forced_reopen_internal
  *              used to ensure the correct locking
@@ -543,7 +543,7 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    called if a port is to be opened
  *             initiates Reopen recovery which is done
@@ -612,7 +612,7 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    called if a unit is to be opened
  *             initiates Reopen recovery which is done
@@ -704,7 +704,7 @@ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    disable I/O,
  *             return any open requests and clean them up,
@@ -725,7 +725,7 @@ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    enable I/O
  *
@@ -742,7 +742,7 @@ zfcp_erp_port_unblock(struct zfcp_port *port)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    disable I/O,
  *             return any open requests and clean them up,
@@ -763,7 +763,7 @@ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    enable I/O
  *
@@ -792,7 +792,7 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:
  *
@@ -967,7 +967,7 @@ static void zfcp_erp_timeout_handler(unsigned long data)
  * zfcp_erp_action_dismiss - dismiss an erp_action
  *
  * adapter->erp_lock must be held
- * 
+ *
  * Dismissal of an erp_action is usually required if an erp_action of
  * higher priority is generated.
  */
@@ -1005,9 +1005,9 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:
  *
@@ -1094,7 +1094,7 @@ zfcp_erp_thread(void *data)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    drives single error recovery action and schedules higher and
  *             subordinate actions, if necessary
@@ -1206,7 +1206,7 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
 
        /*
         * put this target through the erp mill again if someone has
-        * requested to change the status of a target being online 
+        * requested to change the status of a target being online
         * to offline or the other way around
         * (old retval is preserved if nothing has to be done here)
         */
@@ -1228,7 +1228,7 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
  unlock:
        write_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
-       
+
        if (retval != ZFCP_ERP_CONTINUES)
                zfcp_erp_action_cleanup(action, adapter, port, unit, retval);
 
@@ -1250,9 +1250,9 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_DISMISSED      - if action has been dismissed
  *             retval                  - otherwise
@@ -1322,7 +1322,7 @@ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    triggers retry of this action after a certain amount of time
  *             by means of timer provided by erp_action
@@ -1346,7 +1346,7 @@ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
        return retval;
 }
 
-/* 
+/*
  * function:    zfcp_erp_adapter_failed
  *
  * purpose:     sets the adapter and all underlying devices to ERP_FAILED
@@ -1362,7 +1362,7 @@ zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
        debug_text_event(adapter->erp_dbf, 2, "a_afail");
 }
 
-/* 
+/*
  * function:    zfcp_erp_port_failed
  *
  * purpose:     sets the port and all underlying devices to ERP_FAILED
@@ -1386,7 +1386,7 @@ zfcp_erp_port_failed(struct zfcp_port *port)
        debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t));
 }
 
-/* 
+/*
  * function:    zfcp_erp_unit_failed
  *
  * purpose:     sets the unit to ERP_FAILED
@@ -1417,7 +1417,7 @@ zfcp_erp_unit_failed(struct zfcp_unit *unit)
  *              successfully is reset.
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (not considered)
- *             ZFCP_ERP_SUCCEEDED      - action finished successfully 
+ *             ZFCP_ERP_SUCCEEDED      - action finished successfully
  *             ZFCP_ERP_EXIT           - action failed and will not continue
  */
 static int
@@ -1646,7 +1646,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    remaining things in good cases,
  *             escalation in bad cases
@@ -1687,8 +1687,8 @@ zfcp_erp_strategy_followup_actions(int action,
                break;
 
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
-               if (status == ZFCP_ERP_SUCCEEDED) ;     /* no further action */
-               else
+               /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */
+               if (status != ZFCP_ERP_SUCCEEDED)
                        zfcp_erp_port_reopen_internal(unit->port, 0);
                break;
        }
@@ -1815,7 +1815,7 @@ zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    Wrappper for zfcp_erp_port_reopen_all_internal
  *              used to ensure the correct locking
@@ -1852,9 +1852,9 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    FIXME
  */
@@ -1871,7 +1871,7 @@ zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    this routine executes the 'Reopen Adapter' action
  *             (the entire action is processed synchronously, since
@@ -1908,9 +1908,9 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_SUCCEEDED      - action finished successfully
  *              ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -1930,9 +1930,9 @@ zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_SUCCEEDED      - action finished successfully
  *              ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -1957,7 +1957,7 @@ zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action)
  * purpose:    allocate the irq associated with this devno and register
  *             the FSF adapter with the SCSI stack
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
@@ -2197,7 +2197,7 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
        zfcp_erp_action_to_running(erp_action);
        write_unlock_irq(&adapter->erp_lock);
 
-       ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+       ret = zfcp_fsf_exchange_port_data(erp_action);
        if (ret == -EOPNOTSUPP) {
                debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
                return ZFCP_ERP_SUCCEEDED;
@@ -2249,7 +2249,7 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    this routine executes the 'Reopen Physical Port' action
  *
@@ -2308,7 +2308,7 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    this routine executes the 'Reopen Port' action
  *
@@ -2530,7 +2530,7 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    makes the erp thread continue with reopen (physical) port
  *             actions which have been paused until the name server port
@@ -2570,9 +2570,9 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (asynchronously)
  *             ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -2626,9 +2626,9 @@ zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (asynchronously)
  *             ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -2663,9 +2663,9 @@ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (asynchronously)
  *             ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -2700,9 +2700,9 @@ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (asynchronously)
  *             ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -2737,7 +2737,7 @@ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    this routine executes the 'Reopen Unit' action
  *             currently no retries
@@ -2825,9 +2825,9 @@ zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (asynchronously)
  *             ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -2865,9 +2865,9 @@ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
 }
 
 /*
- * function:   
+ * function:
  *
- * purpose:    
+ * purpose:
  *
  * returns:    ZFCP_ERP_CONTINUES      - action continues (asynchronously)
  *             ZFCP_ERP_FAILED         - action finished unsuccessfully
@@ -2913,7 +2913,7 @@ void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
 }
 
 /*
- * function:   
+ * function:
  *
  * purpose:    enqueue the specified error recovery action, if needed
  *
@@ -2992,7 +2992,7 @@ zfcp_erp_action_enqueue(int action,
                                              port->erp_action.action);
                                debug_text_event(adapter->erp_dbf, 4,
                                                 "pf_actenq_drp");
-                       } else 
+                       } else
                                debug_text_event(adapter->erp_dbf, 4,
                                                 "pf_actenq_drpcp");
                        debug_event(adapter->erp_dbf, 4, &port->wwpn,
index 991d45667a44d0453f06d0134d1345a8a5509d2a..8534cf09546c3c120a6b23d4a1a8ebd76a6b7894 100644 (file)
@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  *
  * (C) Copyright IBM Corp. 2002, 2006
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License as published by 
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version. 
- * 
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #ifndef ZFCP_EXT_H
@@ -82,9 +82,11 @@ extern int  zfcp_fsf_open_unit(struct zfcp_erp_action *);
 extern int  zfcp_fsf_close_unit(struct zfcp_erp_action *);
 
 extern int  zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
-extern int  zfcp_fsf_exchange_port_data(struct zfcp_erp_action *,
-                                       struct zfcp_adapter *,
-                                       struct fsf_qtcb_bottom_port *);
+extern int  zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *,
+                                              struct fsf_qtcb_bottom_config *);
+extern int  zfcp_fsf_exchange_port_data(struct zfcp_erp_action *);
+extern int  zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *,
+                                             struct fsf_qtcb_bottom_port *);
 extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
                                  u32, u32, struct zfcp_sg_list *);
 extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
index 99299976e89195288a32768147325b4958e99aea..ff866ebd44ac1ae2771d62b346d485489c2473e5 100644 (file)
@@ -80,10 +80,10 @@ static const char zfcp_act_subtable_type[5][8] = {
 /*
  * function:   zfcp_fsf_req_alloc
  *
- * purpose:     Obtains an fsf_req and potentially a qtcb (for all but 
+ * purpose:     Obtains an fsf_req and potentially a qtcb (for all but
  *              unsolicited requests) via helper functions
  *              Does some initial fsf request set-up.
- *              
+ *
  * returns:    pointer to allocated fsf_req if successfull
  *              NULL otherwise
  *
@@ -192,7 +192,7 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
  * returns:    0 - success
  *             !0 - failure
  *
- * context:    
+ * context:
  */
 int
 zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
@@ -214,8 +214,8 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
        }
 
        /*
-        * fsf_req may be deleted due to waking up functions, so 
-        * cleanup is saved here and used later 
+        * fsf_req may be deleted due to waking up functions, so
+        * cleanup is saved here and used later
         */
        if (likely(fsf_req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
                cleanup = 1;
@@ -259,9 +259,9 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
  *             and initiates appropriate actions
  *             (usually calling FSF command specific handlers)
  *
- * returns:    
+ * returns:
  *
- * context:    
+ * context:
  *
  * locks:
  */
@@ -638,7 +638,7 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
  *
  * purpose:    calls the appropriate command specific handler
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
@@ -854,7 +854,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
  *
  * purpose:    is called for finished Open Port command
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
@@ -1088,7 +1088,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
  * returns:    address of initiated FSF request
  *             NULL - request could not be initiated
  *
- * FIXME(design): should be watched by a timeout !!! 
+ * FIXME(design): should be watched by a timeout !!!
  * FIXME(design) shouldn't this be modified to return an int
  *               also...don't know how though
  */
@@ -1157,7 +1157,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
  *
  * purpose:    is called for finished Abort FCP Command request
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
@@ -1941,25 +1941,28 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 {
        volatile struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *fsf_req;
+       struct zfcp_adapter *adapter = erp_action->adapter;
        unsigned long lock_flags;
-       int retval = 0;
+       int retval;
 
        /* setup new FSF request */
-       retval = zfcp_fsf_req_create(erp_action->adapter,
+       retval = zfcp_fsf_req_create(adapter,
                                     FSF_QTCB_EXCHANGE_CONFIG_DATA,
                                     ZFCP_REQ_AUTO_CLEANUP,
-                                    erp_action->adapter->pool.fsf_req_erp,
+                                    adapter->pool.fsf_req_erp,
                                     &lock_flags, &fsf_req);
-       if (retval < 0) {
+       if (retval) {
                ZFCP_LOG_INFO("error: Could not create exchange configuration "
                              "data request for adapter %s.\n",
-                             zfcp_get_busid_by_adapter(erp_action->adapter));
-               goto out;
+                             zfcp_get_busid_by_adapter(adapter));
+               write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+                                       lock_flags);
+               return retval;
        }
 
        sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
-        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
        fsf_req->qtcb->bottom.config.feature_selection =
                        FSF_FEATURE_CFDC |
@@ -1971,23 +1974,71 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 
        zfcp_erp_start_timer(fsf_req);
        retval = zfcp_fsf_req_send(fsf_req);
+       write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+                               lock_flags);
        if (retval) {
-               ZFCP_LOG_INFO
-                   ("error: Could not send exchange configuration data "
-                    "command on the adapter %s\n",
-                    zfcp_get_busid_by_adapter(erp_action->adapter));
+               ZFCP_LOG_INFO("error: Could not send exchange configuration "
+                             "data command on the adapter %s\n",
+                             zfcp_get_busid_by_adapter(adapter));
                zfcp_fsf_req_free(fsf_req);
                erp_action->fsf_req = NULL;
-               goto out;
        }
+       else
+               ZFCP_LOG_DEBUG("exchange configuration data request initiated "
+                              "(adapter %s)\n",
+                              zfcp_get_busid_by_adapter(adapter));
 
-       ZFCP_LOG_DEBUG("exchange configuration data request initiated "
-                      "(adapter %s)\n",
-                      zfcp_get_busid_by_adapter(erp_action->adapter));
+       return retval;
+}
 
- out:
-       write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock,
+int
+zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
+                               struct fsf_qtcb_bottom_config *data)
+{
+       volatile struct qdio_buffer_element *sbale;
+       struct zfcp_fsf_req *fsf_req;
+       unsigned long lock_flags;
+       int retval;
+
+       /* setup new FSF request */
+       retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
+                                    0, NULL, &lock_flags, &fsf_req);
+       if (retval) {
+               ZFCP_LOG_INFO("error: Could not create exchange configuration "
+                             "data request for adapter %s.\n",
+                             zfcp_get_busid_by_adapter(adapter));
+               write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+                                       lock_flags);
+               return retval;
+       }
+
+       sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+       fsf_req->qtcb->bottom.config.feature_selection =
+                       FSF_FEATURE_CFDC |
+                       FSF_FEATURE_LUN_SHARING |
+                       FSF_FEATURE_NOTIFICATION_LOST |
+                       FSF_FEATURE_UPDATE_ALERT;
+
+       if (data)
+               fsf_req->data = (unsigned long) data;
+
+       zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+       retval = zfcp_fsf_req_send(fsf_req);
+       write_unlock_irqrestore(&adapter->request_queue.queue_lock,
                                lock_flags);
+       if (retval)
+               ZFCP_LOG_INFO("error: Could not send exchange configuration "
+                             "data command on the adapter %s\n",
+                             zfcp_get_busid_by_adapter(adapter));
+       else
+               wait_event(fsf_req->completion_wq,
+                          fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+
+       zfcp_fsf_req_free(fsf_req);
+
        return retval;
 }
 
@@ -2016,11 +2067,17 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
        adapter->peer_d_id = 0;
 
        if (xchg_ok) {
+
+               if (fsf_req->data)
+                       memcpy((struct fsf_qtcb_bottom_config *) fsf_req->data,
+                               bottom, sizeof (struct fsf_qtcb_bottom_config));
+
                fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
                fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
                fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
                fc_host_speed(shost) = bottom->fc_link_speed;
-               fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
+               fc_host_supported_classes(shost) =
+                               FC_COS_CLASS2 | FC_COS_CLASS3;
                adapter->hydra_version = bottom->adapter_type;
                if (fc_host_permanent_port_name(shost) == -1)
                        fc_host_permanent_port_name(shost) =
@@ -2053,7 +2110,8 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                       min(FC_SERIAL_NUMBER_SIZE, 17));
        }
 
-       ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n"
+       ZFCP_LOG_NORMAL("The adapter %s reported the following "
+                       "characteristics:\n"
                        "WWNN 0x%016Lx, "
                        "WWPN 0x%016Lx, "
                        "S_ID 0x%06x,\n"
@@ -2090,7 +2148,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
        return 0;
 }
 
-/*
+/**
  * function:    zfcp_fsf_exchange_config_data_handler
  *
  * purpose:     is called for finished Exchange Configuration Data command
@@ -2125,7 +2183,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                                        adapter->peer_wwpn,
                                        adapter->peer_d_id);
                        debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "top-p-to-p");
+                                       "top-p-to-p");
                        break;
                case FC_PORTTYPE_NLPORT:
                        ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
@@ -2138,8 +2196,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                        return -EIO;
                case FC_PORTTYPE_NPORT:
                        ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
-                                     "network detected at adapter %s.\n",
-                                     zfcp_get_busid_by_adapter(adapter));
+                                       "network detected at adapter %s.\n",
+                                       zfcp_get_busid_by_adapter(adapter));
                        break;
                default:
                        ZFCP_LOG_NORMAL("bug: The fibrechannel topology "
@@ -2179,7 +2237,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
                        return -EIO;
 
-               atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
+               atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+                               &adapter->status);
 
                zfcp_fsf_link_down_info_eval(adapter,
                        &qtcb->header.fsf_status_qual.link_down_info);
@@ -2187,7 +2246,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
        default:
                debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
                debug_event(fsf_req->adapter->erp_dbf, 0,
-                           &fsf_req->qtcb->header.fsf_status, sizeof (u32));
+                           &fsf_req->qtcb->header.fsf_status, sizeof(u32));
                zfcp_erp_adapter_shutdown(adapter, 0);
                return -EIO;
        }
@@ -2197,74 +2256,118 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
 /**
  * zfcp_fsf_exchange_port_data - request information about local port
  * @erp_action: ERP action for the adapter for which port data is requested
- * @adapter: for which port data is requested
- * @data: response to exchange port data request
  */
 int
-zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
-                           struct zfcp_adapter *adapter,
-                           struct fsf_qtcb_bottom_port *data)
+zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
 {
        volatile struct qdio_buffer_element *sbale;
-        struct zfcp_fsf_req *fsf_req;
+       struct zfcp_fsf_req *fsf_req;
+       struct zfcp_adapter *adapter = erp_action->adapter;
        unsigned long lock_flags;
-       int retval = 0;
+       int retval;
 
        if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
                ZFCP_LOG_INFO("error: exchange port data "
-                              "command not supported by adapter %s\n",
+                             "command not supported by adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
-                return -EOPNOTSUPP;
-        }
+               return -EOPNOTSUPP;
+       }
 
        /* setup new FSF request */
        retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
-                                    erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0,
-                                    NULL, &lock_flags, &fsf_req);
-       if (retval < 0) {
+                                    ZFCP_REQ_AUTO_CLEANUP,
+                                    adapter->pool.fsf_req_erp,
+                                    &lock_flags, &fsf_req);
+       if (retval) {
                ZFCP_LOG_INFO("error: Out of resources. Could not create an "
-                              "exchange port data request for"
-                              "the adapter %s.\n",
+                             "exchange port data request for"
+                             "the adapter %s.\n",
                              zfcp_get_busid_by_adapter(adapter));
                write_unlock_irqrestore(&adapter->request_queue.queue_lock,
                                        lock_flags);
                return retval;
        }
 
-       if (data)
-               fsf_req->data = (unsigned long) data;
-
        sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
-        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-       if (erp_action) {
-               erp_action->fsf_req = fsf_req;
-               fsf_req->erp_action = erp_action;
-               zfcp_erp_start_timer(fsf_req);
-       } else
-               zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+       erp_action->fsf_req = fsf_req;
+       fsf_req->erp_action = erp_action;
+       zfcp_erp_start_timer(fsf_req);
 
        retval = zfcp_fsf_req_send(fsf_req);
+       write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
+
        if (retval) {
                ZFCP_LOG_INFO("error: Could not send an exchange port data "
-                              "command on the adapter %s\n",
+                             "command on the adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
                zfcp_fsf_req_free(fsf_req);
-               if (erp_action)
-                       erp_action->fsf_req = NULL;
+               erp_action->fsf_req = NULL;
+       }
+       else
+               ZFCP_LOG_DEBUG("exchange port data request initiated "
+                              "(adapter %s)\n",
+                              zfcp_get_busid_by_adapter(adapter));
+       return retval;
+}
+
+
+/**
+ * zfcp_fsf_exchange_port_data_sync - request information about local port
+ * and wait until information is ready
+ */
+int
+zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
+                               struct fsf_qtcb_bottom_port *data)
+{
+       volatile struct qdio_buffer_element *sbale;
+       struct zfcp_fsf_req *fsf_req;
+       unsigned long lock_flags;
+       int retval;
+
+       if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
+               ZFCP_LOG_INFO("error: exchange port data "
+                             "command not supported by adapter %s\n",
+                             zfcp_get_busid_by_adapter(adapter));
+               return -EOPNOTSUPP;
+       }
+
+       /* setup new FSF request */
+       retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
+                               0, NULL, &lock_flags, &fsf_req);
+       if (retval) {
+               ZFCP_LOG_INFO("error: Out of resources. Could not create an "
+                             "exchange port data request for"
+                             "the adapter %s.\n",
+                             zfcp_get_busid_by_adapter(adapter));
                write_unlock_irqrestore(&adapter->request_queue.queue_lock,
                                        lock_flags);
                return retval;
        }
 
+       if (data)
+               fsf_req->data = (unsigned long) data;
+
+       sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+       zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+       retval = zfcp_fsf_req_send(fsf_req);
        write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
 
-       if (!erp_action) {
+       if (retval)
+               ZFCP_LOG_INFO("error: Could not send an exchange port data "
+                             "command on the adapter %s\n",
+                             zfcp_get_busid_by_adapter(adapter));
+       else
                wait_event(fsf_req->completion_wq,
                           fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
-               zfcp_fsf_req_free(fsf_req);
-       }
+
+       zfcp_fsf_req_free(fsf_req);
+
        return retval;
 }
 
@@ -2277,18 +2380,16 @@ static void
 zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
 {
        struct zfcp_adapter *adapter;
-       struct fsf_qtcb *qtcb;
-       struct fsf_qtcb_bottom_port *bottom, *data;
+       struct fsf_qtcb_bottom_port *bottom;
        struct Scsi_Host *shost;
 
        adapter = fsf_req->adapter;
-       qtcb = fsf_req->qtcb;
-       bottom = &qtcb->bottom.port;
+       bottom = &fsf_req->qtcb->bottom.port;
        shost = adapter->scsi_host;
 
-       data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
-       if (data)
-               memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
+       if (fsf_req->data)
+               memcpy((struct fsf_qtcb_bottom_port*) fsf_req->data, bottom,
+                       sizeof(struct fsf_qtcb_bottom_port));
 
        if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
                fc_host_permanent_port_name(shost) = bottom->wwpn;
@@ -2336,10 +2437,10 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
 /*
  * function:    zfcp_fsf_open_port
  *
- * purpose:    
+ * purpose:
  *
  * returns:    address of initiated FSF request
- *             NULL - request could not be initiated 
+ *             NULL - request could not be initiated
  */
 int
 zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
@@ -2400,7 +2501,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
  *
  * purpose:    is called for finished Open Port command
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
@@ -3002,7 +3103,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
  *
  * purpose:    is called for finished Open LUN command
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
@@ -3265,7 +3366,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
  * purpose:
  *
  * returns:    address of fsf_req - request successfully initiated
- *             NULL - 
+ *             NULL -
  *
  * assumptions: This routine does not check whether the associated
  *              remote port/lun has already been opened. This should be
@@ -3586,17 +3687,17 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
                        ZFCP_LOG_DEBUG(
                                "Data did not fit into available buffer(s), "
                               "waiting for more...\n");
-               retval = -EIO;
-       } else {
-               ZFCP_LOG_NORMAL("error: No truncation implemented but "
-                               "required. Shutting down unit "
-                               "(adapter %s, port 0x%016Lx, "
-                               "unit 0x%016Lx)\n",
-                               zfcp_get_busid_by_unit(unit),
-                               unit->port->wwpn,
-                               unit->fcp_lun);
-               zfcp_erp_unit_shutdown(unit, 0);
-               retval = -EINVAL;
+                       retval = -EIO;
+               } else {
+                       ZFCP_LOG_NORMAL("error: No truncation implemented but "
+                                       "required. Shutting down unit "
+                                       "(adapter %s, port 0x%016Lx, "
+                                       "unit 0x%016Lx)\n",
+                                       zfcp_get_busid_by_unit(unit),
+                                       unit->port->wwpn,
+                                       unit->fcp_lun);
+                       zfcp_erp_unit_shutdown(unit, 0);
+                       retval = -EINVAL;
                }
                goto no_fit;
        }
@@ -3727,7 +3828,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
  *
  * purpose:    is called for finished Send FCP Command
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
@@ -3964,7 +4065,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
  *
  * purpose:    evaluates FCP_RSP IU
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
@@ -4192,7 +4293,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
  *
  * purpose:    evaluates FCP_RSP IU
  *
- * returns:    
+ * returns:
  */
 static int
 zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
@@ -4635,7 +4736,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
        INIT_LIST_HEAD(&fsf_req->list);
        init_timer(&fsf_req->timer);
 
-       /* initialize waitqueue which may be used to wait on 
+       /* initialize waitqueue which may be used to wait on
           this request completion */
        init_waitqueue_head(&fsf_req->completion_wq);
 
index 71186618947c5abf7187b210a71b17f99bf94f73..8cce5cc11d50c23e0df383ad08d65ee5ab67136f 100644 (file)
@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  *
  * (C) Copyright IBM Corp. 2002, 2006
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License as published by 
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version. 
- * 
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #ifndef FSF_H
index c6899efdc8f66fd8633ec03b38993b43762dd86b..3f105fdcf239610b18e14a9617b90630b0444302 100644 (file)
@@ -174,10 +174,9 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
                 * That is why we need to clear the link-down flag
                 * which is set again in case we have missed by a mile.
                 */
-               zfcp_erp_adapter_reopen(
-                       adapter, 
-                       ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
-                       ZFCP_STATUS_COMMON_ERP_FAILED);
+               zfcp_erp_adapter_reopen(adapter,
+                                      ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+                                      ZFCP_STATUS_COMMON_ERP_FAILED);
        }
        return retval;
 }
index ad7eb4a9261c64a0450b1a4e0adf54c6c0de0aa9..abae2027f7e598c9b6c6249f6064889af140afa1 100644 (file)
@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  *
  * (C) Copyright IBM Corp. 2002, 2006
- * 
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License as published by 
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version. 
- * 
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_SCSI
@@ -101,7 +101,7 @@ zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd)
                ((unsigned char *) fcp_cmd +
                 sizeof (struct fcp_cmnd_iu) + additional_length);
        /*
-        * fcp_dl_addr = start address of fcp_cmnd structure + 
+        * fcp_dl_addr = start address of fcp_cmnd structure +
         * size of fixed part + size of dynamically sized add_dcp_cdb field
         * SEE FCP-2 documentation
         */
@@ -189,13 +189,12 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
                unit->device = NULL;
                zfcp_erp_unit_failed(unit);
                zfcp_unit_put(unit);
-       } else {
+       } else
                ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
                                "address %p\n", sdpnt);
-       }
 }
 
-/* 
+/*
  * called from scsi midlayer to allow finetuning of a device.
  */
 static int
@@ -361,12 +360,11 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
        list_for_each_entry(port, &adapter->port_list_head, list) {
                if (!port->rport || (id != port->rport->scsi_target_id))
                        continue;
-               list_for_each_entry(unit, &port->unit_list_head, list) {
+               list_for_each_entry(unit, &port->unit_list_head, list)
                        if (lun == unit->scsi_lun) {
                                retval = unit;
                                goto out;
                        }
-               }
        }
  out:
        return retval;
@@ -374,7 +372,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
 
 /**
  * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
- * @scpnt: pointer to scsi_cmnd to be aborted 
+ * @scpnt: pointer to scsi_cmnd to be aborted
  * Return: SUCCESS - command has been aborted and cleaned up in internal
  *          bookkeeping, SCSI stack won't be called for aborted command
  *         FAILED - otherwise
@@ -733,7 +731,7 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost)
        if (!data)
                return NULL;
 
-       ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+       ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
        if (ret) {
                kfree(data);
                return NULL; /* XXX return zeroed fc_stats? */
@@ -763,7 +761,7 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
        if (!data)
                return;
 
-       ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+       ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
        if (ret) {
                kfree(data);
        } else {
@@ -802,6 +800,7 @@ struct fc_function_template zfcp_transport_functions = {
        .show_host_port_type = 1,
        .show_host_speed = 1,
        .show_host_port_id = 1,
+       .disable_target_scan = 1,
 };
 
 /**
index 81a484175863ee2bdac9fb49764f6091149cb18b..63f75ee95c338e588e005228d2b2b18aee204862 100644 (file)
@@ -139,7 +139,7 @@ static struct attribute_group zfcp_unit_attr_group = {
        .attrs = zfcp_unit_attrs,
 };
 
-/** 
+/**
  * zfcp_sysfs_create_unit_files - create sysfs unit files
  * @dev: pointer to belonging device
  *
@@ -151,7 +151,7 @@ zfcp_sysfs_unit_create_files(struct device *dev)
        return sysfs_create_group(&dev->kobj, &zfcp_unit_attr_group);
 }
 
-/** 
+/**
  * zfcp_sysfs_remove_unit_files - remove sysfs unit files
  * @dev: pointer to belonging device
  *
index 6f2c71ef47eee062990b76641128361c840f2b85..30905cebefbb4d876f8c249f9334e291ccce5751 100644 (file)
@@ -272,6 +272,13 @@ config SCSI_FC_ATTRS
          each attached FiberChannel device to sysfs, say Y.
          Otherwise, say N.
 
+config SCSI_FC_TGT_ATTRS
+       bool "SCSI target support for FiberChannel Transport Attributes"
+       depends on SCSI_FC_ATTRS
+       depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS
+       help
+               If you want to use SCSI target mode drivers enable this option.
+
 config SCSI_ISCSI_ATTRS
        tristate "iSCSI Transport Attributes"
        depends on SCSI && NET
@@ -289,6 +296,20 @@ config SCSI_SAS_ATTRS
 
 source "drivers/scsi/libsas/Kconfig"
 
+config SCSI_SRP_ATTRS
+       tristate "SRP Transport Attributes"
+       depends on SCSI
+       help
+         If you wish to export transport-specific information about
+         each attached SRP device to sysfs, say Y.
+
+config SCSI_SRP_TGT_ATTRS
+       bool "SCSI target support for SRP Transport Attributes"
+       depends on SCSI_SRP_ATTRS
+       depends on SCSI_TGT = y || SCSI_TGT = SCSI_SRP_ATTRS
+       help
+               If you want to use SCSI target mode drivers enable this option.
+
 endmenu
 
 menuconfig SCSI_LOWLEVEL
@@ -502,7 +523,6 @@ config SCSI_ADVANSYS
        tristate "AdvanSys SCSI support"
        depends on SCSI
        depends on ISA || EISA || PCI
-       depends on BROKEN || X86_32
        help
          This is a driver for all SCSI host adapters manufactured by
          AdvanSys. It is documented in the kernel source in
@@ -524,19 +544,32 @@ config SCSI_IN2000
          module will be called in2000.
 
 config SCSI_ARCMSR
-       tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support"
+       tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter"
        depends on PCI && SCSI
        help
-         This driver supports all of ARECA's SATA RAID controller cards.
+         This driver supports all of ARECA's SATA/SAS RAID controller cards.
          This is an ARECA-maintained driver by Erich Chen.
-         If you have any problems, please mail to: < erich@areca.com.tw >
+         If you have any problems, please mail to: <erich@areca.com.tw>.
          Areca supports Linux RAID config tools.
-
-         < http://www.areca.com.tw >
+         Please link <http://www.areca.com.tw>
 
          To compile this driver as a module, choose M here: the
          module will be called arcmsr (modprobe arcmsr).
 
+config SCSI_ARCMSR_AER
+       bool "Enable PCI Error Recovery Capability in Areca Driver(ARCMSR)"
+       depends on SCSI_ARCMSR && PCIEAER
+       default n
+       help
+         The advanced error reporting(AER) capability is "NOT" provided by
+         ARC1200/1201/1202 SATA RAID controllers cards.
+         If your card is one of ARC1200/1201/1202, please use the default setting, n.
+         If your card is other models, you could pick it
+         on condition that the kernel version is greater than 2.6.19.
+         This function is maintained driver by Nick Cheng. If you have any
+         problems or suggestion, you are welcome to contact with <nick.cheng@areca.com.tw>.
+         To enable this function, choose Y here.
+
 source "drivers/scsi/megaraid/Kconfig.megaraid"
 
 config SCSI_HPTIOP
@@ -836,6 +869,7 @@ config SCSI_IPS
 config SCSI_IBMVSCSI
        tristate "IBM Virtual SCSI support"
        depends on PPC_PSERIES || PPC_ISERIES
+       select SCSI_SRP_ATTRS
        help
          This is the IBM POWER Virtual SCSI Client
 
@@ -844,7 +878,7 @@ config SCSI_IBMVSCSI
 
 config SCSI_IBMVSCSIS
        tristate "IBM Virtual SCSI Server support"
-       depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP
+       depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS
        help
          This is the SRP target driver for IBM pSeries virtual environments.
 
index 86a7ba7bad63f4f7b9e3c005e45381a0c351d2db..6141389dcdb24fd28f014e278a2ddec5a614b03b 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS)   += scsi_transport_fc.o
 obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)   += scsi_transport_sas.o
 obj-$(CONFIG_SCSI_SAS_LIBSAS)  += libsas/
+obj-$(CONFIG_SCSI_SRP_ATTRS)   += scsi_transport_srp.o
 
 obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
 obj-$(CONFIG_INFINIBAND_ISER)  += libiscsi.o
index f8e449a98d29e03f9c03a491bbea94c7b158ceb7..988f0bc5eda5e081929864f40f87fbf4e0b49f75 100644 (file)
@@ -1542,9 +1542,7 @@ part2:
        hostdata->connected = cmd;
        hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 
-       if (cmd->SCp.ptr != (char *)cmd->sense_buffer) {
-               initialize_SCp(cmd);
-       }
+       initialize_SCp(cmd);
 
        return 0;
 
@@ -2133,7 +2131,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                sink = 1;
                                do_abort(instance);
                                cmd->result = DID_ERROR << 16;
-                               cmd->done(cmd);
+                               cmd->scsi_done(cmd);
                                return;
 #endif
                                /* 
@@ -2196,7 +2194,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                                sink = 1;
                                                do_abort(instance);
                                                cmd->result = DID_ERROR << 16;
-                                               cmd->done(cmd);
+                                               cmd->scsi_done(cmd);
                                                /* XXX - need to source or sink data here, as appropriate */
                                        } else
                                                cmd->SCp.this_residual -= transfersize - len;
@@ -2280,19 +2278,16 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                                cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
 #ifdef AUTOSENSE
+                                       if ((cmd->cmnd[0] == REQUEST_SENSE) &&
+                                               hostdata->ses.cmd_len) {
+                                               scsi_eh_restore_cmnd(cmd, &hostdata->ses);
+                                               hostdata->ses.cmd_len = 0 ;
+                                       }
+
                                        if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+                                               scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
+
                                                dprintk(NDEBUG_AUTOSENSE, ("scsi%d : performing request sense\n", instance->host_no));
-                                               cmd->cmnd[0] = REQUEST_SENSE;
-                                               cmd->cmnd[1] &= 0xe0;
-                                               cmd->cmnd[2] = 0;
-                                               cmd->cmnd[3] = 0;
-                                               cmd->cmnd[4] = sizeof(cmd->sense_buffer);
-                                               cmd->cmnd[5] = 0;
-
-                                               cmd->SCp.buffer = NULL;
-                                               cmd->SCp.buffers_residual = 0;
-                                               cmd->SCp.ptr = (char *) cmd->sense_buffer;
-                                               cmd->SCp.this_residual = sizeof(cmd->sense_buffer);
 
                                                LIST(cmd, hostdata->issue_queue);
                                                cmd->host_scribble = (unsigned char *)
@@ -2740,7 +2735,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
                        tmp->host_scribble = NULL;
                        tmp->result = DID_ABORT << 16;
                        dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
-                       tmp->done(tmp);
+                       tmp->scsi_done(tmp);
                        return SUCCESS;
                }
 #if (NDEBUG  & NDEBUG_ABORT)
@@ -2805,7 +2800,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
                                        *prev = (Scsi_Cmnd *) tmp->host_scribble;
                                        tmp->host_scribble = NULL;
                                        tmp->result = DID_ABORT << 16;
-                                       tmp->done(tmp);
+                                       tmp->scsi_done(tmp);
                                        return SUCCESS;
                                }
                }
index bccf13f715321a9daaaf82cac1a50d6b868646a8..bdc468c9e1d9d6de71ba091041096fd831512ee7 100644 (file)
 
 #include <linux/interrupt.h>
 
+#ifdef AUTOSENSE
+#include <scsi/scsi_eh.h>
+#endif
+
 #define NCR5380_PUBLIC_RELEASE 7
 #define NCR53C400_PUBLIC_RELEASE 2
 
@@ -281,6 +285,9 @@ struct NCR5380_hostdata {
        unsigned pendingr;
        unsigned pendingw;
 #endif
+#ifdef AUTOSENSE
+       struct scsi_eh_save ses;
+#endif
 };
 
 #ifdef __KERNEL__
index 79b4df1581400691d1b9bbf9676b732a01586167..96e8e29aa05dd5428c58f64c33bbe046c2424d3a 100644 (file)
@@ -1385,7 +1385,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
                                this->host_scribble = NULL;
                                esp_release_dmabufs(esp, this);
                                this->result = DID_ABORT << 16;
-                               this->done(this);
+                               this->scsi_done(this);
                                if(don)
                                        esp->dma_ints_on(esp);
                                return SUCCESS;
index 3a8089705febc738ef719312c734948cc87dac72..9e64b21ef637787c3a5d6e2d709377dafe649c3a 100644 (file)
@@ -97,7 +97,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mca.h>
-#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
@@ -314,10 +313,10 @@ NCR_D700_probe(struct device *dev)
                break;
        }
 
-       p = kmalloc(sizeof(*p), GFP_KERNEL);
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
-       memset(p, '\0', sizeof(*p));
+
        p->dev = dev;
        snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
        if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {
index 0c758d1452baa3196010a12f266d3a67d7d17c5e..d4bda201774652d9f3df315fa182832abb52610c 100644 (file)
@@ -37,7 +37,7 @@ static struct platform_device *a4000t_scsi_device;
 
 static int __devinit a4000t_probe(struct device *dev)
 {
-       struct Scsi_Host * host = NULL;
+       struct Scsi_Host *host;
        struct NCR_700_Host_Parameters *hostdata;
 
        if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
@@ -47,12 +47,11 @@ static int __devinit a4000t_probe(struct device *dev)
                                "A4000T builtin SCSI"))
                goto out;
 
-       hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-       if (hostdata == NULL) {
+       hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+       if (!hostdata) {
                printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
                goto out_release;
        }
-       memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 
        /* Fill in the required pieces of hostdata */
        hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
index 6800e578e4b1f82dc2a9b4763588497f2835fe63..80e448d0f3dbd541bae7406b68617d904472bc13 100644 (file)
@@ -177,9 +177,9 @@ int check_interval = 24 * 60 * 60;
 module_param(check_interval, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks.");
 
-int check_reset = 1;
-module_param(check_reset, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the adapter.");
+int aac_check_reset = 1;
+module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the adapter.");
 
 int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
@@ -1305,7 +1305,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
                          (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
                          dev->supplement_adapter_info.VpdInfo.Tsid);
                }
-               if (!check_reset ||
+               if (!aac_check_reset ||
                  (dev->supplement_adapter_info.SupportedOptions2 &
                  le32_to_cpu(AAC_OPTION_IGNORE_RESET))) {
                        printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
index 94727b9375ecafde6fc46a74c4b7188bfe63fb2c..03b51025a8f441fdb4258d452f218fd5d05c8ee4 100644 (file)
@@ -1871,4 +1871,4 @@ extern int aac_reset_devices;
 extern int aac_commit;
 extern int update_interval;
 extern int check_interval;
-extern int check_reset;
+extern int aac_check_reset;
index bb870906b4cf72fa15ec8243403bf13812a1c824..240a0bb8986fe3d428c58430234f241bdddd7630 100644 (file)
@@ -1372,8 +1372,9 @@ int aac_check_health(struct aac_dev * aac)
 
        printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED);
 
-       if (!check_reset || (aac->supplement_adapter_info.SupportedOptions2 &
-         le32_to_cpu(AAC_OPTION_IGNORE_RESET)))
+       if (!aac_check_reset ||
+               (aac->supplement_adapter_info.SupportedOptions2 &
+                       le32_to_cpu(AAC_OPTION_IGNORE_RESET)))
                goto out;
        host = aac->scsi_host_ptr;
        if (aac->thread->pid != current->pid)
index 79c0b6e37a3b92abe629101857f0364a046acfd6..9dd3952516c548c84b61b0754ab406b14ae36dd0 100644 (file)
-#define ASC_VERSION "3.3K"     /* AdvanSys Driver Version */
+#define DRV_NAME "advansys"
+#define ASC_VERSION "3.4"      /* AdvanSys Driver Version */
 
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  *
  * Copyright (c) 1995-2000 Advanced System Products, Inc.
  * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
+ * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
  * All Rights Reserved.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
- * changed its name to ConnectCom Solutions, Inc.
- *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  */
 
 /*
-
-  Documentation for the AdvanSys Driver
-
-  A. Linux Kernels Supported by this Driver
-  B. Adapters Supported by this Driver
-  C. Linux source files modified by AdvanSys Driver
-  D. Source Comments
-  E. Driver Compile Time Options and Debugging
-  F. Driver LILO Option
-  G. Tests to run before releasing new driver
-  H. Release History
-  I. Known Problems/Fix List
-  J. Credits (Chronological Order)
-
-  A. Linux Kernels Supported by this Driver
-
-     This driver has been tested in the following Linux kernels: v2.2.18
-     v2.4.0. The driver is supported on v2.2 and v2.4 kernels and on x86,
-     alpha, and PowerPC platforms.
-
-  B. Adapters Supported by this Driver
-
-     AdvanSys (Advanced System Products, Inc.) manufactures the following
-     RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
-     (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
-     buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
-     transfer) SCSI Host Adapters for the PCI bus.
-
-     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. A CDB is a single SCSI command. The driver
-     detect routine will display the number of CDBs available for each
-     adapter detected. The number of CDBs used by the driver can be
-     lowered in the BIOS by changing the 'Host Queue Size' adapter setting.
-
-     Laptop Products:
-        ABP-480 - Bus-Master CardBus (16 CDB) (2.4 kernel and greater)
-
-     Connectivity Products:
-        ABP510/5150 - Bus-Master ISA (240 CDB)
-        ABP5140 - Bus-Master ISA PnP (16 CDB)
-        ABP5142 - Bus-Master ISA PnP with floppy (16 CDB)
-        ABP902/3902 - Bus-Master PCI (16 CDB)
-        ABP3905 - Bus-Master PCI (16 CDB)
-        ABP915 - Bus-Master PCI (16 CDB)
-        ABP920 - Bus-Master PCI (16 CDB)
-        ABP3922 - Bus-Master PCI (16 CDB)
-        ABP3925 - Bus-Master PCI (16 CDB)
-        ABP930 - Bus-Master PCI (16 CDB)
-        ABP930U - Bus-Master PCI Ultra (16 CDB)
-        ABP930UA - Bus-Master PCI Ultra (16 CDB)
-        ABP960 - Bus-Master PCI MAC/PC (16 CDB)
-        ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
-
-     Single Channel Products:
-        ABP542 - Bus-Master ISA with floppy (240 CDB)
-        ABP742 - Bus-Master EISA (240 CDB)
-        ABP842 - Bus-Master VL (240 CDB)
-        ABP940 - Bus-Master PCI (240 CDB)
-        ABP940U - Bus-Master PCI Ultra (240 CDB)
-        ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB)
-        ABP970 - Bus-Master PCI MAC/PC (240 CDB)
-        ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
-        ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB)
-        ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB)
-        ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB)
-        ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB)
-
-     Multi-Channel Products:
-        ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
-        ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
-        ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
-        ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel)
-        ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
-        ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
-        ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.)
-        ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB)
-        ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB)
-
-  C. Linux source files modified by AdvanSys Driver
-
-     This section for historical purposes documents the changes
-     originally made to the Linux kernel source to add the advansys
-     driver. As Linux has changed some of these files have also
-     been modified.
-
-     1. linux/arch/i386/config.in:
-
-          bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
-
-     2. linux/drivers/scsi/hosts.c:
-
-          #ifdef CONFIG_SCSI_ADVANSYS
-          #include "advansys.h"
-          #endif
-
-        and after "static struct scsi_host_template builtin_scsi_hosts[] =":
-
-          #ifdef CONFIG_SCSI_ADVANSYS
-          ADVANSYS,
-          #endif
-
-     3. 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. linux/init/main.c:
-
-          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
-
-  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 File
-           --- Driver Options
-           --- Debugging Header
-           --- Asc Library Constants and Macros
-           --- Adv Library Constants and Macros
-           --- Driver Constants and Macros
-           --- Driver Structures
-           --- Driver Data
-           --- Driver Function Prototypes
-           --- Linux 'struct scsi_host_template' and advansys_setup() Functions
-           --- Loadable Driver Support
-           --- Miscellaneous Driver Functions
-           --- Functions Required by the Asc Library
-           --- Functions Required by the Adv Library
-           --- Tracing and Debugging Functions
-           --- Asc Library Functions
-           --- Adv 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 and Adv Library to reduce the size of this file. This
-        source can be found under the following headings. The Asc Library
-        is used to support Narrow Boards. The Adv Library is used to
-        support Wide Boards.
-
-           --- Asc Library Constants and Macros
-           --- Adv Library Constants and Macros
-           --- Asc Library Functions
-           --- Adv 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_ASSERT - Enable driver assertions (Def: Enabled)
-
-        Enabling this option adds assertion logic statements to the
-        driver. If an assertion fails a message will be displayed to
-        the console, but the system will continue to operate. Any
-        assertions encountered should be reported to the person
-        responsible for the driver. Assertion statements may proactively
-        detect problems with the driver and facilitate fixing these
-        problems. Enabling assertions will add a small overhead to the
-        execution of the driver.
-
-     2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled)
-
-        Enabling this option adds tracing functions to the driver and
-        the ability to set a driver tracing level at boot time. This
-        option will also export symbols not required outside the driver to
-        the kernel name space. This option is very useful for debugging
-        the driver, but it will add to the size of the driver execution
-        image and add overhead to the execution of the driver.
-
-        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_IOPORT_PROBE + 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,0,0,0,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
-
-        To enable debug output to console, please make sure that:
-
-        a. System and kernel logging is enabled (syslogd, klogd running).
-        b. Kernel messages are routed to console output. Check
-           /etc/syslog.conf for an entry similar to this:
-
-                kern.*                  /dev/console
-
-        c. klogd is started with the appropriate -c parameter
-           (e.g. klogd -c 8)
-
-        This will cause printk() messages to be be displayed on the
-        current console. Refer to the klogd(8) and syslogd(8) man pages
-        for details.
-
-        Alternatively you can enable printk() to console with this
-        program. However, this is not the 'official' way to do this.
-        Debug output is logged in /var/log/messages.
-
-          main()
-          {
-                  syscall(103, 7, 0, 0);
-          }
-
-        Increasing LOG_BUF_LEN in kernel/printk.c to something like
-        40960 allows more debug messages to be buffered in the kernel
-        and written to the console or log file.
-
-     3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0)
-
-        Enabling this option adds statistics collection and display
-        through /proc to the driver. The information is useful for
-        monitoring driver and device performance. It will add to the
-        size of the driver execution image and add minor overhead to
-        the execution of the driver.
-
-        Statistics are maintained on a per adapter basis. Driver entry
-        point call counts and transfer size counts are maintained.
-        Statistics are only available for kernels greater than or equal
-        to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured.
-
-        AdvanSys SCSI adapter files have the following path name format:
-
-           /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
-
-        This information can be displayed with cat. For example:
-
-           cat /proc/scsi/advansys/0
-
-        When ADVANSYS_STATS is not defined the AdvanSys /proc files only
-        contain adapter and device configuration information.
-
-  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_IOPORT_PROBE + 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. Tests to run before releasing new driver
-
-     1. In the supported kernels verify there are no warning or compile
-        errors when the kernel is built as both a driver and as a module
-        and with the following options:
-
-        ADVANSYS_DEBUG - enabled and disabled
-        CONFIG_SMP - enabled and disabled
-        CONFIG_PROC_FS - enabled and disabled
-
-     2. Run tests on an x86, alpha, and PowerPC with at least one narrow
-        card and one wide card attached to a hard disk and CD-ROM drive:
-        fdisk, mkfs, fsck, bonnie, copy/compare test from the
-        CD-ROM to the hard drive.
-
-  H. Release History
-
-     BETA-1.0 (12/23/95):
-         First Release
-
-     BETA-1.1 (12/28/95):
-         1. Prevent advansys_detect() from being called twice.
-         2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
-
-     1.2 (1/12/96):
-         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 v1.3.X.
-
-     1.3 (2/23/96):
-         1. Fix problem in advansys_biosparam() that resulted in the
-            wrong drive geometry being returned for drives > 1GB with
-            extended translation enabled.
-         2. Add additional tracing during device initialization.
-         3. Change code that only applies to ISA PnP adapter.
-         4. Eliminate 'make dep' warning.
-         5. Try to fix problem with handling resets by increasing their
-            timeout value.
-
-     1.4 (5/8/96):
-         1. Change definitions to eliminate conflicts with other subsystems.
-         2. Add versioning code for the shared interrupt changes.
-         3. Eliminate problem in asc_rmqueue() with iterating after removing
-            a request.
-         4. Remove reset request loop problem from the "Known Problems or
-            Issues" section. This problem was isolated and fixed in the
-            mid-level SCSI driver.
-
-     1.5 (8/8/96):
-         1. Add support for ABP-940U (PCI Ultra) adapter.
-         2. Add support for IRQ sharing by setting the IRQF_SHARED flag for
-            request_irq and supplying a dev_id pointer to both request_irq()
-            and free_irq().
-         3. In AscSearchIOPortAddr11() restore a call to check_region() which
-            should be used before I/O port probing.
-         4. Fix bug in asc_prt_hex() which resulted in the displaying
-            the wrong data.
-         5. Incorporate miscellaneous Asc Library bug fixes and new microcode.
-         6. Change driver versioning to be specific to each Linux sub-level.
-         7. Change statistics gathering to be per adapter instead of global
-            to the driver.
-         8. Add more information and statistics to the adapter /proc file:
-            /proc/scsi/advansys[0...].
-         9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list.
-            This problem has been addressed with the SCSI mid-level changes
-            made in v1.3.89. The advansys_select_queue_depths() function
-            was added for the v1.3.89 changes.
-
-     1.6 (9/10/96):
-         1. Incorporate miscellaneous Asc Library bug fixes and new microcode.
-
-     1.7 (9/25/96):
-         1. Enable clustering and optimize the setting of the maximum number
-            of scatter gather elements for any particular board. Clustering
-            increases CPU utilization, but results in a relatively larger
-            increase in I/O throughput.
-         2. Improve the performance of the request queuing functions by
-            adding a last pointer to the queue structure.
-         3. Correct problems with reset and abort request handling that
-            could have hung or crashed Linux.
-         4. Add more information to the adapter /proc file:
-            /proc/scsi/advansys[0...].
-         5. Remove the request timeout issue form the driver issues list.
-         6. Miscellaneous documentation additions and changes.
-
-     1.8 (10/4/96):
-         1. Make changes to handle the new v2.1.0 kernel memory mapping
-            in which a kernel virtual address may not be equivalent to its
-            bus or DMA memory address.
-         2. Change abort and reset request handling to make it yet even
-            more robust.
-         3. Try to mitigate request starvation by sending ordered requests
-            to heavily loaded, tag queuing enabled devices.
-         4. Maintain statistics on request response time.
-         5. Add request response time statistics and other information to
-            the adapter /proc file: /proc/scsi/advansys[0...].
-
-     1.9 (10/21/96):
-         1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
-            make use of mid-level SCSI driver device queue depth flow
-            control mechanism. This will eliminate aborts caused by a
-            device being unable to keep up with requests and eliminate
-            repeat busy or QUEUE FULL status returned by a device.
-         2. Incorporate miscellaneous Asc Library bug fixes.
-         3. To allow the driver to work in kernels with broken module
-            support set 'cmd_per_lun' if the driver is compiled as a
-            module. This change affects kernels v1.3.89 to present.
-         4. Remove PCI BIOS address from the driver banner. The PCI BIOS
-            is relocated by the motherboard BIOS and its new address can
-            not be determined by the driver.
-         5. Add mid-level SCSI queue depth information to the adapter
-            /proc file: /proc/scsi/advansys[0...].
-
-     2.0 (11/14/96):
-         1. Change allocation of global structures used for device
-            initialization to guarantee they are in DMA-able memory.
-            Previously when the driver was loaded as a module these
-            structures might not have been in DMA-able memory, causing
-            device initialization to fail.
-
-     2.1 (12/30/96):
-         1. In advansys_reset(), if the request is a synchronous reset
-            request, even if the request serial number has changed, then
-            complete the request.
-         2. Add Asc Library bug fixes including new microcode.
-         3. Clear inquiry buffer before using it.
-         4. Correct ifdef typo.
-
-     2.2 (1/15/97):
-         1. Add Asc Library bug fixes including new microcode.
-         2. Add synchronous data transfer rate information to the
-            adapter /proc file: /proc/scsi/advansys[0...].
-         3. Change ADVANSYS_DEBUG to be disabled by default. This
-            will reduce the size of the driver image, eliminate execution
-            overhead, and remove unneeded symbols from the kernel symbol
-            space that were previously added by the driver.
-         4. Add new compile-time option ADVANSYS_ASSERT for assertion
-            code that used to be defined within ADVANSYS_DEBUG. This
-            option is enabled by default.
-
-     2.8 (5/26/97):
-         1. Change version number to 2.8 to synchronize the Linux driver
-            version numbering with other AdvanSys drivers.
-         2. Reformat source files without tabs to present the same view
-            of the file to everyone regardless of the editor tab setting
-            being used.
-         3. Add Asc Library bug fixes.
-
-     3.1A (1/8/98):
-         1. Change version number to 3.1 to indicate that support for
-            Ultra-Wide adapters (ABP-940UW) is included in this release.
-         2. Add Asc Library (Narrow Board) bug fixes.
-         3. Report an underrun condition with the host status byte set
-            to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which
-            causes the underrun condition to be ignored. When Linux defines
-            its own DID_UNDERRUN the constant defined in this file can be
-            removed.
-         4. Add patch to AscWaitTixISRDone().
-         5. Add support for up to 16 different AdvanSys host adapter SCSI
-            channels in one system. This allows four cards with four channels
-            to be used in one system.
-
-     3.1B (1/9/98):
-         1. Handle that PCI register base addresses are not always page
-            aligned even though ioremap() requires that the address argument
-            be page aligned.
-
-     3.1C (1/10/98):
-         1. Update latest BIOS version checked for from the /proc file.
-         2. Don't set microcode SDTR variable at initialization. Instead
-            wait until device capabilities have been detected from an Inquiry
-            command.
-
-     3.1D (1/21/98):
-         1. Improve performance when the driver is compiled as module by
-            allowing up to 64 scatter-gather elements instead of 8.
-
-     3.1E (5/1/98):
-         1. Set time delay in AscWaitTixISRDone() to 1000 ms.
-         2. Include SMP locking changes.
-         3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS
-            access functions.
-         4. Update board serial number printing.
-         5. Try allocating an IRQ both with and without the IRQF_DISABLED
-            flag set to allow IRQ sharing with drivers that do not set
-            the IRQF_DISABLED flag. Also display a more descriptive error
-            message if request_irq() fails.
-         6. Update to latest Asc and Adv Libraries.
-
-     3.2A (7/22/99):
-         1. Update Adv Library to 4.16 which includes support for
-            the ASC38C0800 (Ultra2/LVD) IC.
-
-     3.2B (8/23/99):
-         1. Correct PCI compile time option for v2.1.93 and greater
-            kernels, advansys_info() string, and debug compile time
-            option.
-         2. Correct DvcSleepMilliSecond() for v2.1.0 and greater
-            kernels. This caused an LVD detection/BIST problem problem
-            among other things.
-         3. Sort PCI cards by PCI Bus, Slot, Function ascending order
-            to be consistent with the BIOS.
-         4. Update to Asc Library S121 and Adv Library 5.2.
-
-     3.2C (8/24/99):
-         1. Correct PCI card detection bug introduced in 3.2B that
-            prevented PCI cards from being detected in kernels older
-            than v2.1.93.
-
-     3.2D (8/26/99):
-         1. Correct /proc device synchronous speed information display.
-            Also when re-negotiation is pending for a target device
-            note this condition with an * and footnote.
-         2. Correct initialization problem with Ultra-Wide cards that
-            have a pre-3.2 BIOS. A microcode variable changed locations
-            in 3.2 and greater BIOSes which caused WDTR to be attempted
-            erroneously with drives that don't support WDTR.
-
-     3.2E (8/30/99):
-         1. Fix compile error caused by v2.3.13 PCI structure change.
-         2. Remove field from ASCEEP_CONFIG that resulted in an EEPROM
-            checksum error for ISA cards.
-         3. Remove ASC_QUEUE_FLOW_CONTROL conditional code. The mid-level
-            SCSI changes that it depended on were never included in Linux.
-
-     3.2F (9/3/99):
-         1. Handle new initial function code added in v2.3.16 for all
-            driver versions.
-
-     3.2G (9/8/99):
-         1. Fix PCI board detection in v2.3.13 and greater kernels.
-         2. Fix comiple errors in v2.3.X with debugging enabled.
-
-     3.2H (9/13/99):
-         1. Add 64-bit address, long support for Alpha and UltraSPARC.
-            The driver has been verified to work on an Alpha system.
-         2. Add partial byte order handling support for Power PC and
-            other big-endian platforms. This support has not yet been
-            completed or verified.
-         3. For wide boards replace block zeroing of request and
-            scatter-gather structures with individual field initialization
-            to improve performance.
-         4. Correct and clarify ROM BIOS version detection.
-
-     3.2I (10/8/99):
-         1. Update to Adv Library 5.4.
-         2. Add v2.3.19 underrun reporting to asc_isr_callback() and
-            adv_isr_callback().  Remove DID_UNDERRUN constant and other
-            no longer needed code that previously documented the lack
-            of underrun handling.
-
-     3.2J (10/14/99):
-         1. Eliminate compile errors for v2.0 and earlier kernels.
-
-     3.2K (11/15/99):
-         1. Correct debug compile error in asc_prt_adv_scsi_req_q().
-         2. Update Adv Library to 5.5.
-         3. Add ifdef handling for /proc changes added in v2.3.28.
-         4. Increase Wide board scatter-gather list maximum length to
-            255 when the driver is compiled into the kernel.
-
-     3.2L (11/18/99):
-         1. Fix bug in adv_get_sglist() that caused an assertion failure
-            at line 7475. The reqp->sgblkp pointer must be initialized
-            to NULL in adv_get_sglist().
-
-     3.2M (11/29/99):
-         1. Really fix bug in adv_get_sglist().
-         2. Incorporate v2.3.29 changes into driver.
-
-     3.2N (4/1/00):
-         1. Add CONFIG_ISA ifdef code.
-         2. Include advansys_interrupts_enabled name change patch.
-         3. For >= v2.3.28 use new SCSI error handling with new function
-            advansys_eh_bus_reset(). Don't include an abort function
-            because of base library limitations.
-         4. For >= v2.3.28 use per board lock instead of io_request_lock.
-         5. For >= v2.3.28 eliminate advansys_command() and
-            advansys_command_done().
-         6. Add some changes for PowerPC (Big Endian) support, but it isn't
-            working yet.
-         7. Fix "nonexistent resource free" problem that occurred on a module
-            unload for boards with an I/O space >= 255. The 'n_io_port' field
-            is only one byte and can not be used to hold an ioport length more
-            than 255.
-
-     3.3A (4/4/00):
-         1. Update to Adv Library 5.8.
-         2. For wide cards add support for CDBs up to 16 bytes.
-         3. Eliminate warnings when CONFIG_PROC_FS is not defined.
-
-     3.3B (5/1/00):
-         1. Support for PowerPC (Big Endian) wide cards. Narrow cards
-            still need work.
-         2. Change bitfields to shift and mask access for endian
-            portability.
-
-     3.3C (10/13/00):
-         1. Update for latest 2.4 kernel.
-         2. Test ABP-480 CardBus support in 2.4 kernel - works!
-         3. Update to Asc Library S123.
-         4. Update to Adv Library 5.12.
-
-     3.3D (11/22/00):
-         1. Update for latest 2.4 kernel.
-         2. Create patches for 2.2 and 2.4 kernels.
-
-     3.3E (1/9/01):
-         1. Now that 2.4 is released remove ifdef code for kernel versions
-            less than 2.2. The driver is now only supported in kernels 2.2,
-            2.4, and greater.
-         2. Add code to release and acquire the io_request_lock in
-            the driver entrypoint functions: advansys_detect and
-            advansys_queuecommand. In kernel 2.4 the SCSI mid-level driver
-            still holds the io_request_lock on entry to SCSI low-level drivers.
-            This was supposed to be removed before 2.4 was released but never
-            happened. When the mid-level SCSI driver is changed all references
-            to the io_request_lock should be removed from the driver.
-         3. Simplify error handling by removing advansys_abort(),
-            AscAbortSRB(), AscResetDevice(). SCSI bus reset requests are
-            now handled by resetting the SCSI bus and fully re-initializing
-            the chip. This simple method of error recovery has proven to work
-            most reliably after attempts at different methods. Also now only
-            support the "new" error handling method and remove the obsolete
-            error handling interface.
-         4. Fix debug build errors.
-
-     3.3F (1/24/01):
-         1. Merge with ConnectCom version from Andy Kellner which
-            updates Adv Library to 5.14.
-         2. Make PowerPC (Big Endian) work for narrow cards and
-            fix problems writing EEPROM for wide cards.
-         3. Remove interrupts_enabled assertion function.
-
-     3.3G (2/16/01):
-         1. Return an error from narrow boards if passed a 16 byte
-            CDB. The wide board can already handle 16 byte CDBs.
-
-     3.3GJ (4/15/02):
-        1. hacks for lk 2.5 series (D. Gilbert)
-
-     3.3GJD (10/14/02):
-         1. change select_queue_depths to slave_configure
-        2. make cmd_per_lun be sane again
-
-     3.3K [2004/06/24]:
-         1. continuing cleanup for lk 2.6 series
-         2. Fix problem in lk 2.6.7-bk2 that broke PCI wide cards
-         3. Fix problem that oopsed ISA cards
-
-  I. Known Problems/Fix List (XXX)
-
-     1. Need to add memory mapping workaround. Test the memory mapping.
-        If it doesn't work revert to I/O port access. Can a test be done
-        safely?
-     2. Handle an interrupt not working. Keep an interrupt counter in
-        the interrupt handler. In the timeout function if the interrupt
-        has not occurred then print a message and run in polled mode.
-     3. Allow bus type scanning order to be changed.
-     4. Need to add support for target mode commands, cf. CAM XPT.
-
-  J. Credits (Chronological Order)
-
-     Bob Frey <bfrey@turbolinux.com.cn> wrote the AdvanSys SCSI driver
-     and maintained it up to 3.3F. He continues to answer questions
-     and help maintain the driver.
-
-     Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
-     basis for the Linux v1.3.X changes which were included in the
-     1.2 release.
-
-     Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug
-     in advansys_biosparam() which was fixed in the 1.3 release.
-
-     Erik Ratcliffe <erik@caldera.com> has done testing of the
-     AdvanSys driver in the Caldera releases.
-
-     Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
-     AscWaitTixISRDone() which he found necessary to make the
-     driver work with a SCSI-1 disk.
-
-     Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide
-     support in the 3.1A driver.
-
-     Doug Gilbert <dgilbert@interlog.com> has made changes and
-     suggestions to improve the driver and done a lot of testing.
-
-     Ken Mort <ken@mort.net> reported a DEBUG compile bug fixed
-     in 3.2K.
-
-     Tom Rini <trini@kernel.crashing.org> provided the CONFIG_ISA
-     patch and helped with PowerPC wide and narrow board support.
-
-     Philip Blundell <philb@gnu.org> provided an
-     advansys_interrupts_enabled patch.
-
-     Dave Jones <dave@denial.force9.co.uk> reported the compiler
-     warnings generated when CONFIG_PROC_FS was not defined in
-     the 3.2M driver.
-
-     Jerry Quinn <jlquinn@us.ibm.com> fixed PowerPC support (endian
-     problems) for wide cards.
-
-     Bryan Henderson <bryanh@giraffe-data.com> helped debug narrow
-     card error handling.
-
-     Manuel Veloso <veloso@pobox.com> worked hard on PowerPC narrow
-     board support and fixed a bug in AscGetEEPConfig().
-
-     Arnaldo Carvalho de Melo <acme@conectiva.com.br> made
-     save_flags/restore_flags changes.
-
-     Andy Kellner <AKellner@connectcom.net> continues the Advansys SCSI
-     driver development for ConnectCom (Version > 3.3F).
-
-  K. ConnectCom (AdvanSys) Contact Information
-
-     Mail:                   ConnectCom Solutions, Inc.
-                             1150 Ringwood Court
-                             San Jose, CA 95131
-     Operator/Sales:         1-408-383-9400
-     FAX:                    1-408-383-9612
-     Tech Support:           1-408-467-2930
-     Tech Support E-Mail:    linux@connectcom.net
-     FTP Site:               ftp.connectcom.net (login: anonymous)
-     Web Site:               http://www.connectcom.net
-
-*/
-
-/*
- * --- Linux Include Files
+ * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
+ * changed its name to ConnectCom Solutions, Inc.
+ * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets
  */
 
 #include <linux/module.h>
-
-#if defined(CONFIG_X86) && !defined(CONFIG_ISA)
-#define CONFIG_ISA
-#endif /* CONFIG_X86 && !CONFIG_ISA */
-
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
-#include <linux/stat.h>
+#include <linux/isa.h>
+#include <linux/eisa.h>
+#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 
 #include <asm/system.h>
 #include <asm/dma.h>
 
-/* FIXME: (by jejb@steeleye.com) This warning is present for two
- * reasons:
- *
- * 1) This driver badly needs converting to the correct driver model
- *    probing API
- *
- * 2) Although all of the necessary command mapping places have the
- * appropriate dma_map.. APIs, the driver still processes its internal
- * queue using bus_to_virt() and virt_to_bus() which are illegal under
- * the API.  The entire queue processing structure will need to be
- * altered to fix this.
- */
-#warning this driver is still not properly converted to the DMA API
-
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif /* CONFIG_PCI */
 
-/*
- * --- Driver Options
+/* FIXME:
+ *
+ *  1. Although all of the necessary command mapping places have the
+ *     appropriate dma_map.. APIs, the driver still processes its internal
+ *     queue using bus_to_virt() and virt_to_bus() which are illegal under
+ *     the API.  The entire queue processing structure will need to be
+ *     altered to fix this.
+ *  2. Need to add memory mapping workaround. Test the memory mapping.
+ *     If it doesn't work revert to I/O port access. Can a test be done
+ *     safely?
+ *  3. Handle an interrupt not working. Keep an interrupt counter in
+ *     the interrupt handler. In the timeout function if the interrupt
+ *     has not occurred then print a message and run in polled mode.
+ *  4. Need to add support for target mode commands, cf. CAM XPT.
+ *  5. check DMA mapping functions for failure
+ *  6. Use scsi_transport_spi
+ *  7. advansys_info is not safe against multiple simultaneous callers
+ *  8. Add module_param to override ISA/VLB ioport array
  */
-
-/* Enable driver assertions. */
-#define ADVANSYS_ASSERT
+#warning this driver is still not properly converted to the DMA API
 
 /* Enable driver /proc statistics. */
 #define ADVANSYS_STATS
 
 /* Enable driver tracing. */
-/* #define ADVANSYS_DEBUG */
-
-/*
- * --- Asc Library Constants and Macros
- */
-
-#define ASC_LIB_VERSION_MAJOR  1
-#define ASC_LIB_VERSION_MINOR  24
-#define ASC_LIB_SERIAL_NUMBER  123
+#undef ADVANSYS_DEBUG
 
 /*
  * Portable Data Types
 #define ASC_DCNT  __u32                /* Unsigned Data count type. */
 #define ASC_SDCNT __s32                /* Signed Data count type. */
 
-/*
- * These macros are used to convert a virtual address to a
- * 32-bit value. This currently can be used on Linux Alpha
- * which uses 64-bit virtual address but a 32-bit bus address.
- * This is likely to break in the future, but doing this now
- * will give us time to change the HW and FW to handle 64-bit
- * addresses.
- */
-#define ASC_VADDR_TO_U32   virt_to_bus
-#define ASC_U32_TO_VADDR   bus_to_virt
-
 typedef unsigned char uchar;
 
 #ifndef TRUE
@@ -857,29 +99,9 @@ typedef unsigned char uchar;
 #define FALSE    (0)
 #endif
 
-#define EOF      (-1)
 #define ERR      (-1)
 #define UW_ERR   (uint)(0xFFFF)
 #define isodd_word(val)   ((((uint)val) & (uint)0x0001) != 0)
-#define AscPCIConfigVendorIDRegister      0x0000
-#define AscPCIConfigDeviceIDRegister      0x0002
-#define AscPCIConfigCommandRegister       0x0004
-#define AscPCIConfigStatusRegister        0x0006
-#define AscPCIConfigRevisionIDRegister    0x0008
-#define AscPCIConfigCacheSize             0x000C
-#define AscPCIConfigLatencyTimer          0x000D
-#define AscPCIIOBaseRegister              0x0010
-#define AscPCICmdRegBits_IOMemBusMaster   0x0007
-#define ASC_PCI_ID2BUS(id)    ((id) & 0xFF)
-#define ASC_PCI_ID2DEV(id)    (((id) >> 11) & 0x1F)
-#define ASC_PCI_ID2FUNC(id)   (((id) >> 8) & 0x7)
-#define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
-#define ASC_PCI_REVISION_3150             0x02
-#define ASC_PCI_REVISION_3050             0x03
-
-#define  ASC_DVCLIB_CALL_DONE     (1)
-#define  ASC_DVCLIB_CALL_FAILED   (0)
-#define  ASC_DVCLIB_CALL_ERROR    (-1)
 
 #define PCI_VENDOR_ID_ASP              0x10cd
 #define PCI_DEVICE_ID_ASP_1200A                0x1100
@@ -898,7 +120,7 @@ typedef unsigned char uchar;
 #define CC_VERY_LONG_SG_LIST 0
 #define ASC_SRB2SCSIQ(srb_ptr)  (srb_ptr)
 
-#define PortAddr                 unsigned short        /* port address size  */
+#define PortAddr                 unsigned int  /* port address size  */
 #define inp(port)                inb(port)
 #define outp(port, byte)         outb((byte), (port))
 
@@ -918,11 +140,10 @@ typedef unsigned char uchar;
 #define ASC_IS_PCMCIA       (0x0008)
 #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)
@@ -941,16 +162,9 @@ typedef unsigned char uchar;
 #define ASC_CHIP_MAX_VER_EISA (0x47)
 #define ASC_CHIP_VER_EISA_BIT (0x40)
 #define ASC_CHIP_LATEST_VER_EISA   ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
-#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER   0x21
-#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER   0x0A
-#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)
 
 #define ASC_SCSI_ID_BITS  3
 #define ASC_SCSI_TIX_TYPE     uchar
@@ -961,82 +175,17 @@ typedef unsigned char uchar;
 #define ASC_SCSI_WIDTH_BIT_SET  0xFF
 #define ASC_MAX_SENSE_LEN   32
 #define ASC_MIN_SENSE_LEN   14
-#define ASC_MAX_CDB_LEN     12
 #define ASC_SCSI_RESET_HOLD_TIME_US  60
 
-#define ADV_INQ_CLOCKING_ST_ONLY    0x0
-#define ADV_INQ_CLOCKING_DT_ONLY    0x1
-#define ADV_INQ_CLOCKING_ST_AND_DT  0x3
-
 /*
- * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
- * and CmdDt (Command Support Data) field bit definitions.
+ * Narrow boards only support 12-byte commands, while wide boards
+ * extend to 16-byte commands.
  */
-#define ADV_INQ_RTN_VPD_AND_CMDDT           0x3
-#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE       0x2
-#define ADV_INQ_RTN_VPD_FOR_PG_CODE         0x1
-#define ADV_INQ_RTN_STD_INQUIRY_DATA        0x0
-
-#define ASC_SCSIDIR_NOCHK    0x00
-#define ASC_SCSIDIR_T2H      0x08
-#define ASC_SCSIDIR_H2T      0x10
-#define ASC_SCSIDIR_NODATA   0x18
-#define SCSI_ASC_NOMEDIA          0x3A
-#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 MS_CMD_DONE    0x00
-#define MS_EXTEND      0x01
+#define ASC_MAX_CDB_LEN     12
+#define ADV_MAX_CDB_LEN     16
+
 #define MS_SDTR_LEN    0x03
-#define MS_SDTR_CODE   0x01
 #define MS_WDTR_LEN    0x02
-#define MS_WDTR_CODE   0x03
-#define MS_MDP_LEN    0x05
-#define MS_MDP_CODE   0x00
-
-/*
- * Inquiry data structure and bitfield macros
- *
- * Only quantities of more than 1 bit are shifted, since the others are
- * just tested for true or false. C bitfields aren't portable between big
- * and little-endian platforms so they are not used.
- */
-
-#define ASC_INQ_DVC_TYPE(inq)       ((inq)->periph & 0x1f)
-#define ASC_INQ_QUALIFIER(inq)      (((inq)->periph & 0xe0) >> 5)
-#define ASC_INQ_DVC_TYPE_MOD(inq)   ((inq)->devtype & 0x7f)
-#define ASC_INQ_REMOVABLE(inq)      ((inq)->devtype & 0x80)
-#define ASC_INQ_ANSI_VER(inq)       ((inq)->ver & 0x07)
-#define ASC_INQ_ECMA_VER(inq)       (((inq)->ver & 0x38) >> 3)
-#define ASC_INQ_ISO_VER(inq)        (((inq)->ver & 0xc0) >> 6)
-#define ASC_INQ_RESPONSE_FMT(inq)   ((inq)->byte3 & 0x0f)
-#define ASC_INQ_TERM_IO(inq)        ((inq)->byte3 & 0x40)
-#define ASC_INQ_ASYNC_NOTIF(inq)    ((inq)->byte3 & 0x80)
-#define ASC_INQ_SOFT_RESET(inq)     ((inq)->flags & 0x01)
-#define ASC_INQ_CMD_QUEUE(inq)      ((inq)->flags & 0x02)
-#define ASC_INQ_LINK_CMD(inq)       ((inq)->flags & 0x08)
-#define ASC_INQ_SYNC(inq)           ((inq)->flags & 0x10)
-#define ASC_INQ_WIDE16(inq)         ((inq)->flags & 0x20)
-#define ASC_INQ_WIDE32(inq)         ((inq)->flags & 0x40)
-#define ASC_INQ_REL_ADDR(inq)       ((inq)->flags & 0x80)
-#define ASC_INQ_INFO_UNIT(inq)      ((inq)->info & 0x01)
-#define ASC_INQ_QUICK_ARB(inq)      ((inq)->info & 0x02)
-#define ASC_INQ_CLOCKING(inq)       (((inq)->info & 0x0c) >> 2)
-
-typedef struct {
-       uchar periph;
-       uchar devtype;
-       uchar ver;
-       uchar byte3;
-       uchar add_len;
-       uchar res1;
-       uchar res2;
-       uchar flags;
-       uchar vendor_id[8];
-       uchar product_id[16];
-       uchar product_rev_level[4];
-} ASC_SCSI_INQUIRY;
 
 #define ASC_SG_LIST_PER_Q   7
 #define QS_FREE        0x00
@@ -1215,22 +364,9 @@ typedef struct asc_sg_head {
        ushort queue_cnt;
        ushort entry_to_copy;
        ushort res;
-       ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
+       ASC_SG_LIST sg_list[0];
 } ASC_SG_HEAD;
 
-#define ASC_MIN_SG_LIST   2
-
-typedef struct asc_min_sg_head {
-       ushort entry_cnt;
-       ushort queue_cnt;
-       ushort entry_to_copy;
-       ushort res;
-       ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
-} ASC_MIN_SG_HEAD;
-
-#define QCX_SORT        (0x0001)
-#define QCX_COALEASE    (0x0002)
-
 typedef struct asc_scsi_q {
        ASC_SCSIQ_1 q1;
        ASC_SCSIQ_2 q2;
@@ -1287,45 +423,12 @@ typedef struct asc_risc_sg_list_q {
        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
 
 /*
  * Warning code values are set in ASC_DVC_VAR  'warn_code'.
@@ -1338,84 +441,51 @@ typedef struct asc_risc_sg_list_q {
 #define ASC_WARN_CMD_QNG_CONFLICT     0x0010
 #define ASC_WARN_EEPROM_RECOVER       0x0020
 #define ASC_WARN_CFG_MSW_RECOVER      0x0040
-#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
 
 /*
- * Error code values are set in ASC_DVC_VAR  'err_code'.
+ * Error code values are set in {ASC/ADV}_DVC_VAR  'err_code'.
  */
-#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_IERR_NO_CARRIER            0x0001  /* No more carrier memory */
+#define ASC_IERR_MCODE_CHKSUM          0x0002  /* micro code check sum error */
+#define ASC_IERR_SET_PC_ADDR           0x0004
+#define ASC_IERR_START_STOP_CHIP       0x0008  /* start/stop chip failed */
+#define ASC_IERR_ILLEGAL_CONNECTION    0x0010  /* Illegal cable connection */
+#define ASC_IERR_SINGLE_END_DEVICE     0x0020  /* SE device on DIFF bus */
+#define ASC_IERR_REVERSED_CABLE                0x0040  /* Narrow flat cable reversed */
+#define ASC_IERR_SET_SCSI_ID           0x0080  /* set SCSI ID failed */
+#define ASC_IERR_HVD_DEVICE            0x0100  /* HVD device on LVD port */
+#define ASC_IERR_BAD_SIGNATURE         0x0200  /* signature not found */
+#define ASC_IERR_NO_BUS_TYPE           0x0400
+#define ASC_IERR_BIST_PRE_TEST         0x0800  /* BIST pre-test error */
+#define ASC_IERR_BIST_RAM_TEST         0x1000  /* BIST RAM test error */
+#define ASC_IERR_BAD_CHIPTYPE          0x2000  /* Invalid chip_type setting */
+
 #define ASC_DEF_MAX_TOTAL_QNG   (0xF0)
 #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_FREE_Q        (0x02)
 #define ASC_MIN_TOTAL_QNG     ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
 #define ASC_MAX_TOTAL_QNG 240
 #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
 #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG   8
 #define ASC_MAX_PCI_INRAM_TOTAL_QNG  20
 #define ASC_MAX_INRAM_TAG_QNG   16
-#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_LIB_SCSIQ_WK_SP        256
-#define ASC_MAX_SYN_XFER_NO        16
 #define ASC_SYN_MAX_OFFSET         0x0F
 #define ASC_DEF_SDTR_OFFSET        0x0F
-#define ASC_DEF_SDTR_INDEX         0x00
 #define ASC_SDTR_ULTRA_PCI_10MB_INDEX  0x02
-#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 SYN_ULTRA_XFER_NS_0    12
-#define SYN_ULTRA_XFER_NS_1    19
-#define SYN_ULTRA_XFER_NS_2    25
-#define SYN_ULTRA_XFER_NS_3    32
-#define SYN_ULTRA_XFER_NS_4    38
-#define SYN_ULTRA_XFER_NS_5    44
-#define SYN_ULTRA_XFER_NS_6    50
-#define SYN_ULTRA_XFER_NS_7    57
-#define SYN_ULTRA_XFER_NS_8    63
-#define SYN_ULTRA_XFER_NS_9    69
-#define SYN_ULTRA_XFER_NS_10   75
-#define SYN_ULTRA_XFER_NS_11   82
-#define SYN_ULTRA_XFER_NS_12   88
-#define SYN_ULTRA_XFER_NS_13   94
-#define SYN_ULTRA_XFER_NS_14  100
-#define SYN_ULTRA_XFER_NS_15  107
+#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
+
+/* The narrow chip only supports a limited selection of transfer rates.
+ * These are encoded in the range 0..7 or 0..15 depending whether the chip
+ * is Ultra-capable or not.  These tables let us convert from one to the other.
+ */
+static const unsigned char asc_syn_xfer_period[8] = {
+       25, 30, 35, 40, 50, 60, 70, 85
+};
+
+static const unsigned char asc_syn_ultra_xfer_period[16] = {
+       12, 19, 25, 32, 38, 44, 50, 57, 63, 69, 75, 82, 88, 94, 100, 107
+};
 
 typedef struct ext_msg {
        uchar msg_type;
@@ -1456,22 +526,16 @@ typedef struct asc_dvc_cfg {
        uchar isa_dma_speed;
        uchar isa_dma_channel;
        uchar chip_version;
-       ushort lib_serial_no;
-       ushort lib_version;
        ushort mcode_date;
        ushort mcode_version;
        uchar max_tag_qng[ASC_MAX_TID + 1];
-       uchar *overrun_buf;
        uchar sdtr_period_offset[ASC_MAX_TID + 1];
-       ushort pci_slot_info;
        uchar adapter_info[6];
-       struct device *dev;
 } 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
@@ -1484,43 +548,39 @@ typedef struct asc_dvc_cfg {
 #define ASC_INIT_STATE_WITHOUT_EEP   0x8000
 #define ASC_BUG_FIX_IF_NOT_DWB       0x0001
 #define ASC_BUG_FIX_ASYN_USE_SYN     0x0002
-#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
 #define ASC_MIN_TAGGED_CMD  7
 #define ASC_MAX_SCSI_RESET_WAIT      30
+#define ASC_OVERRUN_BSIZE              64
 
 struct asc_dvc_var;            /* Forward Declaration. */
 
-typedef void (*ASC_ISR_CALLBACK) (struct asc_dvc_var *, ASC_QDONE_INFO *);
-typedef int (*ASC_EXE_CALLBACK) (struct asc_dvc_var *, ASC_SCSI_Q *);
-
 typedef struct asc_dvc_var {
        PortAddr iop_base;
        ushort err_code;
        ushort dvc_cntl;
        ushort bug_fix_cntl;
        ushort bus_type;
-       ASC_ISR_CALLBACK isr_callback;
-       ASC_EXE_CALLBACK 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 overrun_buf[ASC_OVERRUN_BSIZE] __aligned(8);
+       dma_addr_t overrun_dma;
        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 *scsiq_busy_head[ASC_MAX_TID + 1];
        ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
-       uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
+       const uchar *sdtr_period_tbl;
        ASC_DVC_CFG *cfg;
        ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
        char redo_scam;
@@ -1529,9 +589,11 @@ typedef struct asc_dvc_var {
        ASC_DCNT max_dma_count;
        ASC_SCSI_BIT_ID_TYPE no_scam;
        ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
+       uchar min_sdtr_index;
        uchar max_sdtr_index;
-       uchar host_init_sdtr_index;
        struct asc_board *drv_ptr;
+       int ptr_map_count;
+       void **ptr_map;
        ASC_DCNT uc_break;
 } ASC_DVC_VAR;
 
@@ -1568,12 +630,7 @@ typedef struct asc_cap_info_array {
 #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
 
 /*
  * These macros keep the chip SCSI id and ISA DMA speed
@@ -1609,17 +666,10 @@ typedef struct asceep_config {
        ushort chksum;
 } ASCEEP_CONFIG;
 
-#define ASC_PCI_CFG_LSW_SCSI_PARITY  0x0800
-#define ASC_PCI_CFG_LSW_BURST_MODE   0x0080
-#define ASC_PCI_CFG_LSW_INTR_ABLE    0x0020
-
 #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 ASC_CTRL_BREAK_ONCE        0x0001
-#define ASC_CTRL_BREAK_STAY_IDLE   0x0002
 #define ASCV_MSGOUT_BEG         0x0000
 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
 #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
@@ -1796,16 +846,9 @@ typedef struct asceep_config {
 #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
@@ -1828,11 +871,10 @@ typedef struct asc_mc_saved {
 #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 AscPutMCodeSDTRDoneAtID(port, id, data)  AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
-#define AscGetMCodeSDTRDoneAtID(port, id)        AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
-#define AscPutMCodeInitSDTRAtID(port, id, data)  AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
-#define AscGetMCodeInitSDTRAtID(port, id)        AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
-#define AscSynIndexToPeriod(index)        (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
+#define AscPutMCodeSDTRDoneAtID(port, id, data)  AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data))
+#define AscGetMCodeSDTRDoneAtID(port, id)        AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id))
+#define AscPutMCodeInitSDTRAtID(port, id, data)  AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data)
+#define AscGetMCodeInitSDTRAtID(port, id)        AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id))
 #define AscGetChipSignatureByte(port)     (uchar)inp((port)+IOP_SIG_BYTE)
 #define AscGetChipSignatureWord(port)     (ushort)inpw((port)+IOP_SIG_WORD)
 #define AscGetChipVerNo(port)             (uchar)inp((port)+IOP_VERSION)
@@ -1887,125 +929,6 @@ typedef struct asc_mc_saved {
 #define AscReadChipDvcID(port)            (uchar)inp((port)+IOP_REG_ID)
 #define AscWriteChipDvcID(port, data)     outp((port)+IOP_REG_ID, data)
 
-static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
-static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
-static void AscWaitEEPRead(void);
-static void AscWaitEEPWrite(void);
-static ushort AscReadEEPWord(PortAddr, uchar);
-static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
-static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
-static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
-static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
-static int AscStartChip(PortAddr);
-static int AscStopChip(PortAddr);
-static void AscSetChipIH(PortAddr, ushort);
-static int AscIsChipHalted(PortAddr);
-static void AscAckInterrupt(PortAddr);
-static void AscDisableInterrupt(PortAddr);
-static void AscEnableInterrupt(PortAddr);
-static void AscSetBank(PortAddr, uchar);
-static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
-#ifdef CONFIG_ISA
-static ushort AscGetIsaDmaChannel(PortAddr);
-static ushort AscSetIsaDmaChannel(PortAddr, ushort);
-static uchar AscSetIsaDmaSpeed(PortAddr, uchar);
-static uchar AscGetIsaDmaSpeed(PortAddr);
-#endif /* CONFIG_ISA */
-static uchar AscReadLramByte(PortAddr, ushort);
-static ushort AscReadLramWord(PortAddr, ushort);
-#if CC_VERY_LONG_SG_LIST
-static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
-#endif /* CC_VERY_LONG_SG_LIST */
-static void AscWriteLramWord(PortAddr, ushort, ushort);
-static void AscWriteLramByte(PortAddr, ushort, uchar);
-static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
-static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
-static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
-static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
-static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
-static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
-static ushort AscInitFromEEP(ASC_DVC_VAR *);
-static ushort AscInitFromAscDvcVar(ASC_DVC_VAR *);
-static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
-static int AscTestExternalLram(ASC_DVC_VAR *);
-static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
-static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
-static void AscSetChipSDTR(PortAddr, uchar, uchar);
-static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
-static uchar AscAllocFreeQueue(PortAddr, uchar);
-static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
-static int AscHostReqRiscHalt(PortAddr);
-static int AscStopQueueExe(PortAddr);
-static int AscSendScsiQueue(ASC_DVC_VAR *,
-                           ASC_SCSI_Q *scsiq, uchar n_q_required);
-static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
-static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
-static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
-static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
-static ushort AscInitLram(ASC_DVC_VAR *);
-static ushort AscInitQLinkVar(ASC_DVC_VAR *);
-static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
-static int AscIsrChipHalted(ASC_DVC_VAR *);
-static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
-                                  ASC_QDONE_INFO *, ASC_DCNT);
-static int AscIsrQDone(ASC_DVC_VAR *);
-static int AscCompareString(uchar *, uchar *, int);
-#ifdef CONFIG_ISA
-static ushort AscGetEisaChipCfg(PortAddr);
-static ASC_DCNT AscGetEisaProductID(PortAddr);
-static PortAddr AscSearchIOPortAddrEISA(PortAddr);
-static PortAddr AscSearchIOPortAddr11(PortAddr);
-static PortAddr AscSearchIOPortAddr(PortAddr, ushort);
-static void AscSetISAPNPWaitForKey(void);
-#endif /* CONFIG_ISA */
-static uchar AscGetChipScsiCtrl(PortAddr);
-static uchar AscSetChipScsiID(PortAddr, uchar);
-static uchar AscGetChipVersion(PortAddr, ushort);
-static ushort AscGetChipBusType(PortAddr);
-static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
-static int AscFindSignature(PortAddr);
-static void AscToggleIRQAct(PortAddr);
-static uchar AscGetChipIRQ(PortAddr, ushort);
-static uchar AscSetChipIRQ(PortAddr, uchar, ushort);
-static ushort AscGetChipBiosAddress(PortAddr, ushort);
-static inline ulong DvcEnterCritical(void);
-static inline void DvcLeaveCritical(ulong);
-#ifdef CONFIG_PCI
-static uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort);
-static void DvcWritePCIConfigByte(ASC_DVC_VAR *, ushort, uchar);
-#endif /* CONFIG_PCI */
-static ushort AscGetChipBiosAddress(PortAddr, ushort);
-static void DvcSleepMilliSecond(ASC_DCNT);
-static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT);
-static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
-static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
-static ushort AscInitGetConfig(ASC_DVC_VAR *);
-static ushort AscInitSetConfig(ASC_DVC_VAR *);
-static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
-static void AscAsyncFix(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *);
-static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
-static void AscInquiryHandling(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *);
-static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
-static int AscISR(ASC_DVC_VAR *);
-static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
-static int AscSgListToQueue(int);
-#ifdef CONFIG_ISA
-static void AscEnableIsaDma(uchar);
-#endif /* CONFIG_ISA */
-static ASC_DCNT AscGetMaxDmaCount(ushort);
-static const char *advansys_info(struct Scsi_Host *shost);
-
-/*
- * --- Adv Library Constants and Macros
- */
-
-#define ADV_LIB_VERSION_MAJOR  5
-#define ADV_LIB_VERSION_MINOR  14
-
-/*
- * Define Adv Library required special types.
- */
-
 /*
  * Portable Data Types
  *
@@ -2044,12 +967,6 @@ static const char *advansys_info(struct Scsi_Host *shost);
 
 #define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
 
-/*
- * For wide  boards a CDB length maximum of 16 bytes
- * is supported.
- */
-#define ADV_MAX_CDB_LEN     16
-
 /*
  * Define total number of simultaneous maximum element scatter-gather
  * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
@@ -2058,28 +975,14 @@ static const char *advansys_info(struct Scsi_Host *shost);
  * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
  * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
  * structures or 255 scatter-gather elements.
- *
  */
 #define ADV_TOT_SG_BLOCK        ASC_DEF_MAX_HOST_QNG
 
 /*
- * Define Adv Library required maximum number of scatter-gather
- * elements per request.
+ * Define maximum number of scatter-gather elements per request.
  */
 #define ADV_MAX_SG_LIST         255
-
-/* Number of SG blocks needed. */
-#define ADV_NUM_SG_BLOCK \
-    ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
-
-/* Total contiguous memory needed for SG blocks. */
-#define ADV_SG_TOTAL_MEM_SIZE \
-    (sizeof(ADV_SG_BLOCK) *  ADV_NUM_SG_BLOCK)
-
-#define ADV_PAGE_SIZE PAGE_SIZE
-
-#define ADV_NUM_PAGE_CROSSING \
-    ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
+#define NO_OF_SG_PER_BLOCK              15
 
 #define ADV_EEP_DVC_CFG_BEGIN           (0x00)
 #define ADV_EEP_DVC_CFG_END             (0x15)
@@ -2385,10 +1288,6 @@ typedef struct adveep_38C1600_config {
  * EEPROM Commands
  */
 #define ASC_EEP_CMD_DONE             0x0200
-#define ASC_EEP_CMD_DONE_ERR         0x0001
-
-/* cfg_word */
-#define EEP_CFG_WORD_BIG_ENDIAN      0x8000
 
 /* bios_ctrl */
 #define BIOS_CTRL_BIOS               0x0001
@@ -2405,10 +1304,8 @@ typedef struct adveep_38C1600_config {
 #define BIOS_CTRL_AIPP_DIS           0x2000
 
 #define ADV_3550_MEMSIZE   0x2000      /* 8 KB Internal Memory */
-#define ADV_3550_IOLEN     0x40        /* I/O Port Range in bytes */
 
 #define ADV_38C0800_MEMSIZE  0x4000    /* 16 KB Internal Memory */
-#define ADV_38C0800_IOLEN    0x100     /* I/O Port Range in bytes */
 
 /*
  * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
@@ -2418,8 +1315,6 @@ typedef struct adveep_38C1600_config {
  * #define ADV_38C1600_MEMSIZE  0x8000L   * 32 KB Internal Memory *
  */
 #define ADV_38C1600_MEMSIZE  0x4000    /* 16 KB Internal Memory */
-#define ADV_38C1600_IOLEN    0x100     /* I/O Port Range 256 bytes */
-#define ADV_38C1600_MEMLEN   0x1000    /* Memory Range 4KB bytes */
 
 /*
  * Byte I/O register address from base of 'iop_base'.
@@ -2549,8 +1444,6 @@ typedef struct adveep_38C1600_config {
 #define ADV_CHIP_ID_BYTE         0x25
 #define ADV_CHIP_ID_WORD         0x04C1
 
-#define ADV_SC_SCSI_BUS_RESET    0x2000
-
 #define ADV_INTR_ENABLE_HOST_INTR                   0x01
 #define ADV_INTR_ENABLE_SEL_INTR                    0x02
 #define ADV_INTR_ENABLE_DPR_INTR                    0x04
@@ -2590,8 +1483,6 @@ typedef struct adveep_38C1600_config {
 #define ADV_TICKLE_B                        0x02
 #define ADV_TICKLE_C                        0x03
 
-#define ADV_SCSI_CTRL_RSTOUT        0x2000
-
 #define AdvIsIntPending(port) \
     (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
 
@@ -2744,14 +1635,11 @@ typedef struct adveep_38C1600_config {
  */
 #define INTAB           0x01
 
-/* a_advlib.h */
-
 /*
  * Adv Library Status Definitions
  */
 #define ADV_TRUE        1
 #define ADV_FALSE       0
-#define ADV_NOERROR     1
 #define ADV_SUCCESS     1
 #define ADV_BUSY        0
 #define ADV_ERROR       (-1)
@@ -2762,30 +1650,11 @@ typedef struct adveep_38C1600_config {
 #define ASC_WARN_BUSRESET_ERROR         0x0001 /* SCSI Bus Reset error */
 #define ASC_WARN_EEPROM_CHKSUM          0x0002 /* EEP check sum error */
 #define ASC_WARN_EEPROM_TERMINATION     0x0004 /* EEP termination bad field */
-#define ASC_WARN_SET_PCI_CONFIG_SPACE   0x0080 /* PCI config space set error */
 #define ASC_WARN_ERROR                  0xFFFF /* ADV_ERROR return */
 
 #define ADV_MAX_TID                     15     /* max. target identifier */
 #define ADV_MAX_LUN                     7      /* max. logical unit number */
 
-/*
- * Error code values are set in ADV_DVC_VAR 'err_code'.
- */
-#define ASC_IERR_WRITE_EEPROM       0x0001     /* write EEPROM error */
-#define ASC_IERR_MCODE_CHKSUM       0x0002     /* micro code check sum error */
-#define ASC_IERR_NO_CARRIER         0x0004     /* No more carrier memory. */
-#define ASC_IERR_START_STOP_CHIP    0x0008     /* start/stop chip failed */
-#define ASC_IERR_CHIP_VERSION       0x0040     /* wrong chip version */
-#define ASC_IERR_SET_SCSI_ID        0x0080     /* set SCSI ID failed */
-#define ASC_IERR_HVD_DEVICE         0x0100     /* HVD attached to LVD connector. */
-#define ASC_IERR_BAD_SIGNATURE      0x0200     /* signature not found */
-#define ASC_IERR_ILLEGAL_CONNECTION 0x0400     /* Illegal cable connection */
-#define ASC_IERR_SINGLE_END_DEVICE  0x0800     /* Single-end used w/differential */
-#define ASC_IERR_REVERSED_CABLE     0x1000     /* Narrow flat cable reversed */
-#define ASC_IERR_BIST_PRE_TEST      0x2000     /* BIST pre-test error */
-#define ASC_IERR_BIST_RAM_TEST      0x4000     /* BIST RAM test error */
-#define ASC_IERR_BAD_CHIPTYPE       0x8000     /* Invalid 'chip_type' setting. */
-
 /*
  * Fixed locations of microcode operating variables.
  */
@@ -2902,8 +1771,7 @@ typedef struct adv_carr_t {
 #define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
 
 #define ADV_CARRIER_NUM_PAGE_CROSSING \
-    (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
-        (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
+    (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + (PAGE_SIZE - 1))/PAGE_SIZE)
 
 #define ADV_CARRIER_BUFSIZE \
     ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
@@ -2937,80 +1805,17 @@ typedef struct adv_dvc_cfg {
        ushort disc_enable;     /* enable disconnection */
        uchar chip_version;     /* chip version */
        uchar termination;      /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
-       ushort lib_version;     /* Adv Library version number */
        ushort control_flag;    /* Microcode Control Flag */
        ushort mcode_date;      /* Microcode date */
        ushort mcode_version;   /* Microcode version */
-       ushort pci_slot_info;   /* high byte device/function number */
-       /* bits 7-3 device num., bits 2-0 function num. */
-       /* low byte bus num. */
        ushort serial1;         /* EEPROM serial number word 1 */
        ushort serial2;         /* EEPROM serial number word 2 */
        ushort serial3;         /* EEPROM serial number word 3 */
-       struct device *dev;     /* pointer to the pci dev structure for this board */
 } ADV_DVC_CFG;
 
 struct adv_dvc_var;
 struct adv_scsi_req_q;
 
-typedef void (*ADV_ISR_CALLBACK)
- (struct adv_dvc_var *, struct adv_scsi_req_q *);
-
-typedef void (*ADV_ASYNC_CALLBACK)
- (struct adv_dvc_var *, uchar);
-
-/*
- * Adapter operation variable structure.
- *
- * One structure is required per host adapter.
- *
- * Field naming convention:
- *
- *  *_able indicates both whether a feature should be enabled or disabled
- *  and whether a device isi capable of the feature. At initialization
- *  this field may be set, but later if a device is found to be incapable
- *  of the feature, the field is cleared.
- */
-typedef struct adv_dvc_var {
-       AdvPortAddr iop_base;   /* I/O port address */
-       ushort err_code;        /* fatal error code */
-       ushort bios_ctrl;       /* BIOS control word, EEPROM word 12 */
-       ADV_ISR_CALLBACK isr_callback;
-       ADV_ASYNC_CALLBACK async_callback;
-       ushort wdtr_able;       /* try WDTR for a device */
-       ushort sdtr_able;       /* try SDTR for a device */
-       ushort ultra_able;      /* try SDTR Ultra speed for a device */
-       ushort sdtr_speed1;     /* EEPROM SDTR Speed for TID 0-3   */
-       ushort sdtr_speed2;     /* EEPROM SDTR Speed for TID 4-7   */
-       ushort sdtr_speed3;     /* EEPROM SDTR Speed for TID 8-11  */
-       ushort sdtr_speed4;     /* EEPROM SDTR Speed for TID 12-15 */
-       ushort tagqng_able;     /* try tagged queuing with a device */
-       ushort ppr_able;        /* PPR message capable per TID bitmask. */
-       uchar max_dvc_qng;      /* maximum number of tagged commands per device */
-       ushort start_motor;     /* start motor command allowed */
-       uchar scsi_reset_wait;  /* delay in seconds after scsi bus reset */
-       uchar chip_no;          /* should be assigned by caller */
-       uchar max_host_qng;     /* maximum number of Q'ed command allowed */
-       uchar irq_no;           /* IRQ number */
-       ushort no_scam;         /* scam_tolerant of EEPROM */
-       struct asc_board *drv_ptr;      /* driver pointer to private structure */
-       uchar chip_scsi_id;     /* chip SCSI target ID */
-       uchar chip_type;
-       uchar bist_err_code;
-       ADV_CARR_T *carrier_buf;
-       ADV_CARR_T *carr_freelist;      /* Carrier free list. */
-       ADV_CARR_T *icq_sp;     /* Initiator command queue stopper pointer. */
-       ADV_CARR_T *irq_sp;     /* Initiator response queue stopper pointer. */
-       ushort carr_pending_cnt;        /* Count of pending carriers. */
-       /*
-        * Note: The following fields will not be used after initialization. The
-        * driver may discard the buffer after initialization is done.
-        */
-       ADV_DVC_CFG *cfg;       /* temporary configuration structure  */
-} ADV_DVC_VAR;
-
-#define NO_OF_SG_PER_BLOCK              15
-
 typedef struct asc_sg_block {
        uchar reserved1;
        uchar reserved2;
@@ -3068,6 +1873,83 @@ typedef struct adv_scsi_req_q {
        uchar pad[2];           /* Pad out to a word boundary. */
 } ADV_SCSI_REQ_Q;
 
+/*
+ * The following two structures are used to process Wide Board requests.
+ *
+ * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
+ * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
+ * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
+ * Mid-Level SCSI request structure.
+ *
+ * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
+ * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
+ * up to 255 scatter-gather elements may be used per request or
+ * ADV_SCSI_REQ_Q.
+ *
+ * Both structures must be 32 byte aligned.
+ */
+typedef struct adv_sgblk {
+       ADV_SG_BLOCK sg_block;  /* Sgblock structure. */
+       uchar align[32];        /* Sgblock structure padding. */
+       struct adv_sgblk *next_sgblkp;  /* Next scatter-gather structure. */
+} adv_sgblk_t;
+
+typedef struct adv_req {
+       ADV_SCSI_REQ_Q scsi_req_q;      /* Adv Library request structure. */
+       uchar align[32];        /* Request structure padding. */
+       struct scsi_cmnd *cmndp;        /* Mid-Level SCSI command pointer. */
+       adv_sgblk_t *sgblkp;    /* Adv Library scatter-gather pointer. */
+       struct adv_req *next_reqp;      /* Next Request Structure. */
+} adv_req_t;
+
+/*
+ * Adapter operation variable structure.
+ *
+ * One structure is required per host adapter.
+ *
+ * Field naming convention:
+ *
+ *  *_able indicates both whether a feature should be enabled or disabled
+ *  and whether a device isi capable of the feature. At initialization
+ *  this field may be set, but later if a device is found to be incapable
+ *  of the feature, the field is cleared.
+ */
+typedef struct adv_dvc_var {
+       AdvPortAddr iop_base;   /* I/O port address */
+       ushort err_code;        /* fatal error code */
+       ushort bios_ctrl;       /* BIOS control word, EEPROM word 12 */
+       ushort wdtr_able;       /* try WDTR for a device */
+       ushort sdtr_able;       /* try SDTR for a device */
+       ushort ultra_able;      /* try SDTR Ultra speed for a device */
+       ushort sdtr_speed1;     /* EEPROM SDTR Speed for TID 0-3   */
+       ushort sdtr_speed2;     /* EEPROM SDTR Speed for TID 4-7   */
+       ushort sdtr_speed3;     /* EEPROM SDTR Speed for TID 8-11  */
+       ushort sdtr_speed4;     /* EEPROM SDTR Speed for TID 12-15 */
+       ushort tagqng_able;     /* try tagged queuing with a device */
+       ushort ppr_able;        /* PPR message capable per TID bitmask. */
+       uchar max_dvc_qng;      /* maximum number of tagged commands per device */
+       ushort start_motor;     /* start motor command allowed */
+       uchar scsi_reset_wait;  /* delay in seconds after scsi bus reset */
+       uchar chip_no;          /* should be assigned by caller */
+       uchar max_host_qng;     /* maximum number of Q'ed command allowed */
+       ushort no_scam;         /* scam_tolerant of EEPROM */
+       struct asc_board *drv_ptr;      /* driver pointer to private structure */
+       uchar chip_scsi_id;     /* chip SCSI target ID */
+       uchar chip_type;
+       uchar bist_err_code;
+       ADV_CARR_T *carrier_buf;
+       ADV_CARR_T *carr_freelist;      /* Carrier free list. */
+       ADV_CARR_T *icq_sp;     /* Initiator command queue stopper pointer. */
+       ADV_CARR_T *irq_sp;     /* Initiator response queue stopper pointer. */
+       ushort carr_pending_cnt;        /* Count of pending carriers. */
+       struct adv_req *orig_reqp;      /* adv_req_t memory block. */
+       /*
+        * Note: The following fields will not be used after initialization. The
+        * driver may discard the buffer after initialization is done.
+        */
+       ADV_DVC_CFG *cfg;       /* temporary configuration structure  */
+} ADV_DVC_VAR;
+
 /*
  * Microcode idle loop commands
  */
@@ -3092,10 +1974,8 @@ typedef struct adv_scsi_req_q {
 /*
  * Wait loop time out values.
  */
-#define SCSI_WAIT_10_SEC             10UL      /* 10 seconds */
 #define SCSI_WAIT_100_MSEC           100UL     /* 100 milliseconds */
 #define SCSI_US_PER_MSEC             1000      /* microseconds per millisecond */
-#define SCSI_MS_PER_SEC              1000UL    /* milliseconds per second */
 #define SCSI_MAX_RETRY               10        /* retry count */
 
 #define ADV_ASYNC_RDMA_FAILURE          0x01   /* Fatal RDMA failure. */
@@ -3105,53 +1985,6 @@ typedef struct adv_scsi_req_q {
 
 #define ADV_HOST_SCSI_BUS_RESET      0x80      /* Host Initiated SCSI Bus Reset. */
 
-/*
- * Device drivers must define the following functions.
- */
-static inline ulong DvcEnterCritical(void);
-static inline void DvcLeaveCritical(ulong);
-static void DvcSleepMilliSecond(ADV_DCNT);
-static uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
-static void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
-static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
-                              uchar *, ASC_SDCNT *, int);
-static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
-
-/*
- * Adv Library functions available to drivers.
- */
-static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
-static int AdvISR(ADV_DVC_VAR *);
-static int AdvInitGetConfig(ADV_DVC_VAR *);
-static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
-static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
-static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
-static int AdvResetChipAndSB(ADV_DVC_VAR *);
-static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
-
-/*
- * Internal Adv Library functions.
- */
-static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
-static void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
-static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
-static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
-static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
-static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
-static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
-static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
-static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
-static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
-static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
-static void AdvWaitEEPCmd(AdvPortAddr);
-static ushort AdvReadEEPWord(AdvPortAddr, int);
-
-/*
- * PCI Bus Definitions
- */
-#define AscPCICmdRegBits_BusMastering     0x0007
-#define AscPCICmdRegBits_ParErrRespCtrl   0x0040
-
 /* Read byte from a register. */
 #define AdvReadByteRegister(iop_base, reg_off) \
      (ADV_MEM_READB((iop_base) + (reg_off)))
@@ -3319,23 +2152,6 @@ do { \
 #define QHSTA_M_FROZEN_TIDQ         0x46       /* TID Queue frozen. */
 #define QHSTA_M_SGBACKUP_ERROR      0x47       /* Scatter-Gather backup error */
 
-/*
- * Default EEPROM Configuration structure defined in a_init.c.
- */
-static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
-static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
-static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
-
-/*
- * DvcGetPhyAddr() flag arguments
- */
-#define ADV_IS_SCSIQ_FLAG       0x01   /* 'addr' is ASC_SCSI_REQ_Q pointer */
-#define ADV_ASCGETSGLIST_VADDR  0x02   /* 'addr' is AscGetSGList() virtual addr */
-#define ADV_IS_SENSE_FLAG       0x04   /* 'addr' is sense virtual pointer */
-#define ADV_IS_DATA_FLAG        0x08   /* 'addr' is data virtual pointer */
-#define ADV_IS_SGLIST_FLAG      0x10   /* 'addr' is sglist virtual pointer */
-#define ADV_IS_CARRIER_FLAG     0x20   /* 'addr' is ADV_CARR_T pointer */
-
 /* Return the address that is aligned at the next doubleword >= to 'addr'. */
 #define ADV_8BALIGN(addr)      (((ulong) (addr) + 0x7) & ~0x7)
 #define ADV_16BALIGN(addr)     (((ulong) (addr) + 0xF) & ~0xF)
@@ -3353,92 +2169,10 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
          (sizeof(ADV_SG_BLOCK) * \
           ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
 
-/*
- * Inquiry data structure and bitfield macros
- *
- * Using bitfields to access the subchar data isn't portable across
- * endianness, so instead mask and shift. Only quantities of more
- * than 1 bit are shifted, since the others are just tested for true
- * or false.
- */
-
-#define ADV_INQ_DVC_TYPE(inq)       ((inq)->periph & 0x1f)
-#define ADV_INQ_QUALIFIER(inq)      (((inq)->periph & 0xe0) >> 5)
-#define ADV_INQ_DVC_TYPE_MOD(inq)   ((inq)->devtype & 0x7f)
-#define ADV_INQ_REMOVABLE(inq)      ((inq)->devtype & 0x80)
-#define ADV_INQ_ANSI_VER(inq)       ((inq)->ver & 0x07)
-#define ADV_INQ_ECMA_VER(inq)       (((inq)->ver & 0x38) >> 3)
-#define ADV_INQ_ISO_VER(inq)        (((inq)->ver & 0xc0) >> 6)
-#define ADV_INQ_RESPONSE_FMT(inq)   ((inq)->byte3 & 0x0f)
-#define ADV_INQ_TERM_IO(inq)        ((inq)->byte3 & 0x40)
-#define ADV_INQ_ASYNC_NOTIF(inq)    ((inq)->byte3 & 0x80)
-#define ADV_INQ_SOFT_RESET(inq)     ((inq)->flags & 0x01)
-#define ADV_INQ_CMD_QUEUE(inq)      ((inq)->flags & 0x02)
-#define ADV_INQ_LINK_CMD(inq)       ((inq)->flags & 0x08)
-#define ADV_INQ_SYNC(inq)           ((inq)->flags & 0x10)
-#define ADV_INQ_WIDE16(inq)         ((inq)->flags & 0x20)
-#define ADV_INQ_WIDE32(inq)         ((inq)->flags & 0x40)
-#define ADV_INQ_REL_ADDR(inq)       ((inq)->flags & 0x80)
-#define ADV_INQ_INFO_UNIT(inq)      ((inq)->info & 0x01)
-#define ADV_INQ_QUICK_ARB(inq)      ((inq)->info & 0x02)
-#define ADV_INQ_CLOCKING(inq)       (((inq)->info & 0x0c) >> 2)
-
-typedef struct {
-       uchar periph;           /* peripheral device type [0:4] */
-       /* peripheral qualifier [5:7] */
-       uchar devtype;          /* device type modifier (for SCSI I) [0:6] */
-       /* RMB - removable medium bit [7] */
-       uchar ver;              /* ANSI approved version [0:2] */
-       /* ECMA version [3:5] */
-       /* ISO version [6:7] */
-       uchar byte3;            /* response data format [0:3] */
-       /* 0 SCSI 1 */
-       /* 1 CCS */
-       /* 2 SCSI-2 */
-       /* 3-F reserved */
-       /* reserved [4:5] */
-       /* terminate I/O process bit (see 5.6.22) [6] */
-       /* asynch. event notification (processor) [7] */
-       uchar add_len;          /* additional length */
-       uchar res1;             /* reserved */
-       uchar res2;             /* reserved */
-       uchar flags;            /* soft reset implemented [0] */
-       /* command queuing [1] */
-       /* reserved [2] */
-       /* linked command for this logical unit [3] */
-       /* synchronous data transfer [4] */
-       /* wide bus 16 bit data transfer [5] */
-       /* wide bus 32 bit data transfer [6] */
-       /* relative addressing mode [7] */
-       uchar vendor_id[8];     /* vendor identification */
-       uchar product_id[16];   /* product identification */
-       uchar product_rev_level[4];     /* product revision level */
-       uchar vendor_specific[20];      /* vendor specific */
-       uchar info;             /* information unit supported [0] */
-       /* quick arbitrate supported [1] */
-       /* clocking field [2:3] */
-       /* reserved [4:7] */
-       uchar res3;             /* reserved */
-} ADV_SCSI_INQUIRY;            /* 58 bytes */
-
-/*
- * --- Driver Constants and Macros
- */
-
-#define ASC_NUM_BOARD_SUPPORTED 16
-#define ASC_NUM_IOPORT_PROBE    4
-#define ASC_NUM_BUS             4
-
-/* Reference Scsi_Host hostdata */
-#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
-
-/* asc_board_t flags */
-#define ASC_HOST_IN_RESET       0x01
+/* struct asc_board flags */
 #define ASC_IS_WIDE_BOARD       0x04   /* AdvanSys Wide Board */
-#define ASC_SELECT_QUEUE_DEPTHS 0x08
 
 #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
-#define ASC_WIDE_BOARD(boardp)   ((boardp)->flags & ASC_IS_WIDE_BOARD)
 
 #define NO_ISA_DMA              0xff   /* No ISA DMA Channel Used */
 
@@ -3473,82 +2207,14 @@ typedef struct {
 #define HOST_BYTE(byte)     ((byte) << 16)
 #define DRIVER_BYTE(byte)   ((byte) << 24)
 
-/*
- * The following definitions and macros are OS independent interfaces to
- * the queue functions:
- *  REQ - SCSI request structure
- *  REQP - pointer to SCSI request structure
- *  REQPTID(reqp) - reqp's target id
- *  REQPNEXT(reqp) - reqp's next pointer
- *  REQPNEXTP(reqp) - pointer to reqp's next pointer
- *  REQPTIME(reqp) - reqp's time stamp value
- *  REQTIMESTAMP() - system time stamp value
- */
-typedef struct scsi_cmnd REQ, *REQP;
-#define REQPNEXT(reqp)       ((REQP) ((reqp)->host_scribble))
-#define REQPNEXTP(reqp)      ((REQP *) &((reqp)->host_scribble))
-#define REQPTID(reqp)        ((reqp)->device->id)
-#define REQPTIME(reqp)       ((reqp)->SCp.this_residual)
-#define REQTIMESTAMP()       (jiffies)
-
-#define REQTIMESTAT(function, ascq, reqp, tid) \
-{ \
-    /*
-     * If the request time stamp is less than the system time stamp, then \
-     * maybe the system time stamp wrapped. Set the request time to zero.\
-     */ \
-    if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
-        REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
-    } else { \
-        /* Indicate an error occurred with the assertion. */ \
-        ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
-        REQPTIME(reqp) = 0; \
-    } \
-    /* Handle first minimum time case without external initialization. */ \
-    if (((ascq)->q_tot_cnt[tid] == 1) ||  \
-        (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
-            (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
-            ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
-                (function), (tid), (ascq)->q_min_tim[tid]); \
-        } \
-    if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
-        (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
-        ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
-            (function), tid, (ascq)->q_max_tim[tid]); \
-    } \
-    (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
-    /* Reset the time stamp field. */ \
-    REQPTIME(reqp) = 0; \
-}
-
-/* asc_enqueue() flags */
-#define ASC_FRONT       1
-#define ASC_BACK        2
-
-/* asc_dequeue_list() argument */
-#define ASC_TID_ALL        (-1)
-
-/* Return non-zero, if the queue is empty. */
-#define ASC_QUEUE_EMPTY(ascq)    ((ascq)->q_tidmask == 0)
-
-#define PCI_MAX_SLOT            0x1F
-#define PCI_MAX_BUS             0xFF
-#define PCI_IOADDRESS_MASK      0xFFFE
-#define ASC_PCI_DEVICE_ID_CNT   6      /* PCI Device ID count. */
-
+#define ASC_STATS(shost, counter) ASC_STATS_ADD(shost, counter, 1)
 #ifndef ADVANSYS_STATS
-#define ASC_STATS(shost, counter)
 #define ASC_STATS_ADD(shost, counter, count)
 #else /* ADVANSYS_STATS */
-#define ASC_STATS(shost, counter) \
-    (ASC_BOARDP(shost)->asc_stats.counter++)
-
 #define ASC_STATS_ADD(shost, counter, count) \
-    (ASC_BOARDP(shost)->asc_stats.counter += (count))
+       (((struct asc_board *) shost_priv(shost))->asc_stats.counter += (count))
 #endif /* ADVANSYS_STATS */
 
-#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
-
 /* If the result wraps when calculating tenths, return 0. */
 #define ASC_TENTHS(num, den) \
     (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
@@ -3589,13 +2255,8 @@ typedef struct scsi_cmnd REQ, *REQP;
 
 #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(lvl, s...)
 #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
-#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
@@ -3614,40 +2275,11 @@ typedef struct scsi_cmnd REQ, *REQP;
  * 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(lvl, format, arg...) {                                 \
+       if (asc_dbglvl >= (lvl))                                        \
+               printk(KERN_DEBUG "%s: %s: " format, DRV_NAME,          \
+                       __FUNCTION__ , ## arg);                         \
+}
 
 #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
     { \
@@ -3656,13 +2288,6 @@ typedef struct scsi_cmnd REQ, *REQP;
         } \
     }
 
-#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            asc_prt_scsi_cmnd(s); \
-        } \
-    }
-
 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
     { \
         if (asc_dbglvl >= (lvl)) { \
@@ -3701,24 +2326,6 @@ typedef struct scsi_cmnd REQ, *REQP;
         ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
 #endif /* ADVANSYS_DEBUG */
 
-#ifndef ADVANSYS_ASSERT
-#define ASC_ASSERT(a)
-#else /* ADVANSYS_ASSERT */
-
-#define ASC_ASSERT(a) \
-    { \
-        if (!(a)) { \
-            printk("ASC_ASSERT() Failure: file %s, line %d\n", \
-                __FILE__, __LINE__); \
-        } \
-    }
-
-#endif /* ADVANSYS_ASSERT */
-
-/*
- * --- Driver Structures
- */
-
 #ifdef ADVANSYS_STATS
 
 /* Per board statistics structure */
@@ -3739,72 +2346,23 @@ struct asc_stats {
        ADV_DCNT exe_error;     /* # ASC_ERROR returns. */
        ADV_DCNT exe_unknown;   /* # unknown returns. */
        /* Data Transfer Statistics */
-       ADV_DCNT cont_cnt;      /* # non-scatter-gather I/O requests received */
-       ADV_DCNT cont_xfer;     /* # contiguous transfer 512-bytes */
-       ADV_DCNT sg_cnt;        /* # scatter-gather I/O requests received */
-       ADV_DCNT sg_elem;       /* # scatter-gather elements */
-       ADV_DCNT sg_xfer;       /* # scatter-gather transfer 512-bytes */
+       ADV_DCNT xfer_cnt;      /* # I/O requests received */
+       ADV_DCNT xfer_elem;     /* # scatter-gather elements */
+       ADV_DCNT xfer_sect;     /* # 512-byte blocks */
 };
 #endif /* ADVANSYS_STATS */
 
-/*
- * Request queuing structure
- */
-typedef struct asc_queue {
-       ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
-       REQP q_first[ADV_MAX_TID + 1];  /* first queued request */
-       REQP q_last[ADV_MAX_TID + 1];   /* last queued request */
-#ifdef ADVANSYS_STATS
-       short q_cur_cnt[ADV_MAX_TID + 1];       /* current queue count */
-       short q_max_cnt[ADV_MAX_TID + 1];       /* maximum queue count */
-       ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1];    /* total enqueue count */
-       ADV_DCNT q_tot_tim[ADV_MAX_TID + 1];    /* total time queued */
-       ushort q_max_tim[ADV_MAX_TID + 1];      /* maximum time queued */
-       ushort q_min_tim[ADV_MAX_TID + 1];      /* minimum time queued */
-#endif                         /* ADVANSYS_STATS */
-} asc_queue_t;
-
-/*
- * Adv Library Request Structures
- *
- * The following two structures are used to process Wide Board requests.
- *
- * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
- * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
- * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
- * Mid-Level SCSI request structure.
- *
- * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
- * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
- * up to 255 scatter-gather elements may be used per request or
- * ADV_SCSI_REQ_Q.
- *
- * Both structures must be 32 byte aligned.
- */
-typedef struct adv_sgblk {
-       ADV_SG_BLOCK sg_block;  /* Sgblock structure. */
-       uchar align[32];        /* Sgblock structure padding. */
-       struct adv_sgblk *next_sgblkp;  /* Next scatter-gather structure. */
-} adv_sgblk_t;
-
-typedef struct adv_req {
-       ADV_SCSI_REQ_Q scsi_req_q;      /* Adv Library request structure. */
-       uchar align[32];        /* Request structure padding. */
-       struct scsi_cmnd *cmndp;        /* Mid-Level SCSI command pointer. */
-       adv_sgblk_t *sgblkp;    /* Adv Library scatter-gather pointer. */
-       struct adv_req *next_reqp;      /* Next Request Structure. */
-} adv_req_t;
-
 /*
  * Structure allocated for each board.
  *
- * This structure is allocated by scsi_register() at the end
+ * This structure is allocated by scsi_host_alloc() at the end
  * of the 'Scsi_Host' structure starting at the 'hostdata'
  * field. It is guaranteed to be allocated from DMA-able memory.
  */
-typedef struct asc_board {
-       int id;                 /* Board Id */
+struct asc_board {
+       struct device *dev;
        uint flags;             /* Board flags */
+       unsigned int irq;
        union {
                ASC_DVC_VAR asc_dvc_var;        /* Narrow board */
                ADV_DVC_VAR adv_dvc_var;        /* Wide board */
@@ -3814,11 +2372,7 @@ typedef struct asc_board {
                ADV_DVC_CFG adv_dvc_cfg;        /* Wide board */
        } dvc_cfg;
        ushort asc_n_io_port;   /* Number I/O ports. */
-       asc_queue_t active;     /* Active command queue */
-       asc_queue_t waiting;    /* Waiting command queue */
-       asc_queue_t done;       /* Done command queue */
        ADV_SCSI_BIT_ID_TYPE init_tidmask;      /* Target init./valid mask */
-       struct scsi_device *device[ADV_MAX_TID + 1];    /* Mid-Level Scsi Device */
        ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
        ADV_SCSI_BIT_ID_TYPE queue_full;        /* Queue full mask */
        ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
@@ -3829,2413 +2383,1679 @@ typedef struct asc_board {
                ADVEEP_38C1600_CONFIG adv_38C1600_eep;  /* 38C1600 EEPROM config. */
        } eep_config;
        ulong last_reset;       /* Saved last reset time */
-       spinlock_t lock;        /* Board spinlock */
-#ifdef CONFIG_PROC_FS
        /* /proc/scsi/advansys/[0...] */
        char *prtbuf;           /* /proc print buffer */
-#endif                         /* CONFIG_PROC_FS */
 #ifdef ADVANSYS_STATS
        struct asc_stats asc_stats;     /* Board statistics */
 #endif                         /* ADVANSYS_STATS */
        /*
         * The following fields are used only for Narrow Boards.
         */
-       /* The following three structures must be in DMA-able memory. */
-       ASC_SCSI_REQ_Q scsireqq;
-       ASC_CAP_INFO cap_info;
-       ASC_SCSI_INQUIRY inquiry;
        uchar sdtr_data[ASC_MAX_TID + 1];       /* SDTR information */
        /*
         * The following fields are used only for Wide Boards.
         */
        void __iomem *ioremap_addr;     /* I/O Memory remap address. */
        ushort ioport;          /* I/O Port address. */
-       ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */
-       adv_req_t *orig_reqp;   /* adv_req_t memory block. */
        adv_req_t *adv_reqp;    /* Request structures. */
        adv_sgblk_t *adv_sgblkp;        /* Scatter-gather structures. */
        ushort bios_signature;  /* BIOS Signature. */
        ushort bios_version;    /* BIOS Version. */
        ushort bios_codeseg;    /* BIOS Code Segment. */
        ushort bios_codelen;    /* BIOS Code Segment Length. */
-} asc_board_t;
+};
 
-/*
- * 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;
-       ADV_PADDR baseAddress[6];
-       ushort reserved[4];
-       ADV_PADDR optionRomAddr;
-       ushort reserved2[4];
-       uchar irqLine;
-       uchar irqPin;
-       uchar minGnt;
-       uchar maxLatency;
-} PCI_CONFIG_SPACE;
+#define asc_dvc_to_board(asc_dvc) container_of(asc_dvc, struct asc_board, \
+                                                       dvc_var.asc_dvc_var)
+#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
+                                                       dvc_var.adv_dvc_var)
+#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
+
+#ifdef ADVANSYS_DEBUG
+static int asc_dbglvl = 3;
 
 /*
- * --- Driver Data
+ * asc_prt_asc_dvc_var()
  */
+static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
+{
+       printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
+
+       printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
+              "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
+
+       printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
+               (unsigned)h->init_sdtr);
 
-/* Note: All driver global data should be initialized. */
+       printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
+              "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
+              (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
+              (unsigned)h->chip_no);
 
-/* Number of boards detected in system. */
-static int asc_board_count = 0;
-static struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL };
+       printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
+              "%u,\n", (unsigned)h->queue_full_or_busy,
+              (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
 
-/* Overrun buffer used by all narrow boards. */
-static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
+       printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
+              "in_critical_cnt %u,\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 %u, init_state 0x%x, no_scam 0x%x, "
+              "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
+              (unsigned)h->init_state, (unsigned)h->no_scam,
+              (unsigned)h->pci_fix_asyn_xfer);
+
+       printk(" cfg 0x%lx\n", (ulong)h->cfg);
+}
 
 /*
- * Global structures required to issue a command.
+ * asc_prt_asc_dvc_cfg()
  */
-static ASC_SCSI_Q asc_scsi_q = { {0} };
-static ASC_SG_HEAD asc_sg_head = { 0 };
-
-/* List of supported bus types. */
-static ushort asc_bus[ASC_NUM_BUS] __initdata = {
-       ASC_IS_ISA,
-       ASC_IS_VL,
-       ASC_IS_EISA,
-       ASC_IS_PCI,
-};
-
-static int asc_iopflag = ASC_FALSE;
-static int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
+static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
+{
+       printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
 
-#ifdef ADVANSYS_DEBUG
-static char *asc_bus_name[ASC_NUM_BUS] = {
-       "ASC_IS_ISA",
-       "ASC_IS_VL",
-       "ASC_IS_EISA",
-       "ASC_IS_PCI",
-};
+       printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
+              h->can_tagged_qng, h->cmd_qng_enabled);
+       printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
+              h->disc_enable, h->sdtr_enable);
 
-static int asc_dbglvl = 3;
-#endif /* ADVANSYS_DEBUG */
+       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);
 
-/* Declaration for Asc Library internal data referenced by driver. */
-static PortAddr _asc_def_iop_base[];
+       printk(" mcode_date 0x%x, mcode_version %d\n",
+               h->mcode_date, h->mcode_version);
+}
 
 /*
- * --- Driver Function Prototypes
+ * asc_prt_adv_dvc_var()
  *
- * advansys.h contains function prototypes for functions global to Linux.
+ * Display an ADV_DVC_VAR structure.
  */
+static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
+{
+       printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
 
-static irqreturn_t advansys_interrupt(int, void *);
-static int advansys_slave_configure(struct scsi_device *);
-static void asc_scsi_done_list(struct scsi_cmnd *);
-static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
-static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
-static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
-static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
-static void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
-static void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
-static void adv_async_callback(ADV_DVC_VAR *, uchar);
-static void asc_enqueue(asc_queue_t *, REQP, int);
-static REQP asc_dequeue(asc_queue_t *, int);
-static REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
-static int asc_rmqueue(asc_queue_t *, REQP);
-static void asc_execute_queue(asc_queue_t *);
-#ifdef CONFIG_PROC_FS
-static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
-static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
-static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
-static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
-static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
-static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
-static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
-static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
-static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
-static int asc_prt_line(char *, int, char *fmt, ...);
-#endif /* CONFIG_PROC_FS */
+       printk("  iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
+              (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
 
-/* Declaration for Asc Library internal functions referenced by driver. */
-static int AscFindSignature(PortAddr);
-static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
+       printk("  sdtr_able 0x%x, wdtr_able 0x%x\n",
+              (unsigned)h->sdtr_able, (unsigned)h->wdtr_able);
 
-/* Statistics function prototypes. */
-#ifdef ADVANSYS_STATS
-#ifdef CONFIG_PROC_FS
-static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
-static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
-#endif /* CONFIG_PROC_FS */
-#endif /* ADVANSYS_STATS */
+       printk("  start_motor 0x%x, scsi_reset_wait 0x%x\n",
+              (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
 
-/* Debug function prototypes. */
-#ifdef ADVANSYS_DEBUG
-static void asc_prt_scsi_host(struct Scsi_Host *);
-static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
-static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
-static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
-static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
-static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
-static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
-static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
-static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
-static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
-static void asc_prt_hex(char *f, uchar *, int);
-#endif /* ADVANSYS_DEBUG */
+       printk("  max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
+              (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
+              (ulong)h->carr_freelist);
+
+       printk("  icq_sp 0x%lx, irq_sp 0x%lx\n",
+              (ulong)h->icq_sp, (ulong)h->irq_sp);
+
+       printk("  no_scam 0x%x, tagqng_able 0x%x\n",
+              (unsigned)h->no_scam, (unsigned)h->tagqng_able);
+
+       printk("  chip_scsi_id 0x%x, cfg 0x%lx\n",
+              (unsigned)h->chip_scsi_id, (ulong)h->cfg);
+}
 
-#ifdef CONFIG_PROC_FS
 /*
- * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset into a /proc/scsi/advansys/[0...] 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 a
- * /proc/scsi/advansys/[0...] file.
+ * asc_prt_adv_dvc_cfg()
  *
- * Note: This function uses the per board buffer 'prtbuf' which is
- * allocated when the board is initialized in advansys_detect(). The
- * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
- * used to write to the buffer. The way asc_proc_copy() is written
- * if 'prtbuf' is too small it will not be overwritten. Instead the
- * user just won't get all the available statistics.
+ * Display an ADV_DVC_CFG structure.
  */
-static int
-advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-                  off_t offset, int length, int inout)
+static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
 {
-       struct Scsi_Host *shp;
-       asc_board_t *boardp;
-       int i;
-       char *cp;
-       int cplen;
-       int cnt;
-       int totcnt;
-       int leftlen;
-       char *curbuf;
-       off_t advoffset;
-#ifdef ADVANSYS_STATS
-       int tgt_id;
-#endif /* ADVANSYS_STATS */
+       printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
 
-       ASC_DBG(1, "advansys_proc_info: begin\n");
+       printk("  disc_enable 0x%x, termination 0x%x\n",
+              h->disc_enable, h->termination);
 
-       /*
-        * User write not supported.
-        */
-       if (inout == TRUE) {
-               return (-ENOSYS);
-       }
+       printk("  chip_version 0x%x, mcode_date 0x%x\n",
+              h->chip_version, h->mcode_date);
 
-       /*
-        * User read of /proc/scsi/advansys/[0...] file.
-        */
+       printk("  mcode_version 0x%x, control_flag 0x%x\n",
+              h->mcode_version, h->control_flag);
+}
 
-       /* Find the specified board. */
-       for (i = 0; i < asc_board_count; i++) {
-               if (asc_host[i]->host_no == shost->host_no) {
-                       break;
-               }
-       }
-       if (i == asc_board_count) {
-               return (-ENOENT);
-       }
+/*
+ * asc_prt_scsi_host()
+ */
+static void asc_prt_scsi_host(struct Scsi_Host *s)
+{
+       struct asc_board *boardp = shost_priv(s);
 
-       shp = asc_host[i];
-       boardp = ASC_BOARDP(shp);
+       printk("Scsi_Host at addr 0x%p, device %s\n", s, boardp->dev->bus_id);
+       printk(" host_busy %u, host_no %d, last_reset %d,\n",
+              s->host_busy, s->host_no, (unsigned)s->last_reset);
 
-       /* Copy read data starting at the beginning of the buffer. */
-       *start = buffer;
-       curbuf = buffer;
-       advoffset = 0;
-       totcnt = 0;
-       leftlen = length;
+       printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
+              (ulong)s->base, (ulong)s->io_port, boardp->irq);
 
-       /*
-        * Get board configuration information.
-        *
-        * advansys_info() returns the board string from its own static buffer.
-        */
-       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;
+       printk(" dma_channel %d, this_id %d, can_queue %d,\n",
+              s->dma_channel, s->this_id, s->can_queue);
 
-       /*
-        * Display Wide Board BIOS Information.
-        */
-       if (ASC_WIDE_BOARD(boardp)) {
-               cp = boardp->prtbuf;
-               cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
-               ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-               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;
+       printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
+              s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
+
+       if (ASC_NARROW_BOARD(boardp)) {
+               asc_prt_asc_dvc_var(&boardp->dvc_var.asc_dvc_var);
+               asc_prt_asc_dvc_cfg(&boardp->dvc_cfg.asc_dvc_cfg);
+       } else {
+               asc_prt_adv_dvc_var(&boardp->dvc_var.adv_dvc_var);
+               asc_prt_adv_dvc_cfg(&boardp->dvc_cfg.adv_dvc_cfg);
        }
-
-       /*
-        * Display driver information for each device attached to the board.
-        */
-       cp = boardp->prtbuf;
-       cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
-       ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-       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;
-
-       /*
-        * Display EEPROM configuration for the board.
-        */
-       cp = boardp->prtbuf;
-       if (ASC_NARROW_BOARD(boardp)) {
-               cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
-       } else {
-               cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
-       }
-       ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-       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;
-
-       /*
-        * Display driver configuration and information for the board.
-        */
-       cp = boardp->prtbuf;
-       cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
-       ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-       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
-       /*
-        * Display driver statistics for the board.
-        */
-       cp = boardp->prtbuf;
-       cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
-       ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
-       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;
-
-       /*
-        * Display driver statistics for each target.
-        */
-       for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
-               cp = boardp->prtbuf;
-               cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE);
-               ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
-               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 */
-
-       /*
-        * Display Asc Library dynamic configuration information
-        * for the board.
-        */
-       cp = boardp->prtbuf;
-       if (ASC_NARROW_BOARD(boardp)) {
-               cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
-       } else {
-               cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
-       }
-       ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-       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;
-
-       ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-
-       return totcnt;
-}
-#endif /* CONFIG_PROC_FS */
+}
 
 /*
- * advansys_info()
- *
- * Return suitable for printing on the console with the argument
- * adapter's configuration information.
+ * asc_prt_hex()
  *
- * Note: The information line should not exceed ASC_INFO_SIZE bytes,
- * otherwise the static 'info' array will be overrun.
+ * Print hexadecimal output in 4 byte groupings 32 bytes
+ * or 8 double-words per line.
  */
-static const char *advansys_info(struct Scsi_Host *shost)
+static void asc_prt_hex(char *f, uchar *s, int l)
 {
-       static char info[ASC_INFO_SIZE];
-       asc_board_t *boardp;
-       ASC_DVC_VAR *asc_dvc_varp;
-       ADV_DVC_VAR *adv_dvc_varp;
-       char *busname;
-       int iolen;
-       char *widename = NULL;
+       int i;
+       int j;
+       int k;
+       int m;
 
-       boardp = ASC_BOARDP(shost);
-       if (ASC_NARROW_BOARD(boardp)) {
-               asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
-               ASC_DBG(1, "advansys_info: begin\n");
-               if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
-                       if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
-                           ASC_IS_ISAPNP) {
-                               busname = "ISA PnP";
-                       } else {
-                               busname = "ISA";
-                       }
-                       /* Don't reference 'shost->n_io_port'; It may be truncated. */
-                       sprintf(info,
-                               "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
-                               ASC_VERSION, busname,
-                               (ulong)shost->io_port,
-                               (ulong)shost->io_port + boardp->asc_n_io_port -
-                               1, shost->irq, shost->dma_channel);
+       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 {
-                       if (asc_dvc_varp->bus_type & ASC_IS_VL) {
-                               busname = "VL";
-                       } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
-                               busname = "EISA";
-                       } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
-                               if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
-                                   == ASC_IS_PCI_ULTRA) {
-                                       busname = "PCI Ultra";
-                               } else {
-                                       busname = "PCI";
-                               }
-                       } else {
-                               busname = "?";
-                               ASC_PRINT2
-                                   ("advansys_info: board %d: unknown bus type %d\n",
-                                    boardp->id, asc_dvc_varp->bus_type);
-                       }
-                       /* Don't reference 'shost->n_io_port'; It may be truncated. */
-                       sprintf(info,
-                               "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
-                               ASC_VERSION, busname,
-                               (ulong)shost->io_port,
-                               (ulong)shost->io_port + boardp->asc_n_io_port -
-                               1, shost->irq);
+                       m = (l - i) % 4;
                }
-       } else {
-               /*
-                * Wide Adapter Information
-                *
-                * Memory-mapped I/O is used instead of I/O space to access
-                * the adapter, but display the I/O Port range. The Memory
-                * I/O address is displayed through the driver /proc file.
-                */
-               adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
-               if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-                       iolen = ADV_3550_IOLEN;
-                       widename = "Ultra-Wide";
-               } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-                       iolen = ADV_38C0800_IOLEN;
-                       widename = "Ultra2-Wide";
-               } else {
-                       iolen = ADV_38C1600_IOLEN;
-                       widename = "Ultra3-Wide";
+
+               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]);
                }
-               sprintf(info,
-                       "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
-                       ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
-                       (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq);
+
+               switch (m) {
+               case 0:
+               default:
+                       break;
+               case 1:
+                       printk(" %2.2X", (unsigned)s[i + (j * 4)]);
+                       break;
+               case 2:
+                       printk(" %2.2X%2.2X",
+                              (unsigned)s[i + (j * 4)],
+                              (unsigned)s[i + (j * 4) + 1]);
+                       break;
+               case 3:
+                       printk(" %2.2X%2.2X%2.2X",
+                              (unsigned)s[i + (j * 4) + 1],
+                              (unsigned)s[i + (j * 4) + 2],
+                              (unsigned)s[i + (j * 4) + 3]);
+                       break;
+               }
+
+               printk("\n");
        }
-       ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
-       ASC_DBG(1, "advansys_info: end\n");
-       return info;
 }
 
 /*
- * advansys_queuecommand() - interrupt-driven I/O entrypoint.
- *
- * This function always returns 0. Command return status is saved
- * in the 'scp' result field.
+ * asc_prt_asc_scsi_q()
  */
-static int
-advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *))
+static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
 {
-       struct Scsi_Host *shost;
-       asc_board_t *boardp;
-       ulong flags;
-       struct scsi_cmnd *done_scp;
+       ASC_SG_HEAD *sgp;
+       int i;
 
-       shost = scp->device->host;
-       boardp = ASC_BOARDP(shost);
-       ASC_STATS(shost, queuecommand);
+       printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
 
-       /* host_lock taken by mid-level prior to call but need to protect */
-       /* against own ISR */
-       spin_lock_irqsave(&boardp->lock, flags);
+       printk
+           (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
+            q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
+            q->q2.tag_code);
 
-       /*
-        * Block new commands while handling a reset or abort request.
-        */
-       if (boardp->flags & ASC_HOST_IN_RESET) {
-               ASC_DBG1(1,
-                        "advansys_queuecommand: scp 0x%lx blocked for reset request\n",
-                        (ulong)scp);
-               scp->result = HOST_BYTE(DID_RESET);
+       printk
+           (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
+            (ulong)le32_to_cpu(q->q1.data_addr),
+            (ulong)le32_to_cpu(q->q1.data_cnt),
+            (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
 
-               /*
-                * Add blocked requests to the board's 'done' queue. The queued
-                * requests will be completed at the end of the abort or reset
-                * handling.
-                */
-               asc_enqueue(&boardp->done, scp, ASC_BACK);
-               spin_unlock_irqrestore(&boardp->lock, flags);
-               return 0;
-       }
+       printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
+              (ulong)q->cdbptr, q->q2.cdb_len,
+              (ulong)q->sg_head, q->q1.sg_queue_cnt);
 
-       /*
-        * Attempt to execute any waiting commands for the board.
-        */
-       if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
-               ASC_DBG(1,
-                       "advansys_queuecommand: before asc_execute_queue() waiting\n");
-               asc_execute_queue(&boardp->waiting);
-       }
+       if (q->sg_head) {
+               sgp = q->sg_head;
+               printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)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 0x%lx, bytes %lu\n",
+                              i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
+                              (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
+               }
 
-       /*
-        * Save the function pointer to Linux mid-level 'done' function
-        * and attempt to execute the command.
-        *
-        * If ASC_NOERROR is returned the request has been added to the
-        * board's 'active' queue and will be completed by the interrupt
-        * handler.
-        *
-        * If ASC_BUSY is returned add the request to the board's per
-        * target waiting list. This is the first time the request has
-        * been tried. Add it to the back of the waiting list. It will be
-        * retried later.
-        *
-        * If an error occurred, the request will have been placed on the
-        * board's 'done' queue and must be completed before returning.
-        */
-       scp->scsi_done = done;
-       switch (asc_execute_scsi_cmnd(scp)) {
-       case ASC_NOERROR:
-               break;
-       case ASC_BUSY:
-               asc_enqueue(&boardp->waiting, scp, ASC_BACK);
-               break;
-       case ASC_ERROR:
-       default:
-               done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
-               /* Interrupts could be enabled here. */
-               asc_scsi_done_list(done_scp);
-               break;
        }
-       spin_unlock_irqrestore(&boardp->lock, flags);
-
-       return 0;
 }
 
 /*
- * advansys_reset()
- *
- * Reset the bus associated with the command 'scp'.
- *
- * This function runs its own thread. Interrupts must be blocked but
- * sleeping is allowed and no locking other than for host structures is
- * required. Returns SUCCESS or FAILED.
+ * asc_prt_asc_qdone_info()
  */
-static int advansys_reset(struct scsi_cmnd *scp)
+static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
 {
-       struct Scsi_Host *shost;
-       asc_board_t *boardp;
-       ASC_DVC_VAR *asc_dvc_varp;
-       ADV_DVC_VAR *adv_dvc_varp;
-       ulong flags;
-       struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
-       struct scsi_cmnd *tscp, *new_last_scp;
-       int status;
-       int ret = SUCCESS;
+       printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
+       printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
+              (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
+              q->d2.tag_code);
+       printk
+           (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
+            q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
+}
 
-       ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
+/*
+ * asc_prt_adv_sgblock()
+ *
+ * Display an ADV_SG_BLOCK structure.
+ */
+static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
+{
+       int i;
 
-#ifdef ADVANSYS_STATS
-       if (scp->device->host != NULL) {
-               ASC_STATS(scp->device->host, reset);
+       printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
+              (ulong)b, sgblockno);
+       printk("  sg_cnt %u, sg_ptr 0x%lx\n",
+              b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
+       BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
+       if (b->sg_ptr != 0)
+               BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
+       for (i = 0; i < b->sg_cnt; i++) {
+               printk("  [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
+                      i, (ulong)b->sg_list[i].sg_addr,
+                      (ulong)b->sg_list[i].sg_count);
        }
-#endif /* ADVANSYS_STATS */
+}
 
-       if ((shost = scp->device->host) == NULL) {
-               scp->result = HOST_BYTE(DID_ERROR);
-               return FAILED;
-       }
+/*
+ * asc_prt_adv_scsi_req_q()
+ *
+ * Display an ADV_SCSI_REQ_Q structure.
+ */
+static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
+{
+       int sg_blk_cnt;
+       struct asc_sg_block *sg_ptr;
 
-       boardp = ASC_BOARDP(shost);
+       printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
 
-       ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
-                  boardp->id);
-       /*
-        * Check for re-entrancy.
-        */
-       spin_lock_irqsave(&boardp->lock, flags);
-       if (boardp->flags & ASC_HOST_IN_RESET) {
-               spin_unlock_irqrestore(&boardp->lock, flags);
-               return FAILED;
-       }
-       boardp->flags |= ASC_HOST_IN_RESET;
-       spin_unlock_irqrestore(&boardp->lock, flags);
+       printk("  target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
+              q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
 
-       if (ASC_NARROW_BOARD(boardp)) {
-               /*
-                * Narrow Board
-                */
-               asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+       printk("  cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
+              q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
 
-               /*
-                * Reset the chip and SCSI bus.
-                */
-               ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
-               status = AscInitAsc1000Driver(asc_dvc_varp);
+       printk("  data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
+              (ulong)le32_to_cpu(q->data_cnt),
+              (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
 
-               /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
-               if (asc_dvc_varp->err_code) {
-                       ASC_PRINT2
-                           ("advansys_reset: board %d: SCSI bus reset error: 0x%x\n",
-                            boardp->id, asc_dvc_varp->err_code);
-                       ret = FAILED;
-               } else if (status) {
-                       ASC_PRINT2
-                           ("advansys_reset: board %d: SCSI bus reset warning: 0x%x\n",
-                            boardp->id, status);
-               } else {
-                       ASC_PRINT1
-                           ("advansys_reset: board %d: SCSI bus reset successful.\n",
-                            boardp->id);
-               }
+       printk
+           ("  cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
+            q->cdb_len, q->done_status, q->host_status, q->scsi_status);
 
-               ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
-               spin_lock_irqsave(&boardp->lock, flags);
+       printk("  sg_working_ix 0x%x, target_cmd %u\n",
+              q->sg_working_ix, q->target_cmd);
 
-       } else {
-               /*
-                * Wide Board
-                *
-                * If the suggest reset bus flags are set, then reset the bus.
-                * Otherwise only reset the device.
-                */
-               adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+       printk("  scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
+              (ulong)le32_to_cpu(q->scsiq_rptr),
+              (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
 
-               /*
-                * Reset the target's SCSI bus.
-                */
-               ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
-               switch (AdvResetChipAndSB(adv_dvc_varp)) {
-               case ASC_TRUE:
-                       ASC_PRINT1
-                           ("advansys_reset: board %d: SCSI bus reset successful.\n",
-                            boardp->id);
-                       break;
-               case ASC_FALSE:
-               default:
-                       ASC_PRINT1
-                           ("advansys_reset: board %d: SCSI bus reset error.\n",
-                            boardp->id);
-                       ret = FAILED;
-                       break;
+       /* Display the request's ADV_SG_BLOCK structures. */
+       if (q->sg_list_ptr != NULL) {
+               sg_blk_cnt = 0;
+               while (1) {
+                       /*
+                        * 'sg_ptr' is a physical address. Convert it to a virtual
+                        * address by indexing 'sg_blk_cnt' into the virtual address
+                        * array 'sg_list_ptr'.
+                        *
+                        * XXX - Assumes all SG physical blocks are virtually contiguous.
+                        */
+                       sg_ptr =
+                           &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
+                       asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
+                       if (sg_ptr->sg_ptr == 0) {
+                               break;
+                       }
+                       sg_blk_cnt++;
                }
-               spin_lock_irqsave(&boardp->lock, flags);
-               (void)AdvISR(adv_dvc_varp);
        }
-       /* Board lock is held. */
+}
+#endif /* ADVANSYS_DEBUG */
 
-       /*
-        * Dequeue all board 'done' requests. A pointer to the last request
-        * is returned in 'last_scp'.
-        */
-       done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL);
+/*
+ * The advansys chip/microcode contains a 32-bit identifier for each command
+ * known as the 'srb'.  I don't know what it stands for.  The driver used
+ * to encode the scsi_cmnd pointer by calling virt_to_bus and retrieve it
+ * with bus_to_virt.  Now the driver keeps a per-host map of integers to
+ * pointers.  It auto-expands when full, unless it can't allocate memory.
+ * Note that an srb of 0 is treated specially by the chip/firmware, hence
+ * the return of i+1 in this routine, and the corresponding subtraction in
+ * the inverse routine.
+ */
+#define BAD_SRB 0
+static u32 advansys_ptr_to_srb(struct asc_dvc_var *asc_dvc, void *ptr)
+{
+       int i;
+       void **new_ptr;
 
-       /*
-        * Dequeue all board 'active' requests for all devices and set
-        * the request status to DID_RESET. A pointer to the last request
-        * is returned in 'last_scp'.
-        */
-       if (done_scp == NULL) {
-               done_scp =
-                   asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL);
-               for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
-                       tscp->result = HOST_BYTE(DID_RESET);
-               }
-       } else {
-               /* Append to 'done_scp' at the end with 'last_scp'. */
-               ASC_ASSERT(last_scp != NULL);
-               last_scp->host_scribble =
-                   (unsigned char *)asc_dequeue_list(&boardp->active,
-                                                     &new_last_scp,
-                                                     ASC_TID_ALL);
-               if (new_last_scp != NULL) {
-                       ASC_ASSERT(REQPNEXT(last_scp) != NULL);
-                       for (tscp = REQPNEXT(last_scp); tscp;
-                            tscp = REQPNEXT(tscp)) {
-                               tscp->result = HOST_BYTE(DID_RESET);
-                       }
-                       last_scp = new_last_scp;
-               }
+       for (i = 0; i < asc_dvc->ptr_map_count; i++) {
+               if (!asc_dvc->ptr_map[i])
+                       goto out;
        }
 
-       /*
-        * Dequeue all 'waiting' requests and set the request status
-        * to DID_RESET.
-        */
-       if (done_scp == NULL) {
-               done_scp =
-                   asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL);
-               for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
-                       tscp->result = HOST_BYTE(DID_RESET);
-               }
-       } else {
-               /* Append to 'done_scp' at the end with 'last_scp'. */
-               ASC_ASSERT(last_scp != NULL);
-               last_scp->host_scribble =
-                   (unsigned char *)asc_dequeue_list(&boardp->waiting,
-                                                     &new_last_scp,
-                                                     ASC_TID_ALL);
-               if (new_last_scp != NULL) {
-                       ASC_ASSERT(REQPNEXT(last_scp) != NULL);
-                       for (tscp = REQPNEXT(last_scp); tscp;
-                            tscp = REQPNEXT(tscp)) {
-                               tscp->result = HOST_BYTE(DID_RESET);
-                       }
-                       last_scp = new_last_scp;
-               }
-       }
+       if (asc_dvc->ptr_map_count == 0)
+               asc_dvc->ptr_map_count = 1;
+       else
+               asc_dvc->ptr_map_count *= 2;
 
-       /* Save the time of the most recently completed reset. */
-       boardp->last_reset = jiffies;
+       new_ptr = krealloc(asc_dvc->ptr_map,
+                       asc_dvc->ptr_map_count * sizeof(void *), GFP_ATOMIC);
+       if (!new_ptr)
+               return BAD_SRB;
+       asc_dvc->ptr_map = new_ptr;
+ out:
+       ASC_DBG(3, "Putting ptr %p into array offset %d\n", ptr, i);
+       asc_dvc->ptr_map[i] = ptr;
+       return i + 1;
+}
 
-       /* Clear reset flag. */
-       boardp->flags &= ~ASC_HOST_IN_RESET;
-       spin_unlock_irqrestore(&boardp->lock, flags);
+static void * advansys_srb_to_ptr(struct asc_dvc_var *asc_dvc, u32 srb)
+{
+       void *ptr;
 
-       /*
-        * Complete all the 'done_scp' requests.
-        */
-       if (done_scp != NULL) {
-               asc_scsi_done_list(done_scp);
+       srb--;
+       if (srb >= asc_dvc->ptr_map_count) {
+               printk("advansys: bad SRB %u, max %u\n", srb,
+                                                       asc_dvc->ptr_map_count);
+               return NULL;
        }
-
-       ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
-
-       return ret;
+       ptr = asc_dvc->ptr_map[srb];
+       asc_dvc->ptr_map[srb] = NULL;
+       ASC_DBG(3, "Returning ptr %p from array offset %d\n", ptr, srb);
+       return ptr;
 }
 
 /*
- * advansys_biosparam()
+ * advansys_info()
  *
- * Translate disk drive geometry if the "BIOS greater than 1 GB"
- * support is enabled for a drive.
+ * Return suitable for printing on the console with the argument
+ * adapter's configuration information.
  *
- * ip (information pointer) is an int array with the following definition:
- * ip[0]: heads
- * ip[1]: sectors
- * ip[2]: cylinders
+ * Note: The information line should not exceed ASC_INFO_SIZE bytes,
+ * otherwise the static 'info' array will be overrun.
  */
-static int
-advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-                  sector_t capacity, int ip[])
+static const char *advansys_info(struct Scsi_Host *shost)
 {
-       asc_board_t *boardp;
+       static char info[ASC_INFO_SIZE];
+       struct asc_board *boardp = shost_priv(shost);
+       ASC_DVC_VAR *asc_dvc_varp;
+       ADV_DVC_VAR *adv_dvc_varp;
+       char *busname;
+       char *widename = NULL;
 
-       ASC_DBG(1, "advansys_biosparam: begin\n");
-       ASC_STATS(sdev->host, biosparam);
-       boardp = ASC_BOARDP(sdev->host);
        if (ASC_NARROW_BOARD(boardp)) {
-               if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
-                    ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
-                       ip[0] = 255;
-                       ip[1] = 63;
+               asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+               ASC_DBG(1, "begin\n");
+               if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
+                       if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
+                           ASC_IS_ISAPNP) {
+                               busname = "ISA PnP";
+                       } else {
+                               busname = "ISA";
+                       }
+                       sprintf(info,
+                               "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
+                               ASC_VERSION, busname,
+                               (ulong)shost->io_port,
+                               (ulong)shost->io_port + ASC_IOADR_GAP - 1,
+                               boardp->irq, shost->dma_channel);
                } else {
-                       ip[0] = 64;
-                       ip[1] = 32;
+                       if (asc_dvc_varp->bus_type & ASC_IS_VL) {
+                               busname = "VL";
+                       } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
+                               busname = "EISA";
+                       } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
+                               if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
+                                   == ASC_IS_PCI_ULTRA) {
+                                       busname = "PCI Ultra";
+                               } else {
+                                       busname = "PCI";
+                               }
+                       } else {
+                               busname = "?";
+                               shost_printk(KERN_ERR, shost, "unknown bus "
+                                       "type %d\n", asc_dvc_varp->bus_type);
+                       }
+                       sprintf(info,
+                               "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
+                               ASC_VERSION, busname, (ulong)shost->io_port,
+                               (ulong)shost->io_port + ASC_IOADR_GAP - 1,
+                               boardp->irq);
                }
        } else {
-               if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
-                    BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
-                       ip[0] = 255;
-                       ip[1] = 63;
+               /*
+                * Wide Adapter Information
+                *
+                * Memory-mapped I/O is used instead of I/O space to access
+                * the adapter, but display the I/O Port range. The Memory
+                * I/O address is displayed through the driver /proc file.
+                */
+               adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+               if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+                       widename = "Ultra-Wide";
+               } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+                       widename = "Ultra2-Wide";
                } else {
-                       ip[0] = 64;
-                       ip[1] = 32;
+                       widename = "Ultra3-Wide";
                }
+               sprintf(info,
+                       "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
+                       ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
+                       (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, boardp->irq);
        }
-       ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
-       ASC_DBG(1, "advansys_biosparam: end\n");
-       return 0;
+       BUG_ON(strlen(info) >= ASC_INFO_SIZE);
+       ASC_DBG(1, "end\n");
+       return info;
 }
 
-static int __init advansys_detect(struct scsi_host_template *tpnt);
-static int advansys_release(struct Scsi_Host *shp);
-
-static struct scsi_host_template driver_template = {
-       .proc_name = "advansys",
 #ifdef CONFIG_PROC_FS
-       .proc_info = advansys_proc_info,
-#endif
-       .name = "advansys",
-       .detect = advansys_detect,
-       .release = advansys_release,
-       .info = advansys_info,
-       .queuecommand = advansys_queuecommand,
-       .eh_bus_reset_handler = advansys_reset,
-       .bios_param = advansys_biosparam,
-       .slave_configure = advansys_slave_configure,
-       /*
-        * Because the driver may control an ISA adapter 'unchecked_isa_dma'
-        * must be set. The flag will be cleared in advansys_detect for non-ISA
-        * adapters. Refer to the comment in scsi_module.c for more information.
-        */
-       .unchecked_isa_dma = 1,
-       /*
-        * All adapters controlled by this driver are capable of large
-        * scatter-gather lists. According to the mid-level SCSI documentation
-        * this obviates any performance gain provided by setting
-        * 'use_clustering'. But empirically while CPU utilization is increased
-        * by enabling clustering, I/O throughput increases as well.
-        */
-       .use_clustering = ENABLE_CLUSTERING,
-};
-
-#include "scsi_module.c"
-
 /*
- * --- Miscellaneous Driver Functions
- */
+ * asc_prt_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 ASC_PRTLINE_SIZE bytes the stack
+ * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
+ */
+static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
+{
+       va_list args;
+       int ret;
+       char s[ASC_PRTLINE_SIZE];
+
+       va_start(args, fmt);
+       ret = vsprintf(s, fmt, args);
+       BUG_ON(ret >= ASC_PRTLINE_SIZE);
+       if (buf == NULL) {
+               (void)printk(s);
+               ret = 0;
+       } else {
+               ret = min(buflen, ret);
+               memcpy(buf, s, ret);
+       }
+       va_end(args);
+       return ret;
+}
 
 /*
- * First-level interrupt handler.
+ * asc_prt_board_devices()
+ *
+ * Print driver information for devices attached to the board.
  *
- * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
- * all boards are currently checked for interrupts on each interrupt, 'dev_id'
- * is not referenced. 'dev_id' could be used to identify an interrupt passed
- * to the AdvanSys driver which is for a device sharing an interrupt with
- * an AdvanSys adapter.
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
  */
-static irqreturn_t advansys_interrupt(int irq, void *dev_id)
+static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       ulong flags;
+       struct asc_board *boardp = shost_priv(shost);
+       int leftlen;
+       int totlen;
+       int len;
+       int chip_scsi_id;
        int i;
-       asc_board_t *boardp;
-       struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
-       struct scsi_cmnd *new_last_scp;
-       struct Scsi_Host *shost;
 
-       ASC_DBG(1, "advansys_interrupt: begin\n");
+       leftlen = cplen;
+       totlen = len = 0;
 
-       /*
-        * Check for interrupts on all boards.
-        * AscISR() will call asc_isr_callback().
-        */
-       for (i = 0; i < asc_board_count; i++) {
-               shost = asc_host[i];
-               boardp = ASC_BOARDP(shost);
-               ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
-                        i, (ulong)boardp);
-               spin_lock_irqsave(&boardp->lock, flags);
-               if (ASC_NARROW_BOARD(boardp)) {
-                       /*
-                        * Narrow Board
-                        */
-                       if (AscIsIntPending(shost->io_port)) {
-                               ASC_STATS(shost, interrupt);
-                               ASC_DBG(1,
-                                       "advansys_interrupt: before AscISR()\n");
-                               AscISR(&boardp->dvc_var.asc_dvc_var);
-                       }
-               } else {
-                       /*
-                        * Wide Board
-                        */
-                       ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
-                       if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
-                               ASC_STATS(shost, interrupt);
-                       }
-               }
+       len = asc_prt_line(cp, leftlen,
+                          "\nDevice Information for AdvanSys SCSI Host %d:\n",
+                          shost->host_no);
+       ASC_PRT_NEXT();
 
-               /*
-                * Start waiting requests and create a list of completed requests.
-                *
-                * If a reset request is being performed for the board, the reset
-                * handler will complete pending requests after it has completed.
-                */
-               if ((boardp->flags & ASC_HOST_IN_RESET) == 0) {
-                       ASC_DBG2(1,
-                                "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n",
-                                (ulong)done_scp, (ulong)last_scp);
-
-                       /* Start any waiting commands for the board. */
-                       if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
-                               ASC_DBG(1,
-                                       "advansys_interrupt: before asc_execute_queue()\n");
-                               asc_execute_queue(&boardp->waiting);
-                       }
+       if (ASC_NARROW_BOARD(boardp)) {
+               chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
+       } else {
+               chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
+       }
 
-                       /*
-                        * Add to the list of requests that must be completed.
-                        *
-                        * 'done_scp' will always be NULL on the first iteration
-                        * of this loop. 'last_scp' is set at the same time as
-                        * 'done_scp'.
-                        */
-                       if (done_scp == NULL) {
-                               done_scp =
-                                   asc_dequeue_list(&boardp->done, &last_scp,
-                                                    ASC_TID_ALL);
-                       } else {
-                               ASC_ASSERT(last_scp != NULL);
-                               last_scp->host_scribble =
-                                   (unsigned char *)asc_dequeue_list(&boardp->
-                                                                     done,
-                                                                     &new_last_scp,
-                                                                     ASC_TID_ALL);
-                               if (new_last_scp != NULL) {
-                                       ASC_ASSERT(REQPNEXT(last_scp) != NULL);
-                                       last_scp = new_last_scp;
-                               }
-                       }
+       len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
+                       len = asc_prt_line(cp, leftlen, " %X,", i);
+                       ASC_PRT_NEXT();
                }
-               spin_unlock_irqrestore(&boardp->lock, flags);
        }
+       len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
+       ASC_PRT_NEXT();
 
-       /*
-        * If interrupts were enabled on entry, then they
-        * are now enabled here.
-        *
-        * Complete all requests on the done list.
-        */
-
-       asc_scsi_done_list(done_scp);
-
-       ASC_DBG(1, "advansys_interrupt: end\n");
-       return IRQ_HANDLED;
+       return totlen;
 }
 
 /*
- * Set the number of commands to queue per device for the
- * specified host adapter.
+ * Display Wide Board BIOS Information.
  */
-static int advansys_slave_configure(struct scsi_device *device)
+static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       asc_board_t *boardp;
+       struct asc_board *boardp = shost_priv(shost);
+       int leftlen;
+       int totlen;
+       int len;
+       ushort major, minor, letter;
+
+       leftlen = cplen;
+       totlen = len = 0;
+
+       len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
+       ASC_PRT_NEXT();
 
-       boardp = ASC_BOARDP(device->host);
-       boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
        /*
-        * Save a pointer to the device and set its initial/maximum
-        * queue depth.  Only save the pointer for a lun0 dev though.
+        * If the BIOS saved a valid signature, then fill in
+        * the BIOS code segment base address.
         */
-       if (device->lun == 0)
-               boardp->device[device->id] = device;
-       if (device->tagged_supported) {
-               if (ASC_NARROW_BOARD(boardp)) {
-                       scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
-                                               boardp->dvc_var.asc_dvc_var.
-                                               max_dvc_qng[device->id]);
-               } else {
-                       scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
-                                               boardp->dvc_var.adv_dvc_var.
-                                               max_dvc_qng);
-               }
+       if (boardp->bios_signature != 0x55AA) {
+               len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
+               ASC_PRT_NEXT();
+               len = asc_prt_line(cp, leftlen,
+                                  "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
+               ASC_PRT_NEXT();
+               len = asc_prt_line(cp, leftlen,
+                                  "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
+               ASC_PRT_NEXT();
        } else {
-               scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun);
-       }
-       ASC_DBG4(1,
-                "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n",
-                (ulong)device, (ulong)boardp, device->id, device->queue_depth);
-       return 0;
-}
-
-/*
- * Complete all requests on the singly linked list pointed
- * to by 'scp'.
- *
- * Interrupts can be enabled on entry.
- */
-static void asc_scsi_done_list(struct scsi_cmnd *scp)
-{
-       struct scsi_cmnd *tscp;
-
-       ASC_DBG(2, "asc_scsi_done_list: begin\n");
-       while (scp != NULL) {
-               asc_board_t *boardp;
-               struct device *dev;
-
-               ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
-               tscp = REQPNEXT(scp);
-               scp->host_scribble = NULL;
-
-               boardp = ASC_BOARDP(scp->device->host);
-
-               if (ASC_NARROW_BOARD(boardp))
-                       dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
-               else
-                       dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
-
-               if (scp->use_sg)
-                       dma_unmap_sg(dev,
-                                    (struct scatterlist *)scp->request_buffer,
-                                    scp->use_sg, scp->sc_data_direction);
-               else if (scp->request_bufflen)
-                       dma_unmap_single(dev, scp->SCp.dma_handle,
-                                        scp->request_bufflen,
-                                        scp->sc_data_direction);
-
-               ASC_STATS(scp->device->host, done);
-               ASC_ASSERT(scp->scsi_done != NULL);
+               major = (boardp->bios_version >> 12) & 0xF;
+               minor = (boardp->bios_version >> 8) & 0xF;
+               letter = (boardp->bios_version & 0xFF);
 
-               scp->scsi_done(scp);
+               len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
+                                  major, minor,
+                                  letter >= 26 ? '?' : letter + 'A');
+               ASC_PRT_NEXT();
 
-               scp = tscp;
+               /*
+                * Current available ROM BIOS release is 3.1I for UW
+                * and 3.2I for U2W. This code doesn't differentiate
+                * UW and U2W boards.
+                */
+               if (major < 3 || (major <= 3 && minor < 1) ||
+                   (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
+                       len = asc_prt_line(cp, leftlen,
+                                          "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
+                       ASC_PRT_NEXT();
+                       len = asc_prt_line(cp, leftlen,
+                                          "ftp://ftp.connectcom.net/pub\n");
+                       ASC_PRT_NEXT();
+               }
        }
-       ASC_DBG(2, "asc_scsi_done_list: done\n");
-       return;
+
+       return totlen;
 }
 
 /*
- * 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
+ * Add serial number to information bar if signature AAh
+ * is found in at bit 15-9 (7 bits) of word 1.
  *
- *  if (use_sg == 0) {
- *    request_buffer - buffer address for request
- *    request_bufflen - length of request buffer
- *  } else {
- *    request_buffer - pointer to scatterlist structure
- *  }
+ * Serial Number consists fo 12 alpha-numeric digits.
  *
- *  sense_buffer - sense command buffer
+ *       1 - Product type (A,B,C,D..)  Word0: 15-13 (3 bits)
+ *       2 - MFG Location (A,B,C,D..)  Word0: 12-10 (3 bits)
+ *     3-4 - Product ID (0-99)         Word0: 9-0 (10 bits)
+ *       5 - Product revision (A-J)    Word0:  "         "
  *
- *  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
+ *           Signature                 Word1: 15-9 (7 bits)
+ *       6 - Year (0-9)                Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
+ *     7-8 - Week of the year (1-52)   Word1: 5-0 (6 bits)
  *
- *  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 struct scsi_cmnd
+ *    9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
  *
- * If this function returns ASC_NOERROR the request has been enqueued
- * on the board's 'active' queue and will be completed from the
- * interrupt handler.
+ * Note 1: Only production cards will have a serial number.
  *
- * If this function returns ASC_NOERROR the request has been enqueued
- * on the board's 'done' queue and must be completed by the caller.
+ * Note 2: Signature is most significant 7 bits (0xFE).
  *
- * If ASC_BUSY is returned the request will be enqueued by the
- * caller on the target's waiting queue and re-tried later.
+ * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
  */
-static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
+static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
 {
-       asc_board_t *boardp;
-       ASC_DVC_VAR *asc_dvc_varp;
-       ADV_DVC_VAR *adv_dvc_varp;
-       ADV_SCSI_REQ_Q *adv_scsiqp;
-       struct scsi_device *device;
-       int ret;
-
-       ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
-                (ulong)scp, (ulong)scp->scsi_done);
-
-       boardp = ASC_BOARDP(scp->device->host);
-       device = boardp->device[scp->device->id];
+       ushort w, num;
 
-       if (ASC_NARROW_BOARD(boardp)) {
+       if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
+               return ASC_FALSE;
+       } else {
                /*
-                * Build and execute Narrow Board request.
+                * First word - 6 digits.
                 */
+               w = serialnum[0];
 
-               asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
-
-               /*
-                * Build Asc Library request structure using the
-                * global structures 'asc_scsi_req' and 'asc_sg_head'.
-                *
-                * If an error is returned, then the request has been
-                * queued on the board done queue. It will be completed
-                * by the caller.
-                *
-                * asc_build_req() can not return ASC_BUSY.
-                */
-               if (asc_build_req(boardp, scp) == ASC_ERROR) {
-                       ASC_STATS(scp->device->host, build_error);
-                       return ASC_ERROR;
+               /* Product type - 1st digit. */
+               if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
+                       /* Product type is P=Prototype */
+                       *cp += 0x8;
                }
+               cp++;
+
+               /* Manufacturing location - 2nd digit. */
+               *cp++ = 'A' + ((w & 0x1C00) >> 10);
+
+               /* Product ID - 3rd, 4th digits. */
+               num = w & 0x3FF;
+               *cp++ = '0' + (num / 100);
+               num %= 100;
+               *cp++ = '0' + (num / 10);
+
+               /* Product revision - 5th digit. */
+               *cp++ = 'A' + (num % 10);
 
                /*
-                * Execute the command. If there is no error, add the command
-                * to the active queue.
-                */
-               switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
-               case ASC_NOERROR:
-                       ASC_STATS(scp->device->host, exe_noerror);
-                       /*
-                        * Increment monotonically increasing per device successful
-                        * request counter. Wrapping doesn't matter.
-                        */
-                       boardp->reqcnt[scp->device->id]++;
-                       asc_enqueue(&boardp->active, scp, ASC_BACK);
-                       ASC_DBG(1,
-                               "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
-                       break;
-               case ASC_BUSY:
-                       /*
-                        * Caller will enqueue request on the target's waiting queue
-                        * and retry later.
-                        */
-                       ASC_STATS(scp->device->host, exe_busy);
-                       break;
-               case ASC_ERROR:
-                       ASC_PRINT2
-                           ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
-                            boardp->id, asc_dvc_varp->err_code);
-                       ASC_STATS(scp->device->host, exe_error);
-                       scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->done, scp, ASC_BACK);
-                       break;
-               default:
-                       ASC_PRINT2
-                           ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n",
-                            boardp->id, asc_dvc_varp->err_code);
-                       ASC_STATS(scp->device->host, exe_unknown);
-                       scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->done, scp, ASC_BACK);
-                       break;
-               }
-       } else {
-               /*
-                * Build and execute Wide Board request.
+                * Second word
                 */
-               adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+               w = serialnum[1];
 
                /*
-                * Build and get a pointer to an Adv Library request structure.
+                * Year - 6th digit.
                 *
-                * If the request is successfully built then send it below,
-                * otherwise return with an error.
+                * If bit 15 of third word is set, then the
+                * last digit of the year is greater than 7.
                 */
-               switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
-               case ASC_NOERROR:
-                       ASC_DBG(3,
-                               "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
-                       break;
-               case ASC_BUSY:
-                       ASC_DBG(1,
-                               "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
-                       /*
-                        * If busy is returned the request has not been enqueued.
-                        * It will be enqueued by the caller on the target's waiting
-                        * queue and retried later.
-                        *
-                        * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg'
-                        * count wide board busy conditions. They are updated in
-                        * adv_build_req and adv_get_sglist, respectively.
-                        */
-                       return ASC_BUSY;
-               case ASC_ERROR:
-                       /* 
-                        * If an error is returned, then the request has been
-                        * queued on the board done queue. It will be completed
-                        * by the caller.
-                        */
-               default:
-                       ASC_DBG(1,
-                               "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
-                       ASC_STATS(scp->device->host, build_error);
-                       return ASC_ERROR;
+               if (serialnum[2] & 0x8000) {
+                       *cp++ = '8' + ((w & 0x1C0) >> 6);
+               } else {
+                       *cp++ = '0' + ((w & 0x1C0) >> 6);
                }
 
-               /*
-                * Execute the command. If there is no error, add the command
-                * to the active queue.
-                */
-               switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
-               case ASC_NOERROR:
-                       ASC_STATS(scp->device->host, exe_noerror);
-                       /*
-                        * Increment monotonically increasing per device successful
-                        * request counter. Wrapping doesn't matter.
-                        */
-                       boardp->reqcnt[scp->device->id]++;
-                       asc_enqueue(&boardp->active, scp, ASC_BACK);
-                       ASC_DBG(1,
-                               "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
-                       break;
-               case ASC_BUSY:
-                       /*
-                        * Caller will enqueue request on the target's waiting queue
-                        * and retry later.
-                        */
-                       ASC_STATS(scp->device->host, exe_busy);
-                       break;
-               case ASC_ERROR:
-                       ASC_PRINT2
-                           ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
-                            boardp->id, adv_dvc_varp->err_code);
-                       ASC_STATS(scp->device->host, exe_error);
-                       scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->done, scp, ASC_BACK);
-                       break;
-               default:
-                       ASC_PRINT2
-                           ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n",
-                            boardp->id, adv_dvc_varp->err_code);
-                       ASC_STATS(scp->device->host, exe_unknown);
-                       scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->done, scp, ASC_BACK);
-                       break;
-               }
-       }
+               /* Week of year - 7th, 8th digits. */
+               num = w & 0x003F;
+               *cp++ = '0' + num / 10;
+               num %= 10;
+               *cp++ = '0' + num;
 
-       ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
-       return ret;
+               /*
+                * Third word
+                */
+               w = serialnum[2] & 0x7FFF;
+
+               /* Serial number - 9th digit. */
+               *cp++ = 'A' + (w / 1000);
+
+               /* 10th, 11th, 12th digits. */
+               num = w % 1000;
+               *cp++ = '0' + num / 100;
+               num %= 100;
+               *cp++ = '0' + num / 10;
+               num %= 10;
+               *cp++ = '0' + num;
+
+               *cp = '\0';     /* Null Terminate the string. */
+               return ASC_TRUE;
+       }
 }
 
 /*
- * Build a request structure for the Asc Library (Narrow Board).
+ * asc_prt_asc_board_eeprom()
  *
- * The global structures 'asc_scsi_q' and 'asc_sg_head' are
- * used to build the request.
+ * Print board EEPROM configuration.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
  *
- * If an error occurs, then queue the request on the board done
- * queue and return ASC_ERROR.
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
+static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
+       struct asc_board *boardp = shost_priv(shost);
+       ASC_DVC_VAR *asc_dvc_varp;
+       int leftlen;
+       int totlen;
+       int len;
+       ASCEEP_CONFIG *ep;
+       int i;
+#ifdef CONFIG_ISA
+       int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
+#endif /* CONFIG_ISA */
+       uchar serialstr[13];
 
-       /*
-        * Mutually exclusive access is required to 'asc_scsi_q' and
-        * 'asc_sg_head' until after the request is started.
-        */
-       memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
+       asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+       ep = &boardp->eep_config.asc_eep;
 
-       /*
-        * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
-        */
-       asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
+       leftlen = cplen;
+       totlen = len = 0;
 
-       /*
-        * Build the ASC_SCSI_Q request.
-        *
-        * For narrow boards a CDB length maximum of 12 bytes
-        * is supported.
-        */
-       if (scp->cmd_len > ASC_MAX_CDB_LEN) {
-               ASC_PRINT3
-                   ("asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN  %d\n",
-                    boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN);
-               scp->result = HOST_BYTE(DID_ERROR);
-               asc_enqueue(&boardp->done, scp, ASC_BACK);
-               return ASC_ERROR;
-       }
-       asc_scsi_q.cdbptr = &scp->cmnd[0];
-       asc_scsi_q.q2.cdb_len = scp->cmd_len;
-       asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
-       asc_scsi_q.q1.target_lun = scp->device->lun;
-       asc_scsi_q.q2.target_ix =
-           ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
-       asc_scsi_q.q1.sense_addr =
-           cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
-       asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
+       len = asc_prt_line(cp, leftlen,
+                          "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+                          shost->host_no);
+       ASC_PRT_NEXT();
 
-       /*
-        * If there are any outstanding requests for the current target,
-        * then every 255th request send an ORDERED request. This heuristic
-        * tries to retain the benefit of request sorting while preventing
-        * request starvation. 255 is the max number of tags or pending commands
-        * a device may have outstanding.
-        *
-        * The request count is incremented below for every successfully
-        * started request.
-        *
-        */
-       if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
-           (boardp->reqcnt[scp->device->id] % 255) == 0) {
-               asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
+       if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
+           == ASC_TRUE) {
+               len =
+                   asc_prt_line(cp, leftlen, " Serial Number: %s\n",
+                                serialstr);
+               ASC_PRT_NEXT();
        } else {
-               asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
+               if (ep->adapter_info[5] == 0xBB) {
+                       len = asc_prt_line(cp, leftlen,
+                                          " Default Settings Used for EEPROM-less Adapter.\n");
+                       ASC_PRT_NEXT();
+               } else {
+                       len = asc_prt_line(cp, leftlen,
+                                          " Serial Number Signature Not Present.\n");
+                       ASC_PRT_NEXT();
+               }
        }
 
-       /*
-        * 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(scp->device->host, cont_cnt);
-               scp->SCp.dma_handle = scp->request_bufflen ?
-                   dma_map_single(dev, scp->request_buffer,
-                                  scp->request_bufflen,
-                                  scp->sc_data_direction) : 0;
-               asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
-               asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
-               ASC_STATS_ADD(scp->device->host, cont_xfer,
-                             ASC_CEILING(scp->request_bufflen, 512));
-               asc_scsi_q.q1.sg_queue_cnt = 0;
-               asc_scsi_q.sg_head = NULL;
-       } else {
-               /*
-                * CDB scatter-gather request list.
-                */
-               int sgcnt;
-               int use_sg;
-               struct scatterlist *slp;
+       len = asc_prt_line(cp, leftlen,
+                          " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+                          ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
+                          ep->max_tag_qng);
+       ASC_PRT_NEXT();
 
-               slp = (struct scatterlist *)scp->request_buffer;
-               use_sg =
-                   dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
+       len = asc_prt_line(cp, leftlen,
+                          " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
+       ASC_PRT_NEXT();
 
-               if (use_sg > scp->device->host->sg_tablesize) {
-                       ASC_PRINT3
-                           ("asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
-                            boardp->id, use_sg,
-                            scp->device->host->sg_tablesize);
-                       dma_unmap_sg(dev, slp, scp->use_sg,
-                                    scp->sc_data_direction);
-                       scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->done, scp, ASC_BACK);
-                       return ASC_ERROR;
-               }
+       len = asc_prt_line(cp, leftlen, " Target ID:           ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %d", i);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               ASC_STATS(scp->device->host, sg_cnt);
+       len = asc_prt_line(cp, leftlen, " Disconnects:         ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (ep->
+                                   disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               /*
-                * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
-                * structure to point to it.
-                */
-               memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
+       len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (ep->
+                                   use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               asc_scsi_q.q1.cntl |= QC_SG_HEAD;
-               asc_scsi_q.sg_head = &asc_sg_head;
-               asc_scsi_q.q1.data_cnt = 0;
-               asc_scsi_q.q1.data_addr = 0;
-               /* This is a byte value, otherwise it would need to be swapped. */
-               asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
-               ASC_STATS_ADD(scp->device->host, sg_elem,
-                             asc_sg_head.entry_cnt);
+       len = asc_prt_line(cp, leftlen, " Start Motor:         ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (ep->
+                                   start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               /*
-                * Convert scatter-gather list into ASC_SG_HEAD list.
-                */
-               for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
-                       asc_sg_head.sg_list[sgcnt].addr =
-                           cpu_to_le32(sg_dma_address(slp));
-                       asc_sg_head.sg_list[sgcnt].bytes =
-                           cpu_to_le32(sg_dma_len(slp));
-                       ASC_STATS_ADD(scp->device->host, sg_xfer,
-                                     ASC_CEILING(sg_dma_len(slp), 512));
-               }
+       len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (ep->
+                                   init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
        }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
-       ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
+#ifdef CONFIG_ISA
+       if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
+               len = asc_prt_line(cp, leftlen,
+                                  " Host ISA DMA speed:   %d MB/S\n",
+                                  isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
+               ASC_PRT_NEXT();
+       }
+#endif /* CONFIG_ISA */
 
-       return ASC_NOERROR;
+       return totlen;
 }
 
 /*
- * Build a request structure for the Adv Library (Wide Board).
+ * asc_prt_adv_board_eeprom()
  *
- * If an adv_req_t can not be allocated to issue the request,
- * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
+ * Print board EEPROM configuration.
  *
- * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
- * microcode for DMA addresses or math operations are byte swapped
- * to little-endian order.
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
  */
-static int
-adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
-             ADV_SCSI_REQ_Q **adv_scsiqpp)
+static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       adv_req_t *reqp;
-       ADV_SCSI_REQ_Q *scsiqp;
+       struct asc_board *boardp = shost_priv(shost);
+       ADV_DVC_VAR *adv_dvc_varp;
+       int leftlen;
+       int totlen;
+       int len;
        int i;
-       int ret;
-       struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
+       char *termstr;
+       uchar serialstr[13];
+       ADVEEP_3550_CONFIG *ep_3550 = NULL;
+       ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
+       ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
+       ushort word;
+       ushort *wordp;
+       ushort sdtr_speed = 0;
 
-       /*
-        * Allocate an adv_req_t structure from the board to execute
-        * the command.
-        */
-       if (boardp->adv_reqp == NULL) {
-               ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
-               ASC_STATS(scp->device->host, adv_build_noreq);
-               return ASC_BUSY;
+       adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               ep_3550 = &boardp->eep_config.adv_3550_eep;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
        } else {
-               reqp = boardp->adv_reqp;
-               boardp->adv_reqp = reqp->next_reqp;
-               reqp->next_reqp = NULL;
+               ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
        }
 
-       /*
-        * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
-        */
-       scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
-
-       /*
-        * Initialize the structure.
-        */
-       scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
+       leftlen = cplen;
+       totlen = len = 0;
 
-       /*
-        * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
-        */
-       scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
+       len = asc_prt_line(cp, leftlen,
+                          "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+                          shost->host_no);
+       ASC_PRT_NEXT();
 
-       /*
-        * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
-        */
-       reqp->cmndp = scp;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               wordp = &ep_3550->serial_number_word1;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               wordp = &ep_38C0800->serial_number_word1;
+       } else {
+               wordp = &ep_38C1600->serial_number_word1;
+       }
 
-       /*
-        * Build the ADV_SCSI_REQ_Q request.
-        */
+       if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
+               len =
+                   asc_prt_line(cp, leftlen, " Serial Number: %s\n",
+                                serialstr);
+               ASC_PRT_NEXT();
+       } else {
+               len = asc_prt_line(cp, leftlen,
+                                  " Serial Number Signature Not Present.\n");
+               ASC_PRT_NEXT();
+       }
 
-       /*
-        * Set CDB length and copy it to the request structure.
-        * For wide  boards a CDB length maximum of 16 bytes
-        * is supported.
-        */
-       if (scp->cmd_len > ADV_MAX_CDB_LEN) {
-               ASC_PRINT3
-                   ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN  %d\n",
-                    boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN);
-               scp->result = HOST_BYTE(DID_ERROR);
-               asc_enqueue(&boardp->done, scp, ASC_BACK);
-               return ASC_ERROR;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               len = asc_prt_line(cp, leftlen,
+                                  " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+                                  ep_3550->adapter_scsi_id,
+                                  ep_3550->max_host_qng, ep_3550->max_dvc_qng);
+               ASC_PRT_NEXT();
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               len = asc_prt_line(cp, leftlen,
+                                  " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+                                  ep_38C0800->adapter_scsi_id,
+                                  ep_38C0800->max_host_qng,
+                                  ep_38C0800->max_dvc_qng);
+               ASC_PRT_NEXT();
+       } else {
+               len = asc_prt_line(cp, leftlen,
+                                  " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+                                  ep_38C1600->adapter_scsi_id,
+                                  ep_38C1600->max_host_qng,
+                                  ep_38C1600->max_dvc_qng);
+               ASC_PRT_NEXT();
        }
-       scsiqp->cdb_len = scp->cmd_len;
-       /* Copy first 12 CDB bytes to cdb[]. */
-       for (i = 0; i < scp->cmd_len && i < 12; i++) {
-               scsiqp->cdb[i] = scp->cmnd[i];
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               word = ep_3550->termination;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               word = ep_38C0800->termination_lvd;
+       } else {
+               word = ep_38C1600->termination_lvd;
        }
-       /* Copy last 4 CDB bytes, if present, to cdb16[]. */
-       for (; i < scp->cmd_len; i++) {
-               scsiqp->cdb16[i - 12] = scp->cmnd[i];
+       switch (word) {
+       case 1:
+               termstr = "Low Off/High Off";
+               break;
+       case 2:
+               termstr = "Low Off/High On";
+               break;
+       case 3:
+               termstr = "Low On/High On";
+               break;
+       default:
+       case 0:
+               termstr = "Automatic";
+               break;
        }
 
-       scsiqp->target_id = scp->device->id;
-       scsiqp->target_lun = scp->device->lun;
-
-       scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
-       scsiqp->sense_len = sizeof(scp->sense_buffer);
-
-       /*
-        * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
-        * buffer command.
-        */
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               len = asc_prt_line(cp, leftlen,
+                                  " termination: %u (%s), bios_ctrl: 0x%x\n",
+                                  ep_3550->termination, termstr,
+                                  ep_3550->bios_ctrl);
+               ASC_PRT_NEXT();
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               len = asc_prt_line(cp, leftlen,
+                                  " termination: %u (%s), bios_ctrl: 0x%x\n",
+                                  ep_38C0800->termination_lvd, termstr,
+                                  ep_38C0800->bios_ctrl);
+               ASC_PRT_NEXT();
+       } else {
+               len = asc_prt_line(cp, leftlen,
+                                  " termination: %u (%s), bios_ctrl: 0x%x\n",
+                                  ep_38C1600->termination_lvd, termstr,
+                                  ep_38C1600->bios_ctrl);
+               ASC_PRT_NEXT();
+       }
 
-       scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
-       scsiqp->vdata_addr = scp->request_buffer;
-       scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
+       len = asc_prt_line(cp, leftlen, " Target ID:           ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %X", i);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       if (scp->use_sg == 0) {
-               /*
-                * CDB request of single contiguous buffer.
-                */
-               reqp->sgblkp = NULL;
-               scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
-               if (scp->request_bufflen) {
-                       scsiqp->vdata_addr = scp->request_buffer;
-                       scp->SCp.dma_handle =
-                           dma_map_single(dev, scp->request_buffer,
-                                          scp->request_bufflen,
-                                          scp->sc_data_direction);
-               } else {
-                       scsiqp->vdata_addr = NULL;
-                       scp->SCp.dma_handle = 0;
-               }
-               scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
-               scsiqp->sg_list_ptr = NULL;
-               scsiqp->sg_real_addr = 0;
-               ASC_STATS(scp->device->host, cont_cnt);
-               ASC_STATS_ADD(scp->device->host, cont_xfer,
-                             ASC_CEILING(scp->request_bufflen, 512));
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               word = ep_3550->disc_enable;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               word = ep_38C0800->disc_enable;
        } else {
-               /*
-                * CDB scatter-gather request list.
-                */
-               struct scatterlist *slp;
-               int use_sg;
-
-               slp = (struct scatterlist *)scp->request_buffer;
-               use_sg =
-                   dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
+               word = ep_38C1600->disc_enable;
+       }
+       len = asc_prt_line(cp, leftlen, " Disconnects:         ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               if (use_sg > ADV_MAX_SG_LIST) {
-                       ASC_PRINT3
-                           ("adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
-                            boardp->id, use_sg,
-                            scp->device->host->sg_tablesize);
-                       dma_unmap_sg(dev, slp, scp->use_sg,
-                                    scp->sc_data_direction);
-                       scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->done, scp, ASC_BACK);
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               word = ep_3550->tagqng_able;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               word = ep_38C0800->tagqng_able;
+       } else {
+               word = ep_38C1600->tagqng_able;
+       }
+       len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-                       /*
-                        * Free the 'adv_req_t' structure by adding it back to the
-                        * board free list.
-                        */
-                       reqp->next_reqp = boardp->adv_reqp;
-                       boardp->adv_reqp = reqp;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               word = ep_3550->start_motor;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               word = ep_38C0800->start_motor;
+       } else {
+               word = ep_38C1600->start_motor;
+       }
+       len = asc_prt_line(cp, leftlen, " Start Motor:         ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-                       return ASC_ERROR;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
+               ASC_PRT_NEXT();
+               for (i = 0; i <= ADV_MAX_TID; i++) {
+                       len = asc_prt_line(cp, leftlen, " %c",
+                                          (ep_3550->
+                                           sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
+                                          'Y' : 'N');
+                       ASC_PRT_NEXT();
                }
+               len = asc_prt_line(cp, leftlen, "\n");
+               ASC_PRT_NEXT();
+       }
 
-               if ((ret =
-                    adv_get_sglist(boardp, reqp, scp,
-                                   use_sg)) != ADV_SUCCESS) {
-                       /*
-                        * Free the adv_req_t structure by adding it back to the
-                        * board free list.
-                        */
-                       reqp->next_reqp = boardp->adv_reqp;
-                       boardp->adv_reqp = reqp;
-
-                       return ret;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               len = asc_prt_line(cp, leftlen, " Ultra Transfer:      ");
+               ASC_PRT_NEXT();
+               for (i = 0; i <= ADV_MAX_TID; i++) {
+                       len = asc_prt_line(cp, leftlen, " %c",
+                                          (ep_3550->
+                                           ultra_able & ADV_TID_TO_TIDMASK(i))
+                                          ? 'Y' : 'N');
+                       ASC_PRT_NEXT();
                }
-
-               ASC_STATS(scp->device->host, sg_cnt);
-               ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
+               len = asc_prt_line(cp, leftlen, "\n");
+               ASC_PRT_NEXT();
        }
 
-       ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
-       ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
-
-       *adv_scsiqpp = scsiqp;
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               word = ep_3550->wdtr_able;
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               word = ep_38C0800->wdtr_able;
+       } else {
+               word = ep_38C1600->wdtr_able;
+       }
+       len = asc_prt_line(cp, leftlen, " Wide Transfer:       ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               len = asc_prt_line(cp, leftlen, " %c",
+                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       return ASC_NOERROR;
-}
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
+           adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
+               len = asc_prt_line(cp, leftlen,
+                                  " Synchronous Transfer Speed (Mhz):\n  ");
+               ASC_PRT_NEXT();
+               for (i = 0; i <= ADV_MAX_TID; i++) {
+                       char *speed_str;
 
-/*
- * Build scatter-gather list for Adv Library (Wide Board).
- *
- * Additional ADV_SG_BLOCK structures will need to be allocated
- * if the total number of scatter-gather elements exceeds
- * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
- * assumed to be physically contiguous.
- *
- * Return:
- *      ADV_SUCCESS(1) - SG List successfully created
- *      ADV_ERROR(-1) - SG List creation failed
- */
-static int
-adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
-              int use_sg)
-{
-       adv_sgblk_t *sgblkp;
-       ADV_SCSI_REQ_Q *scsiqp;
-       struct scatterlist *slp;
-       int sg_elem_cnt;
-       ADV_SG_BLOCK *sg_block, *prev_sg_block;
-       ADV_PADDR sg_block_paddr;
-       int i;
+                       if (i == 0) {
+                               sdtr_speed = adv_dvc_varp->sdtr_speed1;
+                       } else if (i == 4) {
+                               sdtr_speed = adv_dvc_varp->sdtr_speed2;
+                       } else if (i == 8) {
+                               sdtr_speed = adv_dvc_varp->sdtr_speed3;
+                       } else if (i == 12) {
+                               sdtr_speed = adv_dvc_varp->sdtr_speed4;
+                       }
+                       switch (sdtr_speed & ADV_MAX_TID) {
+                       case 0:
+                               speed_str = "Off";
+                               break;
+                       case 1:
+                               speed_str = "  5";
+                               break;
+                       case 2:
+                               speed_str = " 10";
+                               break;
+                       case 3:
+                               speed_str = " 20";
+                               break;
+                       case 4:
+                               speed_str = " 40";
+                               break;
+                       case 5:
+                               speed_str = " 80";
+                               break;
+                       default:
+                               speed_str = "Unk";
+                               break;
+                       }
+                       len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
+                       ASC_PRT_NEXT();
+                       if (i == 7) {
+                               len = asc_prt_line(cp, leftlen, "\n  ");
+                               ASC_PRT_NEXT();
+                       }
+                       sdtr_speed >>= 4;
+               }
+               len = asc_prt_line(cp, leftlen, "\n");
+               ASC_PRT_NEXT();
+       }
 
-       scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
-       slp = (struct scatterlist *)scp->request_buffer;
-       sg_elem_cnt = use_sg;
-       prev_sg_block = NULL;
-       reqp->sgblkp = NULL;
+       return totlen;
+}
 
-       do {
-               /*
-                * Allocate a 'adv_sgblk_t' structure from the board free
-                * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
-                * (15) scatter-gather elements.
-                */
-               if ((sgblkp = boardp->adv_sgblkp) == NULL) {
-                       ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
-                       ASC_STATS(scp->device->host, adv_build_nosg);
+/*
+ * asc_prt_driver_conf()
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
+static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
+{
+       struct asc_board *boardp = shost_priv(shost);
+       int leftlen;
+       int totlen;
+       int len;
+       int chip_scsi_id;
 
-                       /*
-                        * Allocation failed. Free 'adv_sgblk_t' structures already
-                        * allocated for the request.
-                        */
-                       while ((sgblkp = reqp->sgblkp) != NULL) {
-                               /* Remove 'sgblkp' from the request list. */
-                               reqp->sgblkp = sgblkp->next_sgblkp;
+       leftlen = cplen;
+       totlen = len = 0;
 
-                               /* Add 'sgblkp' to the board free list. */
-                               sgblkp->next_sgblkp = boardp->adv_sgblkp;
-                               boardp->adv_sgblkp = sgblkp;
-                       }
-                       return ASC_BUSY;
-               } else {
-                       /* Complete 'adv_sgblk_t' board allocation. */
-                       boardp->adv_sgblkp = sgblkp->next_sgblkp;
-                       sgblkp->next_sgblkp = NULL;
+       len = asc_prt_line(cp, leftlen,
+                          "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
+                          shost->host_no);
+       ASC_PRT_NEXT();
 
-                       /*
-                        * Get 8 byte aligned virtual and physical addresses for
-                        * the allocated ADV_SG_BLOCK structure.
-                        */
-                       sg_block =
-                           (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
-                       sg_block_paddr = virt_to_bus(sg_block);
+       len = asc_prt_line(cp, leftlen,
+                          " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
+                          shost->host_busy, shost->last_reset, shost->max_id,
+                          shost->max_lun, shost->max_channel);
+       ASC_PRT_NEXT();
 
-                       /*
-                        * Check if this is the first 'adv_sgblk_t' for the request.
-                        */
-                       if (reqp->sgblkp == NULL) {
-                               /* Request's first scatter-gather block. */
-                               reqp->sgblkp = sgblkp;
+       len = asc_prt_line(cp, leftlen,
+                          " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+                          shost->unique_id, shost->can_queue, shost->this_id,
+                          shost->sg_tablesize, shost->cmd_per_lun);
+       ASC_PRT_NEXT();
 
-                               /*
-                                * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
-                                * address pointers.
-                                */
-                               scsiqp->sg_list_ptr = sg_block;
-                               scsiqp->sg_real_addr =
-                                   cpu_to_le32(sg_block_paddr);
-                       } else {
-                               /* Request's second or later scatter-gather block. */
-                               sgblkp->next_sgblkp = reqp->sgblkp;
-                               reqp->sgblkp = sgblkp;
+       len = asc_prt_line(cp, leftlen,
+                          " unchecked_isa_dma %d, use_clustering %d\n",
+                          shost->unchecked_isa_dma, shost->use_clustering);
+       ASC_PRT_NEXT();
 
-                               /*
-                                * Point the previous ADV_SG_BLOCK structure to
-                                * the newly allocated ADV_SG_BLOCK structure.
-                                */
-                               ASC_ASSERT(prev_sg_block != NULL);
-                               prev_sg_block->sg_ptr =
-                                   cpu_to_le32(sg_block_paddr);
-                       }
-               }
+       len = asc_prt_line(cp, leftlen,
+                          " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
+                          boardp->flags, boardp->last_reset, jiffies,
+                          boardp->asc_n_io_port);
+       ASC_PRT_NEXT();
 
-               for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
-                       sg_block->sg_list[i].sg_addr =
-                           cpu_to_le32(sg_dma_address(slp));
-                       sg_block->sg_list[i].sg_count =
-                           cpu_to_le32(sg_dma_len(slp));
-                       ASC_STATS_ADD(scp->device->host, sg_xfer,
-                                     ASC_CEILING(sg_dma_len(slp), 512));
+       len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
+       ASC_PRT_NEXT();
 
-                       if (--sg_elem_cnt == 0) {       /* Last ADV_SG_BLOCK and scatter-gather entry. */
-                               sg_block->sg_cnt = i + 1;
-                               sg_block->sg_ptr = 0L;  /* Last ADV_SG_BLOCK in list. */
-                               return ADV_SUCCESS;
-                       }
-                       slp++;
-               }
-               sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
-               prev_sg_block = sg_block;
+       if (ASC_NARROW_BOARD(boardp)) {
+               chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
+       } else {
+               chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
        }
-       while (1);
-       /* NOTREACHED */
+
+       return totlen;
 }
 
 /*
- * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
+ * asc_prt_asc_board_info()
  *
- * Interrupt callback function for the Narrow SCSI Asc Library.
+ * Print dynamic board configuration information.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
  */
-static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
+static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       asc_board_t *boardp;
-       struct scsi_cmnd *scp;
-       struct Scsi_Host *shost;
+       struct asc_board *boardp = shost_priv(shost);
+       int chip_scsi_id;
+       int leftlen;
+       int totlen;
+       int len;
+       ASC_DVC_VAR *v;
+       ASC_DVC_CFG *c;
        int i;
+       int renegotiate = 0;
 
-       ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
-                (ulong)asc_dvc_varp, (ulong)qdonep);
-       ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
+       v = &boardp->dvc_var.asc_dvc_var;
+       c = &boardp->dvc_cfg.asc_dvc_cfg;
+       chip_scsi_id = c->chip_scsi_id;
 
-       /*
-        * Get the struct scsi_cmnd structure and Scsi_Host structure for the
-        * command that has been completed.
-        */
-       scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
-       ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
+       leftlen = cplen;
+       totlen = len = 0;
 
-       if (scp == NULL) {
-               ASC_PRINT("asc_isr_callback: scp is NULL\n");
-               return;
-       }
-       ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
+       len = asc_prt_line(cp, leftlen,
+                          "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+                          shost->host_no);
+       ASC_PRT_NEXT();
 
-       /*
-        * If the request's host pointer is not valid, display a
-        * message and return.
-        */
-       shost = scp->device->host;
-       for (i = 0; i < asc_board_count; i++) {
-               if (asc_host[i] == shost) {
-                       break;
-               }
-       }
-       if (i == asc_board_count) {
-               ASC_PRINT2
-                   ("asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n",
-                    (ulong)scp, (ulong)shost);
-               return;
-       }
+       len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
+                          "mcode_version 0x%x, err_code %u\n",
+                          c->chip_version, c->mcode_date, c->mcode_version,
+                          v->err_code);
+       ASC_PRT_NEXT();
 
-       ASC_STATS(shost, callback);
-       ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
+       /* Current number of commands waiting for the host. */
+       len = asc_prt_line(cp, leftlen,
+                          " Total Command Pending: %d\n", v->cur_total_qng);
+       ASC_PRT_NEXT();
 
-       /*
-        * If the request isn't found on the active queue, it may
-        * have been removed to handle a reset request.
-        * Display a message and return.
-        */
-       boardp = ASC_BOARDP(shost);
-       ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
-       if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
-               ASC_PRINT2
-                   ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n",
-                    boardp->id, (ulong)scp);
-               return;
+       len = asc_prt_line(cp, leftlen, " Command Queuing:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %X:%c",
+                                  i,
+                                  (v->
+                                   use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
+                                  'Y' : 'N');
+               ASC_PRT_NEXT();
        }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       /*
-        * '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");
-               scp->result = 0;
-
-               /*
-                * If an INQUIRY command completed successfully, then call
-                * the AscInquiryHandling() function to set-up the device.
-                */
-               if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 &&
-                   (scp->request_bufflen - qdonep->remain_bytes) >= 8) {
-                       AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7,
-                                          (ASC_SCSI_INQUIRY *)scp->
-                                          request_buffer);
+       /* Current number of commands waiting for a device. */
+       len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
                }
+               len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               /*
-                * Check for an underrun condition.
-                *
-                * If there was no error and an underrun condition, then
-                * then return the number of underrun bytes.
-                */
-               if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
-                   qdonep->remain_bytes <= scp->request_bufflen) {
-                       ASC_DBG1(1,
-                                "asc_isr_callback: underrun condition %u bytes\n",
-                                (unsigned)qdonep->remain_bytes);
-                       scp->resid = qdonep->remain_bytes;
+       /* Current limit on number of commands that can be sent to a device. */
+       len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
                }
-               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 == SAM_STAT_CHECK_CONDITION) {
-                               ASC_DBG(2,
-                                       "asc_isr_callback: SAM_STAT_CHECK_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 right shifted status byte definitions. For
-                                * instance target drivers use CHECK_CONDITION, defined to
-                                * 0x1, instead of the SCSI defined check condition value
-                                * of 0x2. Host drivers are supposed to return the status
-                                * byte as it is defined by SCSI.
-                                */
-                               scp->result = DRIVER_BYTE(DRIVER_SENSE) |
-                                   STATUS_BYTE(qdonep->d3.scsi_stat);
-                       } else {
-                               scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
-                       }
-                       break;
+               len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               default:
-                       /* QHSTA error occurred */
-                       ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
-                                qdonep->d3.host_stat);
-                       scp->result = HOST_BYTE(DID_BAD_TARGET);
-                       break;
+       /* Indicate whether the device has returned queue full status. */
+       len = asc_prt_line(cp, leftlen, " Command Queue Full:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
                }
-               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;
+               if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
+                       len = asc_prt_line(cp, leftlen, " %X:Y-%d",
+                                          i, boardp->queue_full_cnt[i]);
+               } else {
+                       len = asc_prt_line(cp, leftlen, " %X:N", i);
+               }
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       default:
-               ASC_DBG1(1, "asc_isr_callback: done_stat 0x%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;
+       len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %X:%c",
+                                  i,
+                                  (v->
+                                   sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
        }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       /*
-        * If the 'init_tidmask' bit isn't already set for the target and the
-        * current request finished normally, then set the bit for the target
-        * to indicate that a device is present.
-        */
-       if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
-           qdonep->d3.done_stat == QD_NO_ERROR &&
-           qdonep->d3.host_stat == QHSTA_NO_ERROR) {
-               boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               uchar syn_period_ix;
+
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
+                   ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
+
+               len = asc_prt_line(cp, leftlen, "  %X:", i);
+               ASC_PRT_NEXT();
+
+               if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
+                       len = asc_prt_line(cp, leftlen, " Asynchronous");
+                       ASC_PRT_NEXT();
+               } else {
+                       syn_period_ix =
+                           (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
+                                                          1);
+
+                       len = asc_prt_line(cp, leftlen,
+                                          " Transfer Period Factor: %d (%d.%d Mhz),",
+                                          v->sdtr_period_tbl[syn_period_ix],
+                                          250 /
+                                          v->sdtr_period_tbl[syn_period_ix],
+                                          ASC_TENTHS(250,
+                                                     v->
+                                                     sdtr_period_tbl
+                                                     [syn_period_ix]));
+                       ASC_PRT_NEXT();
+
+                       len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
+                                          boardp->
+                                          sdtr_data[i] & ASC_SYN_MAX_OFFSET);
+                       ASC_PRT_NEXT();
+               }
+
+               if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
+                       len = asc_prt_line(cp, leftlen, "*\n");
+                       renegotiate = 1;
+               } else {
+                       len = asc_prt_line(cp, leftlen, "\n");
+               }
+               ASC_PRT_NEXT();
        }
 
-       /*
-        * Because interrupts may be enabled by the 'struct scsi_cmnd' done
-        * function, add the command to the end of the board's done queue.
-        * The done function for the command will be called from
-        * advansys_interrupt().
-        */
-       asc_enqueue(&boardp->done, scp, ASC_BACK);
+       if (renegotiate) {
+               len = asc_prt_line(cp, leftlen,
+                                  " * = Re-negotiation pending before next command.\n");
+               ASC_PRT_NEXT();
+       }
 
-       return;
+       return totlen;
 }
 
 /*
- * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
+ * asc_prt_adv_board_info()
  *
- * Callback function for the Wide SCSI Adv Library.
+ * Print dynamic board configuration information.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
  */
-static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
+static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       asc_board_t *boardp;
-       adv_req_t *reqp;
-       adv_sgblk_t *sgblkp;
-       struct scsi_cmnd *scp;
-       struct Scsi_Host *shost;
+       struct asc_board *boardp = shost_priv(shost);
+       int leftlen;
+       int totlen;
+       int len;
        int i;
-       ADV_DCNT resid_cnt;
+       ADV_DVC_VAR *v;
+       ADV_DVC_CFG *c;
+       AdvPortAddr iop_base;
+       ushort chip_scsi_id;
+       ushort lramword;
+       uchar lrambyte;
+       ushort tagqng_able;
+       ushort sdtr_able, wdtr_able;
+       ushort wdtr_done, sdtr_done;
+       ushort period = 0;
+       int renegotiate = 0;
 
-       ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
-                (ulong)adv_dvc_varp, (ulong)scsiqp);
-       ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
+       v = &boardp->dvc_var.adv_dvc_var;
+       c = &boardp->dvc_cfg.adv_dvc_cfg;
+       iop_base = v->iop_base;
+       chip_scsi_id = v->chip_scsi_id;
 
-       /*
-        * Get the adv_req_t structure for the command that has been
-        * completed. The adv_req_t structure actually contains the
-        * completed ADV_SCSI_REQ_Q structure.
-        */
-       reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
-       ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
-       if (reqp == NULL) {
-               ASC_PRINT("adv_isr_callback: reqp is NULL\n");
-               return;
-       }
+       leftlen = cplen;
+       totlen = len = 0;
 
-       /*
-        * Get the struct scsi_cmnd structure and Scsi_Host structure for the
-        * command that has been completed.
-        *
-        * Note: The adv_req_t request structure and adv_sgblk_t structure,
-        * if any, are dropped, because a board structure pointer can not be
-        * determined.
-        */
-       scp = reqp->cmndp;
-       ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
-       if (scp == NULL) {
-               ASC_PRINT
-                   ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
-               return;
-       }
-       ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
+       len = asc_prt_line(cp, leftlen,
+                          "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+                          shost->host_no);
+       ASC_PRT_NEXT();
 
-       /*
-        * If the request's host pointer is not valid, display a message
-        * and return.
-        */
-       shost = scp->device->host;
-       for (i = 0; i < asc_board_count; i++) {
-               if (asc_host[i] == shost) {
-                       break;
+       len = asc_prt_line(cp, leftlen,
+                          " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
+                          v->iop_base,
+                          AdvReadWordRegister(iop_base,
+                                              IOPW_SCSI_CFG1) & CABLE_DETECT,
+                          v->err_code);
+       ASC_PRT_NEXT();
+
+       len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
+                          "mcode_version 0x%x\n", c->chip_version,
+                          c->mcode_date, c->mcode_version);
+       ASC_PRT_NEXT();
+
+       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
+       len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
                }
+
+               len = asc_prt_line(cp, leftlen, " %X:%c",
+                                  i,
+                                  (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
        }
-       /*
-        * Note: If the host structure is not found, the adv_req_t request
-        * structure and adv_sgblk_t structure, if any, is dropped.
-        */
-       if (i == asc_board_count) {
-               ASC_PRINT2
-                   ("adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n",
-                    (ulong)scp, (ulong)shost);
-               return;
-       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       ASC_STATS(shost, callback);
-       ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
+       len = asc_prt_line(cp, leftlen, " Queue Limit:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
 
-       /*
-        * If the request isn't found on the active queue, it may have been
-        * removed to handle a reset request. Display a message and return.
-        *
-        * Note: Because the structure may still be in use don't attempt
-        * to free the adv_req_t and adv_sgblk_t, if any, structures.
-        */
-       boardp = ASC_BOARDP(shost);
-       ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
-       if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
-               ASC_PRINT2
-                   ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n",
-                    boardp->id, (ulong)scp);
-               return;
-       }
+               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
+                               lrambyte);
 
-       /*
-        * 'done_status' contains the command's ending status.
-        */
-       switch (scsiqp->done_status) {
-       case QD_NO_ERROR:
-               ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
-               scp->result = 0;
+               len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-               /*
-                * Check for an underrun condition.
-                *
-                * If there was no error and an underrun condition, then
-                * then return the number of underrun bytes.
-                */
-               resid_cnt = le32_to_cpu(scsiqp->data_cnt);
-               if (scp->request_bufflen != 0 && resid_cnt != 0 &&
-                   resid_cnt <= scp->request_bufflen) {
-                       ASC_DBG1(1,
-                                "adv_isr_callback: underrun condition %lu bytes\n",
-                                (ulong)resid_cnt);
-                       scp->resid = resid_cnt;
+       len = asc_prt_line(cp, leftlen, " Command Pending:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
                }
-               break;
 
-       case QD_WITH_ERROR:
-               ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
-               switch (scsiqp->host_status) {
-               case QHSTA_NO_ERROR:
-                       if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
-                               ASC_DBG(2,
-                                       "adv_isr_callback: SAM_STAT_CHECK_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 right shifted status byte definitions. For
-                                * instance target drivers use CHECK_CONDITION, defined to
-                                * 0x1, instead of the SCSI defined check condition value
-                                * of 0x2. Host drivers are supposed to return the status
-                                * byte as it is defined by SCSI.
-                                */
-                               scp->result = DRIVER_BYTE(DRIVER_SENSE) |
-                                   STATUS_BYTE(scsiqp->scsi_status);
-                       } else {
-                               scp->result = STATUS_BYTE(scsiqp->scsi_status);
-                       }
-                       break;
+               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
+                               lrambyte);
 
-               default:
-                       /* Some other QHSTA error occurred. */
-                       ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
-                                scsiqp->host_status);
-                       scp->result = HOST_BYTE(DID_BAD_TARGET);
-                       break;
-               }
-               break;
+               len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       case QD_ABORTED_BY_HOST:
-               ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
-               scp->result =
-                   HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
-               break;
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+       len = asc_prt_line(cp, leftlen, " Wide Enabled:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
 
-       default:
-               ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
-                        scsiqp->done_status);
-               scp->result =
-                   HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
-               break;
+               len = asc_prt_line(cp, leftlen, " %X:%c",
+                                  i,
+                                  (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
        }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       /*
-        * If the 'init_tidmask' bit isn't already set for the target and the
-        * current request finished normally, then set the bit for the target
-        * to indicate that a device is present.
-        */
-       if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
-           scsiqp->done_status == QD_NO_ERROR &&
-           scsiqp->host_status == QHSTA_NO_ERROR) {
-               boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
-       }
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
+       len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
 
-       /*
-        * Because interrupts may be enabled by the 'struct scsi_cmnd' done
-        * function, add the command to the end of the board's done queue.
-        * The done function for the command will be called from
-        * advansys_interrupt().
-        */
-       asc_enqueue(&boardp->done, scp, ASC_BACK);
+               AdvReadWordLram(iop_base,
+                               ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
+                               lramword);
 
-       /*
-        * Free all 'adv_sgblk_t' structures allocated for the request.
-        */
-       while ((sgblkp = reqp->sgblkp) != NULL) {
-               /* Remove 'sgblkp' from the request list. */
-               reqp->sgblkp = sgblkp->next_sgblkp;
+               len = asc_prt_line(cp, leftlen, " %X:%d",
+                                  i, (lramword & 0x8000) ? 16 : 8);
+               ASC_PRT_NEXT();
 
-               /* Add 'sgblkp' to the board free list. */
-               sgblkp->next_sgblkp = boardp->adv_sgblkp;
-               boardp->adv_sgblkp = sgblkp;
+               if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
+                   (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
+                       len = asc_prt_line(cp, leftlen, "*");
+                       ASC_PRT_NEXT();
+                       renegotiate = 1;
+               }
        }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       /*
-        * Free the adv_req_t structure used with the command by adding
-        * it back to the board free list.
-        */
-       reqp->next_reqp = boardp->adv_reqp;
-       boardp->adv_reqp = reqp;
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+       len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ADV_MAX_TID; i++) {
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
+
+               len = asc_prt_line(cp, leftlen, " %X:%c",
+                                  i,
+                                  (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
+                                  'N');
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
 
-       ASC_DBG(1, "adv_isr_callback: done\n");
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
+       for (i = 0; i <= ADV_MAX_TID; i++) {
 
-       return;
-}
+               AdvReadWordLram(iop_base,
+                               ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
+                               lramword);
+               lramword &= ~0x8000;
 
-/*
- * adv_async_callback() - Adv Library asynchronous event callback function.
- */
-static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
-{
-       switch (code) {
-       case ADV_ASYNC_SCSI_BUS_RESET_DET:
-               /*
-                * The firmware detected a SCSI Bus reset.
-                */
-               ASC_DBG(0,
-                       "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
-               break;
+               if ((chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
+                   ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                       continue;
+               }
 
-       case ADV_ASYNC_RDMA_FAILURE:
-               /*
-                * Handle RDMA failure by resetting the SCSI Bus and
-                * possibly the chip if it is unresponsive. Log the error
-                * with a unique code.
-                */
-               ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
-               AdvResetChipAndSB(adv_dvc_varp);
-               break;
+               len = asc_prt_line(cp, leftlen, "  %X:", i);
+               ASC_PRT_NEXT();
 
-       case ADV_HOST_SCSI_BUS_RESET:
-               /*
-                * Host generated SCSI bus reset occurred.
-                */
-               ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
-               break;
+               if ((lramword & 0x1F) == 0) {   /* Check for REQ/ACK Offset 0. */
+                       len = asc_prt_line(cp, leftlen, " Asynchronous");
+                       ASC_PRT_NEXT();
+               } else {
+                       len =
+                           asc_prt_line(cp, leftlen,
+                                        " Transfer Period Factor: ");
+                       ASC_PRT_NEXT();
 
-       default:
-               ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
-               break;
-       }
-}
+                       if ((lramword & 0x1F00) == 0x1100) {    /* 80 Mhz */
+                               len =
+                                   asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
+                               ASC_PRT_NEXT();
+                       } else if ((lramword & 0x1F00) == 0x1000) {     /* 40 Mhz */
+                               len =
+                                   asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
+                               ASC_PRT_NEXT();
+                       } else {        /* 20 Mhz or below. */
 
-/*
- * Add a 'REQP' to the end of specified queue. Set 'tidmask'
- * to indicate a command is queued for the device.
- *
- * 'flag' may be either ASC_FRONT or ASC_BACK.
- *
- * 'REQPNEXT(reqp)' returns reqp's next pointer.
- */
-static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
-{
-       int tid;
-
-       ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n",
-                (ulong)ascq, (ulong)reqp, flag);
-       ASC_ASSERT(reqp != NULL);
-       ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
-       tid = REQPTID(reqp);
-       ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
-       if (flag == ASC_FRONT) {
-               reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
-               ascq->q_first[tid] = reqp;
-               /* If the queue was empty, set the last pointer. */
-               if (ascq->q_last[tid] == NULL) {
-                       ascq->q_last[tid] = reqp;
-               }
-       } else {                /* ASC_BACK */
-               if (ascq->q_last[tid] != NULL) {
-                       ascq->q_last[tid]->host_scribble =
-                           (unsigned char *)reqp;
+                               period = (((lramword >> 8) * 25) + 50) / 4;
+
+                               if (period == 0) {      /* Should never happen. */
+                                       len =
+                                           asc_prt_line(cp, leftlen,
+                                                        "%d (? Mhz), ");
+                                       ASC_PRT_NEXT();
+                               } else {
+                                       len = asc_prt_line(cp, leftlen,
+                                                          "%d (%d.%d Mhz),",
+                                                          period, 250 / period,
+                                                          ASC_TENTHS(250,
+                                                                     period));
+                                       ASC_PRT_NEXT();
+                               }
+                       }
+
+                       len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
+                                          lramword & 0x1F);
+                       ASC_PRT_NEXT();
                }
-               ascq->q_last[tid] = reqp;
-               reqp->host_scribble = NULL;
-               /* If the queue was empty, set the first pointer. */
-               if (ascq->q_first[tid] == NULL) {
-                       ascq->q_first[tid] = reqp;
+
+               if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
+                       len = asc_prt_line(cp, leftlen, "*\n");
+                       renegotiate = 1;
+               } else {
+                       len = asc_prt_line(cp, leftlen, "\n");
                }
+               ASC_PRT_NEXT();
        }
-       /* The queue has at least one entry, set its bit. */
-       ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
-#ifdef ADVANSYS_STATS
-       /* Maintain request queue statistics. */
-       ascq->q_tot_cnt[tid]++;
-       ascq->q_cur_cnt[tid]++;
-       if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
-               ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
-               ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
-                        tid, ascq->q_max_cnt[tid]);
-       }
-       REQPTIME(reqp) = REQTIMESTAMP();
-#endif /* ADVANSYS_STATS */
-       ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp);
-       return;
-}
 
-/*
- * Return first queued 'REQP' on the specified queue for
- * the specified target device. Clear the 'tidmask' bit for
- * the device if no more commands are left queued for it.
- *
- * 'REQPNEXT(reqp)' returns reqp's next pointer.
- */
-static REQP asc_dequeue(asc_queue_t *ascq, int tid)
-{
-       REQP reqp;
-
-       ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
-       ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
-       if ((reqp = ascq->q_first[tid]) != NULL) {
-               ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
-               ascq->q_first[tid] = REQPNEXT(reqp);
-               /* If the queue is empty, clear its bit and the last pointer. */
-               if (ascq->q_first[tid] == NULL) {
-                       ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
-                       ASC_ASSERT(ascq->q_last[tid] == reqp);
-                       ascq->q_last[tid] = NULL;
-               }
-#ifdef ADVANSYS_STATS
-               /* Maintain request queue statistics. */
-               ascq->q_cur_cnt[tid]--;
-               ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
-               REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
-#endif /* ADVANSYS_STATS */
+       if (renegotiate) {
+               len = asc_prt_line(cp, leftlen,
+                                  " * = Re-negotiation pending before next command.\n");
+               ASC_PRT_NEXT();
        }
-       ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp);
-       return reqp;
+
+       return totlen;
 }
 
 /*
- * Return a pointer to a singly linked list of all the requests queued
- * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
- *
- * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
- * the last request returned in the singly linked list.
- *
- * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
- * then all queued requests are concatenated into one list and
- * returned.
- *
- * Note: If 'lastpp' is used to append a new list to the end of
- * an old list, only change the old list last pointer if '*lastpp'
- * (or the function return value) is not NULL, i.e. use a temporary
- * variable for 'lastpp' and check its value after the function return
- * before assigning it to the list last pointer.
+ * asc_proc_copy()
  *
- * Unfortunately collecting queuing time statistics adds overhead to
- * the function that isn't inherent to the function's algorithm.
+ * Copy proc information to a read buffer taking into account the current
+ * read offset in the file and the remaining space in the read buffer.
  */
-static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
+static int
+asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
+             char *cp, int cplen)
 {
-       REQP firstp, lastp;
-       int i;
-
-       ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
-       ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
+       int cnt = 0;
 
-       /*
-        * If 'tid' is not ASC_TID_ALL, return requests only for
-        * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
-        * requests for all tids.
-        */
-       if (tid != ASC_TID_ALL) {
-               /* Return all requests for the specified 'tid'. */
-               if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
-                       /* List is empty; Set first and last return pointers to NULL. */
-                       firstp = lastp = NULL;
-               } else {
-                       firstp = ascq->q_first[tid];
-                       lastp = ascq->q_last[tid];
-                       ascq->q_first[tid] = ascq->q_last[tid] = NULL;
-                       ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
-#ifdef ADVANSYS_STATS
-                       {
-                               REQP reqp;
-                               ascq->q_cur_cnt[tid] = 0;
-                               for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
-                                       REQTIMESTAT("asc_dequeue_list", ascq,
-                                                   reqp, tid);
-                               }
-                       }
-#endif /* ADVANSYS_STATS */
-               }
-       } else {
-               /* Return all requests for all tids. */
-               firstp = lastp = NULL;
-               for (i = 0; i <= ADV_MAX_TID; i++) {
-                       if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
-                               if (firstp == NULL) {
-                                       firstp = ascq->q_first[i];
-                                       lastp = ascq->q_last[i];
-                               } else {
-                                       ASC_ASSERT(lastp != NULL);
-                                       lastp->host_scribble =
-                                           (unsigned char *)ascq->q_first[i];
-                                       lastp = ascq->q_last[i];
-                               }
-                               ascq->q_first[i] = ascq->q_last[i] = NULL;
-                               ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
-#ifdef ADVANSYS_STATS
-                               ascq->q_cur_cnt[i] = 0;
-#endif /* ADVANSYS_STATS */
-                       }
-               }
-#ifdef ADVANSYS_STATS
-               {
-                       REQP reqp;
-                       for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
-                               REQTIMESTAT("asc_dequeue_list", ascq, reqp,
-                                           reqp->device->id);
-                       }
-               }
-#endif /* ADVANSYS_STATS */
-       }
-       if (lastpp) {
-               *lastpp = lastp;
+       ASC_DBG(2, "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_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
+                        (ulong)curbuf, (ulong)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_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
+                        (ulong)curbuf, (ulong)cp, cnt);
+               memcpy(curbuf, cp, cnt);
        }
-       ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp);
-       return firstp;
+       return cnt;
 }
 
-/*
- * Remove the specified 'REQP' from the specified queue for
- * the specified target device. Clear the 'tidmask' bit for the
- * device if no more commands are left queued for it.
- *
- * 'REQPNEXT(reqp)' returns reqp's the next pointer.
- *
- * Return ASC_TRUE if the command was found and removed,
- * otherwise return ASC_FALSE.
- */
-static int asc_rmqueue(asc_queue_t *ascq, REQP reqp)
-{
-       REQP currp, prevp;
-       int tid;
-       int ret = ASC_FALSE;
-
-       ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n",
-                (ulong)ascq, (ulong)reqp);
-       ASC_ASSERT(reqp != NULL);
-
-       tid = REQPTID(reqp);
-       ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
-
-       /*
-        * Handle the common case of 'reqp' being the first
-        * entry on the queue.
-        */
-       if (reqp == ascq->q_first[tid]) {
-               ret = ASC_TRUE;
-               ascq->q_first[tid] = REQPNEXT(reqp);
-               /* If the queue is now empty, clear its bit and the last pointer. */
-               if (ascq->q_first[tid] == NULL) {
-                       ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
-                       ASC_ASSERT(ascq->q_last[tid] == reqp);
-                       ascq->q_last[tid] = NULL;
-               }
-       } else if (ascq->q_first[tid] != NULL) {
-               ASC_ASSERT(ascq->q_last[tid] != NULL);
-               /*
-                * Because the case of 'reqp' being the first entry has been
-                * handled above and it is known the queue is not empty, if
-                * 'reqp' is found on the queue it is guaranteed the queue will
-                * not become empty and that 'q_first[tid]' will not be changed.
-                *
-                * Set 'prevp' to the first entry, 'currp' to the second entry,
-                * and search for 'reqp'.
-                */
-               for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
-                    currp; prevp = currp, currp = REQPNEXT(currp)) {
-                       if (currp == reqp) {
-                               ret = ASC_TRUE;
-                               prevp->host_scribble =
-                                   (unsigned char *)REQPNEXT(currp);
-                               reqp->host_scribble = NULL;
-                               if (ascq->q_last[tid] == reqp) {
-                                       ascq->q_last[tid] = prevp;
-                               }
-                               break;
-                       }
-               }
-       }
 #ifdef ADVANSYS_STATS
-       /* Maintain request queue statistics. */
-       if (ret == ASC_TRUE) {
-               ascq->q_cur_cnt[tid]--;
-               REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
-       }
-       ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
-#endif /* ADVANSYS_STATS */
-       ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret);
-       return ret;
-}
-
-/*
- * Execute as many queued requests as possible for the specified queue.
- *
- * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd.
- */
-static void asc_execute_queue(asc_queue_t *ascq)
-{
-       ADV_SCSI_BIT_ID_TYPE scan_tidmask;
-       REQP reqp;
-       int i;
-
-       ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq);
-       /*
-        * Execute queued commands for devices attached to
-        * the current board in round-robin fashion.
-        */
-       scan_tidmask = ascq->q_tidmask;
-       do {
-               for (i = 0; i <= ADV_MAX_TID; i++) {
-                       if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
-                               if ((reqp = asc_dequeue(ascq, i)) == NULL) {
-                                       scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
-                               } else
-                                   if (asc_execute_scsi_cmnd
-                                       ((struct scsi_cmnd *)reqp)
-                                       == ASC_BUSY) {
-                                       scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
-                                       /*
-                                        * The request returned ASC_BUSY. Enqueue at the front of
-                                        * target's waiting list to maintain correct ordering.
-                                        */
-                                       asc_enqueue(ascq, reqp, ASC_FRONT);
-                               }
-                       }
-               }
-       } while (scan_tidmask);
-       return;
-}
-
-#ifdef CONFIG_PROC_FS
 /*
- * asc_prt_board_devices()
- *
- * Print driver information for devices attached to the board.
+ * asc_prt_board_stats()
  *
  * Note: no single line should be greater than ASC_PRTLINE_SIZE,
  * cf. asc_prt_line().
@@ -6243,10624 +4063,8194 @@ static void asc_execute_queue(asc_queue_t *ascq)
  * Return the number of characters copied into 'cp'. No more than
  * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
+static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
 {
-       asc_board_t *boardp;
-       int leftlen;
-       int totlen;
-       int len;
-       int chip_scsi_id;
-       int i;
+       struct asc_board *boardp = shost_priv(shost);
+       struct asc_stats *s = &boardp->asc_stats;
 
-       boardp = ASC_BOARDP(shost);
-       leftlen = cplen;
-       totlen = len = 0;
+       int leftlen = cplen;
+       int len, totlen = 0;
 
        len = asc_prt_line(cp, leftlen,
-                          "\nDevice Information for AdvanSys SCSI Host %d:\n",
+                          "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
                           shost->host_no);
        ASC_PRT_NEXT();
 
-       if (ASC_NARROW_BOARD(boardp)) {
-               chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
-       } else {
-               chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
-       }
-
-       len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
-                       len = asc_prt_line(cp, leftlen, " %X,", i);
-                       ASC_PRT_NEXT();
-               }
-       }
-       len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
+       len = asc_prt_line(cp, leftlen,
+                          " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
+                          s->queuecommand, s->reset, s->biosparam,
+                          s->interrupt);
        ASC_PRT_NEXT();
 
-       return totlen;
-}
-
-/*
- * Display Wide Board BIOS Information.
- */
-static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
-{
-       asc_board_t *boardp;
-       int leftlen;
-       int totlen;
-       int len;
-       ushort major, minor, letter;
-
-       boardp = ASC_BOARDP(shost);
-       leftlen = cplen;
-       totlen = len = 0;
+       len = asc_prt_line(cp, leftlen,
+                          " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
+                          s->callback, s->done, s->build_error,
+                          s->adv_build_noreq, s->adv_build_nosg);
+       ASC_PRT_NEXT();
 
-       len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
+       len = asc_prt_line(cp, leftlen,
+                          " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
+                          s->exe_noerror, s->exe_busy, s->exe_error,
+                          s->exe_unknown);
        ASC_PRT_NEXT();
 
        /*
-        * If the BIOS saved a valid signature, then fill in
-        * the BIOS code segment base address.
+        * Display data transfer statistics.
         */
-       if (boardp->bios_signature != 0x55AA) {
-               len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
+       if (s->xfer_cnt > 0) {
+               len = asc_prt_line(cp, leftlen, " xfer_cnt %lu, xfer_elem %lu, ",
+                                  s->xfer_cnt, s->xfer_elem);
                ASC_PRT_NEXT();
-               len = asc_prt_line(cp, leftlen,
-                                  "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
+
+               len = asc_prt_line(cp, leftlen, "xfer_bytes %lu.%01lu kb\n",
+                                  s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
                ASC_PRT_NEXT();
-               len = asc_prt_line(cp, leftlen,
-                                  "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
+
+               /* Scatter gather transfer statistics */
+               len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
+                                  s->xfer_elem / s->xfer_cnt,
+                                  ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
                ASC_PRT_NEXT();
-       } else {
-               major = (boardp->bios_version >> 12) & 0xF;
-               minor = (boardp->bios_version >> 8) & 0xF;
-               letter = (boardp->bios_version & 0xFF);
 
-               len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
-                                  major, minor,
-                                  letter >= 26 ? '?' : letter + 'A');
+               len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
+                                  (s->xfer_sect / 2) / s->xfer_elem,
+                                  ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
                ASC_PRT_NEXT();
 
-               /*
-                * Current available ROM BIOS release is 3.1I for UW
-                * and 3.2I for U2W. This code doesn't differentiate
-                * UW and U2W boards.
-                */
-               if (major < 3 || (major <= 3 && minor < 1) ||
-                   (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
-                       len = asc_prt_line(cp, leftlen,
-                                          "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
-                       ASC_PRT_NEXT();
-                       len = asc_prt_line(cp, leftlen,
-                                          "ftp://ftp.connectcom.net/pub\n");
-                       ASC_PRT_NEXT();
-               }
+               len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
+                                  (s->xfer_sect / 2) / s->xfer_cnt,
+                                  ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
+               ASC_PRT_NEXT();
        }
 
        return totlen;
 }
+#endif /* ADVANSYS_STATS */
 
 /*
- * Add serial number to information bar if signature AAh
- * is found in at bit 15-9 (7 bits) of word 1.
- *
- * Serial Number consists fo 12 alpha-numeric digits.
- *
- *       1 - Product type (A,B,C,D..)  Word0: 15-13 (3 bits)
- *       2 - MFG Location (A,B,C,D..)  Word0: 12-10 (3 bits)
- *     3-4 - Product ID (0-99)         Word0: 9-0 (10 bits)
- *       5 - Product revision (A-J)    Word0:  "         "
- *
- *           Signature                 Word1: 15-9 (7 bits)
- *       6 - Year (0-9)                Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
- *     7-8 - Week of the year (1-52)   Word1: 5-0 (6 bits)
- *
- *    9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
+ * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
  *
- * Note 1: Only production cards will have a serial number.
+ * *buffer: I/O buffer
+ * **start: if inout == FALSE pointer into buffer where user read should start
+ * offset: current offset into a /proc/scsi/advansys/[0...] file
+ * length: length of buffer
+ * hostno: Scsi_Host host_no
+ * inout: TRUE - user is writing; FALSE - user is reading
  *
- * Note 2: Signature is most significant 7 bits (0xFE).
+ * Return the number of bytes read from or written to a
+ * /proc/scsi/advansys/[0...] file.
  *
- * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
+ * Note: This function uses the per board buffer 'prtbuf' which is
+ * allocated when the board is initialized in advansys_detect(). The
+ * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
+ * used to write to the buffer. The way asc_proc_copy() is written
+ * if 'prtbuf' is too small it will not be overwritten. Instead the
+ * user just won't get all the available statistics.
  */
-static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
+static int
+advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
+                  off_t offset, int length, int inout)
 {
-       ushort w, num;
-
-       if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
-               return ASC_FALSE;
-       } else {
-               /*
-                * First word - 6 digits.
-                */
-               w = serialnum[0];
-
-               /* Product type - 1st digit. */
-               if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
-                       /* Product type is P=Prototype */
-                       *cp += 0x8;
-               }
-               cp++;
+       struct asc_board *boardp = shost_priv(shost);
+       char *cp;
+       int cplen;
+       int cnt;
+       int totcnt;
+       int leftlen;
+       char *curbuf;
+       off_t advoffset;
 
-               /* Manufacturing location - 2nd digit. */
-               *cp++ = 'A' + ((w & 0x1C00) >> 10);
+       ASC_DBG(1, "begin\n");
 
-               /* Product ID - 3rd, 4th digits. */
-               num = w & 0x3FF;
-               *cp++ = '0' + (num / 100);
-               num %= 100;
-               *cp++ = '0' + (num / 10);
+       /*
+        * User write not supported.
+        */
+       if (inout == TRUE)
+               return -ENOSYS;
 
-               /* Product revision - 5th digit. */
-               *cp++ = 'A' + (num % 10);
+       /*
+        * User read of /proc/scsi/advansys/[0...] file.
+        */
 
-               /*
-                * Second word
-                */
-               w = serialnum[1];
+       /* Copy read data starting at the beginning of the buffer. */
+       *start = buffer;
+       curbuf = buffer;
+       advoffset = 0;
+       totcnt = 0;
+       leftlen = length;
 
-               /*
-                * Year - 6th digit.
-                *
-                * If bit 15 of third word is set, then the
-                * last digit of the year is greater than 7.
-                */
-               if (serialnum[2] & 0x8000) {
-                       *cp++ = '8' + ((w & 0x1C0) >> 6);
-               } else {
-                       *cp++ = '0' + ((w & 0x1C0) >> 6);
+       /*
+        * Get board configuration information.
+        *
+        * advansys_info() returns the board string from its own static buffer.
+        */
+       cp = (char *)advansys_info(shost);
+       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_DBG(1, "totcnt %d\n", totcnt);
+               return totcnt;
+       }
+       advoffset += cplen;
+       curbuf += cnt;
+
+       /*
+        * Display Wide Board BIOS Information.
+        */
+       if (!ASC_NARROW_BOARD(boardp)) {
+               cp = boardp->prtbuf;
+               cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
+               BUG_ON(cplen >= ASC_PRTBUF_SIZE);
+               cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
+                                 cplen);
+               totcnt += cnt;
+               leftlen -= cnt;
+               if (leftlen == 0) {
+                       ASC_DBG(1, "totcnt %d\n", totcnt);
+                       return totcnt;
                }
+               advoffset += cplen;
+               curbuf += cnt;
+       }
 
-               /* Week of year - 7th, 8th digits. */
-               num = w & 0x003F;
-               *cp++ = '0' + num / 10;
-               num %= 10;
-               *cp++ = '0' + num;
+       /*
+        * Display driver information for each device attached to the board.
+        */
+       cp = boardp->prtbuf;
+       cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
+       BUG_ON(cplen >= ASC_PRTBUF_SIZE);
+       cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+       totcnt += cnt;
+       leftlen -= cnt;
+       if (leftlen == 0) {
+               ASC_DBG(1, "totcnt %d\n", totcnt);
+               return totcnt;
+       }
+       advoffset += cplen;
+       curbuf += cnt;
 
-               /*
-                * Third word
-                */
-               w = serialnum[2] & 0x7FFF;
+       /*
+        * Display EEPROM configuration for the board.
+        */
+       cp = boardp->prtbuf;
+       if (ASC_NARROW_BOARD(boardp)) {
+               cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
+       } else {
+               cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
+       }
+       BUG_ON(cplen >= ASC_PRTBUF_SIZE);
+       cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+       totcnt += cnt;
+       leftlen -= cnt;
+       if (leftlen == 0) {
+               ASC_DBG(1, "totcnt %d\n", totcnt);
+               return totcnt;
+       }
+       advoffset += cplen;
+       curbuf += cnt;
 
-               /* Serial number - 9th digit. */
-               *cp++ = 'A' + (w / 1000);
+       /*
+        * Display driver configuration and information for the board.
+        */
+       cp = boardp->prtbuf;
+       cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
+       BUG_ON(cplen >= ASC_PRTBUF_SIZE);
+       cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+       totcnt += cnt;
+       leftlen -= cnt;
+       if (leftlen == 0) {
+               ASC_DBG(1, "totcnt %d\n", totcnt);
+               return totcnt;
+       }
+       advoffset += cplen;
+       curbuf += cnt;
 
-               /* 10th, 11th, 12th digits. */
-               num = w % 1000;
-               *cp++ = '0' + num / 100;
-               num %= 100;
-               *cp++ = '0' + num / 10;
-               num %= 10;
-               *cp++ = '0' + num;
+#ifdef ADVANSYS_STATS
+       /*
+        * Display driver statistics for the board.
+        */
+       cp = boardp->prtbuf;
+       cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
+       BUG_ON(cplen >= ASC_PRTBUF_SIZE);
+       cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+       totcnt += cnt;
+       leftlen -= cnt;
+       if (leftlen == 0) {
+               ASC_DBG(1, "totcnt %d\n", totcnt);
+               return totcnt;
+       }
+       advoffset += cplen;
+       curbuf += cnt;
+#endif /* ADVANSYS_STATS */
 
-               *cp = '\0';     /* Null Terminate the string. */
-               return ASC_TRUE;
+       /*
+        * Display Asc Library dynamic configuration information
+        * for the board.
+        */
+       cp = boardp->prtbuf;
+       if (ASC_NARROW_BOARD(boardp)) {
+               cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
+       } else {
+               cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
        }
-}
+       BUG_ON(cplen >= ASC_PRTBUF_SIZE);
+       cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+       totcnt += cnt;
+       leftlen -= cnt;
+       if (leftlen == 0) {
+               ASC_DBG(1, "totcnt %d\n", totcnt);
+               return totcnt;
+       }
+       advoffset += cplen;
+       curbuf += cnt;
 
-/*
- * asc_prt_asc_board_eeprom()
- *
- * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
-{
-       asc_board_t *boardp;
-       ASC_DVC_VAR *asc_dvc_varp;
-       int leftlen;
-       int totlen;
-       int len;
-       ASCEEP_CONFIG *ep;
-       int i;
-#ifdef CONFIG_ISA
-       int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
-#endif /* CONFIG_ISA */
-       uchar serialstr[13];
+       ASC_DBG(1, "totcnt %d\n", totcnt);
 
-       boardp = ASC_BOARDP(shost);
-       asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
-       ep = &boardp->eep_config.asc_eep;
+       return totcnt;
+}
+#endif /* CONFIG_PROC_FS */
 
-       leftlen = cplen;
-       totlen = len = 0;
+static void asc_scsi_done(struct scsi_cmnd *scp)
+{
+       scsi_dma_unmap(scp);
+       ASC_STATS(scp->device->host, done);
+       scp->scsi_done(scp);
+}
 
-       len = asc_prt_line(cp, leftlen,
-                          "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
-                          shost->host_no);
-       ASC_PRT_NEXT();
+static void AscSetBank(PortAddr iop_base, uchar bank)
+{
+       uchar val;
 
-       if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
-           == ASC_TRUE) {
-               len =
-                   asc_prt_line(cp, leftlen, " Serial Number: %s\n",
-                                serialstr);
-               ASC_PRT_NEXT();
+       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 {
-               if (ep->adapter_info[5] == 0xBB) {
-                       len = asc_prt_line(cp, leftlen,
-                                          " Default Settings Used for EEPROM-less Adapter.\n");
-                       ASC_PRT_NEXT();
-               } else {
-                       len = asc_prt_line(cp, leftlen,
-                                          " Serial Number Signature Not Present.\n");
-                       ASC_PRT_NEXT();
-               }
+               val &= ~CC_BANK_ONE;
        }
+       AscSetChipControl(iop_base, val);
+}
 
-       len = asc_prt_line(cp, leftlen,
-                          " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-                          ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
-                          ep->max_tag_qng);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
-       ASC_PRT_NEXT();
+static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
+{
+       AscSetBank(iop_base, 1);
+       AscWriteChipIH(iop_base, ins_code);
+       AscSetBank(iop_base, 0);
+}
 
-       len = asc_prt_line(cp, leftlen, " Target ID:           ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %d", i);
-               ASC_PRT_NEXT();
+static int AscStartChip(PortAddr iop_base)
+{
+       AscSetChipControl(iop_base, 0);
+       if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+               return (0);
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+       return (1);
+}
 
-       len = asc_prt_line(cp, leftlen, " Disconnects:         ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (ep->
-                                   disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+static int AscStopChip(PortAddr iop_base)
+{
+       uchar cc_val;
 
-       len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (ep->
-                                   use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
+       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);
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+       return (1);
+}
 
-       len = asc_prt_line(cp, leftlen, " Start Motor:         ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (ep->
-                                   start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
+static int AscIsChipHalted(PortAddr iop_base)
+{
+       if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+               if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
+                       return (1);
+               }
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+       return (0);
+}
 
-       len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (ep->
-                                   init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
+static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
+{
+       PortAddr iop_base;
+       int i = 10;
+
+       iop_base = asc_dvc->iop_base;
+       while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
+              && (i-- > 0)) {
+               mdelay(100);
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+       AscStopChip(iop_base);
+       AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
+       udelay(60);
+       AscSetChipIH(iop_base, INS_RFLAG_WTM);
+       AscSetChipIH(iop_base, INS_HALT);
+       AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
+       AscSetChipControl(iop_base, CC_HALT);
+       mdelay(200);
+       AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
+       AscSetChipStatus(iop_base, 0);
+       return (AscIsChipHalted(iop_base));
+}
 
-#ifdef CONFIG_ISA
-       if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
-               len = asc_prt_line(cp, leftlen,
-                                  " Host ISA DMA speed:   %d MB/S\n",
-                                  isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
-               ASC_PRT_NEXT();
+static int AscFindSignature(PortAddr iop_base)
+{
+       ushort sig_word;
+
+       ASC_DBG(1, "AscGetChipSignatureByte(0x%x) 0x%x\n",
+                iop_base, AscGetChipSignatureByte(iop_base));
+       if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
+               ASC_DBG(1, "AscGetChipSignatureWord(0x%x) 0x%x\n",
+                        iop_base, AscGetChipSignatureWord(iop_base));
+               sig_word = AscGetChipSignatureWord(iop_base);
+               if ((sig_word == (ushort)ASC_1000_ID0W) ||
+                   (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
+                       return (1);
+               }
        }
-#endif /* CONFIG_ISA */
+       return (0);
+}
 
-       return totlen;
+static void AscEnableInterrupt(PortAddr iop_base)
+{
+       ushort cfg;
+
+       cfg = AscGetChipCfgLsw(iop_base);
+       AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
 }
 
-/*
- * asc_prt_adv_board_eeprom()
- *
- * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void AscDisableInterrupt(PortAddr iop_base)
 {
-       asc_board_t *boardp;
-       ADV_DVC_VAR *adv_dvc_varp;
-       int leftlen;
-       int totlen;
-       int len;
-       int i;
-       char *termstr;
-       uchar serialstr[13];
-       ADVEEP_3550_CONFIG *ep_3550 = NULL;
-       ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
-       ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
-       ushort word;
-       ushort *wordp;
-       ushort sdtr_speed = 0;
+       ushort cfg;
 
-       boardp = ASC_BOARDP(shost);
-       adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               ep_3550 = &boardp->eep_config.adv_3550_eep;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
+       cfg = AscGetChipCfgLsw(iop_base);
+       AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
+}
+
+static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
+{
+       unsigned char byte_data;
+       unsigned short word_data;
+
+       if (isodd_word(addr)) {
+               AscSetChipLramAddr(iop_base, addr - 1);
+               word_data = AscGetChipLramData(iop_base);
+               byte_data = (word_data >> 8) & 0xFF;
        } else {
-               ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
+               AscSetChipLramAddr(iop_base, addr);
+               word_data = AscGetChipLramData(iop_base);
+               byte_data = word_data & 0xFF;
        }
+       return byte_data;
+}
 
-       leftlen = cplen;
-       totlen = len = 0;
+static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
+{
+       ushort word_data;
 
-       len = asc_prt_line(cp, leftlen,
-                          "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
-                          shost->host_no);
-       ASC_PRT_NEXT();
+       AscSetChipLramAddr(iop_base, addr);
+       word_data = AscGetChipLramData(iop_base);
+       return (word_data);
+}
 
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               wordp = &ep_3550->serial_number_word1;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               wordp = &ep_38C0800->serial_number_word1;
-       } else {
-               wordp = &ep_38C1600->serial_number_word1;
-       }
+#if CC_VERY_LONG_SG_LIST
+static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
+{
+       ushort val_low, val_high;
+       ASC_DCNT dword_data;
 
-       if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
-               len =
-                   asc_prt_line(cp, leftlen, " Serial Number: %s\n",
-                                serialstr);
-               ASC_PRT_NEXT();
-       } else {
-               len = asc_prt_line(cp, leftlen,
-                                  " Serial Number Signature Not Present.\n");
-               ASC_PRT_NEXT();
-       }
+       AscSetChipLramAddr(iop_base, addr);
+       val_low = AscGetChipLramData(iop_base);
+       val_high = AscGetChipLramData(iop_base);
+       dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
+       return (dword_data);
+}
+#endif /* CC_VERY_LONG_SG_LIST */
 
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               len = asc_prt_line(cp, leftlen,
-                                  " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-                                  ep_3550->adapter_scsi_id,
-                                  ep_3550->max_host_qng, ep_3550->max_dvc_qng);
-               ASC_PRT_NEXT();
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               len = asc_prt_line(cp, leftlen,
-                                  " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-                                  ep_38C0800->adapter_scsi_id,
-                                  ep_38C0800->max_host_qng,
-                                  ep_38C0800->max_dvc_qng);
-               ASC_PRT_NEXT();
-       } else {
-               len = asc_prt_line(cp, leftlen,
-                                  " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-                                  ep_38C1600->adapter_scsi_id,
-                                  ep_38C1600->max_host_qng,
-                                  ep_38C1600->max_dvc_qng);
-               ASC_PRT_NEXT();
-       }
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               word = ep_3550->termination;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               word = ep_38C0800->termination_lvd;
-       } else {
-               word = ep_38C1600->termination_lvd;
-       }
-       switch (word) {
-       case 1:
-               termstr = "Low Off/High Off";
-               break;
-       case 2:
-               termstr = "Low Off/High On";
-               break;
-       case 3:
-               termstr = "Low On/High On";
-               break;
-       default:
-       case 0:
-               termstr = "Automatic";
-               break;
-       }
+static void
+AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
+{
+       int i;
 
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               len = asc_prt_line(cp, leftlen,
-                                  " termination: %u (%s), bios_ctrl: 0x%x\n",
-                                  ep_3550->termination, termstr,
-                                  ep_3550->bios_ctrl);
-               ASC_PRT_NEXT();
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               len = asc_prt_line(cp, leftlen,
-                                  " termination: %u (%s), bios_ctrl: 0x%x\n",
-                                  ep_38C0800->termination_lvd, termstr,
-                                  ep_38C0800->bios_ctrl);
-               ASC_PRT_NEXT();
-       } else {
-               len = asc_prt_line(cp, leftlen,
-                                  " termination: %u (%s), bios_ctrl: 0x%x\n",
-                                  ep_38C1600->termination_lvd, termstr,
-                                  ep_38C1600->bios_ctrl);
-               ASC_PRT_NEXT();
+       AscSetChipLramAddr(iop_base, s_addr);
+       for (i = 0; i < words; i++) {
+               AscSetChipLramData(iop_base, set_wval);
        }
+}
 
-       len = asc_prt_line(cp, leftlen, " Target ID:           ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %X", i);
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
+{
+       AscSetChipLramAddr(iop_base, addr);
+       AscSetChipLramData(iop_base, word_val);
+}
 
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               word = ep_3550->disc_enable;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               word = ep_38C0800->disc_enable;
+static 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 = ep_38C1600->disc_enable;
-       }
-       len = asc_prt_line(cp, leftlen, " Disconnects:         ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               word = ep_3550->tagqng_able;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               word = ep_38C0800->tagqng_able;
-       } else {
-               word = ep_38C1600->tagqng_able;
-       }
-       len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               word = ep_3550->start_motor;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               word = ep_38C0800->start_motor;
-       } else {
-               word = ep_38C1600->start_motor;
-       }
-       len = asc_prt_line(cp, leftlen, " Start Motor:         ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-               ASC_PRT_NEXT();
-               for (i = 0; i <= ADV_MAX_TID; i++) {
-                       len = asc_prt_line(cp, leftlen, " %c",
-                                          (ep_3550->
-                                           sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
-                                          'Y' : 'N');
-                       ASC_PRT_NEXT();
-               }
-               len = asc_prt_line(cp, leftlen, "\n");
-               ASC_PRT_NEXT();
-       }
-
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               len = asc_prt_line(cp, leftlen, " Ultra Transfer:      ");
-               ASC_PRT_NEXT();
-               for (i = 0; i <= ADV_MAX_TID; i++) {
-                       len = asc_prt_line(cp, leftlen, " %c",
-                                          (ep_3550->
-                                           ultra_able & ADV_TID_TO_TIDMASK(i))
-                                          ? 'Y' : 'N');
-                       ASC_PRT_NEXT();
-               }
-               len = asc_prt_line(cp, leftlen, "\n");
-               ASC_PRT_NEXT();
-       }
-
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-               word = ep_3550->wdtr_able;
-       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-               word = ep_38C0800->wdtr_able;
-       } else {
-               word = ep_38C1600->wdtr_able;
-       }
-       len = asc_prt_line(cp, leftlen, " Wide Transfer:       ");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               len = asc_prt_line(cp, leftlen, " %c",
-                                  (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-               ASC_PRT_NEXT();
+               word_data = AscReadLramWord(iop_base, addr);
+               word_data &= 0xFF00;
+               word_data |= ((ushort)byte_val & 0x00FF);
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+       AscWriteLramWord(iop_base, addr, word_data);
+}
 
-       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
-           adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
-               len = asc_prt_line(cp, leftlen,
-                                  " Synchronous Transfer Speed (Mhz):\n  ");
-               ASC_PRT_NEXT();
-               for (i = 0; i <= ADV_MAX_TID; i++) {
-                       char *speed_str;
+/*
+ * Copy 2 bytes to LRAM.
+ *
+ * The source data is assumed to be in little-endian order in memory
+ * and is maintained in little-endian order when written to LRAM.
+ */
+static void
+AscMemWordCopyPtrToLram(PortAddr iop_base,
+                       ushort s_addr, uchar *s_buffer, int words)
+{
+       int i;
 
-                       if (i == 0) {
-                               sdtr_speed = adv_dvc_varp->sdtr_speed1;
-                       } else if (i == 4) {
-                               sdtr_speed = adv_dvc_varp->sdtr_speed2;
-                       } else if (i == 8) {
-                               sdtr_speed = adv_dvc_varp->sdtr_speed3;
-                       } else if (i == 12) {
-                               sdtr_speed = adv_dvc_varp->sdtr_speed4;
-                       }
-                       switch (sdtr_speed & ADV_MAX_TID) {
-                       case 0:
-                               speed_str = "Off";
-                               break;
-                       case 1:
-                               speed_str = "  5";
-                               break;
-                       case 2:
-                               speed_str = " 10";
-                               break;
-                       case 3:
-                               speed_str = " 20";
-                               break;
-                       case 4:
-                               speed_str = " 40";
-                               break;
-                       case 5:
-                               speed_str = " 80";
-                               break;
-                       default:
-                               speed_str = "Unk";
-                               break;
-                       }
-                       len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
-                       ASC_PRT_NEXT();
-                       if (i == 7) {
-                               len = asc_prt_line(cp, leftlen, "\n  ");
-                               ASC_PRT_NEXT();
-                       }
-                       sdtr_speed >>= 4;
-               }
-               len = asc_prt_line(cp, leftlen, "\n");
-               ASC_PRT_NEXT();
+       AscSetChipLramAddr(iop_base, s_addr);
+       for (i = 0; i < 2 * words; i += 2) {
+               /*
+                * On a little-endian system the second argument below
+                * produces a little-endian ushort which is written to
+                * LRAM in little-endian order. On a big-endian system
+                * the second argument produces a big-endian ushort which
+                * is "transparently" byte-swapped by outpw() and written
+                * in little-endian order to LRAM.
+                */
+               outpw(iop_base + IOP_RAM_DATA,
+                     ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
        }
-
-       return totlen;
 }
 
 /*
- * asc_prt_driver_conf()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
+ * Copy 4 bytes to LRAM.
  *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
+ * The source data is assumed to be in little-endian order in memory
+ * and is maintained in little-endian order when writen to LRAM.
  */
-static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
+static void
+AscMemDWordCopyPtrToLram(PortAddr iop_base,
+                        ushort s_addr, uchar *s_buffer, int dwords)
 {
-       asc_board_t *boardp;
-       int leftlen;
-       int totlen;
-       int len;
-       int chip_scsi_id;
-
-       boardp = ASC_BOARDP(shost);
-
-       leftlen = cplen;
-       totlen = len = 0;
-
-       len = asc_prt_line(cp, leftlen,
-                          "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
-                          shost->host_no);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
-                          shost->host_busy, shost->last_reset, shost->max_id,
-                          shost->max_lun, shost->max_channel);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-                          shost->unique_id, shost->can_queue, shost->this_id,
-                          shost->sg_tablesize, shost->cmd_per_lun);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " unchecked_isa_dma %d, use_clustering %d\n",
-                          shost->unchecked_isa_dma, shost->use_clustering);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
-                          boardp->flags, boardp->last_reset, jiffies,
-                          boardp->asc_n_io_port);
-       ASC_PRT_NEXT();
-
-       /* 'shost->n_io_port' may be truncated because it is only one byte. */
-       len = asc_prt_line(cp, leftlen,
-                          " io_port 0x%x, n_io_port 0x%x\n",
-                          shost->io_port, shost->n_io_port);
-       ASC_PRT_NEXT();
+       int i;
 
-       if (ASC_NARROW_BOARD(boardp)) {
-               chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
-       } else {
-               chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
+       AscSetChipLramAddr(iop_base, s_addr);
+       for (i = 0; i < 4 * dwords; i += 4) {
+               outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);   /* LSW */
+               outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]);       /* MSW */
        }
-
-       return totlen;
 }
 
 /*
- * asc_prt_asc_board_info()
- *
- * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
+ * Copy 2 bytes from LRAM.
  *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
+ * The source data is assumed to be in little-endian order in LRAM
+ * and is maintained in little-endian order when written to memory.
  */
-static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void
+AscMemWordCopyPtrFromLram(PortAddr iop_base,
+                         ushort s_addr, uchar *d_buffer, int words)
 {
-       asc_board_t *boardp;
-       int chip_scsi_id;
-       int leftlen;
-       int totlen;
-       int len;
-       ASC_DVC_VAR *v;
-       ASC_DVC_CFG *c;
        int i;
-       int renegotiate = 0;
+       ushort word;
 
-       boardp = ASC_BOARDP(shost);
-       v = &boardp->dvc_var.asc_dvc_var;
-       c = &boardp->dvc_cfg.asc_dvc_cfg;
-       chip_scsi_id = c->chip_scsi_id;
-
-       leftlen = cplen;
-       totlen = len = 0;
-
-       len = asc_prt_line(cp, leftlen,
-                          "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-                          shost->host_no);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
-                          c->chip_version, c->lib_version, c->lib_serial_no,
-                          c->mcode_date);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " mcode_version 0x%x, err_code %u\n",
-                          c->mcode_version, v->err_code);
-       ASC_PRT_NEXT();
-
-       /* Current number of commands waiting for the host. */
-       len = asc_prt_line(cp, leftlen,
-                          " Total Command Pending: %d\n", v->cur_total_qng);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen, " Command Queuing:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-               len = asc_prt_line(cp, leftlen, " %X:%c",
-                                  i,
-                                  (v->
-                                   use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
-                                  'Y' : 'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       /* Current number of commands waiting for a device. */
-       len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-               len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       /* Current limit on number of commands that can be sent to a device. */
-       len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-               len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
-               ASC_PRT_NEXT();
+       AscSetChipLramAddr(iop_base, s_addr);
+       for (i = 0; i < 2 * words; i += 2) {
+               word = inpw(iop_base + IOP_RAM_DATA);
+               d_buffer[i] = word & 0xff;
+               d_buffer[i + 1] = (word >> 8) & 0xff;
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+}
 
-       /* Indicate whether the device has returned queue full status. */
-       len = asc_prt_line(cp, leftlen, " Command Queue Full:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-               if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
-                       len = asc_prt_line(cp, leftlen, " %X:Y-%d",
-                                          i, boardp->queue_full_cnt[i]);
-               } else {
-                       len = asc_prt_line(cp, leftlen, " %X:N", i);
-               }
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
+{
+       ASC_DCNT sum;
+       int i;
 
-       len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-               len = asc_prt_line(cp, leftlen, " %X:%c",
-                                  i,
-                                  (v->
-                                   sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
+       sum = 0L;
+       for (i = 0; i < words; i++, s_addr += 2) {
+               sum += AscReadLramWord(iop_base, s_addr);
        }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               uchar syn_period_ix;
-
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
-                   ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-
-               len = asc_prt_line(cp, leftlen, "  %X:", i);
-               ASC_PRT_NEXT();
-
-               if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
-                       len = asc_prt_line(cp, leftlen, " Asynchronous");
-                       ASC_PRT_NEXT();
-               } else {
-                       syn_period_ix =
-                           (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
-                                                          1);
-
-                       len = asc_prt_line(cp, leftlen,
-                                          " Transfer Period Factor: %d (%d.%d Mhz),",
-                                          v->sdtr_period_tbl[syn_period_ix],
-                                          250 /
-                                          v->sdtr_period_tbl[syn_period_ix],
-                                          ASC_TENTHS(250,
-                                                     v->
-                                                     sdtr_period_tbl
-                                                     [syn_period_ix]));
-                       ASC_PRT_NEXT();
+       return (sum);
+}
 
-                       len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
-                                          boardp->
-                                          sdtr_data[i] & ASC_SYN_MAX_OFFSET);
-                       ASC_PRT_NEXT();
-               }
+static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
+{
+       uchar i;
+       ushort s_addr;
+       PortAddr iop_base;
+       ushort warn_code;
 
-               if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-                       len = asc_prt_line(cp, leftlen, "*\n");
-                       renegotiate = 1;
-               } else {
-                       len = asc_prt_line(cp, leftlen, "\n");
-               }
-               ASC_PRT_NEXT();
+       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);
        }
-
-       if (renegotiate) {
-               len = asc_prt_line(cp, leftlen,
-                                  " * = Re-negotiation pending before next command.\n");
-               ASC_PRT_NEXT();
+       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 totlen;
+       return warn_code;
 }
 
-/*
- * asc_prt_adv_board_info()
- *
- * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static ASC_DCNT
+AscLoadMicroCode(PortAddr iop_base,
+                ushort s_addr, uchar *mcode_buf, ushort mcode_size)
 {
-       asc_board_t *boardp;
-       int leftlen;
-       int totlen;
-       int len;
-       int i;
-       ADV_DVC_VAR *v;
-       ADV_DVC_CFG *c;
-       AdvPortAddr iop_base;
-       ushort chip_scsi_id;
-       ushort lramword;
-       uchar lrambyte;
-       ushort tagqng_able;
-       ushort sdtr_able, wdtr_able;
-       ushort wdtr_done, sdtr_done;
-       ushort period = 0;
-       int renegotiate = 0;
-
-       boardp = ASC_BOARDP(shost);
-       v = &boardp->dvc_var.adv_dvc_var;
-       c = &boardp->dvc_cfg.adv_dvc_cfg;
-       iop_base = v->iop_base;
-       chip_scsi_id = v->chip_scsi_id;
-
-       leftlen = cplen;
-       totlen = len = 0;
+       ASC_DCNT chksum;
+       ushort mcode_word_size;
+       ushort mcode_chksum;
 
-       len = asc_prt_line(cp, leftlen,
-                          "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-                          shost->host_no);
-       ASC_PRT_NEXT();
+       /* Write the microcode buffer starting at LRAM address 0. */
+       mcode_word_size = (ushort)(mcode_size >> 1);
+       AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
+       AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
 
-       len = asc_prt_line(cp, leftlen,
-                          " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
-                          v->iop_base,
-                          AdvReadWordRegister(iop_base,
-                                              IOPW_SCSI_CFG1) & CABLE_DETECT,
-                          v->err_code);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
-                          c->chip_version, c->lib_version, c->mcode_date,
-                          c->mcode_version);
-       ASC_PRT_NEXT();
-
-       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-       len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-
-               len = asc_prt_line(cp, leftlen, " %X:%c",
-                                  i,
-                                  (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen, " Queue Limit:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-
-               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
-                               lrambyte);
-
-               len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen, " Command Pending:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
+       chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
+       ASC_DBG(1, "chksum 0x%lx\n", (ulong)chksum);
+       mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
+                                                (ushort)ASC_CODE_SEC_BEG,
+                                                (ushort)((mcode_size -
+                                                          s_addr - (ushort)
+                                                          ASC_CODE_SEC_BEG) /
+                                                         2));
+       ASC_DBG(1, "mcode_chksum 0x%lx\n", (ulong)mcode_chksum);
+       AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
+       AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
+       return chksum;
+}
 
-               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
-                               lrambyte);
+/* Microcode buffer is kept after initialization for error recovery. */
+static uchar _asc_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, 0xC3, 0x12, 0x0D, 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, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
+       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
+       0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
+       0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
+       0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
+       0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
+       0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
+       0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
+       0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
+       0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
+       0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
+       0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
+       0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
+       0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
+       0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
+       0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
+       0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
+       0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
+       0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
+       0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
+       0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
+       0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
+       0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
+       0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
+       0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
+       0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
+       0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
+       0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
+       0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
+       0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
+       0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
+       0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
+       0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
+       0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
+       0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
+       0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
+       0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
+       0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
+       0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
+       0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
+       0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
+       0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
+       0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 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, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
+       0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
+       0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
+       0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 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, 0xEA, 0x82,
+       0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
+       0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
+       0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
+       0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
+       0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
+       0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
+       0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
+       0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
+       0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
+       0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
+       0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
+       0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
+       0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
+       0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
+       0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
+       0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
+       0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
+       0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
+       0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
+       0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
+       0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
+       0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
+       0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
+       0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
+       0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
+       0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
+       0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
+       0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
+       0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
+       0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
+       0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
+       0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
+       0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
+       0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
+       0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
+       0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
+       0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
+       0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
+       0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
+       0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
+       0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
+       0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
+       0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
+       0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
+       0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
+       0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
+       0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
+       0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
+       0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
+       0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
+       0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
+       0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 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, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
+       0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
+       0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
+       0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
+       0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
+       0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
+       0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
+       0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
+       0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
+       0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
+       0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
+       0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
+       0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
+       0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
+       0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
+       0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
+       0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
+       0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
+       0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
+       0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
+       0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
+       0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
+       0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
+       0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
+       0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
+       0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
+       0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
+       0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
+       0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
+       0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
+       0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
+       0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
+       0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
+       0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
+       0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
+       0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
+       0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
+       0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
+       0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
+       0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 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,
+       0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 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, 0xE4, 0x07,
+       0x00, 0x05, 0xDA, 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,
+       0x14, 0x08, 0x16, 0x88, 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, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
+       0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
+       0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
+       0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
+       0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
+       0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
+       0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
+       0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
+       0x31, 0x05, 0x92, 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, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
+       0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
+       0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
+       0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
+       0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
+       0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
+       0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
+       0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
+};
 
-               len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
+static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
 
-       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-       len = asc_prt_line(cp, leftlen, " Wide Enabled:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
+/* Microcode buffer is kept after initialization for error recovery. */
+static unsigned char _adv_asc3550_buf[] = {
+       0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
+       0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
+       0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
+       0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
+       0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
+       0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
+       0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
+       0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
+       0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
+       0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
+       0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
+       0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
+       0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
+       0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
+       0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
+       0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
+       0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
+       0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
+       0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
+       0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
+       0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
+       0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
+       0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
+       0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
+       0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
+       0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
+       0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
+       0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
+       0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
+       0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
+       0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
+       0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
+       0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
+       0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
+       0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
+       0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
+       0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
+       0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
+       0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
+       0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
+       0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
+       0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
+       0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
+       0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
+       0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
+       0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
+       0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
+       0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
+       0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
+       0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
+       0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
+       0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
+       0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
+       0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
+       0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
+       0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
+       0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
+       0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
+       0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
+       0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
+       0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
+       0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
+       0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
+       0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
+       0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
+       0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
+       0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
+       0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
+       0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
+       0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
+       0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
+       0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
+       0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
+       0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
+       0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
+       0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
+       0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
+       0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
+       0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
+       0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
+       0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
+       0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
+       0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
+       0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
+       0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
+       0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
+       0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
+       0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
+       0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
+       0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
+       0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
+       0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
+       0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
+       0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
+       0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
+       0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
+       0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
+       0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
+       0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
+       0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
+       0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
+       0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
+       0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
+       0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
+       0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
+       0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
+       0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
+       0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
+       0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
+       0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
+       0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
+       0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
+       0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
+       0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
+       0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
+       0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
+       0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
+       0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
+       0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
+       0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
+       0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
+       0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
+       0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
+       0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
+       0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
+       0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
+       0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
+       0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
+       0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
+       0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
+       0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
+       0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
+       0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
+       0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
+       0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
+       0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
+       0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
+       0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
+       0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
+       0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
+       0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
+       0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
+       0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
+       0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
+       0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
+       0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
+       0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
+       0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
+       0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
+       0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
+       0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
+       0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
+       0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
+       0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
+       0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
+       0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
+       0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
+       0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
+       0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
+       0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
+       0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
+       0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
+       0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
+       0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
+       0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
+       0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
+       0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
+       0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
+       0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
+       0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
+       0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
+       0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
+       0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
+       0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
+       0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
+       0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
+       0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
+       0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
+       0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
+       0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
+       0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
+       0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
+       0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
+       0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
+       0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
+       0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
+       0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
+       0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
+       0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
+       0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
+       0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
+       0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
+       0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
+       0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
+       0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
+       0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
+       0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
+       0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
+       0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
+       0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
+       0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
+       0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
+       0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
+       0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
+       0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
+       0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
+       0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
+       0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
+       0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
+       0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
+       0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
+       0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
+       0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
+       0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
+       0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
+       0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
+       0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
+       0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
+       0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
+       0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
+       0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
+       0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
+       0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
+       0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
+       0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
+       0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
+       0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
+       0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
+       0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
+       0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
+       0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
+       0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
+       0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
+       0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
+       0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
+       0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
+       0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
+       0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
+       0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
+       0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
+       0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
+       0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
+       0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
+       0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
+       0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
+       0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
+       0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
+       0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
+       0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
+       0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
+       0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
+       0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
+       0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
+       0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
+       0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
+       0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
+       0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
+       0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
+       0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
+       0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
+       0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
+       0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
+       0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
+       0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
+       0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
+       0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
+       0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
+       0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
+       0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
+       0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
+       0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
+       0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
+       0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
+       0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
+       0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
+       0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
+       0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
+       0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
+       0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
+       0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
+       0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
+       0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
+       0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
+       0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
+       0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
+       0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
+       0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
+       0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
+       0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
+       0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
+       0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
+       0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
+       0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
+       0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
+       0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
+       0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
+       0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
+       0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
+       0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
+       0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
+       0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
+       0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
+       0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
+       0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
+       0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
+       0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
+       0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
+       0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
+       0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
+       0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
+       0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
+       0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
+       0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
+       0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
+       0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
+       0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
+       0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
+       0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
+       0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
+       0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
+       0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
+       0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
+       0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
+       0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
+       0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
+       0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
+       0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
+       0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
+       0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
+       0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
+       0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
+       0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
+       0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
+       0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
+       0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
+       0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
+       0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
+       0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
+       0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
+       0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
+       0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
+       0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
+       0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
+       0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
+       0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
+       0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
+       0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
+       0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
+       0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
+       0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
+       0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
+       0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
+       0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
+       0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
+       0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
+       0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
+       0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
+       0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
+       0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
+       0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
+       0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
+       0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
+       0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
+       0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
+       0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
+       0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
+       0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
+       0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
+       0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
+       0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
+       0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
+       0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
+       0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
+       0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
+       0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
+       0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
+       0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
+       0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
+       0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
+       0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
+       0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
+       0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
+       0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
+       0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
+       0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
+       0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
+       0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
+       0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
+       0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
+       0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
+       0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
+       0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
+       0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
+       0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
+       0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
+       0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
+       0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
+       0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
+       0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
+       0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
+       0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
+       0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
+       0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
+       0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
+       0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
+       0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
+       0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
+       0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
+       0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
+       0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
+       0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
+       0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
+       0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
+       0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
+       0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
+       0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
+       0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
+       0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
+       0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
+};
 
-               len = asc_prt_line(cp, leftlen, " %X:%c",
-                                  i,
-                                  (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
+static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf);    /* 0x13AD */
+static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL;    /* Expanded little-endian checksum. */
 
-       AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
-       len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-
-               AdvReadWordLram(iop_base,
-                               ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
-                               lramword);
-
-               len = asc_prt_line(cp, leftlen, " %X:%d",
-                                  i, (lramword & 0x8000) ? 16 : 8);
-               ASC_PRT_NEXT();
-
-               if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
-                   (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-                       len = asc_prt_line(cp, leftlen, "*");
-                       ASC_PRT_NEXT();
-                       renegotiate = 1;
-               }
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-       len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
-       ASC_PRT_NEXT();
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-
-               len = asc_prt_line(cp, leftlen, " %X:%c",
-                                  i,
-                                  (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-                                  'N');
-               ASC_PRT_NEXT();
-       }
-       len = asc_prt_line(cp, leftlen, "\n");
-       ASC_PRT_NEXT();
-
-       AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
-       for (i = 0; i <= ADV_MAX_TID; i++) {
-
-               AdvReadWordLram(iop_base,
-                               ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
-                               lramword);
-               lramword &= ~0x8000;
-
-               if ((chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
-                   ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
-                       continue;
-               }
-
-               len = asc_prt_line(cp, leftlen, "  %X:", i);
-               ASC_PRT_NEXT();
-
-               if ((lramword & 0x1F) == 0) {   /* Check for REQ/ACK Offset 0. */
-                       len = asc_prt_line(cp, leftlen, " Asynchronous");
-                       ASC_PRT_NEXT();
-               } else {
-                       len =
-                           asc_prt_line(cp, leftlen,
-                                        " Transfer Period Factor: ");
-                       ASC_PRT_NEXT();
-
-                       if ((lramword & 0x1F00) == 0x1100) {    /* 80 Mhz */
-                               len =
-                                   asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
-                               ASC_PRT_NEXT();
-                       } else if ((lramword & 0x1F00) == 0x1000) {     /* 40 Mhz */
-                               len =
-                                   asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
-                               ASC_PRT_NEXT();
-                       } else {        /* 20 Mhz or below. */
-
-                               period = (((lramword >> 8) * 25) + 50) / 4;
-
-                               if (period == 0) {      /* Should never happen. */
-                                       len =
-                                           asc_prt_line(cp, leftlen,
-                                                        "%d (? Mhz), ");
-                                       ASC_PRT_NEXT();
-                               } else {
-                                       len = asc_prt_line(cp, leftlen,
-                                                          "%d (%d.%d Mhz),",
-                                                          period, 250 / period,
-                                                          ASC_TENTHS(250,
-                                                                     period));
-                                       ASC_PRT_NEXT();
-                               }
-                       }
-
-                       len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
-                                          lramword & 0x1F);
-                       ASC_PRT_NEXT();
-               }
-
-               if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-                       len = asc_prt_line(cp, leftlen, "*\n");
-                       renegotiate = 1;
-               } else {
-                       len = asc_prt_line(cp, leftlen, "\n");
-               }
-               ASC_PRT_NEXT();
-       }
-
-       if (renegotiate) {
-               len = asc_prt_line(cp, leftlen,
-                                  " * = Re-negotiation pending before next command.\n");
-               ASC_PRT_NEXT();
-       }
-
-       return totlen;
-}
-
-/*
- * asc_proc_copy()
- *
- * Copy proc information to a read buffer taking into account 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 0x%lx, cp 0x%lx, cnt %d\n",
-                        (ulong)curbuf, (ulong)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 0x%lx, cp 0x%lx, cnt %d\n",
-                        (ulong)curbuf, (ulong)cp, cnt);
-               memcpy(curbuf, cp, cnt);
-       }
-       return cnt;
-}
-
-/*
- * asc_prt_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 ASC_PRTLINE_SIZE bytes the stack
- * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
- */
-static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
-{
-       va_list args;
-       int ret;
-       char s[ASC_PRTLINE_SIZE];
-
-       va_start(args, fmt);
-       ret = vsprintf(s, fmt, args);
-       ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
-       if (buf == NULL) {
-               (void)printk(s);
-               ret = 0;
-       } else {
-               ret = min(buflen, ret);
-               memcpy(buf, s, ret);
-       }
-       va_end(args);
-       return ret;
-}
-#endif /* CONFIG_PROC_FS */
-
-/*
- * --- 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.
- */
-static void DvcSleepMilliSecond(ADV_DCNT n)
-{
-       ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n);
-       mdelay(n);
-}
-
-/*
- * Currently and inline noop but leave as a placeholder.
- * Leave DvcEnterCritical() as a noop placeholder.
- */
-static inline ulong DvcEnterCritical(void)
-{
-       return 0;
-}
-
-/*
- * Critical sections are all protected by the board spinlock.
- * Leave DvcLeaveCritical() as a noop placeholder.
- */
-static inline void DvcLeaveCritical(ulong flags)
-{
-       return;
-}
-
-/*
- * void
- * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
- *
- * Calling/Exit State:
- *    none
- *
- * Description:
- *     Output an ASC_SCSI_Q structure to the chip
- */
-static void
-DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
-{
-       int i;
-
-       ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
-       AscSetChipLramAddr(iop_base, s_addr);
-       for (i = 0; i < 2 * words; i += 2) {
-               if (i == 4 || i == 20) {
-                       continue;
-               }
-               outpw(iop_base + IOP_RAM_DATA,
-                     ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
-       }
-}
-
-/*
- * void
- * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
- *
- * Calling/Exit State:
- *    none
- *
- * Description:
- *     Input an ASC_QDONE_INFO structure from the chip
- */
-static void
-DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
-{
-       int i;
-       ushort word;
-
-       AscSetChipLramAddr(iop_base, s_addr);
-       for (i = 0; i < 2 * words; i += 2) {
-               if (i == 10) {
-                       continue;
-               }
-               word = inpw(iop_base + IOP_RAM_DATA);
-               inbuf[i] = word & 0xff;
-               inbuf[i + 1] = (word >> 8) & 0xff;
-       }
-       ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
-}
-
-/*
- * Read a PCI configuration byte.
- */
-static uchar __init DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset)
-{
-#ifdef CONFIG_PCI
-       uchar byte_data;
-       pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
-       return byte_data;
-#else /* !defined(CONFIG_PCI) */
-       return 0;
-#endif /* !defined(CONFIG_PCI) */
-}
-
-/*
- * Write a PCI configuration byte.
- */
-static void __init
-DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data)
-{
-#ifdef CONFIG_PCI
-       pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
-#endif /* CONFIG_PCI */
-}
-
-/*
- * Return the BIOS address of the adapter at the specified
- * I/O port and with the specified bus type.
- */
-static ushort __init AscGetChipBiosAddress(PortAddr iop_base, ushort bus_type)
-{
-       ushort cfg_lsw;
-       ushort bios_addr;
-
-       /*
-        * The PCI BIOS is re-located by the motherboard BIOS. Because
-        * of this the driver can not determine where a PCI BIOS is
-        * loaded and executes.
-        */
-       if (bus_type & ASC_IS_PCI) {
-               return (0);
-       }
-#ifdef CONFIG_ISA
-       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);
-       }                       /* if */
-#endif /* CONFIG_ISA */
-
-       cfg_lsw = AscGetChipCfgLsw(iop_base);
-
-       /*
-        *  ISA PnP uses the top bit as the 32K BIOS flag
-        */
-       if (bus_type == ASC_IS_ISAPNP) {
-               cfg_lsw &= 0x7FFF;
-       }
-       /* if */
-       bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
-                            ASC_BIOS_MIN_ADDR);
-       return (bios_addr);
-}
-
-/*
- * --- Functions Required by the Adv Library
- */
-
-/*
- * DvcGetPhyAddr()
- *
- * Return the physical address of 'vaddr' and set '*lenp' to the
- * number of physically contiguous bytes that follow 'vaddr'.
- * 'flag' indicates the type of structure whose physical address
- * is being translated.
- *
- * Note: Because Linux currently doesn't page the kernel and all
- * kernel buffers are physically contiguous, leave '*lenp' unchanged.
- */
-ADV_PADDR
-DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
-             uchar *vaddr, ADV_SDCNT *lenp, int flag)
-{
-       ADV_PADDR paddr;
-
-       paddr = virt_to_bus(vaddr);
-
-       ASC_DBG4(4,
-                "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
-                (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
-                (ulong)paddr);
-
-       return paddr;
-}
-
-/*
- * Read a PCI configuration byte.
- */
-static uchar __init DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset)
-{
-#ifdef CONFIG_PCI
-       uchar byte_data;
-       pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
-       return byte_data;
-#else /* CONFIG_PCI */
-       return 0;
-#endif /* CONFIG_PCI */
-}
-
-/*
- * Write a PCI configuration byte.
- */
-static void __init
-DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data)
-{
-#ifdef CONFIG_PCI
-       pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
-#else /* CONFIG_PCI */
-       return;
-#endif /* CONFIG_PCI */
-}
-
-/*
- * --- Tracing and Debugging Functions
- */
-
-#ifdef ADVANSYS_STATS
-#ifdef CONFIG_PROC_FS
-/*
- * asc_prt_board_stats()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
-{
-       int leftlen;
-       int totlen;
-       int len;
-       struct asc_stats *s;
-       asc_board_t *boardp;
-
-       leftlen = cplen;
-       totlen = len = 0;
-
-       boardp = ASC_BOARDP(shost);
-       s = &boardp->asc_stats;
-
-       len = asc_prt_line(cp, leftlen,
-                          "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
-                          shost->host_no);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
-                          s->queuecommand, s->reset, s->biosparam,
-                          s->interrupt);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
-                          s->callback, s->done, s->build_error,
-                          s->adv_build_noreq, s->adv_build_nosg);
-       ASC_PRT_NEXT();
-
-       len = asc_prt_line(cp, leftlen,
-                          " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
-                          s->exe_noerror, s->exe_busy, s->exe_error,
-                          s->exe_unknown);
-       ASC_PRT_NEXT();
-
-       /*
-        * Display data transfer statistics.
-        */
-       if (s->cont_cnt > 0) {
-               len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
-               ASC_PRT_NEXT();
-
-               len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
-                                  s->cont_xfer / 2,
-                                  ASC_TENTHS(s->cont_xfer, 2));
-               ASC_PRT_NEXT();
-
-               /* Contiguous transfer average size */
-               len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
-                                  (s->cont_xfer / 2) / s->cont_cnt,
-                                  ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
-               ASC_PRT_NEXT();
-       }
-
-       if (s->sg_cnt > 0) {
-
-               len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
-                                  s->sg_cnt, s->sg_elem);
-               ASC_PRT_NEXT();
-
-               len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
-                                  s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
-               ASC_PRT_NEXT();
-
-               /* Scatter gather transfer statistics */
-               len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
-                                  s->sg_elem / s->sg_cnt,
-                                  ASC_TENTHS(s->sg_elem, s->sg_cnt));
-               ASC_PRT_NEXT();
-
-               len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
-                                  (s->sg_xfer / 2) / s->sg_elem,
-                                  ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
-               ASC_PRT_NEXT();
-
-               len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
-                                  (s->sg_xfer / 2) / s->sg_cnt,
-                                  ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
-               ASC_PRT_NEXT();
-       }
-
-       /*
-        * Display request queuing statistics.
-        */
-       len = asc_prt_line(cp, leftlen,
-                          " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
-                          HZ);
-       ASC_PRT_NEXT();
-
-       return totlen;
-}
-
-/*
- * asc_prt_target_stats()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * This is separated from asc_prt_board_stats because a full set
- * of targets will overflow ASC_PRTBUF_SIZE.
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-static int
-asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen)
-{
-       int leftlen;
-       int totlen;
-       int len;
-       struct asc_stats *s;
-       ushort chip_scsi_id;
-       asc_board_t *boardp;
-       asc_queue_t *active;
-       asc_queue_t *waiting;
-
-       leftlen = cplen;
-       totlen = len = 0;
-
-       boardp = ASC_BOARDP(shost);
-       s = &boardp->asc_stats;
-
-       active = &ASC_BOARDP(shost)->active;
-       waiting = &ASC_BOARDP(shost)->waiting;
-
-       if (ASC_NARROW_BOARD(boardp)) {
-               chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
-       } else {
-               chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
-       }
-
-       if ((chip_scsi_id == tgt_id) ||
-           ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) {
-               return 0;
-       }
-
-       do {
-               if (active->q_tot_cnt[tgt_id] > 0
-                   || waiting->q_tot_cnt[tgt_id] > 0) {
-                       len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id);
-                       ASC_PRT_NEXT();
-
-                       len = asc_prt_line(cp, leftlen,
-                                          "   active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
-                                          active->q_cur_cnt[tgt_id],
-                                          active->q_max_cnt[tgt_id],
-                                          active->q_tot_cnt[tgt_id],
-                                          active->q_min_tim[tgt_id],
-                                          active->q_max_tim[tgt_id],
-                                          (active->q_tot_cnt[tgt_id] ==
-                                           0) ? 0 : (active->
-                                                     q_tot_tim[tgt_id] /
-                                                     active->
-                                                     q_tot_cnt[tgt_id]),
-                                          (active->q_tot_cnt[tgt_id] ==
-                                           0) ? 0 : ASC_TENTHS(active->
-                                                               q_tot_tim
-                                                               [tgt_id],
-                                                               active->
-                                                               q_tot_cnt
-                                                               [tgt_id]));
-                       ASC_PRT_NEXT();
-
-                       len = asc_prt_line(cp, leftlen,
-                                          "   waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
-                                          waiting->q_cur_cnt[tgt_id],
-                                          waiting->q_max_cnt[tgt_id],
-                                          waiting->q_tot_cnt[tgt_id],
-                                          waiting->q_min_tim[tgt_id],
-                                          waiting->q_max_tim[tgt_id],
-                                          (waiting->q_tot_cnt[tgt_id] ==
-                                           0) ? 0 : (waiting->
-                                                     q_tot_tim[tgt_id] /
-                                                     waiting->
-                                                     q_tot_cnt[tgt_id]),
-                                          (waiting->q_tot_cnt[tgt_id] ==
-                                           0) ? 0 : ASC_TENTHS(waiting->
-                                                               q_tot_tim
-                                                               [tgt_id],
-                                                               waiting->
-                                                               q_tot_cnt
-                                                               [tgt_id]));
-                       ASC_PRT_NEXT();
-               }
-       } while (0);
-
-       return totlen;
-}
-#endif /* CONFIG_PROC_FS */
-#endif /* ADVANSYS_STATS */
-
-#ifdef ADVANSYS_DEBUG
-/*
- * asc_prt_scsi_host()
- */
-static void asc_prt_scsi_host(struct Scsi_Host *s)
-{
-       asc_board_t *boardp;
-
-       boardp = ASC_BOARDP(s);
-
-       printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
-       printk(" host_busy %u, host_no %d, last_reset %d,\n",
-              s->host_busy, s->host_no, (unsigned)s->last_reset);
-
-       printk(" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n",
-              (ulong)s->base, (ulong)s->io_port, s->n_io_port, s->irq);
-
-       printk(" dma_channel %d, this_id %d, can_queue %d,\n",
-              s->dma_channel, s->this_id, s->can_queue);
-
-       printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
-              s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
-
-       if (ASC_NARROW_BOARD(boardp)) {
-               asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
-               asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
-       } else {
-               asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
-               asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
-       }
-}
-
-/*
- * asc_prt_scsi_cmnd()
- */
-static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
-{
-       printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
-
-       printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
-              (ulong)s->device->host, (ulong)s->device, s->device->id,
-              s->device->lun, s->device->channel);
-
-       asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
-
-       printk("sc_data_direction %u, resid %d\n",
-              s->sc_data_direction, s->resid);
-
-       printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
-
-       printk(" serial_number 0x%x, retries %d, allowed %d\n",
-              (unsigned)s->serial_number, s->retries, s->allowed);
-
-       printk(" timeout_per_command %d\n", s->timeout_per_command);
-
-       printk
-           (" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
-            (ulong)s->scsi_done, (ulong)s->done, (ulong)s->host_scribble,
-            s->result);
-
-       printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
-}
-
-/*
- * asc_prt_asc_dvc_var()
- */
-static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
-{
-       printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
-
-       printk
-           (" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%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 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n",
-            h->bus_type, (ulong)h->isr_callback, (ulong)h->exe_callback,
-            (unsigned)h->init_sdtr);
-
-       printk
-           (" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%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 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n",
-            (unsigned)h->queue_full_or_busy, (unsigned)h->start_motor,
-            (unsigned)h->scsi_reset_wait);
-
-       printk
-           (" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\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 %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n",
-            (unsigned)h->last_q_shortage, (unsigned)h->init_state,
-            (unsigned)h->no_scam, (unsigned)h->pci_fix_asyn_xfer);
-
-       printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
-}
-
-/*
- * asc_prt_asc_dvc_cfg()
- */
-static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
-{
-       printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
-
-       printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
-              h->can_tagged_qng, h->cmd_qng_enabled);
-       printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
-              h->disc_enable, h->sdtr_enable);
-
-       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 %u, lib_version %u, mcode_date 0x%x,\n",
-            to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
-            h->mcode_date);
-
-       printk(" mcode_version %d, overrun_buf 0x%lx\n",
-              h->mcode_version, (ulong)h->overrun_buf);
-}
-
-/*
- * asc_prt_asc_scsi_q()
- */
-static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
-{
-       ASC_SG_HEAD *sgp;
-       int i;
-
-       printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
-
-       printk
-           (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
-            q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
-            q->q2.tag_code);
-
-       printk
-           (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
-            (ulong)le32_to_cpu(q->q1.data_addr),
-            (ulong)le32_to_cpu(q->q1.data_cnt),
-            (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
-
-       printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
-              (ulong)q->cdbptr, q->q2.cdb_len,
-              (ulong)q->sg_head, q->q1.sg_queue_cnt);
-
-       if (q->sg_head) {
-               sgp = q->sg_head;
-               printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)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 0x%lx, bytes %lu\n",
-                              i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
-                              (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
-               }
-
-       }
-}
-
-/*
- * asc_prt_asc_qdone_info()
- */
-static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
-{
-       printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
-       printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
-              (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
-              q->d2.tag_code);
-       printk
-           (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
-            q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
-}
-
-/*
- * asc_prt_adv_dvc_var()
- *
- * Display an ADV_DVC_VAR structure.
- */
-static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
-{
-       printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
-
-       printk("  iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
-              (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
-
-       printk("  isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
-              (ulong)h->isr_callback, (unsigned)h->sdtr_able,
-              (unsigned)h->wdtr_able);
-
-       printk("  start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
-              (unsigned)h->start_motor,
-              (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
-
-       printk("  max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
-              (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
-              (ulong)h->carr_freelist);
-
-       printk("  icq_sp 0x%lx, irq_sp 0x%lx\n",
-              (ulong)h->icq_sp, (ulong)h->irq_sp);
-
-       printk("  no_scam 0x%x, tagqng_able 0x%x\n",
-              (unsigned)h->no_scam, (unsigned)h->tagqng_able);
-
-       printk("  chip_scsi_id 0x%x, cfg 0x%lx\n",
-              (unsigned)h->chip_scsi_id, (ulong)h->cfg);
-}
-
-/*
- * asc_prt_adv_dvc_cfg()
- *
- * Display an ADV_DVC_CFG structure.
- */
-static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
-{
-       printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
-
-       printk("  disc_enable 0x%x, termination 0x%x\n",
-              h->disc_enable, h->termination);
-
-       printk("  chip_version 0x%x, mcode_date 0x%x\n",
-              h->chip_version, h->mcode_date);
-
-       printk("  mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
-              h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
-
-       printk("  control_flag 0x%x, pci_slot_info 0x%x\n",
-              h->control_flag, h->pci_slot_info);
-}
-
-/*
- * asc_prt_adv_scsi_req_q()
- *
- * Display an ADV_SCSI_REQ_Q structure.
- */
-static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
-{
-       int sg_blk_cnt;
-       struct asc_sg_block *sg_ptr;
-
-       printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
-
-       printk("  target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
-              q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
-
-       printk("  cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
-              q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
-
-       printk("  data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
-              (ulong)le32_to_cpu(q->data_cnt),
-              (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
-
-       printk
-           ("  cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
-            q->cdb_len, q->done_status, q->host_status, q->scsi_status);
-
-       printk("  sg_working_ix 0x%x, target_cmd %u\n",
-              q->sg_working_ix, q->target_cmd);
-
-       printk("  scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
-              (ulong)le32_to_cpu(q->scsiq_rptr),
-              (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
-
-       /* Display the request's ADV_SG_BLOCK structures. */
-       if (q->sg_list_ptr != NULL) {
-               sg_blk_cnt = 0;
-               while (1) {
-                       /*
-                        * 'sg_ptr' is a physical address. Convert it to a virtual
-                        * address by indexing 'sg_blk_cnt' into the virtual address
-                        * array 'sg_list_ptr'.
-                        *
-                        * XXX - Assumes all SG physical blocks are virtually contiguous.
-                        */
-                       sg_ptr =
-                           &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
-                       asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
-                       if (sg_ptr->sg_ptr == 0) {
-                               break;
-                       }
-                       sg_blk_cnt++;
-               }
-       }
-}
-
-/*
- * asc_prt_adv_sgblock()
- *
- * Display an ADV_SG_BLOCK structure.
- */
-static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
-{
-       int i;
-
-       printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
-              (ulong)b, sgblockno);
-       printk("  sg_cnt %u, sg_ptr 0x%lx\n",
-              b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
-       ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK);
-       if (b->sg_ptr != 0) {
-               ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK);
-       }
-       for (i = 0; i < b->sg_cnt; i++) {
-               printk("  [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
-                      i, (ulong)b->sg_list[i].sg_addr,
-                      (ulong)b->sg_list[i].sg_count);
-       }
-}
-
-/*
- * 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)]);
-                       break;
-               case 2:
-                       printk(" %2.2X%2.2X",
-                              (unsigned)s[i + (j * 4)],
-                              (unsigned)s[i + (j * 4) + 1]);
-                       break;
-               case 3:
-                       printk(" %2.2X%2.2X%2.2X",
-                              (unsigned)s[i + (j * 4) + 1],
-                              (unsigned)s[i + (j * 4) + 2],
-                              (unsigned)s[i + (j * 4) + 3]);
-                       break;
-               }
-
-               printk("\n");
-       }
-}
-#endif /* ADVANSYS_DEBUG */
-
-/*
- * --- Asc Library Functions
- */
-
-static ushort __init 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));
-}
-
-static uchar __init 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));
-}
-
-static uchar __init AscGetChipScsiCtrl(PortAddr iop_base)
-{
-       uchar sc;
-
-       AscSetBank(iop_base, 1);
-       sc = inp(iop_base + IOP_REG_SC);
-       AscSetBank(iop_base, 0);
-       return (sc);
-}
-
-static uchar __init 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));
-}
-
-static ushort __init 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);
-       }
-       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);
-       }
-       return (0);
-}
-
-static ASC_DCNT
-AscLoadMicroCode(PortAddr iop_base,
-                ushort s_addr, uchar *mcode_buf, ushort mcode_size)
-{
-       ASC_DCNT chksum;
-       ushort mcode_word_size;
-       ushort mcode_chksum;
-
-       /* Write the microcode buffer starting at LRAM address 0. */
-       mcode_word_size = (ushort)(mcode_size >> 1);
-       AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
-       AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
-
-       chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
-       ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
-       mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
-                                                (ushort)ASC_CODE_SEC_BEG,
-                                                (ushort)((mcode_size -
-                                                          s_addr - (ushort)
-                                                          ASC_CODE_SEC_BEG) /
-                                                         2));
-       ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
-                (ulong)mcode_chksum);
-       AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
-       AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
-       return (chksum);
-}
-
-static int AscFindSignature(PortAddr iop_base)
-{
-       ushort sig_word;
-
-       ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
-                iop_base, AscGetChipSignatureByte(iop_base));
-       if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
-               ASC_DBG2(1,
-                        "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
-                        iop_base, AscGetChipSignatureWord(iop_base));
-               sig_word = AscGetChipSignatureWord(iop_base);
-               if ((sig_word == (ushort)ASC_1000_ID0W) ||
-                   (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
-                       return (1);
-               }
-       }
-       return (0);
-}
-
-static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = {
-       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
-};
-
-#ifdef CONFIG_ISA
-static uchar _isa_pnp_inited __initdata = 0;
-
-static PortAddr __init 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);
-}
-
-static PortAddr __init 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 (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
-                       ASC_DBG1(1,
-                                "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n",
-                                iop_base);
-                       continue;
-               }
-               ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n",
-                        iop_base);
-               release_region(iop_base, ASC_IOADR_GAP);
-               if (AscFindSignature(iop_base)) {
-                       return (iop_base);
-               }
-       }
-       return (0);
-}
-
-static void __init AscSetISAPNPWaitForKey(void)
-{
-       outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
-       outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
-       return;
-}
-#endif /* CONFIG_ISA */
-
-static void __init AscToggleIRQAct(PortAddr iop_base)
-{
-       AscSetChipStatus(iop_base, CIW_IRQ_ACT);
-       AscSetChipStatus(iop_base, 0);
-       return;
-}
-
-static uchar __init 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);
-       }
-       if ((bus_type & ASC_IS_VL) != 0) {
-               cfg_lsw = AscGetChipCfgLsw(iop_base);
-               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)));
-       }
-       cfg_lsw = AscGetChipCfgLsw(iop_base);
-       chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
-       if (chip_irq == 3)
-               chip_irq += (uchar)2;
-       return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
-}
-
-static uchar __init
-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));
-       }
-       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));
-       }
-       return (0);
-}
-
-#ifdef CONFIG_ISA
-static void __init 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;
-}
-#endif /* CONFIG_ISA */
-
-static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
-{
-       EXT_MSG ext_msg;
-       EXT_MSG 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;
-       asc_board_t *boardp;
-
-       ASC_ASSERT(asc_dvc->drv_ptr != NULL);
-       boardp = asc_dvc->drv_ptr;
-
-       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_DISABLE_ASYN_USE_SYN_FIX) {
-               if (asc_dvc->pci_fix_asyn_xfer & target_id) {
-                       AscSetChipSDTR(iop_base, 0, tid_no);
-                       boardp->sdtr_data[tid_no] = 0;
-               }
-               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-               return (0);
-       } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
-               if (asc_dvc->pci_fix_asyn_xfer & target_id) {
-                       AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
-                       boardp->sdtr_data[tid_no] = asyn_sdtr;
-               }
-               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-               return (0);
-       } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
-
-               AscMemWordCopyPtrFromLram(iop_base,
-                                         ASCV_MSGIN_BEG,
-                                         (uchar *)&ext_msg,
-                                         sizeof(EXT_MSG) >> 1);
-
-               if (ext_msg.msg_type == MS_EXTEND &&
-                   ext_msg.msg_req == MS_SDTR_CODE &&
-                   ext_msg.msg_len == MS_SDTR_LEN) {
-                       sdtr_accept = TRUE;
-                       if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
-
-                               sdtr_accept = FALSE;
-                               ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
-                       }
-                       if ((ext_msg.xfer_period <
-                            asc_dvc->sdtr_period_tbl[asc_dvc->
-                                                     host_init_sdtr_index])
-                           || (ext_msg.xfer_period >
-                               asc_dvc->sdtr_period_tbl[asc_dvc->
-                                                        max_sdtr_index])) {
-                               sdtr_accept = FALSE;
-                               ext_msg.xfer_period =
-                                   asc_dvc->sdtr_period_tbl[asc_dvc->
-                                                            host_init_sdtr_index];
-                       }
-                       if (sdtr_accept) {
-                               sdtr_data =
-                                   AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
-                                                  ext_msg.req_ack_offset);
-                               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);
-                                       boardp->sdtr_data[tid_no] = asyn_sdtr;
-                               }
-                       }
-                       if (ext_msg.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_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;
-                                       sdtr_data =
-                                           AscCalSDTRData(asc_dvc,
-                                                          ext_msg.xfer_period,
-                                                          ext_msg.
-                                                          req_ack_offset);
-                                       AscSetChipSDTR(iop_base, sdtr_data,
-                                                      tid_no);
-                                       boardp->sdtr_data[tid_no] = sdtr_data;
-                               } else {
-
-                                       q_cntl |= QC_MSG_OUT;
-                                       AscMsgOutSDTR(asc_dvc,
-                                                     ext_msg.xfer_period,
-                                                     ext_msg.req_ack_offset);
-                                       asc_dvc->pci_fix_asyn_xfer &=
-                                           ~target_id;
-                                       sdtr_data =
-                                           AscCalSDTRData(asc_dvc,
-                                                          ext_msg.xfer_period,
-                                                          ext_msg.
-                                                          req_ack_offset);
-                                       AscSetChipSDTR(iop_base, sdtr_data,
-                                                      tid_no);
-                                       boardp->sdtr_data[tid_no] = sdtr_data;
-                                       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 (ext_msg.msg_type == MS_EXTEND &&
-                          ext_msg.msg_req == MS_WDTR_CODE &&
-                          ext_msg.msg_len == MS_WDTR_LEN) {
-
-                       ext_msg.wdtr_width = 0;
-                       AscMemWordCopyPtrToLram(iop_base,
-                                               ASCV_MSGOUT_BEG,
-                                               (uchar *)&ext_msg,
-                                               sizeof(EXT_MSG) >> 1);
-                       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 {
-
-                       ext_msg.msg_type = MESSAGE_REJECT;
-                       AscMemWordCopyPtrToLram(iop_base,
-                                               ASCV_MSGOUT_BEG,
-                                               (uchar *)&ext_msg,
-                                               sizeof(EXT_MSG) >> 1);
-                       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_CHK_CONDITION) {
-
-               q_cntl |= QC_REQ_SENSE;
-
-               if ((asc_dvc->init_sdtr & target_id) != 0) {
-
-                       asc_dvc->sdtr_done &= ~target_id;
-
-                       sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
-                       q_cntl |= QC_MSG_OUT;
-                       AscMsgOutSDTR(asc_dvc,
-                                     asc_dvc->
-                                     sdtr_period_tbl[(sdtr_data >> 4) &
-                                                     (uchar)(asc_dvc->
-                                                             max_sdtr_index -
-                                                             1)],
-                                     (uchar)(sdtr_data & (uchar)
-                                             ASC_SYN_MAX_OFFSET));
-               }
-
-               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;
-               if ((asc_dvc->pci_fix_asyn_xfer & target_id)
-                   && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
-                   ) {
-
-                       tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
-                                    | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
-
-               }
-               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) {
-
-               AscMemWordCopyPtrFromLram(iop_base,
-                                         ASCV_MSGOUT_BEG,
-                                         (uchar *)&out_msg,
-                                         sizeof(EXT_MSG) >> 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);
-                       boardp->sdtr_data[tid_no] = asyn_sdtr;
-               }
-               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 == SAM_STAT_TASK_SET_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);
-
-                                       /*
-                                        * Set the device queue depth to the number of
-                                        * active requests when the QUEUE FULL condition
-                                        * was encountered.
-                                        */
-                                       boardp->queue_full |= target_id;
-                                       boardp->queue_full_cnt[tid_no] =
-                                           cur_dvc_qng;
-                               }
-                       }
-               }
-               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-               return (0);
-       }
-#if CC_VERY_LONG_SG_LIST
-       else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
-               uchar q_no;
-               ushort q_addr;
-               uchar sg_wk_q_no;
-               uchar first_sg_wk_q_no;
-               ASC_SCSI_Q *scsiq;      /* Ptr to driver request. */
-               ASC_SG_HEAD *sg_head;   /* Ptr to driver SG request. */
-               ASC_SG_LIST_Q scsi_sg_q;        /* Structure written to queue. */
-               ushort sg_list_dwords;
-               ushort sg_entry_cnt;
-               uchar next_qp;
-               int i;
-
-               q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
-               if (q_no == ASC_QLINK_END) {
-                       return (0);
-               }
-
-               q_addr = ASC_QNO_TO_QADDR(q_no);
-
-               /*
-                * Convert the request's SRB pointer to a host ASC_SCSI_REQ
-                * structure pointer using a macro provided by the driver.
-                * The ASC_SCSI_REQ pointer provides a pointer to the
-                * host ASC_SG_HEAD structure.
-                */
-               /* Read request's SRB pointer. */
-               scsiq = (ASC_SCSI_Q *)
-                   ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
-                                                                   (ushort)
-                                                                   (q_addr +
-                                                                    ASC_SCSIQ_D_SRBPTR))));
-
-               /*
-                * Get request's first and working SG queue.
-                */
-               sg_wk_q_no = AscReadLramByte(iop_base,
-                                            (ushort)(q_addr +
-                                                     ASC_SCSIQ_B_SG_WK_QP));
-
-               first_sg_wk_q_no = AscReadLramByte(iop_base,
-                                                  (ushort)(q_addr +
-                                                           ASC_SCSIQ_B_FIRST_SG_WK_QP));
-
-               /*
-                * Reset request's working SG queue back to the
-                * first SG queue.
-                */
-               AscWriteLramByte(iop_base,
-                                (ushort)(q_addr +
-                                         (ushort)ASC_SCSIQ_B_SG_WK_QP),
-                                first_sg_wk_q_no);
-
-               sg_head = scsiq->sg_head;
-
-               /*
-                * Set sg_entry_cnt to the number of SG elements
-                * that will be completed on this interrupt.
-                *
-                * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
-                * SG elements. The data_cnt and data_addr fields which
-                * add 1 to the SG element capacity are not used when
-                * restarting SG handling after a halt.
-                */
-               if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
-                       sg_entry_cnt = ASC_MAX_SG_LIST - 1;
-
-                       /*
-                        * Keep track of remaining number of SG elements that will
-                        * need to be handled on the next interrupt.
-                        */
-                       scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
-               } else {
-                       sg_entry_cnt = scsiq->remain_sg_entry_cnt;
-                       scsiq->remain_sg_entry_cnt = 0;
-               }
-
-               /*
-                * Copy SG elements into the list of allocated SG queues.
-                *
-                * Last index completed is saved in scsiq->next_sg_index.
-                */
-               next_qp = first_sg_wk_q_no;
-               q_addr = ASC_QNO_TO_QADDR(next_qp);
-               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;
-                               /*
-                                * After very first SG queue RISC FW uses next
-                                * SG queue first element then checks sg_list_cnt
-                                * against zero and then decrements, so set
-                                * sg_list_cnt 1 less than number of SG elements
-                                * in each SG queue.
-                                */
-                               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 {
-                               /*
-                                * This is the last SG queue in the list of
-                                * allocated SG queues. If there are more
-                                * SG elements than will fit in the allocated
-                                * queues, then set the QCSG_SG_XFER_MORE flag.
-                                */
-                               if (scsiq->remain_sg_entry_cnt != 0) {
-                                       scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
-                               } else {
-                                       scsi_sg_q.cntl |= QCSG_SG_XFER_END;
-                               }
-                               /* equals sg_entry_cnt * 2 */
-                               sg_list_dwords = sg_entry_cnt << 1;
-                               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;
-                       }
-
-                       scsi_sg_q.q_no = next_qp;
-                       AscMemWordCopyPtrToLram(iop_base,
-                                               q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
-                                               (uchar *)&scsi_sg_q,
-                                               sizeof(ASC_SG_LIST_Q) >> 1);
-
-                       AscMemDWordCopyPtrToLram(iop_base,
-                                                q_addr + ASC_SGQ_LIST_BEG,
-                                                (uchar *)&sg_head->
-                                                sg_list[scsiq->next_sg_index],
-                                                sg_list_dwords);
-
-                       scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
-
-                       /*
-                        * If the just completed SG queue contained the
-                        * last SG element, then no more SG queues need
-                        * to be written.
-                        */
-                       if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
-                               break;
-                       }
-
-                       next_qp = AscReadLramByte(iop_base,
-                                                 (ushort)(q_addr +
-                                                          ASC_SCSIQ_B_FWD));
-                       q_addr = ASC_QNO_TO_QADDR(next_qp);
-               }
-
-               /*
-                * Clear the halt condition so the RISC will be restarted
-                * after the return.
-                */
-               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-               return (0);
-       }
-#endif /* CC_VERY_LONG_SG_LIST */
-       return (0);
-}
-
-static uchar
-_AscCopyLramScsiDoneQ(PortAddr iop_base,
-                     ushort q_addr,
-                     ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
-{
-       ushort _val;
-       uchar sg_queue_cnt;
-
-       DvcGetQinfo(iop_base,
-                   q_addr + ASC_SCSIQ_DONE_INFO_BEG,
-                   (uchar *)scsiq,
-                   (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
-
-       _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->extra_bytes = (uchar)(_val >> 8);
-
-       /*
-        * Read high word of remain bytes from alternate location.
-        */
-       scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
-                                                         (ushort)(q_addr +
-                                                                  (ushort)
-                                                                  ASC_SCSIQ_W_ALT_DC1)))
-                              << 16);
-       /*
-        * Read low word of remain bytes from original location.
-        */
-       scsiq->remain_bytes += AscReadLramWord(iop_base,
-                                              (ushort)(q_addr + (ushort)
-                                                       ASC_SCSIQ_DW_REMAIN_XFER_CNT));
-
-       scsiq->remain_bytes &= max_dma_count;
-       return (sg_queue_cnt);
-}
-
-static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
-{
-       uchar next_qp;
-       uchar n_q_used;
-       uchar sg_list_qp;
-       uchar sg_queue_cnt;
-       uchar q_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 *scsiq;
-       int false_overrun;
-       ASC_ISR_CALLBACK asc_isr_callback;
-
-       iop_base = asc_dvc->iop_base;
-       asc_isr_callback = asc_dvc->isr_callback;
-       n_q_used = 1;
-       scsiq = (ASC_QDONE_INFO *)&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 (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
-                               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 (scsiq->extra_bytes != 0) {
-                               scsiq->remain_bytes +=
-                                   (ADV_DCNT)scsiq->extra_bytes;
-                       }
-                       if (scsiq->d3.done_stat == QD_WITH_ERROR) {
-                               if (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;
-                                       }
-                               } else if (scsiq->d3.host_stat ==
-                                          QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
-                                       AscStopChip(iop_base);
-                                       AscSetChipControl(iop_base,
-                                                         (uchar)(CC_SCSI_RESET
-                                                                 | CC_HALT));
-                                       DvcDelayNanoSecond(asc_dvc, 60000);
-                                       AscSetChipControl(iop_base, CC_HALT);
-                                       AscSetChipStatus(iop_base,
-                                                        CIW_CLR_SCSI_RESET_INT);
-                                       AscSetChipStatus(iop_base, 0);
-                                       AscSetChipControl(iop_base, 0);
-                               }
-                       }
-                       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))
-                                    == START_STOP)) {
-                                       asc_dvc->unit_not_ready &= ~target_id;
-                                       if (scsiq->d3.done_stat != QD_NO_ERROR) {
-                                               asc_dvc->start_motor &=
-                                                   ~target_id;
-                                       }
-                               }
-                       }
-                       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);
-}
-
-static int AscISR(ASC_DVC_VAR *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;
-
-       if (AscIsIntPending(iop_base) == 0) {
-               return int_pending;
-       }
-
-       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);
-               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));
-       chipstat = AscGetChipStatus(iop_base);
-       if (chipstat & CSW_SCSI_RESET_LATCH) {
-               if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
-                       int i = 10;
-                       int_pending = TRUE;
-                       asc_dvc->sdtr_done = 0;
-                       saved_ctrl_reg &= (uchar)(~CC_HALT);
-                       while ((AscGetChipStatus(iop_base) &
-                               CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
-                               DvcSleepMilliSecond(100);
-                       }
-                       AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
-                       AscSetChipControl(iop_base, CC_HALT);
-                       AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
-                       AscSetChipStatus(iop_base, 0);
-                       chipstat = AscGetChipStatus(iop_base);
-               }
-       }
-       saved_ram_addr = AscGetChipLramAddr(iop_base);
-       host_flag = AscReadLramByte(iop_base,
-                                   ASCV_HOST_FLAG_B) &
-           (uchar)(~ASC_HOST_FLAG_IN_ISR);
-       AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
-                        (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
-       if ((chipstat & CSW_INT_PENDING)
-           || (int_pending)
-           ) {
-               AscAckInterrupt(iop_base);
-               int_pending = TRUE;
-               if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
-                       if (AscIsrChipHalted(asc_dvc) == ERR) {
-                               goto ISR_REPORT_QDONE_FATAL_ERROR;
-                       } else {
-                               saved_ctrl_reg &= (uchar)(~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;
-               }
-       }
-       AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
-       AscSetChipLramAddr(iop_base, saved_ram_addr);
-       AscSetChipControl(iop_base, saved_ctrl_reg);
-       asc_dvc->is_in_int = FALSE;
-       return (int_pending);
-}
+/* Microcode buffer is kept after initialization for error recovery. */
+static unsigned char _adv_asc38C0800_buf[] = {
+       0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
+       0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
+       0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
+       0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
+       0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
+       0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
+       0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
+       0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
+       0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
+       0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
+       0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
+       0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
+       0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
+       0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
+       0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
+       0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
+       0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
+       0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
+       0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
+       0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
+       0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
+       0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
+       0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
+       0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
+       0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
+       0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
+       0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
+       0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
+       0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
+       0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
+       0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
+       0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
+       0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
+       0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
+       0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
+       0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
+       0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
+       0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
+       0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
+       0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
+       0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
+       0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
+       0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
+       0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
+       0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
+       0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
+       0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
+       0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
+       0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
+       0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
+       0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
+       0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
+       0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
+       0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
+       0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
+       0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
+       0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
+       0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
+       0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
+       0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
+       0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
+       0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
+       0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
+       0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
+       0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
+       0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
+       0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
+       0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
+       0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
+       0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
+       0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
+       0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
+       0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
+       0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
+       0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
+       0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
+       0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
+       0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
+       0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
+       0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
+       0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
+       0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
+       0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
+       0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
+       0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
+       0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
+       0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
+       0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
+       0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
+       0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
+       0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
+       0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
+       0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
+       0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
+       0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
+       0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
+       0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
+       0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
+       0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
+       0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
+       0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
+       0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
+       0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
+       0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
+       0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
+       0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
+       0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
+       0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
+       0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
+       0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
+       0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
+       0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
+       0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
+       0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
+       0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
+       0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
+       0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
+       0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
+       0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
+       0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
+       0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
+       0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
+       0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
+       0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
+       0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
+       0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
+       0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
+       0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
+       0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
+       0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
+       0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
+       0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
+       0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
+       0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
+       0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
+       0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
+       0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
+       0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
+       0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
+       0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
+       0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
+       0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
+       0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
+       0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
+       0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
+       0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
+       0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
+       0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
+       0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
+       0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
+       0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
+       0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
+       0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
+       0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
+       0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
+       0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
+       0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
+       0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
+       0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
+       0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
+       0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
+       0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
+       0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
+       0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
+       0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
+       0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
+       0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
+       0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
+       0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
+       0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
+       0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
+       0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
+       0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
+       0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
+       0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
+       0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
+       0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
+       0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
+       0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
+       0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
+       0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
+       0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
+       0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
+       0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
+       0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
+       0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
+       0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
+       0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
+       0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
+       0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
+       0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
+       0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
+       0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
+       0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
+       0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
+       0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
+       0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
+       0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
+       0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
+       0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
+       0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
+       0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
+       0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
+       0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
+       0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
+       0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
+       0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
+       0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
+       0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
+       0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
+       0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
+       0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
+       0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
+       0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
+       0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
+       0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
+       0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
+       0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
+       0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
+       0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
+       0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
+       0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
+       0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
+       0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
+       0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
+       0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
+       0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
+       0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
+       0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
+       0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
+       0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
+       0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
+       0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
+       0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
+       0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
+       0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
+       0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
+       0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
+       0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
+       0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
+       0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
+       0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
+       0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
+       0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
+       0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
+       0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
+       0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
+       0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
+       0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
+       0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
+       0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
+       0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
+       0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
+       0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
+       0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
+       0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
+       0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
+       0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
+       0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
+       0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
+       0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
+       0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
+       0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
+       0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
+       0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
+       0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
+       0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
+       0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
+       0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
+       0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
+       0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
+       0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
+       0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
+       0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
+       0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
+       0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
+       0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
+       0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
+       0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
+       0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
+       0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
+       0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
+       0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
+       0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
+       0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
+       0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
+       0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
+       0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
+       0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
+       0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
+       0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
+       0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
+       0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
+       0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
+       0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
+       0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
+       0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
+       0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
+       0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
+       0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
+       0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
+       0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
+       0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
+       0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
+       0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
+       0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
+       0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
+       0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
+       0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
+       0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
+       0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
+       0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
+       0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
+       0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
+       0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
+       0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
+       0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
+       0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
+       0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
+       0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
+       0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
+       0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
+       0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
+       0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
+       0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
+       0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
+       0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
+       0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
+       0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
+       0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
+       0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
+       0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
+       0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
+       0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
+       0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
+       0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
+       0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
+       0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
+       0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
+       0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
+       0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
+       0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
+       0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
+       0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
+       0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
+       0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
+       0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
+       0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
+       0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
+       0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
+       0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
+       0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
+       0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
+       0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
+       0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
+       0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
+       0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
+       0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
+       0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
+       0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
+       0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
+       0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
+       0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
+       0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
+       0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
+       0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
+       0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
+       0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
+       0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
+       0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
+       0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
+       0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
+       0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
+       0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
+       0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
+       0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
+       0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
+       0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
+       0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
+       0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
+       0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
+       0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
+       0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
+       0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
+       0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
+       0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
+       0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
+       0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
+       0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
+       0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
+       0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
+       0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
+       0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
+       0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
+       0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
+       0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
+       0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
+       0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
+       0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
+       0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
+       0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
+       0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
+       0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
+       0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
+       0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
+       0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
+       0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
+       0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
+       0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
+       0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
+       0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
+       0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
+       0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
+       0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
+       0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
+       0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
+       0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
+       0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
+       0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
+       0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
+       0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
+       0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
+       0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
+       0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
+       0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
+       0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
+       0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
+       0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
+       0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
+       0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
+       0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
+       0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
+       0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
+       0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
+       0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
+       0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
+       0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
+       0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
+       0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
+       0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
+       0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
+       0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
+       0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
+       0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
+       0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
+};
+
+static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf);      /* 0x14E1 */
+static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
 
 /* Microcode buffer is kept after initialization for error recovery. */
-static uchar _asc_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, 0xC3, 0x12, 0x0D, 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, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0x00,
-       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88,
-       0x00, 0x00, 0x00, 0x00,
-       0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73,
-       0x03, 0x23, 0x36, 0x40,
-       0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
-       0xC2, 0x00, 0x92, 0x80,
-       0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60,
-       0xB6, 0x00, 0x92, 0x80,
-       0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00,
-       0x92, 0x80, 0x80, 0x62,
-       0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
-       0xCD, 0x04, 0x4D, 0x00,
-       0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01,
-       0xE6, 0x84, 0xD2, 0xC1,
-       0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97,
-       0xC6, 0x81, 0xC2, 0x88,
-       0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
-       0x84, 0x97, 0x07, 0xA6,
-       0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE,
-       0xC2, 0x88, 0xCE, 0x00,
-       0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01,
-       0x80, 0x63, 0x07, 0xA6,
-       0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
-       0x34, 0x01, 0x00, 0x33,
-       0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23,
-       0x68, 0x98, 0x4D, 0x04,
-       0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23,
-       0xF8, 0x88, 0xFB, 0x23,
-       0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
-       0x00, 0x33, 0x0A, 0x00,
-       0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00,
-       0xC2, 0x88, 0xCD, 0x04,
-       0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81,
-       0x06, 0xAB, 0x82, 0x01,
-       0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
-       0x3C, 0x01, 0x00, 0x05,
-       0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01,
-       0x15, 0x23, 0xA1, 0x01,
-       0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00,
-       0x06, 0x61, 0x00, 0xA0,
-       0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
-       0xC2, 0x88, 0x06, 0x23,
-       0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01,
-       0x57, 0x60, 0x00, 0xA0,
-       0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73,
-       0x4B, 0x00, 0x06, 0x61,
-       0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
-       0x4F, 0x00, 0x84, 0x97,
-       0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97,
-       0x48, 0x04, 0x84, 0x80,
-       0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00,
-       0x81, 0x73, 0x06, 0x29,
-       0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
-       0x04, 0x98, 0xF0, 0x80,
-       0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6,
-       0x34, 0x02, 0x03, 0xA6,
-       0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96,
-       0x46, 0x82, 0xFE, 0x95,
-       0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
-       0x07, 0xA6, 0x5A, 0x02,
-       0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95,
-       0x48, 0x82, 0x60, 0x96,
-       0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 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, 0xAA, 0x02,
-       0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04,
-       0x01, 0xA6, 0xB4, 0x02,
-       0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
-       0x80, 0x63, 0x00, 0x43,
-       0x00, 0xA0, 0x8C, 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, 0xEA, 0x82,
-       0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
-       0x00, 0x33, 0x1F, 0x00,
-       0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98,
-       0xB6, 0x2D, 0x01, 0xA6,
-       0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6,
-       0x10, 0x03, 0x03, 0xA6,
-       0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
-       0x7C, 0x95, 0xEE, 0x82,
-       0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4,
-       0x04, 0x01, 0x2D, 0xC8,
-       0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01,
-       0x05, 0x05, 0x86, 0x98,
-       0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
-       0x3C, 0x04, 0x06, 0xA6,
-       0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88,
-       0x7C, 0x95, 0x32, 0x83,
-       0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05,
-       0xEB, 0x04, 0x00, 0x33,
-       0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
-       0xFF, 0xA2, 0x7A, 0x03,
-       0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01,
-       0x00, 0xA2, 0x9A, 0x03,
-       0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00,
-       0x01, 0xA6, 0x96, 0x03,
-       0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
-       0xA4, 0x03, 0x00, 0xA6,
-       0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03,
-       0x07, 0xA6, 0xB2, 0x03,
-       0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88,
-       0xA8, 0x98, 0x80, 0x42,
-       0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
-       0xC0, 0x83, 0x00, 0x33,
-       0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23,
-       0xA0, 0x01, 0x12, 0x23,
-       0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B,
-       0x80, 0x67, 0x05, 0x23,
-       0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
-       0x06, 0xA6, 0x0A, 0x04,
-       0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96,
-       0xF4, 0x83, 0x20, 0x84,
-       0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
-       0x83, 0x03, 0x80, 0x63,
-       0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
-       0x38, 0x04, 0x00, 0x33,
-       0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84,
-       0x1D, 0x01, 0x06, 0xCC,
-       0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62,
-       0xA2, 0x0D, 0x80, 0x63,
-       0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
-       0x80, 0x63, 0xA3, 0x01,
-       0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0,
-       0x76, 0x04, 0xE0, 0x00,
-       0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00,
-       0x00, 0x33, 0x1E, 0x00,
-       0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
-       0x08, 0x23, 0x22, 0xA3,
-       0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3,
-       0xC4, 0x04, 0x42, 0x23,
-       0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23,
-       0xF8, 0x88, 0x04, 0x98,
-       0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
-       0x81, 0x62, 0xE8, 0x81,
-       0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98,
-       0x00, 0x33, 0x00, 0x81,
-       0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23,
-       0xF8, 0x88, 0x04, 0x23,
-       0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
-       0xF4, 0x04, 0x00, 0x33,
-       0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01,
-       0x04, 0x23, 0xA0, 0x01,
-       0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00,
-       0x00, 0xA3, 0x22, 0x05,
-       0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
-       0x46, 0x97, 0xCD, 0x04,
-       0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23,
-       0x82, 0x01, 0x34, 0x85,
-       0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 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, 0x60, 0x05, 0x77, 0x04,
-       0x01, 0x23, 0xEA, 0x00,
-       0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
-       0x07, 0xA4, 0xF8, 0x05,
-       0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00,
-       0xC2, 0x88, 0x04, 0xA0,
-       0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61,
-       0x00, 0xA2, 0xA4, 0x05,
-       0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
-       0x62, 0x97, 0x04, 0x85,
-       0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05,
-       0xF4, 0x85, 0x03, 0xA0,
-       0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63,
-       0xCC, 0x86, 0x07, 0xA0,
-       0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
-       0x80, 0x67, 0x80, 0x63,
-       0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23,
-       0xF8, 0x88, 0x07, 0x23,
-       0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00,
-       0x00, 0x63, 0x4A, 0x00,
-       0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
-       0x07, 0x41, 0x83, 0x03,
-       0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88,
-       0x1D, 0x01, 0x01, 0xD6,
-       0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00,
-       0x07, 0xA6, 0x7C, 0x05,
-       0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
-       0x52, 0x00, 0x06, 0x61,
-       0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41,
-       0x00, 0x63, 0x1D, 0x01,
-       0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23,
-       0x07, 0x41, 0x00, 0x63,
-       0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
-       0xDF, 0x00, 0x06, 0xA6,
-       0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33,
-       0x00, 0x40, 0xC0, 0x20,
-       0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63,
-       0x06, 0xA6, 0x94, 0x06,
-       0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
-       0x40, 0x0E, 0x80, 0x63,
-       0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E,
-       0x80, 0x63, 0x00, 0x43,
-       0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05,
-       0x80, 0x67, 0x40, 0x0E,
-       0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
-       0x07, 0xA6, 0xD6, 0x06,
-       0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00,
-       0x0A, 0x2B, 0x07, 0xA6,
-       0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2,
-       0xF4, 0x06, 0xC0, 0x0E,
-       0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
-       0x81, 0x62, 0x04, 0x01,
-       0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
-       0x8C, 0x06, 0x00, 0x33,
-       0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03,
-       0x80, 0x63, 0x06, 0xA6,
-       0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
-       0x00, 0x00, 0x80, 0x67,
-       0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05,
-       0xBF, 0x23, 0x04, 0x61,
-       0x84, 0x01, 0xE6, 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,
-       0xC4, 0x07, 0x00, 0x33,
-       0x07, 0x00, 0xC2, 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, 0xE4, 0x07,
-       0x00, 0x05, 0xDA, 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,
-       0x14, 0x08, 0x16, 0x88, 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, 0x44, 0x08,
-       0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1,
-       0x24, 0x08, 0x04, 0x98,
-       0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
-       0x5A, 0x88, 0x02, 0x01,
-       0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00,
-       0x00, 0xA3, 0x64, 0x08,
-       0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63,
-       0x06, 0xA6, 0x76, 0x08,
-       0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
-       0x00, 0x63, 0x38, 0x2B,
-       0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 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, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
-       0x40, 0x36, 0x40, 0x3A,
-       0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08,
-       0x5D, 0x00, 0xFE, 0xC3,
-       0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73,
-       0xFF, 0xFD, 0x80, 0x73,
-       0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
-       0xA1, 0x23, 0xA1, 0x01,
-       0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2,
-       0x80, 0x00, 0x03, 0xC2,
-       0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23,
-       0xA0, 0x01, 0xE6, 0x84,
+static unsigned char _adv_asc38C1600_buf[] = {
+       0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
+       0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
+       0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
+       0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
+       0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
+       0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
+       0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
+       0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
+       0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
+       0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
+       0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
+       0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
+       0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
+       0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
+       0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
+       0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
+       0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
+       0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
+       0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
+       0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
+       0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
+       0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
+       0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
+       0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
+       0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
+       0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
+       0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
+       0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
+       0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
+       0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
+       0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
+       0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
+       0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
+       0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
+       0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
+       0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
+       0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
+       0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
+       0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
+       0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
+       0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
+       0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
+       0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
+       0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
+       0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
+       0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
+       0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
+       0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
+       0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
+       0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
+       0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
+       0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
+       0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
+       0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
+       0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
+       0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
+       0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
+       0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
+       0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
+       0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
+       0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
+       0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
+       0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
+       0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
+       0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
+       0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
+       0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
+       0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
+       0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
+       0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
+       0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
+       0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
+       0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
+       0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
+       0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
+       0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
+       0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
+       0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
+       0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
+       0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
+       0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
+       0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
+       0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
+       0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
+       0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
+       0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
+       0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
+       0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
+       0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
+       0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
+       0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
+       0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
+       0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
+       0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
+       0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
+       0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
+       0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
+       0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
+       0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
+       0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
+       0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
+       0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
+       0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
+       0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
+       0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
+       0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
+       0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
+       0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
+       0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
+       0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
+       0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
+       0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
+       0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
+       0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
+       0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
+       0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
+       0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
+       0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
+       0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
+       0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
+       0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
+       0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
+       0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
+       0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
+       0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
+       0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
+       0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
+       0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
+       0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
+       0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
+       0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
+       0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
+       0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
+       0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
+       0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
+       0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
+       0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
+       0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
+       0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
+       0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
+       0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
+       0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
+       0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
+       0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
+       0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
+       0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
+       0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
+       0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
+       0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
+       0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
+       0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
+       0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
+       0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
+       0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
+       0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
+       0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
+       0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
+       0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
+       0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
+       0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
+       0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
+       0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
+       0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
+       0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
+       0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
+       0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
+       0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
+       0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
+       0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
+       0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
+       0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
+       0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
+       0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
+       0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
+       0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
+       0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
+       0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
+       0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
+       0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
+       0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
+       0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
+       0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
+       0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
+       0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
+       0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
+       0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
+       0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
+       0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
+       0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
+       0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
+       0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
+       0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
+       0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
+       0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
+       0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
+       0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
+       0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
+       0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
+       0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
+       0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
+       0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
+       0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
+       0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
+       0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
+       0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
+       0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
+       0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
+       0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
+       0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
+       0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
+       0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
+       0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
+       0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
+       0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
+       0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
+       0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
+       0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
+       0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
+       0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
+       0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
+       0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
+       0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
+       0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
+       0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
+       0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
+       0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
+       0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
+       0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
+       0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
+       0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
+       0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
+       0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
+       0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
+       0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
+       0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
+       0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
+       0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
+       0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
+       0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
+       0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
+       0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
+       0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
+       0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
+       0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
+       0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
+       0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
+       0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
+       0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
+       0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
+       0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
+       0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
+       0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
+       0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
+       0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
+       0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
+       0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
+       0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
+       0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
+       0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
+       0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
+       0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
+       0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
+       0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
+       0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
+       0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
+       0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
+       0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
+       0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
+       0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
+       0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
+       0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
+       0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
+       0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
+       0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
+       0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
+       0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
+       0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
+       0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
+       0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
+       0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
+       0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
+       0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
+       0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
+       0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
+       0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
+       0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
+       0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
+       0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
+       0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
+       0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
+       0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
+       0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
+       0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
+       0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
+       0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
+       0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
+       0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
+       0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
+       0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
+       0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
+       0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
+       0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
+       0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
+       0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
+       0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
+       0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
+       0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
+       0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
+       0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
+       0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
+       0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
+       0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
+       0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
+       0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
+       0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
+       0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
+       0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
+       0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
+       0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
+       0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
+       0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
+       0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
+       0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
+       0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
+       0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
+       0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
+       0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
+       0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
+       0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
+       0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
+       0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
+       0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
+       0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
+       0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
+       0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
+       0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
+       0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
+       0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
+       0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
+       0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
+       0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
+       0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
+       0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
+       0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
+       0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
+       0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
+       0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
+       0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
+       0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
+       0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
+       0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
+       0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
+       0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
+       0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
+       0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
+       0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
+       0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
+       0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
+       0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
+       0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
+       0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
+       0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
+       0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
+       0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
+       0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
+       0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
+       0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
+       0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
+       0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
+       0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
+       0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
+       0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
+       0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
+       0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
+       0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
+       0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
+       0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
+       0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
+       0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
+       0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
+       0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
+       0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
+       0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
+       0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
+       0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
+       0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
+       0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
+       0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
+       0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
+       0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
+       0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
+       0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
+       0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
+       0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
+       0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
+       0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
+       0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
+       0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
+       0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
+       0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
+       0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
+       0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
+       0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
+       0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
+       0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
+       0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
+       0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
+       0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
+       0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
+       0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
+       0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
+       0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
+       0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
+       0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
+       0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
+       0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
+       0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
+       0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
+       0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
+       0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
+       0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
+       0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
+       0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
+       0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
+       0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
+       0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
+       0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
+       0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
+       0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
+       0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
+       0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
+       0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
+       0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
+       0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
+       0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
+       0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
+       0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
+       0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
+       0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
+       0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
+       0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
+       0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
+       0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
+       0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
+       0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
+       0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
+       0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
+       0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
+       0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
+       0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
+       0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
+       0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
+       0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
+       0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
+       0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
+       0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
+       0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
+       0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
+       0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
+       0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
+       0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
+       0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
+       0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
+       0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
+       0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
+       0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
+       0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
+       0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
+       0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
+       0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
+       0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
+       0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
+       0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
+       0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
+       0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
+       0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
+       0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
+       0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
+       0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
+       0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
+       0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
+       0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
+       0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
+       0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
+       0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
+       0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
+       0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
+       0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
+       0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
+       0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
+       0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
+       0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
+       0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
+       0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
+       0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
+       0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
+       0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
+       0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
+       0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
+       0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
+       0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
+       0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
+       0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
+       0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
+       0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
+       0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
+       0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
+       0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
+       0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
+       0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
+       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
+       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
+       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
+       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
+       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
+       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
+       0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
+       0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
+       0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
+       0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
+       0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
+       0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
 };
 
-static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
-static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
+static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf);      /* 0x1673 */
+static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
 
-#define ASC_SYN_OFFSET_ONE_DISABLE_LIST  16
-static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
-       INQUIRY,
-       REQUEST_SENSE,
-       READ_CAPACITY,
-       READ_TOC,
-       MODE_SELECT,
-       MODE_SENSE,
-       MODE_SELECT_10,
-       MODE_SENSE_10,
-       0xFF,
-       0xFF,
-       0xFF,
-       0xFF,
-       0xFF,
-       0xFF,
-       0xFF,
-       0xFF
-};
+static void AscInitQLinkVar(ASC_DVC_VAR *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);
+       AscPutQDoneInProgress(iop_base, 0);
+       lram_addr = ASC_QADR_BEG;
+       for (i = 0; i < 32; i++, lram_addr += 2) {
+               AscWriteLramWord(iop_base, lram_addr, 0);
+       }
+}
 
-static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
+static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
 {
-       PortAddr iop_base;
-       ulong last_int_level;
-       int sta;
-       int n_q_required;
-       int disable_syn_offset_one_fix;
        int i;
-       ASC_PADDR addr;
-       ASC_EXE_CALLBACK asc_exe_callback;
-       ushort sg_entry_cnt = 0;
-       ushort sg_entry_cnt_minus_one = 0;
-       uchar target_ix;
-       uchar tid_no;
-       uchar sdtr_data;
-       uchar extra_bytes;
-       uchar scsi_cmd;
-       uchar disable_cmd;
-       ASC_SG_HEAD *sg_head;
-       ASC_DCNT data_cnt;
+       ushort warn_code;
+       PortAddr iop_base;
+       ASC_PADDR phy_addr;
+       ASC_DCNT phy_size;
+       struct asc_board *board = asc_dvc_to_board(asc_dvc);
 
        iop_base = asc_dvc->iop_base;
-       sg_head = scsiq->sg_head;
-       asc_exe_callback = asc_dvc->exe_callback;
-       if (asc_dvc->err_code != 0)
-               return (ERR);
-       if (scsiq == (ASC_SCSI_Q *)0L) {
-               AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
-               return (ERR);
-       }
-       scsiq->q1.q_no = 0;
-       if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
-               scsiq->q1.extra_bytes = 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] == REQUEST_SENSE) {
-               if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
-                       asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
-                       sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
-                       AscMsgOutSDTR(asc_dvc,
-                                     asc_dvc->
-                                     sdtr_period_tbl[(sdtr_data >> 4) &
-                                                     (uchar)(asc_dvc->
-                                                             max_sdtr_index -
-                                                             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 = sg_head->entry_cnt) == 0) {
-                       asc_dvc->in_critical_cnt--;
-                       DvcLeaveCritical(last_int_level);
-                       return (ERR);
-               }
-#if !CC_VERY_LONG_SG_LIST
-               if (sg_entry_cnt > ASC_MAX_SG_LIST) {
-                       asc_dvc->in_critical_cnt--;
-                       DvcLeaveCritical(last_int_level);
-                       return (ERR);
-               }
-#endif /* !CC_VERY_LONG_SG_LIST */
-               if (sg_entry_cnt == 1) {
-                       scsiq->q1.data_addr =
-                           (ADV_PADDR)sg_head->sg_list[0].addr;
-                       scsiq->q1.data_cnt =
-                           (ADV_DCNT)sg_head->sg_list[0].bytes;
-                       scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
-               }
-               sg_entry_cnt_minus_one = sg_entry_cnt - 1;
-       }
-       scsi_cmd = scsiq->cdbptr[0];
-       disable_syn_offset_one_fix = FALSE;
-       if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
-           !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
-               if (scsiq->q1.cntl & QC_SG_HEAD) {
-                       data_cnt = 0;
-                       for (i = 0; i < sg_entry_cnt; i++) {
-                               data_cnt +=
-                                   (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
-                                                         bytes);
-                       }
-               } else {
-                       data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
-               }
-               if (data_cnt != 0UL) {
-                       if (data_cnt < 512UL) {
-                               disable_syn_offset_one_fix = TRUE;
-                       } else {
-                               for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
-                                    i++) {
-                                       disable_cmd =
-                                           _syn_offset_one_disable_cmd[i];
-                                       if (disable_cmd == 0xFF) {
-                                               break;
-                                       }
-                                       if (scsi_cmd == disable_cmd) {
-                                               disable_syn_offset_one_fix =
-                                                   TRUE;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       }
-       if (disable_syn_offset_one_fix) {
-               scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
-               scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
-                                      ASC_TAG_FLAG_DISABLE_DISCONNECT);
-       } else {
-               scsiq->q2.tag_code &= 0x27;
+       warn_code = 0;
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               AscPutMCodeInitSDTRAtID(iop_base, i,
+                                       asc_dvc->cfg->sdtr_period_offset[i]);
        }
-       if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
-               if (asc_dvc->bug_fix_cntl) {
-                       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
-                               if ((scsi_cmd == READ_6) ||
-                                   (scsi_cmd == READ_10)) {
-                                       addr =
-                                           (ADV_PADDR)le32_to_cpu(sg_head->
-                                                                  sg_list
-                                                                  [sg_entry_cnt_minus_one].
-                                                                  addr) +
-                                           (ADV_DCNT)le32_to_cpu(sg_head->
-                                                                 sg_list
-                                                                 [sg_entry_cnt_minus_one].
-                                                                 bytes);
-                                       extra_bytes =
-                                           (uchar)((ushort)addr & 0x0003);
-                                       if ((extra_bytes != 0)
-                                           &&
-                                           ((scsiq->q2.
-                                             tag_code &
-                                             ASC_TAG_FLAG_EXTRA_BYTES)
-                                            == 0)) {
-                                               scsiq->q2.tag_code |=
-                                                   ASC_TAG_FLAG_EXTRA_BYTES;
-                                               scsiq->q1.extra_bytes =
-                                                   extra_bytes;
-                                               data_cnt =
-                                                   le32_to_cpu(sg_head->
-                                                               sg_list
-                                                               [sg_entry_cnt_minus_one].
-                                                               bytes);
-                                               data_cnt -=
-                                                   (ASC_DCNT) extra_bytes;
-                                               sg_head->
-                                                   sg_list
-                                                   [sg_entry_cnt_minus_one].
-                                                   bytes =
-                                                   cpu_to_le32(data_cnt);
-                                       }
-                               }
-                       }
-               }
-               sg_head->entry_to_copy = sg_head->entry_cnt;
-#if CC_VERY_LONG_SG_LIST
-               /*
-                * Set the sg_entry_cnt to the maximum possible. The rest of
-                * the SG elements will be copied when the RISC completes the
-                * SG elements that fit and halts.
-                */
-               if (sg_entry_cnt > ASC_MAX_SG_LIST) {
-                       sg_entry_cnt = ASC_MAX_SG_LIST;
-               }
-#endif /* CC_VERY_LONG_SG_LIST */
-               n_q_required = AscSgListToQueue(sg_entry_cnt);
-               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 {
-               if (asc_dvc->bug_fix_cntl) {
-                       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
-                               if ((scsi_cmd == READ_6) ||
-                                   (scsi_cmd == READ_10)) {
-                                       addr =
-                                           le32_to_cpu(scsiq->q1.data_addr) +
-                                           le32_to_cpu(scsiq->q1.data_cnt);
-                                       extra_bytes =
-                                           (uchar)((ushort)addr & 0x0003);
-                                       if ((extra_bytes != 0)
-                                           &&
-                                           ((scsiq->q2.
-                                             tag_code &
-                                             ASC_TAG_FLAG_EXTRA_BYTES)
-                                            == 0)) {
-                                               data_cnt =
-                                                   le32_to_cpu(scsiq->q1.
-                                                               data_cnt);
-                                               if (((ushort)data_cnt & 0x01FF)
-                                                   == 0) {
-                                                       scsiq->q2.tag_code |=
-                                                           ASC_TAG_FLAG_EXTRA_BYTES;
-                                                       data_cnt -= (ASC_DCNT)
-                                                           extra_bytes;
-                                                       scsiq->q1.data_cnt =
-                                                           cpu_to_le32
-                                                           (data_cnt);
-                                                       scsiq->q1.extra_bytes =
-                                                           extra_bytes;
-                                               }
-                                       }
-                               }
-                       }
-               }
-               n_q_required = 1;
-               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);
-                       }
-               }
+
+       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));
+
+       /* Ensure overrun buffer is aligned on an 8 byte boundary. */
+       BUG_ON((unsigned long)asc_dvc->overrun_buf & 7);
+       asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf,
+                                       ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+       phy_addr = cpu_to_le32(asc_dvc->overrun_dma);
+       AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
+                                (uchar *)&phy_addr, 1);
+       phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE);
+       AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
+                                (uchar *)&phy_size, 1);
+
+       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;
        }
-       asc_dvc->in_critical_cnt--;
-       DvcLeaveCritical(last_int_level);
-       return (sta);
+       if (AscStartChip(iop_base) != 1) {
+               asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
+               return warn_code;
+       }
+
+       return warn_code;
 }
 
-static int
-AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
+static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
 {
+       ushort warn_code;
        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) {
-                               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) {
-                               AscPutVarFreeQHead(iop_base, next_qp);
-                               asc_dvc->cur_total_qng++;
-                               asc_dvc->cur_dvc_qng[tid_no]++;
-                       }
-                       return (sta);
-               }
+       warn_code = 0;
+       if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
+           !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
+               AscResetChipAndScsiBus(asc_dvc);
+               mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
        }
-       return (sta);
+       asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
+       if (asc_dvc->err_code != 0)
+               return UW_ERR;
+       if (!AscFindSignature(asc_dvc->iop_base)) {
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+               return warn_code;
+       }
+       AscDisableInterrupt(iop_base);
+       warn_code |= AscInitLram(asc_dvc);
+       if (asc_dvc->err_code != 0)
+               return UW_ERR;
+       ASC_DBG(1, "_asc_mcode_chksum 0x%lx\n", (ulong)_asc_mcode_chksum);
+       if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
+                            _asc_mcode_size) != _asc_mcode_chksum) {
+               asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+               return warn_code;
+       }
+       warn_code |= AscInitMicroCodeVar(asc_dvc);
+       asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
+       AscEnableInterrupt(iop_base);
+       return warn_code;
 }
 
-static int AscSgListToQueue(int sg_list)
+/*
+ * Load the Microcode
+ *
+ * Write the microcode image to RISC memory starting at address 0.
+ *
+ * The microcode is stored compressed in the following format:
+ *
+ *  254 word (508 byte) table indexed by byte code followed
+ *  by the following byte codes:
+ *
+ *    1-Byte Code:
+ *      00: Emit word 0 in table.
+ *      01: Emit word 1 in table.
+ *      .
+ *      FD: Emit word 253 in table.
+ *
+ *    Multi-Byte Code:
+ *      FE WW WW: (3 byte code) Word to emit is the next word WW WW.
+ *      FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
+ *
+ * Returns 0 or an error if the checksum doesn't match
+ */
+static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
+                           int memsize, int chksum)
 {
-       int n_sg_list_qs;
+       int i, j, end, len = 0;
+       ADV_DCNT sum;
 
-       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);
+       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
+
+       for (i = 253 * 2; i < size; i++) {
+               if (buf[i] == 0xff) {
+                       unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
+                       for (j = 0; j < buf[i + 1]; j++) {
+                               AdvWriteWordAutoIncLram(iop_base, word);
+                               len += 2;
+                       }
+                       i += 3;
+               } else if (buf[i] == 0xfe) {
+                       unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
+                       AdvWriteWordAutoIncLram(iop_base, word);
+                       i += 2;
+                       len += 2;
+               } else {
+                       unsigned char off = buf[i] * 2;
+                       unsigned short word = (buf[off + 1] << 8) | buf[off];
+                       AdvWriteWordAutoIncLram(iop_base, word);
+                       len += 2;
+               }
+       }
+
+       end = len;
+
+       while (len < memsize) {
+               AdvWriteWordAutoIncLram(iop_base, 0);
+               len += 2;
+       }
+
+       /* Verify the microcode checksum. */
+       sum = 0;
+       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
+
+       for (len = 0; len < end; len += 2) {
+               sum += AdvReadWordAutoIncLram(iop_base);
+       }
+
+       if (sum != chksum)
+               return ASC_IERR_MCODE_CHKSUM;
+
+       return 0;
 }
 
-static uint
-AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
+static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
 {
-       uint cur_used_qs;
-       uint cur_free_qs;
-       ASC_SCSI_BIT_ID_TYPE target_id;
-       uchar tid_no;
+       ADV_CARR_T *carrp;
+       ADV_SDCNT buf_size;
+       ADV_PADDR carr_paddr;
 
-       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;
+       carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
+       asc_dvc->carr_freelist = NULL;
+       if (carrp == asc_dvc->carrier_buf) {
+               buf_size = ADV_CARRIER_BUFSIZE;
        } else {
-               cur_used_qs = (uint) asc_dvc->cur_total_qng +
-                   (uint) ASC_MIN_FREE_Q;
+               buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
        }
-       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);
+
+       do {
+               /* Get physical address of the carrier 'carrp'. */
+               carr_paddr = cpu_to_le32(virt_to_bus(carrp));
+
+               buf_size -= sizeof(ADV_CARR_T);
+
+               carrp->carr_pa = carr_paddr;
+               carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
+
+               /*
+                * Insert the carrier at the beginning of the freelist.
+                */
+               carrp->next_vpa =
+                       cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
+               asc_dvc->carr_freelist = carrp;
+
+               carrp++;
+       } while (buf_size > 0);
+}
+
+/*
+ * Send an idle command to the chip and wait for completion.
+ *
+ * Command completion is polled for once per microsecond.
+ *
+ * The function can be called from anywhere including an interrupt handler.
+ * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
+ * functions to prevent reentrancy.
+ *
+ * Return Values:
+ *   ADV_TRUE - command completed successfully
+ *   ADV_FALSE - command failed
+ *   ADV_ERROR - command timed out
+ */
+static int
+AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
+              ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
+{
+       int result;
+       ADV_DCNT i, j;
+       AdvPortAddr iop_base;
+
+       iop_base = asc_dvc->iop_base;
+
+       /*
+        * Clear the idle command status which is set by the microcode
+        * to a non-zero value to indicate when the command is completed.
+        * The non-zero result is one of the IDLE_CMD_STATUS_* values
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
+
+       /*
+        * Write the idle command value after the idle command parameter
+        * has been written to avoid a race condition. If the order is not
+        * followed, the microcode may process the idle command before the
+        * parameters have been written to LRAM.
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
+                               cpu_to_le32(idle_cmd_parameter));
+       AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
+
+       /*
+        * Tickle the RISC to tell it to process the idle command.
+        */
+       AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
+       if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
+               /*
+                * Clear the tickle value. In the ASC-3550 the RISC flag
+                * command 'clr_tickle_b' does not work unless the host
+                * value is cleared.
+                */
+               AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
        }
-       if (n_qs > 1) {
-               if ((n_qs > asc_dvc->last_q_shortage)
-                   && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
-                       asc_dvc->last_q_shortage = n_qs;
+
+       /* Wait for up to 100 millisecond for the idle command to timeout. */
+       for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
+               /* Poll once each microsecond for command completion. */
+               for (j = 0; j < SCSI_US_PER_MSEC; j++) {
+                       AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
+                                       result);
+                       if (result != 0)
+                               return result;
+                       udelay(1);
                }
        }
-       return (0);
+
+       BUG();          /* The idle command should never timeout. */
+       return ADV_ERROR;
 }
 
-static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
+/*
+ * Reset SCSI Bus and purge all outstanding requests.
+ *
+ * Return Value:
+ *      ADV_TRUE(1) -   All requests are purged and SCSI Bus is reset.
+ *      ADV_FALSE(0) -  Microcode command failed.
+ *      ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
+ *                      may be hung which requires driver recovery.
+ */
+static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
 {
-       ushort q_addr;
-       uchar tid_no;
-       uchar sdtr_data;
-       uchar syn_period_ix;
-       uchar syn_offset;
-       PortAddr iop_base;
+       int status;
 
-       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 = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
-               syn_period_ix =
-                   (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
-               syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
-               AscMsgOutSDTR(asc_dvc,
-                             asc_dvc->sdtr_period_tbl[syn_period_ix],
-                             syn_offset);
-               scsiq->q1.cntl |= QC_MSG_OUT;
+       /*
+        * Send the SCSI Bus Reset idle start idle command which asserts
+        * the SCSI Bus Reset signal.
+        */
+       status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
+       if (status != ADV_TRUE) {
+               return status;
        }
-       q_addr = ASC_QNO_TO_QADDR(q_no);
-       if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
-               scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
+
+       /*
+        * Delay for the specified SCSI Bus Reset hold time.
+        *
+        * The hold time delay is done on the host because the RISC has no
+        * microsecond accurate timer.
+        */
+       udelay(ASC_SCSI_RESET_HOLD_TIME_US);
+
+       /*
+        * Send the SCSI Bus Reset end idle command which de-asserts
+        * the SCSI Bus Reset signal and purges any pending requests.
+        */
+       status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
+       if (status != ADV_TRUE) {
+               return status;
        }
-       scsiq->q1.status = QS_FREE;
-       AscMemWordCopyPtrToLram(iop_base,
-                               q_addr + ASC_SCSIQ_CDB_BEG,
-                               (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
 
-       DvcPutScsiQ(iop_base,
-                   q_addr + ASC_SCSIQ_CPY_BEG,
-                   (uchar *)&scsiq->q1.cntl,
-                   ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
-       AscWriteLramWord(iop_base,
-                        (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
-                        (ushort)(((ushort)scsiq->q1.
-                                  q_no << 8) | (ushort)QS_READY));
-       return (1);
+       mdelay(asc_dvc->scsi_reset_wait * 1000);        /* XXX: msleep? */
+
+       return status;
 }
 
-static int
-AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
+/*
+ * Initialize the ASC-3550.
+ *
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ *
+ * Needed after initialization for error recovery.
+ */
+static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
 {
-       int sta;
+       AdvPortAddr iop_base;
+       ushort warn_code;
+       int begin_addr;
+       int end_addr;
+       ushort code_sum;
+       int word;
        int i;
-       ASC_SG_HEAD *sg_head;
-       ASC_SG_LIST_Q scsi_sg_q;
-       ASC_DCNT saved_data_addr;
-       ASC_DCNT saved_data_cnt;
-       PortAddr iop_base;
-       ushort sg_list_dwords;
-       ushort sg_index;
-       ushort sg_entry_cnt;
-       ushort q_addr;
-       uchar next_qp;
+       ushort scsi_cfg1;
+       uchar tid;
+       ushort bios_mem[ASC_MC_BIOSLEN / 2];    /* BIOS RISC Memory 0x40-0x8F. */
+       ushort wdtr_able = 0, sdtr_able, tagqng_able;
+       uchar max_cmd[ADV_MAX_TID + 1];
+
+       /* If there is already an error, don't continue. */
+       if (asc_dvc->err_code != 0)
+               return ADV_ERROR;
 
-       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 = (ASC_PADDR) sg_head->sg_list[0].addr;
-       scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
-#if CC_VERY_LONG_SG_LIST
        /*
-        * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
-        * then not all SG elements will fit in the allocated queues.
-        * The rest of the SG elements will be copied when the RISC
-        * completes the SG elements that fit and halts.
+        * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
         */
-       if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
-               /*
-                * Set sg_entry_cnt to be the number of SG elements that
-                * will fit in the allocated SG queues. It is minus 1, because
-                * the first SG element is handled above. ASC_MAX_SG_LIST is
-                * already inflated by 1 to account for this. For example it
-                * may be 50 which is 1 + 7 queues * 7 SG elements.
-                */
-               sg_entry_cnt = ASC_MAX_SG_LIST - 1;
+       if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
+               asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
+               return ADV_ERROR;
+       }
 
-               /*
-                * Keep track of remaining number of SG elements that will
-                * need to be handled from a_isr.c.
-                */
-               scsiq->remain_sg_entry_cnt =
-                   sg_head->entry_cnt - ASC_MAX_SG_LIST;
-       } else {
-#endif /* CC_VERY_LONG_SG_LIST */
-               /*
-                * Set sg_entry_cnt to be the number of SG elements that
-                * will fit in the allocated SG queues. It is minus 1, because
-                * the first SG element is handled above.
-                */
-               sg_entry_cnt = sg_head->entry_cnt - 1;
-#if CC_VERY_LONG_SG_LIST
+       warn_code = 0;
+       iop_base = asc_dvc->iop_base;
+
+       /*
+        * Save the RISC memory BIOS region before writing the microcode.
+        * The BIOS may already be loaded and using its RISC LRAM region
+        * so its region must be saved and restored.
+        *
+        * Note: This code makes the assumption, which is currently true,
+        * that a chip reset does not clear RISC LRAM.
+        */
+       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
+               AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
+                               bios_mem[i]);
        }
-#endif /* CC_VERY_LONG_SG_LIST */
-       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 {
-#if CC_VERY_LONG_SG_LIST
-                               /*
-                                * This is the last SG queue in the list of
-                                * allocated SG queues. If there are more
-                                * SG elements than will fit in the allocated
-                                * queues, then set the QCSG_SG_XFER_MORE flag.
-                                */
-                               if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
-                                       scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
-                               } else {
-#endif /* CC_VERY_LONG_SG_LIST */
-                                       scsi_sg_q.cntl |= QCSG_SG_XFER_END;
-#if CC_VERY_LONG_SG_LIST
-                               }
-#endif /* CC_VERY_LONG_SG_LIST */
-                               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);
-                       AscMemWordCopyPtrToLram(iop_base,
-                                               q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
-                                               (uchar *)&scsi_sg_q,
-                                               sizeof(ASC_SG_LIST_Q) >> 1);
-                       AscMemDWordCopyPtrToLram(iop_base,
-                                                q_addr + ASC_SGQ_LIST_BEG,
-                                                (uchar *)&sg_head->
-                                                sg_list[sg_index],
-                                                sg_list_dwords);
-                       sg_index += ASC_SG_LIST_PER_Q;
-                       scsiq->next_sg_index = sg_index;
+
+       /*
+        * Save current per TID negotiated values.
+        */
+       if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
+               ushort bios_version, major, minor;
+
+               bios_version =
+                   bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
+               major = (bios_version >> 12) & 0xF;
+               minor = (bios_version >> 8) & 0xF;
+               if (major < 3 || (major == 3 && minor == 1)) {
+                       /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
+                       AdvReadWordLram(iop_base, 0x120, wdtr_able);
+               } else {
+                       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
                }
-       } 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);
-}
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
+       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                               max_cmd[tid]);
+       }
 
-static int
-AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
-{
-       int sta = FALSE;
+       asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
+                                       _adv_asc3550_size, ADV_3550_MEMSIZE,
+                                       _adv_asc3550_chksum);
+       if (asc_dvc->err_code)
+               return ADV_ERROR;
 
-       if (AscHostReqRiscHalt(iop_base)) {
-               sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
-               AscStartChip(iop_base);
-               return (sta);
+       /*
+        * Restore the RISC memory BIOS region.
+        */
+       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
+               AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
+                                bios_mem[i]);
+       }
+
+       /*
+        * Calculate and write the microcode code checksum to the microcode
+        * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
+        */
+       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
+       AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
+       code_sum = 0;
+       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
+       for (word = begin_addr; word < end_addr; word += 2) {
+               code_sum += AdvReadWordAutoIncLram(iop_base);
+       }
+       AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
+
+       /*
+        * Read and save microcode version and date.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
+                       asc_dvc->cfg->mcode_date);
+       AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
+                       asc_dvc->cfg->mcode_version);
+
+       /*
+        * Set the chip type to indicate the ASC3550.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
+
+       /*
+        * If the PCI Configuration Command Register "Parity Error Response
+        * Control" Bit was clear (0), then set the microcode variable
+        * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
+        * to ignore DMA parity errors.
+        */
+       if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
+               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+               word |= CONTROL_FLAG_IGNORE_PERR;
+               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
        }
-       return (sta);
-}
 
-static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
-{
-       ASC_SCSI_BIT_ID_TYPE org_id;
-       int i;
-       int sta = TRUE;
+       /*
+        * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
+        * threshold of 128 bytes. This register is only accessible to the host.
+        */
+       AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
+                            START_CTL_EMFU | READ_CMD_MRM);
 
-       AscSetBank(iop_base, 1);
-       org_id = AscReadChipDvcID(iop_base);
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               if (org_id == (0x01 << i))
-                       break;
+       /*
+        * Microcode operating variables for WDTR, SDTR, and command tag
+        * queuing will be set in slave_configure() based on what a
+        * device reports it is capable of in Inquiry byte 7.
+        *
+        * If SCSI Bus Resets have been disabled, then directly set
+        * SDTR and WDTR from the EEPROM configuration. This will allow
+        * the BIOS and warm boot to work without a SCSI bus hang on
+        * the Inquiry caused by host and target mismatched DTR values.
+        * Without the SCSI Bus Reset, before an Inquiry a device can't
+        * be assumed to be in Asynchronous, Narrow mode.
+        */
+       if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
+               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
+                                asc_dvc->wdtr_able);
+               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
+                                asc_dvc->sdtr_able);
        }
-       org_id = (ASC_SCSI_BIT_ID_TYPE) i;
-       AscWriteChipDvcID(iop_base, id);
-       if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
-               AscSetBank(iop_base, 0);
-               AscSetChipSyn(iop_base, sdtr_data);
-               if (AscGetChipSyn(iop_base) != sdtr_data) {
-                       sta = FALSE;
+
+       /*
+        * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
+        * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
+        * bitmask. These values determine the maximum SDTR speed negotiated
+        * with a device.
+        *
+        * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
+        * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
+        * without determining here whether the device supports SDTR.
+        *
+        * 4-bit speed  SDTR speed name
+        * ===========  ===============
+        * 0000b (0x0)  SDTR disabled
+        * 0001b (0x1)  5 Mhz
+        * 0010b (0x2)  10 Mhz
+        * 0011b (0x3)  20 Mhz (Ultra)
+        * 0100b (0x4)  40 Mhz (LVD/Ultra2)
+        * 0101b (0x5)  80 Mhz (LVD2/Ultra3)
+        * 0110b (0x6)  Undefined
+        * .
+        * 1111b (0xF)  Undefined
+        */
+       word = 0;
+       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+               if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
+                       /* Set Ultra speed for TID 'tid'. */
+                       word |= (0x3 << (4 * (tid % 4)));
+               } else {
+                       /* Set Fast speed for TID 'tid'. */
+                       word |= (0x2 << (4 * (tid % 4)));
+               }
+               if (tid == 3) { /* Check if done with sdtr_speed1. */
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
+                       word = 0;
+               } else if (tid == 7) {  /* Check if done with sdtr_speed2. */
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
+                       word = 0;
+               } else if (tid == 11) { /* Check if done with sdtr_speed3. */
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
+                       word = 0;
+               } else if (tid == 15) { /* Check if done with sdtr_speed4. */
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
+                       /* End of loop. */
                }
-       } else {
-               sta = FALSE;
        }
-       AscSetBank(iop_base, 1);
-       AscWriteChipDvcID(iop_base, org_id);
-       AscSetBank(iop_base, 0);
-       return (sta);
-}
 
-static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
-{
-       uchar i;
-       ushort s_addr;
-       PortAddr iop_base;
-       ushort warn_code;
+       /*
+        * Set microcode operating variable for the disconnect per TID bitmask.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
+                        asc_dvc->cfg->disc_enable);
 
-       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);
+       /*
+        * Set SCSI_CFG0 Microcode Default Value.
+        *
+        * The microcode will set the SCSI_CFG0 register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
+                        PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
+                        asc_dvc->chip_scsi_id);
+
+       /*
+        * Determine SCSI_CFG1 Microcode Default Value.
+        *
+        * The microcode will set the SCSI_CFG1 register using this value
+        * after it is started below.
+        */
+
+       /* Read current SCSI_CFG1 Register value. */
+       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+
+       /*
+        * If all three connectors are in use, return an error.
+        */
+       if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
+           (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
+               asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
+               return ADV_ERROR;
        }
-       return (warn_code);
-}
 
-static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
-{
-       PortAddr iop_base;
-       int i;
-       ushort lram_addr;
+       /*
+        * If the internal narrow cable is reversed all of the SCSI_CTRL
+        * register signals will be set. Check for and return an error if
+        * this condition is found.
+        */
+       if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
+               asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
+               return ADV_ERROR;
+       }
 
-       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);
-       AscPutQDoneInProgress(iop_base, 0);
-       lram_addr = ASC_QADR_BEG;
-       for (i = 0; i < 32; i++, lram_addr += 2) {
-               AscWriteLramWord(iop_base, lram_addr, 0);
+       /*
+        * If this is a differential board and a single-ended device
+        * is attached to one of the connectors, return an error.
+        */
+       if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
+               asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
+               return ADV_ERROR;
        }
-       return (0);
-}
 
-static int AscSetLibErrorCode(ASC_DVC_VAR *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);
+       /*
+        * If automatic termination control is enabled, then set the
+        * termination value based on a table listed in a_condor.h.
+        *
+        * If manual termination was specified with an EEPROM setting
+        * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
+        * is ready to be 'ored' into SCSI_CFG1.
+        */
+       if (asc_dvc->cfg->termination == 0) {
+               /*
+                * The software always controls termination by setting TERM_CTL_SEL.
+                * If TERM_CTL_SEL were set to 0, the hardware would set termination.
+                */
+               asc_dvc->cfg->termination |= TERM_CTL_SEL;
+
+               switch (scsi_cfg1 & CABLE_DETECT) {
+                       /* TERM_CTL_H: on, TERM_CTL_L: on */
+               case 0x3:
+               case 0x7:
+               case 0xB:
+               case 0xD:
+               case 0xE:
+               case 0xF:
+                       asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
+                       break;
+
+                       /* TERM_CTL_H: on, TERM_CTL_L: off */
+               case 0x1:
+               case 0x5:
+               case 0x9:
+               case 0xA:
+               case 0xC:
+                       asc_dvc->cfg->termination |= TERM_CTL_H;
+                       break;
+
+                       /* TERM_CTL_H: off, TERM_CTL_L: off */
+               case 0x2:
+               case 0x6:
+                       break;
+               }
        }
-       return (err_code);
-}
 
-static uchar
-AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
-{
-       EXT_MSG sdtr_buf;
-       uchar sdtr_period_index;
-       PortAddr iop_base;
+       /*
+        * Clear any set TERM_CTL_H and TERM_CTL_L bits.
+        */
+       scsi_cfg1 &= ~TERM_CTL;
 
-       iop_base = asc_dvc->iop_base;
-       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;
-       if ((sdtr_period_index =
-            AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
-           asc_dvc->max_sdtr_index) {
-               AscMemWordCopyPtrToLram(iop_base,
-                                       ASCV_MSGOUT_BEG,
-                                       (uchar *)&sdtr_buf,
-                                       sizeof(EXT_MSG) >> 1);
-               return ((sdtr_period_index << 4) | sdtr_offset);
-       } else {
+       /*
+        * Invert the TERM_CTL_H and TERM_CTL_L bits and then
+        * set 'scsi_cfg1'. The TERM_POL bit does not need to be
+        * referenced, because the hardware internally inverts
+        * the Termination High and Low bits if TERM_POL is set.
+        */
+       scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
 
-               sdtr_buf.req_ack_offset = 0;
-               AscMemWordCopyPtrToLram(iop_base,
-                                       ASCV_MSGOUT_BEG,
-                                       (uchar *)&sdtr_buf,
-                                       sizeof(EXT_MSG) >> 1);
-               return (0);
-       }
-}
+       /*
+        * Set SCSI_CFG1 Microcode Default Value
+        *
+        * Set filter value and possibly modified termination control
+        * bits in the Microcode SCSI_CFG1 Register Value.
+        *
+        * The microcode will set the SCSI_CFG1 register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
+                        FLTR_DISABLE | scsi_cfg1);
 
-static uchar
-AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
-{
-       uchar byte;
-       uchar sdtr_period_ix;
+       /*
+        * Set MEM_CFG Microcode Default Value
+        *
+        * The microcode will set the MEM_CFG register using this value
+        * after it is started below.
+        *
+        * MEM_CFG may be accessed as a word or byte, but only bits 0-7
+        * are defined.
+        *
+        * ASC-3550 has 8KB internal memory.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
+                        BIOS_EN | RAM_SZ_8KB);
 
-       sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
-       if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
-           ) {
-               return (0xFF);
-       }
-       byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
-       return (byte);
-}
+       /*
+        * Set SEL_MASK Microcode Default Value
+        *
+        * The microcode will set the SEL_MASK register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
+                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
 
-static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
-{
-       AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
-       AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
-       return;
-}
+       AdvBuildCarrierFreelist(asc_dvc);
 
-static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
-{
-       uchar *period_table;
-       int max_index;
-       int min_index;
-       int i;
+       /*
+        * Set-up the Host->RISC Initiator Command Queue (ICQ).
+        */
 
-       period_table = asc_dvc->sdtr_period_tbl;
-       max_index = (int)asc_dvc->max_sdtr_index;
-       min_index = (int)asc_dvc->host_init_sdtr_index;
-       if ((syn_time <= period_table[max_index])) {
-               for (i = min_index; i < (max_index - 1); i++) {
-                       if (syn_time <= period_table[i]) {
-                               return ((uchar)i);
-                       }
-               }
-               return ((uchar)max_index);
-       } else {
-               return ((uchar)(max_index + 1));
+       if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
+               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
+               return ADV_ERROR;
        }
-}
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
 
-static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
-{
-       ushort q_addr;
-       uchar next_qp;
-       uchar q_status;
+       /*
+        * The first command issued will be placed in the stopper carrier.
+        */
+       asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
 
-       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);
+       /*
+        * Set RISC ICQ physical address start value.
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
+
+       /*
+        * Set-up the RISC->Host Initiator Response Queue (IRQ).
+        */
+       if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
+               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
+               return ADV_ERROR;
        }
-       return (ASC_QLINK_END);
-}
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
 
-static uchar
-AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
-{
-       uchar i;
+       /*
+        * The first command completed by the RISC will be placed in
+        * the stopper.
+        *
+        * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
+        * completed the RISC will set the ASC_RQ_STOPPER bit.
+        */
+       asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
 
-       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);
-}
+       /*
+        * Set RISC IRQ physical address start value.
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
+       asc_dvc->carr_pending_cnt = 0;
 
-static int AscHostReqRiscHalt(PortAddr iop_base)
-{
-       int count = 0;
-       int sta = 0;
-       uchar saved_stop_code;
+       AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
+                            (ADV_INTR_ENABLE_HOST_INTR |
+                             ADV_INTR_ENABLE_GLOBAL_INTR));
 
-       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);
-}
+       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
+       AdvWriteWordRegister(iop_base, IOPW_PC, word);
 
-static int AscStopQueueExe(PortAddr iop_base)
-{
-       int count = 0;
+       /* finally, finally, gentlemen, start your engine */
+       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
 
-       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);
+       /*
+        * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
+        * Resets should be performed. The RISC has to be running
+        * to issue a SCSI Bus Reset.
+        */
+       if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
+               /*
+                * If the BIOS Signature is present in memory, restore the
+                * BIOS Handshake Configuration Table and do not perform
+                * a SCSI Bus Reset.
+                */
+               if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
+                   0x55AA) {
+                       /*
+                        * Restore per TID negotiated values.
+                        */
+                       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
+                                        tagqng_able);
+                       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+                               AdvWriteByteLram(iop_base,
+                                                ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                                                max_cmd[tid]);
                        }
-                       DvcSleepMilliSecond(100);
-               } while (count++ < 20);
+               } else {
+                       if (AdvResetSB(asc_dvc) != ADV_TRUE) {
+                               warn_code = ASC_WARN_BUSRESET_ERROR;
+                       }
+               }
        }
-       return (0);
+
+       return warn_code;
 }
 
-static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
-{
-       udelay(micro_sec);
-}
+/*
+ * Initialize the ASC-38C0800.
+ *
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ *
+ * Needed after initialization for error recovery.
+ */
+static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
+{
+       AdvPortAddr iop_base;
+       ushort warn_code;
+       int begin_addr;
+       int end_addr;
+       ushort code_sum;
+       int word;
+       int i;
+       ushort scsi_cfg1;
+       uchar byte;
+       uchar tid;
+       ushort bios_mem[ASC_MC_BIOSLEN / 2];    /* BIOS RISC Memory 0x40-0x8F. */
+       ushort wdtr_able, sdtr_able, tagqng_able;
+       uchar max_cmd[ADV_MAX_TID + 1];
+
+       /* If there is already an error, don't continue. */
+       if (asc_dvc->err_code != 0)
+               return ADV_ERROR;
 
-static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec)
-{
-       udelay((nano_sec + 999) / 1000);
-}
+       /*
+        * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
+        */
+       if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
+               asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
+               return ADV_ERROR;
+       }
 
-#ifdef CONFIG_ISA
-static ASC_DCNT __init AscGetEisaProductID(PortAddr iop_base)
-{
-       PortAddr eisa_iop;
-       ushort product_id_high, product_id_low;
-       ASC_DCNT 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 = ((ASC_DCNT) product_id_high << 16) |
-           (ASC_DCNT) product_id_low;
-       return (product_id);
-}
+       warn_code = 0;
+       iop_base = asc_dvc->iop_base;
 
-static PortAddr __init AscSearchIOPortAddrEISA(PortAddr iop_base)
-{
-       ASC_DCNT eisa_product_id;
+       /*
+        * Save the RISC memory BIOS region before writing the microcode.
+        * The BIOS may already be loaded and using its RISC LRAM region
+        * so its region must be saved and restored.
+        *
+        * Note: This code makes the assumption, which is currently true,
+        * that a chip reset does not clear RISC LRAM.
+        */
+       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
+               AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
+                               bios_mem[i]);
+       }
 
-       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;
-               }
+       /*
+        * Save current per TID negotiated values.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
+       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                               max_cmd[tid]);
        }
-       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);
-                       }
+
+       /*
+        * RAM BIST (RAM Built-In Self Test)
+        *
+        * Address : I/O base + offset 0x38h register (byte).
+        * Function: Bit 7-6(RW) : RAM mode
+        *                          Normal Mode   : 0x00
+        *                          Pre-test Mode : 0x40
+        *                          RAM Test Mode : 0x80
+        *           Bit 5       : unused
+        *           Bit 4(RO)   : Done bit
+        *           Bit 3-0(RO) : Status
+        *                          Host Error    : 0x08
+        *                          Int_RAM Error : 0x04
+        *                          RISC Error    : 0x02
+        *                          SCSI Error    : 0x01
+        *                          No Error      : 0x00
+        *
+        * Note: RAM BIST code should be put right here, before loading the
+        * microcode and after saving the RISC memory BIOS region.
+        */
+
+       /*
+        * LRAM Pre-test
+        *
+        * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
+        * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
+        * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
+        * to NORMAL_MODE, return an error too.
+        */
+       for (i = 0; i < 2; i++) {
+               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
+               mdelay(10);     /* Wait for 10ms before reading back. */
+               byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
+               if ((byte & RAM_TEST_DONE) == 0
+                   || (byte & 0x0F) != PRE_TEST_VALUE) {
+                       asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
+                       return ADV_ERROR;
                }
-               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;
+
+               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
+               mdelay(10);     /* Wait for 10ms before reading back. */
+               if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
+                   != NORMAL_VALUE) {
+                       asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
+                       return ADV_ERROR;
                }
        }
-       return (0);
-}
-#endif /* CONFIG_ISA */
 
-static int AscStartChip(PortAddr iop_base)
-{
-       AscSetChipControl(iop_base, 0);
-       if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
-               return (0);
+       /*
+        * LRAM Test - It takes about 1.5 ms to run through the test.
+        *
+        * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
+        * If Done bit not set or Status not 0, save register byte, set the
+        * err_code, and return an error.
+        */
+       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
+       mdelay(10);     /* Wait for 10ms before checking status. */
+
+       byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
+       if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
+               /* Get here if Done bit not set or Status not 0. */
+               asc_dvc->bist_err_code = byte;  /* for BIOS display message */
+               asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
+               return ADV_ERROR;
        }
-       return (1);
-}
 
-static int AscStopChip(PortAddr iop_base)
-{
-       uchar cc_val;
+       /* We need to reset back to normal mode after LRAM test passes. */
+       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
 
-       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);
+       asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
+                                _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
+                                _adv_asc38C0800_chksum);
+       if (asc_dvc->err_code)
+               return ADV_ERROR;
+
+       /*
+        * Restore the RISC memory BIOS region.
+        */
+       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
+               AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
+                                bios_mem[i]);
        }
-       return (1);
-}
 
-static int AscIsChipHalted(PortAddr iop_base)
-{
-       if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
-               if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
-                       return (1);
-               }
+       /*
+        * Calculate and write the microcode code checksum to the microcode
+        * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
+        */
+       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
+       AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
+       code_sum = 0;
+       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
+       for (word = begin_addr; word < end_addr; word += 2) {
+               code_sum += AdvReadWordAutoIncLram(iop_base);
        }
-       return (0);
-}
+       AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
 
-static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
-{
-       AscSetBank(iop_base, 1);
-       AscWriteChipIH(iop_base, ins_code);
-       AscSetBank(iop_base, 0);
-       return;
-}
+       /*
+        * Read microcode version and date.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
+                       asc_dvc->cfg->mcode_date);
+       AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
+                       asc_dvc->cfg->mcode_version);
 
-static void AscAckInterrupt(PortAddr iop_base)
-{
-       uchar host_flag;
-       uchar risc_flag;
-       ushort loop;
+       /*
+        * Set the chip type to indicate the ASC38C0800.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
 
-       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) & (~ASC_HOST_FLAG_ACK_INT);
-       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;
-}
+       /*
+        * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
+        * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
+        * cable detection and then we are able to read C_DET[3:0].
+        *
+        * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
+        * Microcode Default Value' section below.
+        */
+       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+       AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
+                            scsi_cfg1 | DIS_TERM_DRV);
 
-static void AscDisableInterrupt(PortAddr iop_base)
-{
-       ushort cfg;
+       /*
+        * If the PCI Configuration Command Register "Parity Error Response
+        * Control" Bit was clear (0), then set the microcode variable
+        * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
+        * to ignore DMA parity errors.
+        */
+       if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
+               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+               word |= CONTROL_FLAG_IGNORE_PERR;
+               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+       }
 
-       cfg = AscGetChipCfgLsw(iop_base);
-       AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
-       return;
-}
+       /*
+        * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
+        * bits for the default FIFO threshold.
+        *
+        * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
+        *
+        * For DMA Errata #4 set the BC_THRESH_ENB bit.
+        */
+       AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
+                            BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
+                            READ_CMD_MRM);
 
-static void AscEnableInterrupt(PortAddr iop_base)
-{
-       ushort cfg;
+       /*
+        * Microcode operating variables for WDTR, SDTR, and command tag
+        * queuing will be set in slave_configure() based on what a
+        * device reports it is capable of in Inquiry byte 7.
+        *
+        * If SCSI Bus Resets have been disabled, then directly set
+        * SDTR and WDTR from the EEPROM configuration. This will allow
+        * the BIOS and warm boot to work without a SCSI bus hang on
+        * the Inquiry caused by host and target mismatched DTR values.
+        * Without the SCSI Bus Reset, before an Inquiry a device can't
+        * be assumed to be in Asynchronous, Narrow mode.
+        */
+       if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
+               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
+                                asc_dvc->wdtr_able);
+               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
+                                asc_dvc->sdtr_able);
+       }
 
-       cfg = AscGetChipCfgLsw(iop_base);
-       AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
-       return;
-}
+       /*
+        * Set microcode operating variables for DISC and SDTR_SPEED1,
+        * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
+        * configuration values.
+        *
+        * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
+        * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
+        * without determining here whether the device supports SDTR.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
+                        asc_dvc->cfg->disc_enable);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
 
-static void AscSetBank(PortAddr iop_base, uchar bank)
-{
-       uchar val;
+       /*
+        * Set SCSI_CFG0 Microcode Default Value.
+        *
+        * The microcode will set the SCSI_CFG0 register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
+                        PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
+                        asc_dvc->chip_scsi_id);
 
-       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;
-}
+       /*
+        * Determine SCSI_CFG1 Microcode Default Value.
+        *
+        * The microcode will set the SCSI_CFG1 register using this value
+        * after it is started below.
+        */
 
-static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
-{
-       PortAddr iop_base;
-       int i = 10;
+       /* Read current SCSI_CFG1 Register value. */
+       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
 
-       iop_base = asc_dvc->iop_base;
-       while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
-              && (i-- > 0)) {
-               DvcSleepMilliSecond(100);
+       /*
+        * If the internal narrow cable is reversed all of the SCSI_CTRL
+        * register signals will be set. Check for and return an error if
+        * this condition is found.
+        */
+       if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
+               asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
+               return ADV_ERROR;
        }
-       AscStopChip(iop_base);
-       AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
-       DvcDelayNanoSecond(asc_dvc, 60000);
-       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);
-       AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
-       AscSetChipStatus(iop_base, 0);
-       return (AscIsChipHalted(iop_base));
-}
 
-static ASC_DCNT __init 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);
-}
-
-#ifdef CONFIG_ISA
-static ushort __init 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);
-}
+       /*
+        * All kind of combinations of devices attached to one of four
+        * connectors are acceptable except HVD device attached. For example,
+        * LVD device can be attached to SE connector while SE device attached
+        * to LVD connector.  If LVD device attached to SE connector, it only
+        * runs up to Ultra speed.
+        *
+        * If an HVD device is attached to one of LVD connectors, return an
+        * error.  However, there is no way to detect HVD device attached to
+        * SE connectors.
+        */
+       if (scsi_cfg1 & HVD) {
+               asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
+               return ADV_ERROR;
+       }
 
-static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
-{
-       ushort cfg_lsw;
-       uchar value;
+       /*
+        * If either SE or LVD automatic termination control is enabled, then
+        * set the termination value based on a table listed in a_condor.h.
+        *
+        * If manual termination was specified with an EEPROM setting then
+        * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
+        * to be 'ored' into SCSI_CFG1.
+        */
+       if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
+               /* SE automatic termination control is enabled. */
+               switch (scsi_cfg1 & C_DET_SE) {
+                       /* TERM_SE_HI: on, TERM_SE_LO: on */
+               case 0x1:
+               case 0x2:
+               case 0x3:
+                       asc_dvc->cfg->termination |= TERM_SE;
+                       break;
 
-       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));
+                       /* TERM_SE_HI: on, TERM_SE_LO: off */
+               case 0x0:
+                       asc_dvc->cfg->termination |= TERM_SE_HI;
+                       break;
+               }
        }
-       return (0);
-}
 
-static uchar __init AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
-{
-       speed_value &= 0x07;
-       AscSetBank(iop_base, 1);
-       AscWriteChipDmaSpeed(iop_base, speed_value);
-       AscSetBank(iop_base, 0);
-       return (AscGetIsaDmaSpeed(iop_base));
-}
+       if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
+               /* LVD automatic termination control is enabled. */
+               switch (scsi_cfg1 & C_DET_LVD) {
+                       /* TERM_LVD_HI: on, TERM_LVD_LO: on */
+               case 0x4:
+               case 0x8:
+               case 0xC:
+                       asc_dvc->cfg->termination |= TERM_LVD;
+                       break;
 
-static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base)
-{
-       uchar speed_value;
+                       /* TERM_LVD_HI: off, TERM_LVD_LO: off */
+               case 0x0:
+                       break;
+               }
+       }
 
-       AscSetBank(iop_base, 1);
-       speed_value = AscReadChipDmaSpeed(iop_base);
-       speed_value &= 0x07;
-       AscSetBank(iop_base, 0);
-       return (speed_value);
-}
-#endif /* CONFIG_ISA */
+       /*
+        * Clear any set TERM_SE and TERM_LVD bits.
+        */
+       scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
 
-static ushort __init
-AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset)
-{
-       uchar lsb, msb;
+       /*
+        * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
+        */
+       scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
 
-       lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
-       msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
-       return ((ushort)((msb << 8) | lsb));
-}
+       /*
+        * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
+        * bits and set possibly modified termination control bits in the
+        * Microcode SCSI_CFG1 Register Value.
+        */
+       scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
 
-static ushort __init AscInitGetConfig(ASC_DVC_VAR *asc_dvc)
-{
-       ushort warn_code;
-       PortAddr iop_base;
-       ushort PCIDeviceID;
-       ushort PCIVendorID;
-       uchar PCIRevisionID;
-       uchar prevCmdRegBits;
+       /*
+        * Set SCSI_CFG1 Microcode Default Value
+        *
+        * Set possibly modified termination control and reset DIS_TERM_DRV
+        * bits in the Microcode SCSI_CFG1 Register Value.
+        *
+        * The microcode will set the SCSI_CFG1 register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
 
-       warn_code = 0;
-       iop_base = asc_dvc->iop_base;
-       asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
-       if (asc_dvc->err_code != 0) {
-               return (UW_ERR);
-       }
-       if (asc_dvc->bus_type == ASC_IS_PCI) {
-               PCIVendorID = AscReadPCIConfigWord(asc_dvc,
-                                                  AscPCIConfigVendorIDRegister);
+       /*
+        * Set MEM_CFG Microcode Default Value
+        *
+        * The microcode will set the MEM_CFG register using this value
+        * after it is started below.
+        *
+        * MEM_CFG may be accessed as a word or byte, but only bits 0-7
+        * are defined.
+        *
+        * ASC-38C0800 has 16KB internal memory.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
+                        BIOS_EN | RAM_SZ_16KB);
 
-               PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
-                                                  AscPCIConfigDeviceIDRegister);
+       /*
+        * Set SEL_MASK Microcode Default Value
+        *
+        * The microcode will set the SEL_MASK register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
+                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
 
-               PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
-                                                    AscPCIConfigRevisionIDRegister);
+       AdvBuildCarrierFreelist(asc_dvc);
 
-               if (PCIVendorID != PCI_VENDOR_ID_ASP) {
-                       warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-               }
-               prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
-                                                     AscPCIConfigCommandRegister);
-
-               if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
-                   AscPCICmdRegBits_IOMemBusMaster) {
-                       DvcWritePCIConfigByte(asc_dvc,
-                                             AscPCIConfigCommandRegister,
-                                             (prevCmdRegBits |
-                                              AscPCICmdRegBits_IOMemBusMaster));
-
-                       if ((DvcReadPCIConfigByte(asc_dvc,
-                                                 AscPCIConfigCommandRegister)
-                            & AscPCICmdRegBits_IOMemBusMaster)
-                           != AscPCICmdRegBits_IOMemBusMaster) {
-                               warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-                       }
-               }
-               if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) ||
-                   (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) {
-                       DvcWritePCIConfigByte(asc_dvc,
-                                             AscPCIConfigLatencyTimer, 0x00);
-                       if (DvcReadPCIConfigByte
-                           (asc_dvc, AscPCIConfigLatencyTimer)
-                           != 0x00) {
-                               warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-                       }
-               } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) {
-                       if (DvcReadPCIConfigByte(asc_dvc,
-                                                AscPCIConfigLatencyTimer) <
-                           0x20) {
-                               DvcWritePCIConfigByte(asc_dvc,
-                                                     AscPCIConfigLatencyTimer,
-                                                     0x20);
-
-                               if (DvcReadPCIConfigByte(asc_dvc,
-                                                        AscPCIConfigLatencyTimer)
-                                   < 0x20) {
-                                       warn_code |=
-                                           ASC_WARN_SET_PCI_CONFIG_SPACE;
-                               }
-                       }
-               }
-       }
+       /*
+        * Set-up the Host->RISC Initiator Command Queue (ICQ).
+        */
 
-       if (AscFindSignature(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 > ASC_MAX_SCSI_RESET_WAIT) {
-                       asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
-               }
-       } else {
-               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+       if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
+               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
+               return ADV_ERROR;
        }
-       return (warn_code);
-}
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
 
-static ushort __init AscInitSetConfig(ASC_DVC_VAR *asc_dvc)
-{
-       ushort warn_code = 0;
+       /*
+        * The first command issued will be placed in the stopper carrier.
+        */
+       asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
 
-       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;
+       /*
+        * Set RISC ICQ physical address start value.
+        * carr_pa is LE, must be native before write
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
+
+       /*
+        * Set-up the RISC->Host Initiator Response Queue (IRQ).
+        */
+       if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
+               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
+               return ADV_ERROR;
        }
-       return (warn_code);
-}
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
 
-static ushort __init AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc)
-{
-       PortAddr iop_base;
-       ushort cfg_msw;
-       ushort warn_code;
-       ushort pci_device_id = 0;
+       /*
+        * The first command completed by the RISC will be placed in
+        * the stopper.
+        *
+        * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
+        * completed the RISC will set the ASC_RQ_STOPPER bit.
+        */
+       asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
 
-       iop_base = asc_dvc->iop_base;
-#ifdef CONFIG_PCI
-       if (asc_dvc->cfg->dev)
-               pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device;
-#endif
-       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 ((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 (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
-               warn_code |= ASC_WARN_AUTO_CONFIG;
-       }
-       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 (asc_dvc->bus_type & ASC_IS_PCI) {
-               cfg_msw &= 0xFFC0;
-               AscSetChipCfgMsw(iop_base, cfg_msw);
-               if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
-               } else {
-                       if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) ||
-                           (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) {
-                               asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
-                               asc_dvc->bug_fix_cntl |=
-                                   ASC_BUG_FIX_ASYN_USE_SYN;
-                       }
-               }
-       } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
-               if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
-                   == ASC_CHIP_VER_ASYN_BUG) {
-                       asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
-               }
-       }
-       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;
-       }
-#ifdef CONFIG_ISA
-       if (asc_dvc->bus_type & ASC_IS_ISA) {
-               AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
-               AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
-       }
-#endif /* CONFIG_ISA */
-       return (warn_code);
-}
+       /*
+        * Set RISC IRQ physical address start value.
+        *
+        * carr_pa is LE, must be native before write *
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
+       asc_dvc->carr_pending_cnt = 0;
 
-static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
-{
-       ushort warn_code;
-       PortAddr iop_base;
+       AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
+                            (ADV_INTR_ENABLE_HOST_INTR |
+                             ADV_INTR_ENABLE_GLOBAL_INTR));
 
-       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)) {
-               AscResetChipAndScsiBus(asc_dvc);
-               DvcSleepMilliSecond((ASC_DCNT)
-                                   ((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);
-       if (!AscFindSignature(asc_dvc->iop_base)) {
-               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
-               return (warn_code);
-       }
-       AscDisableInterrupt(iop_base);
-       warn_code |= AscInitLram(asc_dvc);
-       if (asc_dvc->err_code != 0)
-               return (UW_ERR);
-       ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
-                (ulong)_asc_mcode_chksum);
-       if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
-                            _asc_mcode_size) != _asc_mcode_chksum) {
-               asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
-               return (warn_code);
-       }
-       warn_code |= AscInitMicroCodeVar(asc_dvc);
-       asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
-       AscEnableInterrupt(iop_base);
-       return (warn_code);
-}
+       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
+       AdvWriteWordRegister(iop_base, IOPW_PC, word);
 
-static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
-{
-       int i;
-       PortAddr iop_base;
-       ushort warn_code;
-       uchar chip_version;
+       /* finally, finally, gentlemen, start your engine */
+       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
 
-       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;
-       }
-       AscSetChipControl(iop_base, CC_HALT);
-       AscSetChipStatus(iop_base, 0);
-       asc_dvc->bug_fix_cntl = 0;
-       asc_dvc->pci_fix_asyn_xfer = 0;
-       asc_dvc->pci_fix_asyn_xfer_always = 0;
-       /* asc_dvc->init_state initalized in AscInitGetConfig(). */
-       asc_dvc->sdtr_done = 0;
-       asc_dvc->cur_total_qng = 0;
-       asc_dvc->is_in_int = 0;
-       asc_dvc->in_critical_cnt = 0;
-       asc_dvc->last_q_shortage = 0;
-       asc_dvc->use_tagged_qng = 0;
-       asc_dvc->no_scam = 0;
-       asc_dvc->unit_not_ready = 0;
-       asc_dvc->queue_full_or_busy = 0;
-       asc_dvc->redo_scam = 0;
-       asc_dvc->res2 = 0;
-       asc_dvc->host_init_sdtr_index = 0;
-       asc_dvc->cfg->can_tagged_qng = 0;
-       asc_dvc->cfg->cmd_qng_enabled = 0;
-       asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
-       asc_dvc->init_sdtr = 0;
-       asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
-       asc_dvc->scsi_reset_wait = 3;
-       asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
-       asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
-       asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
-       asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
-       asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
-       asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
-       asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
-           ASC_LIB_VERSION_MINOR;
-       chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
-       asc_dvc->cfg->chip_version = chip_version;
-       asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
-       asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
-       asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
-       asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
-       asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
-       asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
-       asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
-       asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
-       asc_dvc->max_sdtr_index = 7;
-       if ((asc_dvc->bus_type & ASC_IS_PCI) &&
-           (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
-               asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
-               asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
-               asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
-               asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
-               asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
-               asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
-               asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
-               asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
-               asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
-               asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
-               asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
-               asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
-               asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
-               asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
-               asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
-               asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
-               asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
-               asc_dvc->max_sdtr_index = 15;
-               if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
-                       AscSetExtraControl(iop_base,
-                                          (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
-               } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
-                       AscSetExtraControl(iop_base,
-                                          (SEC_ACTIVE_NEGATE |
-                                           SEC_ENABLE_FILTER));
+       /*
+        * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
+        * Resets should be performed. The RISC has to be running
+        * to issue a SCSI Bus Reset.
+        */
+       if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
+               /*
+                * If the BIOS Signature is present in memory, restore the
+                * BIOS Handshake Configuration Table and do not perform
+                * a SCSI Bus Reset.
+                */
+               if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
+                   0x55AA) {
+                       /*
+                        * Restore per TID negotiated values.
+                        */
+                       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
+                                        tagqng_able);
+                       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+                               AdvWriteByteLram(iop_base,
+                                                ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                                                max_cmd[tid]);
+                       }
+               } else {
+                       if (AdvResetSB(asc_dvc) != ADV_TRUE) {
+                               warn_code = ASC_WARN_BUSRESET_ERROR;
+                       }
                }
        }
-       if (asc_dvc->bus_type == ASC_IS_PCI) {
-               AscSetExtraControl(iop_base,
-                                  (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
-       }
 
-       asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
-       if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
-               AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
-               asc_dvc->bus_type = ASC_IS_ISAPNP;
-       }
-#ifdef CONFIG_ISA
-       if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
-               asc_dvc->cfg->isa_dma_channel =
-                   (uchar)AscGetIsaDmaChannel(iop_base);
-       }
-#endif /* CONFIG_ISA */
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               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 *)0L;
-               asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
-               asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
-       }
-       return (warn_code);
+       return warn_code;
 }
 
-static ushort __init AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
+/*
+ * Initialize the ASC-38C1600.
+ *
+ * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ *
+ * Needed after initialization for error recovery.
+ */
+static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
 {
-       ASCEEP_CONFIG eep_config_buf;
-       ASCEEP_CONFIG *eep_config;
-       PortAddr iop_base;
-       ushort chksum;
+       AdvPortAddr iop_base;
        ushort warn_code;
-       ushort cfg_msw, cfg_lsw;
+       int begin_addr;
+       int end_addr;
+       ushort code_sum;
+       long word;
        int i;
-       int write_eep = 0;
-
-       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(asc_dvc);
-               DvcSleepMilliSecond((ASC_DCNT)
-                                   ((ushort)asc_dvc->scsi_reset_wait * 1000));
-       }
-       if (AscIsChipHalted(iop_base) == FALSE) {
-               asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
-               return (warn_code);
+       ushort scsi_cfg1;
+       uchar byte;
+       uchar tid;
+       ushort bios_mem[ASC_MC_BIOSLEN / 2];    /* BIOS RISC Memory 0x40-0x8F. */
+       ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
+       uchar max_cmd[ASC_MAX_TID + 1];
+
+       /* If there is already an error, don't continue. */
+       if (asc_dvc->err_code != 0) {
+               return ADV_ERROR;
        }
-       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);
+
+       /*
+        * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
+        */
+       if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
+               asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
+               return ADV_ERROR;
        }
-       eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
-       cfg_msw = AscGetChipCfgMsw(iop_base);
-       cfg_lsw = AscGetChipCfgLsw(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);
+
+       warn_code = 0;
+       iop_base = asc_dvc->iop_base;
+
+       /*
+        * Save the RISC memory BIOS region before writing the microcode.
+        * The BIOS may already be loaded and using its RISC LRAM region
+        * so its region must be saved and restored.
+        *
+        * Note: This code makes the assumption, which is currently true,
+        * that a chip reset does not clear RISC LRAM.
+        */
+       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
+               AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
+                               bios_mem[i]);
        }
-       chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
-       ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
-       if (chksum == 0) {
-               chksum = 0xaa55;
+
+       /*
+        * Save current per TID negotiated values.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+       AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
+       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
+       for (tid = 0; tid <= ASC_MAX_TID; tid++) {
+               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                               max_cmd[tid]);
        }
-       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);
-                       }
+
+       /*
+        * RAM BIST (Built-In Self Test)
+        *
+        * Address : I/O base + offset 0x38h register (byte).
+        * Function: Bit 7-6(RW) : RAM mode
+        *                          Normal Mode   : 0x00
+        *                          Pre-test Mode : 0x40
+        *                          RAM Test Mode : 0x80
+        *           Bit 5       : unused
+        *           Bit 4(RO)   : Done bit
+        *           Bit 3-0(RO) : Status
+        *                          Host Error    : 0x08
+        *                          Int_RAM Error : 0x04
+        *                          RISC Error    : 0x02
+        *                          SCSI Error    : 0x01
+        *                          No Error      : 0x00
+        *
+        * Note: RAM BIST code should be put right here, before loading the
+        * microcode and after saving the RISC memory BIOS region.
+        */
+
+       /*
+        * LRAM Pre-test
+        *
+        * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
+        * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
+        * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
+        * to NORMAL_MODE, return an error too.
+        */
+       for (i = 0; i < 2; i++) {
+               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
+               mdelay(10);     /* Wait for 10ms before reading back. */
+               byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
+               if ((byte & RAM_TEST_DONE) == 0
+                   || (byte & 0x0F) != PRE_TEST_VALUE) {
+                       asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
+                       return ADV_ERROR;
                }
-       }
-       eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
-       eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
-       ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
-                eep_config->chksum);
-       if (chksum != eep_config->chksum) {
-               if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
-                   ASC_CHIP_VER_PCI_ULTRA_3050) {
-                       ASC_DBG(1,
-                               "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
-                       eep_config->init_sdtr = 0xFF;
-                       eep_config->disc_enable = 0xFF;
-                       eep_config->start_motor = 0xFF;
-                       eep_config->use_cmd_qng = 0;
-                       eep_config->max_total_qng = 0xF0;
-                       eep_config->max_tag_qng = 0x20;
-                       eep_config->cntl = 0xBFFF;
-                       ASC_EEP_SET_CHIP_ID(eep_config, 7);
-                       eep_config->no_scam = 0;
-                       eep_config->adapter_info[0] = 0;
-                       eep_config->adapter_info[1] = 0;
-                       eep_config->adapter_info[2] = 0;
-                       eep_config->adapter_info[3] = 0;
-                       eep_config->adapter_info[4] = 0;
-                       /* Indicate EEPROM-less board. */
-                       eep_config->adapter_info[5] = 0xBB;
-               } else {
-                       ASC_PRINT
-                           ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
-                       write_eep = 1;
-                       warn_code |= ASC_WARN_EEPROM_CHKSUM;
+
+               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
+               mdelay(10);     /* Wait for 10ms before reading back. */
+               if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
+                   != NORMAL_VALUE) {
+                       asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
+                       return ADV_ERROR;
                }
        }
-       asc_dvc->cfg->sdtr_enable = 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 = ASC_EEP_GET_DMA_SPD(eep_config);
-       asc_dvc->start_motor = eep_config->start_motor;
-       asc_dvc->dvc_cntl = eep_config->cntl;
-       asc_dvc->no_scam = eep_config->no_scam;
-       asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
-       asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
-       asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
-       asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
-       asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
-       asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
-       if (!AscTestExternalLram(asc_dvc)) {
-               if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
-                    ASC_IS_PCI_ULTRA)) {
-                       eep_config->max_total_qng =
-                           ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
-                       eep_config->max_tag_qng =
-                           ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
-               } else {
-                       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 {
+
+       /*
+        * LRAM Test - It takes about 1.5 ms to run through the test.
+        *
+        * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
+        * If Done bit not set or Status not 0, save register byte, set the
+        * err_code, and return an error.
+        */
+       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
+       mdelay(10);     /* Wait for 10ms before checking status. */
+
+       byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
+       if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
+               /* Get here if Done bit not set or Status not 0. */
+               asc_dvc->bist_err_code = byte;  /* for BIOS display message */
+               asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
+               return ADV_ERROR;
        }
-       if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
-               eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
+
+       /* We need to reset back to normal mode after LRAM test passes. */
+       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
+
+       asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
+                                _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
+                                _adv_asc38C1600_chksum);
+       if (asc_dvc->err_code)
+               return ADV_ERROR;
+
+       /*
+        * Restore the RISC memory BIOS region.
+        */
+       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
+               AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
+                                bios_mem[i]);
        }
-       if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
-               eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
+
+       /*
+        * Calculate and write the microcode code checksum to the microcode
+        * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
+        */
+       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
+       AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
+       code_sum = 0;
+       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
+       for (word = begin_addr; word < end_addr; word += 2) {
+               code_sum += AdvReadWordAutoIncLram(iop_base);
        }
-       if (eep_config->max_tag_qng > eep_config->max_total_qng) {
-               eep_config->max_tag_qng = eep_config->max_total_qng;
+       AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
+
+       /*
+        * Read microcode version and date.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
+                       asc_dvc->cfg->mcode_date);
+       AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
+                       asc_dvc->cfg->mcode_version);
+
+       /*
+        * Set the chip type to indicate the ASC38C1600.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
+
+       /*
+        * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
+        * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
+        * cable detection and then we are able to read C_DET[3:0].
+        *
+        * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
+        * Microcode Default Value' section below.
+        */
+       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+       AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
+                            scsi_cfg1 | DIS_TERM_DRV);
+
+       /*
+        * If the PCI Configuration Command Register "Parity Error Response
+        * Control" Bit was clear (0), then set the microcode variable
+        * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
+        * to ignore DMA parity errors.
+        */
+       if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
+               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+               word |= CONTROL_FLAG_IGNORE_PERR;
+               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+       }
+
+       /*
+        * If the BIOS control flag AIPP (Asynchronous Information
+        * Phase Protection) disable bit is not set, then set the firmware
+        * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
+        * AIPP checking and encoding.
+        */
+       if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
+               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+               word |= CONTROL_FLAG_ENABLE_AIPP;
+               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+       }
+
+       /*
+        * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
+        * and START_CTL_TH [3:2].
+        */
+       AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
+                            FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
+
+       /*
+        * Microcode operating variables for WDTR, SDTR, and command tag
+        * queuing will be set in slave_configure() based on what a
+        * device reports it is capable of in Inquiry byte 7.
+        *
+        * If SCSI Bus Resets have been disabled, then directly set
+        * SDTR and WDTR from the EEPROM configuration. This will allow
+        * the BIOS and warm boot to work without a SCSI bus hang on
+        * the Inquiry caused by host and target mismatched DTR values.
+        * Without the SCSI Bus Reset, before an Inquiry a device can't
+        * be assumed to be in Asynchronous, Narrow mode.
+        */
+       if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
+               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
+                                asc_dvc->wdtr_able);
+               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
+                                asc_dvc->sdtr_able);
        }
-       if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
-               eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
+
+       /*
+        * Set microcode operating variables for DISC and SDTR_SPEED1,
+        * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
+        * configuration values.
+        *
+        * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
+        * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
+        * without determining here whether the device supports SDTR.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
+                        asc_dvc->cfg->disc_enable);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
+
+       /*
+        * Set SCSI_CFG0 Microcode Default Value.
+        *
+        * The microcode will set the SCSI_CFG0 register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
+                        PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
+                        asc_dvc->chip_scsi_id);
+
+       /*
+        * Calculate SCSI_CFG1 Microcode Default Value.
+        *
+        * The microcode will set the SCSI_CFG1 register using this value
+        * after it is started below.
+        *
+        * Each ASC-38C1600 function has only two cable detect bits.
+        * The bus mode override bits are in IOPB_SOFT_OVER_WR.
+        */
+       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+
+       /*
+        * If the cable is reversed all of the SCSI_CTRL register signals
+        * will be set. Check for and return an error if this condition is
+        * found.
+        */
+       if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
+               asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
+               return ADV_ERROR;
        }
-       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;
+
+       /*
+        * Each ASC-38C1600 function has two connectors. Only an HVD device
+        * can not be connected to either connector. An LVD device or SE device
+        * may be connected to either connecor. If an SE device is connected,
+        * then at most Ultra speed (20 Mhz) can be used on both connectors.
+        *
+        * If an HVD device is attached, return an error.
+        */
+       if (scsi_cfg1 & HVD) {
+               asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
+               return ADV_ERROR;
        }
-       if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
-               asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
+
+       /*
+        * Each function in the ASC-38C1600 uses only the SE cable detect and
+        * termination because there are two connectors for each function. Each
+        * function may use either LVD or SE mode. Corresponding the SE automatic
+        * termination control EEPROM bits are used for each function. Each
+        * function has its own EEPROM. If SE automatic control is enabled for
+        * the function, then set the termination value based on a table listed
+        * in a_condor.h.
+        *
+        * If manual termination is specified in the EEPROM for the function,
+        * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
+        * ready to be 'ored' into SCSI_CFG1.
+        */
+       if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
+               struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
+               /* SE automatic termination control is enabled. */
+               switch (scsi_cfg1 & C_DET_SE) {
+                       /* TERM_SE_HI: on, TERM_SE_LO: on */
+               case 0x1:
+               case 0x2:
+               case 0x3:
+                       asc_dvc->cfg->termination |= TERM_SE;
+                       break;
+
+               case 0x0:
+                       if (PCI_FUNC(pdev->devfn) == 0) {
+                               /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
+                       } else {
+                               /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
+                               asc_dvc->cfg->termination |= TERM_SE_HI;
+                       }
+                       break;
+               }
        }
-       ASC_EEP_SET_CHIP_ID(eep_config,
-                           ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
-       asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
-       if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
-           !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
-               asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
+
+       /*
+        * Clear any set TERM_SE bits.
+        */
+       scsi_cfg1 &= ~TERM_SE;
+
+       /*
+        * Invert the TERM_SE bits and then set 'scsi_cfg1'.
+        */
+       scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
+
+       /*
+        * Clear Big Endian and Terminator Polarity bits and set possibly
+        * modified termination control bits in the Microcode SCSI_CFG1
+        * Register Value.
+        *
+        * Big Endian bit is not used even on big endian machines.
+        */
+       scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
+
+       /*
+        * Set SCSI_CFG1 Microcode Default Value
+        *
+        * Set possibly modified termination control bits in the Microcode
+        * SCSI_CFG1 Register Value.
+        *
+        * The microcode will set the SCSI_CFG1 register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
+
+       /*
+        * Set MEM_CFG Microcode Default Value
+        *
+        * The microcode will set the MEM_CFG register using this value
+        * after it is started below.
+        *
+        * MEM_CFG may be accessed as a word or byte, but only bits 0-7
+        * are defined.
+        *
+        * ASC-38C1600 has 32KB internal memory.
+        *
+        * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
+        * out a special 16K Adv Library and Microcode version. After the issue
+        * resolved, we should turn back to the 32K support. Both a_condor.h and
+        * mcode.sas files also need to be updated.
+        *
+        * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
+        *  BIOS_EN | RAM_SZ_32KB);
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
+                        BIOS_EN | RAM_SZ_16KB);
+
+       /*
+        * Set SEL_MASK Microcode Default Value
+        *
+        * The microcode will set the SEL_MASK register using this value
+        * after it is started below.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
+                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
+
+       AdvBuildCarrierFreelist(asc_dvc);
+
+       /*
+        * Set-up the Host->RISC Initiator Command Queue (ICQ).
+        */
+       if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
+               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
+               return ADV_ERROR;
        }
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
 
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
-               asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
-               asc_dvc->cfg->sdtr_period_offset[i] =
-                   (uchar)(ASC_DEF_SDTR_OFFSET |
-                           (asc_dvc->host_init_sdtr_index << 4));
+       /*
+        * The first command issued will be placed in the stopper carrier.
+        */
+       asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+
+       /*
+        * Set RISC ICQ physical address start value. Initialize the
+        * COMMA register to the same value otherwise the RISC will
+        * prematurely detect a command is available.
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
+       AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
+                             le32_to_cpu(asc_dvc->icq_sp->carr_pa));
+
+       /*
+        * Set-up the RISC->Host Initiator Response Queue (IRQ).
+        */
+       if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
+               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
+               return ADV_ERROR;
        }
-       eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
-       if (write_eep) {
-               if ((i =
-                    AscSetEEPConfig(iop_base, eep_config,
-                                    asc_dvc->bus_type)) != 0) {
-                       ASC_PRINT1
-                           ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
-                            i);
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
+
+       /*
+        * The first command completed by the RISC will be placed in
+        * the stopper.
+        *
+        * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
+        * completed the RISC will set the ASC_RQ_STOPPER bit.
+        */
+       asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+
+       /*
+        * Set RISC IRQ physical address start value.
+        */
+       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
+       asc_dvc->carr_pending_cnt = 0;
+
+       AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
+                            (ADV_INTR_ENABLE_HOST_INTR |
+                             ADV_INTR_ENABLE_GLOBAL_INTR));
+       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
+       AdvWriteWordRegister(iop_base, IOPW_PC, word);
+
+       /* finally, finally, gentlemen, start your engine */
+       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
+
+       /*
+        * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
+        * Resets should be performed. The RISC has to be running
+        * to issue a SCSI Bus Reset.
+        */
+       if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
+               /*
+                * If the BIOS Signature is present in memory, restore the
+                * per TID microcode operating variables.
+                */
+               if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
+                   0x55AA) {
+                       /*
+                        * Restore per TID negotiated values.
+                        */
+                       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
+                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
+                                        tagqng_able);
+                       for (tid = 0; tid <= ASC_MAX_TID; tid++) {
+                               AdvWriteByteLram(iop_base,
+                                                ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                                                max_cmd[tid]);
+                       }
                } else {
-                       ASC_PRINT
-                           ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
+                       if (AdvResetSB(asc_dvc) != ADV_TRUE) {
+                               warn_code = ASC_WARN_BUSRESET_ERROR;
+                       }
                }
        }
-       return (warn_code);
+
+       return warn_code;
 }
 
-static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
+/*
+ * Reset chip and SCSI Bus.
+ *
+ * Return Value:
+ *      ADV_TRUE(1) -   Chip re-initialization and SCSI Bus Reset successful.
+ *      ADV_FALSE(0) -  Chip re-initialization and SCSI Bus Reset failure.
+ */
+static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
 {
-       int i;
-       ushort warn_code;
-       PortAddr iop_base;
-       ASC_PADDR phy_addr;
-       ASC_DCNT phy_size;
+       int status;
+       ushort wdtr_able, sdtr_able, tagqng_able;
+       ushort ppr_able = 0;
+       uchar tid, max_cmd[ADV_MAX_TID + 1];
+       AdvPortAddr iop_base;
+       ushort bios_sig;
 
        iop_base = asc_dvc->iop_base;
-       warn_code = 0;
-       for (i = 0; i <= ASC_MAX_TID; i++) {
-               AscPutMCodeInitSDTRAtID(iop_base, i,
-                                       asc_dvc->cfg->sdtr_period_offset[i]
-                   );
+
+       /*
+        * Save current per TID negotiated values.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+       if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
+               AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
+       }
+       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
+       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                               max_cmd[tid]);
        }
 
-       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));
+       /*
+        * Force the AdvInitAsc3550/38C0800Driver() function to
+        * perform a SCSI Bus Reset by clearing the BIOS signature word.
+        * The initialization functions assumes a SCSI Bus Reset is not
+        * needed if the BIOS signature word is present.
+        */
+       AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
+       AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
 
-       /* Align overrun buffer on an 8 byte boundary. */
-       phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
-       phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
-       AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
-                                (uchar *)&phy_addr, 1);
-       phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
-       AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
-                                (uchar *)&phy_size, 1);
+       /*
+        * Stop chip and reset it.
+        */
+       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
+       AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
+       mdelay(100);
+       AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
+                            ADV_CTRL_REG_CMD_WR_IO_REG);
 
-       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);
+       /*
+        * Reset Adv Library error code, if any, and try
+        * re-initializing the chip.
+        */
+       asc_dvc->err_code = 0;
+       if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
+               status = AdvInitAsc38C1600Driver(asc_dvc);
+       } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
+               status = AdvInitAsc38C0800Driver(asc_dvc);
+       } else {
+               status = AdvInitAsc3550Driver(asc_dvc);
+       }
 
-       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);
+       /* Translate initialization return value to status value. */
+       if (status == 0) {
+               status = ADV_TRUE;
+       } else {
+               status = ADV_FALSE;
        }
-       if (AscStartChip(iop_base) != 1) {
-               asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
-               return (warn_code);
+
+       /*
+        * Restore the BIOS signature word.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
+
+       /*
+        * Restore per TID negotiated values.
+        */
+       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+       if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
+               AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
+       }
+       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
+       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+               AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                                max_cmd[tid]);
        }
 
-       return (warn_code);
+       return status;
 }
 
-static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
+/*
+ * adv_async_callback() - Adv Library asynchronous event callback function.
+ */
+static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
 {
-       PortAddr iop_base;
-       ushort q_addr;
-       ushort saved_word;
-       int sta;
+       switch (code) {
+       case ADV_ASYNC_SCSI_BUS_RESET_DET:
+               /*
+                * The firmware detected a SCSI Bus reset.
+                */
+               ASC_DBG(0, "ADV_ASYNC_SCSI_BUS_RESET_DET\n");
+               break;
 
-       iop_base = asc_dvc->iop_base;
-       sta = 0;
-       q_addr = ASC_QNO_TO_QADDR(241);
-       saved_word = AscReadLramWord(iop_base, q_addr);
-       AscSetChipLramAddr(iop_base, q_addr);
-       AscSetChipLramData(iop_base, 0x55AA);
-       DvcSleepMilliSecond(10);
-       AscSetChipLramAddr(iop_base, q_addr);
-       if (AscGetChipLramData(iop_base) == 0x55AA) {
-               sta = 1;
-               AscWriteLramWord(iop_base, q_addr, saved_word);
+       case ADV_ASYNC_RDMA_FAILURE:
+               /*
+                * Handle RDMA failure by resetting the SCSI Bus and
+                * possibly the chip if it is unresponsive. Log the error
+                * with a unique code.
+                */
+               ASC_DBG(0, "ADV_ASYNC_RDMA_FAILURE\n");
+               AdvResetChipAndSB(adv_dvc_varp);
+               break;
+
+       case ADV_HOST_SCSI_BUS_RESET:
+               /*
+                * Host generated SCSI bus reset occurred.
+                */
+               ASC_DBG(0, "ADV_HOST_SCSI_BUS_RESET\n");
+               break;
+
+       default:
+               ASC_DBG(0, "unknown code 0x%x\n", code);
+               break;
        }
-       return (sta);
 }
 
-static int __init AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
+/*
+ * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
+ *
+ * Callback function for the Wide SCSI Adv Library.
+ */
+static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 {
-       uchar read_back;
-       int retry;
+       struct asc_board *boardp;
+       adv_req_t *reqp;
+       adv_sgblk_t *sgblkp;
+       struct scsi_cmnd *scp;
+       struct Scsi_Host *shost;
+       ADV_DCNT resid_cnt;
 
-       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);
-               }
+       ASC_DBG(1, "adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
+                (ulong)adv_dvc_varp, (ulong)scsiqp);
+       ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
+
+       /*
+        * Get the adv_req_t structure for the command that has been
+        * completed. The adv_req_t structure actually contains the
+        * completed ADV_SCSI_REQ_Q structure.
+        */
+       reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
+       ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp);
+       if (reqp == NULL) {
+               ASC_PRINT("adv_isr_callback: reqp is NULL\n");
+               return;
        }
-}
 
-static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
-{
-       ushort read_back;
-       int retry;
+       /*
+        * Get the struct scsi_cmnd structure and Scsi_Host structure for the
+        * command that has been completed.
+        *
+        * Note: The adv_req_t request structure and adv_sgblk_t structure,
+        * if any, are dropped, because a board structure pointer can not be
+        * determined.
+        */
+       scp = reqp->cmndp;
+       ASC_DBG(1, "scp 0x%p\n", scp);
+       if (scp == NULL) {
+               ASC_PRINT
+                   ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
+               return;
+       }
+       ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 
-       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);
+       shost = scp->device->host;
+       ASC_STATS(shost, callback);
+       ASC_DBG(1, "shost 0x%p\n", shost);
+
+       boardp = shost_priv(shost);
+       BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
+
+       /*
+        * 'done_status' contains the command's ending status.
+        */
+       switch (scsiqp->done_status) {
+       case QD_NO_ERROR:
+               ASC_DBG(2, "QD_NO_ERROR\n");
+               scp->result = 0;
+
+               /*
+                * Check for an underrun condition.
+                *
+                * If there was no error and an underrun condition, then
+                * then return the number of underrun bytes.
+                */
+               resid_cnt = le32_to_cpu(scsiqp->data_cnt);
+               if (scsi_bufflen(scp) != 0 && resid_cnt != 0 &&
+                   resid_cnt <= scsi_bufflen(scp)) {
+                       ASC_DBG(1, "underrun condition %lu bytes\n",
+                                (ulong)resid_cnt);
+                       scsi_set_resid(scp, resid_cnt);
                }
-       }
-}
-
-static void __init AscWaitEEPRead(void)
-{
-       DvcSleepMilliSecond(1);
-       return;
-}
+               break;
 
-static void __init AscWaitEEPWrite(void)
-{
-       DvcSleepMilliSecond(20);
-       return;
-}
+       case QD_WITH_ERROR:
+               ASC_DBG(2, "QD_WITH_ERROR\n");
+               switch (scsiqp->host_status) {
+               case QHSTA_NO_ERROR:
+                       if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
+                               ASC_DBG(2, "SAM_STAT_CHECK_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 right shifted status byte definitions.
+                                * For instance target drivers use
+                                * CHECK_CONDITION, defined to 0x1, instead of
+                                * the SCSI defined check condition value of
+                                * 0x2. Host drivers are supposed to return
+                                * the status byte as it is defined by SCSI.
+                                */
+                               scp->result = DRIVER_BYTE(DRIVER_SENSE) |
+                                   STATUS_BYTE(scsiqp->scsi_status);
+                       } else {
+                               scp->result = STATUS_BYTE(scsiqp->scsi_status);
+                       }
+                       break;
 
-static ushort __init AscReadEEPWord(PortAddr iop_base, uchar addr)
-{
-       ushort read_wval;
-       uchar cmd_reg;
+               default:
+                       /* Some other QHSTA error occurred. */
+                       ASC_DBG(1, "host_status 0x%x\n", scsiqp->host_status);
+                       scp->result = HOST_BYTE(DID_BAD_TARGET);
+                       break;
+               }
+               break;
 
-       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);
-}
+       case QD_ABORTED_BY_HOST:
+               ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
+               scp->result =
+                   HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
+               break;
 
-static ushort __init
-AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
-{
-       ushort read_wval;
+       default:
+               ASC_DBG(1, "done_status 0x%x\n", scsiqp->done_status);
+               scp->result =
+                   HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
+               break;
+       }
 
-       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));
+       /*
+        * If the 'init_tidmask' bit isn't already set for the target and the
+        * current request finished normally, then set the bit for the target
+        * to indicate that a device is present.
+        */
+       if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
+           scsiqp->done_status == QD_NO_ERROR &&
+           scsiqp->host_status == QHSTA_NO_ERROR) {
+               boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
        }
-       return (read_wval);
-}
 
-static ushort __init
-AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
-{
-       ushort wval;
-       ushort sum;
-       ushort *wbuf;
-       int cfg_beg;
-       int cfg_end;
-       int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
-       int s_addr;
+       asc_scsi_done(scp);
 
-       wbuf = (ushort *)cfg_buf;
-       sum = 0;
-       /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
-       for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
-               *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
-               sum += *wbuf;
-       }
-       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);
-               if (s_addr <= uchar_end_in_config) {
-                       /*
-                        * Swap all char fields - must unswap bytes already swapped
-                        * by AscReadEEPWord().
-                        */
-                       *wbuf = le16_to_cpu(wval);
-               } else {
-                       /* Don't swap word field at the end - cntl field. */
-                       *wbuf = wval;
-               }
-               sum += wval;    /* Checksum treats all EEPROM data as words. */
+       /*
+        * Free all 'adv_sgblk_t' structures allocated for the request.
+        */
+       while ((sgblkp = reqp->sgblkp) != NULL) {
+               /* Remove 'sgblkp' from the request list. */
+               reqp->sgblkp = sgblkp->next_sgblkp;
+
+               /* Add 'sgblkp' to the board free list. */
+               sgblkp->next_sgblkp = boardp->adv_sgblkp;
+               boardp->adv_sgblkp = sgblkp;
        }
+
        /*
-        * Read the checksum word which will be compared against 'sum'
-        * by the caller. Word field already swapped.
+        * Free the adv_req_t structure used with the command by adding
+        * it back to the board free list.
         */
-       *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
-       return (sum);
+       reqp->next_reqp = boardp->adv_reqp;
+       boardp->adv_reqp = reqp;
+
+       ASC_DBG(1, "done\n");
 }
 
-static int __init
-AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+/*
+ * Adv Library Interrupt Service Routine
+ *
+ *  This function is called by a driver's interrupt service routine.
+ *  The function disables and re-enables interrupts.
+ *
+ *  When a microcode idle command is completed, the ADV_DVC_VAR
+ *  'idle_cmd_done' field is set to ADV_TRUE.
+ *
+ *  Note: AdvISR() can be called when interrupts are disabled or even
+ *  when there is no hardware interrupt condition present. It will
+ *  always check for completed idle commands and microcode requests.
+ *  This is an important feature that shouldn't be changed because it
+ *  allows commands to be completed from polling mode loops.
+ *
+ * Return:
+ *   ADV_TRUE(1) - interrupt was pending
+ *   ADV_FALSE(0) - no interrupt was pending
+ */
+static int AdvISR(ADV_DVC_VAR *asc_dvc)
 {
-       int n_error;
-       ushort *wbuf;
-       ushort word;
-       ushort sum;
-       int s_addr;
-       int cfg_beg;
-       int cfg_end;
-       int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
+       AdvPortAddr iop_base;
+       uchar int_stat;
+       ushort target_bit;
+       ADV_CARR_T *free_carrp;
+       ADV_VADDR irq_next_vpa;
+       ADV_SCSI_REQ_Q *scsiq;
 
-       wbuf = (ushort *)cfg_buf;
-       n_error = 0;
-       sum = 0;
-       /* Write two config words; AscWriteEEPWord() will swap bytes. */
-       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++) {
-               if (s_addr <= uchar_end_in_config) {
-                       /*
-                        * This is a char field. Swap char fields before they are
-                        * swapped again by AscWriteEEPWord().
-                        */
-                       word = cpu_to_le16(*wbuf);
-                       if (word !=
-                           AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
-                               n_error++;
-                       }
-               } else {
-                       /* Don't swap word field at the end - cntl field. */
-                       if (*wbuf !=
-                           AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
-                               n_error++;
-                       }
-               }
-               sum += *wbuf;   /* Checksum calculated from word values. */
-       }
-       /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
-       *wbuf = sum;
-       if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
-               n_error++;
+       iop_base = asc_dvc->iop_base;
+
+       /* Reading the register clears the interrupt. */
+       int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
+
+       if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
+                        ADV_INTR_STATUS_INTRC)) == 0) {
+               return ADV_FALSE;
        }
 
-       /* Read EEPROM back again. */
-       wbuf = (ushort *)cfg_buf;
        /*
-        * Read two config words; Byte-swapping done by AscReadEEPWord().
+        * Notify the driver of an asynchronous microcode condition by
+        * calling the adv_async_callback function. The function
+        * is passed the microcode ASC_MC_INTRB_CODE byte value.
         */
-       for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
-               if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
-                       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++) {
-               if (s_addr <= uchar_end_in_config) {
-                       /*
-                        * Swap all char fields. Must unswap bytes already swapped
-                        * by AscReadEEPWord().
-                        */
-                       word =
-                           le16_to_cpu(AscReadEEPWord
-                                       (iop_base, (uchar)s_addr));
-               } else {
-                       /* Don't swap word field at the end - cntl field. */
-                       word = AscReadEEPWord(iop_base, (uchar)s_addr);
+       if (int_stat & ADV_INTR_STATUS_INTRB) {
+               uchar intrb_code;
+
+               AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
+
+               if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
+                   asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
+                       if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
+                           asc_dvc->carr_pending_cnt != 0) {
+                               AdvWriteByteRegister(iop_base, IOPB_TICKLE,
+                                                    ADV_TICKLE_A);
+                               if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
+                                       AdvWriteByteRegister(iop_base,
+                                                            IOPB_TICKLE,
+                                                            ADV_TICKLE_NOP);
+                               }
+                       }
                }
-               if (*wbuf != word) {
-                       n_error++;
+
+               adv_async_callback(asc_dvc, intrb_code);
+       }
+
+       /*
+        * Check if the IRQ stopper carrier contains a completed request.
+        */
+       while (((irq_next_vpa =
+                le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
+               /*
+                * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
+                * The RISC will have set 'areq_vpa' to a virtual address.
+                *
+                * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
+                * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
+                * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
+                * in AdvExeScsiQueue().
+                */
+               scsiq = (ADV_SCSI_REQ_Q *)
+                   ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
+
+               /*
+                * Request finished with good status and the queue was not
+                * DMAed to host memory by the firmware. Set all status fields
+                * to indicate good status.
+                */
+               if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
+                       scsiq->done_status = QD_NO_ERROR;
+                       scsiq->host_status = scsiq->scsi_status = 0;
+                       scsiq->data_cnt = 0L;
                }
+
+               /*
+                * Advance the stopper pointer to the next carrier
+                * ignoring the lower four bits. Free the previous
+                * stopper carrier.
+                */
+               free_carrp = asc_dvc->irq_sp;
+               asc_dvc->irq_sp = (ADV_CARR_T *)
+                   ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
+
+               free_carrp->next_vpa =
+                   cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
+               asc_dvc->carr_freelist = free_carrp;
+               asc_dvc->carr_pending_cnt--;
+
+               target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
+
+               /*
+                * Clear request microcode control flag.
+                */
+               scsiq->cntl = 0;
+
+               /*
+                * Notify the driver of the completed request by passing
+                * the ADV_SCSI_REQ_Q pointer to its callback function.
+                */
+               scsiq->a_flag |= ADV_SCSIQ_DONE;
+               adv_isr_callback(asc_dvc, scsiq);
+               /*
+                * Note: After the driver callback function is called, 'scsiq'
+                * can no longer be referenced.
+                *
+                * Fall through and continue processing other completed
+                * requests...
+                */
        }
-       /* Read checksum; Byte swapping not needed. */
-       if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
-               n_error++;
+       return ADV_TRUE;
+}
+
+static int AscSetLibErrorCode(ASC_DVC_VAR *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 (n_error);
+       return err_code;
 }
 
-static int __init
-AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static void AscAckInterrupt(PortAddr iop_base)
 {
-       int retry;
-       int n_error;
+       uchar host_flag;
+       uchar risc_flag;
+       ushort loop;
 
-       retry = 0;
-       while (TRUE) {
-               if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
-                                                  bus_type)) == 0) {
+       loop = 0;
+       do {
+               risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
+               if (loop++ > 0x7FFF) {
                        break;
                }
-               if (++retry > ASC_EEP_MAX_RETRY) {
+       } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
+       host_flag =
+           AscReadLramByte(iop_base,
+                           ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
+       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;
                }
        }
-       return (n_error);
+       AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
 }
 
-static void
-AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq)
+static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
 {
-       uchar dvc_type;
-       ASC_SCSI_BIT_ID_TYPE tid_bits;
-
-       dvc_type = ASC_INQ_DVC_TYPE(inq);
-       tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
-
-       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
-               if (!(asc_dvc->init_sdtr & tid_bits)) {
-                       if ((dvc_type == TYPE_ROM) &&
-                           (AscCompareString((uchar *)inq->vendor_id,
-                                             (uchar *)"HP ", 3) == 0)) {
-                               asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
-                       }
-                       asc_dvc->pci_fix_asyn_xfer |= tid_bits;
-                       if ((dvc_type == TYPE_PROCESSOR) ||
-                           (dvc_type == TYPE_SCANNER) ||
-                           (dvc_type == TYPE_ROM) || (dvc_type == TYPE_TAPE)) {
-                               asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                       }
+       const uchar *period_table;
+       int max_index;
+       int min_index;
+       int i;
 
-                       if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
-                               AscSetRunChipSynRegAtID(asc_dvc->iop_base,
-                                                       tid_no,
-                                                       ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+       period_table = asc_dvc->sdtr_period_tbl;
+       max_index = (int)asc_dvc->max_sdtr_index;
+       min_index = (int)asc_dvc->min_sdtr_index;
+       if ((syn_time <= period_table[max_index])) {
+               for (i = min_index; i < (max_index - 1); i++) {
+                       if (syn_time <= period_table[i]) {
+                               return (uchar)i;
                        }
                }
+               return (uchar)max_index;
+       } else {
+               return (uchar)(max_index + 1);
        }
-       return;
 }
 
-static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
+static uchar
+AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
 {
-       if ((inq->add_len >= 32) &&
-           (AscCompareString((uchar *)inq->vendor_id,
-                             (uchar *)"QUANTUM XP34301", 15) == 0) &&
-           (AscCompareString((uchar *)inq->product_rev_level,
-                             (uchar *)"1071", 4) == 0)) {
+       EXT_MSG sdtr_buf;
+       uchar sdtr_period_index;
+       PortAddr iop_base;
+
+       iop_base = asc_dvc->iop_base;
+       sdtr_buf.msg_type = EXTENDED_MESSAGE;
+       sdtr_buf.msg_len = MS_SDTR_LEN;
+       sdtr_buf.msg_req = EXTENDED_SDTR;
+       sdtr_buf.xfer_period = sdtr_period;
+       sdtr_offset &= ASC_SYN_MAX_OFFSET;
+       sdtr_buf.req_ack_offset = sdtr_offset;
+       sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
+       if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
+               AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
+                                       (uchar *)&sdtr_buf,
+                                       sizeof(EXT_MSG) >> 1);
+               return ((sdtr_period_index << 4) | sdtr_offset);
+       } else {
+               sdtr_buf.req_ack_offset = 0;
+               AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
+                                       (uchar *)&sdtr_buf,
+                                       sizeof(EXT_MSG) >> 1);
                return 0;
        }
-       return 1;
 }
 
-static void
-AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq)
+static uchar
+AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
 {
-       ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
-       ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
+       uchar byte;
+       uchar sdtr_period_ix;
 
-       orig_init_sdtr = asc_dvc->init_sdtr;
-       orig_use_tagged_qng = asc_dvc->use_tagged_qng;
+       sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
+       if (sdtr_period_ix > asc_dvc->max_sdtr_index)
+               return 0xFF;
+       byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
+       return byte;
+}
 
-       asc_dvc->init_sdtr &= ~tid_bit;
-       asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
-       asc_dvc->use_tagged_qng &= ~tid_bit;
+static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
+{
+       ASC_SCSI_BIT_ID_TYPE org_id;
+       int i;
+       int sta = TRUE;
 
-       if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) {
-               if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) {
-                       asc_dvc->init_sdtr |= tid_bit;
-               }
-               if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) &&
-                   ASC_INQ_CMD_QUEUE(inq)) {
-                       if (AscTagQueuingSafe(inq)) {
-                               asc_dvc->use_tagged_qng |= tid_bit;
-                               asc_dvc->cfg->can_tagged_qng |= tid_bit;
-                       }
+       AscSetBank(iop_base, 1);
+       org_id = AscReadChipDvcID(iop_base);
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if (org_id == (0x01 << i))
+                       break;
+       }
+       org_id = (ASC_SCSI_BIT_ID_TYPE) i;
+       AscWriteChipDvcID(iop_base, id);
+       if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
+               AscSetBank(iop_base, 0);
+               AscSetChipSyn(iop_base, sdtr_data);
+               if (AscGetChipSyn(iop_base) != sdtr_data) {
+                       sta = FALSE;
                }
+       } else {
+               sta = FALSE;
        }
-       if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
-               AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
-                                asc_dvc->cfg->disc_enable);
-               AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
-                                asc_dvc->use_tagged_qng);
-               AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
-                                asc_dvc->cfg->can_tagged_qng);
+       AscSetBank(iop_base, 1);
+       AscWriteChipDvcID(iop_base, org_id);
+       AscSetBank(iop_base, 0);
+       return (sta);
+}
 
-               asc_dvc->max_dvc_qng[tid_no] =
-                   asc_dvc->cfg->max_tag_qng[tid_no];
-               AscWriteLramByte(asc_dvc->iop_base,
-                                (ushort)(ASCV_MAX_DVC_QNG_BEG + tid_no),
-                                asc_dvc->max_dvc_qng[tid_no]);
-       }
-       if (orig_init_sdtr != asc_dvc->init_sdtr) {
-               AscAsyncFix(asc_dvc, tid_no, inq);
-       }
-       return;
+static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
+{
+       AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
+       AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
 }
 
-static int AscCompareString(uchar *str1, uchar *str2, int len)
+static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
 {
-       int i;
-       int diff;
+       EXT_MSG ext_msg;
+       EXT_MSG 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;
+       struct asc_board *boardp;
+
+       BUG_ON(!asc_dvc->drv_ptr);
+       boardp = asc_dvc->drv_ptr;
+
+       iop_base = asc_dvc->iop_base;
+       int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
 
-       for (i = 0; i < len; i++) {
-               diff = (int)(str1[i] - str2[i]);
-               if (diff != 0)
-                       return (diff);
+       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;
        }
-       return (0);
-}
+       if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
+               if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+                       AscSetChipSDTR(iop_base, 0, tid_no);
+                       boardp->sdtr_data[tid_no] = 0;
+               }
+               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+               return (0);
+       } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
+               if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+                       AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+                       boardp->sdtr_data[tid_no] = asyn_sdtr;
+               }
+               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+               return (0);
+       } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
+               AscMemWordCopyPtrFromLram(iop_base,
+                                         ASCV_MSGIN_BEG,
+                                         (uchar *)&ext_msg,
+                                         sizeof(EXT_MSG) >> 1);
+
+               if (ext_msg.msg_type == EXTENDED_MESSAGE &&
+                   ext_msg.msg_req == EXTENDED_SDTR &&
+                   ext_msg.msg_len == MS_SDTR_LEN) {
+                       sdtr_accept = TRUE;
+                       if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
 
-static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
-{
-       uchar byte_data;
-       ushort word_data;
+                               sdtr_accept = FALSE;
+                               ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
+                       }
+                       if ((ext_msg.xfer_period <
+                            asc_dvc->sdtr_period_tbl[asc_dvc->min_sdtr_index])
+                           || (ext_msg.xfer_period >
+                               asc_dvc->sdtr_period_tbl[asc_dvc->
+                                                        max_sdtr_index])) {
+                               sdtr_accept = FALSE;
+                               ext_msg.xfer_period =
+                                   asc_dvc->sdtr_period_tbl[asc_dvc->
+                                                            min_sdtr_index];
+                       }
+                       if (sdtr_accept) {
+                               sdtr_data =
+                                   AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
+                                                  ext_msg.req_ack_offset);
+                               if ((sdtr_data == 0xFF)) {
 
-       if (isodd_word(addr)) {
-               AscSetChipLramAddr(iop_base, addr - 1);
-               word_data = AscGetChipLramData(iop_base);
-               byte_data = (uchar)((word_data >> 8) & 0xFF);
-       } else {
-               AscSetChipLramAddr(iop_base, addr);
-               word_data = AscGetChipLramData(iop_base);
-               byte_data = (uchar)(word_data & 0xFF);
-       }
-       return (byte_data);
-}
+                                       q_cntl |= QC_MSG_OUT;
+                                       asc_dvc->init_sdtr &= ~target_id;
+                                       asc_dvc->sdtr_done &= ~target_id;
+                                       AscSetChipSDTR(iop_base, asyn_sdtr,
+                                                      tid_no);
+                                       boardp->sdtr_data[tid_no] = asyn_sdtr;
+                               }
+                       }
+                       if (ext_msg.req_ack_offset == 0) {
 
-static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
-{
-       ushort word_data;
+                               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;
+                                       sdtr_data =
+                                           AscCalSDTRData(asc_dvc,
+                                                          ext_msg.xfer_period,
+                                                          ext_msg.
+                                                          req_ack_offset);
+                                       AscSetChipSDTR(iop_base, sdtr_data,
+                                                      tid_no);
+                                       boardp->sdtr_data[tid_no] = sdtr_data;
+                               } else {
+                                       q_cntl |= QC_MSG_OUT;
+                                       AscMsgOutSDTR(asc_dvc,
+                                                     ext_msg.xfer_period,
+                                                     ext_msg.req_ack_offset);
+                                       asc_dvc->pci_fix_asyn_xfer &=
+                                           ~target_id;
+                                       sdtr_data =
+                                           AscCalSDTRData(asc_dvc,
+                                                          ext_msg.xfer_period,
+                                                          ext_msg.
+                                                          req_ack_offset);
+                                       AscSetChipSDTR(iop_base, sdtr_data,
+                                                      tid_no);
+                                       boardp->sdtr_data[tid_no] = sdtr_data;
+                                       asc_dvc->sdtr_done |= target_id;
+                                       asc_dvc->init_sdtr |= target_id;
+                               }
+                       }
 
-       AscSetChipLramAddr(iop_base, addr);
-       word_data = AscGetChipLramData(iop_base);
-       return (word_data);
-}
+                       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 (ext_msg.msg_type == EXTENDED_MESSAGE &&
+                          ext_msg.msg_req == EXTENDED_WDTR &&
+                          ext_msg.msg_len == MS_WDTR_LEN) {
 
-#if CC_VERY_LONG_SG_LIST
-static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
-{
-       ushort val_low, val_high;
-       ASC_DCNT dword_data;
+                       ext_msg.wdtr_width = 0;
+                       AscMemWordCopyPtrToLram(iop_base,
+                                               ASCV_MSGOUT_BEG,
+                                               (uchar *)&ext_msg,
+                                               sizeof(EXT_MSG) >> 1);
+                       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 {
 
-       AscSetChipLramAddr(iop_base, addr);
-       val_low = AscGetChipLramData(iop_base);
-       val_high = AscGetChipLramData(iop_base);
-       dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
-       return (dword_data);
-}
-#endif /* CC_VERY_LONG_SG_LIST */
+                       ext_msg.msg_type = MESSAGE_REJECT;
+                       AscMemWordCopyPtrToLram(iop_base,
+                                               ASCV_MSGOUT_BEG,
+                                               (uchar *)&ext_msg,
+                                               sizeof(EXT_MSG) >> 1);
+                       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_CHK_CONDITION) {
 
-static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
-{
-       AscSetChipLramAddr(iop_base, addr);
-       AscSetChipLramData(iop_base, word_val);
-       return;
-}
+               q_cntl |= QC_REQ_SENSE;
 
-static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
-{
-       ushort word_data;
+               if ((asc_dvc->init_sdtr & target_id) != 0) {
 
-       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;
-}
+                       asc_dvc->sdtr_done &= ~target_id;
 
-/*
- * Copy 2 bytes to LRAM.
- *
- * The source data is assumed to be in little-endian order in memory
- * and is maintained in little-endian order when written to LRAM.
- */
-static void
-AscMemWordCopyPtrToLram(PortAddr iop_base,
-                       ushort s_addr, uchar *s_buffer, int words)
-{
-       int i;
+                       sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
+                       q_cntl |= QC_MSG_OUT;
+                       AscMsgOutSDTR(asc_dvc,
+                                     asc_dvc->
+                                     sdtr_period_tbl[(sdtr_data >> 4) &
+                                                     (uchar)(asc_dvc->
+                                                             max_sdtr_index -
+                                                             1)],
+                                     (uchar)(sdtr_data & (uchar)
+                                             ASC_SYN_MAX_OFFSET));
+               }
 
-       AscSetChipLramAddr(iop_base, s_addr);
-       for (i = 0; i < 2 * words; i += 2) {
-               /*
-                * On a little-endian system the second argument below
-                * produces a little-endian ushort which is written to
-                * LRAM in little-endian order. On a big-endian system
-                * the second argument produces a big-endian ushort which
-                * is "transparently" byte-swapped by outpw() and written
-                * in little-endian order to LRAM.
-                */
-               outpw(iop_base + IOP_RAM_DATA,
-                     ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
-       }
-       return;
-}
+               AscWriteLramByte(iop_base,
+                                (ushort)(halt_q_addr +
+                                         (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
 
-/*
- * Copy 4 bytes to LRAM.
- *
- * The source data is assumed to be in little-endian order in memory
- * and is maintained in little-endian order when writen to LRAM.
- */
-static void
-AscMemDWordCopyPtrToLram(PortAddr iop_base,
-                        ushort s_addr, uchar *s_buffer, int dwords)
-{
-       int i;
+               tag_code = AscReadLramByte(iop_base,
+                                          (ushort)(halt_q_addr + (ushort)
+                                                   ASC_SCSIQ_B_TAG_CODE));
+               tag_code &= 0xDC;
+               if ((asc_dvc->pci_fix_asyn_xfer & target_id)
+                   && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
+                   ) {
 
-       AscSetChipLramAddr(iop_base, s_addr);
-       for (i = 0; i < 4 * dwords; i += 4) {
-               outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);   /* LSW */
-               outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]);       /* MSW */
-       }
-       return;
-}
+                       tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
+                                    | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
 
-/*
- * Copy 2 bytes from LRAM.
- *
- * The source data is assumed to be in little-endian order in LRAM
- * and is maintained in little-endian order when written to memory.
- */
-static void
-AscMemWordCopyPtrFromLram(PortAddr iop_base,
-                         ushort s_addr, uchar *d_buffer, int words)
-{
-       int i;
-       ushort word;
+               }
+               AscWriteLramByte(iop_base,
+                                (ushort)(halt_q_addr +
+                                         (ushort)ASC_SCSIQ_B_TAG_CODE),
+                                tag_code);
 
-       AscSetChipLramAddr(iop_base, s_addr);
-       for (i = 0; i < 2 * words; i += 2) {
-               word = inpw(iop_base + IOP_RAM_DATA);
-               d_buffer[i] = word & 0xff;
-               d_buffer[i + 1] = (word >> 8) & 0xff;
-       }
-       return;
-}
+               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);
 
-static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
-{
-       ASC_DCNT sum;
-       int i;
+               scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
+               scsi_busy &= ~target_id;
+               AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
 
-       sum = 0L;
-       for (i = 0; i < words; i++, s_addr += 2) {
-               sum += AscReadLramWord(iop_base, s_addr);
-       }
-       return (sum);
-}
+               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+               return (0);
+       } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
 
-static void
-AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
-{
-       int i;
+               AscMemWordCopyPtrFromLram(iop_base,
+                                         ASCV_MSGOUT_BEG,
+                                         (uchar *)&out_msg,
+                                         sizeof(EXT_MSG) >> 1);
 
-       AscSetChipLramAddr(iop_base, s_addr);
-       for (i = 0; i < words; i++) {
-               AscSetChipLramData(iop_base, set_wval);
-       }
-       return;
-}
+               if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
+                   (out_msg.msg_len == MS_SDTR_LEN) &&
+                   (out_msg.msg_req == EXTENDED_SDTR)) {
 
-/*
- * --- Adv Library Functions
- */
+                       asc_dvc->init_sdtr &= ~target_id;
+                       asc_dvc->sdtr_done &= ~target_id;
+                       AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+                       boardp->sdtr_data[tid_no] = asyn_sdtr;
+               }
+               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) {
 
-/* a_mcode.h */
+               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)) {
 
-/* Microcode buffer is kept after initialization for error recovery. */
-static unsigned char _adv_asc3550_buf[] = {
-       0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
-       0x01, 0x00, 0x48, 0xe4,
-       0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff,
-       0x28, 0x0e, 0x9e, 0xe7,
-       0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7,
-       0x55, 0xf0, 0x01, 0xf6,
-       0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
-       0x00, 0xec, 0x85, 0xf0,
-       0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0,
-       0x86, 0xf0, 0xb4, 0x00,
-       0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00,
-       0xaa, 0x18, 0x02, 0x80,
-       0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
-       0x00, 0x57, 0x01, 0xea,
-       0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80,
-       0x03, 0xe6, 0xb6, 0x00,
-       0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12,
-       0x02, 0x4a, 0xb9, 0x54,
-       0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
-       0x3e, 0x00, 0x80, 0x00,
-       0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
-       0x74, 0x01, 0x76, 0x01,
-       0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13,
-       0x4c, 0x1c, 0xbb, 0x55,
-       0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
-       0x03, 0xf7, 0x06, 0xf7,
-       0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08,
-       0x30, 0x13, 0x64, 0x15,
-       0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c,
-       0x04, 0xea, 0x5d, 0xf0,
-       0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
-       0xcc, 0x00, 0x20, 0x01,
-       0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13,
-       0x40, 0x13, 0x30, 0x1c,
-       0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
-       0x59, 0xf0, 0xa7, 0xf0,
-       0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
-       0xa4, 0x00, 0xb5, 0x00,
-       0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a,
-       0x14, 0x0e, 0x02, 0x10,
-       0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13,
-       0x10, 0x15, 0x14, 0x15,
-       0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
-       0x91, 0x44, 0x0a, 0x45,
-       0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58,
-       0x83, 0x59, 0x05, 0xe6,
-       0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8,
-       0x02, 0xfa, 0x03, 0xfa,
-       0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
-       0x9e, 0x00, 0xa8, 0x00,
-       0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01,
-       0x7a, 0x01, 0xc0, 0x01,
-       0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08,
-       0x69, 0x08, 0xba, 0x08,
-       0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
-       0xf1, 0x10, 0x06, 0x12,
-       0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14,
-       0x8a, 0x15, 0xc6, 0x17,
-       0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
-       0x0e, 0x47, 0x48, 0x47,
-       0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
-       0x14, 0x56, 0x77, 0x57,
-       0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c,
-       0xf0, 0x29, 0x02, 0xfe,
-       0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf,
-       0xfe, 0x80, 0x01, 0xff,
-       0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
-       0x00, 0xfe, 0x57, 0x24,
-       0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09,
-       0x00, 0x00, 0xff, 0x08,
-       0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
-       0xff, 0xff, 0xff, 0x0f,
-       0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
-       0xfe, 0x04, 0xf7, 0xcf,
-       0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67,
-       0x0b, 0x3c, 0x2a, 0xfe,
-       0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0,
-       0xfe, 0xf0, 0x01, 0xfe,
-       0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
-       0x02, 0xfe, 0xd4, 0x0c,
-       0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
-       0x1c, 0x05, 0xfe, 0xa6,
-       0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48,
-       0xf0, 0xfe, 0x86, 0x02,
-       0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
-       0xfe, 0x46, 0xf0, 0xfe,
-       0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
-       0x44, 0x02, 0xfe, 0x44,
-       0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b,
-       0xa0, 0x17, 0x06, 0x18,
-       0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
-       0x1e, 0x1c, 0xfe, 0xe9,
-       0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7,
-       0x0a, 0x6b, 0x01, 0x9e,
-       0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b,
-       0x01, 0x82, 0xfe, 0xbd,
-       0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
-       0x58, 0x1c, 0x17, 0x06,
-       0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21,
-       0xfe, 0x94, 0x02, 0xfe,
-       0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97,
-       0x01, 0xfe, 0x54, 0x0f,
-       0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
-       0x69, 0x10, 0x17, 0x06,
-       0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05,
-       0xf6, 0xc7, 0x01, 0xfe,
-       0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6,
-       0x02, 0x29, 0x0a, 0x40,
-       0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
-       0x58, 0x0a, 0x99, 0x01,
-       0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29,
-       0x2a, 0x46, 0xfe, 0x02,
-       0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc,
-       0x01, 0xfe, 0x07, 0x4b,
-       0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
-       0xfe, 0x56, 0x03, 0xfe,
-       0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10,
-       0xfe, 0x9f, 0xf0, 0xfe,
-       0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48,
-       0x1c, 0xeb, 0x09, 0x04,
-       0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
-       0x01, 0x0e, 0xac, 0x75,
-       0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2,
-       0xfe, 0x82, 0xf0, 0xfe,
-       0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25,
-       0x32, 0x1f, 0xfe, 0xb4,
-       0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
-       0x0a, 0xf0, 0xfe, 0x7a,
-       0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c,
-       0x01, 0x33, 0x8f, 0xfe,
-       0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8,
-       0xf7, 0xfe, 0x48, 0x1c,
-       0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
-       0x0a, 0xca, 0x01, 0x0e,
-       0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14,
-       0x2c, 0x01, 0x33, 0x8f,
-       0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65,
-       0xfe, 0x3c, 0x04, 0x1f,
-       0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
-       0x12, 0x2b, 0xff, 0x02,
-       0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f,
-       0x22, 0x30, 0x2e, 0xd5,
-       0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c,
-       0xfe, 0x4c, 0x54, 0x64,
-       0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
-       0xfe, 0x2a, 0x13, 0x2f,
-       0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
-       0xd3, 0xfa, 0xef, 0x86,
-       0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04,
-       0x1d, 0xfe, 0x1c, 0x12,
-       0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
-       0x70, 0x0c, 0x02, 0x22,
-       0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92,
-       0x01, 0x33, 0x02, 0x29,
-       0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87,
-       0x80, 0xfe, 0x31, 0xe4,
-       0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
-       0xfe, 0x70, 0x12, 0x49,
-       0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe,
-       0x80, 0x05, 0xfe, 0x31,
-       0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00,
-       0x28, 0xfe, 0x42, 0x12,
-       0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
-       0x11, 0xfe, 0xe3, 0x00,
-       0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
-       0x64, 0x05, 0x83, 0x24,
-       0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe,
-       0x09, 0x48, 0x01, 0x08,
-       0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
-       0x86, 0x24, 0x06, 0x12,
-       0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47,
-       0x01, 0xa7, 0x14, 0x92,
-       0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c,
-       0x02, 0x22, 0x05, 0xfe,
-       0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
-       0x47, 0x01, 0xa7, 0x26,
-       0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f,
-       0x01, 0xfe, 0xaa, 0x14,
-       0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00,
-       0x05, 0x50, 0xb4, 0x0c,
-       0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
-       0x13, 0x01, 0xfe, 0x14,
-       0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c,
-       0xff, 0x02, 0x00, 0x57,
-       0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe,
-       0x72, 0x06, 0x49, 0x04,
-       0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
-       0x06, 0x11, 0x9a, 0x01,
-       0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06,
-       0x01, 0xa7, 0xec, 0x72,
-       0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32,
-       0xfe, 0x0a, 0xf0, 0xfe,
-       0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
-       0x8d, 0x81, 0x02, 0x22,
-       0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00,
-       0x01, 0x08, 0x15, 0x00,
-       0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15,
-       0x00, 0x02, 0xfe, 0x32,
-       0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
-       0xfe, 0x1b, 0x00, 0x01,
-       0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
-       0x08, 0x15, 0x06, 0x01,
-       0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe,
-       0x9a, 0x81, 0x4b, 0x1d,
-       0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
-       0x45, 0xfe, 0x32, 0x12,
-       0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0,
-       0xfe, 0x32, 0x07, 0x8d,
-       0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a,
-       0x06, 0x15, 0x19, 0x02,
-       0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
-       0x90, 0x77, 0xfe, 0xca,
-       0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07,
-       0x10, 0xfe, 0x0e, 0x12,
-       0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe,
-       0x83, 0xe7, 0xc4, 0xa1,
-       0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
-       0x40, 0x12, 0x58, 0x01,
-       0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6,
-       0x51, 0x83, 0xfb, 0xfe,
-       0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90,
-       0xfe, 0x40, 0x50, 0xfe,
-       0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
-       0xfe, 0x2a, 0x12, 0xfe,
-       0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f,
-       0x85, 0x01, 0xa8, 0xfe,
-       0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56,
-       0x18, 0x57, 0xfb, 0xfe,
-       0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
-       0x0c, 0x39, 0x18, 0x3a,
-       0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e,
-       0x11, 0x65, 0xfe, 0x48,
-       0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73,
-       0xdd, 0xb8, 0xfe, 0x80,
-       0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
-       0xfe, 0x7a, 0x08, 0x8d,
-       0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9,
-       0x10, 0x61, 0x04, 0x06,
-       0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68,
-       0x12, 0xfe, 0x2e, 0x1c,
-       0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
-       0x52, 0x12, 0xfe, 0x2c,
-       0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe,
-       0x08, 0xfe, 0x8a, 0x10,
-       0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe,
-       0x24, 0x0a, 0xab, 0xfe,
-       0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
-       0x1c, 0x12, 0xb5, 0xfe,
-       0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb,
-       0x1c, 0x06, 0x16, 0x9d,
-       0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b,
-       0x14, 0x92, 0x01, 0x33,
-       0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
-       0xfe, 0x74, 0x18, 0x1c,
-       0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b,
-       0x01, 0xe6, 0x1e, 0x27,
-       0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a,
-       0x09, 0x04, 0x6a, 0xfe,
-       0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
-       0xfe, 0x83, 0x80, 0xfe,
-       0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63,
-       0x27, 0xfe, 0x40, 0x59,
-       0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18,
-       0x7c, 0xbe, 0x54, 0xbf,
-       0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
-       0x79, 0x56, 0x68, 0x57,
-       0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5,
-       0xa2, 0x23, 0x0c, 0x7b,
-       0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19,
-       0x16, 0xd7, 0x79, 0x39,
-       0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
-       0xfe, 0x10, 0x58, 0xfe,
-       0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04,
-       0x19, 0x16, 0xd7, 0x09,
-       0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f,
-       0xfe, 0x10, 0x90, 0xfe,
-       0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
-       0x11, 0x9b, 0x09, 0x04,
-       0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08,
-       0xfe, 0x0c, 0x58, 0xfe,
-       0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04,
-       0x0b, 0xfe, 0x1a, 0x12,
-       0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
-       0x14, 0x7a, 0x01, 0x33,
-       0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39,
-       0xfe, 0xed, 0x19, 0xbf,
-       0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff,
-       0x34, 0xfe, 0x74, 0x10,
-       0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
-       0x84, 0x05, 0xcb, 0x1c,
-       0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1,
-       0xf0, 0xfe, 0xc4, 0x0a,
-       0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe,
-       0xce, 0xf0, 0xfe, 0xca,
-       0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
-       0x22, 0x00, 0x02, 0x5a,
-       0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a,
-       0xfe, 0xd0, 0xf0, 0xfe,
-       0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f,
-       0x4c, 0xfe, 0x10, 0x10,
-       0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
-       0x2a, 0x13, 0xfe, 0x4e,
-       0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1,
-       0x16, 0x32, 0x2a, 0x73,
-       0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25,
-       0x32, 0x8c, 0xfe, 0x48,
-       0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
-       0xdb, 0x10, 0x11, 0xfe,
-       0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0,
-       0x22, 0x30, 0x2e, 0xd8,
-       0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1,
-       0x45, 0x0f, 0xfe, 0x42,
-       0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
-       0x09, 0x04, 0x0b, 0xfe,
-       0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28,
-       0x00, 0x21, 0xfe, 0xa6,
-       0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00,
-       0xfe, 0xe2, 0x10, 0x01,
-       0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
-       0x01, 0x6f, 0x02, 0x29,
-       0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10,
-       0x01, 0x86, 0x3e, 0x0b,
-       0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3,
-       0x3e, 0x0b, 0x0f, 0xfe,
-       0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
-       0xe8, 0x59, 0x11, 0x2d,
-       0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09,
-       0x04, 0x0b, 0x84, 0x3e,
-       0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12,
-       0x09, 0x04, 0x1b, 0xfe,
-       0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
-       0x1c, 0x1c, 0xfe, 0x9d,
-       0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f,
-       0xfe, 0x15, 0x00, 0xfe,
-       0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10,
-       0x0f, 0xfe, 0x47, 0x00,
-       0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
-       0xab, 0x70, 0x05, 0x6b,
-       0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe,
-       0x1c, 0x42, 0x59, 0x01,
-       0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31,
-       0x00, 0x37, 0x97, 0x01,
-       0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
-       0x1d, 0xfe, 0xce, 0x45,
-       0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75,
-       0x57, 0x05, 0x51, 0xfe,
-       0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48,
-       0x46, 0x09, 0x04, 0x1d,
-       0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
-       0x99, 0x01, 0x0e, 0xfe,
-       0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51,
-       0xfe, 0xee, 0x14, 0xee,
-       0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad,
-       0x13, 0x02, 0x29, 0x1e,
-       0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
-       0xce, 0x1e, 0x2d, 0x47,
-       0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06,
-       0x12, 0x4d, 0x01, 0xfe,
-       0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe,
-       0xf0, 0x0d, 0xfe, 0x02,
-       0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
-       0xf6, 0xfe, 0x34, 0x01,
-       0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13,
-       0xaf, 0xfe, 0x02, 0xea,
-       0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c,
-       0x05, 0xfe, 0x38, 0x01,
-       0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
-       0x0c, 0xfe, 0x62, 0x01,
-       0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06,
-       0x03, 0x23, 0x03, 0x1e,
-       0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe,
-       0x71, 0x13, 0xfe, 0x24,
-       0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
-       0xdc, 0xfe, 0x73, 0x57,
-       0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe,
-       0x80, 0x5d, 0x03, 0xfe,
-       0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6,
-       0x75, 0x03, 0x09, 0x04,
-       0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
-       0xfe, 0x1e, 0x80, 0xe1,
-       0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e,
-       0x90, 0xa3, 0xfe, 0x3c,
-       0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82,
-       0x16, 0x2f, 0x07, 0x2d,
-       0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
-       0xe8, 0x11, 0xfe, 0xe9,
-       0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe,
-       0x1e, 0x1c, 0xfe, 0x14,
-       0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01,
-       0x09, 0x04, 0x4f, 0xfe,
-       0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
-       0x40, 0x12, 0x20, 0x63,
-       0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08,
-       0x1c, 0x05, 0xfe, 0xac,
-       0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05,
-       0xfe, 0xb0, 0x00, 0xfe,
-       0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
-       0x24, 0x69, 0x12, 0xc9,
-       0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe,
-       0x90, 0x4d, 0xfe, 0x91,
-       0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c,
-       0xfe, 0x90, 0x4d, 0xfe,
-       0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
-       0x46, 0x1e, 0x20, 0xed,
-       0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea,
-       0x70, 0xfe, 0x14, 0x1c,
-       0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee,
-       0xfe, 0x07, 0xe6, 0x1d,
-       0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
-       0xfa, 0xef, 0xfe, 0x42,
-       0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0,
-       0xfe, 0x36, 0x12, 0xf0,
-       0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
-       0x3d, 0x75, 0x07, 0x10,
-       0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
-       0x10, 0x07, 0x7e, 0x45,
-       0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74,
-       0xfe, 0x01, 0xec, 0x97,
-       0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76,
-       0x27, 0x01, 0xda, 0xfe,
-       0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
-       0xfe, 0x48, 0x12, 0x07,
-       0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16,
-       0xfe, 0x3e, 0x11, 0x07,
-       0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8,
-       0x11, 0x07, 0x19, 0xfe,
-       0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
-       0x01, 0x08, 0x8c, 0x43,
-       0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11,
-       0x7e, 0x02, 0x29, 0x2b,
-       0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe,
-       0xfc, 0x10, 0x09, 0x04,
-       0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
-       0xc6, 0x10, 0x1e, 0x58,
-       0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c,
-       0x54, 0x18, 0x55, 0x23,
-       0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01,
-       0xa5, 0xc0, 0x38, 0xc1,
-       0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
-       0x05, 0xfa, 0x4e, 0xfe,
-       0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56,
-       0x0c, 0x56, 0x18, 0x57,
-       0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe,
-       0x00, 0x56, 0xfe, 0xa1,
-       0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
-       0x58, 0xfe, 0x1f, 0x40,
-       0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56,
-       0x31, 0x57, 0xfe, 0x44,
-       0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe,
-       0x8a, 0x50, 0x05, 0x39,
-       0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
-       0x12, 0xcd, 0x02, 0x5b,
-       0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44,
-       0x2f, 0x07, 0x9b, 0x21,
-       0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79,
-       0x39, 0x68, 0x3a, 0xfe,
-       0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
-       0x51, 0xfe, 0x8e, 0x51,
-       0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b,
-       0x01, 0x08, 0x25, 0x32,
-       0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b,
-       0x3b, 0x02, 0x44, 0x01,
-       0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
-       0x01, 0x08, 0x1f, 0xa2,
-       0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c,
-       0x00, 0x28, 0x84, 0x49,
-       0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06,
-       0x78, 0x3d, 0xfe, 0xda,
-       0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
-       0x05, 0xc6, 0x28, 0x84,
-       0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8,
-       0x14, 0xfe, 0x03, 0x17,
-       0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01,
-       0xfe, 0xaa, 0x14, 0x02,
-       0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
-       0x21, 0x44, 0x01, 0xfe,
-       0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87,
-       0xfe, 0x4a, 0xf4, 0x0b,
-       0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a,
-       0x85, 0x02, 0x5b, 0x05,
-       0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
-       0xd8, 0x14, 0x02, 0x5c,
-       0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1,
-       0x01, 0x08, 0x23, 0x72,
-       0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca,
-       0x12, 0x5e, 0x2b, 0x01,
-       0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
-       0x1c, 0xfe, 0xff, 0x7f,
-       0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00,
-       0x57, 0x48, 0x8b, 0x1c,
-       0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02,
-       0x00, 0x57, 0x48, 0x8b,
-       0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
-       0x03, 0x0a, 0x50, 0x01,
-       0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00,
-       0x54, 0xfe, 0x00, 0xf4,
-       0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe,
-       0x03, 0x7c, 0x63, 0x27,
-       0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
-       0xfe, 0x82, 0x4a, 0xfe,
-       0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe,
-       0x42, 0x48, 0x5f, 0x60,
-       0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08,
-       0x1f, 0xfe, 0xa2, 0x14,
-       0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
-       0xcc, 0x12, 0x49, 0x04,
-       0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe,
-       0xe8, 0x13, 0x3b, 0x13,
-       0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55,
-       0xa1, 0xff, 0x02, 0x83,
-       0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
-       0x13, 0x06, 0xfe, 0x56,
-       0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe,
-       0x64, 0x00, 0x17, 0x93,
-       0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe,
-       0xc8, 0x00, 0x8e, 0xe4,
-       0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
-       0x01, 0xba, 0xfe, 0x4e,
-       0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0,
-       0xfe, 0x60, 0x14, 0xfe,
-       0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01,
-       0xfe, 0x22, 0x13, 0x1c,
-       0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
-       0xfe, 0x9c, 0x14, 0xb7,
-       0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba,
-       0xfe, 0x9c, 0x14, 0xb7,
-       0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06,
-       0xfe, 0xb4, 0x56, 0xfe,
-       0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
-       0xe5, 0x15, 0x0b, 0x01,
-       0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89,
-       0x49, 0x01, 0x08, 0x03,
-       0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6,
-       0x15, 0x06, 0x01, 0x08,
-       0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
-       0x4a, 0x01, 0x08, 0x03,
-       0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc,
-       0xfe, 0x49, 0xf4, 0x00,
-       0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01,
-       0x08, 0x2f, 0x07, 0xfe,
-       0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
-       0x01, 0x43, 0x1e, 0xcd,
-       0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e,
-       0xed, 0x88, 0x07, 0x10,
-       0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a,
-       0x80, 0x01, 0x0e, 0x88,
-       0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
-       0x88, 0x03, 0x0a, 0x42,
-       0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e,
-       0xfe, 0x80, 0x80, 0xf2,
-       0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51,
-       0x01, 0x82, 0x03, 0x17,
-       0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
-       0xfe, 0x24, 0x1c, 0xfe,
-       0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0,
-       0x91, 0x1d, 0x66, 0xfe,
-       0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe,
-       0xda, 0x10, 0x17, 0x10,
-       0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
-       0x05, 0xfe, 0x66, 0x01,
-       0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06,
-       0xfe, 0x3c, 0x50, 0x66,
-       0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe,
-       0x40, 0x16, 0xfe, 0xb6,
-       0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
-       0x10, 0x71, 0xfe, 0x83,
-       0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90,
-       0xfe, 0x62, 0x16, 0xfe,
-       0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19,
-       0xfe, 0x98, 0xe7, 0x00,
-       0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
-       0xfe, 0x30, 0xbc, 0xfe,
-       0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
-       0xc5, 0x90, 0xfe, 0x9a,
-       0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe,
-       0x42, 0x10, 0xfe, 0x02,
-       0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
-       0xfe, 0x1d, 0xf7, 0x4f,
-       0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f,
-       0x47, 0xfe, 0x83, 0x58,
-       0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11,
-       0xfe, 0xdd, 0x00, 0x63,
-       0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
-       0x06, 0x37, 0x95, 0xa9,
-       0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e,
-       0x18, 0x1c, 0x1a, 0x5d,
-       0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe,
-       0xe1, 0x10, 0x78, 0x2c,
-       0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
-       0x13, 0x3c, 0x8a, 0x0a,
-       0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
-       0xe3, 0xfe, 0x00, 0xcc,
-       0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01,
-       0x0e, 0xf2, 0x01, 0x6f,
-       0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
-       0xf6, 0xfe, 0xd6, 0xf0,
-       0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe,
-       0x15, 0x00, 0x59, 0x76,
-       0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35,
-       0x11, 0x2d, 0x01, 0x6f,
-       0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
-       0xc8, 0xfe, 0x48, 0x55,
-       0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a,
-       0x99, 0x01, 0x0e, 0xf0,
-       0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73,
-       0x75, 0x03, 0x0a, 0x42,
-       0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
-       0x0e, 0x73, 0x75, 0x03,
-       0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00,
-       0xfe, 0x3a, 0x45, 0x5b,
-       0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00,
-       0xfe, 0x02, 0xe6, 0x1b,
-       0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
-       0xfe, 0x94, 0x00, 0xfe,
-       0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02,
-       0xe6, 0x2c, 0xfe, 0x4e,
-       0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69,
-       0x03, 0x07, 0x7a, 0xfe,
-       0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
-       0x07, 0x1b, 0xfe, 0x5a,
-       0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d,
-       0x24, 0x2c, 0xdc, 0x07,
-       0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d,
-       0x9f, 0xad, 0x03, 0x14,
-       0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
-       0x03, 0x25, 0xfe, 0xca,
-       0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a,
-       0x00, 0x00,
-};
+                       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;
 
-static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf);    /* 0x13AD */
-static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL;    /* Expanded little-endian checksum. */
+                       if (scsi_status == SAM_STAT_TASK_SET_FULL) {
+                               if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
+                                       cur_dvc_qng -= 1;
+                                       asc_dvc->max_dvc_qng[tid_no] =
+                                           cur_dvc_qng;
 
-/* Microcode buffer is kept after initialization for error recovery. */
-static unsigned char _adv_asc38C0800_buf[] = {
-       0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
-       0x01, 0x00, 0x48, 0xe4,
-       0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff,
-       0x1c, 0x0f, 0x00, 0xf6,
-       0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6,
-       0x09, 0xe7, 0x55, 0xf0,
-       0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
-       0x18, 0xf4, 0x08, 0x00,
-       0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6,
-       0x86, 0xf0, 0xb1, 0xf0,
-       0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c,
-       0x3c, 0x00, 0xbb, 0x00,
-       0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
-       0xba, 0x13, 0x18, 0x40,
-       0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01,
-       0x6e, 0x01, 0x74, 0x01,
-       0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00,
-       0xc0, 0x00, 0x01, 0x01,
-       0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
-       0x08, 0x12, 0x02, 0x4a,
-       0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4,
-       0x5d, 0xf0, 0x02, 0xfa,
-       0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01,
-       0x68, 0x01, 0x6a, 0x01,
-       0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
-       0x06, 0x13, 0x4c, 0x1c,
-       0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00,
-       0x0f, 0x00, 0x47, 0x00,
-       0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c,
-       0x4e, 0x1c, 0x10, 0x44,
-       0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
-       0x05, 0x00, 0x34, 0x00,
-       0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b,
-       0x42, 0x0c, 0x12, 0x0f,
-       0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48,
-       0x00, 0x4e, 0x42, 0x54,
-       0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
-       0x59, 0xf0, 0xb8, 0xf0,
-       0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00,
-       0x19, 0x00, 0x33, 0x00,
-       0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00,
-       0xe7, 0x00, 0xe2, 0x03,
-       0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
-       0x12, 0x13, 0x24, 0x14,
-       0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c,
-       0x36, 0x1c, 0x08, 0x44,
-       0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54,
-       0x3a, 0x55, 0x83, 0x55,
-       0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
-       0x0c, 0xf0, 0x04, 0xf8,
-       0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00,
-       0xa8, 0x00, 0xaa, 0x00,
-       0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01,
-       0xc4, 0x01, 0xc6, 0x01,
-       0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
-       0x68, 0x08, 0x69, 0x08,
-       0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10,
-       0xed, 0x10, 0xf1, 0x10,
-       0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13,
-       0x1e, 0x13, 0x46, 0x14,
-       0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
-       0xca, 0x18, 0xe6, 0x19,
-       0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c,
-       0xf0, 0x2b, 0x02, 0xfe,
-       0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6,
-       0xfe, 0x84, 0x01, 0xff,
-       0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
-       0x00, 0xfe, 0x57, 0x24,
-       0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09,
-       0x00, 0x00, 0xff, 0x08,
-       0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
-       0xff, 0xff, 0xff, 0x11,
-       0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
-       0xfe, 0x04, 0xf7, 0xd6,
-       0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99,
-       0x0a, 0x42, 0x2c, 0xfe,
-       0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0,
-       0xfe, 0xf4, 0x01, 0xfe,
-       0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
-       0x02, 0xfe, 0xc8, 0x0d,
-       0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28,
-       0x1c, 0x03, 0xfe, 0xa6,
-       0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48,
-       0xf0, 0xfe, 0x8a, 0x02,
-       0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
-       0xfe, 0x46, 0xf0, 0xfe,
-       0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe,
-       0x48, 0x02, 0xfe, 0x44,
-       0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a,
-       0xaa, 0x18, 0x06, 0x14,
-       0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
-       0x1e, 0x1c, 0xfe, 0xe9,
-       0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce,
-       0x09, 0x70, 0x01, 0xa8,
-       0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70,
-       0x01, 0x87, 0xfe, 0xbd,
-       0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
-       0x58, 0x1c, 0x18, 0x06,
-       0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23,
-       0xfe, 0x98, 0x02, 0xfe,
-       0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2,
-       0x01, 0xfe, 0x48, 0x10,
-       0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
-       0x69, 0x10, 0x18, 0x06,
-       0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05,
-       0xf6, 0xce, 0x01, 0xfe,
-       0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe,
-       0x82, 0x16, 0x02, 0x2b,
-       0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
-       0xfe, 0x41, 0x58, 0x09,
-       0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe,
-       0x82, 0x16, 0x02, 0x2b,
-       0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43,
-       0xfe, 0x77, 0x57, 0xfe,
-       0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
-       0xfe, 0x40, 0x1c, 0x1c,
-       0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48,
-       0x03, 0xfe, 0x11, 0xf0,
-       0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10,
-       0xfe, 0x11, 0x00, 0x02,
-       0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
-       0x21, 0x22, 0xa3, 0xb7,
-       0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16,
-       0x12, 0xd1, 0x1c, 0xd9,
-       0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12,
-       0xfe, 0xe4, 0x00, 0x27,
-       0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
-       0x06, 0xf0, 0xfe, 0xc8,
-       0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03,
-       0x70, 0x28, 0x17, 0xfe,
-       0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8,
-       0xf9, 0x2c, 0x99, 0x19,
-       0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
-       0x74, 0x01, 0xaf, 0x8c,
-       0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e,
-       0x8d, 0x51, 0x64, 0x79,
-       0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b,
-       0xfe, 0x6a, 0x02, 0x02,
-       0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
-       0xfe, 0x3c, 0x04, 0x3b,
-       0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02,
-       0x00, 0x10, 0x01, 0x0b,
-       0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde,
-       0xfe, 0x4c, 0x44, 0xfe,
-       0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
-       0xda, 0x4f, 0x79, 0x2a,
-       0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b,
-       0xfe, 0x2a, 0x13, 0x32,
-       0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c,
-       0x54, 0x6b, 0xda, 0xfe,
-       0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
-       0x08, 0x13, 0x32, 0x07,
-       0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d,
-       0x08, 0x05, 0x06, 0x4d,
-       0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24,
-       0x2d, 0x12, 0xfe, 0xe6,
-       0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
-       0x02, 0x2b, 0xfe, 0x42,
-       0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
-       0xfe, 0x87, 0x80, 0xfe,
-       0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80,
-       0x07, 0x19, 0xfe, 0x7c,
-       0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
-       0x17, 0xfe, 0x90, 0x05,
-       0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe,
-       0xa0, 0x00, 0x28, 0xfe,
-       0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c,
-       0x34, 0xfe, 0x89, 0x48,
-       0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
-       0x12, 0xfe, 0xe3, 0x00,
-       0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe,
-       0x70, 0x05, 0x88, 0x25,
-       0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe,
-       0x09, 0x48, 0xff, 0x02,
-       0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
-       0x08, 0x53, 0x05, 0xcb,
-       0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08,
-       0x05, 0x1b, 0xfe, 0x22,
-       0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe,
-       0x0d, 0x00, 0x01, 0x36,
-       0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
-       0x03, 0x5c, 0x28, 0xfe,
-       0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53,
-       0x05, 0x1f, 0xfe, 0x02,
-       0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5,
-       0x01, 0x4b, 0x12, 0xfe,
-       0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
-       0x12, 0x03, 0x45, 0x28,
-       0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe,
-       0x43, 0x48, 0xc4, 0xcc,
-       0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4,
-       0x6e, 0x41, 0x01, 0xb2,
-       0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
-       0xfe, 0xcc, 0x15, 0x1d,
-       0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03,
-       0x45, 0xc1, 0x0c, 0x45,
-       0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe,
-       0xe2, 0x00, 0x27, 0xdb,
-       0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
-       0xfe, 0x06, 0xf0, 0xfe,
-       0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12,
-       0x16, 0x19, 0x01, 0x0b,
-       0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
-       0xfe, 0x99, 0xa4, 0x01,
-       0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
-       0x12, 0x08, 0x05, 0x1a,
-       0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
-       0x0b, 0x16, 0x00, 0x01,
-       0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02,
-       0xe2, 0x6c, 0x58, 0xbe,
-       0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
-       0xfe, 0x09, 0x6f, 0xba,
-       0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27,
-       0xfe, 0x54, 0x07, 0x1c,
-       0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c,
-       0x07, 0x02, 0x24, 0x01,
-       0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
-       0x2c, 0x90, 0xfe, 0xae,
-       0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a,
-       0x37, 0x22, 0x20, 0x07,
-       0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a,
-       0xfe, 0x06, 0x10, 0xfe,
-       0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
-       0x37, 0x01, 0xb3, 0xb8,
-       0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a,
-       0x50, 0xfe, 0x44, 0x51,
-       0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e,
-       0x14, 0x5f, 0xfe, 0x0c,
-       0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
-       0x14, 0x3e, 0xfe, 0x4a,
-       0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
-       0x90, 0x0c, 0x60, 0x14,
-       0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62,
-       0xfe, 0x44, 0x90, 0xfe,
-       0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
-       0x0c, 0x5e, 0x14, 0x5f,
-       0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e,
-       0x14, 0x3c, 0x21, 0x0c,
-       0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11,
-       0x27, 0xdd, 0xfe, 0x9e,
-       0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
-       0x9a, 0x08, 0xc6, 0xfe,
-       0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08,
-       0x95, 0x86, 0x02, 0x24,
-       0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05,
-       0x06, 0xfe, 0x10, 0x12,
-       0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
-       0x1c, 0x02, 0xfe, 0x18,
-       0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe,
-       0x2c, 0x1c, 0xfe, 0xaa,
-       0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe,
-       0xde, 0x09, 0xfe, 0xb7,
-       0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
-       0xfe, 0xf1, 0x18, 0xfe,
-       0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe,
-       0x14, 0x59, 0xfe, 0x95,
-       0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0,
-       0xfe, 0xf0, 0x08, 0xb5,
-       0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
-       0x0b, 0xb6, 0xfe, 0xbf,
-       0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c,
-       0x12, 0xc2, 0xfe, 0xd2,
-       0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e,
-       0x06, 0x17, 0x85, 0xc5,
-       0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
-       0x9d, 0x01, 0x36, 0x10,
-       0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe,
-       0x98, 0x80, 0xfe, 0x19,
-       0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18,
-       0xfe, 0x44, 0x54, 0xbe,
-       0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
-       0x02, 0x4a, 0x08, 0x05,
-       0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e,
-       0x9c, 0x3c, 0xfe, 0x6c,
-       0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f,
-       0x3b, 0x40, 0x03, 0x49,
-       0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
-       0x8f, 0xfe, 0xe3, 0x54,
-       0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe,
-       0xda, 0x09, 0xfe, 0x8b,
-       0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa,
-       0x0a, 0x3a, 0x49, 0x3b,
-       0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
-       0xad, 0xfe, 0x01, 0x59,
-       0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a,
-       0x49, 0x8f, 0xfe, 0xe3,
-       0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02,
-       0x4a, 0x3a, 0x49, 0x3b,
-       0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
-       0x02, 0x4a, 0x08, 0x05,
-       0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62,
-       0xb7, 0xfe, 0x03, 0xa1,
-       0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
-       0xfe, 0x86, 0x91, 0x6a,
-       0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
-       0x61, 0x0c, 0x7f, 0x14,
-       0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62,
-       0x9b, 0x2e, 0x9c, 0x3c,
-       0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05,
-       0xfa, 0x3c, 0x01, 0xef,
-       0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
-       0xe4, 0x08, 0x05, 0x1f,
-       0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37,
-       0x03, 0x5e, 0x29, 0x5f,
-       0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe,
-       0xf4, 0x09, 0x08, 0x05,
-       0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
-       0x81, 0x50, 0xfe, 0x10,
-       0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe,
-       0x08, 0x09, 0x12, 0xa6,
-       0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe,
-       0x08, 0x09, 0xfe, 0x0c,
-       0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
-       0x08, 0x05, 0x0a, 0xfe,
-       0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1,
-       0xf0, 0xe2, 0x15, 0x7e,
-       0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19,
-       0x57, 0x3d, 0xfe, 0xed,
-       0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
-       0x00, 0xff, 0x35, 0xfe,
-       0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18,
-       0x1e, 0x19, 0x8a, 0x03,
-       0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65,
-       0xfe, 0xd1, 0xf0, 0xfe,
-       0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
-       0x10, 0xfe, 0xce, 0xf0,
-       0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b,
-       0x10, 0xfe, 0x22, 0x00,
-       0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00,
-       0x02, 0x65, 0xfe, 0xd0,
-       0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
-       0x0b, 0x10, 0x58, 0xfe,
-       0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe,
-       0x12, 0x00, 0x2c, 0x0f,
-       0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14,
-       0x0c, 0xbc, 0x17, 0x34,
-       0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
-       0x0c, 0x1c, 0x34, 0x94,
-       0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01,
-       0x4b, 0xfe, 0xdb, 0x10,
-       0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe,
-       0x89, 0xf0, 0x24, 0x33,
-       0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
-       0x33, 0x31, 0xdf, 0xbc,
-       0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49,
-       0x17, 0xfe, 0x2c, 0x0d,
-       0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54,
-       0x12, 0x55, 0xfe, 0x28,
-       0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
-       0x44, 0xfe, 0x28, 0x00,
-       0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26,
-       0x0f, 0x64, 0x12, 0x2f,
-       0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44,
-       0x0a, 0xfe, 0xb4, 0x10,
-       0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
-       0xfe, 0x34, 0x46, 0xac,
-       0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a,
-       0x37, 0x01, 0xf5, 0x01,
-       0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02,
-       0xfe, 0x2e, 0x03, 0x08,
-       0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
-       0x1a, 0xfe, 0x58, 0x12,
-       0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
-       0xfe, 0x50, 0x0d, 0xfe,
-       0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37,
-       0xfe, 0xa9, 0x10, 0x10,
-       0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
-       0xfe, 0x13, 0x00, 0xfe,
-       0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe,
-       0x24, 0x00, 0x8c, 0xb5,
-       0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a,
-       0xfe, 0x9d, 0x41, 0xfe,
-       0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
-       0xb4, 0x15, 0xfe, 0x31,
-       0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06,
-       0xec, 0xd0, 0xfc, 0x44,
-       0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47,
-       0x4b, 0x91, 0xfe, 0x75,
-       0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
-       0x0e, 0xfe, 0x44, 0x48,
-       0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41,
-       0xfe, 0x41, 0x58, 0x09,
-       0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe,
-       0x2e, 0x03, 0x09, 0x5d,
-       0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
-       0xce, 0x47, 0xfe, 0xad,
-       0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13,
-       0x59, 0x13, 0x9f, 0x13,
-       0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe,
-       0xe0, 0x0e, 0x0f, 0x06,
-       0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
-       0x3a, 0x01, 0x56, 0xfe,
-       0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec,
-       0x20, 0x4f, 0xfe, 0x05,
-       0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe,
-       0x48, 0xf4, 0x0d, 0xfe,
-       0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
-       0x15, 0x1a, 0x39, 0xa0,
-       0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff,
-       0x0c, 0xfe, 0x60, 0x01,
-       0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25,
-       0x06, 0x13, 0x2f, 0x12,
-       0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
-       0x22, 0x9f, 0xb7, 0x13,
-       0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39,
-       0xa0, 0xb4, 0xfe, 0xd9,
-       0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04,
-       0xc3, 0xfe, 0x03, 0xdc,
-       0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
-       0xfe, 0x00, 0xcc, 0x04,
-       0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13,
-       0xfe, 0x1c, 0x80, 0x07,
-       0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae,
-       0xfe, 0x0c, 0x90, 0xfe,
-       0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
-       0x0a, 0xfe, 0x3c, 0x50,
-       0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4,
-       0x16, 0x08, 0x05, 0x1b,
-       0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58,
-       0xfe, 0x2c, 0x13, 0x01,
-       0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
-       0x0c, 0xfe, 0x64, 0x01,
-       0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03,
-       0x80, 0x8d, 0xfe, 0x01,
-       0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64,
-       0x22, 0x20, 0xfb, 0x79,
-       0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
-       0x03, 0xfe, 0xae, 0x00,
+                                       AscWriteLramByte(iop_base,
+                                                        (ushort)((ushort)
+                                                                 ASCV_MAX_DVC_QNG_BEG
+                                                                 + (ushort)
+                                                                 tid_no),
+                                                        cur_dvc_qng);
+
+                                       /*
+                                        * Set the device queue depth to the
+                                        * number of active requests when the
+                                        * QUEUE FULL condition was encountered.
+                                        */
+                                       boardp->queue_full |= target_id;
+                                       boardp->queue_full_cnt[tid_no] =
+                                           cur_dvc_qng;
+                               }
+                       }
+               }
+               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+               return (0);
+       }
+#if CC_VERY_LONG_SG_LIST
+       else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
+               uchar q_no;
+               ushort q_addr;
+               uchar sg_wk_q_no;
+               uchar first_sg_wk_q_no;
+               ASC_SCSI_Q *scsiq;      /* Ptr to driver request. */
+               ASC_SG_HEAD *sg_head;   /* Ptr to driver SG request. */
+               ASC_SG_LIST_Q scsi_sg_q;        /* Structure written to queue. */
+               ushort sg_list_dwords;
+               ushort sg_entry_cnt;
+               uchar next_qp;
+               int i;
 
-       0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe,
-       0xb2, 0x00, 0xfe, 0x09,
-       0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c,
-       0x45, 0x0f, 0x46, 0x52,
-       0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
-       0x0f, 0x44, 0x11, 0x0f,
-       0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4,
-       0x25, 0x11, 0x13, 0x20,
-       0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14,
-       0x56, 0xfe, 0xd6, 0xf0,
-       0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
-       0x18, 0x1c, 0x04, 0x42,
-       0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe,
-       0xf5, 0x13, 0x04, 0x01,
-       0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
-       0x13, 0x32, 0x07, 0x2f,
-       0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
-       0x41, 0x48, 0xfe, 0x45,
-       0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78,
-       0x07, 0x11, 0xac, 0x09,
-       0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07,
-       0x82, 0x4e, 0xfe, 0x14,
-       0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
-       0xfe, 0x01, 0xec, 0xa2,
-       0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79,
-       0x2a, 0x01, 0xe3, 0xfe,
-       0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a,
-       0xfe, 0x48, 0x12, 0x07,
-       0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
-       0xfe, 0x32, 0x12, 0x07,
-       0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07,
-       0x1f, 0xfe, 0x12, 0x12,
-       0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b,
-       0x94, 0x4b, 0x04, 0x2d,
-       0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
-       0x32, 0x07, 0xa6, 0xfe,
-       0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05,
-       0x5a, 0xfe, 0x72, 0x12,
-       0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62,
-       0xfe, 0x26, 0x13, 0x03,
-       0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
-       0x0c, 0x7f, 0x0c, 0x80,
-       0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c,
-       0x3c, 0xfe, 0x04, 0x55,
-       0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe,
-       0x91, 0x10, 0x03, 0x3f,
-       0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
-       0x88, 0x9b, 0x2e, 0x9c,
-       0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
-       0x56, 0x0c, 0x5e, 0x14,
-       0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40,
-       0x03, 0x60, 0x29, 0x61,
-       0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
-       0x50, 0xfe, 0xc6, 0x50,
-       0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d,
-       0x29, 0x3e, 0xfe, 0x40,
-       0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72,
-       0x2d, 0x01, 0x0b, 0x1d,
-       0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
-       0x72, 0x01, 0xaf, 0x1e,
-       0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe,
-       0x0a, 0x55, 0x35, 0xfe,
-       0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51,
-       0x02, 0x72, 0xfe, 0x19,
-       0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
-       0x1d, 0xe8, 0x33, 0x31,
-       0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01,
-       0x0b, 0x1c, 0x34, 0x1d,
-       0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8,
-       0x33, 0x31, 0xfe, 0xe8,
-       0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
-       0x05, 0x1f, 0x35, 0xa9,
-       0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda,
-       0x14, 0x01, 0xaf, 0x8c,
-       0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a,
-       0x03, 0x45, 0x28, 0x35,
-       0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
-       0x03, 0x5c, 0xc1, 0x0c,
-       0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02,
-       0x89, 0x01, 0x0b, 0x1c,
-       0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1,
-       0xfe, 0x42, 0x58, 0xf1,
-       0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
-       0xf4, 0x06, 0xea, 0x32,
-       0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d,
-       0x01, 0x0b, 0x26, 0x89,
-       0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13,
-       0x26, 0xfe, 0xd4, 0x13,
-       0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
-       0x13, 0x1c, 0xfe, 0xd0,
-       0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10,
-       0x0f, 0x71, 0xff, 0x02,
-       0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe,
-       0x00, 0x5c, 0x04, 0x0f,
-       0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
-       0xfe, 0x00, 0x5c, 0x04,
-       0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff,
-       0x02, 0x00, 0x57, 0x52,
-       0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01,
-       0x87, 0x04, 0xfe, 0x03,
-       0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
-       0xfe, 0x00, 0x7d, 0xfe,
-       0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e,
-       0x14, 0x5f, 0x57, 0x3f,
-       0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83,
-       0x5a, 0x8d, 0x04, 0x01,
-       0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
-       0xfe, 0x96, 0x15, 0x33,
-       0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8,
-       0x0a, 0xfe, 0xc1, 0x59,
-       0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13,
-       0x21, 0x69, 0x1a, 0xee,
-       0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
-       0x30, 0xfe, 0x78, 0x10,
-       0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae,
-       0x98, 0xfe, 0x30, 0x00,
-       0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed,
-       0x98, 0xfe, 0x64, 0x00,
-       0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
-       0x10, 0x69, 0x06, 0xfe,
-       0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00,
-       0x18, 0x59, 0x0f, 0x06,
-       0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe,
-       0x43, 0xf4, 0x9f, 0xfe,
-       0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
-       0x9e, 0xfe, 0xf3, 0x10,
-       0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00,
-       0x17, 0xfe, 0x4d, 0xe4,
-       0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00,
-       0x17, 0xfe, 0x4d, 0xe4,
-       0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
-       0xf4, 0x00, 0xe9, 0x91,
-       0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a,
-       0x04, 0x16, 0x06, 0x01,
-       0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01,
-       0x0b, 0x26, 0xf3, 0x76,
-       0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
-       0x16, 0x19, 0x01, 0x0b,
-       0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01,
-       0x0b, 0x26, 0xb1, 0x76,
-       0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06,
-       0xfe, 0x48, 0x13, 0xb8,
-       0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
-       0xec, 0xfe, 0x27, 0x01,
-       0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32,
-       0x07, 0xfe, 0xe3, 0x00,
-       0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b,
-       0x22, 0xd4, 0x07, 0x06,
-       0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
-       0x07, 0x11, 0xae, 0x09,
-       0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01,
-       0x0e, 0x8e, 0xfe, 0x80,
-       0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04,
-       0x09, 0x48, 0x01, 0x0e,
-       0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
-       0x80, 0xfe, 0x80, 0x4c,
-       0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c,
-       0x09, 0x5d, 0x01, 0x87,
-       0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe,
-       0x19, 0xde, 0xfe, 0x24,
-       0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
-       0x17, 0xad, 0x9a, 0x1b,
-       0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde,
-       0x16, 0xfe, 0xda, 0x10,
-       0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe,
-       0x18, 0x58, 0x03, 0xfe,
-       0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
-       0xf4, 0x06, 0xfe, 0x3c,
-       0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f,
-       0x97, 0xfe, 0x38, 0x17,
-       0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c,
-       0x10, 0x18, 0x11, 0x75,
-       0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
-       0x2e, 0x97, 0xfe, 0x5a,
-       0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19,
-       0xfe, 0x98, 0xe7, 0x00,
-       0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75,
-       0xfe, 0x30, 0xbc, 0xfe,
-       0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
-       0xcb, 0x97, 0xfe, 0x92,
-       0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe,
-       0x42, 0x10, 0xfe, 0x02,
-       0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe,
-       0x03, 0xa1, 0xfe, 0x1d,
-       0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
-       0x9a, 0x5b, 0x41, 0xfe,
-       0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7,
-       0x11, 0x12, 0xfe, 0xdd,
-       0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8,
-       0x17, 0x15, 0x06, 0x39,
-       0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
-       0xfe, 0x7e, 0x18, 0x1e,
-       0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef,
-       0x12, 0xfe, 0xe1, 0x10,
-       0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42,
-       0x13, 0x42, 0x92, 0x09,
-       0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
-       0xf0, 0xfe, 0x00, 0xcc,
-       0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01,
-       0x0e, 0xfe, 0x80, 0x4c,
-       0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe,
-       0x24, 0x12, 0xfe, 0x14,
-       0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
-       0xe7, 0x0a, 0x10, 0xfe,
-       0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92,
-       0x08, 0x54, 0x1b, 0x37,
-       0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba,
-       0x90, 0x3a, 0xce, 0x3b,
-       0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
-       0x13, 0xa3, 0x04, 0x09,
-       0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49,
-       0x44, 0x17, 0xfe, 0xe8,
-       0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09,
-       0x5d, 0x01, 0xa8, 0x09,
-       0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
-       0x1c, 0x19, 0x03, 0xfe,
-       0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9,
-       0x6b, 0xfe, 0x2e, 0x19,
-       0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4,
-       0xfe, 0x0b, 0x00, 0x6b,
-       0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
-       0x08, 0x10, 0x03, 0xfe,
-       0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff,
-       0x04, 0x68, 0x54, 0xe7,
-       0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe,
-       0x1a, 0xf4, 0xfe, 0x00,
-       0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
-       0x04, 0x07, 0x7e, 0xfe,
-       0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
-       0x07, 0x1a, 0xfe, 0x5a,
-       0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66,
-       0x25, 0x6d, 0xe5, 0x07,
-       0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
-       0xa9, 0xb8, 0x04, 0x15,
-       0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe,
-       0x40, 0x5c, 0x04, 0x1c,
-       0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b,
-       0xf7, 0xfe, 0x82, 0xf0,
-       0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
-};
+               q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
+               if (q_no == ASC_QLINK_END)
+                       return 0;
 
-static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf);      /* 0x14E1 */
-static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
+               q_addr = ASC_QNO_TO_QADDR(q_no);
 
-/* Microcode buffer is kept after initialization for error recovery. */
-static unsigned char _adv_asc38C1600_buf[] = {
-       0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
-       0x18, 0xe4, 0x01, 0x00,
-       0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00,
-       0x07, 0x17, 0xc0, 0x5f,
-       0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7,
-       0x85, 0xf0, 0x86, 0xf0,
-       0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
-       0x98, 0x57, 0x01, 0xe6,
-       0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d,
-       0x38, 0x54, 0x32, 0xf0,
-       0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4,
-       0x00, 0xe6, 0xb1, 0xf0,
-       0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
-       0x06, 0x13, 0x0c, 0x1c,
-       0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12,
-       0xb9, 0x54, 0x00, 0x80,
-       0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56,
-       0x03, 0xe6, 0x01, 0xea,
-       0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
-       0x04, 0x13, 0xbb, 0x55,
-       0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00,
-       0xbb, 0x00, 0xc0, 0x00,
-       0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12,
-       0x4c, 0x1c, 0x4e, 0x1c,
-       0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
-       0x24, 0x01, 0x3c, 0x01,
-       0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01,
-       0x78, 0x01, 0x7c, 0x01,
-       0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c,
-       0x6e, 0x1e, 0x02, 0x48,
-       0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
-       0x03, 0xfc, 0x06, 0x00,
-       0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a,
-       0x30, 0x1c, 0x38, 0x1c,
-       0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea,
-       0x5d, 0xf0, 0xa7, 0xf0,
-       0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
-       0x33, 0x00, 0x34, 0x00,
-       0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01,
-       0x79, 0x01, 0x3c, 0x09,
-       0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13,
-       0x40, 0x16, 0x50, 0x16,
-       0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
-       0x05, 0xf0, 0x09, 0xf0,
-       0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00,
-       0x9c, 0x00, 0xa4, 0x00,
-       0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08,
-       0xe9, 0x09, 0x5c, 0x0c,
-       0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
-       0x42, 0x1d, 0x08, 0x44,
-       0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54,
-       0x83, 0x55, 0x83, 0x59,
-       0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0,
-       0x4b, 0xf4, 0x04, 0xf8,
-       0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
-       0xa8, 0x00, 0xaa, 0x00,
-       0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01,
-       0x7a, 0x01, 0x82, 0x01,
-       0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07,
-       0x68, 0x08, 0x10, 0x0d,
-       0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
-       0xf3, 0x10, 0x06, 0x12,
-       0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c,
-       0xf0, 0x35, 0x05, 0xfe,
-       0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8,
-       0xfe, 0x88, 0x01, 0xff,
-       0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
-       0x00, 0xfe, 0x57, 0x24,
-       0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09,
-       0x00, 0x00, 0xff, 0x08,
-       0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10,
-       0xff, 0xff, 0xff, 0x13,
-       0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
-       0xfe, 0x04, 0xf7, 0xe8,
-       0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d,
-       0x0d, 0x51, 0x37, 0xfe,
-       0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0,
-       0xfe, 0xf8, 0x01, 0xfe,
-       0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
-       0x05, 0xfe, 0x08, 0x0f,
-       0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe,
-       0x28, 0x1c, 0x03, 0xfe,
-       0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe,
-       0x48, 0xf0, 0xfe, 0x90,
-       0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
-       0x02, 0xfe, 0x46, 0xf0,
-       0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0,
-       0xfe, 0x4e, 0x02, 0xfe,
-       0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c,
-       0x0d, 0xa2, 0x1c, 0x07,
-       0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
-       0x1c, 0xf5, 0xfe, 0x1e,
-       0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc,
-       0xde, 0x0a, 0x81, 0x01,
-       0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a,
-       0x81, 0x01, 0x5c, 0xfe,
-       0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
-       0xfe, 0x58, 0x1c, 0x1c,
-       0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02,
-       0x2b, 0xfe, 0x9e, 0x02,
-       0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30,
-       0x00, 0x47, 0xb8, 0x01,
-       0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
-       0x1a, 0x31, 0xfe, 0x69,
-       0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe,
-       0x1e, 0x1e, 0x20, 0x2c,
-       0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a,
-       0x44, 0x15, 0x56, 0x51,
-       0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
-       0x01, 0x18, 0x09, 0x00,
-       0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01,
-       0x18, 0xfe, 0xc8, 0x54,
-       0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60,
-       0xfe, 0x02, 0xe8, 0x30,
-       0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
-       0xfe, 0xe4, 0x01, 0xfe,
-       0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe,
-       0x26, 0xf0, 0xfe, 0x66,
-       0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe,
-       0xef, 0x10, 0xfe, 0x9f,
-       0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
-       0x70, 0x37, 0xfe, 0x48,
-       0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26,
-       0x21, 0xb9, 0xc7, 0x20,
-       0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15,
-       0xe1, 0x2a, 0xeb, 0xfe,
-       0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
-       0x15, 0xfe, 0xe4, 0x00,
-       0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41,
-       0xfe, 0x06, 0xf0, 0xfe,
-       0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29,
-       0x03, 0x81, 0x1e, 0x1b,
-       0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
-       0xea, 0xfe, 0x46, 0x1c,
-       0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57,
-       0xfe, 0x48, 0x1c, 0x75,
-       0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a,
-       0xe1, 0x01, 0x18, 0x77,
-       0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
-       0x8f, 0xfe, 0x70, 0x02,
-       0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04,
-       0x16, 0xfe, 0x4a, 0x04,
-       0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff,
-       0x02, 0x00, 0x10, 0x01,
-       0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
-       0xee, 0xfe, 0x4c, 0x44,
-       0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54,
-       0x7b, 0xec, 0x60, 0x8d,
-       0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01,
-       0x0c, 0x06, 0x28, 0xfe,
-       0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
-       0x13, 0x34, 0xfe, 0x4c,
-       0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54,
-       0x13, 0x01, 0x0c, 0x06,
-       0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06,
-       0x28, 0xf9, 0x1f, 0x7f,
-       0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
-       0xfe, 0xa4, 0x0e, 0x05,
-       0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe,
-       0x9c, 0x93, 0x3a, 0x0b,
-       0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b,
-       0x7d, 0x1d, 0xfe, 0x46,
-       0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
-       0xfe, 0x87, 0x83, 0xfe,
-       0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98,
-       0x13, 0x0f, 0xfe, 0x20,
-       0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84,
-       0x12, 0x01, 0x38, 0x06,
-       0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
-       0x05, 0xd0, 0x54, 0x01,
-       0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe,
-       0x50, 0x12, 0x5e, 0xff,
-       0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02,
-       0x00, 0x10, 0x2f, 0xfe,
-       0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
-       0x38, 0xfe, 0x4a, 0xf0,
-       0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe,
-       0x21, 0x00, 0xf1, 0x2e,
-       0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00,
-       0x10, 0x2f, 0xfe, 0xd0,
-       0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
-       0x1c, 0x00, 0x4d, 0x01,
-       0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06,
-       0x28, 0xfe, 0x24, 0x12,
-       0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe,
-       0x0d, 0x00, 0x01, 0x42,
-       0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
-       0x03, 0xb6, 0x1e, 0xfe,
-       0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17,
-       0xfe, 0x72, 0x06, 0x0a,
-       0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56,
-       0x19, 0x16, 0xfe, 0x68,
-       0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
-       0x03, 0x9a, 0x1e, 0xfe,
-       0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12,
-       0x48, 0xfe, 0x92, 0x06,
-       0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13,
-       0x58, 0xff, 0x02, 0x00,
-       0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
-       0xfe, 0xea, 0x06, 0x01,
-       0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16,
-       0xfe, 0xe0, 0x06, 0x15,
-       0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07,
-       0x01, 0x84, 0xfe, 0xae,
-       0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
-       0x1e, 0xfe, 0x1a, 0x12,
-       0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
-       0x43, 0x48, 0x62, 0x80,
-       0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24,
-       0x36, 0xfe, 0x02, 0xf6,
-       0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
-       0xd0, 0x0d, 0x17, 0xfe,
-       0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20,
-       0x9e, 0x15, 0x82, 0x01,
-       0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58,
-       0x57, 0x10, 0xe6, 0x05,
-       0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
-       0xfe, 0x9c, 0x32, 0x5f,
-       0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c,
-       0xfe, 0x0a, 0xf0, 0xfe,
-       0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08,
-       0xaf, 0xa0, 0x05, 0x29,
-       0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
-       0x00, 0x01, 0x08, 0x14,
-       0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08,
-       0x14, 0x00, 0x05, 0xfe,
-       0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06,
-       0x12, 0xfe, 0x30, 0x13,
-       0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
-       0x01, 0x08, 0x14, 0x00,
-       0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a,
-       0x78, 0x4f, 0x0f, 0xfe,
-       0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d,
-       0x28, 0x48, 0xfe, 0x6c,
-       0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
-       0x12, 0x53, 0x63, 0x4e,
-       0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe,
-       0x6c, 0x08, 0xaf, 0xa0,
-       0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24,
-       0x05, 0xed, 0xfe, 0x9c,
-       0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
-       0x1e, 0xfe, 0x99, 0x58,
-       0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a,
-       0x22, 0x6b, 0x01, 0x0c,
-       0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e,
-       0x1e, 0x47, 0x2c, 0x7a,
-       0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
-       0x01, 0x0c, 0x61, 0x65,
-       0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a,
-       0x16, 0xfe, 0x08, 0x50,
-       0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10,
-       0x01, 0xfe, 0xce, 0x1e,
-       0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
-       0x01, 0xfe, 0xfe, 0x1e,
-       0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a,
-       0x10, 0x01, 0x0c, 0x06,
-       0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e,
-       0x10, 0x6a, 0x22, 0x6b,
-       0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
-       0xfe, 0x9f, 0x83, 0x33,
-       0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93,
-       0x3a, 0x0b, 0xfe, 0xc6,
-       0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d,
-       0x01, 0xfe, 0xce, 0x1e,
-       0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
-       0x04, 0xfe, 0xc0, 0x93,
-       0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e,
-       0x10, 0x4b, 0x22, 0x4c,
-       0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe,
-       0x4e, 0x11, 0x2f, 0xfe,
-       0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
-       0x3c, 0x37, 0x88, 0xf5,
-       0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a,
-       0xd3, 0xfe, 0x42, 0x0a,
-       0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0,
-       0x05, 0x29, 0x01, 0x41,
-       0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
-       0xfe, 0x14, 0x12, 0x01,
-       0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe,
-       0x2e, 0x1c, 0x05, 0xfe,
-       0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41,
-       0xfe, 0x2c, 0x1c, 0xfe,
-       0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
-       0x92, 0x10, 0xc4, 0xf6,
-       0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe,
-       0xe7, 0x10, 0xfe, 0x2b,
-       0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12,
-       0xac, 0xfe, 0xd2, 0xf0,
-       0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
-       0x1b, 0xbf, 0xd4, 0x5b,
-       0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75,
-       0x5e, 0x32, 0x1f, 0x7f,
-       0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98,
-       0x05, 0x70, 0xfe, 0x74,
-       0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
-       0x0f, 0x4d, 0x01, 0xfe,
-       0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06,
-       0x0d, 0x2b, 0xfe, 0xe2,
-       0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24,
-       0xfe, 0x88, 0x13, 0x21,
-       0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
-       0x83, 0x83, 0xfe, 0xc9,
-       0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04,
-       0x91, 0x04, 0xfe, 0x84,
-       0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93,
-       0xfe, 0xcb, 0x57, 0x0b,
-       0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
-       0x6a, 0x3b, 0x6b, 0x10,
-       0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30,
-       0x20, 0x6e, 0xdb, 0x64,
-       0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55,
-       0xfe, 0x04, 0xfa, 0x64,
-       0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
-       0x10, 0x98, 0x91, 0x6c,
-       0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91,
-       0x4b, 0x7e, 0x4c, 0x01,
-       0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10,
-       0x58, 0xfe, 0x91, 0x58,
-       0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
-       0x1b, 0x40, 0x01, 0x0c,
-       0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f,
-       0xfe, 0x10, 0x90, 0x04,
-       0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93,
-       0x79, 0x0b, 0x0e, 0xfe,
-       0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
-       0x01, 0x0c, 0x06, 0x0d,
-       0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe,
-       0x0c, 0x58, 0xfe, 0x8d,
-       0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99,
-       0x83, 0x33, 0x0b, 0x0e,
-       0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
-       0x19, 0xfe, 0x19, 0x41,
-       0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42,
-       0x19, 0xfe, 0x44, 0x00,
-       0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda,
-       0x4c, 0xfe, 0x0c, 0x51,
-       0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
-       0x76, 0x10, 0xac, 0xfe,
-       0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03,
-       0xe3, 0x23, 0x07, 0xfe,
-       0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe,
-       0xcc, 0x0c, 0x1f, 0x92,
-       0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
-       0x0c, 0xfe, 0x3e, 0x10,
-       0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70,
-       0xfe, 0xcb, 0xf0, 0xfe,
-       0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe,
-       0xf4, 0x0c, 0x19, 0x94,
-       0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
-       0xfe, 0xcc, 0xf0, 0xef,
-       0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe,
-       0x4e, 0x11, 0x2f, 0xfe,
-       0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b,
-       0x3c, 0x37, 0x88, 0xf5,
-       0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
-       0x2f, 0xfe, 0x3e, 0x0d,
-       0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f,
-       0xd2, 0x9f, 0xd3, 0x9f,
-       0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4,
-       0xc5, 0x75, 0xd7, 0x99,
-       0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
-       0x9c, 0x2f, 0xfe, 0x8c,
-       0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe,
-       0x42, 0x00, 0x05, 0x70,
-       0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06,
-       0x0d, 0xfe, 0x44, 0x13,
-       0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
-       0xfe, 0xda, 0x0e, 0x0a,
-       0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa,
-       0x10, 0x01, 0xfe, 0xf4,
-       0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40,
-       0x15, 0x56, 0x01, 0x85,
-       0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
-       0xcc, 0x10, 0x01, 0xa7,
-       0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04,
-       0xfe, 0x99, 0x83, 0xfe,
-       0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe,
-       0x43, 0x00, 0xfe, 0xa2,
-       0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
-       0x00, 0x1d, 0x40, 0x15,
-       0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05,
-       0xfe, 0x3a, 0x03, 0x01,
-       0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01,
-       0x76, 0x06, 0x12, 0xfe,
-       0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
-       0xfe, 0x9d, 0xf0, 0xfe,
-       0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01,
-       0x0c, 0x61, 0x12, 0x44,
-       0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f,
-       0xfe, 0x2e, 0x10, 0x19,
-       0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
-       0xfe, 0x41, 0x00, 0xa2,
-       0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b,
-       0xea, 0x4f, 0xfe, 0x04,
-       0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05,
-       0x35, 0xfe, 0x12, 0x1c,
-       0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
-       0xfe, 0xd4, 0x11, 0x05,
-       0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe,
-       0xce, 0x45, 0x31, 0x51,
-       0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03,
-       0x67, 0xfe, 0x98, 0x56,
-       0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
-       0x0c, 0x06, 0x28, 0xfe,
-       0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba,
-       0xfe, 0xfa, 0x14, 0xfe,
-       0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67,
-       0xfe, 0xe0, 0x14, 0xfe,
-       0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
-       0xfe, 0xad, 0x13, 0x05,
-       0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20,
-       0xe7, 0xfe, 0x08, 0x1c,
-       0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe,
-       0x48, 0x55, 0xa5, 0x3b,
-       0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
-       0xf0, 0x1a, 0x03, 0xfe,
-       0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02,
-       0xec, 0xe7, 0x53, 0x00,
-       0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
-       0x01, 0xfe, 0x62, 0x1b,
-       0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
-       0xea, 0xe7, 0x53, 0x92,
-       0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03,
-       0xfe, 0x38, 0x01, 0x23,
-       0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62,
-       0x01, 0x01, 0xfe, 0x1e,
-       0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
-       0x26, 0x02, 0x21, 0x96,
-       0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5,
-       0xc3, 0xfe, 0xe1, 0x10,
-       0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf,
-       0xfe, 0x03, 0xdc, 0xfe,
-       0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
-       0x00, 0xcc, 0x02, 0xfe,
-       0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13,
-       0x0f, 0xfe, 0x1c, 0x80,
-       0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13,
-       0x0f, 0xfe, 0x1e, 0x80,
-       0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
-       0x1d, 0x80, 0x04, 0xfe,
-       0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee,
-       0x1e, 0xac, 0xfe, 0x14,
-       0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e,
-       0x1f, 0xfe, 0x30, 0xf4,
-       0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
-       0x56, 0xfb, 0x01, 0xfe,
-       0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01,
-       0xfe, 0x00, 0x1d, 0x15,
-       0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe,
-       0x22, 0x1b, 0xfe, 0x1e,
-       0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
-       0x96, 0x90, 0x04, 0xfe,
-       0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66,
-       0x01, 0x01, 0x0c, 0x06,
-       0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b,
-       0x0e, 0x77, 0xfe, 0x01,
-       0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
-       0x21, 0x2c, 0xfe, 0x00,
-       0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe,
-       0x06, 0x58, 0x03, 0xfe,
-       0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58,
-       0x03, 0xfe, 0xb2, 0x00,
-       0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
-       0x66, 0x10, 0x55, 0x10,
-       0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91,
-       0x54, 0x2b, 0xfe, 0x88,
-       0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe,
-       0x91, 0x54, 0x2b, 0xfe,
-       0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
-       0x00, 0x40, 0x8d, 0x2c,
-       0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe,
-       0x12, 0x1c, 0x75, 0xfe,
-       0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c,
-       0x14, 0xfe, 0x0e, 0x47,
-       0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
-       0xa7, 0x90, 0x34, 0x60,
-       0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80,
-       0x09, 0x56, 0xfe, 0x34,
-       0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48,
-       0xfe, 0x45, 0x48, 0x01,
-       0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
-       0x09, 0x1a, 0xa5, 0x0a,
-       0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4,
-       0xfe, 0x14, 0x56, 0xfe,
-       0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01,
-       0xec, 0xb8, 0xfe, 0x9e,
-       0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
-       0xf4, 0xfe, 0xdd, 0x10,
-       0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48,
-       0x12, 0x09, 0x0d, 0xfe,
-       0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4,
-       0x13, 0x09, 0xfe, 0x23,
-       0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
-       0x24, 0xfe, 0x12, 0x12,
-       0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08,
-       0xae, 0x41, 0x02, 0x32,
-       0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05,
-       0x35, 0x32, 0x01, 0x43,
-       0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
-       0x13, 0x01, 0x0c, 0x06,
-       0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe,
-       0xe5, 0x55, 0xb0, 0xfe,
-       0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e,
-       0xfe, 0xb6, 0x0e, 0x10,
-       0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
-       0x88, 0x20, 0x6e, 0x01,
-       0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5,
-       0x55, 0xfe, 0x04, 0xfa,
-       0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d,
-       0xfe, 0x40, 0x56, 0xfe,
-       0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
-       0x44, 0x55, 0xfe, 0xe5,
-       0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10,
-       0x68, 0x22, 0x69, 0x01,
-       0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b,
-       0x6b, 0xfe, 0x2c, 0x50,
-       0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
-       0x50, 0x03, 0x68, 0x3b,
-       0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe,
-       0x40, 0x50, 0xfe, 0xc2,
-       0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08,
-       0x16, 0x3d, 0x27, 0x25,
-       0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
-       0xa6, 0x23, 0x3f, 0x1b,
-       0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c,
-       0xfe, 0x0a, 0x55, 0x31,
-       0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e,
-       0x51, 0x05, 0x72, 0x01,
-       0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
-       0x2a, 0x3c, 0x16, 0xc0,
-       0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b,
-       0xfe, 0x66, 0x15, 0x05,
-       0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d,
-       0x2b, 0x3d, 0x01, 0x08,
-       0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
-       0xb6, 0x1e, 0x83, 0x01,
-       0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46,
-       0x07, 0x90, 0x3f, 0x01,
-       0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13,
-       0x01, 0x43, 0x09, 0x82,
-       0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
-       0x05, 0x72, 0xfe, 0xc0,
-       0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e,
-       0x32, 0x01, 0x08, 0x17,
-       0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16,
-       0x3d, 0x27, 0x25, 0xbd,
-       0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
-       0xe8, 0x14, 0x01, 0xa6,
-       0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe,
-       0x0e, 0x12, 0x01, 0x43,
-       0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32,
-       0x01, 0x08, 0x17, 0x73,
-       0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
-       0x27, 0x25, 0xbd, 0x09,
-       0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe,
-       0xb6, 0x14, 0x86, 0xa8,
-       0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09,
-       0x82, 0x4e, 0x05, 0x72,
-       0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
-       0xfe, 0xc0, 0x19, 0x05,
-       0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f,
-       0xcc, 0x01, 0x08, 0x26,
-       0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe,
-       0xcc, 0x15, 0x5e, 0x32,
-       0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
-       0xad, 0x23, 0xfe, 0xff,
-       0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02,
-       0x00, 0x57, 0x52, 0xad,
-       0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff,
-       0x02, 0x00, 0x57, 0x52,
-       0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
-       0x02, 0x13, 0x58, 0xff,
-       0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01,
-       0x5c, 0x0a, 0x55, 0x01,
-       0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a,
-       0xff, 0x03, 0x00, 0x54,
-       0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
-       0x7c, 0x3a, 0x0b, 0x0e,
-       0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19,
-       0xfe, 0x1a, 0xf7, 0x00,
-       0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c,
-       0xda, 0x6d, 0x02, 0xfe,
-       0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
-       0x02, 0x01, 0xc6, 0xfe,
-       0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27,
-       0x25, 0xbe, 0x01, 0x08,
-       0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59,
-       0x03, 0x9a, 0x1e, 0xfe,
-       0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
-       0x48, 0xfe, 0x08, 0x17,
-       0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26,
-       0x17, 0x4d, 0x13, 0x07,
-       0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1,
-       0xff, 0x02, 0x83, 0x55,
-       0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
-       0x17, 0x1c, 0x63, 0x13,
-       0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64,
-       0x00, 0xb0, 0xfe, 0x80,
-       0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10,
-       0x53, 0x07, 0xfe, 0x60,
-       0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
-       0x00, 0x1c, 0x95, 0x13,
-       0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3,
-       0xfe, 0x43, 0xf4, 0x96,
-       0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43,
-       0xf4, 0x94, 0xf6, 0x8b,
-       0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
-       0xda, 0x17, 0x62, 0x49,
-       0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80,
-       0x71, 0x50, 0x26, 0xfe,
-       0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3,
-       0x58, 0x02, 0x50, 0x13,
-       0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
-       0x25, 0xbe, 0xfe, 0x03,
-       0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9,
-       0x0a, 0x01, 0x08, 0x16,
-       0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01,
-       0x01, 0x08, 0x16, 0xa9,
-       0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
-       0x08, 0x16, 0xa9, 0x27,
-       0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83,
-       0x01, 0x38, 0x06, 0x24,
-       0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1,
-       0x78, 0x03, 0x9a, 0x1e,
-       0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
-       0xfe, 0x40, 0x5a, 0x23,
-       0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c,
-       0x80, 0x48, 0xfe, 0xaa,
-       0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01,
-       0xfe, 0xac, 0x1d, 0xfe,
-       0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
-       0x43, 0x48, 0x2d, 0x93,
-       0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4,
-       0x36, 0xfe, 0x34, 0xf4,
-       0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe,
-       0x28, 0x10, 0xfe, 0xc0,
-       0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
-       0x18, 0x45, 0xfe, 0x1c,
-       0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c,
-       0x19, 0xfe, 0x04, 0xf4,
-       0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d,
-       0x21, 0xfe, 0x7f, 0x01,
-       0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
-       0x7e, 0x01, 0xfe, 0xc8,
-       0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa,
-       0x21, 0xfe, 0x81, 0x01,
-       0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50,
-       0x13, 0x0d, 0x02, 0x14,
-       0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
-       0xfe, 0x82, 0x19, 0x14,
-       0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01,
-       0x08, 0x02, 0x14, 0x07,
-       0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07,
-       0x01, 0x08, 0x17, 0xc1,
-       0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
-       0x08, 0x02, 0x50, 0x02,
-       0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74,
-       0x14, 0x12, 0x01, 0x08,
-       0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01,
-       0x08, 0x17, 0x74, 0xfe,
-       0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
-       0x74, 0x5f, 0xcc, 0x01,
-       0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4,
-       0xfe, 0x49, 0xf4, 0x00,
-       0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff,
-       0x02, 0x00, 0x10, 0x2f,
-       0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
-       0x16, 0xfe, 0x64, 0x1a,
-       0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c,
-       0x61, 0x07, 0x44, 0x02,
-       0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12,
-       0x13, 0x0a, 0x9d, 0x01,
-       0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
-       0xfe, 0x80, 0xe7, 0x1a,
-       0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02,
-       0x0a, 0x5a, 0x01, 0x18,
-       0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe,
-       0x7e, 0x1e, 0xfe, 0x80,
-       0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
-       0xfe, 0x80, 0x4c, 0x0a,
-       0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf,
-       0xfe, 0x19, 0xde, 0xfe,
-       0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe,
-       0x2a, 0x1c, 0xfa, 0xb3,
-       0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
-       0xf4, 0x1a, 0xfe, 0xfa,
-       0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24,
-       0xfe, 0x18, 0x58, 0x03,
-       0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f,
-       0xfe, 0x30, 0xf4, 0x07,
-       0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
-       0xf7, 0x24, 0xb1, 0xfe,
-       0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b,
-       0xfe, 0xba, 0x10, 0x1c,
-       0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
-       0x1d, 0xf7, 0x54, 0xb1,
-       0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
-       0xaf, 0x19, 0xfe, 0x98,
-       0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c,
-       0x1a, 0x87, 0x8b, 0x0f,
-       0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58,
-       0xfe, 0x32, 0x90, 0x04,
-       0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
-       0x7c, 0x12, 0xfe, 0x0f,
-       0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14,
-       0x31, 0x02, 0xc9, 0x2b,
-       0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe,
-       0x6a, 0xfe, 0x19, 0xfe,
-       0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
-       0x1b, 0xfe, 0x36, 0x14,
-       0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19,
-       0xfe, 0x80, 0xe7, 0x1a,
-       0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a,
-       0x30, 0xfe, 0x12, 0x45,
-       0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
-       0x39, 0xf0, 0x75, 0x26,
-       0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03,
-       0xe3, 0x23, 0x07, 0xfe,
-       0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09,
-       0x56, 0xfe, 0x3c, 0x13,
-       0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
-       0x01, 0x18, 0xcb, 0xfe,
-       0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16,
-       0xfe, 0x00, 0xcc, 0xcb,
-       0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18,
-       0xfe, 0x80, 0x4c, 0x01,
-       0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
-       0x12, 0xfe, 0x14, 0x56,
-       0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7,
-       0x0d, 0x19, 0xfe, 0x15,
-       0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06,
-       0x83, 0xfe, 0x18, 0x80,
-       0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
-       0x90, 0xfe, 0xba, 0x90,
-       0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02,
-       0x21, 0xb9, 0x88, 0x20,
-       0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01,
-       0x18, 0xfe, 0x49, 0x44,
-       0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
-       0x1a, 0xa4, 0x0a, 0x67,
-       0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4,
-       0x1d, 0x7b, 0xfe, 0x52,
-       0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe,
-       0x4e, 0xe4, 0xdd, 0x7b,
-       0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
-       0xfe, 0x4e, 0xe4, 0xfe,
-       0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24,
-       0xfe, 0x08, 0x10, 0x03,
-       0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04,
-       0x68, 0x54, 0xfe, 0xf1,
-       0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
-       0xfe, 0x1a, 0xf4, 0xfe,
-       0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02,
-       0x09, 0x92, 0xfe, 0x5a,
-       0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe,
-       0x5a, 0xf0, 0xfe, 0xc8,
-       0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
-       0x1a, 0x10, 0x09, 0x0d,
-       0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02,
-       0x1f, 0x93, 0x01, 0x42,
-       0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e,
-       0xfe, 0x14, 0xf0, 0x08,
-       0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
-       0xfe, 0x82, 0xf0, 0xfe,
-       0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e,
-       0x02, 0x0f, 0xfe, 0x18,
-       0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02,
-       0x80, 0x04, 0xfe, 0x82,
-       0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
-       0x83, 0x33, 0x0b, 0x0e,
-       0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e,
-       0x02, 0x0f, 0xfe, 0x04,
-       0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80,
-       0x80, 0x04, 0xfe, 0x80,
-       0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
-       0xfe, 0x99, 0x83, 0xfe,
-       0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86,
-       0x83, 0xfe, 0xce, 0x47,
-       0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a,
-       0x0b, 0x0e, 0x02, 0x0f,
-       0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
-       0xfe, 0x08, 0x90, 0x04,
-       0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04,
-       0xfe, 0x8a, 0x93, 0x79,
-       0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a,
-       0x0b, 0x0e, 0x02, 0x0f,
-       0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
-       0xfe, 0x3c, 0x90, 0x04,
-       0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80,
-       0x04, 0xfe, 0x83, 0x83,
-       0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
-};
+               /*
+                * Convert the request's SRB pointer to a host ASC_SCSI_REQ
+                * structure pointer using a macro provided by the driver.
+                * The ASC_SCSI_REQ pointer provides a pointer to the
+                * host ASC_SG_HEAD structure.
+                */
+               /* Read request's SRB pointer. */
+               scsiq = (ASC_SCSI_Q *)
+                   ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
+                                                                   (ushort)
+                                                                   (q_addr +
+                                                                    ASC_SCSIQ_D_SRBPTR))));
+
+               /*
+                * Get request's first and working SG queue.
+                */
+               sg_wk_q_no = AscReadLramByte(iop_base,
+                                            (ushort)(q_addr +
+                                                     ASC_SCSIQ_B_SG_WK_QP));
+
+               first_sg_wk_q_no = AscReadLramByte(iop_base,
+                                                  (ushort)(q_addr +
+                                                           ASC_SCSIQ_B_FIRST_SG_WK_QP));
+
+               /*
+                * Reset request's working SG queue back to the
+                * first SG queue.
+                */
+               AscWriteLramByte(iop_base,
+                                (ushort)(q_addr +
+                                         (ushort)ASC_SCSIQ_B_SG_WK_QP),
+                                first_sg_wk_q_no);
+
+               sg_head = scsiq->sg_head;
+
+               /*
+                * Set sg_entry_cnt to the number of SG elements
+                * that will be completed on this interrupt.
+                *
+                * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
+                * SG elements. The data_cnt and data_addr fields which
+                * add 1 to the SG element capacity are not used when
+                * restarting SG handling after a halt.
+                */
+               if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
+                       sg_entry_cnt = ASC_MAX_SG_LIST - 1;
+
+                       /*
+                        * Keep track of remaining number of SG elements that
+                        * will need to be handled on the next interrupt.
+                        */
+                       scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
+               } else {
+                       sg_entry_cnt = scsiq->remain_sg_entry_cnt;
+                       scsiq->remain_sg_entry_cnt = 0;
+               }
+
+               /*
+                * Copy SG elements into the list of allocated SG queues.
+                *
+                * Last index completed is saved in scsiq->next_sg_index.
+                */
+               next_qp = first_sg_wk_q_no;
+               q_addr = ASC_QNO_TO_QADDR(next_qp);
+               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;
+                               /*
+                                * After very first SG queue RISC FW uses next
+                                * SG queue first element then checks sg_list_cnt
+                                * against zero and then decrements, so set
+                                * sg_list_cnt 1 less than number of SG elements
+                                * in each SG queue.
+                                */
+                               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 {
+                               /*
+                                * This is the last SG queue in the list of
+                                * allocated SG queues. If there are more
+                                * SG elements than will fit in the allocated
+                                * queues, then set the QCSG_SG_XFER_MORE flag.
+                                */
+                               if (scsiq->remain_sg_entry_cnt != 0) {
+                                       scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
+                               } else {
+                                       scsi_sg_q.cntl |= QCSG_SG_XFER_END;
+                               }
+                               /* equals sg_entry_cnt * 2 */
+                               sg_list_dwords = sg_entry_cnt << 1;
+                               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;
+                       }
 
-static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf);      /* 0x1673 */
-static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
+                       scsi_sg_q.q_no = next_qp;
+                       AscMemWordCopyPtrToLram(iop_base,
+                                               q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
+                                               (uchar *)&scsi_sg_q,
+                                               sizeof(ASC_SG_LIST_Q) >> 1);
+
+                       AscMemDWordCopyPtrToLram(iop_base,
+                                                q_addr + ASC_SGQ_LIST_BEG,
+                                                (uchar *)&sg_head->
+                                                sg_list[scsiq->next_sg_index],
+                                                sg_list_dwords);
+
+                       scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
+
+                       /*
+                        * If the just completed SG queue contained the
+                        * last SG element, then no more SG queues need
+                        * to be written.
+                        */
+                       if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
+                               break;
+                       }
+
+                       next_qp = AscReadLramByte(iop_base,
+                                                 (ushort)(q_addr +
+                                                          ASC_SCSIQ_B_FWD));
+                       q_addr = ASC_QNO_TO_QADDR(next_qp);
+               }
+
+               /*
+                * Clear the halt condition so the RISC will be restarted
+                * after the return.
+                */
+               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+               return (0);
+       }
+#endif /* CC_VERY_LONG_SG_LIST */
+       return (0);
+}
 
-/* a_init.c */
 /*
- * EEPROM Configuration.
+ * void
+ * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
  *
- * All drivers should use this structure to set the default EEPROM
- * configuration. The BIOS now uses this structure when it is built.
- * Additional structure information can be found in a_condor.h where
- * the structure is defined.
+ * Calling/Exit State:
+ *    none
  *
- * The *_Field_IsChar structs are needed to correct for endianness.
- * These values are read from the board 16 bits at a time directly
- * into the structs. Because some fields are char, the values will be
- * in the wrong order. The *_Field_IsChar tells when to flip the
- * bytes. Data read and written to PCI memory is automatically swapped
- * on big-endian platforms so char fields read as words are actually being
- * unswapped on big-endian platforms.
+ * Description:
+ *     Input an ASC_QDONE_INFO structure from the chip
  */
-static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __initdata = {
-       ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
-       0x0000,                 /* cfg_msw */
-       0xFFFF,                 /* disc_enable */
-       0xFFFF,                 /* wdtr_able */
-       0xFFFF,                 /* sdtr_able */
-       0xFFFF,                 /* start_motor */
-       0xFFFF,                 /* tagqng_able */
-       0xFFFF,                 /* bios_scan */
-       0,                      /* scam_tolerant */
-       7,                      /* adapter_scsi_id */
-       0,                      /* bios_boot_delay */
-       3,                      /* scsi_reset_delay */
-       0,                      /* bios_id_lun */
-       0,                      /* termination */
-       0,                      /* reserved1 */
-       0xFFE7,                 /* bios_ctrl */
-       0xFFFF,                 /* ultra_able */
-       0,                      /* reserved2 */
-       ASC_DEF_MAX_HOST_QNG,   /* max_host_qng */
-       ASC_DEF_MAX_DVC_QNG,    /* max_dvc_qng */
-       0,                      /* dvc_cntl */
-       0,                      /* bug_fix */
-       0,                      /* serial_number_word1 */
-       0,                      /* serial_number_word2 */
-       0,                      /* serial_number_word3 */
-       0,                      /* check_sum */
-       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-       ,                       /* oem_name[16] */
-       0,                      /* dvc_err_code */
-       0,                      /* adv_err_code */
-       0,                      /* adv_err_addr */
-       0,                      /* saved_dvc_err_code */
-       0,                      /* saved_adv_err_code */
-       0,                      /* saved_adv_err_addr */
-       0                       /* num_of_err */
-};
+static void
+DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
+{
+       int i;
+       ushort word;
+
+       AscSetChipLramAddr(iop_base, s_addr);
+       for (i = 0; i < 2 * words; i += 2) {
+               if (i == 10) {
+                       continue;
+               }
+               word = inpw(iop_base + IOP_RAM_DATA);
+               inbuf[i] = word & 0xff;
+               inbuf[i + 1] = (word >> 8) & 0xff;
+       }
+       ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
+}
+
+static uchar
+_AscCopyLramScsiDoneQ(PortAddr iop_base,
+                     ushort q_addr,
+                     ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
+{
+       ushort _val;
+       uchar sg_queue_cnt;
+
+       DvcGetQinfo(iop_base,
+                   q_addr + ASC_SCSIQ_DONE_INFO_BEG,
+                   (uchar *)scsiq,
+                   (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
+
+       _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->extra_bytes = (uchar)(_val >> 8);
+
+       /*
+        * Read high word of remain bytes from alternate location.
+        */
+       scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
+                                                         (ushort)(q_addr +
+                                                                  (ushort)
+                                                                  ASC_SCSIQ_W_ALT_DC1)))
+                              << 16);
+       /*
+        * Read low word of remain bytes from original location.
+        */
+       scsiq->remain_bytes += AscReadLramWord(iop_base,
+                                              (ushort)(q_addr + (ushort)
+                                                       ASC_SCSIQ_DW_REMAIN_XFER_CNT));
+
+       scsiq->remain_bytes &= max_dma_count;
+       return sg_queue_cnt;
+}
+
+/*
+ * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
+ *
+ * Interrupt callback function for the Narrow SCSI Asc Library.
+ */
+static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
+{
+       struct asc_board *boardp;
+       struct scsi_cmnd *scp;
+       struct Scsi_Host *shost;
+
+       ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
+       ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
+
+       scp = advansys_srb_to_ptr(asc_dvc_varp, qdonep->d2.srb_ptr);
+       if (!scp)
+               return;
+
+       ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
+
+       shost = scp->device->host;
+       ASC_STATS(shost, callback);
+       ASC_DBG(1, "shost 0x%p\n", shost);
+
+       boardp = shost_priv(shost);
+       BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
+
+       dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
+                       sizeof(scp->sense_buffer), DMA_FROM_DEVICE);
+       /*
+        * 'qdonep' contains the command's ending status.
+        */
+       switch (qdonep->d3.done_stat) {
+       case QD_NO_ERROR:
+               ASC_DBG(2, "QD_NO_ERROR\n");
+               scp->result = 0;
+
+               /*
+                * Check for an underrun condition.
+                *
+                * If there was no error and an underrun condition, then
+                * return the number of underrun bytes.
+                */
+               if (scsi_bufflen(scp) != 0 && qdonep->remain_bytes != 0 &&
+                   qdonep->remain_bytes <= scsi_bufflen(scp)) {
+                       ASC_DBG(1, "underrun condition %u bytes\n",
+                                (unsigned)qdonep->remain_bytes);
+                       scsi_set_resid(scp, qdonep->remain_bytes);
+               }
+               break;
+
+       case QD_WITH_ERROR:
+               ASC_DBG(2, "QD_WITH_ERROR\n");
+               switch (qdonep->d3.host_stat) {
+               case QHSTA_NO_ERROR:
+                       if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
+                               ASC_DBG(2, "SAM_STAT_CHECK_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 right shifted status byte definitions.
+                                * For instance target drivers use
+                                * CHECK_CONDITION, defined to 0x1, instead of
+                                * the SCSI defined check condition value of
+                                * 0x2. Host drivers are supposed to return
+                                * the status byte as it is defined by SCSI.
+                                */
+                               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_DBG(1, "host_stat 0x%x\n", qdonep->d3.host_stat);
+                       scp->result = HOST_BYTE(DID_BAD_TARGET);
+                       break;
+               }
+               break;
 
-static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = {
-       0,                      /* cfg_lsw */
-       0,                      /* cfg_msw */
-       0,                      /* -disc_enable */
-       0,                      /* wdtr_able */
-       0,                      /* sdtr_able */
-       0,                      /* start_motor */
-       0,                      /* tagqng_able */
-       0,                      /* bios_scan */
-       0,                      /* scam_tolerant */
-       1,                      /* adapter_scsi_id */
-       1,                      /* bios_boot_delay */
-       1,                      /* scsi_reset_delay */
-       1,                      /* bios_id_lun */
-       1,                      /* termination */
-       1,                      /* reserved1 */
-       0,                      /* bios_ctrl */
-       0,                      /* ultra_able */
-       0,                      /* reserved2 */
-       1,                      /* max_host_qng */
-       1,                      /* max_dvc_qng */
-       0,                      /* dvc_cntl */
-       0,                      /* bug_fix */
-       0,                      /* serial_number_word1 */
-       0,                      /* serial_number_word2 */
-       0,                      /* serial_number_word3 */
-       0,                      /* check_sum */
-       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
-       ,                       /* oem_name[16] */
-       0,                      /* dvc_err_code */
-       0,                      /* adv_err_code */
-       0,                      /* adv_err_addr */
-       0,                      /* saved_dvc_err_code */
-       0,                      /* saved_adv_err_code */
-       0,                      /* saved_adv_err_addr */
-       0                       /* num_of_err */
-};
+       case QD_ABORTED_BY_HOST:
+               ASC_DBG(1, "QD_ABORTED_BY_HOST\n");
+               scp->result =
+                   HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
+                                                   scsi_msg) |
+                   STATUS_BYTE(qdonep->d3.scsi_stat);
+               break;
 
-static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = {
-       ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
-       0x0000,                 /* 01 cfg_msw */
-       0xFFFF,                 /* 02 disc_enable */
-       0xFFFF,                 /* 03 wdtr_able */
-       0x4444,                 /* 04 sdtr_speed1 */
-       0xFFFF,                 /* 05 start_motor */
-       0xFFFF,                 /* 06 tagqng_able */
-       0xFFFF,                 /* 07 bios_scan */
-       0,                      /* 08 scam_tolerant */
-       7,                      /* 09 adapter_scsi_id */
-       0,                      /*    bios_boot_delay */
-       3,                      /* 10 scsi_reset_delay */
-       0,                      /*    bios_id_lun */
-       0,                      /* 11 termination_se */
-       0,                      /*    termination_lvd */
-       0xFFE7,                 /* 12 bios_ctrl */
-       0x4444,                 /* 13 sdtr_speed2 */
-       0x4444,                 /* 14 sdtr_speed3 */
-       ASC_DEF_MAX_HOST_QNG,   /* 15 max_host_qng */
-       ASC_DEF_MAX_DVC_QNG,    /*    max_dvc_qng */
-       0,                      /* 16 dvc_cntl */
-       0x4444,                 /* 17 sdtr_speed4 */
-       0,                      /* 18 serial_number_word1 */
-       0,                      /* 19 serial_number_word2 */
-       0,                      /* 20 serial_number_word3 */
-       0,                      /* 21 check_sum */
-       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-       ,                       /* 22-29 oem_name[16] */
-       0,                      /* 30 dvc_err_code */
-       0,                      /* 31 adv_err_code */
-       0,                      /* 32 adv_err_addr */
-       0,                      /* 33 saved_dvc_err_code */
-       0,                      /* 34 saved_adv_err_code */
-       0,                      /* 35 saved_adv_err_addr */
-       0,                      /* 36 reserved */
-       0,                      /* 37 reserved */
-       0,                      /* 38 reserved */
-       0,                      /* 39 reserved */
-       0,                      /* 40 reserved */
-       0,                      /* 41 reserved */
-       0,                      /* 42 reserved */
-       0,                      /* 43 reserved */
-       0,                      /* 44 reserved */
-       0,                      /* 45 reserved */
-       0,                      /* 46 reserved */
-       0,                      /* 47 reserved */
-       0,                      /* 48 reserved */
-       0,                      /* 49 reserved */
-       0,                      /* 50 reserved */
-       0,                      /* 51 reserved */
-       0,                      /* 52 reserved */
-       0,                      /* 53 reserved */
-       0,                      /* 54 reserved */
-       0,                      /* 55 reserved */
-       0,                      /* 56 cisptr_lsw */
-       0,                      /* 57 cisprt_msw */
-       PCI_VENDOR_ID_ASP,      /* 58 subsysvid */
-       PCI_DEVICE_ID_38C0800_REV1,     /* 59 subsysid */
-       0,                      /* 60 reserved */
-       0,                      /* 61 reserved */
-       0,                      /* 62 reserved */
-       0                       /* 63 reserved */
-};
+       default:
+               ASC_DBG(1, "done_stat 0x%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;
+       }
+
+       /*
+        * If the 'init_tidmask' bit isn't already set for the target and the
+        * current request finished normally, then set the bit for the target
+        * to indicate that a device is present.
+        */
+       if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
+           qdonep->d3.done_stat == QD_NO_ERROR &&
+           qdonep->d3.host_stat == QHSTA_NO_ERROR) {
+               boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
+       }
+
+       asc_scsi_done(scp);
+}
+
+static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
+{
+       uchar next_qp;
+       uchar n_q_used;
+       uchar sg_list_qp;
+       uchar sg_queue_cnt;
+       uchar q_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 *scsiq;
+       int false_overrun;
+
+       iop_base = asc_dvc->iop_base;
+       n_q_used = 1;
+       scsiq = (ASC_QDONE_INFO *)&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 (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
+                               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 (scsiq->extra_bytes != 0) {
+                               scsiq->remain_bytes +=
+                                   (ADV_DCNT)scsiq->extra_bytes;
+                       }
+                       if (scsiq->d3.done_stat == QD_WITH_ERROR) {
+                               if (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;
+                                       }
+                               } else if (scsiq->d3.host_stat ==
+                                          QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
+                                       AscStopChip(iop_base);
+                                       AscSetChipControl(iop_base,
+                                                         (uchar)(CC_SCSI_RESET
+                                                                 | CC_HALT));
+                                       udelay(60);
+                                       AscSetChipControl(iop_base, CC_HALT);
+                                       AscSetChipStatus(iop_base,
+                                                        CIW_CLR_SCSI_RESET_INT);
+                                       AscSetChipStatus(iop_base, 0);
+                                       AscSetChipControl(iop_base, 0);
+                               }
+                       }
+                       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))
+                                    == START_STOP)) {
+                                       asc_dvc->unit_not_ready &= ~target_id;
+                                       if (scsiq->d3.done_stat != QD_NO_ERROR) {
+                                               asc_dvc->start_motor &=
+                                                   ~target_id;
+                                       }
+                               }
+                       }
+                       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);
+}
 
-static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = {
-       0,                      /* 00 cfg_lsw */
-       0,                      /* 01 cfg_msw */
-       0,                      /* 02 disc_enable */
-       0,                      /* 03 wdtr_able */
-       0,                      /* 04 sdtr_speed1 */
-       0,                      /* 05 start_motor */
-       0,                      /* 06 tagqng_able */
-       0,                      /* 07 bios_scan */
-       0,                      /* 08 scam_tolerant */
-       1,                      /* 09 adapter_scsi_id */
-       1,                      /*    bios_boot_delay */
-       1,                      /* 10 scsi_reset_delay */
-       1,                      /*    bios_id_lun */
-       1,                      /* 11 termination_se */
-       1,                      /*    termination_lvd */
-       0,                      /* 12 bios_ctrl */
-       0,                      /* 13 sdtr_speed2 */
-       0,                      /* 14 sdtr_speed3 */
-       1,                      /* 15 max_host_qng */
-       1,                      /*    max_dvc_qng */
-       0,                      /* 16 dvc_cntl */
-       0,                      /* 17 sdtr_speed4 */
-       0,                      /* 18 serial_number_word1 */
-       0,                      /* 19 serial_number_word2 */
-       0,                      /* 20 serial_number_word3 */
-       0,                      /* 21 check_sum */
-       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
-       ,                       /* 22-29 oem_name[16] */
-       0,                      /* 30 dvc_err_code */
-       0,                      /* 31 adv_err_code */
-       0,                      /* 32 adv_err_addr */
-       0,                      /* 33 saved_dvc_err_code */
-       0,                      /* 34 saved_adv_err_code */
-       0,                      /* 35 saved_adv_err_addr */
-       0,                      /* 36 reserved */
-       0,                      /* 37 reserved */
-       0,                      /* 38 reserved */
-       0,                      /* 39 reserved */
-       0,                      /* 40 reserved */
-       0,                      /* 41 reserved */
-       0,                      /* 42 reserved */
-       0,                      /* 43 reserved */
-       0,                      /* 44 reserved */
-       0,                      /* 45 reserved */
-       0,                      /* 46 reserved */
-       0,                      /* 47 reserved */
-       0,                      /* 48 reserved */
-       0,                      /* 49 reserved */
-       0,                      /* 50 reserved */
-       0,                      /* 51 reserved */
-       0,                      /* 52 reserved */
-       0,                      /* 53 reserved */
-       0,                      /* 54 reserved */
-       0,                      /* 55 reserved */
-       0,                      /* 56 cisptr_lsw */
-       0,                      /* 57 cisprt_msw */
-       0,                      /* 58 subsysvid */
-       0,                      /* 59 subsysid */
-       0,                      /* 60 reserved */
-       0,                      /* 61 reserved */
-       0,                      /* 62 reserved */
-       0                       /* 63 reserved */
-};
+static int AscISR(ASC_DVC_VAR *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;
 
-static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = {
-       ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
-       0x0000,                 /* 01 cfg_msw */
-       0xFFFF,                 /* 02 disc_enable */
-       0xFFFF,                 /* 03 wdtr_able */
-       0x5555,                 /* 04 sdtr_speed1 */
-       0xFFFF,                 /* 05 start_motor */
-       0xFFFF,                 /* 06 tagqng_able */
-       0xFFFF,                 /* 07 bios_scan */
-       0,                      /* 08 scam_tolerant */
-       7,                      /* 09 adapter_scsi_id */
-       0,                      /*    bios_boot_delay */
-       3,                      /* 10 scsi_reset_delay */
-       0,                      /*    bios_id_lun */
-       0,                      /* 11 termination_se */
-       0,                      /*    termination_lvd */
-       0xFFE7,                 /* 12 bios_ctrl */
-       0x5555,                 /* 13 sdtr_speed2 */
-       0x5555,                 /* 14 sdtr_speed3 */
-       ASC_DEF_MAX_HOST_QNG,   /* 15 max_host_qng */
-       ASC_DEF_MAX_DVC_QNG,    /*    max_dvc_qng */
-       0,                      /* 16 dvc_cntl */
-       0x5555,                 /* 17 sdtr_speed4 */
-       0,                      /* 18 serial_number_word1 */
-       0,                      /* 19 serial_number_word2 */
-       0,                      /* 20 serial_number_word3 */
-       0,                      /* 21 check_sum */
-       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-       ,                       /* 22-29 oem_name[16] */
-       0,                      /* 30 dvc_err_code */
-       0,                      /* 31 adv_err_code */
-       0,                      /* 32 adv_err_addr */
-       0,                      /* 33 saved_dvc_err_code */
-       0,                      /* 34 saved_adv_err_code */
-       0,                      /* 35 saved_adv_err_addr */
-       0,                      /* 36 reserved */
-       0,                      /* 37 reserved */
-       0,                      /* 38 reserved */
-       0,                      /* 39 reserved */
-       0,                      /* 40 reserved */
-       0,                      /* 41 reserved */
-       0,                      /* 42 reserved */
-       0,                      /* 43 reserved */
-       0,                      /* 44 reserved */
-       0,                      /* 45 reserved */
-       0,                      /* 46 reserved */
-       0,                      /* 47 reserved */
-       0,                      /* 48 reserved */
-       0,                      /* 49 reserved */
-       0,                      /* 50 reserved */
-       0,                      /* 51 reserved */
-       0,                      /* 52 reserved */
-       0,                      /* 53 reserved */
-       0,                      /* 54 reserved */
-       0,                      /* 55 reserved */
-       0,                      /* 56 cisptr_lsw */
-       0,                      /* 57 cisprt_msw */
-       PCI_VENDOR_ID_ASP,      /* 58 subsysvid */
-       PCI_DEVICE_ID_38C1600_REV1,     /* 59 subsysid */
-       0,                      /* 60 reserved */
-       0,                      /* 61 reserved */
-       0,                      /* 62 reserved */
-       0                       /* 63 reserved */
-};
+       iop_base = asc_dvc->iop_base;
+       int_pending = FALSE;
 
-static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = {
-       0,                      /* 00 cfg_lsw */
-       0,                      /* 01 cfg_msw */
-       0,                      /* 02 disc_enable */
-       0,                      /* 03 wdtr_able */
-       0,                      /* 04 sdtr_speed1 */
-       0,                      /* 05 start_motor */
-       0,                      /* 06 tagqng_able */
-       0,                      /* 07 bios_scan */
-       0,                      /* 08 scam_tolerant */
-       1,                      /* 09 adapter_scsi_id */
-       1,                      /*    bios_boot_delay */
-       1,                      /* 10 scsi_reset_delay */
-       1,                      /*    bios_id_lun */
-       1,                      /* 11 termination_se */
-       1,                      /*    termination_lvd */
-       0,                      /* 12 bios_ctrl */
-       0,                      /* 13 sdtr_speed2 */
-       0,                      /* 14 sdtr_speed3 */
-       1,                      /* 15 max_host_qng */
-       1,                      /*    max_dvc_qng */
-       0,                      /* 16 dvc_cntl */
-       0,                      /* 17 sdtr_speed4 */
-       0,                      /* 18 serial_number_word1 */
-       0,                      /* 19 serial_number_word2 */
-       0,                      /* 20 serial_number_word3 */
-       0,                      /* 21 check_sum */
-       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
-       ,                       /* 22-29 oem_name[16] */
-       0,                      /* 30 dvc_err_code */
-       0,                      /* 31 adv_err_code */
-       0,                      /* 32 adv_err_addr */
-       0,                      /* 33 saved_dvc_err_code */
-       0,                      /* 34 saved_adv_err_code */
-       0,                      /* 35 saved_adv_err_addr */
-       0,                      /* 36 reserved */
-       0,                      /* 37 reserved */
-       0,                      /* 38 reserved */
-       0,                      /* 39 reserved */
-       0,                      /* 40 reserved */
-       0,                      /* 41 reserved */
-       0,                      /* 42 reserved */
-       0,                      /* 43 reserved */
-       0,                      /* 44 reserved */
-       0,                      /* 45 reserved */
-       0,                      /* 46 reserved */
-       0,                      /* 47 reserved */
-       0,                      /* 48 reserved */
-       0,                      /* 49 reserved */
-       0,                      /* 50 reserved */
-       0,                      /* 51 reserved */
-       0,                      /* 52 reserved */
-       0,                      /* 53 reserved */
-       0,                      /* 54 reserved */
-       0,                      /* 55 reserved */
-       0,                      /* 56 cisptr_lsw */
-       0,                      /* 57 cisprt_msw */
-       0,                      /* 58 subsysvid */
-       0,                      /* 59 subsysid */
-       0,                      /* 60 reserved */
-       0,                      /* 61 reserved */
-       0,                      /* 62 reserved */
-       0                       /* 63 reserved */
-};
+       if (AscIsIntPending(iop_base) == 0)
+               return int_pending;
+
+       if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 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);
+               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));
+       chipstat = AscGetChipStatus(iop_base);
+       if (chipstat & CSW_SCSI_RESET_LATCH) {
+               if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
+                       int i = 10;
+                       int_pending = TRUE;
+                       asc_dvc->sdtr_done = 0;
+                       saved_ctrl_reg &= (uchar)(~CC_HALT);
+                       while ((AscGetChipStatus(iop_base) &
+                               CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
+                               mdelay(100);
+                       }
+                       AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
+                       AscSetChipControl(iop_base, CC_HALT);
+                       AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
+                       AscSetChipStatus(iop_base, 0);
+                       chipstat = AscGetChipStatus(iop_base);
+               }
+       }
+       saved_ram_addr = AscGetChipLramAddr(iop_base);
+       host_flag = AscReadLramByte(iop_base,
+                                   ASCV_HOST_FLAG_B) &
+           (uchar)(~ASC_HOST_FLAG_IN_ISR);
+       AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
+                        (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
+       if ((chipstat & CSW_INT_PENDING) || (int_pending)) {
+               AscAckInterrupt(iop_base);
+               int_pending = TRUE;
+               if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
+                       if (AscIsrChipHalted(asc_dvc) == ERR) {
+                               goto ISR_REPORT_QDONE_FATAL_ERROR;
+                       } else {
+                               saved_ctrl_reg &= (uchar)(~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;
+               }
+       }
+       AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
+       AscSetChipLramAddr(iop_base, saved_ram_addr);
+       AscSetChipControl(iop_base, saved_ctrl_reg);
+       asc_dvc->is_in_int = FALSE;
+       return int_pending;
+}
 
 /*
- * Initialize the ADV_DVC_VAR structure.
+ * advansys_reset()
  *
- * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ * Reset the bus associated with the command 'scp'.
  *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
+ * This function runs its own thread. Interrupts must be blocked but
+ * sleeping is allowed and no locking other than for host structures is
+ * required. Returns SUCCESS or FAILED.
  */
-static int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
+static int advansys_reset(struct scsi_cmnd *scp)
 {
-       ushort warn_code;
-       AdvPortAddr iop_base;
-       uchar pci_cmd_reg;
+       struct Scsi_Host *shost = scp->device->host;
+       struct asc_board *boardp = shost_priv(shost);
+       unsigned long flags;
        int status;
+       int ret = SUCCESS;
 
-       warn_code = 0;
-       asc_dvc->err_code = 0;
-       iop_base = asc_dvc->iop_base;
-
-       /*
-        * PCI Command Register
-        *
-        * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes
-        * I/O Space Control, Memory Space Control and Bus Master Control bits.
-        */
-
-       if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
-                                                   AscPCIConfigCommandRegister))
-            & AscPCICmdRegBits_BusMastering)
-           != AscPCICmdRegBits_BusMastering) {
-               pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
-
-               DvcAdvWritePCIConfigByte(asc_dvc,
-                                        AscPCIConfigCommandRegister,
-                                        pci_cmd_reg);
-
-               if (((DvcAdvReadPCIConfigByte
-                     (asc_dvc, AscPCIConfigCommandRegister))
-                    & AscPCICmdRegBits_BusMastering)
-                   != AscPCICmdRegBits_BusMastering) {
-                       warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-               }
-       }
+       ASC_DBG(1, "0x%p\n", scp);
 
-       /*
-        * PCI Latency Timer
-        *
-        * If the "latency timer" register is 0x20 or above, then we don't need
-        * to change it.  Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
-        * comes up less than 0x20).
-        */
-       if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
-               DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer,
-                                        0x20);
-               if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) <
-                   0x20) {
-                       warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-               }
-       }
+       ASC_STATS(shost, reset);
 
-       /*
-        * Save the state of the PCI Configuration Command Register
-        * "Parity Error Response Control" Bit. If the bit is clear (0),
-        * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
-        * DMA parity errors.
-        */
-       asc_dvc->cfg->control_flag = 0;
-       if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
-             & AscPCICmdRegBits_ParErrRespCtrl)) == 0) {
-               asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
-       }
+       scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n");
 
-       asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
-           ADV_LIB_VERSION_MINOR;
-       asc_dvc->cfg->chip_version =
-           AdvGetChipVersion(iop_base, asc_dvc->bus_type);
+       if (ASC_NARROW_BOARD(boardp)) {
+               ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
 
-       ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
-                (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
-                (ushort)ADV_CHIP_ID_BYTE);
+               /* Reset the chip and SCSI bus. */
+               ASC_DBG(1, "before AscInitAsc1000Driver()\n");
+               status = AscInitAsc1000Driver(asc_dvc);
 
-       ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
-                (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
-                (ushort)ADV_CHIP_ID_WORD);
+               /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
+               if (asc_dvc->err_code) {
+                       scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
+                                   "0x%x\n", asc_dvc->err_code);
+                       ret = FAILED;
+               } else if (status) {
+                       scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
+                                   "0x%x\n", status);
+               } else {
+                       scmd_printk(KERN_INFO, scp, "SCSI bus reset "
+                                   "successful\n");
+               }
 
-       /*
-        * Reset the chip to start and allow register writes.
-        */
-       if (AdvFindSignature(iop_base) == 0) {
-               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
-               return ADV_ERROR;
+               ASC_DBG(1, "after AscInitAsc1000Driver()\n");
+               spin_lock_irqsave(shost->host_lock, flags);
        } else {
                /*
-                * The caller must set 'chip_type' to a valid setting.
+                * If the suggest reset bus flags are set, then reset the bus.
+                * Otherwise only reset the device.
                 */
-               if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
-                   asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
-                   asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
-                       asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
-                       return ADV_ERROR;
-               }
+               ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
 
                /*
-                * Reset Chip.
+                * Reset the target's SCSI bus.
                 */
-               AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
-                                    ADV_CTRL_REG_CMD_RESET);
-               DvcSleepMilliSecond(100);
-               AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
-                                    ADV_CTRL_REG_CMD_WR_IO_REG);
-
-               if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
-                       if ((status =
-                            AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) {
-                               return ADV_ERROR;
-                       }
-               } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
-                       if ((status =
-                            AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) {
-                               return ADV_ERROR;
-                       }
-               } else {
-                       if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) {
-                               return ADV_ERROR;
-                       }
+               ASC_DBG(1, "before AdvResetChipAndSB()\n");
+               switch (AdvResetChipAndSB(adv_dvc)) {
+               case ASC_TRUE:
+                       scmd_printk(KERN_INFO, scp, "SCSI bus reset "
+                                   "successful\n");
+                       break;
+               case ASC_FALSE:
+               default:
+                       scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n");
+                       ret = FAILED;
+                       break;
                }
-               warn_code |= status;
+               spin_lock_irqsave(shost->host_lock, flags);
+               AdvISR(adv_dvc);
        }
 
-       return warn_code;
+       /* Save the time of the most recently completed reset. */
+       boardp->last_reset = jiffies;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+
+       ASC_DBG(1, "ret %d\n", ret);
+
+       return ret;
 }
 
 /*
- * Initialize the ASC-3550.
- *
- * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ * advansys_biosparam()
  *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
+ * Translate disk drive geometry if the "BIOS greater than 1 GB"
+ * support is enabled for a drive.
  *
- * Needed after initialization for error recovery.
+ * ip (information pointer) is an int array with the following definition:
+ * ip[0]: heads
+ * ip[1]: sectors
+ * ip[2]: cylinders
  */
-static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
+static int
+advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+                  sector_t capacity, int ip[])
 {
-       AdvPortAddr iop_base;
-       ushort warn_code;
-       ADV_DCNT sum;
-       int begin_addr;
-       int end_addr;
-       ushort code_sum;
-       int word;
-       int j;
-       int adv_asc3550_expanded_size;
-       ADV_CARR_T *carrp;
-       ADV_DCNT contig_len;
-       ADV_SDCNT buf_size;
-       ADV_PADDR carr_paddr;
-       int i;
-       ushort scsi_cfg1;
-       uchar tid;
-       ushort bios_mem[ASC_MC_BIOSLEN / 2];    /* BIOS RISC Memory 0x40-0x8F. */
-       ushort wdtr_able = 0, sdtr_able, tagqng_able;
-       uchar max_cmd[ADV_MAX_TID + 1];
-
-       /* If there is already an error, don't continue. */
-       if (asc_dvc->err_code != 0) {
-               return ADV_ERROR;
-       }
-
-       /*
-        * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
-        */
-       if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
-               asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
-               return ADV_ERROR;
-       }
-
-       warn_code = 0;
-       iop_base = asc_dvc->iop_base;
-
-       /*
-        * Save the RISC memory BIOS region before writing the microcode.
-        * The BIOS may already be loaded and using its RISC LRAM region
-        * so its region must be saved and restored.
-        *
-        * Note: This code makes the assumption, which is currently true,
-        * that a chip reset does not clear RISC LRAM.
-        */
-       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
-               AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
-                               bios_mem[i]);
-       }
-
-       /*
-        * Save current per TID negotiated values.
-        */
-       if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
-               ushort bios_version, major, minor;
+       struct asc_board *boardp = shost_priv(sdev->host);
 
-               bios_version =
-                   bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
-               major = (bios_version >> 12) & 0xF;
-               minor = (bios_version >> 8) & 0xF;
-               if (major < 3 || (major == 3 && minor == 1)) {
-                       /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
-                       AdvReadWordLram(iop_base, 0x120, wdtr_able);
+       ASC_DBG(1, "begin\n");
+       ASC_STATS(sdev->host, biosparam);
+       if (ASC_NARROW_BOARD(boardp)) {
+               if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
+                    ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
+                       ip[0] = 255;
+                       ip[1] = 63;
                } else {
-                       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
+                       ip[0] = 64;
+                       ip[1] = 32;
                }
-       }
-       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                               max_cmd[tid]);
-       }
-
-       /*
-        * Load the Microcode
-        *
-        * Write the microcode image to RISC memory starting at address 0.
-        */
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
-       /* Assume the following compressed format of the microcode buffer:
-        *
-        *  254 word (508 byte) table indexed by byte code followed
-        *  by the following byte codes:
-        *
-        *    1-Byte Code:
-        *      00: Emit word 0 in table.
-        *      01: Emit word 1 in table.
-        *      .
-        *      FD: Emit word 253 in table.
-        *
-        *    Multi-Byte Code:
-        *      FE WW WW: (3 byte code) Word to emit is the next word WW WW.
-        *      FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
-        */
-       word = 0;
-       for (i = 253 * 2; i < _adv_asc3550_size; i++) {
-               if (_adv_asc3550_buf[i] == 0xff) {
-                       for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) {
-                               AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                                   _adv_asc3550_buf
-                                                                   [i +
-                                                                    3] << 8) |
-                                                                  _adv_asc3550_buf
-                                                                  [i + 2]));
-                               word++;
-                       }
-                       i += 3;
-               } else if (_adv_asc3550_buf[i] == 0xfe) {
-                       AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                           _adv_asc3550_buf[i +
-                                                                            2]
-                                                           << 8) |
-                                                          _adv_asc3550_buf[i +
-                                                                           1]));
-                       i += 2;
-                       word++;
+       } else {
+               if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
+                    BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
+                       ip[0] = 255;
+                       ip[1] = 63;
                } else {
-                       AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                           _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
-                       word++;
+                       ip[0] = 64;
+                       ip[1] = 32;
                }
        }
+       ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
+       ASC_DBG(1, "end\n");
+       return 0;
+}
 
-       /*
-        * Set 'word' for later use to clear the rest of memory and save
-        * the expanded mcode size.
-        */
-       word *= 2;
-       adv_asc3550_expanded_size = word;
-
-       /*
-        * Clear the rest of ASC-3550 Internal RAM (8KB).
-        */
-       for (; word < ADV_3550_MEMSIZE; word += 2) {
-               AdvWriteWordAutoIncLram(iop_base, 0);
-       }
-
-       /*
-        * Verify the microcode checksum.
-        */
-       sum = 0;
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
-
-       for (word = 0; word < adv_asc3550_expanded_size; word += 2) {
-               sum += AdvReadWordAutoIncLram(iop_base);
-       }
-
-       if (sum != _adv_asc3550_chksum) {
-               asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
-               return ADV_ERROR;
-       }
-
-       /*
-        * Restore the RISC memory BIOS region.
-        */
-       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
-               AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
-                                bios_mem[i]);
-       }
+/*
+ * First-level interrupt handler.
+ *
+ * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host.
+ */
+static irqreturn_t advansys_interrupt(int irq, void *dev_id)
+{
+       struct Scsi_Host *shost = dev_id;
+       struct asc_board *boardp = shost_priv(shost);
+       irqreturn_t result = IRQ_NONE;
 
-       /*
-        * Calculate and write the microcode code checksum to the microcode
-        * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
-        */
-       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
-       AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
-       code_sum = 0;
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
-       for (word = begin_addr; word < end_addr; word += 2) {
-               code_sum += AdvReadWordAutoIncLram(iop_base);
+       ASC_DBG(2, "boardp 0x%p\n", boardp);
+       spin_lock(shost->host_lock);
+       if (ASC_NARROW_BOARD(boardp)) {
+               if (AscIsIntPending(shost->io_port)) {
+                       result = IRQ_HANDLED;
+                       ASC_STATS(shost, interrupt);
+                       ASC_DBG(1, "before AscISR()\n");
+                       AscISR(&boardp->dvc_var.asc_dvc_var);
+               }
+       } else {
+               ASC_DBG(1, "before AdvISR()\n");
+               if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
+                       result = IRQ_HANDLED;
+                       ASC_STATS(shost, interrupt);
+               }
        }
-       AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
+       spin_unlock(shost->host_lock);
 
-       /*
-        * Read and save microcode version and date.
-        */
-       AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
-                       asc_dvc->cfg->mcode_date);
-       AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
-                       asc_dvc->cfg->mcode_version);
+       ASC_DBG(1, "end\n");
+       return result;
+}
 
-       /*
-        * Set the chip type to indicate the ASC3550.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
+static int AscHostReqRiscHalt(PortAddr iop_base)
+{
+       int count = 0;
+       int sta = 0;
+       uchar saved_stop_code;
 
-       /*
-        * If the PCI Configuration Command Register "Parity Error Response
-        * Control" Bit was clear (0), then set the microcode variable
-        * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
-        * to ignore DMA parity errors.
-        */
-       if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
-               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
-               word |= CONTROL_FLAG_IGNORE_PERR;
-               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
-       }
+       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;
+               }
+               mdelay(100);
+       } while (count++ < 20);
+       AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
+       return (sta);
+}
 
-       /*
-        * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
-        * threshold of 128 bytes. This register is only accessible to the host.
-        */
-       AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
-                            START_CTL_EMFU | READ_CMD_MRM);
+static int
+AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
+{
+       int sta = FALSE;
 
-       /*
-        * Microcode operating variables for WDTR, SDTR, and command tag
-        * queuing will be set in AdvInquiryHandling() based on what a
-        * device reports it is capable of in Inquiry byte 7.
-        *
-        * If SCSI Bus Resets have been disabled, then directly set
-        * SDTR and WDTR from the EEPROM configuration. This will allow
-        * the BIOS and warm boot to work without a SCSI bus hang on
-        * the Inquiry caused by host and target mismatched DTR values.
-        * Without the SCSI Bus Reset, before an Inquiry a device can't
-        * be assumed to be in Asynchronous, Narrow mode.
-        */
-       if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
-               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
-                                asc_dvc->wdtr_able);
-               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
-                                asc_dvc->sdtr_able);
+       if (AscHostReqRiscHalt(iop_base)) {
+               sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
+               AscStartChip(iop_base);
        }
+       return sta;
+}
 
-       /*
-        * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
-        * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
-        * bitmask. These values determine the maximum SDTR speed negotiated
-        * with a device.
-        *
-        * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
-        * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
-        * without determining here whether the device supports SDTR.
-        *
-        * 4-bit speed  SDTR speed name
-        * ===========  ===============
-        * 0000b (0x0)  SDTR disabled
-        * 0001b (0x1)  5 Mhz
-        * 0010b (0x2)  10 Mhz
-        * 0011b (0x3)  20 Mhz (Ultra)
-        * 0100b (0x4)  40 Mhz (LVD/Ultra2)
-        * 0101b (0x5)  80 Mhz (LVD2/Ultra3)
-        * 0110b (0x6)  Undefined
-        * .
-        * 1111b (0xF)  Undefined
-        */
-       word = 0;
-       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-               if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
-                       /* Set Ultra speed for TID 'tid'. */
-                       word |= (0x3 << (4 * (tid % 4)));
-               } else {
-                       /* Set Fast speed for TID 'tid'. */
-                       word |= (0x2 << (4 * (tid % 4)));
-               }
-               if (tid == 3) { /* Check if done with sdtr_speed1. */
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
-                       word = 0;
-               } else if (tid == 7) {  /* Check if done with sdtr_speed2. */
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
-                       word = 0;
-               } else if (tid == 11) { /* Check if done with sdtr_speed3. */
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
-                       word = 0;
-               } else if (tid == 15) { /* Check if done with sdtr_speed4. */
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
-                       /* End of loop. */
-               }
-       }
+static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
+{
+       char type = sdev->type;
+       ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
 
-       /*
-        * Set microcode operating variable for the disconnect per TID bitmask.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
-                        asc_dvc->cfg->disc_enable);
+       if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN))
+               return;
+       if (asc_dvc->init_sdtr & tid_bits)
+               return;
 
-       /*
-        * Set SCSI_CFG0 Microcode Default Value.
-        *
-        * The microcode will set the SCSI_CFG0 register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
-                        PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
-                        asc_dvc->chip_scsi_id);
+       if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0))
+               asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
 
-       /*
-        * Determine SCSI_CFG1 Microcode Default Value.
-        *
-        * The microcode will set the SCSI_CFG1 register using this value
-        * after it is started below.
-        */
+       asc_dvc->pci_fix_asyn_xfer |= tid_bits;
+       if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) ||
+           (type == TYPE_ROM) || (type == TYPE_TAPE))
+               asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
 
-       /* Read current SCSI_CFG1 Register value. */
-       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+       if (asc_dvc->pci_fix_asyn_xfer & tid_bits)
+               AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id,
+                                       ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+}
 
-       /*
-        * If all three connectors are in use, return an error.
-        */
-       if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
-           (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
-               asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
-               return ADV_ERROR;
-       }
+static void
+advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
+{
+       ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
+       ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
 
-       /*
-        * If the internal narrow cable is reversed all of the SCSI_CTRL
-        * register signals will be set. Check for and return an error if
-        * this condition is found.
-        */
-       if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
-               asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
-               return ADV_ERROR;
-       }
+       if (sdev->lun == 0) {
+               ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
+               if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
+                       asc_dvc->init_sdtr |= tid_bit;
+               } else {
+                       asc_dvc->init_sdtr &= ~tid_bit;
+               }
 
-       /*
-        * If this is a differential board and a single-ended device
-        * is attached to one of the connectors, return an error.
-        */
-       if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
-               asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
-               return ADV_ERROR;
+               if (orig_init_sdtr != asc_dvc->init_sdtr)
+                       AscAsyncFix(asc_dvc, sdev);
        }
 
-       /*
-        * If automatic termination control is enabled, then set the
-        * termination value based on a table listed in a_condor.h.
-        *
-        * If manual termination was specified with an EEPROM setting
-        * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
-        * is ready to be 'ored' into SCSI_CFG1.
-        */
-       if (asc_dvc->cfg->termination == 0) {
-               /*
-                * The software always controls termination by setting TERM_CTL_SEL.
-                * If TERM_CTL_SEL were set to 0, the hardware would set termination.
-                */
-               asc_dvc->cfg->termination |= TERM_CTL_SEL;
-
-               switch (scsi_cfg1 & CABLE_DETECT) {
-                       /* TERM_CTL_H: on, TERM_CTL_L: on */
-               case 0x3:
-               case 0x7:
-               case 0xB:
-               case 0xD:
-               case 0xE:
-               case 0xF:
-                       asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
-                       break;
+       if (sdev->tagged_supported) {
+               if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
+                       if (sdev->lun == 0) {
+                               asc_dvc->cfg->can_tagged_qng |= tid_bit;
+                               asc_dvc->use_tagged_qng |= tid_bit;
+                       }
+                       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+                                               asc_dvc->max_dvc_qng[sdev->id]);
+               }
+       } else {
+               if (sdev->lun == 0) {
+                       asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
+                       asc_dvc->use_tagged_qng &= ~tid_bit;
+               }
+               scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+       }
 
-                       /* TERM_CTL_H: on, TERM_CTL_L: off */
-               case 0x1:
-               case 0x5:
-               case 0x9:
-               case 0xA:
-               case 0xC:
-                       asc_dvc->cfg->termination |= TERM_CTL_H;
-                       break;
+       if ((sdev->lun == 0) &&
+           (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
+               AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
+                                asc_dvc->cfg->disc_enable);
+               AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
+                                asc_dvc->use_tagged_qng);
+               AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
+                                asc_dvc->cfg->can_tagged_qng);
 
-                       /* TERM_CTL_H: off, TERM_CTL_L: off */
-               case 0x2:
-               case 0x6:
-                       break;
-               }
+               asc_dvc->max_dvc_qng[sdev->id] =
+                                       asc_dvc->cfg->max_tag_qng[sdev->id];
+               AscWriteLramByte(asc_dvc->iop_base,
+                                (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
+                                asc_dvc->max_dvc_qng[sdev->id]);
        }
+}
 
-       /*
-        * Clear any set TERM_CTL_H and TERM_CTL_L bits.
-        */
-       scsi_cfg1 &= ~TERM_CTL;
+/*
+ * Wide Transfers
+ *
+ * If the EEPROM enabled WDTR for the device and the device supports wide
+ * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
+ * write the new value to the microcode.
+ */
+static void
+advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
+{
+       unsigned short cfg_word;
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
+       if ((cfg_word & tidmask) != 0)
+               return;
 
-       /*
-        * Invert the TERM_CTL_H and TERM_CTL_L bits and then
-        * set 'scsi_cfg1'. The TERM_POL bit does not need to be
-        * referenced, because the hardware internally inverts
-        * the Termination High and Low bits if TERM_POL is set.
-        */
-       scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
+       cfg_word |= tidmask;
+       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
 
        /*
-        * Set SCSI_CFG1 Microcode Default Value
-        *
-        * Set filter value and possibly modified termination control
-        * bits in the Microcode SCSI_CFG1 Register Value.
-        *
-        * The microcode will set the SCSI_CFG1 register using this value
-        * after it is started below.
+        * Clear the microcode SDTR and WDTR negotiation done indicators for
+        * the target to cause it to negotiate with the new setting set above.
+        * WDTR when accepted causes the target to enter asynchronous mode, so
+        * SDTR must be negotiated.
         */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
-                        FLTR_DISABLE | scsi_cfg1);
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
+       cfg_word &= ~tidmask;
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
+       AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
+       cfg_word &= ~tidmask;
+       AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
+}
 
-       /*
-        * Set MEM_CFG Microcode Default Value
-        *
-        * The microcode will set the MEM_CFG register using this value
-        * after it is started below.
-        *
-        * MEM_CFG may be accessed as a word or byte, but only bits 0-7
-        * are defined.
-        *
-        * ASC-3550 has 8KB internal memory.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
-                        BIOS_EN | RAM_SZ_8KB);
+/*
+ * Synchronous Transfers
+ *
+ * If the EEPROM enabled SDTR for the device and the device
+ * supports synchronous transfers, then turn on the device's
+ * 'sdtr_able' bit. Write the new value to the microcode.
+ */
+static void
+advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
+{
+       unsigned short cfg_word;
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
+       if ((cfg_word & tidmask) != 0)
+               return;
 
-       /*
-        * Set SEL_MASK Microcode Default Value
-        *
-        * The microcode will set the SEL_MASK register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
-                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
+       cfg_word |= tidmask;
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
 
        /*
-        * Build carrier freelist.
-        *
-        * Driver must have already allocated memory and set 'carrier_buf'.
+        * Clear the microcode "SDTR negotiation" done indicator for the
+        * target to cause it to negotiate with the new setting set above.
         */
-       ASC_ASSERT(asc_dvc->carrier_buf != NULL);
+       AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
+       cfg_word &= ~tidmask;
+       AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
+}
 
-       carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
-       asc_dvc->carr_freelist = NULL;
-       if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
-               buf_size = ADV_CARRIER_BUFSIZE;
-       } else {
-               buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
-       }
+/*
+ * PPR (Parallel Protocol Request) Capable
+ *
+ * If the device supports DT mode, then it must be PPR capable.
+ * The PPR message will be used in place of the SDTR and WDTR
+ * messages to negotiate synchronous speed and offset, transfer
+ * width, and protocol options.
+ */
+static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
+                               AdvPortAddr iop_base, unsigned short tidmask)
+{
+       AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
+       adv_dvc->ppr_able |= tidmask;
+       AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
+}
 
-       do {
+static void
+advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
+{
+       AdvPortAddr iop_base = adv_dvc->iop_base;
+       unsigned short tidmask = 1 << sdev->id;
+
+       if (sdev->lun == 0) {
                /*
-                * Get physical address of the carrier 'carrp'.
+                * Handle WDTR, SDTR, and Tag Queuing. If the feature
+                * is enabled in the EEPROM and the device supports the
+                * feature, then enable it in the microcode.
                 */
-               contig_len = sizeof(ADV_CARR_T);
-               carr_paddr =
-                   cpu_to_le32(DvcGetPhyAddr
-                               (asc_dvc, NULL, (uchar *)carrp,
-                                (ADV_SDCNT *)&contig_len,
-                                ADV_IS_CARRIER_FLAG));
 
-               buf_size -= sizeof(ADV_CARR_T);
+               if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
+                       advansys_wide_enable_wdtr(iop_base, tidmask);
+               if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
+                       advansys_wide_enable_sdtr(iop_base, tidmask);
+               if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
+                       advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
 
                /*
-                * If the current carrier is not physically contiguous, then
-                * maybe there was a page crossing. Try the next carrier aligned
-                * start address.
+                * Tag Queuing is disabled for the BIOS which runs in polled
+                * mode and would see no benefit from Tag Queuing. Also by
+                * disabling Tag Queuing in the BIOS devices with Tag Queuing
+                * bugs will at least work with the BIOS.
                 */
-               if (contig_len < sizeof(ADV_CARR_T)) {
-                       carrp++;
-                       continue;
+               if ((adv_dvc->tagqng_able & tidmask) &&
+                   sdev->tagged_supported) {
+                       unsigned short cfg_word;
+                       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
+                       cfg_word |= tidmask;
+                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
+                                        cfg_word);
+                       AdvWriteByteLram(iop_base,
+                                        ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
+                                        adv_dvc->max_dvc_qng);
                }
+       }
 
-               carrp->carr_pa = carr_paddr;
-               carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
+       if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
+               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+                                       adv_dvc->max_dvc_qng);
+       } else {
+               scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+       }
+}
 
-               /*
-                * Insert the carrier at the beginning of the freelist.
-                */
-               carrp->next_vpa =
-                   cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
-               asc_dvc->carr_freelist = carrp;
+/*
+ * Set the number of commands to queue per device for the
+ * specified host adapter.
+ */
+static int advansys_slave_configure(struct scsi_device *sdev)
+{
+       struct asc_board *boardp = shost_priv(sdev->host);
 
-               carrp++;
-       }
-       while (buf_size > 0);
+       if (ASC_NARROW_BOARD(boardp))
+               advansys_narrow_slave_configure(sdev,
+                                               &boardp->dvc_var.asc_dvc_var);
+       else
+               advansys_wide_slave_configure(sdev,
+                                               &boardp->dvc_var.adv_dvc_var);
 
-       /*
-        * Set-up the Host->RISC Initiator Command Queue (ICQ).
-        */
+       return 0;
+}
 
-       if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
-               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
-               return ADV_ERROR;
-       }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
+static __le32 advansys_get_sense_buffer_dma(struct scsi_cmnd *scp)
+{
+       struct asc_board *board = shost_priv(scp->device->host);
+       scp->SCp.dma_handle = dma_map_single(board->dev, scp->sense_buffer,
+                               sizeof(scp->sense_buffer), DMA_FROM_DEVICE);
+       dma_cache_sync(board->dev, scp->sense_buffer,
+                               sizeof(scp->sense_buffer), DMA_FROM_DEVICE);
+       return cpu_to_le32(scp->SCp.dma_handle);
+}
 
-       /*
-        * The first command issued will be placed in the stopper carrier.
-        */
-       asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
+                       struct asc_scsi_q *asc_scsi_q)
+{
+       struct asc_dvc_var *asc_dvc = &boardp->dvc_var.asc_dvc_var;
+       int use_sg;
 
-       /*
-        * Set RISC ICQ physical address start value.
-        */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
+       memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
 
        /*
-        * Set-up the RISC->Host Initiator Response Queue (IRQ).
+        * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
         */
-       if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
-               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
-               return ADV_ERROR;
+       asc_scsi_q->q2.srb_ptr = advansys_ptr_to_srb(asc_dvc, scp);
+       if (asc_scsi_q->q2.srb_ptr == BAD_SRB) {
+               scp->result = HOST_BYTE(DID_SOFT_ERROR);
+               return ASC_ERROR;
        }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
 
        /*
-        * The first command completed by the RISC will be placed in
-        * the stopper.
-        *
-        * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
-        * completed the RISC will set the ASC_RQ_STOPPER bit.
+        * Build the ASC_SCSI_Q request.
         */
-       asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+       asc_scsi_q->cdbptr = &scp->cmnd[0];
+       asc_scsi_q->q2.cdb_len = scp->cmd_len;
+       asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
+       asc_scsi_q->q1.target_lun = scp->device->lun;
+       asc_scsi_q->q2.target_ix =
+           ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
+       asc_scsi_q->q1.sense_addr = advansys_get_sense_buffer_dma(scp);
+       asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
 
        /*
-        * Set RISC IRQ physical address start value.
+        * If there are any outstanding requests for the current target,
+        * then every 255th request send an ORDERED request. This heuristic
+        * tries to retain the benefit of request sorting while preventing
+        * request starvation. 255 is the max number of tags or pending commands
+        * a device may have outstanding.
+        *
+        * The request count is incremented below for every successfully
+        * started request.
+        *
         */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
-       asc_dvc->carr_pending_cnt = 0;
+       if ((asc_dvc->cur_dvc_qng[scp->device->id] > 0) &&
+           (boardp->reqcnt[scp->device->id] % 255) == 0) {
+               asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
+       } else {
+               asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG;
+       }
 
-       AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
-                            (ADV_INTR_ENABLE_HOST_INTR |
-                             ADV_INTR_ENABLE_GLOBAL_INTR));
+       /* Build ASC_SCSI_Q */
+       use_sg = scsi_dma_map(scp);
+       if (use_sg != 0) {
+               int sgcnt;
+               struct scatterlist *slp;
+               struct asc_sg_head *asc_sg_head;
 
-       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
-       AdvWriteWordRegister(iop_base, IOPW_PC, word);
+               if (use_sg > scp->device->host->sg_tablesize) {
+                       scmd_printk(KERN_ERR, scp, "use_sg %d > "
+                               "sg_tablesize %d\n", use_sg,
+                               scp->device->host->sg_tablesize);
+                       scsi_dma_unmap(scp);
+                       scp->result = HOST_BYTE(DID_ERROR);
+                       return ASC_ERROR;
+               }
 
-       /* finally, finally, gentlemen, start your engine */
-       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
+               asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
+                       use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
+               if (!asc_sg_head) {
+                       scsi_dma_unmap(scp);
+                       scp->result = HOST_BYTE(DID_SOFT_ERROR);
+                       return ASC_ERROR;
+               }
+
+               asc_scsi_q->q1.cntl |= QC_SG_HEAD;
+               asc_scsi_q->sg_head = asc_sg_head;
+               asc_scsi_q->q1.data_cnt = 0;
+               asc_scsi_q->q1.data_addr = 0;
+               /* This is a byte value, otherwise it would need to be swapped. */
+               asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
+               ASC_STATS_ADD(scp->device->host, xfer_elem,
+                             asc_sg_head->entry_cnt);
 
-       /*
-        * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
-        * Resets should be performed. The RISC has to be running
-        * to issue a SCSI Bus Reset.
-        */
-       if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
                /*
-                * If the BIOS Signature is present in memory, restore the
-                * BIOS Handshake Configuration Table and do not perform
-                * a SCSI Bus Reset.
+                * Convert scatter-gather list into ASC_SG_HEAD list.
                 */
-               if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
-                   0x55AA) {
+               scsi_for_each_sg(scp, slp, use_sg, sgcnt) {
+                       asc_sg_head->sg_list[sgcnt].addr =
+                           cpu_to_le32(sg_dma_address(slp));
+                       asc_sg_head->sg_list[sgcnt].bytes =
+                           cpu_to_le32(sg_dma_len(slp));
+                       ASC_STATS_ADD(scp->device->host, xfer_sect,
+                                     DIV_ROUND_UP(sg_dma_len(slp), 512));
+               }
+       }
+
+       ASC_STATS(scp->device->host, xfer_cnt);
+
+       ASC_DBG_PRT_ASC_SCSI_Q(2, asc_scsi_q);
+       ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
+
+       return ASC_NOERROR;
+}
+
+/*
+ * Build scatter-gather list for Adv Library (Wide Board).
+ *
+ * Additional ADV_SG_BLOCK structures will need to be allocated
+ * if the total number of scatter-gather elements exceeds
+ * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
+ * assumed to be physically contiguous.
+ *
+ * Return:
+ *      ADV_SUCCESS(1) - SG List successfully created
+ *      ADV_ERROR(-1) - SG List creation failed
+ */
+static int
+adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
+              int use_sg)
+{
+       adv_sgblk_t *sgblkp;
+       ADV_SCSI_REQ_Q *scsiqp;
+       struct scatterlist *slp;
+       int sg_elem_cnt;
+       ADV_SG_BLOCK *sg_block, *prev_sg_block;
+       ADV_PADDR sg_block_paddr;
+       int i;
+
+       scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
+       slp = scsi_sglist(scp);
+       sg_elem_cnt = use_sg;
+       prev_sg_block = NULL;
+       reqp->sgblkp = NULL;
+
+       for (;;) {
+               /*
+                * Allocate a 'adv_sgblk_t' structure from the board free
+                * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
+                * (15) scatter-gather elements.
+                */
+               if ((sgblkp = boardp->adv_sgblkp) == NULL) {
+                       ASC_DBG(1, "no free adv_sgblk_t\n");
+                       ASC_STATS(scp->device->host, adv_build_nosg);
+
                        /*
-                        * Restore per TID negotiated values.
+                        * Allocation failed. Free 'adv_sgblk_t' structures
+                        * already allocated for the request.
                         */
-                       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
-                                        tagqng_able);
-                       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-                               AdvWriteByteLram(iop_base,
-                                                ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                                                max_cmd[tid]);
+                       while ((sgblkp = reqp->sgblkp) != NULL) {
+                               /* Remove 'sgblkp' from the request list. */
+                               reqp->sgblkp = sgblkp->next_sgblkp;
+
+                               /* Add 'sgblkp' to the board free list. */
+                               sgblkp->next_sgblkp = boardp->adv_sgblkp;
+                               boardp->adv_sgblkp = sgblkp;
                        }
+                       return ASC_BUSY;
+               }
+
+               /* Complete 'adv_sgblk_t' board allocation. */
+               boardp->adv_sgblkp = sgblkp->next_sgblkp;
+               sgblkp->next_sgblkp = NULL;
+
+               /*
+                * Get 8 byte aligned virtual and physical addresses
+                * for the allocated ADV_SG_BLOCK structure.
+                */
+               sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
+               sg_block_paddr = virt_to_bus(sg_block);
+
+               /*
+                * Check if this is the first 'adv_sgblk_t' for the
+                * request.
+                */
+               if (reqp->sgblkp == NULL) {
+                       /* Request's first scatter-gather block. */
+                       reqp->sgblkp = sgblkp;
+
+                       /*
+                        * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
+                        * address pointers.
+                        */
+                       scsiqp->sg_list_ptr = sg_block;
+                       scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
                } else {
-                       if (AdvResetSB(asc_dvc) != ADV_TRUE) {
-                               warn_code = ASC_WARN_BUSRESET_ERROR;
+                       /* Request's second or later scatter-gather block. */
+                       sgblkp->next_sgblkp = reqp->sgblkp;
+                       reqp->sgblkp = sgblkp;
+
+                       /*
+                        * Point the previous ADV_SG_BLOCK structure to
+                        * the newly allocated ADV_SG_BLOCK structure.
+                        */
+                       prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
+               }
+
+               for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
+                       sg_block->sg_list[i].sg_addr =
+                                       cpu_to_le32(sg_dma_address(slp));
+                       sg_block->sg_list[i].sg_count =
+                                       cpu_to_le32(sg_dma_len(slp));
+                       ASC_STATS_ADD(scp->device->host, xfer_sect,
+                                     DIV_ROUND_UP(sg_dma_len(slp), 512));
+
+                       if (--sg_elem_cnt == 0) {       /* Last ADV_SG_BLOCK and scatter-gather entry. */
+                               sg_block->sg_cnt = i + 1;
+                               sg_block->sg_ptr = 0L;  /* Last ADV_SG_BLOCK in list. */
+                               return ADV_SUCCESS;
                        }
+                       slp++;
                }
+               sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
+               prev_sg_block = sg_block;
        }
-
-       return warn_code;
 }
 
 /*
- * Initialize the ASC-38C0800.
- *
- * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ * Build a request structure for the Adv Library (Wide Board).
  *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
+ * If an adv_req_t can not be allocated to issue the request,
+ * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
  *
- * Needed after initialization for error recovery.
+ * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
+ * microcode for DMA addresses or math operations are byte swapped
+ * to little-endian order.
  */
-static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
+static int
+adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
+             ADV_SCSI_REQ_Q **adv_scsiqpp)
 {
-       AdvPortAddr iop_base;
-       ushort warn_code;
-       ADV_DCNT sum;
-       int begin_addr;
-       int end_addr;
-       ushort code_sum;
-       int word;
-       int j;
-       int adv_asc38C0800_expanded_size;
-       ADV_CARR_T *carrp;
-       ADV_DCNT contig_len;
-       ADV_SDCNT buf_size;
-       ADV_PADDR carr_paddr;
+       adv_req_t *reqp;
+       ADV_SCSI_REQ_Q *scsiqp;
        int i;
-       ushort scsi_cfg1;
-       uchar byte;
-       uchar tid;
-       ushort bios_mem[ASC_MC_BIOSLEN / 2];    /* BIOS RISC Memory 0x40-0x8F. */
-       ushort wdtr_able, sdtr_able, tagqng_able;
-       uchar max_cmd[ADV_MAX_TID + 1];
-
-       /* If there is already an error, don't continue. */
-       if (asc_dvc->err_code != 0) {
-               return ADV_ERROR;
-       }
+       int ret;
+       int use_sg;
 
        /*
-        * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
+        * Allocate an adv_req_t structure from the board to execute
+        * the command.
         */
-       if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
-               asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
-               return ADV_ERROR;
+       if (boardp->adv_reqp == NULL) {
+               ASC_DBG(1, "no free adv_req_t\n");
+               ASC_STATS(scp->device->host, adv_build_noreq);
+               return ASC_BUSY;
+       } else {
+               reqp = boardp->adv_reqp;
+               boardp->adv_reqp = reqp->next_reqp;
+               reqp->next_reqp = NULL;
        }
 
-       warn_code = 0;
-       iop_base = asc_dvc->iop_base;
+       /*
+        * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
+        */
+       scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
 
        /*
-        * Save the RISC memory BIOS region before writing the microcode.
-        * The BIOS may already be loaded and using its RISC LRAM region
-        * so its region must be saved and restored.
-        *
-        * Note: This code makes the assumption, which is currently true,
-        * that a chip reset does not clear RISC LRAM.
+        * Initialize the structure.
         */
-       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
-               AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
-                               bios_mem[i]);
-       }
+       scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
 
        /*
-        * Save current per TID negotiated values.
+        * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
         */
-       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                               max_cmd[tid]);
-       }
+       scsiqp->srb_ptr = ADV_VADDR_TO_U32(reqp);
 
        /*
-        * RAM BIST (RAM Built-In Self Test)
-        *
-        * Address : I/O base + offset 0x38h register (byte).
-        * Function: Bit 7-6(RW) : RAM mode
-        *                          Normal Mode   : 0x00
-        *                          Pre-test Mode : 0x40
-        *                          RAM Test Mode : 0x80
-        *           Bit 5       : unused
-        *           Bit 4(RO)   : Done bit
-        *           Bit 3-0(RO) : Status
-        *                          Host Error    : 0x08
-        *                          Int_RAM Error : 0x04
-        *                          RISC Error    : 0x02
-        *                          SCSI Error    : 0x01
-        *                          No Error      : 0x00
-        *
-        * Note: RAM BIST code should be put right here, before loading the
-        * microcode and after saving the RISC memory BIOS region.
+        * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
         */
+       reqp->cmndp = scp;
 
        /*
-        * LRAM Pre-test
-        *
-        * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
-        * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
-        * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
-        * to NORMAL_MODE, return an error too.
+        * Build the ADV_SCSI_REQ_Q request.
         */
-       for (i = 0; i < 2; i++) {
-               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
-               DvcSleepMilliSecond(10);        /* Wait for 10ms before reading back. */
-               byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
-               if ((byte & RAM_TEST_DONE) == 0
-                   || (byte & 0x0F) != PRE_TEST_VALUE) {
-                       asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
-                       return ADV_ERROR;
+
+       /* Set CDB length and copy it to the request structure.  */
+       scsiqp->cdb_len = scp->cmd_len;
+       /* Copy first 12 CDB bytes to cdb[]. */
+       for (i = 0; i < scp->cmd_len && i < 12; i++) {
+               scsiqp->cdb[i] = scp->cmnd[i];
+       }
+       /* Copy last 4 CDB bytes, if present, to cdb16[]. */
+       for (; i < scp->cmd_len; i++) {
+               scsiqp->cdb16[i - 12] = scp->cmnd[i];
+       }
+
+       scsiqp->target_id = scp->device->id;
+       scsiqp->target_lun = scp->device->lun;
+
+       scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
+       scsiqp->sense_len = sizeof(scp->sense_buffer);
+
+       /* Build ADV_SCSI_REQ_Q */
+
+       use_sg = scsi_dma_map(scp);
+       if (use_sg == 0) {
+               /* Zero-length transfer */
+               reqp->sgblkp = NULL;
+               scsiqp->data_cnt = 0;
+               scsiqp->vdata_addr = NULL;
+
+               scsiqp->data_addr = 0;
+               scsiqp->sg_list_ptr = NULL;
+               scsiqp->sg_real_addr = 0;
+       } else {
+               if (use_sg > ADV_MAX_SG_LIST) {
+                       scmd_printk(KERN_ERR, scp, "use_sg %d > "
+                                  "ADV_MAX_SG_LIST %d\n", use_sg,
+                                  scp->device->host->sg_tablesize);
+                       scsi_dma_unmap(scp);
+                       scp->result = HOST_BYTE(DID_ERROR);
+
+                       /*
+                        * Free the 'adv_req_t' structure by adding it back
+                        * to the board free list.
+                        */
+                       reqp->next_reqp = boardp->adv_reqp;
+                       boardp->adv_reqp = reqp;
+
+                       return ASC_ERROR;
                }
 
-               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
-               DvcSleepMilliSecond(10);        /* Wait for 10ms before reading back. */
-               if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
-                   != NORMAL_VALUE) {
-                       asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
-                       return ADV_ERROR;
+               scsiqp->data_cnt = cpu_to_le32(scsi_bufflen(scp));
+
+               ret = adv_get_sglist(boardp, reqp, scp, use_sg);
+               if (ret != ADV_SUCCESS) {
+                       /*
+                        * Free the adv_req_t structure by adding it back to
+                        * the board free list.
+                        */
+                       reqp->next_reqp = boardp->adv_reqp;
+                       boardp->adv_reqp = reqp;
+
+                       return ret;
                }
+
+               ASC_STATS_ADD(scp->device->host, xfer_elem, use_sg);
        }
 
-       /*
-        * LRAM Test - It takes about 1.5 ms to run through the test.
-        *
-        * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
-        * If Done bit not set or Status not 0, save register byte, set the
-        * err_code, and return an error.
-        */
-       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
-       DvcSleepMilliSecond(10);        /* Wait for 10ms before checking status. */
+       ASC_STATS(scp->device->host, xfer_cnt);
 
-       byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
-       if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
-               /* Get here if Done bit not set or Status not 0. */
-               asc_dvc->bist_err_code = byte;  /* for BIOS display message */
-               asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
-               return ADV_ERROR;
-       }
+       ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
+       ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
 
-       /* We need to reset back to normal mode after LRAM test passes. */
-       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
+       *adv_scsiqpp = scsiqp;
 
-       /*
-        * Load the Microcode
-        *
-        * Write the microcode image to RISC memory starting at address 0.
-        *
-        */
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
+       return ASC_NOERROR;
+}
 
-       /* Assume the following compressed format of the microcode buffer:
-        *
-        *  254 word (508 byte) table indexed by byte code followed
-        *  by the following byte codes:
-        *
-        *    1-Byte Code:
-        *      00: Emit word 0 in table.
-        *      01: Emit word 1 in table.
-        *      .
-        *      FD: Emit word 253 in table.
-        *
-        *    Multi-Byte Code:
-        *      FE WW WW: (3 byte code) Word to emit is the next word WW WW.
-        *      FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
-        */
-       word = 0;
-       for (i = 253 * 2; i < _adv_asc38C0800_size; i++) {
-               if (_adv_asc38C0800_buf[i] == 0xff) {
-                       for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) {
-                               AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                                   _adv_asc38C0800_buf
-                                                                   [i +
-                                                                    3] << 8) |
-                                                                  _adv_asc38C0800_buf
-                                                                  [i + 2]));
-                               word++;
-                       }
-                       i += 3;
-               } else if (_adv_asc38C0800_buf[i] == 0xfe) {
-                       AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                           _adv_asc38C0800_buf
-                                                           [i +
-                                                            2] << 8) |
-                                                          _adv_asc38C0800_buf[i
-                                                                              +
-                                                                              1]));
-                       i += 2;
-                       word++;
-               } else {
-                       AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                           _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
-                       word++;
+static 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;
+}
+
+static uint
+AscGetNumOfFreeQueue(ASC_DVC_VAR *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)
+                   && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
+                       asc_dvc->last_q_shortage = n_qs;
                }
        }
+       return 0;
+}
 
-       /*
-        * Set 'word' for later use to clear the rest of memory and save
-        * the expanded mcode size.
-        */
-       word *= 2;
-       adv_asc38C0800_expanded_size = word;
-
-       /*
-        * Clear the rest of ASC-38C0800 Internal RAM (16KB).
-        */
-       for (; word < ADV_38C0800_MEMSIZE; word += 2) {
-               AdvWriteWordAutoIncLram(iop_base, 0);
-       }
-
-       /*
-        * Verify the microcode checksum.
-        */
-       sum = 0;
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
+static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
+{
+       ushort q_addr;
+       uchar next_qp;
+       uchar q_status;
 
-       for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) {
-               sum += AdvReadWordAutoIncLram(iop_base);
-       }
-       ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i);
+       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;
+}
 
-       ASC_DBG2(1,
-                "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n",
-                (ulong)sum, (ulong)_adv_asc38C0800_chksum);
+static uchar
+AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
+{
+       uchar i;
 
-       if (sum != _adv_asc38C0800_chksum) {
-               asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
-               return ADV_ERROR;
+       for (i = 0; i < n_free_q; i++) {
+               free_q_head = AscAllocFreeQueue(iop_base, free_q_head);
+               if (free_q_head == ASC_QLINK_END)
+                       break;
        }
+       return free_q_head;
+}
 
-       /*
-        * Restore the RISC memory BIOS region.
-        */
-       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
-               AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
-                                bios_mem[i]);
-       }
+/*
+ * void
+ * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
+ *
+ * Calling/Exit State:
+ *    none
+ *
+ * Description:
+ *     Output an ASC_SCSI_Q structure to the chip
+ */
+static void
+DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
+{
+       int i;
 
-       /*
-        * Calculate and write the microcode code checksum to the microcode
-        * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
-        */
-       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
-       AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
-       code_sum = 0;
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
-       for (word = begin_addr; word < end_addr; word += 2) {
-               code_sum += AdvReadWordAutoIncLram(iop_base);
+       ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
+       AscSetChipLramAddr(iop_base, s_addr);
+       for (i = 0; i < 2 * words; i += 2) {
+               if (i == 4 || i == 20) {
+                       continue;
+               }
+               outpw(iop_base + IOP_RAM_DATA,
+                     ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
        }
-       AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
-
-       /*
-        * Read microcode version and date.
-        */
-       AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
-                       asc_dvc->cfg->mcode_date);
-       AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
-                       asc_dvc->cfg->mcode_version);
-
-       /*
-        * Set the chip type to indicate the ASC38C0800.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
+}
 
-       /*
-        * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
-        * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
-        * cable detection and then we are able to read C_DET[3:0].
-        *
-        * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
-        * Microcode Default Value' section below.
-        */
-       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
-       AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
-                            scsi_cfg1 | DIS_TERM_DRV);
+static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
+{
+       ushort q_addr;
+       uchar tid_no;
+       uchar sdtr_data;
+       uchar syn_period_ix;
+       uchar syn_offset;
+       PortAddr iop_base;
 
-       /*
-        * If the PCI Configuration Command Register "Parity Error Response
-        * Control" Bit was clear (0), then set the microcode variable
-        * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
-        * to ignore DMA parity errors.
-        */
-       if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
-               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
-               word |= CONTROL_FLAG_IGNORE_PERR;
-               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+       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 = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
+               syn_period_ix =
+                   (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
+               syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
+               AscMsgOutSDTR(asc_dvc,
+                             asc_dvc->sdtr_period_tbl[syn_period_ix],
+                             syn_offset);
+               scsiq->q1.cntl |= QC_MSG_OUT;
        }
-
-       /*
-        * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
-        * bits for the default FIFO threshold.
-        *
-        * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
-        *
-        * For DMA Errata #4 set the BC_THRESH_ENB bit.
-        */
-       AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
-                            BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
-                            READ_CMD_MRM);
-
-       /*
-        * Microcode operating variables for WDTR, SDTR, and command tag
-        * queuing will be set in AdvInquiryHandling() based on what a
-        * device reports it is capable of in Inquiry byte 7.
-        *
-        * If SCSI Bus Resets have been disabled, then directly set
-        * SDTR and WDTR from the EEPROM configuration. This will allow
-        * the BIOS and warm boot to work without a SCSI bus hang on
-        * the Inquiry caused by host and target mismatched DTR values.
-        * Without the SCSI Bus Reset, before an Inquiry a device can't
-        * be assumed to be in Asynchronous, Narrow mode.
-        */
-       if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
-               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
-                                asc_dvc->wdtr_able);
-               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
-                                asc_dvc->sdtr_able);
+       q_addr = ASC_QNO_TO_QADDR(q_no);
+       if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
+               scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
        }
+       scsiq->q1.status = QS_FREE;
+       AscMemWordCopyPtrToLram(iop_base,
+                               q_addr + ASC_SCSIQ_CDB_BEG,
+                               (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
 
-       /*
-        * Set microcode operating variables for DISC and SDTR_SPEED1,
-        * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
-        * configuration values.
-        *
-        * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
-        * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
-        * without determining here whether the device supports SDTR.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
-                        asc_dvc->cfg->disc_enable);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
-
-       /*
-        * Set SCSI_CFG0 Microcode Default Value.
-        *
-        * The microcode will set the SCSI_CFG0 register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
-                        PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
-                        asc_dvc->chip_scsi_id);
-
-       /*
-        * Determine SCSI_CFG1 Microcode Default Value.
-        *
-        * The microcode will set the SCSI_CFG1 register using this value
-        * after it is started below.
-        */
-
-       /* Read current SCSI_CFG1 Register value. */
-       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
-
-       /*
-        * If the internal narrow cable is reversed all of the SCSI_CTRL
-        * register signals will be set. Check for and return an error if
-        * this condition is found.
-        */
-       if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
-               asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
-               return ADV_ERROR;
-       }
+       DvcPutScsiQ(iop_base,
+                   q_addr + ASC_SCSIQ_CPY_BEG,
+                   (uchar *)&scsiq->q1.cntl,
+                   ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
+       AscWriteLramWord(iop_base,
+                        (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
+                        (ushort)(((ushort)scsiq->q1.
+                                  q_no << 8) | (ushort)QS_READY));
+       return 1;
+}
 
-       /*
-        * All kind of combinations of devices attached to one of four connectors
-        * are acceptable except HVD device attached. For example, LVD device can
-        * be attached to SE connector while SE device attached to LVD connector.
-        * If LVD device attached to SE connector, it only runs up to Ultra speed.
-        *
-        * If an HVD device is attached to one of LVD connectors, return an error.
-        * However, there is no way to detect HVD device attached to SE connectors.
-        */
-       if (scsi_cfg1 & HVD) {
-               asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
-               return ADV_ERROR;
-       }
+static int
+AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
+{
+       int sta;
+       int i;
+       ASC_SG_HEAD *sg_head;
+       ASC_SG_LIST_Q scsi_sg_q;
+       ASC_DCNT saved_data_addr;
+       ASC_DCNT saved_data_cnt;
+       PortAddr iop_base;
+       ushort sg_list_dwords;
+       ushort sg_index;
+       ushort sg_entry_cnt;
+       ushort q_addr;
+       uchar next_qp;
 
+       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 = (ASC_PADDR) sg_head->sg_list[0].addr;
+       scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
+#if CC_VERY_LONG_SG_LIST
        /*
-        * If either SE or LVD automatic termination control is enabled, then
-        * set the termination value based on a table listed in a_condor.h.
-        *
-        * If manual termination was specified with an EEPROM setting then
-        * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to
-        * be 'ored' into SCSI_CFG1.
+        * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
+        * then not all SG elements will fit in the allocated queues.
+        * The rest of the SG elements will be copied when the RISC
+        * completes the SG elements that fit and halts.
         */
-       if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
-               /* SE automatic termination control is enabled. */
-               switch (scsi_cfg1 & C_DET_SE) {
-                       /* TERM_SE_HI: on, TERM_SE_LO: on */
-               case 0x1:
-               case 0x2:
-               case 0x3:
-                       asc_dvc->cfg->termination |= TERM_SE;
-                       break;
+       if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
+               /*
+                * Set sg_entry_cnt to be the number of SG elements that
+                * will fit in the allocated SG queues. It is minus 1, because
+                * the first SG element is handled above. ASC_MAX_SG_LIST is
+                * already inflated by 1 to account for this. For example it
+                * may be 50 which is 1 + 7 queues * 7 SG elements.
+                */
+               sg_entry_cnt = ASC_MAX_SG_LIST - 1;
 
-                       /* TERM_SE_HI: on, TERM_SE_LO: off */
-               case 0x0:
-                       asc_dvc->cfg->termination |= TERM_SE_HI;
-                       break;
+               /*
+                * Keep track of remaining number of SG elements that will
+                * need to be handled from a_isr.c.
+                */
+               scsiq->remain_sg_entry_cnt =
+                   sg_head->entry_cnt - ASC_MAX_SG_LIST;
+       } else {
+#endif /* CC_VERY_LONG_SG_LIST */
+               /*
+                * Set sg_entry_cnt to be the number of SG elements that
+                * will fit in the allocated SG queues. It is minus 1, because
+                * the first SG element is handled above.
+                */
+               sg_entry_cnt = sg_head->entry_cnt - 1;
+#if CC_VERY_LONG_SG_LIST
+       }
+#endif /* CC_VERY_LONG_SG_LIST */
+       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 {
+#if CC_VERY_LONG_SG_LIST
+                               /*
+                                * This is the last SG queue in the list of
+                                * allocated SG queues. If there are more
+                                * SG elements than will fit in the allocated
+                                * queues, then set the QCSG_SG_XFER_MORE flag.
+                                */
+                               if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
+                                       scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
+                               } else {
+#endif /* CC_VERY_LONG_SG_LIST */
+                                       scsi_sg_q.cntl |= QCSG_SG_XFER_END;
+#if CC_VERY_LONG_SG_LIST
+                               }
+#endif /* CC_VERY_LONG_SG_LIST */
+                               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);
+                       AscMemWordCopyPtrToLram(iop_base,
+                                               q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
+                                               (uchar *)&scsi_sg_q,
+                                               sizeof(ASC_SG_LIST_Q) >> 1);
+                       AscMemDWordCopyPtrToLram(iop_base,
+                                                q_addr + ASC_SGQ_LIST_BEG,
+                                                (uchar *)&sg_head->
+                                                sg_list[sg_index],
+                                                sg_list_dwords);
+                       sg_index += ASC_SG_LIST_PER_Q;
+                       scsiq->next_sg_index = sg_index;
                }
+       } 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);
+}
 
-       if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
-               /* LVD automatic termination control is enabled. */
-               switch (scsi_cfg1 & C_DET_LVD) {
-                       /* TERM_LVD_HI: on, TERM_LVD_LO: on */
-               case 0x4:
-               case 0x8:
-               case 0xC:
-                       asc_dvc->cfg->termination |= TERM_LVD;
-                       break;
+static int
+AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
+{
+       PortAddr iop_base;
+       uchar free_q_head;
+       uchar next_qp;
+       uchar tid_no;
+       uchar target_ix;
+       int sta;
 
-                       /* TERM_LVD_HI: off, TERM_LVD_LO: off */
-               case 0x0:
-                       break;
+       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) {
+               next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head,
+                                                   (uchar)n_q_required);
+               if (next_qp != 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;
+                       sta = AscPutReadySgListQueue(asc_dvc, scsiq,
+                                                    free_q_head);
+               }
+       } else if (n_q_required == 1) {
+               next_qp = AscAllocFreeQueue(iop_base, free_q_head);
+               if (next_qp != ASC_QLINK_END) {
+                       scsiq->q1.q_no = free_q_head;
+                       sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head);
                }
        }
+       if (sta == 1) {
+               AscPutVarFreeQHead(iop_base, next_qp);
+               asc_dvc->cur_total_qng += n_q_required;
+               asc_dvc->cur_dvc_qng[tid_no]++;
+       }
+       return sta;
+}
 
-       /*
-        * Clear any set TERM_SE and TERM_LVD bits.
-        */
-       scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
-
-       /*
-        * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
-        */
-       scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
-
-       /*
-        * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits
-        * and set possibly modified termination control bits in the Microcode
-        * SCSI_CFG1 Register Value.
-        */
-       scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
-
-       /*
-        * Set SCSI_CFG1 Microcode Default Value
-        *
-        * Set possibly modified termination control and reset DIS_TERM_DRV
-        * bits in the Microcode SCSI_CFG1 Register Value.
-        *
-        * The microcode will set the SCSI_CFG1 register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
-
-       /*
-        * Set MEM_CFG Microcode Default Value
-        *
-        * The microcode will set the MEM_CFG register using this value
-        * after it is started below.
-        *
-        * MEM_CFG may be accessed as a word or byte, but only bits 0-7
-        * are defined.
-        *
-        * ASC-38C0800 has 16KB internal memory.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
-                        BIOS_EN | RAM_SZ_16KB);
-
-       /*
-        * Set SEL_MASK Microcode Default Value
-        *
-        * The microcode will set the SEL_MASK register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
-                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
+#define ASC_SYN_OFFSET_ONE_DISABLE_LIST  16
+static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
+       INQUIRY,
+       REQUEST_SENSE,
+       READ_CAPACITY,
+       READ_TOC,
+       MODE_SELECT,
+       MODE_SENSE,
+       MODE_SELECT_10,
+       MODE_SENSE_10,
+       0xFF,
+       0xFF,
+       0xFF,
+       0xFF,
+       0xFF,
+       0xFF,
+       0xFF,
+       0xFF
+};
 
-       /*
-        * Build the carrier freelist.
-        *
-        * Driver must have already allocated memory and set 'carrier_buf'.
-        */
-       ASC_ASSERT(asc_dvc->carrier_buf != NULL);
+static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
+{
+       PortAddr iop_base;
+       int sta;
+       int n_q_required;
+       int disable_syn_offset_one_fix;
+       int i;
+       ASC_PADDR addr;
+       ushort sg_entry_cnt = 0;
+       ushort sg_entry_cnt_minus_one = 0;
+       uchar target_ix;
+       uchar tid_no;
+       uchar sdtr_data;
+       uchar extra_bytes;
+       uchar scsi_cmd;
+       uchar disable_cmd;
+       ASC_SG_HEAD *sg_head;
+       ASC_DCNT data_cnt;
 
-       carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
-       asc_dvc->carr_freelist = NULL;
-       if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
-               buf_size = ADV_CARRIER_BUFSIZE;
-       } else {
-               buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
+       iop_base = asc_dvc->iop_base;
+       sg_head = scsiq->sg_head;
+       if (asc_dvc->err_code != 0)
+               return (ERR);
+       scsiq->q1.q_no = 0;
+       if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
+               scsiq->q1.extra_bytes = 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] == REQUEST_SENSE) {
+               if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
+                       asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
+                       sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
+                       AscMsgOutSDTR(asc_dvc,
+                                     asc_dvc->
+                                     sdtr_period_tbl[(sdtr_data >> 4) &
+                                                     (uchar)(asc_dvc->
+                                                             max_sdtr_index -
+                                                             1)],
+                                     (uchar)(sdtr_data & (uchar)
+                                             ASC_SYN_MAX_OFFSET));
+                       scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
+               }
        }
-
-       do {
-               /*
-                * Get physical address for the carrier 'carrp'.
-                */
-               contig_len = sizeof(ADV_CARR_T);
-               carr_paddr =
-                   cpu_to_le32(DvcGetPhyAddr
-                               (asc_dvc, NULL, (uchar *)carrp,
-                                (ADV_SDCNT *)&contig_len,
-                                ADV_IS_CARRIER_FLAG));
-
-               buf_size -= sizeof(ADV_CARR_T);
-
-               /*
-                * If the current carrier is not physically contiguous, then
-                * maybe there was a page crossing. Try the next carrier aligned
-                * start address.
-                */
-               if (contig_len < sizeof(ADV_CARR_T)) {
-                       carrp++;
-                       continue;
+       if (asc_dvc->in_critical_cnt != 0) {
+               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 = sg_head->entry_cnt) == 0) {
+                       asc_dvc->in_critical_cnt--;
+                       return (ERR);
                }
-
-               carrp->carr_pa = carr_paddr;
-               carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
-
-               /*
-                * Insert the carrier at the beginning of the freelist.
-                */
-               carrp->next_vpa =
-                   cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
-               asc_dvc->carr_freelist = carrp;
-
-               carrp++;
+#if !CC_VERY_LONG_SG_LIST
+               if (sg_entry_cnt > ASC_MAX_SG_LIST) {
+                       asc_dvc->in_critical_cnt--;
+                       return (ERR);
+               }
+#endif /* !CC_VERY_LONG_SG_LIST */
+               if (sg_entry_cnt == 1) {
+                       scsiq->q1.data_addr =
+                           (ADV_PADDR)sg_head->sg_list[0].addr;
+                       scsiq->q1.data_cnt =
+                           (ADV_DCNT)sg_head->sg_list[0].bytes;
+                       scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
+               }
+               sg_entry_cnt_minus_one = sg_entry_cnt - 1;
        }
-       while (buf_size > 0);
-
-       /*
-        * Set-up the Host->RISC Initiator Command Queue (ICQ).
-        */
-
-       if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
-               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
-               return ADV_ERROR;
+       scsi_cmd = scsiq->cdbptr[0];
+       disable_syn_offset_one_fix = FALSE;
+       if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
+           !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
+               if (scsiq->q1.cntl & QC_SG_HEAD) {
+                       data_cnt = 0;
+                       for (i = 0; i < sg_entry_cnt; i++) {
+                               data_cnt +=
+                                   (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
+                                                         bytes);
+                       }
+               } else {
+                       data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
+               }
+               if (data_cnt != 0UL) {
+                       if (data_cnt < 512UL) {
+                               disable_syn_offset_one_fix = TRUE;
+                       } else {
+                               for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
+                                    i++) {
+                                       disable_cmd =
+                                           _syn_offset_one_disable_cmd[i];
+                                       if (disable_cmd == 0xFF) {
+                                               break;
+                                       }
+                                       if (scsi_cmd == disable_cmd) {
+                                               disable_syn_offset_one_fix =
+                                                   TRUE;
+                                               break;
+                                       }
+                               }
+                       }
+               }
        }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
-
-       /*
-        * The first command issued will be placed in the stopper carrier.
-        */
-       asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
-
-       /*
-        * Set RISC ICQ physical address start value.
-        * carr_pa is LE, must be native before write
-        */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
-
-       /*
-        * Set-up the RISC->Host Initiator Response Queue (IRQ).
-        */
-       if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
-               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
-               return ADV_ERROR;
+       if (disable_syn_offset_one_fix) {
+               scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
+               scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
+                                      ASC_TAG_FLAG_DISABLE_DISCONNECT);
+       } else {
+               scsiq->q2.tag_code &= 0x27;
        }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
-
-       /*
-        * The first command completed by the RISC will be placed in
-        * the stopper.
-        *
-        * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
-        * completed the RISC will set the ASC_RQ_STOPPER bit.
-        */
-       asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
-
-       /*
-        * Set RISC IRQ physical address start value.
-        *
-        * carr_pa is LE, must be native before write *
-        */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
-       asc_dvc->carr_pending_cnt = 0;
-
-       AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
-                            (ADV_INTR_ENABLE_HOST_INTR |
-                             ADV_INTR_ENABLE_GLOBAL_INTR));
-
-       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
-       AdvWriteWordRegister(iop_base, IOPW_PC, word);
-
-       /* finally, finally, gentlemen, start your engine */
-       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
-
-       /*
-        * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
-        * Resets should be performed. The RISC has to be running
-        * to issue a SCSI Bus Reset.
-        */
-       if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
+       if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
+               if (asc_dvc->bug_fix_cntl) {
+                       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
+                               if ((scsi_cmd == READ_6) ||
+                                   (scsi_cmd == READ_10)) {
+                                       addr =
+                                           (ADV_PADDR)le32_to_cpu(sg_head->
+                                                                  sg_list
+                                                                  [sg_entry_cnt_minus_one].
+                                                                  addr) +
+                                           (ADV_DCNT)le32_to_cpu(sg_head->
+                                                                 sg_list
+                                                                 [sg_entry_cnt_minus_one].
+                                                                 bytes);
+                                       extra_bytes =
+                                           (uchar)((ushort)addr & 0x0003);
+                                       if ((extra_bytes != 0)
+                                           &&
+                                           ((scsiq->q2.
+                                             tag_code &
+                                             ASC_TAG_FLAG_EXTRA_BYTES)
+                                            == 0)) {
+                                               scsiq->q2.tag_code |=
+                                                   ASC_TAG_FLAG_EXTRA_BYTES;
+                                               scsiq->q1.extra_bytes =
+                                                   extra_bytes;
+                                               data_cnt =
+                                                   le32_to_cpu(sg_head->
+                                                               sg_list
+                                                               [sg_entry_cnt_minus_one].
+                                                               bytes);
+                                               data_cnt -=
+                                                   (ASC_DCNT) extra_bytes;
+                                               sg_head->
+                                                   sg_list
+                                                   [sg_entry_cnt_minus_one].
+                                                   bytes =
+                                                   cpu_to_le32(data_cnt);
+                                       }
+                               }
+                       }
+               }
+               sg_head->entry_to_copy = sg_head->entry_cnt;
+#if CC_VERY_LONG_SG_LIST
                /*
-                * If the BIOS Signature is present in memory, restore the
-                * BIOS Handshake Configuration Table and do not perform
-                * a SCSI Bus Reset.
+                * Set the sg_entry_cnt to the maximum possible. The rest of
+                * the SG elements will be copied when the RISC completes the
+                * SG elements that fit and halts.
                 */
-               if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
-                   0x55AA) {
-                       /*
-                        * Restore per TID negotiated values.
-                        */
-                       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
-                                        tagqng_able);
-                       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-                               AdvWriteByteLram(iop_base,
-                                                ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                                                max_cmd[tid]);
+               if (sg_entry_cnt > ASC_MAX_SG_LIST) {
+                       sg_entry_cnt = ASC_MAX_SG_LIST;
+               }
+#endif /* CC_VERY_LONG_SG_LIST */
+               n_q_required = AscSgListToQueue(sg_entry_cnt);
+               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--;
+                               return (sta);
+                       }
+               }
+       } else {
+               if (asc_dvc->bug_fix_cntl) {
+                       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
+                               if ((scsi_cmd == READ_6) ||
+                                   (scsi_cmd == READ_10)) {
+                                       addr =
+                                           le32_to_cpu(scsiq->q1.data_addr) +
+                                           le32_to_cpu(scsiq->q1.data_cnt);
+                                       extra_bytes =
+                                           (uchar)((ushort)addr & 0x0003);
+                                       if ((extra_bytes != 0)
+                                           &&
+                                           ((scsiq->q2.
+                                             tag_code &
+                                             ASC_TAG_FLAG_EXTRA_BYTES)
+                                            == 0)) {
+                                               data_cnt =
+                                                   le32_to_cpu(scsiq->q1.
+                                                               data_cnt);
+                                               if (((ushort)data_cnt & 0x01FF)
+                                                   == 0) {
+                                                       scsiq->q2.tag_code |=
+                                                           ASC_TAG_FLAG_EXTRA_BYTES;
+                                                       data_cnt -= (ASC_DCNT)
+                                                           extra_bytes;
+                                                       scsiq->q1.data_cnt =
+                                                           cpu_to_le32
+                                                           (data_cnt);
+                                                       scsiq->q1.extra_bytes =
+                                                           extra_bytes;
+                                               }
+                                       }
+                               }
                        }
-               } else {
-                       if (AdvResetSB(asc_dvc) != ADV_TRUE) {
-                               warn_code = ASC_WARN_BUSRESET_ERROR;
+               }
+               n_q_required = 1;
+               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--;
+                               return (sta);
                        }
                }
        }
-
-       return warn_code;
+       asc_dvc->in_critical_cnt--;
+       return (sta);
 }
 
 /*
- * Initialize the ASC-38C1600.
+ * AdvExeScsiQueue() - Send a request to the RISC microcode program.
  *
- * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *   Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
+ *   add the carrier to the ICQ (Initiator Command Queue), and tickle the
+ *   RISC to notify it a new command is ready to be executed.
  *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
+ * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
+ * set to SCSI_MAX_RETRY.
  *
- * Needed after initialization for error recovery.
- */
-static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
-{
-       AdvPortAddr iop_base;
-       ushort warn_code;
-       ADV_DCNT sum;
-       int begin_addr;
-       int end_addr;
-       ushort code_sum;
-       long word;
-       int j;
-       int adv_asc38C1600_expanded_size;
-       ADV_CARR_T *carrp;
-       ADV_DCNT contig_len;
-       ADV_SDCNT buf_size;
-       ADV_PADDR carr_paddr;
-       int i;
-       ushort scsi_cfg1;
-       uchar byte;
-       uchar tid;
-       ushort bios_mem[ASC_MC_BIOSLEN / 2];    /* BIOS RISC Memory 0x40-0x8F. */
-       ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
-       uchar max_cmd[ASC_MAX_TID + 1];
-
-       /* If there is already an error, don't continue. */
-       if (asc_dvc->err_code != 0) {
-               return ADV_ERROR;
-       }
-
-       /*
-        * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
-        */
-       if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
-               asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
-               return ADV_ERROR;
-       }
-
-       warn_code = 0;
-       iop_base = asc_dvc->iop_base;
-
-       /*
-        * Save the RISC memory BIOS region before writing the microcode.
-        * The BIOS may already be loaded and using its RISC LRAM region
-        * so its region must be saved and restored.
-        *
-        * Note: This code makes the assumption, which is currently true,
-        * that a chip reset does not clear RISC LRAM.
-        */
-       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
-               AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
-                               bios_mem[i]);
-       }
-
-       /*
-        * Save current per TID negotiated values.
-        */
-       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-       AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
-       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-       for (tid = 0; tid <= ASC_MAX_TID; tid++) {
-               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                               max_cmd[tid]);
-       }
-
-       /*
-        * RAM BIST (Built-In Self Test)
-        *
-        * Address : I/O base + offset 0x38h register (byte).
-        * Function: Bit 7-6(RW) : RAM mode
-        *                          Normal Mode   : 0x00
-        *                          Pre-test Mode : 0x40
-        *                          RAM Test Mode : 0x80
-        *           Bit 5       : unused
-        *           Bit 4(RO)   : Done bit
-        *           Bit 3-0(RO) : Status
-        *                          Host Error    : 0x08
-        *                          Int_RAM Error : 0x04
-        *                          RISC Error    : 0x02
-        *                          SCSI Error    : 0x01
-        *                          No Error      : 0x00
-        *
-        * Note: RAM BIST code should be put right here, before loading the
-        * microcode and after saving the RISC memory BIOS region.
-        */
-
-       /*
-        * LRAM Pre-test
-        *
-        * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
-        * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
-        * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
-        * to NORMAL_MODE, return an error too.
-        */
-       for (i = 0; i < 2; i++) {
-               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
-               DvcSleepMilliSecond(10);        /* Wait for 10ms before reading back. */
-               byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
-               if ((byte & RAM_TEST_DONE) == 0
-                   || (byte & 0x0F) != PRE_TEST_VALUE) {
-                       asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
-                       return ADV_ERROR;
-               }
-
-               AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
-               DvcSleepMilliSecond(10);        /* Wait for 10ms before reading back. */
-               if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
-                   != NORMAL_VALUE) {
-                       asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
-                       return ADV_ERROR;
-               }
-       }
-
-       /*
-        * LRAM Test - It takes about 1.5 ms to run through the test.
-        *
-        * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
-        * If Done bit not set or Status not 0, save register byte, set the
-        * err_code, and return an error.
-        */
-       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
-       DvcSleepMilliSecond(10);        /* Wait for 10ms before checking status. */
-
-       byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
-       if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
-               /* Get here if Done bit not set or Status not 0. */
-               asc_dvc->bist_err_code = byte;  /* for BIOS display message */
-               asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
-               return ADV_ERROR;
-       }
-
-       /* We need to reset back to normal mode after LRAM test passes. */
-       AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
-
-       /*
-        * Load the Microcode
-        *
-        * Write the microcode image to RISC memory starting at address 0.
-        *
-        */
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
-
-       /*
-        * Assume the following compressed format of the microcode buffer:
-        *
-        *  254 word (508 byte) table indexed by byte code followed
-        *  by the following byte codes:
-        *
-        *    1-Byte Code:
-        *      00: Emit word 0 in table.
-        *      01: Emit word 1 in table.
-        *      .
-        *      FD: Emit word 253 in table.
-        *
-        *    Multi-Byte Code:
-        *      FE WW WW: (3 byte code) Word to emit is the next word WW WW.
-        *      FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
-        */
-       word = 0;
-       for (i = 253 * 2; i < _adv_asc38C1600_size; i++) {
-               if (_adv_asc38C1600_buf[i] == 0xff) {
-                       for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) {
-                               AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                                   _adv_asc38C1600_buf
-                                                                   [i +
-                                                                    3] << 8) |
-                                                                  _adv_asc38C1600_buf
-                                                                  [i + 2]));
-                               word++;
-                       }
-                       i += 3;
-               } else if (_adv_asc38C1600_buf[i] == 0xfe) {
-                       AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                           _adv_asc38C1600_buf
-                                                           [i +
-                                                            2] << 8) |
-                                                          _adv_asc38C1600_buf[i
-                                                                              +
-                                                                              1]));
-                       i += 2;
-                       word++;
-               } else {
-                       AdvWriteWordAutoIncLram(iop_base, (((ushort)
-                                                           _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2]));
-                       word++;
-               }
-       }
-
-       /*
-        * Set 'word' for later use to clear the rest of memory and save
-        * the expanded mcode size.
-        */
-       word *= 2;
-       adv_asc38C1600_expanded_size = word;
-
-       /*
-        * Clear the rest of ASC-38C1600 Internal RAM (32KB).
-        */
-       for (; word < ADV_38C1600_MEMSIZE; word += 2) {
-               AdvWriteWordAutoIncLram(iop_base, 0);
-       }
-
-       /*
-        * Verify the microcode checksum.
-        */
-       sum = 0;
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
-
-       for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) {
-               sum += AdvReadWordAutoIncLram(iop_base);
-       }
-
-       if (sum != _adv_asc38C1600_chksum) {
-               asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
-               return ADV_ERROR;
-       }
-
-       /*
-        * Restore the RISC memory BIOS region.
-        */
-       for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
-               AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
-                                bios_mem[i]);
-       }
-
-       /*
-        * Calculate and write the microcode code checksum to the microcode
-        * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
-        */
-       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
-       AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
-       code_sum = 0;
-       AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
-       for (word = begin_addr; word < end_addr; word += 2) {
-               code_sum += AdvReadWordAutoIncLram(iop_base);
-       }
-       AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
-
-       /*
-        * Read microcode version and date.
-        */
-       AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
-                       asc_dvc->cfg->mcode_date);
-       AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
-                       asc_dvc->cfg->mcode_version);
-
-       /*
-        * Set the chip type to indicate the ASC38C1600.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
-
-       /*
-        * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
-        * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
-        * cable detection and then we are able to read C_DET[3:0].
-        *
-        * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
-        * Microcode Default Value' section below.
-        */
-       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
-       AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
-                            scsi_cfg1 | DIS_TERM_DRV);
+ * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
+ * for DMA addresses or math operations are byte swapped to little-endian
+ * order.
+ *
+ * Return:
+ *      ADV_SUCCESS(1) - The request was successfully queued.
+ *      ADV_BUSY(0) -    Resource unavailable; Retry again after pending
+ *                       request completes.
+ *      ADV_ERROR(-1) -  Invalid ADV_SCSI_REQ_Q request structure
+ *                       host IC error.
+ */
+static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
+{
+       AdvPortAddr iop_base;
+       ADV_PADDR req_paddr;
+       ADV_CARR_T *new_carrp;
 
        /*
-        * If the PCI Configuration Command Register "Parity Error Response
-        * Control" Bit was clear (0), then set the microcode variable
-        * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
-        * to ignore DMA parity errors.
+        * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
         */
-       if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
-               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
-               word |= CONTROL_FLAG_IGNORE_PERR;
-               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+       if (scsiq->target_id > ADV_MAX_TID) {
+               scsiq->host_status = QHSTA_M_INVALID_DEVICE;
+               scsiq->done_status = QD_WITH_ERROR;
+               return ADV_ERROR;
        }
 
+       iop_base = asc_dvc->iop_base;
+
        /*
-        * If the BIOS control flag AIPP (Asynchronous Information
-        * Phase Protection) disable bit is not set, then set the firmware
-        * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
-        * AIPP checking and encoding.
+        * Allocate a carrier ensuring at least one carrier always
+        * remains on the freelist and initialize fields.
         */
-       if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
-               AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
-               word |= CONTROL_FLAG_ENABLE_AIPP;
-               AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+       if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
+               return ADV_BUSY;
        }
+       asc_dvc->carr_freelist = (ADV_CARR_T *)
+           ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
+       asc_dvc->carr_pending_cnt++;
 
        /*
-        * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
-        * and START_CTL_TH [3:2].
+        * Set the carrier to be a stopper by setting 'next_vpa'
+        * to the stopper value. The current stopper will be changed
+        * below to point to the new stopper.
         */
-       AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
-                            FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
+       new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
 
        /*
-        * Microcode operating variables for WDTR, SDTR, and command tag
-        * queuing will be set in AdvInquiryHandling() based on what a
-        * device reports it is capable of in Inquiry byte 7.
-        *
-        * If SCSI Bus Resets have been disabled, then directly set
-        * SDTR and WDTR from the EEPROM configuration. This will allow
-        * the BIOS and warm boot to work without a SCSI bus hang on
-        * the Inquiry caused by host and target mismatched DTR values.
-        * Without the SCSI Bus Reset, before an Inquiry a device can't
-        * be assumed to be in Asynchronous, Narrow mode.
+        * Clear the ADV_SCSI_REQ_Q done flag.
         */
-       if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
-               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
-                                asc_dvc->wdtr_able);
-               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
-                                asc_dvc->sdtr_able);
-       }
+       scsiq->a_flag &= ~ADV_SCSIQ_DONE;
 
-       /*
-        * Set microcode operating variables for DISC and SDTR_SPEED1,
-        * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
-        * configuration values.
-        *
-        * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
-        * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
-        * without determining here whether the device supports SDTR.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
-                        asc_dvc->cfg->disc_enable);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
+       req_paddr = virt_to_bus(scsiq);
+       BUG_ON(req_paddr & 31);
+       /* Wait for assertion before making little-endian */
+       req_paddr = cpu_to_le32(req_paddr);
 
-       /*
-        * Set SCSI_CFG0 Microcode Default Value.
-        *
-        * The microcode will set the SCSI_CFG0 register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
-                        PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
-                        asc_dvc->chip_scsi_id);
+       /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
+       scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
+       scsiq->scsiq_rptr = req_paddr;
 
+       scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
        /*
-        * Calculate SCSI_CFG1 Microcode Default Value.
-        *
-        * The microcode will set the SCSI_CFG1 register using this value
-        * after it is started below.
-        *
-        * Each ASC-38C1600 function has only two cable detect bits.
-        * The bus mode override bits are in IOPB_SOFT_OVER_WR.
+        * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
+        * order during initialization.
         */
-       scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+       scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
 
        /*
-        * If the cable is reversed all of the SCSI_CTRL register signals
-        * will be set. Check for and return an error if this condition is
-        * found.
+        * Use the current stopper to send the ADV_SCSI_REQ_Q command to
+        * the microcode. The newly allocated stopper will become the new
+        * stopper.
         */
-       if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
-               asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
-               return ADV_ERROR;
-       }
+       asc_dvc->icq_sp->areq_vpa = req_paddr;
 
        /*
-        * Each ASC-38C1600 function has two connectors. Only an HVD device
-        * can not be connected to either connector. An LVD device or SE device
-        * may be connected to either connecor. If an SE device is connected,
-        * then at most Ultra speed (20 Mhz) can be used on both connectors.
-        *
-        * If an HVD device is attached, return an error.
+        * Set the 'next_vpa' pointer for the old stopper to be the
+        * physical address of the new stopper. The RISC can only
+        * follow physical addresses.
         */
-       if (scsi_cfg1 & HVD) {
-               asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
-               return ADV_ERROR;
-       }
+       asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
 
        /*
-        * Each function in the ASC-38C1600 uses only the SE cable detect and
-        * termination because there are two connectors for each function. Each
-        * function may use either LVD or SE mode. Corresponding the SE automatic
-        * termination control EEPROM bits are used for each function. Each
-        * function has its own EEPROM. If SE automatic control is enabled for
-        * the function, then set the termination value based on a table listed
-        * in a_condor.h.
-        *
-        * If manual termination is specified in the EEPROM for the function,
-        * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
-        * ready to be 'ored' into SCSI_CFG1.
+        * Set the host adapter stopper pointer to point to the new carrier.
         */
-       if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
-               /* SE automatic termination control is enabled. */
-               switch (scsi_cfg1 & C_DET_SE) {
-                       /* TERM_SE_HI: on, TERM_SE_LO: on */
-               case 0x1:
-               case 0x2:
-               case 0x3:
-                       asc_dvc->cfg->termination |= TERM_SE;
-                       break;
+       asc_dvc->icq_sp = new_carrp;
 
-               case 0x0:
-                       if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) {
-                               /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
-                       } else {
-                               /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
-                               asc_dvc->cfg->termination |= TERM_SE_HI;
-                       }
-                       break;
+       if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
+           asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
+               /*
+                * Tickle the RISC to tell it to read its Command Queue Head pointer.
+                */
+               AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
+               if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
+                       /*
+                        * Clear the tickle value. In the ASC-3550 the RISC flag
+                        * command 'clr_tickle_a' does not work unless the host
+                        * value is cleared.
+                        */
+                       AdvWriteByteRegister(iop_base, IOPB_TICKLE,
+                                            ADV_TICKLE_NOP);
                }
+       } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
+               /*
+                * Notify the RISC a carrier is ready by writing the physical
+                * address of the new carrier stopper to the COMMA register.
+                */
+               AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
+                                     le32_to_cpu(new_carrp->carr_pa));
        }
 
-       /*
-        * Clear any set TERM_SE bits.
-        */
-       scsi_cfg1 &= ~TERM_SE;
-
-       /*
-        * Invert the TERM_SE bits and then set 'scsi_cfg1'.
-        */
-       scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
-
-       /*
-        * Clear Big Endian and Terminator Polarity bits and set possibly
-        * modified termination control bits in the Microcode SCSI_CFG1
-        * Register Value.
-        *
-        * Big Endian bit is not used even on big endian machines.
-        */
-       scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
-
-       /*
-        * Set SCSI_CFG1 Microcode Default Value
-        *
-        * Set possibly modified termination control bits in the Microcode
-        * SCSI_CFG1 Register Value.
-        *
-        * The microcode will set the SCSI_CFG1 register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
+       return ADV_SUCCESS;
+}
 
-       /*
-        * Set MEM_CFG Microcode Default Value
-        *
-        * The microcode will set the MEM_CFG register using this value
-        * after it is started below.
-        *
-        * MEM_CFG may be accessed as a word or byte, but only bits 0-7
-        * are defined.
-        *
-        * ASC-38C1600 has 32KB internal memory.
-        *
-        * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
-        * out a special 16K Adv Library and Microcode version. After the issue
-        * resolved, we should turn back to the 32K support. Both a_condor.h and
-        * mcode.sas files also need to be updated.
-        *
-        * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
-        *  BIOS_EN | RAM_SZ_32KB);
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
-                        BIOS_EN | RAM_SZ_16KB);
+/*
+ * Execute a single 'Scsi_Cmnd'.
+ */
+static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
+{
+       int ret, err_code;
+       struct asc_board *boardp = shost_priv(scp->device->host);
 
-       /*
-        * Set SEL_MASK Microcode Default Value
-        *
-        * The microcode will set the SEL_MASK register using this value
-        * after it is started below.
-        */
-       AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
-                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
+       ASC_DBG(1, "scp 0x%p\n", scp);
 
-       /*
-        * Build the carrier freelist.
-        *
-        * Driver must have already allocated memory and set 'carrier_buf'.
-        */
+       if (ASC_NARROW_BOARD(boardp)) {
+               ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
+               struct asc_scsi_q asc_scsi_q;
 
-       ASC_ASSERT(asc_dvc->carrier_buf != NULL);
+               /* asc_build_req() can not return ASC_BUSY. */
+               ret = asc_build_req(boardp, scp, &asc_scsi_q);
+               if (ret == ASC_ERROR) {
+                       ASC_STATS(scp->device->host, build_error);
+                       return ASC_ERROR;
+               }
 
-       carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
-       asc_dvc->carr_freelist = NULL;
-       if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) {
-               buf_size = ADV_CARRIER_BUFSIZE;
+               ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
+               kfree(asc_scsi_q.sg_head);
+               err_code = asc_dvc->err_code;
        } else {
-               buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
+               ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
+               ADV_SCSI_REQ_Q *adv_scsiqp;
+
+               switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
+               case ASC_NOERROR:
+                       ASC_DBG(3, "adv_build_req ASC_NOERROR\n");
+                       break;
+               case ASC_BUSY:
+                       ASC_DBG(1, "adv_build_req ASC_BUSY\n");
+                       /*
+                        * The asc_stats fields 'adv_build_noreq' and
+                        * 'adv_build_nosg' count wide board busy conditions.
+                        * They are updated in adv_build_req and
+                        * adv_get_sglist, respectively.
+                        */
+                       return ASC_BUSY;
+               case ASC_ERROR:
+               default:
+                       ASC_DBG(1, "adv_build_req ASC_ERROR\n");
+                       ASC_STATS(scp->device->host, build_error);
+                       return ASC_ERROR;
+               }
+
+               ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp);
+               err_code = adv_dvc->err_code;
        }
 
-       do {
+       switch (ret) {
+       case ASC_NOERROR:
+               ASC_STATS(scp->device->host, exe_noerror);
                /*
-                * Get physical address for the carrier 'carrp'.
+                * Increment monotonically increasing per device
+                * successful request counter. Wrapping doesn't matter.
                 */
-               contig_len = sizeof(ADV_CARR_T);
-               carr_paddr =
-                   cpu_to_le32(DvcGetPhyAddr
-                               (asc_dvc, NULL, (uchar *)carrp,
-                                (ADV_SDCNT *)&contig_len,
-                                ADV_IS_CARRIER_FLAG));
+               boardp->reqcnt[scp->device->id]++;
+               ASC_DBG(1, "ExeScsiQueue() ASC_NOERROR\n");
+               break;
+       case ASC_BUSY:
+               ASC_STATS(scp->device->host, exe_busy);
+               break;
+       case ASC_ERROR:
+               scmd_printk(KERN_ERR, scp, "ExeScsiQueue() ASC_ERROR, "
+                       "err_code 0x%x\n", err_code);
+               ASC_STATS(scp->device->host, exe_error);
+               scp->result = HOST_BYTE(DID_ERROR);
+               break;
+       default:
+               scmd_printk(KERN_ERR, scp, "ExeScsiQueue() unknown, "
+                       "err_code 0x%x\n", err_code);
+               ASC_STATS(scp->device->host, exe_unknown);
+               scp->result = HOST_BYTE(DID_ERROR);
+               break;
+       }
 
-               buf_size -= sizeof(ADV_CARR_T);
+       ASC_DBG(1, "end\n");
+       return ret;
+}
 
-               /*
-                * If the current carrier is not physically contiguous, then
-                * maybe there was a page crossing. Try the next carrier aligned
-                * start address.
-                */
-               if (contig_len < sizeof(ADV_CARR_T)) {
-                       carrp++;
-                       continue;
-               }
+/*
+ * advansys_queuecommand() - interrupt-driven I/O entrypoint.
+ *
+ * This function always returns 0. Command return status is saved
+ * in the 'scp' result field.
+ */
+static int
+advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
+{
+       struct Scsi_Host *shost = scp->device->host;
+       int asc_res, result = 0;
 
-               carrp->carr_pa = carr_paddr;
-               carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
+       ASC_STATS(shost, queuecommand);
+       scp->scsi_done = done;
 
-               /*
-                * Insert the carrier at the beginning of the freelist.
-                */
-               carrp->next_vpa =
-                   cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
-               asc_dvc->carr_freelist = carrp;
+       asc_res = asc_execute_scsi_cmnd(scp);
 
-               carrp++;
+       switch (asc_res) {
+       case ASC_NOERROR:
+               break;
+       case ASC_BUSY:
+               result = SCSI_MLQUEUE_HOST_BUSY;
+               break;
+       case ASC_ERROR:
+       default:
+               asc_scsi_done(scp);
+               break;
        }
-       while (buf_size > 0);
+
+       return result;
+}
+
+static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
+{
+       PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
+           (PortAddr) (ASC_EISA_CFG_IOP_MASK);
+       return inpw(eisa_cfg_iop);
+}
+
+/*
+ * Return the BIOS address of the adapter at the specified
+ * I/O port and with the specified bus type.
+ */
+static unsigned short __devinit
+AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
+{
+       unsigned short cfg_lsw;
+       unsigned short bios_addr;
 
        /*
-        * Set-up the Host->RISC Initiator Command Queue (ICQ).
+        * The PCI BIOS is re-located by the motherboard BIOS. Because
+        * of this the driver can not determine where a PCI BIOS is
+        * loaded and executes.
         */
-       if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
-               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
-               return ADV_ERROR;
+       if (bus_type & ASC_IS_PCI)
+               return 0;
+
+       if ((bus_type & ASC_IS_EISA) != 0) {
+               cfg_lsw = AscGetEisaChipCfg(iop_base);
+               cfg_lsw &= 0x000F;
+               bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
+               return bios_addr;
        }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
 
-       /*
-        * The first command issued will be placed in the stopper carrier.
-        */
-       asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+       cfg_lsw = AscGetChipCfgLsw(iop_base);
 
        /*
-        * Set RISC ICQ physical address start value. Initialize the
-        * COMMA register to the same value otherwise the RISC will
-        * prematurely detect a command is available.
+        *  ISA PnP uses the top bit as the 32K BIOS flag
         */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
-       AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
-                             le32_to_cpu(asc_dvc->icq_sp->carr_pa));
+       if (bus_type == ASC_IS_ISAPNP)
+               cfg_lsw &= 0x7FFF;
+       bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
+       return bios_addr;
+}
 
-       /*
-        * Set-up the RISC->Host Initiator Response Queue (IRQ).
-        */
-       if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
-               asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
-               return ADV_ERROR;
+static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
+{
+       ushort cfg_lsw;
+
+       if (AscGetChipScsiID(iop_base) == new_host_id) {
+               return (new_host_id);
        }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
+       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));
+}
 
-       /*
-        * The first command completed by the RISC will be placed in
-        * the stopper.
-        *
-        * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
-        * completed the RISC will set the ASC_RQ_STOPPER bit.
-        */
-       asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
+{
+       unsigned char sc;
 
-       /*
-        * Set RISC IRQ physical address start value.
-        */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
-       asc_dvc->carr_pending_cnt = 0;
+       AscSetBank(iop_base, 1);
+       sc = inp(iop_base + IOP_REG_SC);
+       AscSetBank(iop_base, 0);
+       return sc;
+}
 
-       AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
-                            (ADV_INTR_ENABLE_HOST_INTR |
-                             ADV_INTR_ENABLE_GLOBAL_INTR));
-       AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
-       AdvWriteWordRegister(iop_base, IOPW_PC, word);
+static unsigned char __devinit
+AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
+{
+       if (bus_type & ASC_IS_EISA) {
+               PortAddr eisa_iop;
+               unsigned char revision;
+               eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
+                   (PortAddr) ASC_EISA_REV_IOP_MASK;
+               revision = inp(eisa_iop);
+               return ASC_CHIP_MIN_VER_EISA - 1 + revision;
+       }
+       return AscGetChipVerNo(iop_base);
+}
 
-       /* finally, finally, gentlemen, start your engine */
-       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
+#ifdef CONFIG_ISA
+static void __devinit 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));
+       }
+}
+#endif /* CONFIG_ISA */
 
-       /*
-        * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
-        * Resets should be performed. The RISC has to be running
-        * to issue a SCSI Bus Reset.
-        */
-       if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
-               /*
-                * If the BIOS Signature is present in memory, restore the
-                * per TID microcode operating variables.
-                */
-               if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
-                   0x55AA) {
-                       /*
-                        * Restore per TID negotiated values.
-                        */
-                       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
-                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
-                                        tagqng_able);
-                       for (tid = 0; tid <= ASC_MAX_TID; tid++) {
-                               AdvWriteByteLram(iop_base,
-                                                ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                                                max_cmd[tid]);
-                       }
-               } else {
-                       if (AdvResetSB(asc_dvc) != ADV_TRUE) {
-                               warn_code = ASC_WARN_BUSRESET_ERROR;
+static int AscStopQueueExe(PortAddr iop_base)
+{
+       int 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);
                        }
-               }
+                       mdelay(100);
+               } while (count++ < 20);
        }
+       return (0);
+}
 
-       return warn_code;
+static ASC_DCNT __devinit 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;
 }
 
-/*
- * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
- * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
- * all of this is done.
- *
- * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
- *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
- *
- * Note: Chip is stopped on entry.
- */
-static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
+#ifdef CONFIG_ISA
+static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
 {
-       AdvPortAddr iop_base;
-       ushort warn_code;
-       ADVEEP_3550_CONFIG eep_config;
-       int i;
+       ushort channel;
 
-       iop_base = asc_dvc->iop_base;
+       channel = AscGetChipCfgLsw(iop_base) & 0x0003;
+       if (channel == 0x03)
+               return (0);
+       else if (channel == 0x00)
+               return (7);
+       return (channel + 4);
+}
 
-       warn_code = 0;
+static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
+{
+       ushort cfg_lsw;
+       uchar value;
 
-       /*
-        * Read the board's EEPROM configuration.
-        *
-        * Set default values if a bad checksum is found.
-        */
-       if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
-               warn_code |= ASC_WARN_EEPROM_CHKSUM;
+       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;
+}
 
-               /*
-                * Set EEPROM default values.
-                */
-               for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) {
-                       *((uchar *)&eep_config + i) =
-                           *((uchar *)&Default_3550_EEPROM_Config + i);
-               }
+static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
+{
+       uchar speed_value;
 
-               /*
-                * Assume the 6 byte board serial number that was read
-                * from EEPROM is correct even if the EEPROM checksum
-                * failed.
-                */
-               eep_config.serial_number_word3 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
+       AscSetBank(iop_base, 1);
+       speed_value = AscReadChipDmaSpeed(iop_base);
+       speed_value &= 0x07;
+       AscSetBank(iop_base, 0);
+       return speed_value;
+}
 
-               eep_config.serial_number_word2 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
+static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
+{
+       speed_value &= 0x07;
+       AscSetBank(iop_base, 1);
+       AscWriteChipDmaSpeed(iop_base, speed_value);
+       AscSetBank(iop_base, 0);
+       return AscGetIsaDmaSpeed(iop_base);
+}
+#endif /* CONFIG_ISA */
 
-               eep_config.serial_number_word1 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
+static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
+{
+       int i;
+       PortAddr iop_base;
+       ushort warn_code;
+       uchar chip_version;
 
-               AdvSet3550EEPConfig(iop_base, &eep_config);
+       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;
        }
-       /*
-        * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
-        * EEPROM configuration that was read.
-        *
-        * This is the mapping of EEPROM fields to Adv Library fields.
-        */
-       asc_dvc->wdtr_able = eep_config.wdtr_able;
-       asc_dvc->sdtr_able = eep_config.sdtr_able;
-       asc_dvc->ultra_able = eep_config.ultra_able;
-       asc_dvc->tagqng_able = eep_config.tagqng_able;
-       asc_dvc->cfg->disc_enable = eep_config.disc_enable;
-       asc_dvc->max_host_qng = eep_config.max_host_qng;
-       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
-       asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
-       asc_dvc->start_motor = eep_config.start_motor;
-       asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
-       asc_dvc->bios_ctrl = eep_config.bios_ctrl;
-       asc_dvc->no_scam = eep_config.scam_tolerant;
-       asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
-       asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
-       asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
-
-       /*
-        * Set the host maximum queuing (max. 253, min. 16) and the per device
-        * maximum queuing (max. 63, min. 4).
-        */
-       if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
-               eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
-       } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
-               /* If the value is zero, assume it is uninitialized. */
-               if (eep_config.max_host_qng == 0) {
-                       eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
-               } else {
-                       eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
+       AscSetChipControl(iop_base, CC_HALT);
+       AscSetChipStatus(iop_base, 0);
+       asc_dvc->bug_fix_cntl = 0;
+       asc_dvc->pci_fix_asyn_xfer = 0;
+       asc_dvc->pci_fix_asyn_xfer_always = 0;
+       /* asc_dvc->init_state initalized in AscInitGetConfig(). */
+       asc_dvc->sdtr_done = 0;
+       asc_dvc->cur_total_qng = 0;
+       asc_dvc->is_in_int = 0;
+       asc_dvc->in_critical_cnt = 0;
+       asc_dvc->last_q_shortage = 0;
+       asc_dvc->use_tagged_qng = 0;
+       asc_dvc->no_scam = 0;
+       asc_dvc->unit_not_ready = 0;
+       asc_dvc->queue_full_or_busy = 0;
+       asc_dvc->redo_scam = 0;
+       asc_dvc->res2 = 0;
+       asc_dvc->min_sdtr_index = 0;
+       asc_dvc->cfg->can_tagged_qng = 0;
+       asc_dvc->cfg->cmd_qng_enabled = 0;
+       asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
+       asc_dvc->init_sdtr = 0;
+       asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
+       asc_dvc->scsi_reset_wait = 3;
+       asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
+       asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
+       asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
+       asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
+       asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
+       chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
+       asc_dvc->cfg->chip_version = chip_version;
+       asc_dvc->sdtr_period_tbl = asc_syn_xfer_period;
+       asc_dvc->max_sdtr_index = 7;
+       if ((asc_dvc->bus_type & ASC_IS_PCI) &&
+           (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
+               asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
+               asc_dvc->sdtr_period_tbl = asc_syn_ultra_xfer_period;
+               asc_dvc->max_sdtr_index = 15;
+               if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
+                       AscSetExtraControl(iop_base,
+                                          (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
+               } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
+                       AscSetExtraControl(iop_base,
+                                          (SEC_ACTIVE_NEGATE |
+                                           SEC_ENABLE_FILTER));
                }
        }
+       if (asc_dvc->bus_type == ASC_IS_PCI) {
+               AscSetExtraControl(iop_base,
+                                  (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
+       }
 
-       if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
-               eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
-       } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
-               /* If the value is zero, assume it is uninitialized. */
-               if (eep_config.max_dvc_qng == 0) {
-                       eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
-               } else {
-                       eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
+       asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
+#ifdef CONFIG_ISA
+       if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
+               if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
+                       AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
+                       asc_dvc->bus_type = ASC_IS_ISAPNP;
                }
+               asc_dvc->cfg->isa_dma_channel =
+                   (uchar)AscGetIsaDmaChannel(iop_base);
+       }
+#endif /* CONFIG_ISA */
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               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 *)0L;
+               asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
+               asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
        }
+       return warn_code;
+}
 
-       /*
-        * If 'max_dvc_qng' is greater than 'max_host_qng', then
-        * set 'max_dvc_qng' to 'max_host_qng'.
-        */
-       if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
-               eep_config.max_dvc_qng = eep_config.max_host_qng;
+static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
+{
+       int retry;
+
+       for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) {
+               unsigned char read_back;
+               AscSetChipEEPCmd(iop_base, cmd_reg);
+               mdelay(1);
+               read_back = AscGetChipEEPCmd(iop_base);
+               if (read_back == cmd_reg)
+                       return 1;
        }
+       return 0;
+}
 
-       /*
-        * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
-        * values based on possibly adjusted EEPROM values.
-        */
-       asc_dvc->max_host_qng = eep_config.max_host_qng;
-       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+static void __devinit AscWaitEEPRead(void)
+{
+       mdelay(1);
+}
 
-       /*
-        * If the EEPROM 'termination' field is set to automatic (0), then set
-        * the ADV_DVC_CFG 'termination' field to automatic also.
-        *
-        * If the termination is specified with a non-zero 'termination'
-        * value check that a legal value is set and set the ADV_DVC_CFG
-        * 'termination' field appropriately.
-        */
-       if (eep_config.termination == 0) {
-               asc_dvc->cfg->termination = 0;  /* auto termination */
-       } else {
-               /* Enable manual control with low off / high off. */
-               if (eep_config.termination == 1) {
-                       asc_dvc->cfg->termination = TERM_CTL_SEL;
+static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
+{
+       ushort read_wval;
+       uchar cmd_reg;
 
-                       /* Enable manual control with low off / high on. */
-               } else if (eep_config.termination == 2) {
-                       asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
+       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;
+}
 
-                       /* Enable manual control with low on / high on. */
-               } else if (eep_config.termination == 3) {
-                       asc_dvc->cfg->termination =
-                           TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
-               } else {
+static ushort __devinit
+AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+{
+       ushort wval;
+       ushort sum;
+       ushort *wbuf;
+       int cfg_beg;
+       int cfg_end;
+       int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
+       int s_addr;
+
+       wbuf = (ushort *)cfg_buf;
+       sum = 0;
+       /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
+       for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+               *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
+               sum += *wbuf;
+       }
+       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);
+               if (s_addr <= uchar_end_in_config) {
                        /*
-                        * The EEPROM 'termination' field contains a bad value. Use
-                        * automatic termination instead.
+                        * Swap all char fields - must unswap bytes already swapped
+                        * by AscReadEEPWord().
                         */
-                       asc_dvc->cfg->termination = 0;
-                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+                       *wbuf = le16_to_cpu(wval);
+               } else {
+                       /* Don't swap word field at the end - cntl field. */
+                       *wbuf = wval;
                }
-       }
-
-       return warn_code;
-}
-
-/*
- * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
- * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
- * all of this is done.
- *
- * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
- *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
- *
- * Note: Chip is stopped on entry.
- */
-static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
+               sum += wval;    /* Checksum treats all EEPROM data as words. */
+       }
+       /*
+        * Read the checksum word which will be compared against 'sum'
+        * by the caller. Word field already swapped.
+        */
+       *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
+       return sum;
+}
+
+static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
 {
-       AdvPortAddr iop_base;
-       ushort warn_code;
-       ADVEEP_38C0800_CONFIG eep_config;
-       int i;
-       uchar tid, termination;
-       ushort sdtr_speed = 0;
+       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);
+       AscSetChipLramAddr(iop_base, q_addr);
+       AscSetChipLramData(iop_base, 0x55AA);
+       mdelay(10);
+       AscSetChipLramAddr(iop_base, q_addr);
+       if (AscGetChipLramData(iop_base) == 0x55AA) {
+               sta = 1;
+               AscWriteLramWord(iop_base, q_addr, saved_word);
+       }
+       return (sta);
+}
 
-       warn_code = 0;
+static void __devinit AscWaitEEPWrite(void)
+{
+       mdelay(20);
+}
 
-       /*
-        * Read the board's EEPROM configuration.
-        *
-        * Set default values if a bad checksum is found.
-        */
-       if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
-           eep_config.check_sum) {
-               warn_code |= ASC_WARN_EEPROM_CHKSUM;
+static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
+{
+       ushort read_back;
+       int retry;
 
-               /*
-                * Set EEPROM default values.
-                */
-               for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) {
-                       *((uchar *)&eep_config + i) =
-                           *((uchar *)&Default_38C0800_EEPROM_Config + i);
+       retry = 0;
+       while (TRUE) {
+               AscSetChipEEPData(iop_base, data_reg);
+               mdelay(1);
+               read_back = AscGetChipEEPData(iop_base);
+               if (read_back == data_reg) {
+                       return (1);
                }
+               if (retry++ > ASC_EEP_MAX_RETRY) {
+                       return (0);
+               }
+       }
+}
 
-               /*
-                * Assume the 6 byte board serial number that was read
-                * from EEPROM is correct even if the EEPROM checksum
-                * failed.
-                */
-               eep_config.serial_number_word3 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
-
-               eep_config.serial_number_word2 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
-
-               eep_config.serial_number_word1 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
+static ushort __devinit
+AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
+{
+       ushort read_wval;
 
-               AdvSet38C0800EEPConfig(iop_base, &eep_config);
+       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));
        }
-       /*
-        * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
-        * EEPROM configuration that was read.
-        *
-        * This is the mapping of EEPROM fields to Adv Library fields.
-        */
-       asc_dvc->wdtr_able = eep_config.wdtr_able;
-       asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
-       asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
-       asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
-       asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
-       asc_dvc->tagqng_able = eep_config.tagqng_able;
-       asc_dvc->cfg->disc_enable = eep_config.disc_enable;
-       asc_dvc->max_host_qng = eep_config.max_host_qng;
-       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
-       asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
-       asc_dvc->start_motor = eep_config.start_motor;
-       asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
-       asc_dvc->bios_ctrl = eep_config.bios_ctrl;
-       asc_dvc->no_scam = eep_config.scam_tolerant;
-       asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
-       asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
-       asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
+       return (read_wval);
+}
 
-       /*
-        * For every Target ID if any of its 'sdtr_speed[1234]' bits
-        * are set, then set an 'sdtr_able' bit for it.
-        */
-       asc_dvc->sdtr_able = 0;
-       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-               if (tid == 0) {
-                       sdtr_speed = asc_dvc->sdtr_speed1;
-               } else if (tid == 4) {
-                       sdtr_speed = asc_dvc->sdtr_speed2;
-               } else if (tid == 8) {
-                       sdtr_speed = asc_dvc->sdtr_speed3;
-               } else if (tid == 12) {
-                       sdtr_speed = asc_dvc->sdtr_speed4;
-               }
-               if (sdtr_speed & ADV_MAX_TID) {
-                       asc_dvc->sdtr_able |= (1 << tid);
-               }
-               sdtr_speed >>= 4;
-       }
+static int __devinit
+AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+{
+       int n_error;
+       ushort *wbuf;
+       ushort word;
+       ushort sum;
+       int s_addr;
+       int cfg_beg;
+       int cfg_end;
+       int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
 
-       /*
-        * Set the host maximum queuing (max. 253, min. 16) and the per device
-        * maximum queuing (max. 63, min. 4).
-        */
-       if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
-               eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
-       } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
-               /* If the value is zero, assume it is uninitialized. */
-               if (eep_config.max_host_qng == 0) {
-                       eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
-               } else {
-                       eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
+       wbuf = (ushort *)cfg_buf;
+       n_error = 0;
+       sum = 0;
+       /* Write two config words; AscWriteEEPWord() will swap bytes. */
+       for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+               sum += *wbuf;
+               if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
+                       n_error++;
                }
        }
-
-       if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
-               eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
-       } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
-               /* If the value is zero, assume it is uninitialized. */
-               if (eep_config.max_dvc_qng == 0) {
-                       eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+       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++) {
+               if (s_addr <= uchar_end_in_config) {
+                       /*
+                        * This is a char field. Swap char fields before they are
+                        * swapped again by AscWriteEEPWord().
+                        */
+                       word = cpu_to_le16(*wbuf);
+                       if (word !=
+                           AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
+                               n_error++;
+                       }
                } else {
-                       eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
+                       /* Don't swap word field at the end - cntl field. */
+                       if (*wbuf !=
+                           AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
+                               n_error++;
+                       }
                }
+               sum += *wbuf;   /* Checksum calculated from word values. */
        }
-
-       /*
-        * If 'max_dvc_qng' is greater than 'max_host_qng', then
-        * set 'max_dvc_qng' to 'max_host_qng'.
-        */
-       if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
-               eep_config.max_dvc_qng = eep_config.max_host_qng;
+       /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
+       *wbuf = sum;
+       if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
+               n_error++;
        }
 
+       /* Read EEPROM back again. */
+       wbuf = (ushort *)cfg_buf;
        /*
-        * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
-        * values based on possibly adjusted EEPROM values.
-        */
-       asc_dvc->max_host_qng = eep_config.max_host_qng;
-       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
-
-       /*
-        * If the EEPROM 'termination' field is set to automatic (0), then set
-        * the ADV_DVC_CFG 'termination' field to automatic also.
-        *
-        * If the termination is specified with a non-zero 'termination'
-        * value check that a legal value is set and set the ADV_DVC_CFG
-        * 'termination' field appropriately.
+        * Read two config words; Byte-swapping done by AscReadEEPWord().
         */
-       if (eep_config.termination_se == 0) {
-               termination = 0;        /* auto termination for SE */
+       for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+               if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
+                       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 {
-               /* Enable manual control with low off / high off. */
-               if (eep_config.termination_se == 1) {
-                       termination = 0;
-
-                       /* Enable manual control with low off / high on. */
-               } else if (eep_config.termination_se == 2) {
-                       termination = TERM_SE_HI;
-
-                       /* Enable manual control with low on / high on. */
-               } else if (eep_config.termination_se == 3) {
-                       termination = TERM_SE;
-               } 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++) {
+               if (s_addr <= uchar_end_in_config) {
                        /*
-                        * The EEPROM 'termination_se' field contains a bad value.
-                        * Use automatic termination instead.
+                        * Swap all char fields. Must unswap bytes already swapped
+                        * by AscReadEEPWord().
                         */
-                       termination = 0;
-                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+                       word =
+                           le16_to_cpu(AscReadEEPWord
+                                       (iop_base, (uchar)s_addr));
+               } else {
+                       /* Don't swap word field at the end - cntl field. */
+                       word = AscReadEEPWord(iop_base, (uchar)s_addr);
+               }
+               if (*wbuf != word) {
+                       n_error++;
                }
        }
+       /* Read checksum; Byte swapping not needed. */
+       if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
+               n_error++;
+       }
+       return n_error;
+}
 
-       if (eep_config.termination_lvd == 0) {
-               asc_dvc->cfg->termination = termination;        /* auto termination for LVD */
-       } else {
-               /* Enable manual control with low off / high off. */
-               if (eep_config.termination_lvd == 1) {
-                       asc_dvc->cfg->termination = termination;
-
-                       /* Enable manual control with low off / high on. */
-               } else if (eep_config.termination_lvd == 2) {
-                       asc_dvc->cfg->termination = termination | TERM_LVD_HI;
+static int __devinit
+AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+{
+       int retry;
+       int n_error;
 
-                       /* Enable manual control with low on / high on. */
-               } else if (eep_config.termination_lvd == 3) {
-                       asc_dvc->cfg->termination = termination | TERM_LVD;
-               } else {
-                       /*
-                        * The EEPROM 'termination_lvd' field contains a bad value.
-                        * Use automatic termination instead.
-                        */
-                       asc_dvc->cfg->termination = termination;
-                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+       retry = 0;
+       while (TRUE) {
+               if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
+                                                  bus_type)) == 0) {
+                       break;
+               }
+               if (++retry > ASC_EEP_MAX_RETRY) {
+                       break;
                }
        }
-
-       return warn_code;
+       return n_error;
 }
 
-/*
- * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
- * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
- * all of this is done.
- *
- * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
- *
- * For a non-fatal error return a warning code. If there are no warnings
- * then 0 is returned.
- *
- * Note: Chip is stopped on entry.
- */
-static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
+static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
 {
-       AdvPortAddr iop_base;
+       ASCEEP_CONFIG eep_config_buf;
+       ASCEEP_CONFIG *eep_config;
+       PortAddr iop_base;
+       ushort chksum;
        ushort warn_code;
-       ADVEEP_38C1600_CONFIG eep_config;
+       ushort cfg_msw, cfg_lsw;
        int i;
-       uchar tid, termination;
-       ushort sdtr_speed = 0;
+       int write_eep = 0;
 
        iop_base = asc_dvc->iop_base;
-
        warn_code = 0;
-
-       /*
-        * Read the board's EEPROM configuration.
-        *
-        * Set default values if a bad checksum is found.
-        */
-       if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
-           eep_config.check_sum) {
-               warn_code |= ASC_WARN_EEPROM_CHKSUM;
-
-               /*
-                * Set EEPROM default values.
-                */
-               for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) {
-                       if (i == 1
-                           && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) !=
-                           0) {
-                               /*
-                                * Set Function 1 EEPROM Word 0 MSB
-                                *
-                                * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11)
-                                * EEPROM bits.
-                                *
-                                * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and
-                                * old Mac system booting problem. The Expansion ROM must
-                                * be disabled in Function 1 for these systems.
-                                *
-                                */
-                               *((uchar *)&eep_config + i) =
-                                   ((*
-                                     ((uchar *)&Default_38C1600_EEPROM_Config
-                                      +
-                                      i)) &
-                                    (~
-                                     (((ADV_EEPROM_BIOS_ENABLE |
-                                        ADV_EEPROM_INTAB) >> 8) & 0xFF)));
-
-                               /*
-                                * Set the INTAB (bit 11) if the GPIO 0 input indicates
-                                * the Function 1 interrupt line is wired to INTA.
-                                *
-                                * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
-                                *   1 - Function 1 interrupt line wired to INT A.
-                                *   0 - Function 1 interrupt line wired to INT B.
-                                *
-                                * Note: Adapter boards always have Function 0 wired to INTA.
-                                * Put all 5 GPIO bits in input mode and then read
-                                * their input values.
-                                */
-                               AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL,
-                                                    0);
-                               if (AdvReadByteRegister
-                                   (iop_base, IOPB_GPIO_DATA) & 0x01) {
-                                       /* Function 1 interrupt wired to INTA; Set EEPROM bit. */
-                                       *((uchar *)&eep_config + i) |=
-                                           ((ADV_EEPROM_INTAB >> 8) & 0xFF);
-                               }
-                       } else {
-                               *((uchar *)&eep_config + i) =
-                                   *((uchar *)&Default_38C1600_EEPROM_Config
-                                     + i);
+       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(asc_dvc);
+               mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
+       }
+       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 *)&eep_config_buf;
+       cfg_msw = AscGetChipCfgMsw(iop_base);
+       cfg_lsw = AscGetChipCfgLsw(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);
+       }
+       chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
+       ASC_DBG(1, "chksum 0x%x\n", chksum);
+       if (chksum == 0) {
+               chksum = 0xaa55;
+       }
+       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);
                        }
                }
-
-               /*
-                * Assume the 6 byte board serial number that was read
-                * from EEPROM is correct even if the EEPROM checksum
-                * failed.
-                */
-               eep_config.serial_number_word3 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
-
-               eep_config.serial_number_word2 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
-
-               eep_config.serial_number_word1 =
-                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
-
-               AdvSet38C1600EEPConfig(iop_base, &eep_config);
        }
-
-       /*
-        * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
-        * EEPROM configuration that was read.
-        *
-        * This is the mapping of EEPROM fields to Adv Library fields.
-        */
-       asc_dvc->wdtr_able = eep_config.wdtr_able;
-       asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
-       asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
-       asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
-       asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
-       asc_dvc->ppr_able = 0;
-       asc_dvc->tagqng_able = eep_config.tagqng_able;
-       asc_dvc->cfg->disc_enable = eep_config.disc_enable;
-       asc_dvc->max_host_qng = eep_config.max_host_qng;
-       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
-       asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
-       asc_dvc->start_motor = eep_config.start_motor;
-       asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
-       asc_dvc->bios_ctrl = eep_config.bios_ctrl;
-       asc_dvc->no_scam = eep_config.scam_tolerant;
-
-       /*
-        * For every Target ID if any of its 'sdtr_speed[1234]' bits
-        * are set, then set an 'sdtr_able' bit for it.
-        */
-       asc_dvc->sdtr_able = 0;
-       for (tid = 0; tid <= ASC_MAX_TID; tid++) {
-               if (tid == 0) {
-                       sdtr_speed = asc_dvc->sdtr_speed1;
-               } else if (tid == 4) {
-                       sdtr_speed = asc_dvc->sdtr_speed2;
-               } else if (tid == 8) {
-                       sdtr_speed = asc_dvc->sdtr_speed3;
-               } else if (tid == 12) {
-                       sdtr_speed = asc_dvc->sdtr_speed4;
+       eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
+       eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
+       ASC_DBG(1, "eep_config->chksum 0x%x\n", eep_config->chksum);
+       if (chksum != eep_config->chksum) {
+               if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
+                   ASC_CHIP_VER_PCI_ULTRA_3050) {
+                       ASC_DBG(1, "chksum error ignored; EEPROM-less board\n");
+                       eep_config->init_sdtr = 0xFF;
+                       eep_config->disc_enable = 0xFF;
+                       eep_config->start_motor = 0xFF;
+                       eep_config->use_cmd_qng = 0;
+                       eep_config->max_total_qng = 0xF0;
+                       eep_config->max_tag_qng = 0x20;
+                       eep_config->cntl = 0xBFFF;
+                       ASC_EEP_SET_CHIP_ID(eep_config, 7);
+                       eep_config->no_scam = 0;
+                       eep_config->adapter_info[0] = 0;
+                       eep_config->adapter_info[1] = 0;
+                       eep_config->adapter_info[2] = 0;
+                       eep_config->adapter_info[3] = 0;
+                       eep_config->adapter_info[4] = 0;
+                       /* Indicate EEPROM-less board. */
+                       eep_config->adapter_info[5] = 0xBB;
+               } else {
+                       ASC_PRINT
+                           ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
+                       write_eep = 1;
+                       warn_code |= ASC_WARN_EEPROM_CHKSUM;
                }
-               if (sdtr_speed & ASC_MAX_TID) {
-                       asc_dvc->sdtr_able |= (1 << tid);
+       }
+       asc_dvc->cfg->sdtr_enable = 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 = ASC_EEP_GET_DMA_SPD(eep_config);
+       asc_dvc->start_motor = eep_config->start_motor;
+       asc_dvc->dvc_cntl = eep_config->cntl;
+       asc_dvc->no_scam = eep_config->no_scam;
+       asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
+       asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
+       asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
+       asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
+       asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
+       asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
+       if (!AscTestExternalLram(asc_dvc)) {
+               if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
+                    ASC_IS_PCI_ULTRA)) {
+                       eep_config->max_total_qng =
+                           ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
+                       eep_config->max_tag_qng =
+                           ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
+               } else {
+                       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;
                }
-               sdtr_speed >>= 4;
+       } else {
+       }
+       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_EEP_SET_CHIP_ID(eep_config,
+                           ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
+       asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
+       if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
+           !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
+               asc_dvc->min_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
        }
 
-       /*
-        * Set the host maximum queuing (max. 253, min. 16) and the per device
-        * maximum queuing (max. 63, min. 4).
-        */
-       if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
-               eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
-       } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
-               /* If the value is zero, assume it is uninitialized. */
-               if (eep_config.max_host_qng == 0) {
-                       eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
-               } else {
-                       eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
-               }
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
+               asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
+               asc_dvc->cfg->sdtr_period_offset[i] =
+                   (uchar)(ASC_DEF_SDTR_OFFSET |
+                           (asc_dvc->min_sdtr_index << 4));
        }
-
-       if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
-               eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
-       } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
-               /* If the value is zero, assume it is uninitialized. */
-               if (eep_config.max_dvc_qng == 0) {
-                       eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+       eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+       if (write_eep) {
+               if ((i = AscSetEEPConfig(iop_base, eep_config,
+                                    asc_dvc->bus_type)) != 0) {
+                       ASC_PRINT1
+                           ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
+                            i);
                } else {
-                       eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
+                       ASC_PRINT
+                           ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
                }
        }
+       return (warn_code);
+}
 
-       /*
-        * If 'max_dvc_qng' is greater than 'max_host_qng', then
-        * set 'max_dvc_qng' to 'max_host_qng'.
-        */
-       if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
-               eep_config.max_dvc_qng = eep_config.max_host_qng;
-       }
+static int __devinit AscInitGetConfig(struct Scsi_Host *shost)
+{
+       struct asc_board *board = shost_priv(shost);
+       ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
+       unsigned short warn_code = 0;
 
-       /*
-        * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
-        * values based on possibly adjusted EEPROM values.
-        */
-       asc_dvc->max_host_qng = eep_config.max_host_qng;
-       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+       asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
+       if (asc_dvc->err_code != 0)
+               return asc_dvc->err_code;
 
-       /*
-        * If the EEPROM 'termination' field is set to automatic (0), then set
-        * the ASC_DVC_CFG 'termination' field to automatic also.
-        *
-        * If the termination is specified with a non-zero 'termination'
-        * value check that a legal value is set and set the ASC_DVC_CFG
-        * 'termination' field appropriately.
-        */
-       if (eep_config.termination_se == 0) {
-               termination = 0;        /* auto termination for SE */
+       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 > ASC_MAX_SCSI_RESET_WAIT)
+                       asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
        } else {
-               /* Enable manual control with low off / high off. */
-               if (eep_config.termination_se == 1) {
-                       termination = 0;
-
-                       /* Enable manual control with low off / high on. */
-               } else if (eep_config.termination_se == 2) {
-                       termination = TERM_SE_HI;
-
-                       /* Enable manual control with low on / high on. */
-               } else if (eep_config.termination_se == 3) {
-                       termination = TERM_SE;
-               } else {
-                       /*
-                        * The EEPROM 'termination_se' field contains a bad value.
-                        * Use automatic termination instead.
-                        */
-                       termination = 0;
-                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
-               }
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
        }
 
-       if (eep_config.termination_lvd == 0) {
-               asc_dvc->cfg->termination = termination;        /* auto termination for LVD */
-       } else {
-               /* Enable manual control with low off / high off. */
-               if (eep_config.termination_lvd == 1) {
-                       asc_dvc->cfg->termination = termination;
-
-                       /* Enable manual control with low off / high on. */
-               } else if (eep_config.termination_lvd == 2) {
-                       asc_dvc->cfg->termination = termination | TERM_LVD_HI;
-
-                       /* Enable manual control with low on / high on. */
-               } else if (eep_config.termination_lvd == 3) {
-                       asc_dvc->cfg->termination = termination | TERM_LVD;
-               } else {
-                       /*
-                        * The EEPROM 'termination_lvd' field contains a bad value.
-                        * Use automatic termination instead.
-                        */
-                       asc_dvc->cfg->termination = termination;
-                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
-               }
+       switch (warn_code) {
+       case 0: /* No error */
+               break;
+       case ASC_WARN_IO_PORT_ROTATE:
+               shost_printk(KERN_WARNING, shost, "I/O port address "
+                               "modified\n");
+               break;
+       case ASC_WARN_AUTO_CONFIG:
+               shost_printk(KERN_WARNING, shost, "I/O port increment switch "
+                               "enabled\n");
+               break;
+       case ASC_WARN_EEPROM_CHKSUM:
+               shost_printk(KERN_WARNING, shost, "EEPROM checksum error\n");
+               break;
+       case ASC_WARN_IRQ_MODIFIED:
+               shost_printk(KERN_WARNING, shost, "IRQ modified\n");
+               break;
+       case ASC_WARN_CMD_QNG_CONFLICT:
+               shost_printk(KERN_WARNING, shost, "tag queuing enabled w/o "
+                               "disconnects\n");
+               break;
+       default:
+               shost_printk(KERN_WARNING, shost, "unknown warning: 0x%x\n",
+                               warn_code);
+               break;
        }
 
-       return warn_code;
+       if (asc_dvc->err_code != 0)
+               shost_printk(KERN_ERR, shost, "error 0x%x at init_state "
+                       "0x%x\n", asc_dvc->err_code, asc_dvc->init_state);
+
+       return asc_dvc->err_code;
 }
 
-/*
- * Read EEPROM configuration into the specified buffer.
- *
- * Return a checksum based on the EEPROM configuration read.
- */
-static ushort __init
-AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
+static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
 {
-       ushort wval, chksum;
-       ushort *wbuf;
-       int eep_addr;
-       ushort *charfields;
+       struct asc_board *board = shost_priv(shost);
+       ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
+       PortAddr iop_base = asc_dvc->iop_base;
+       unsigned short cfg_msw;
+       unsigned short warn_code = 0;
 
-       charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
-       wbuf = (ushort *)cfg_buf;
-       chksum = 0;
+       asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
+       if (asc_dvc->err_code != 0)
+               return asc_dvc->err_code;
+       if (!AscFindSignature(asc_dvc->iop_base)) {
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+               return asc_dvc->err_code;
+       }
 
-       for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
-            eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
-               wval = AdvReadEEPWord(iop_base, eep_addr);
-               chksum += wval; /* Checksum is calculated from word values. */
-               if (*charfields++) {
-                       *wbuf = le16_to_cpu(wval);
+       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 ((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 (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
+               warn_code |= ASC_WARN_AUTO_CONFIG;
+       }
+#ifdef CONFIG_PCI
+       if (asc_dvc->bus_type & ASC_IS_PCI) {
+               cfg_msw &= 0xFFC0;
+               AscSetChipCfgMsw(iop_base, cfg_msw);
+               if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
                } else {
-                       *wbuf = wval;
+                       if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
+                           (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
+                               asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
+                               asc_dvc->bug_fix_cntl |=
+                                   ASC_BUG_FIX_ASYN_USE_SYN;
+                       }
+               }
+       } else
+#endif /* CONFIG_PCI */
+       if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
+               if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
+                   == ASC_CHIP_VER_ASYN_BUG) {
+                       asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
                }
        }
-       /* Read checksum word. */
-       *wbuf = AdvReadEEPWord(iop_base, eep_addr);
-       wbuf++;
-       charfields++;
+       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;
+       }
+#ifdef CONFIG_ISA
+       if (asc_dvc->bus_type & ASC_IS_ISA) {
+               AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
+               AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
+       }
+#endif /* CONFIG_ISA */
 
-       /* Read rest of EEPROM not covered by the checksum. */
-       for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
-            eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
-               *wbuf = AdvReadEEPWord(iop_base, eep_addr);
-               if (*charfields++) {
-                       *wbuf = le16_to_cpu(*wbuf);
-               }
+       asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
+
+       switch (warn_code) {
+       case 0: /* No error. */
+               break;
+       case ASC_WARN_IO_PORT_ROTATE:
+               shost_printk(KERN_WARNING, shost, "I/O port address "
+                               "modified\n");
+               break;
+       case ASC_WARN_AUTO_CONFIG:
+               shost_printk(KERN_WARNING, shost, "I/O port increment switch "
+                               "enabled\n");
+               break;
+       case ASC_WARN_EEPROM_CHKSUM:
+               shost_printk(KERN_WARNING, shost, "EEPROM checksum error\n");
+               break;
+       case ASC_WARN_IRQ_MODIFIED:
+               shost_printk(KERN_WARNING, shost, "IRQ modified\n");
+               break;
+       case ASC_WARN_CMD_QNG_CONFLICT:
+               shost_printk(KERN_WARNING, shost, "tag queuing w/o "
+                               "disconnects\n");
+               break;
+       default:
+               shost_printk(KERN_WARNING, shost, "unknown warning: 0x%x\n",
+                               warn_code);
+               break;
        }
-       return chksum;
+
+       if (asc_dvc->err_code != 0)
+               shost_printk(KERN_ERR, shost, "error 0x%x at init_state "
+                       "0x%x\n", asc_dvc->err_code, asc_dvc->init_state);
+
+       return asc_dvc->err_code;
 }
 
 /*
- * Read EEPROM configuration into the specified buffer.
+ * EEPROM Configuration.
  *
- * Return a checksum based on the EEPROM configuration read.
+ * All drivers should use this structure to set the default EEPROM
+ * configuration. The BIOS now uses this structure when it is built.
+ * Additional structure information can be found in a_condor.h where
+ * the structure is defined.
+ *
+ * The *_Field_IsChar structs are needed to correct for endianness.
+ * These values are read from the board 16 bits at a time directly
+ * into the structs. Because some fields are char, the values will be
+ * in the wrong order. The *_Field_IsChar tells when to flip the
+ * bytes. Data read and written to PCI memory is automatically swapped
+ * on big-endian platforms so char fields read as words are actually being
+ * unswapped on big-endian platforms.
  */
-static ushort __init
-AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
-{
-       ushort wval, chksum;
-       ushort *wbuf;
-       int eep_addr;
-       ushort *charfields;
+static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
+       ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
+       0x0000,                 /* cfg_msw */
+       0xFFFF,                 /* disc_enable */
+       0xFFFF,                 /* wdtr_able */
+       0xFFFF,                 /* sdtr_able */
+       0xFFFF,                 /* start_motor */
+       0xFFFF,                 /* tagqng_able */
+       0xFFFF,                 /* bios_scan */
+       0,                      /* scam_tolerant */
+       7,                      /* adapter_scsi_id */
+       0,                      /* bios_boot_delay */
+       3,                      /* scsi_reset_delay */
+       0,                      /* bios_id_lun */
+       0,                      /* termination */
+       0,                      /* reserved1 */
+       0xFFE7,                 /* bios_ctrl */
+       0xFFFF,                 /* ultra_able */
+       0,                      /* reserved2 */
+       ASC_DEF_MAX_HOST_QNG,   /* max_host_qng */
+       ASC_DEF_MAX_DVC_QNG,    /* max_dvc_qng */
+       0,                      /* dvc_cntl */
+       0,                      /* bug_fix */
+       0,                      /* serial_number_word1 */
+       0,                      /* serial_number_word2 */
+       0,                      /* serial_number_word3 */
+       0,                      /* check_sum */
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+       ,                       /* oem_name[16] */
+       0,                      /* dvc_err_code */
+       0,                      /* adv_err_code */
+       0,                      /* adv_err_addr */
+       0,                      /* saved_dvc_err_code */
+       0,                      /* saved_adv_err_code */
+       0,                      /* saved_adv_err_addr */
+       0                       /* num_of_err */
+};
 
-       charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
-       wbuf = (ushort *)cfg_buf;
-       chksum = 0;
+static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
+       0,                      /* cfg_lsw */
+       0,                      /* cfg_msw */
+       0,                      /* -disc_enable */
+       0,                      /* wdtr_able */
+       0,                      /* sdtr_able */
+       0,                      /* start_motor */
+       0,                      /* tagqng_able */
+       0,                      /* bios_scan */
+       0,                      /* scam_tolerant */
+       1,                      /* adapter_scsi_id */
+       1,                      /* bios_boot_delay */
+       1,                      /* scsi_reset_delay */
+       1,                      /* bios_id_lun */
+       1,                      /* termination */
+       1,                      /* reserved1 */
+       0,                      /* bios_ctrl */
+       0,                      /* ultra_able */
+       0,                      /* reserved2 */
+       1,                      /* max_host_qng */
+       1,                      /* max_dvc_qng */
+       0,                      /* dvc_cntl */
+       0,                      /* bug_fix */
+       0,                      /* serial_number_word1 */
+       0,                      /* serial_number_word2 */
+       0,                      /* serial_number_word3 */
+       0,                      /* check_sum */
+       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+       ,                       /* oem_name[16] */
+       0,                      /* dvc_err_code */
+       0,                      /* adv_err_code */
+       0,                      /* adv_err_addr */
+       0,                      /* saved_dvc_err_code */
+       0,                      /* saved_adv_err_code */
+       0,                      /* saved_adv_err_addr */
+       0                       /* num_of_err */
+};
 
-       for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
-            eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
-               wval = AdvReadEEPWord(iop_base, eep_addr);
-               chksum += wval; /* Checksum is calculated from word values. */
-               if (*charfields++) {
-                       *wbuf = le16_to_cpu(wval);
-               } else {
-                       *wbuf = wval;
-               }
-       }
-       /* Read checksum word. */
-       *wbuf = AdvReadEEPWord(iop_base, eep_addr);
-       wbuf++;
-       charfields++;
+static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
+       ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
+       0x0000,                 /* 01 cfg_msw */
+       0xFFFF,                 /* 02 disc_enable */
+       0xFFFF,                 /* 03 wdtr_able */
+       0x4444,                 /* 04 sdtr_speed1 */
+       0xFFFF,                 /* 05 start_motor */
+       0xFFFF,                 /* 06 tagqng_able */
+       0xFFFF,                 /* 07 bios_scan */
+       0,                      /* 08 scam_tolerant */
+       7,                      /* 09 adapter_scsi_id */
+       0,                      /*    bios_boot_delay */
+       3,                      /* 10 scsi_reset_delay */
+       0,                      /*    bios_id_lun */
+       0,                      /* 11 termination_se */
+       0,                      /*    termination_lvd */
+       0xFFE7,                 /* 12 bios_ctrl */
+       0x4444,                 /* 13 sdtr_speed2 */
+       0x4444,                 /* 14 sdtr_speed3 */
+       ASC_DEF_MAX_HOST_QNG,   /* 15 max_host_qng */
+       ASC_DEF_MAX_DVC_QNG,    /*    max_dvc_qng */
+       0,                      /* 16 dvc_cntl */
+       0x4444,                 /* 17 sdtr_speed4 */
+       0,                      /* 18 serial_number_word1 */
+       0,                      /* 19 serial_number_word2 */
+       0,                      /* 20 serial_number_word3 */
+       0,                      /* 21 check_sum */
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+       ,                       /* 22-29 oem_name[16] */
+       0,                      /* 30 dvc_err_code */
+       0,                      /* 31 adv_err_code */
+       0,                      /* 32 adv_err_addr */
+       0,                      /* 33 saved_dvc_err_code */
+       0,                      /* 34 saved_adv_err_code */
+       0,                      /* 35 saved_adv_err_addr */
+       0,                      /* 36 reserved */
+       0,                      /* 37 reserved */
+       0,                      /* 38 reserved */
+       0,                      /* 39 reserved */
+       0,                      /* 40 reserved */
+       0,                      /* 41 reserved */
+       0,                      /* 42 reserved */
+       0,                      /* 43 reserved */
+       0,                      /* 44 reserved */
+       0,                      /* 45 reserved */
+       0,                      /* 46 reserved */
+       0,                      /* 47 reserved */
+       0,                      /* 48 reserved */
+       0,                      /* 49 reserved */
+       0,                      /* 50 reserved */
+       0,                      /* 51 reserved */
+       0,                      /* 52 reserved */
+       0,                      /* 53 reserved */
+       0,                      /* 54 reserved */
+       0,                      /* 55 reserved */
+       0,                      /* 56 cisptr_lsw */
+       0,                      /* 57 cisprt_msw */
+       PCI_VENDOR_ID_ASP,      /* 58 subsysvid */
+       PCI_DEVICE_ID_38C0800_REV1,     /* 59 subsysid */
+       0,                      /* 60 reserved */
+       0,                      /* 61 reserved */
+       0,                      /* 62 reserved */
+       0                       /* 63 reserved */
+};
 
-       /* Read rest of EEPROM not covered by the checksum. */
-       for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
-            eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
-               *wbuf = AdvReadEEPWord(iop_base, eep_addr);
-               if (*charfields++) {
-                       *wbuf = le16_to_cpu(*wbuf);
-               }
-       }
-       return chksum;
-}
+static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
+       0,                      /* 00 cfg_lsw */
+       0,                      /* 01 cfg_msw */
+       0,                      /* 02 disc_enable */
+       0,                      /* 03 wdtr_able */
+       0,                      /* 04 sdtr_speed1 */
+       0,                      /* 05 start_motor */
+       0,                      /* 06 tagqng_able */
+       0,                      /* 07 bios_scan */
+       0,                      /* 08 scam_tolerant */
+       1,                      /* 09 adapter_scsi_id */
+       1,                      /*    bios_boot_delay */
+       1,                      /* 10 scsi_reset_delay */
+       1,                      /*    bios_id_lun */
+       1,                      /* 11 termination_se */
+       1,                      /*    termination_lvd */
+       0,                      /* 12 bios_ctrl */
+       0,                      /* 13 sdtr_speed2 */
+       0,                      /* 14 sdtr_speed3 */
+       1,                      /* 15 max_host_qng */
+       1,                      /*    max_dvc_qng */
+       0,                      /* 16 dvc_cntl */
+       0,                      /* 17 sdtr_speed4 */
+       0,                      /* 18 serial_number_word1 */
+       0,                      /* 19 serial_number_word2 */
+       0,                      /* 20 serial_number_word3 */
+       0,                      /* 21 check_sum */
+       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+       ,                       /* 22-29 oem_name[16] */
+       0,                      /* 30 dvc_err_code */
+       0,                      /* 31 adv_err_code */
+       0,                      /* 32 adv_err_addr */
+       0,                      /* 33 saved_dvc_err_code */
+       0,                      /* 34 saved_adv_err_code */
+       0,                      /* 35 saved_adv_err_addr */
+       0,                      /* 36 reserved */
+       0,                      /* 37 reserved */
+       0,                      /* 38 reserved */
+       0,                      /* 39 reserved */
+       0,                      /* 40 reserved */
+       0,                      /* 41 reserved */
+       0,                      /* 42 reserved */
+       0,                      /* 43 reserved */
+       0,                      /* 44 reserved */
+       0,                      /* 45 reserved */
+       0,                      /* 46 reserved */
+       0,                      /* 47 reserved */
+       0,                      /* 48 reserved */
+       0,                      /* 49 reserved */
+       0,                      /* 50 reserved */
+       0,                      /* 51 reserved */
+       0,                      /* 52 reserved */
+       0,                      /* 53 reserved */
+       0,                      /* 54 reserved */
+       0,                      /* 55 reserved */
+       0,                      /* 56 cisptr_lsw */
+       0,                      /* 57 cisprt_msw */
+       0,                      /* 58 subsysvid */
+       0,                      /* 59 subsysid */
+       0,                      /* 60 reserved */
+       0,                      /* 61 reserved */
+       0,                      /* 62 reserved */
+       0                       /* 63 reserved */
+};
+
+static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
+       ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
+       0x0000,                 /* 01 cfg_msw */
+       0xFFFF,                 /* 02 disc_enable */
+       0xFFFF,                 /* 03 wdtr_able */
+       0x5555,                 /* 04 sdtr_speed1 */
+       0xFFFF,                 /* 05 start_motor */
+       0xFFFF,                 /* 06 tagqng_able */
+       0xFFFF,                 /* 07 bios_scan */
+       0,                      /* 08 scam_tolerant */
+       7,                      /* 09 adapter_scsi_id */
+       0,                      /*    bios_boot_delay */
+       3,                      /* 10 scsi_reset_delay */
+       0,                      /*    bios_id_lun */
+       0,                      /* 11 termination_se */
+       0,                      /*    termination_lvd */
+       0xFFE7,                 /* 12 bios_ctrl */
+       0x5555,                 /* 13 sdtr_speed2 */
+       0x5555,                 /* 14 sdtr_speed3 */
+       ASC_DEF_MAX_HOST_QNG,   /* 15 max_host_qng */
+       ASC_DEF_MAX_DVC_QNG,    /*    max_dvc_qng */
+       0,                      /* 16 dvc_cntl */
+       0x5555,                 /* 17 sdtr_speed4 */
+       0,                      /* 18 serial_number_word1 */
+       0,                      /* 19 serial_number_word2 */
+       0,                      /* 20 serial_number_word3 */
+       0,                      /* 21 check_sum */
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+       ,                       /* 22-29 oem_name[16] */
+       0,                      /* 30 dvc_err_code */
+       0,                      /* 31 adv_err_code */
+       0,                      /* 32 adv_err_addr */
+       0,                      /* 33 saved_dvc_err_code */
+       0,                      /* 34 saved_adv_err_code */
+       0,                      /* 35 saved_adv_err_addr */
+       0,                      /* 36 reserved */
+       0,                      /* 37 reserved */
+       0,                      /* 38 reserved */
+       0,                      /* 39 reserved */
+       0,                      /* 40 reserved */
+       0,                      /* 41 reserved */
+       0,                      /* 42 reserved */
+       0,                      /* 43 reserved */
+       0,                      /* 44 reserved */
+       0,                      /* 45 reserved */
+       0,                      /* 46 reserved */
+       0,                      /* 47 reserved */
+       0,                      /* 48 reserved */
+       0,                      /* 49 reserved */
+       0,                      /* 50 reserved */
+       0,                      /* 51 reserved */
+       0,                      /* 52 reserved */
+       0,                      /* 53 reserved */
+       0,                      /* 54 reserved */
+       0,                      /* 55 reserved */
+       0,                      /* 56 cisptr_lsw */
+       0,                      /* 57 cisprt_msw */
+       PCI_VENDOR_ID_ASP,      /* 58 subsysvid */
+       PCI_DEVICE_ID_38C1600_REV1,     /* 59 subsysid */
+       0,                      /* 60 reserved */
+       0,                      /* 61 reserved */
+       0,                      /* 62 reserved */
+       0                       /* 63 reserved */
+};
+
+static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
+       0,                      /* 00 cfg_lsw */
+       0,                      /* 01 cfg_msw */
+       0,                      /* 02 disc_enable */
+       0,                      /* 03 wdtr_able */
+       0,                      /* 04 sdtr_speed1 */
+       0,                      /* 05 start_motor */
+       0,                      /* 06 tagqng_able */
+       0,                      /* 07 bios_scan */
+       0,                      /* 08 scam_tolerant */
+       1,                      /* 09 adapter_scsi_id */
+       1,                      /*    bios_boot_delay */
+       1,                      /* 10 scsi_reset_delay */
+       1,                      /*    bios_id_lun */
+       1,                      /* 11 termination_se */
+       1,                      /*    termination_lvd */
+       0,                      /* 12 bios_ctrl */
+       0,                      /* 13 sdtr_speed2 */
+       0,                      /* 14 sdtr_speed3 */
+       1,                      /* 15 max_host_qng */
+       1,                      /*    max_dvc_qng */
+       0,                      /* 16 dvc_cntl */
+       0,                      /* 17 sdtr_speed4 */
+       0,                      /* 18 serial_number_word1 */
+       0,                      /* 19 serial_number_word2 */
+       0,                      /* 20 serial_number_word3 */
+       0,                      /* 21 check_sum */
+       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+       ,                       /* 22-29 oem_name[16] */
+       0,                      /* 30 dvc_err_code */
+       0,                      /* 31 adv_err_code */
+       0,                      /* 32 adv_err_addr */
+       0,                      /* 33 saved_dvc_err_code */
+       0,                      /* 34 saved_adv_err_code */
+       0,                      /* 35 saved_adv_err_addr */
+       0,                      /* 36 reserved */
+       0,                      /* 37 reserved */
+       0,                      /* 38 reserved */
+       0,                      /* 39 reserved */
+       0,                      /* 40 reserved */
+       0,                      /* 41 reserved */
+       0,                      /* 42 reserved */
+       0,                      /* 43 reserved */
+       0,                      /* 44 reserved */
+       0,                      /* 45 reserved */
+       0,                      /* 46 reserved */
+       0,                      /* 47 reserved */
+       0,                      /* 48 reserved */
+       0,                      /* 49 reserved */
+       0,                      /* 50 reserved */
+       0,                      /* 51 reserved */
+       0,                      /* 52 reserved */
+       0,                      /* 53 reserved */
+       0,                      /* 54 reserved */
+       0,                      /* 55 reserved */
+       0,                      /* 56 cisptr_lsw */
+       0,                      /* 57 cisprt_msw */
+       0,                      /* 58 subsysvid */
+       0,                      /* 59 subsysid */
+       0,                      /* 60 reserved */
+       0,                      /* 61 reserved */
+       0,                      /* 62 reserved */
+       0                       /* 63 reserved */
+};
 
+#ifdef CONFIG_PCI
 /*
- * Read EEPROM configuration into the specified buffer.
- *
- * Return a checksum based on the EEPROM configuration read.
+ * Wait for EEPROM command to complete
  */
-static ushort __init
-AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
+static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
 {
-       ushort wval, chksum;
-       ushort *wbuf;
-       int eep_addr;
-       ushort *charfields;
-
-       charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
-       wbuf = (ushort *)cfg_buf;
-       chksum = 0;
-
-       for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
-            eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
-               wval = AdvReadEEPWord(iop_base, eep_addr);
-               chksum += wval; /* Checksum is calculated from word values. */
-               if (*charfields++) {
-                       *wbuf = le16_to_cpu(wval);
-               } else {
-                       *wbuf = wval;
-               }
-       }
-       /* Read checksum word. */
-       *wbuf = AdvReadEEPWord(iop_base, eep_addr);
-       wbuf++;
-       charfields++;
+       int eep_delay_ms;
 
-       /* Read rest of EEPROM not covered by the checksum. */
-       for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
-            eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
-               *wbuf = AdvReadEEPWord(iop_base, eep_addr);
-               if (*charfields++) {
-                       *wbuf = le16_to_cpu(*wbuf);
+       for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
+               if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
+                   ASC_EEP_CMD_DONE) {
+                       break;
                }
+               mdelay(1);
        }
-       return chksum;
+       if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
+           0)
+               BUG();
 }
 
 /*
  * Read the EEPROM from specified location
  */
-static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
+static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
 {
        AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
                             ASC_EEP_CMD_READ | eep_word_addr);
@@ -16868,31 +12258,10 @@ static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
        return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
 }
 
-/*
- * Wait for EEPROM command to complete
- */
-static void __init AdvWaitEEPCmd(AdvPortAddr iop_base)
-{
-       int eep_delay_ms;
-
-       for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
-               if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
-                   ASC_EEP_CMD_DONE) {
-                       break;
-               }
-               DvcSleepMilliSecond(1);
-       }
-       if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
-           0) {
-               ASC_ASSERT(0);
-       }
-       return;
-}
-
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void __init
+void __devinit
 AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 {
        ushort *wbuf;
@@ -16923,7 +12292,7 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
                AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
                                     ASC_EEP_CMD_WRITE | addr);
                AdvWaitEEPCmd(iop_base);
-               DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
+               mdelay(ADV_EEP_DELAY_MS);
        }
 
        /*
@@ -16954,13 +12323,12 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
        }
        AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
        AdvWaitEEPCmd(iop_base);
-       return;
 }
 
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void __init
+void __devinit
 AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
 {
        ushort *wbuf;
@@ -16991,7 +12359,7 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
                AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
                                     ASC_EEP_CMD_WRITE | addr);
                AdvWaitEEPCmd(iop_base);
-               DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
+               mdelay(ADV_EEP_DELAY_MS);
        }
 
        /*
@@ -17022,13 +12390,12 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
        }
        AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
        AdvWaitEEPCmd(iop_base);
-       return;
 }
 
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void __init
+void __devinit
 AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
 {
        ushort *wbuf;
@@ -17059,7 +12426,7 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
                AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
                                     ASC_EEP_CMD_WRITE | addr);
                AdvWaitEEPCmd(iop_base);
-               DvcSleepMilliSecond(ADV_EEP_DELAY_MS);
+               mdelay(ADV_EEP_DELAY_MS);
        }
 
        /*
@@ -17071,834 +12438,1005 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
        wbuf++;
        charfields++;
 
-       /*
-        * Write EEPROM OEM name at words 22 to 29.
-        */
-       for (addr = ADV_EEP_DVC_CTL_BEGIN;
-            addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
-               ushort word;
-
+       /*
+        * Write EEPROM OEM name at words 22 to 29.
+        */
+       for (addr = ADV_EEP_DVC_CTL_BEGIN;
+            addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
+               ushort word;
+
+               if (*charfields++) {
+                       word = cpu_to_le16(*wbuf);
+               } else {
+                       word = *wbuf;
+               }
+               AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
+               AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
+                                    ASC_EEP_CMD_WRITE | addr);
+               AdvWaitEEPCmd(iop_base);
+       }
+       AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
+       AdvWaitEEPCmd(iop_base);
+}
+
+/*
+ * Read EEPROM configuration into the specified buffer.
+ *
+ * Return a checksum based on the EEPROM configuration read.
+ */
+static ushort __devinit
+AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
+{
+       ushort wval, chksum;
+       ushort *wbuf;
+       int eep_addr;
+       ushort *charfields;
+
+       charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
+       wbuf = (ushort *)cfg_buf;
+       chksum = 0;
+
+       for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
+            eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
+               wval = AdvReadEEPWord(iop_base, eep_addr);
+               chksum += wval; /* Checksum is calculated from word values. */
+               if (*charfields++) {
+                       *wbuf = le16_to_cpu(wval);
+               } else {
+                       *wbuf = wval;
+               }
+       }
+       /* Read checksum word. */
+       *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+       wbuf++;
+       charfields++;
+
+       /* Read rest of EEPROM not covered by the checksum. */
+       for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
+            eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
+               *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+               if (*charfields++) {
+                       *wbuf = le16_to_cpu(*wbuf);
+               }
+       }
+       return chksum;
+}
+
+/*
+ * Read EEPROM configuration into the specified buffer.
+ *
+ * Return a checksum based on the EEPROM configuration read.
+ */
+static ushort __devinit
+AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
+{
+       ushort wval, chksum;
+       ushort *wbuf;
+       int eep_addr;
+       ushort *charfields;
+
+       charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
+       wbuf = (ushort *)cfg_buf;
+       chksum = 0;
+
+       for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
+            eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
+               wval = AdvReadEEPWord(iop_base, eep_addr);
+               chksum += wval; /* Checksum is calculated from word values. */
+               if (*charfields++) {
+                       *wbuf = le16_to_cpu(wval);
+               } else {
+                       *wbuf = wval;
+               }
+       }
+       /* Read checksum word. */
+       *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+       wbuf++;
+       charfields++;
+
+       /* Read rest of EEPROM not covered by the checksum. */
+       for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
+            eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
+               *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+               if (*charfields++) {
+                       *wbuf = le16_to_cpu(*wbuf);
+               }
+       }
+       return chksum;
+}
+
+/*
+ * Read EEPROM configuration into the specified buffer.
+ *
+ * Return a checksum based on the EEPROM configuration read.
+ */
+static ushort __devinit
+AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
+{
+       ushort wval, chksum;
+       ushort *wbuf;
+       int eep_addr;
+       ushort *charfields;
+
+       charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
+       wbuf = (ushort *)cfg_buf;
+       chksum = 0;
+
+       for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
+            eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
+               wval = AdvReadEEPWord(iop_base, eep_addr);
+               chksum += wval; /* Checksum is calculated from word values. */
+               if (*charfields++) {
+                       *wbuf = le16_to_cpu(wval);
+               } else {
+                       *wbuf = wval;
+               }
+       }
+       /* Read checksum word. */
+       *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+       wbuf++;
+       charfields++;
+
+       /* Read rest of EEPROM not covered by the checksum. */
+       for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
+            eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
+               *wbuf = AdvReadEEPWord(iop_base, eep_addr);
                if (*charfields++) {
-                       word = cpu_to_le16(*wbuf);
-               } else {
-                       word = *wbuf;
+                       *wbuf = le16_to_cpu(*wbuf);
                }
-               AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
-               AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
-                                    ASC_EEP_CMD_WRITE | addr);
-               AdvWaitEEPCmd(iop_base);
        }
-       AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
-       AdvWaitEEPCmd(iop_base);
-       return;
+       return chksum;
 }
 
-/* a_advlib.c */
 /*
- * AdvExeScsiQueue() - Send a request to the RISC microcode program.
- *
- *   Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
- *   add the carrier to the ICQ (Initiator Command Queue), and tickle the
- *   RISC to notify it a new command is ready to be executed.
+ * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
+ * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
+ * all of this is done.
  *
- * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
- * set to SCSI_MAX_RETRY.
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
  *
- * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
- * for DMA addresses or math operations are byte swapped to little-endian
- * order.
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
  *
- * Return:
- *      ADV_SUCCESS(1) - The request was successfully queued.
- *      ADV_BUSY(0) -    Resource unavailable; Retry again after pending
- *                       request completes.
- *      ADV_ERROR(-1) -  Invalid ADV_SCSI_REQ_Q request structure
- *                       host IC error.
+ * Note: Chip is stopped on entry.
  */
-static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
+static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
 {
-       ulong last_int_level;
        AdvPortAddr iop_base;
-       ADV_DCNT req_size;
-       ADV_PADDR req_paddr;
-       ADV_CARR_T *new_carrp;
-
-       ASC_ASSERT(scsiq != NULL);      /* 'scsiq' should never be NULL. */
-
-       /*
-        * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
-        */
-       if (scsiq->target_id > ADV_MAX_TID) {
-               scsiq->host_status = QHSTA_M_INVALID_DEVICE;
-               scsiq->done_status = QD_WITH_ERROR;
-               return ADV_ERROR;
-       }
+       ushort warn_code;
+       ADVEEP_3550_CONFIG eep_config;
 
        iop_base = asc_dvc->iop_base;
 
-       last_int_level = DvcEnterCritical();
-
-       /*
-        * Allocate a carrier ensuring at least one carrier always
-        * remains on the freelist and initialize fields.
-        */
-       if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
-               DvcLeaveCritical(last_int_level);
-               return ADV_BUSY;
-       }
-       asc_dvc->carr_freelist = (ADV_CARR_T *)
-           ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
-       asc_dvc->carr_pending_cnt++;
-
-       /*
-        * Set the carrier to be a stopper by setting 'next_vpa'
-        * to the stopper value. The current stopper will be changed
-        * below to point to the new stopper.
-        */
-       new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
+       warn_code = 0;
 
        /*
-        * Clear the ADV_SCSI_REQ_Q done flag.
+        * Read the board's EEPROM configuration.
+        *
+        * Set default values if a bad checksum is found.
         */
-       scsiq->a_flag &= ~ADV_SCSIQ_DONE;
-
-       req_size = sizeof(ADV_SCSI_REQ_Q);
-       req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
-                                 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
-
-       ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr);
-       ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
+       if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
+               warn_code |= ASC_WARN_EEPROM_CHKSUM;
 
-       /* Wait for assertion before making little-endian */
-       req_paddr = cpu_to_le32(req_paddr);
+               /*
+                * Set EEPROM default values.
+                */
+               memcpy(&eep_config, &Default_3550_EEPROM_Config,
+                       sizeof(ADVEEP_3550_CONFIG));
 
-       /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
-       scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
-       scsiq->scsiq_rptr = req_paddr;
+               /*
+                * Assume the 6 byte board serial number that was read from
+                * EEPROM is correct even if the EEPROM checksum failed.
+                */
+               eep_config.serial_number_word3 =
+                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
 
-       scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
-       /*
-        * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
-        * order during initialization.
-        */
-       scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
+               eep_config.serial_number_word2 =
+                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
 
-       /*
-        * Use the current stopper to send the ADV_SCSI_REQ_Q command to
-        * the microcode. The newly allocated stopper will become the new
-        * stopper.
-        */
-       asc_dvc->icq_sp->areq_vpa = req_paddr;
+               eep_config.serial_number_word1 =
+                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
 
+               AdvSet3550EEPConfig(iop_base, &eep_config);
+       }
        /*
-        * Set the 'next_vpa' pointer for the old stopper to be the
-        * physical address of the new stopper. The RISC can only
-        * follow physical addresses.
+        * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
+        * EEPROM configuration that was read.
+        *
+        * This is the mapping of EEPROM fields to Adv Library fields.
         */
-       asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
+       asc_dvc->wdtr_able = eep_config.wdtr_able;
+       asc_dvc->sdtr_able = eep_config.sdtr_able;
+       asc_dvc->ultra_able = eep_config.ultra_able;
+       asc_dvc->tagqng_able = eep_config.tagqng_able;
+       asc_dvc->cfg->disc_enable = eep_config.disc_enable;
+       asc_dvc->max_host_qng = eep_config.max_host_qng;
+       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+       asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
+       asc_dvc->start_motor = eep_config.start_motor;
+       asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
+       asc_dvc->bios_ctrl = eep_config.bios_ctrl;
+       asc_dvc->no_scam = eep_config.scam_tolerant;
+       asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
+       asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
+       asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
 
        /*
-        * Set the host adapter stopper pointer to point to the new carrier.
+        * Set the host maximum queuing (max. 253, min. 16) and the per device
+        * maximum queuing (max. 63, min. 4).
         */
-       asc_dvc->icq_sp = new_carrp;
-
-       if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
-           asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
-               /*
-                * Tickle the RISC to tell it to read its Command Queue Head pointer.
-                */
-               AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
-               if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
-                       /*
-                        * Clear the tickle value. In the ASC-3550 the RISC flag
-                        * command 'clr_tickle_a' does not work unless the host
-                        * value is cleared.
-                        */
-                       AdvWriteByteRegister(iop_base, IOPB_TICKLE,
-                                            ADV_TICKLE_NOP);
+       if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
+               eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+       } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
+               /* If the value is zero, assume it is uninitialized. */
+               if (eep_config.max_host_qng == 0) {
+                       eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+               } else {
+                       eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
                }
-       } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
-               /*
-                * Notify the RISC a carrier is ready by writing the physical
-                * address of the new carrier stopper to the COMMA register.
-                */
-               AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
-                                     le32_to_cpu(new_carrp->carr_pa));
        }
 
-       DvcLeaveCritical(last_int_level);
-
-       return ADV_SUCCESS;
-}
-
-/*
- * Reset SCSI Bus and purge all outstanding requests.
- *
- * Return Value:
- *      ADV_TRUE(1) -   All requests are purged and SCSI Bus is reset.
- *      ADV_FALSE(0) -  Microcode command failed.
- *      ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
- *                      may be hung which requires driver recovery.
- */
-static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
-{
-       int status;
+       if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
+               eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+       } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
+               /* If the value is zero, assume it is uninitialized. */
+               if (eep_config.max_dvc_qng == 0) {
+                       eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+               } else {
+                       eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
+               }
+       }
 
        /*
-        * Send the SCSI Bus Reset idle start idle command which asserts
-        * the SCSI Bus Reset signal.
+        * If 'max_dvc_qng' is greater than 'max_host_qng', then
+        * set 'max_dvc_qng' to 'max_host_qng'.
         */
-       status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
-       if (status != ADV_TRUE) {
-               return status;
+       if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
+               eep_config.max_dvc_qng = eep_config.max_host_qng;
        }
 
        /*
-        * Delay for the specified SCSI Bus Reset hold time.
-        *
-        * The hold time delay is done on the host because the RISC has no
-        * microsecond accurate timer.
+        * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
+        * values based on possibly adjusted EEPROM values.
         */
-       DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US);
+       asc_dvc->max_host_qng = eep_config.max_host_qng;
+       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
 
        /*
-        * Send the SCSI Bus Reset end idle command which de-asserts
-        * the SCSI Bus Reset signal and purges any pending requests.
+        * If the EEPROM 'termination' field is set to automatic (0), then set
+        * the ADV_DVC_CFG 'termination' field to automatic also.
+        *
+        * If the termination is specified with a non-zero 'termination'
+        * value check that a legal value is set and set the ADV_DVC_CFG
+        * 'termination' field appropriately.
         */
-       status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
-       if (status != ADV_TRUE) {
-               return status;
+       if (eep_config.termination == 0) {
+               asc_dvc->cfg->termination = 0;  /* auto termination */
+       } else {
+               /* Enable manual control with low off / high off. */
+               if (eep_config.termination == 1) {
+                       asc_dvc->cfg->termination = TERM_CTL_SEL;
+
+                       /* Enable manual control with low off / high on. */
+               } else if (eep_config.termination == 2) {
+                       asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
+
+                       /* Enable manual control with low on / high on. */
+               } else if (eep_config.termination == 3) {
+                       asc_dvc->cfg->termination =
+                           TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
+               } else {
+                       /*
+                        * The EEPROM 'termination' field contains a bad value. Use
+                        * automatic termination instead.
+                        */
+                       asc_dvc->cfg->termination = 0;
+                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+               }
        }
 
-       DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000);
-
-       return status;
+       return warn_code;
 }
 
 /*
- * Reset chip and SCSI Bus.
+ * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
+ * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
+ * all of this is done.
  *
- * Return Value:
- *      ADV_TRUE(1) -   Chip re-initialization and SCSI Bus Reset successful.
- *      ADV_FALSE(0) -  Chip re-initialization and SCSI Bus Reset failure.
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ *
+ * Note: Chip is stopped on entry.
  */
-static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
+static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
 {
-       int status;
-       ushort wdtr_able, sdtr_able, tagqng_able;
-       ushort ppr_able = 0;
-       uchar tid, max_cmd[ADV_MAX_TID + 1];
        AdvPortAddr iop_base;
-       ushort bios_sig;
+       ushort warn_code;
+       ADVEEP_38C0800_CONFIG eep_config;
+       uchar tid, termination;
+       ushort sdtr_speed = 0;
 
        iop_base = asc_dvc->iop_base;
 
+       warn_code = 0;
+
        /*
-        * Save current per TID negotiated values.
+        * Read the board's EEPROM configuration.
+        *
+        * Set default values if a bad checksum is found.
         */
-       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-       if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
-               AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
-       }
-       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-               AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                               max_cmd[tid]);
-       }
+       if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
+           eep_config.check_sum) {
+               warn_code |= ASC_WARN_EEPROM_CHKSUM;
 
+               /*
+                * Set EEPROM default values.
+                */
+               memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
+                       sizeof(ADVEEP_38C0800_CONFIG));
+
+               /*
+                * Assume the 6 byte board serial number that was read from
+                * EEPROM is correct even if the EEPROM checksum failed.
+                */
+               eep_config.serial_number_word3 =
+                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
+
+               eep_config.serial_number_word2 =
+                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
+
+               eep_config.serial_number_word1 =
+                   AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
+
+               AdvSet38C0800EEPConfig(iop_base, &eep_config);
+       }
        /*
-        * Force the AdvInitAsc3550/38C0800Driver() function to
-        * perform a SCSI Bus Reset by clearing the BIOS signature word.
-        * The initialization functions assumes a SCSI Bus Reset is not
-        * needed if the BIOS signature word is present.
+        * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
+        * EEPROM configuration that was read.
+        *
+        * This is the mapping of EEPROM fields to Adv Library fields.
         */
-       AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
-       AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
+       asc_dvc->wdtr_able = eep_config.wdtr_able;
+       asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
+       asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
+       asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
+       asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
+       asc_dvc->tagqng_able = eep_config.tagqng_able;
+       asc_dvc->cfg->disc_enable = eep_config.disc_enable;
+       asc_dvc->max_host_qng = eep_config.max_host_qng;
+       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+       asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
+       asc_dvc->start_motor = eep_config.start_motor;
+       asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
+       asc_dvc->bios_ctrl = eep_config.bios_ctrl;
+       asc_dvc->no_scam = eep_config.scam_tolerant;
+       asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
+       asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
+       asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
 
        /*
-        * Stop chip and reset it.
+        * For every Target ID if any of its 'sdtr_speed[1234]' bits
+        * are set, then set an 'sdtr_able' bit for it.
         */
-       AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
-       AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
-       DvcSleepMilliSecond(100);
-       AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
-                            ADV_CTRL_REG_CMD_WR_IO_REG);
+       asc_dvc->sdtr_able = 0;
+       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
+               if (tid == 0) {
+                       sdtr_speed = asc_dvc->sdtr_speed1;
+               } else if (tid == 4) {
+                       sdtr_speed = asc_dvc->sdtr_speed2;
+               } else if (tid == 8) {
+                       sdtr_speed = asc_dvc->sdtr_speed3;
+               } else if (tid == 12) {
+                       sdtr_speed = asc_dvc->sdtr_speed4;
+               }
+               if (sdtr_speed & ADV_MAX_TID) {
+                       asc_dvc->sdtr_able |= (1 << tid);
+               }
+               sdtr_speed >>= 4;
+       }
 
        /*
-        * Reset Adv Library error code, if any, and try
-        * re-initializing the chip.
+        * Set the host maximum queuing (max. 253, min. 16) and the per device
+        * maximum queuing (max. 63, min. 4).
         */
-       asc_dvc->err_code = 0;
-       if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
-               status = AdvInitAsc38C1600Driver(asc_dvc);
-       } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
-               status = AdvInitAsc38C0800Driver(asc_dvc);
-       } else {
-               status = AdvInitAsc3550Driver(asc_dvc);
+       if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
+               eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+       } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
+               /* If the value is zero, assume it is uninitialized. */
+               if (eep_config.max_host_qng == 0) {
+                       eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+               } else {
+                       eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
+               }
        }
 
-       /* Translate initialization return value to status value. */
-       if (status == 0) {
-               status = ADV_TRUE;
-       } else {
-               status = ADV_FALSE;
+       if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
+               eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+       } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
+               /* If the value is zero, assume it is uninitialized. */
+               if (eep_config.max_dvc_qng == 0) {
+                       eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+               } else {
+                       eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
+               }
        }
 
        /*
-        * Restore the BIOS signature word.
+        * If 'max_dvc_qng' is greater than 'max_host_qng', then
+        * set 'max_dvc_qng' to 'max_host_qng'.
         */
-       AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
+       if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
+               eep_config.max_dvc_qng = eep_config.max_host_qng;
+       }
 
        /*
-        * Restore per TID negotiated values.
+        * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
+        * values based on possibly adjusted EEPROM values.
         */
-       AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-       AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-       if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
-               AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
+       asc_dvc->max_host_qng = eep_config.max_host_qng;
+       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+
+       /*
+        * If the EEPROM 'termination' field is set to automatic (0), then set
+        * the ADV_DVC_CFG 'termination' field to automatic also.
+        *
+        * If the termination is specified with a non-zero 'termination'
+        * value check that a legal value is set and set the ADV_DVC_CFG
+        * 'termination' field appropriately.
+        */
+       if (eep_config.termination_se == 0) {
+               termination = 0;        /* auto termination for SE */
+       } else {
+               /* Enable manual control with low off / high off. */
+               if (eep_config.termination_se == 1) {
+                       termination = 0;
+
+                       /* Enable manual control with low off / high on. */
+               } else if (eep_config.termination_se == 2) {
+                       termination = TERM_SE_HI;
+
+                       /* Enable manual control with low on / high on. */
+               } else if (eep_config.termination_se == 3) {
+                       termination = TERM_SE;
+               } else {
+                       /*
+                        * The EEPROM 'termination_se' field contains a bad value.
+                        * Use automatic termination instead.
+                        */
+                       termination = 0;
+                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+               }
        }
-       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-       for (tid = 0; tid <= ADV_MAX_TID; tid++) {
-               AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                                max_cmd[tid]);
+
+       if (eep_config.termination_lvd == 0) {
+               asc_dvc->cfg->termination = termination;        /* auto termination for LVD */
+       } else {
+               /* Enable manual control with low off / high off. */
+               if (eep_config.termination_lvd == 1) {
+                       asc_dvc->cfg->termination = termination;
+
+                       /* Enable manual control with low off / high on. */
+               } else if (eep_config.termination_lvd == 2) {
+                       asc_dvc->cfg->termination = termination | TERM_LVD_HI;
+
+                       /* Enable manual control with low on / high on. */
+               } else if (eep_config.termination_lvd == 3) {
+                       asc_dvc->cfg->termination = termination | TERM_LVD;
+               } else {
+                       /*
+                        * The EEPROM 'termination_lvd' field contains a bad value.
+                        * Use automatic termination instead.
+                        */
+                       asc_dvc->cfg->termination = termination;
+                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+               }
        }
 
-       return status;
+       return warn_code;
 }
 
 /*
- * Adv Library Interrupt Service Routine
- *
- *  This function is called by a driver's interrupt service routine.
- *  The function disables and re-enables interrupts.
+ * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
+ * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
+ * all of this is done.
  *
- *  When a microcode idle command is completed, the ADV_DVC_VAR
- *  'idle_cmd_done' field is set to ADV_TRUE.
+ * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
  *
- *  Note: AdvISR() can be called when interrupts are disabled or even
- *  when there is no hardware interrupt condition present. It will
- *  always check for completed idle commands and microcode requests.
- *  This is an important feature that shouldn't be changed because it
- *  allows commands to be completed from polling mode loops.
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
  *
- * Return:
- *   ADV_TRUE(1) - interrupt was pending
- *   ADV_FALSE(0) - no interrupt was pending
+ * Note: Chip is stopped on entry.
  */
-static int AdvISR(ADV_DVC_VAR *asc_dvc)
+static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
 {
        AdvPortAddr iop_base;
-       uchar int_stat;
-       ushort target_bit;
-       ADV_CARR_T *free_carrp;
-       ADV_VADDR irq_next_vpa;
-       int flags;
-       ADV_SCSI_REQ_Q *scsiq;
-
-       flags = DvcEnterCritical();
+       ushort warn_code;
+       ADVEEP_38C1600_CONFIG eep_config;
+       uchar tid, termination;
+       ushort sdtr_speed = 0;
 
        iop_base = asc_dvc->iop_base;
 
-       /* Reading the register clears the interrupt. */
-       int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
-
-       if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
-                        ADV_INTR_STATUS_INTRC)) == 0) {
-               DvcLeaveCritical(flags);
-               return ADV_FALSE;
-       }
+       warn_code = 0;
 
        /*
-        * Notify the driver of an asynchronous microcode condition by
-        * calling the ADV_DVC_VAR.async_callback function. The function
-        * is passed the microcode ASC_MC_INTRB_CODE byte value.
+        * Read the board's EEPROM configuration.
+        *
+        * Set default values if a bad checksum is found.
         */
-       if (int_stat & ADV_INTR_STATUS_INTRB) {
-               uchar intrb_code;
-
-               AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
-
-               if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
-                   asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
-                       if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
-                           asc_dvc->carr_pending_cnt != 0) {
-                               AdvWriteByteRegister(iop_base, IOPB_TICKLE,
-                                                    ADV_TICKLE_A);
-                               if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
-                                       AdvWriteByteRegister(iop_base,
-                                                            IOPB_TICKLE,
-                                                            ADV_TICKLE_NOP);
-                               }
-                       }
-               }
-
-               if (asc_dvc->async_callback != 0) {
-                       (*asc_dvc->async_callback) (asc_dvc, intrb_code);
-               }
-       }
+       if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
+           eep_config.check_sum) {
+               struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
+               warn_code |= ASC_WARN_EEPROM_CHKSUM;
 
-       /*
-        * Check if the IRQ stopper carrier contains a completed request.
-        */
-       while (((irq_next_vpa =
-                le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
                /*
-                * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
-                * The RISC will have set 'areq_vpa' to a virtual address.
-                *
-                * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
-                * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
-                * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
-                * in AdvExeScsiQueue().
+                * Set EEPROM default values.
                 */
-               scsiq = (ADV_SCSI_REQ_Q *)
-                   ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
+               memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
+                       sizeof(ADVEEP_38C1600_CONFIG));
 
-               /*
-                * Request finished with good status and the queue was not
-                * DMAed to host memory by the firmware. Set all status fields
-                * to indicate good status.
-                */
-               if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
-                       scsiq->done_status = QD_NO_ERROR;
-                       scsiq->host_status = scsiq->scsi_status = 0;
-                       scsiq->data_cnt = 0L;
+               if (PCI_FUNC(pdev->devfn) != 0) {
+                       u8 ints;
+                       /*
+                        * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
+                        * and old Mac system booting problem. The Expansion
+                        * ROM must be disabled in Function 1 for these systems
+                        */
+                       eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
+                       /*
+                        * Clear the INTAB (bit 11) if the GPIO 0 input
+                        * indicates the Function 1 interrupt line is wired
+                        * to INTB.
+                        *
+                        * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
+                        *   1 - Function 1 interrupt line wired to INT A.
+                        *   0 - Function 1 interrupt line wired to INT B.
+                        *
+                        * Note: Function 0 is always wired to INTA.
+                        * Put all 5 GPIO bits in input mode and then read
+                        * their input values.
+                        */
+                       AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
+                       ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
+                       if ((ints & 0x01) == 0)
+                               eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
                }
 
                /*
-                * Advance the stopper pointer to the next carrier
-                * ignoring the lower four bits. Free the previous
-                * stopper carrier.
+                * Assume the 6 byte board serial number that was read from
+                * EEPROM is correct even if the EEPROM checksum failed.
                 */
-               free_carrp = asc_dvc->irq_sp;
-               asc_dvc->irq_sp = (ADV_CARR_T *)
-                   ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
-
-               free_carrp->next_vpa =
-                   cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
-               asc_dvc->carr_freelist = free_carrp;
-               asc_dvc->carr_pending_cnt--;
+               eep_config.serial_number_word3 =
+                       AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
+               eep_config.serial_number_word2 =
+                       AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
+               eep_config.serial_number_word1 =
+                       AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
 
-               ASC_ASSERT(scsiq != NULL);
-               target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
+               AdvSet38C1600EEPConfig(iop_base, &eep_config);
+       }
 
-               /*
-                * Clear request microcode control flag.
-                */
-               scsiq->cntl = 0;
+       /*
+        * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
+        * EEPROM configuration that was read.
+        *
+        * This is the mapping of EEPROM fields to Adv Library fields.
+        */
+       asc_dvc->wdtr_able = eep_config.wdtr_able;
+       asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
+       asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
+       asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
+       asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
+       asc_dvc->ppr_able = 0;
+       asc_dvc->tagqng_able = eep_config.tagqng_able;
+       asc_dvc->cfg->disc_enable = eep_config.disc_enable;
+       asc_dvc->max_host_qng = eep_config.max_host_qng;
+       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+       asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
+       asc_dvc->start_motor = eep_config.start_motor;
+       asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
+       asc_dvc->bios_ctrl = eep_config.bios_ctrl;
+       asc_dvc->no_scam = eep_config.scam_tolerant;
 
-               /*
-                * If the command that completed was a SCSI INQUIRY and
-                * LUN 0 was sent the command, then process the INQUIRY
-                * command information for the device.
-                *
-                * Note: If data returned were either VPD or CmdDt data,
-                * don't process the INQUIRY command information for
-                * the device, otherwise may erroneously set *_able bits.
-                */
-               if (scsiq->done_status == QD_NO_ERROR &&
-                   scsiq->cdb[0] == INQUIRY &&
-                   scsiq->target_lun == 0 &&
-                   (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT)
-                   == ADV_INQ_RTN_STD_INQUIRY_DATA) {
-                       AdvInquiryHandling(asc_dvc, scsiq);
+       /*
+        * For every Target ID if any of its 'sdtr_speed[1234]' bits
+        * are set, then set an 'sdtr_able' bit for it.
+        */
+       asc_dvc->sdtr_able = 0;
+       for (tid = 0; tid <= ASC_MAX_TID; tid++) {
+               if (tid == 0) {
+                       sdtr_speed = asc_dvc->sdtr_speed1;
+               } else if (tid == 4) {
+                       sdtr_speed = asc_dvc->sdtr_speed2;
+               } else if (tid == 8) {
+                       sdtr_speed = asc_dvc->sdtr_speed3;
+               } else if (tid == 12) {
+                       sdtr_speed = asc_dvc->sdtr_speed4;
                }
-
-               /*
-                * Notify the driver of the completed request by passing
-                * the ADV_SCSI_REQ_Q pointer to its callback function.
-                */
-               scsiq->a_flag |= ADV_SCSIQ_DONE;
-               (*asc_dvc->isr_callback) (asc_dvc, scsiq);
-               /*
-                * Note: After the driver callback function is called, 'scsiq'
-                * can no longer be referenced.
-                *
-                * Fall through and continue processing other completed
-                * requests...
-                */
-
-               /*
-                * Disable interrupts again in case the driver inadvertently
-                * enabled interrupts in its callback function.
-                *
-                * The DvcEnterCritical() return value is ignored, because
-                * the 'flags' saved when AdvISR() was first entered will be
-                * used to restore the interrupt flag on exit.
-                */
-               (void)DvcEnterCritical();
+               if (sdtr_speed & ASC_MAX_TID) {
+                       asc_dvc->sdtr_able |= (1 << tid);
+               }
+               sdtr_speed >>= 4;
        }
-       DvcLeaveCritical(flags);
-       return ADV_TRUE;
-}
-
-/*
- * Send an idle command to the chip and wait for completion.
- *
- * Command completion is polled for once per microsecond.
- *
- * The function can be called from anywhere including an interrupt handler.
- * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
- * functions to prevent reentrancy.
- *
- * Return Values:
- *   ADV_TRUE - command completed successfully
- *   ADV_FALSE - command failed
- *   ADV_ERROR - command timed out
- */
-static int
-AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
-              ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
-{
-       ulong last_int_level;
-       int result;
-       ADV_DCNT i, j;
-       AdvPortAddr iop_base;
 
-       last_int_level = DvcEnterCritical();
+       /*
+        * Set the host maximum queuing (max. 253, min. 16) and the per device
+        * maximum queuing (max. 63, min. 4).
+        */
+       if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
+               eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+       } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
+               /* If the value is zero, assume it is uninitialized. */
+               if (eep_config.max_host_qng == 0) {
+                       eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+               } else {
+                       eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
+               }
+       }
 
-       iop_base = asc_dvc->iop_base;
+       if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
+               eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+       } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
+               /* If the value is zero, assume it is uninitialized. */
+               if (eep_config.max_dvc_qng == 0) {
+                       eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+               } else {
+                       eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
+               }
+       }
 
        /*
-        * Clear the idle command status which is set by the microcode
-        * to a non-zero value to indicate when the command is completed.
-        * The non-zero result is one of the IDLE_CMD_STATUS_* values
-        * defined in a_advlib.h.
+        * If 'max_dvc_qng' is greater than 'max_host_qng', then
+        * set 'max_dvc_qng' to 'max_host_qng'.
         */
-       AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
+       if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
+               eep_config.max_dvc_qng = eep_config.max_host_qng;
+       }
 
        /*
-        * Write the idle command value after the idle command parameter
-        * has been written to avoid a race condition. If the order is not
-        * followed, the microcode may process the idle command before the
-        * parameters have been written to LRAM.
+        * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
+        * values based on possibly adjusted EEPROM values.
         */
-       AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
-                               cpu_to_le32(idle_cmd_parameter));
-       AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
+       asc_dvc->max_host_qng = eep_config.max_host_qng;
+       asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
 
        /*
-        * Tickle the RISC to tell it to process the idle command.
+        * If the EEPROM 'termination' field is set to automatic (0), then set
+        * the ASC_DVC_CFG 'termination' field to automatic also.
+        *
+        * If the termination is specified with a non-zero 'termination'
+        * value check that a legal value is set and set the ASC_DVC_CFG
+        * 'termination' field appropriately.
         */
-       AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
-       if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
-               /*
-                * Clear the tickle value. In the ASC-3550 the RISC flag
-                * command 'clr_tickle_b' does not work unless the host
-                * value is cleared.
-                */
-               AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
+       if (eep_config.termination_se == 0) {
+               termination = 0;        /* auto termination for SE */
+       } else {
+               /* Enable manual control with low off / high off. */
+               if (eep_config.termination_se == 1) {
+                       termination = 0;
+
+                       /* Enable manual control with low off / high on. */
+               } else if (eep_config.termination_se == 2) {
+                       termination = TERM_SE_HI;
+
+                       /* Enable manual control with low on / high on. */
+               } else if (eep_config.termination_se == 3) {
+                       termination = TERM_SE;
+               } else {
+                       /*
+                        * The EEPROM 'termination_se' field contains a bad value.
+                        * Use automatic termination instead.
+                        */
+                       termination = 0;
+                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
+               }
        }
 
-       /* Wait for up to 100 millisecond for the idle command to timeout. */
-       for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
-               /* Poll once each microsecond for command completion. */
-               for (j = 0; j < SCSI_US_PER_MSEC; j++) {
-                       AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
-                                       result);
-                       if (result != 0) {
-                               DvcLeaveCritical(last_int_level);
-                               return result;
-                       }
-                       DvcDelayMicroSecond(asc_dvc, (ushort)1);
+       if (eep_config.termination_lvd == 0) {
+               asc_dvc->cfg->termination = termination;        /* auto termination for LVD */
+       } else {
+               /* Enable manual control with low off / high off. */
+               if (eep_config.termination_lvd == 1) {
+                       asc_dvc->cfg->termination = termination;
+
+                       /* Enable manual control with low off / high on. */
+               } else if (eep_config.termination_lvd == 2) {
+                       asc_dvc->cfg->termination = termination | TERM_LVD_HI;
+
+                       /* Enable manual control with low on / high on. */
+               } else if (eep_config.termination_lvd == 3) {
+                       asc_dvc->cfg->termination = termination | TERM_LVD;
+               } else {
+                       /*
+                        * The EEPROM 'termination_lvd' field contains a bad value.
+                        * Use automatic termination instead.
+                        */
+                       asc_dvc->cfg->termination = termination;
+                       warn_code |= ASC_WARN_EEPROM_TERMINATION;
                }
        }
 
-       ASC_ASSERT(0);          /* The idle command should never timeout. */
-       DvcLeaveCritical(last_int_level);
-       return ADV_ERROR;
+       return warn_code;
 }
 
 /*
- * Inquiry Information Byte 7 Handling
+ * Initialize the ADV_DVC_VAR structure.
+ *
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
  *
- * Handle SCSI Inquiry Command information for a device by setting
- * microcode operating variables that affect WDTR, SDTR, and Tag
- * Queuing.
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
  */
-static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
+static int __devinit
+AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
 {
-       AdvPortAddr iop_base;
-       uchar tid;
-       ADV_SCSI_INQUIRY *inq;
-       ushort tidmask;
-       ushort cfg_word;
+       struct asc_board *board = shost_priv(shost);
+       ADV_DVC_VAR *asc_dvc = &board->dvc_var.adv_dvc_var;
+       unsigned short warn_code = 0;
+       AdvPortAddr iop_base = asc_dvc->iop_base;
+       u16 cmd;
+       int status;
+
+       asc_dvc->err_code = 0;
 
        /*
-        * AdvInquiryHandling() requires up to INQUIRY information Byte 7
-        * to be available.
-        *
-        * If less than 8 bytes of INQUIRY information were requested or less
-        * than 8 bytes were transferred, then return. cdb[4] is the request
-        * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
-        * microcode to the transfer residual count.
+        * Save the state of the PCI Configuration Command Register
+        * "Parity Error Response Control" Bit. If the bit is clear (0),
+        * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
+        * DMA parity errors.
         */
+       asc_dvc->cfg->control_flag = 0;
+       pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+       if ((cmd & PCI_COMMAND_PARITY) == 0)
+               asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
 
-       if (scsiq->cdb[4] < 8 ||
-           (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) {
-               return;
-       }
+       asc_dvc->cfg->chip_version =
+           AdvGetChipVersion(iop_base, asc_dvc->bus_type);
 
-       iop_base = asc_dvc->iop_base;
-       tid = scsiq->target_id;
+       ASC_DBG(1, "iopb_chip_id_1: 0x%x 0x%x\n",
+                (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
+                (ushort)ADV_CHIP_ID_BYTE);
 
-       inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr;
+       ASC_DBG(1, "iopw_chip_id_0: 0x%x 0x%x\n",
+                (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
+                (ushort)ADV_CHIP_ID_WORD);
 
        /*
-        * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
+        * Reset the chip to start and allow register writes.
         */
-       if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) {
-               return;
+       if (AdvFindSignature(iop_base) == 0) {
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+               return ADV_ERROR;
        } else {
                /*
-                * INQUIRY Byte 7 Handling
-                *
-                * Use a device's INQUIRY byte 7 to determine whether it
-                * supports WDTR, SDTR, and Tag Queuing. If the feature
-                * is enabled in the EEPROM and the device supports the
-                * feature, then enable it in the microcode.
-                */
-
-               tidmask = ADV_TID_TO_TIDMASK(tid);
-
-               /*
-                * Wide Transfers
-                *
-                * If the EEPROM enabled WDTR for the device and the device
-                * supports wide bus (16 bit) transfers, then turn on the
-                * device's 'wdtr_able' bit and write the new value to the
-                * microcode.
+                * The caller must set 'chip_type' to a valid setting.
                 */
-               if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) {
-                       AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
-                       if ((cfg_word & tidmask) == 0) {
-                               cfg_word |= tidmask;
-                               AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
-                                                cfg_word);
-
-                               /*
-                                * Clear the microcode "SDTR negotiation" and "WDTR
-                                * negotiation" done indicators for the target to cause
-                                * it to negotiate with the new setting set above.
-                                * WDTR when accepted causes the target to enter
-                                * asynchronous mode, so SDTR must be negotiated.
-                                */
-                               AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE,
-                                               cfg_word);
-                               cfg_word &= ~tidmask;
-                               AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE,
-                                                cfg_word);
-                               AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE,
-                                               cfg_word);
-                               cfg_word &= ~tidmask;
-                               AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE,
-                                                cfg_word);
-                       }
+               if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
+                   asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
+                   asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
+                       asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
+                       return ADV_ERROR;
                }
 
                /*
-                * Synchronous Transfers
-                *
-                * If the EEPROM enabled SDTR for the device and the device
-                * supports synchronous transfers, then turn on the device's
-                * 'sdtr_able' bit. Write the new value to the microcode.
+                * Reset Chip.
                 */
-               if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) {
-                       AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
-                       if ((cfg_word & tidmask) == 0) {
-                               cfg_word |= tidmask;
-                               AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
-                                                cfg_word);
+               AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
+                                    ADV_CTRL_REG_CMD_RESET);
+               mdelay(100);
+               AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
+                                    ADV_CTRL_REG_CMD_WR_IO_REG);
 
-                               /*
-                                * Clear the microcode "SDTR negotiation" done indicator
-                                * for the target to cause it to negotiate with the new
-                                * setting set above.
-                                */
-                               AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE,
-                                               cfg_word);
-                               cfg_word &= ~tidmask;
-                               AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE,
-                                                cfg_word);
-                       }
-               }
-               /*
-                * If the Inquiry data included enough space for the SPI-3
-                * Clocking field, then check if DT mode is supported.
-                */
-               if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 &&
-                   (scsiq->cdb[4] >= 57 ||
-                    (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) {
-                       /*
-                        * PPR (Parallel Protocol Request) Capable
-                        *
-                        * If the device supports DT mode, then it must be PPR capable.
-                        * The PPR message will be used in place of the SDTR and WDTR
-                        * messages to negotiate synchronous speed and offset, transfer
-                        * width, and protocol options.
-                        */
-                       if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) {
-                               AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE,
-                                               asc_dvc->ppr_able);
-                               asc_dvc->ppr_able |= tidmask;
-                               AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE,
-                                                asc_dvc->ppr_able);
-                       }
+               if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
+                       status = AdvInitFrom38C1600EEP(asc_dvc);
+               } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
+                       status = AdvInitFrom38C0800EEP(asc_dvc);
+               } else {
+                       status = AdvInitFrom3550EEP(asc_dvc);
                }
+               warn_code |= status;
+       }
 
-               /*
-                * If the EEPROM enabled Tag Queuing for the device and the
-                * device supports Tag Queueing, then turn on the device's
-                * 'tagqng_enable' bit in the microcode and set the microcode
-                * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
-                * value.
-                *
-                * Tag Queuing is disabled for the BIOS which runs in polled
-                * mode and would see no benefit from Tag Queuing. Also by
-                * disabling Tag Queuing in the BIOS devices with Tag Queuing
-                * bugs will at least work with the BIOS.
-                */
-               if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) {
-                       AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
-                       cfg_word |= tidmask;
-                       AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
-                                        cfg_word);
+       if (warn_code != 0)
+               shost_printk(KERN_WARNING, shost, "warning: 0x%x\n", warn_code);
 
-                       AdvWriteByteLram(iop_base,
-                                        ASC_MC_NUMBER_OF_MAX_CMD + tid,
-                                        asc_dvc->max_dvc_qng);
-               }
-       }
+       if (asc_dvc->err_code)
+               shost_printk(KERN_ERR, shost, "error code 0x%x\n",
+                               asc_dvc->err_code);
+
+       return asc_dvc->err_code;
 }
+#endif
 
-MODULE_LICENSE("Dual BSD/GPL");
+static struct scsi_host_template advansys_template = {
+       .proc_name = DRV_NAME,
+#ifdef CONFIG_PROC_FS
+       .proc_info = advansys_proc_info,
+#endif
+       .name = DRV_NAME,
+       .info = advansys_info,
+       .queuecommand = advansys_queuecommand,
+       .eh_bus_reset_handler = advansys_reset,
+       .bios_param = advansys_biosparam,
+       .slave_configure = advansys_slave_configure,
+       /*
+        * Because the driver may control an ISA adapter 'unchecked_isa_dma'
+        * must be set. The flag will be cleared in advansys_board_found
+        * for non-ISA adapters.
+        */
+       .unchecked_isa_dma = 1,
+       /*
+        * All adapters controlled by this driver are capable of large
+        * scatter-gather lists. According to the mid-level SCSI documentation
+        * this obviates any performance gain provided by setting
+        * 'use_clustering'. But empirically while CPU utilization is increased
+        * by enabling clustering, I/O throughput increases as well.
+        */
+       .use_clustering = ENABLE_CLUSTERING,
+};
 
-static struct Scsi_Host *__devinit
-advansys_board_found(int iop, struct device *dev, int bus_type)
+static int __devinit advansys_wide_init_chip(struct Scsi_Host *shost)
 {
-       struct Scsi_Host *shost;
-       struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
-       asc_board_t *boardp;
-       ASC_DVC_VAR *asc_dvc_varp = NULL;
-       ADV_DVC_VAR *adv_dvc_varp = NULL;
-       adv_sgblk_t *sgp = NULL;
-       int share_irq = FALSE;
-       int iolen = 0;
-       ADV_PADDR pci_memory_address;
+       struct asc_board *board = shost_priv(shost);
+       struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
+       int req_cnt = 0;
+       adv_req_t *reqp = NULL;
+       int sg_cnt = 0;
+       adv_sgblk_t *sgp;
        int warn_code, err_code;
-       int ret;
 
        /*
-        * Adapter found.
-        *
-        * Register the adapter, get its configuration, and
-        * initialize it.
+        * Allocate buffer carrier structures. The total size
+        * is about 4 KB, so allocate all at once.
         */
-       ASC_DBG(2, "advansys_board_found: scsi_register()\n");
-       shost = scsi_register(&driver_template, sizeof(asc_board_t));
+       adv_dvc->carrier_buf = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
+       ASC_DBG(1, "carrier_buf 0x%p\n", adv_dvc->carrier_buf);
 
-       if (!shost)
-               return NULL;
+       if (!adv_dvc->carrier_buf)
+               goto kmalloc_failed;
+
+       /*
+        * Allocate up to 'max_host_qng' request structures for the Wide
+        * board. The total size is about 16 KB, so allocate all at once.
+        * If the allocation fails decrement and try again.
+        */
+       for (req_cnt = adv_dvc->max_host_qng; req_cnt > 0; req_cnt--) {
+               reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
 
-       /* Save a pointer to the Scsi_Host of each board found. */
-       asc_host[asc_board_count++] = shost;
+               ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt,
+                        (ulong)sizeof(adv_req_t) * req_cnt);
+
+               if (reqp)
+                       break;
+       }
 
-       /* Initialize private per board data */
-       boardp = ASC_BOARDP(shost);
-       memset(boardp, 0, sizeof(asc_board_t));
-       boardp->id = asc_board_count - 1;
+       if (!reqp)
+               goto kmalloc_failed;
 
-       /* Initialize spinlock. */
-       spin_lock_init(&boardp->lock);
+       adv_dvc->orig_reqp = reqp;
 
        /*
-        * Handle both narrow and wide boards.
-        *
-        * If a Wide board was detected, set the board structure
-        * wide board flag. Set-up the board structure based on
-        * the board type.
+        * Allocate up to ADV_TOT_SG_BLOCK request structures for
+        * the Wide board. Each structure is about 136 bytes.
         */
-#ifdef CONFIG_PCI
-       if (bus_type == ASC_IS_PCI &&
-           (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
-            pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
-            pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
-               boardp->flags |= ASC_IS_WIDE_BOARD;
+       board->adv_sgblkp = NULL;
+       for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
+               sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
+
+               if (!sgp)
+                       break;
+
+               sgp->next_sgblkp = board->adv_sgblkp;
+               board->adv_sgblkp = sgp;
+
        }
-#endif /* CONFIG_PCI */
+
+       ASC_DBG(1, "sg_cnt %d * %lu = %lu bytes\n", sg_cnt, sizeof(adv_sgblk_t),
+                sizeof(adv_sgblk_t) * sg_cnt);
+
+       if (!board->adv_sgblkp)
+               goto kmalloc_failed;
+
+       /*
+        * Point 'adv_reqp' to the request structures and
+        * link them together.
+        */
+       req_cnt--;
+       reqp[req_cnt].next_reqp = NULL;
+       for (; req_cnt > 0; req_cnt--) {
+               reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
+       }
+       board->adv_reqp = &reqp[0];
+
+       if (adv_dvc->chip_type == ADV_CHIP_ASC3550) {
+               ASC_DBG(2, "AdvInitAsc3550Driver()\n");
+               warn_code = AdvInitAsc3550Driver(adv_dvc);
+       } else if (adv_dvc->chip_type == ADV_CHIP_ASC38C0800) {
+               ASC_DBG(2, "AdvInitAsc38C0800Driver()\n");
+               warn_code = AdvInitAsc38C0800Driver(adv_dvc);
+       } else {
+               ASC_DBG(2, "AdvInitAsc38C1600Driver()\n");
+               warn_code = AdvInitAsc38C1600Driver(adv_dvc);
+       }
+       err_code = adv_dvc->err_code;
+
+       if (warn_code || err_code) {
+               shost_printk(KERN_WARNING, shost, "error: warn 0x%x, error "
+                       "0x%x\n", warn_code, err_code);
+       }
+
+       goto exit;
+
+ kmalloc_failed:
+       shost_printk(KERN_ERR, shost, "error: kmalloc() failed\n");
+       err_code = ADV_ERROR;
+ exit:
+       return err_code;
+}
+
+static void advansys_wide_free_mem(struct asc_board *board)
+{
+       struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
+       kfree(adv_dvc->carrier_buf);
+       adv_dvc->carrier_buf = NULL;
+       kfree(adv_dvc->orig_reqp);
+       adv_dvc->orig_reqp = board->adv_reqp = NULL;
+       while (board->adv_sgblkp) {
+               adv_sgblk_t *sgp = board->adv_sgblkp;
+               board->adv_sgblkp = sgp->next_sgblkp;
+               kfree(sgp);
+       }
+}
+
+static int __devinit advansys_board_found(struct Scsi_Host *shost,
+                                         unsigned int iop, int bus_type)
+{
+       struct pci_dev *pdev;
+       struct asc_board *boardp = shost_priv(shost);
+       ASC_DVC_VAR *asc_dvc_varp = NULL;
+       ADV_DVC_VAR *adv_dvc_varp = NULL;
+       int share_irq, warn_code, ret;
+
+       pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL;
 
        if (ASC_NARROW_BOARD(boardp)) {
-               ASC_DBG(1, "advansys_board_found: narrow board\n");
+               ASC_DBG(1, "narrow board\n");
                asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
                asc_dvc_varp->bus_type = bus_type;
                asc_dvc_varp->drv_ptr = boardp;
                asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
-               asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
                asc_dvc_varp->iop_base = iop;
-               asc_dvc_varp->isr_callback = asc_isr_callback;
        } else {
-               ASC_DBG(1, "advansys_board_found: wide board\n");
+#ifdef CONFIG_PCI
                adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
                adv_dvc_varp->drv_ptr = boardp;
                adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
-               adv_dvc_varp->isr_callback = adv_isr_callback;
-               adv_dvc_varp->async_callback = adv_async_callback;
-#ifdef CONFIG_PCI
                if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
-                       ASC_DBG(1, "advansys_board_found: ASC-3550\n");
+                       ASC_DBG(1, "wide board ASC-3550\n");
                        adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
                } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
-                       ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
+                       ASC_DBG(1, "wide board ASC-38C0800\n");
                        adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
                } else {
-                       ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
+                       ASC_DBG(1, "wide board ASC-38C1600\n");
                        adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
                }
-#endif /* CONFIG_PCI */
 
-               /*
-                * Map the board's registers into virtual memory for
-                * PCI slave access. Only memory accesses are used to
-                * access the board's registers.
-                *
-                * Note: The PCI register base address is not always
-                * page aligned, but the address passed to ioremap()
-                * must be page aligned. It is guaranteed that the
-                * PCI register base address will not cross a page
-                * boundary.
-                */
-               if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-                       iolen = ADV_3550_IOLEN;
-               } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-                       iolen = ADV_38C0800_IOLEN;
-               } else {
-                       iolen = ADV_38C1600_IOLEN;
-               }
-#ifdef CONFIG_PCI
-               pci_memory_address = pci_resource_start(pdev, 1);
-               ASC_DBG1(1,
-                        "advansys_board_found: pci_memory_address: 0x%lx\n",
-                        (ulong)pci_memory_address);
-               if ((boardp->ioremap_addr =
-                    ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) {
-                       ASC_PRINT3
-                           ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
-                            boardp->id, pci_memory_address, iolen);
-                       scsi_unregister(shost);
-                       asc_board_count--;
-                       return NULL;
+               boardp->asc_n_io_port = pci_resource_len(pdev, 1);
+               boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
+                                              boardp->asc_n_io_port);
+               if (!boardp->ioremap_addr) {
+                       shost_printk(KERN_ERR, shost, "ioremap(%lx, %d) "
+                                       "returned NULL\n",
+                                       (long)pci_resource_start(pdev, 1),
+                                       boardp->asc_n_io_port);
+                       ret = -ENODEV;
+                       goto err_shost;
                }
-               ASC_DBG1(1,
-                        "advansys_board_found: ioremap_addr: 0x%lx\n",
-                        (ulong)boardp->ioremap_addr);
-               adv_dvc_varp->iop_base = (AdvPortAddr)
-                   (boardp->ioremap_addr +
-                    (pci_memory_address - (pci_memory_address & PAGE_MASK)));
-               ASC_DBG1(1,
-                        "advansys_board_found: iop_base: 0x%lx\n",
-                        adv_dvc_varp->iop_base);
-#endif /* CONFIG_PCI */
+               adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr;
+               ASC_DBG(1, "iop_base: 0x%p\n", adv_dvc_varp->iop_base);
 
                /*
                 * Even though it isn't used to access wide boards, other
@@ -17907,9 +13445,9 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                 */
                boardp->ioport = iop;
 
-               ASC_DBG2(1,
-                        "advansys_board_found: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
-                        (ushort)inp(iop + 1), (ushort)inpw(iop));
+               ASC_DBG(1, "iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n",
+                               (ushort)inp(iop + 1), (ushort)inpw(iop));
+#endif /* CONFIG_PCI */
        }
 
 #ifdef CONFIG_PROC_FS
@@ -17917,18 +13455,16 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
         * Allocate buffer for printing information from
         * /proc/scsi/advansys/[0...].
         */
-       if ((boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
-               ASC_PRINT3
-                   ("advansys_board_found: board %d: kmalloc(%d, %d) returned NULL\n",
-                    boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
-               scsi_unregister(shost);
-               asc_board_count--;
-               return NULL;
+       boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
+       if (!boardp->prtbuf) {
+               shost_printk(KERN_ERR, shost, "kmalloc(%d) returned NULL\n",
+                               ASC_PRTBUF_SIZE);
+               ret = -ENOMEM;
+               goto err_unmap;
        }
 #endif /* CONFIG_PROC_FS */
 
        if (ASC_NARROW_BOARD(boardp)) {
-               asc_dvc_varp->cfg->dev = dev;
                /*
                 * Set the board bus type and PCI IRQ before
                 * calling AscInitGetConfig().
@@ -17937,127 +13473,56 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 #ifdef CONFIG_ISA
                case ASC_IS_ISA:
                        shost->unchecked_isa_dma = TRUE;
-                       share_irq = FALSE;
+                       share_irq = 0;
                        break;
                case ASC_IS_VL:
                        shost->unchecked_isa_dma = FALSE;
-                       share_irq = FALSE;
+                       share_irq = 0;
                        break;
                case ASC_IS_EISA:
                        shost->unchecked_isa_dma = FALSE;
-                       share_irq = TRUE;
+                       share_irq = IRQF_SHARED;
                        break;
 #endif /* CONFIG_ISA */
 #ifdef CONFIG_PCI
                case ASC_IS_PCI:
-                       shost->irq = asc_dvc_varp->irq_no = pdev->irq;
-                       asc_dvc_varp->cfg->pci_slot_info =
-                           ASC_PCI_MKID(pdev->bus->number,
-                                        PCI_SLOT(pdev->devfn),
-                                        PCI_FUNC(pdev->devfn));
                        shost->unchecked_isa_dma = FALSE;
-                       share_irq = TRUE;
+                       share_irq = IRQF_SHARED;
                        break;
 #endif /* CONFIG_PCI */
                default:
-                       ASC_PRINT2
-                           ("advansys_board_found: board %d: unknown adapter type: %d\n",
-                            boardp->id, asc_dvc_varp->bus_type);
+                       shost_printk(KERN_ERR, shost, "unknown adapter type: "
+                                       "%d\n", asc_dvc_varp->bus_type);
                        shost->unchecked_isa_dma = TRUE;
-                       share_irq = FALSE;
+                       share_irq = 0;
                        break;
                }
-       } else {
-               adv_dvc_varp->cfg->dev = dev;
-               /*
-                * For Wide boards set PCI information before calling
-                * AdvInitGetConfig().
-                */
-#ifdef CONFIG_PCI
-               shost->irq = adv_dvc_varp->irq_no = pdev->irq;
-               adv_dvc_varp->cfg->pci_slot_info =
-                   ASC_PCI_MKID(pdev->bus->number,
-                                PCI_SLOT(pdev->devfn),
-                                PCI_FUNC(pdev->devfn));
-               shost->unchecked_isa_dma = FALSE;
-               share_irq = TRUE;
-#endif /* CONFIG_PCI */
-       }
 
-       /*
-        * Read the board configuration.
-        */
-       if (ASC_NARROW_BOARD(boardp)) {
                /*
                 * NOTE: AscInitGetConfig() may change the board's
                 * bus_type value. The bus_type value should no
                 * longer be used. If the bus_type field must be
                 * referenced only use the bit-wise AND operator "&".
                 */
-               ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
-               switch (ret = AscInitGetConfig(asc_dvc_varp)) {
-               case 0: /* No error */
-                       break;
-               case ASC_WARN_IO_PORT_ROTATE:
-                       ASC_PRINT1
-                           ("AscInitGetConfig: board %d: I/O port address modified\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_AUTO_CONFIG:
-                       ASC_PRINT1
-                           ("AscInitGetConfig: board %d: I/O port increment switch enabled\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_EEPROM_CHKSUM:
-                       ASC_PRINT1
-                           ("AscInitGetConfig: board %d: EEPROM checksum error\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_IRQ_MODIFIED:
-                       ASC_PRINT1
-                           ("AscInitGetConfig: board %d: IRQ modified\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_CMD_QNG_CONFLICT:
-                       ASC_PRINT1
-                           ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
-                            boardp->id);
-                       break;
-               default:
-                       ASC_PRINT2
-                           ("AscInitGetConfig: board %d: unknown warning: 0x%x\n",
-                            boardp->id, ret);
-                       break;
-               }
-               if ((err_code = asc_dvc_varp->err_code) != 0) {
-                       ASC_PRINT3
-                           ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
-                            boardp->id,
-                            asc_dvc_varp->init_state, asc_dvc_varp->err_code);
-               }
+               ASC_DBG(2, "AscInitGetConfig()\n");
+               ret = AscInitGetConfig(shost) ? -ENODEV : 0;
        } else {
-               ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
-               if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
-                       ASC_PRINT2
-                           ("AdvInitGetConfig: board %d: warning: 0x%x\n",
-                            boardp->id, ret);
-               }
-               if ((err_code = adv_dvc_varp->err_code) != 0) {
-                       ASC_PRINT2
-                           ("AdvInitGetConfig: board %d error: err_code 0x%x\n",
-                            boardp->id, adv_dvc_varp->err_code);
-               }
-       }
+#ifdef CONFIG_PCI
+               /*
+                * For Wide boards set PCI information before calling
+                * AdvInitGetConfig().
+                */
+               shost->unchecked_isa_dma = FALSE;
+               share_irq = IRQF_SHARED;
+               ASC_DBG(2, "AdvInitGetConfig()\n");
 
-       if (err_code != 0) {
-#ifdef CONFIG_PROC_FS
-               kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-               scsi_unregister(shost);
-               asc_board_count--;
-               return NULL;
+               ret = AdvInitGetConfig(pdev, shost) ? -ENODEV : 0;
+#endif /* CONFIG_PCI */
        }
 
+       if (ret)
+               goto err_free_proc;
+
        /*
         * Save the EEPROM configuration so that it can be displayed
         * from /proc/scsi/advansys/[0...].
@@ -18098,61 +13563,10 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                /*
                 * Modify board configuration.
                 */
-               ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
-               switch (ret = AscInitSetConfig(asc_dvc_varp)) {
-               case 0: /* No error. */
-                       break;
-               case ASC_WARN_IO_PORT_ROTATE:
-                       ASC_PRINT1
-                           ("AscInitSetConfig: board %d: I/O port address modified\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_AUTO_CONFIG:
-                       ASC_PRINT1
-                           ("AscInitSetConfig: board %d: I/O port increment switch enabled\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_EEPROM_CHKSUM:
-                       ASC_PRINT1
-                           ("AscInitSetConfig: board %d: EEPROM checksum error\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_IRQ_MODIFIED:
-                       ASC_PRINT1
-                           ("AscInitSetConfig: board %d: IRQ modified\n",
-                            boardp->id);
-                       break;
-               case ASC_WARN_CMD_QNG_CONFLICT:
-                       ASC_PRINT1
-                           ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
-                            boardp->id);
-                       break;
-               default:
-                       ASC_PRINT2
-                           ("AscInitSetConfig: board %d: unknown warning: 0x%x\n",
-                            boardp->id, ret);
-                       break;
-               }
-               if (asc_dvc_varp->err_code != 0) {
-                       ASC_PRINT3
-                           ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n",
-                            boardp->id,
-                            asc_dvc_varp->init_state, asc_dvc_varp->err_code);
-#ifdef CONFIG_PROC_FS
-                       kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-                       scsi_unregister(shost);
-                       asc_board_count--;
-                       return NULL;
-               }
-
-               /*
-                * Finish initializing the 'Scsi_Host' structure.
-                */
-               /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
-               if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
-                       shost->irq = asc_dvc_varp->irq_no;
-               }
+               ASC_DBG(2, "AscInitSetConfig()\n");
+               ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0;
+               if (ret)
+                       goto err_free_proc;
        } else {
                ADVEEP_3550_CONFIG *ep_3550;
                ADVEEP_38C0800_CONFIG *ep_38C0800;
@@ -18246,11 +13660,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                 */
                boardp->init_tidmask |=
                    ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
-
-               /*
-                * Finish initializing the 'Scsi_Host' structure.
-                */
-               shost->irq = adv_dvc_varp->irq_no;
        }
 
        /*
@@ -18262,6 +13671,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
        if (ASC_NARROW_BOARD(boardp)) {
                shost->max_id = ASC_MAX_TID + 1;
                shost->max_lun = ASC_MAX_LUN + 1;
+               shost->max_cmd_len = ASC_MAX_CDB_LEN;
 
                shost->io_port = asc_dvc_varp->iop_base;
                boardp->asc_n_io_port = ASC_IOADR_GAP;
@@ -18272,6 +13682,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
        } else {
                shost->max_id = ADV_MAX_TID + 1;
                shost->max_lun = ADV_MAX_LUN + 1;
+               shost->max_cmd_len = ADV_MAX_CDB_LEN;
 
                /*
                 * Save the I/O Port address and length even though
@@ -18280,7 +13691,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                 * PCI Memory Mapped I/O.
                 */
                shost->io_port = iop;
-               boardp->asc_n_io_port = iolen;
 
                shost->this_id = adv_dvc_varp->chip_scsi_id;
 
@@ -18288,15 +13698,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                shost->can_queue = adv_dvc_varp->max_host_qng;
        }
 
-       /*
-        * 'n_io_port' currently is one byte.
-        *
-        * Set a value to 'n_io_port', but never referenced it because
-        * it may be truncated.
-        */
-       shost->n_io_port = boardp->asc_n_io_port <= 255 ?
-           boardp->asc_n_io_port : 255;
-
        /*
         * Following v1.3.89, 'cmd_per_lun' is no longer needed
         * and should be set to zero.
@@ -18343,14 +13744,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                shost->sg_tablesize = SG_ALL;
        }
 
-       ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
+       ASC_DBG(1, "sg_tablesize: %d\n", shost->sg_tablesize);
 
        /* BIOS start address. */
        if (ASC_NARROW_BOARD(boardp)) {
-               shost->base = ((ulong)
-                            AscGetChipBiosAddress(asc_dvc_varp->
-                                                  iop_base,
-                                                  asc_dvc_varp->bus_type));
+               shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
+                                                   asc_dvc_varp->bus_type);
        } else {
                /*
                 * Fill-in BIOS board variables. The Wide BIOS saves
@@ -18365,12 +13764,10 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                AdvReadWordLram(adv_dvc_varp->iop_base,
                                BIOS_CODELEN, boardp->bios_codelen);
 
-               ASC_DBG2(1,
-                        "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
+               ASC_DBG(1, "bios_signature 0x%x, bios_version 0x%x\n",
                         boardp->bios_signature, boardp->bios_version);
 
-               ASC_DBG2(1,
-                        "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
+               ASC_DBG(1, "bios_codeseg 0x%x, bios_codelen 0x%x\n",
                         boardp->bios_codeseg, boardp->bios_codelen);
 
                /*
@@ -18392,30 +13789,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
         * Register Board Resources - I/O Port, DMA, IRQ
         */
 
-       /*
-        * Register I/O port range.
-        *
-        * For Wide boards the I/O ports are not used to access
-        * the board, but request the region anyway.
-        *
-        * 'shost->n_io_port' is not referenced, because it may be truncated.
-        */
-       ASC_DBG2(2,
-                "advansys_board_found: request_region port 0x%lx, len 0x%x\n",
-                (ulong)shost->io_port, boardp->asc_n_io_port);
-       if (request_region(shost->io_port, boardp->asc_n_io_port,
-                          "advansys") == NULL) {
-               ASC_PRINT3
-                   ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n",
-                    boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port);
-#ifdef CONFIG_PROC_FS
-               kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-               scsi_unregister(shost);
-               asc_board_count--;
-               return NULL;
-       }
-
        /* Register DMA Channel for Narrow boards. */
        shost->dma_channel = NO_ISA_DMA;        /* Default to no ISA DMA. */
 #ifdef CONFIG_ISA
@@ -18423,19 +13796,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                /* Register DMA channel for ISA bus. */
                if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
                        shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
-                       if ((ret =
-                            request_dma(shost->dma_channel, "advansys")) != 0) {
-                               ASC_PRINT3
-                                   ("advansys_board_found: board %d: request_dma() %d failed %d\n",
-                                    boardp->id, shost->dma_channel, ret);
-                               release_region(shost->io_port,
-                                              boardp->asc_n_io_port);
-#ifdef CONFIG_PROC_FS
-                               kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-                               scsi_unregister(shost);
-                               asc_board_count--;
-                               return NULL;
+                       ret = request_dma(shost->dma_channel, DRV_NAME);
+                       if (ret) {
+                               shost_printk(KERN_ERR, shost, "request_dma() "
+                                               "%d failed %d\n",
+                                               shost->dma_channel, ret);
+                               goto err_free_proc;
                        }
                        AscEnableIsaDma(shost->dma_channel);
                }
@@ -18443,573 +13809,392 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 #endif /* CONFIG_ISA */
 
        /* Register IRQ Number. */
-       ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
-       /*
-        * If request_irq() fails with the IRQF_DISABLED flag set,
-        * then try again without the IRQF_DISABLED flag set. This
-        * allows IRQ sharing to work even with other drivers that
-        * do not set the IRQF_DISABLED flag.
-        *
-        * If IRQF_DISABLED is not set, then interrupts are enabled
-        * before the driver interrupt function is called.
-        */
-       if (((ret = request_irq(shost->irq, advansys_interrupt,
-                               IRQF_DISABLED | (share_irq ==
-                                                TRUE ?
-                                                IRQF_SHARED :
-                                                0), "advansys", boardp)) != 0)
-           &&
-           ((ret =
-             request_irq(shost->irq, advansys_interrupt,
-                         (share_irq == TRUE ? IRQF_SHARED : 0),
-                         "advansys", boardp)) != 0)) {
+       ASC_DBG(2, "request_irq(%d, %p)\n", boardp->irq, shost);
+
+       ret = request_irq(boardp->irq, advansys_interrupt, share_irq,
+                         DRV_NAME, shost);
+
+       if (ret) {
                if (ret == -EBUSY) {
-                       ASC_PRINT2
-                           ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
-                            boardp->id, shost->irq);
+                       shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x "
+                                       "already in use\n", boardp->irq);
                } else if (ret == -EINVAL) {
-                       ASC_PRINT2
-                           ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
-                            boardp->id, shost->irq);
+                       shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x "
+                                       "not valid\n", boardp->irq);
                } else {
-                       ASC_PRINT3
-                           ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
-                            boardp->id, shost->irq, ret);
+                       shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x "
+                                       "failed with %d\n", boardp->irq, ret);
                }
-               release_region(shost->io_port, boardp->asc_n_io_port);
-               iounmap(boardp->ioremap_addr);
-               if (shost->dma_channel != NO_ISA_DMA) {
-                       free_dma(shost->dma_channel);
-               }
-#ifdef CONFIG_PROC_FS
-               kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-               scsi_unregister(shost);
-               asc_board_count--;
-               return NULL;
+               goto err_free_dma;
        }
 
        /*
         * Initialize board RISC chip and enable interrupts.
         */
        if (ASC_NARROW_BOARD(boardp)) {
-               ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
+               ASC_DBG(2, "AscInitAsc1000Driver()\n");
                warn_code = AscInitAsc1000Driver(asc_dvc_varp);
-               err_code = asc_dvc_varp->err_code;
 
-               if (warn_code || err_code) {
-                       ASC_PRINT4
-                           ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
-                            boardp->id,
-                            asc_dvc_varp->init_state, warn_code, err_code);
+               if (warn_code || asc_dvc_varp->err_code) {
+                       shost_printk(KERN_ERR, shost, "error: init_state 0x%x, "
+                                       "warn 0x%x, error 0x%x\n",
+                                       asc_dvc_varp->init_state, warn_code,
+                                       asc_dvc_varp->err_code);
+                       if (asc_dvc_varp->err_code)
+                               ret = -ENODEV;
                }
        } else {
-               ADV_CARR_T *carrp;
-               int req_cnt = 0;
-               adv_req_t *reqp = NULL;
-               int sg_cnt = 0;
-
-               /*
-                * Allocate buffer carrier structures. The total size
-                * is about 4 KB, so allocate all at once.
-                */
-               carrp = (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC);
-               ASC_DBG1(1, "advansys_board_found: carrp 0x%lx\n", (ulong)carrp);
-
-               if (carrp == NULL) {
-                       goto kmalloc_error;
-               }
+               if (advansys_wide_init_chip(shost))
+                       ret = -ENODEV;
+       }
 
-               /*
-                * Allocate up to 'max_host_qng' request structures for
-                * the Wide board. The total size is about 16 KB, so
-                * allocate all at once. If the allocation fails decrement
-                * and try again.
-                */
-               for (req_cnt = adv_dvc_varp->max_host_qng;
-                    req_cnt > 0; req_cnt--) {
+       if (ret)
+               goto err_free_wide_mem;
 
-                       reqp = (adv_req_t *)
-                           kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
+       ASC_DBG_PRT_SCSI_HOST(2, shost);
 
-                       ASC_DBG3(1,
-                                "advansys_board_found: reqp 0x%lx, req_cnt %d, bytes %lu\n",
-                                (ulong)reqp, req_cnt,
-                                (ulong)sizeof(adv_req_t) * req_cnt);
+       ret = scsi_add_host(shost, boardp->dev);
+       if (ret)
+               goto err_free_wide_mem;
 
-                       if (reqp != NULL) {
-                               break;
-                       }
-               }
-               if (reqp == NULL) {
-                       goto kmalloc_error;
-               }
+       scsi_scan_host(shost);
+       return 0;
 
-               /*
-                * Allocate up to ADV_TOT_SG_BLOCK request structures for
-                * the Wide board. Each structure is about 136 bytes.
-                */
-               boardp->adv_sgblkp = NULL;
-               for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
+ err_free_wide_mem:
+       advansys_wide_free_mem(boardp);
+       free_irq(boardp->irq, shost);
+ err_free_dma:
+       if (shost->dma_channel != NO_ISA_DMA)
+               free_dma(shost->dma_channel);
+ err_free_proc:
+       kfree(boardp->prtbuf);
+ err_unmap:
+       if (boardp->ioremap_addr)
+               iounmap(boardp->ioremap_addr);
+ err_shost:
+       return ret;
+}
 
-                       sgp = (adv_sgblk_t *)
-                           kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC);
+/*
+ * advansys_release()
+ *
+ * Release resources allocated for a single AdvanSys adapter.
+ */
+static int advansys_release(struct Scsi_Host *shost)
+{
+       struct asc_board *board = shost_priv(shost);
+       ASC_DBG(1, "begin\n");
+       scsi_remove_host(shost);
+       free_irq(board->irq, shost);
+       if (shost->dma_channel != NO_ISA_DMA) {
+               ASC_DBG(1, "free_dma()\n");
+               free_dma(shost->dma_channel);
+       }
+       if (ASC_NARROW_BOARD(board)) {
+               dma_unmap_single(board->dev,
+                                       board->dvc_var.asc_dvc_var.overrun_dma,
+                                       ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+       } else {
+               iounmap(board->ioremap_addr);
+               advansys_wide_free_mem(board);
+       }
+       kfree(board->prtbuf);
+       scsi_host_put(shost);
+       ASC_DBG(1, "end\n");
+       return 0;
+}
 
-                       if (sgp == NULL) {
-                               break;
-                       }
+#define ASC_IOADR_TABLE_MAX_IX  11
 
-                       sgp->next_sgblkp = boardp->adv_sgblkp;
-                       boardp->adv_sgblkp = sgp;
+static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
+       0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
+       0x0210, 0x0230, 0x0250, 0x0330
+};
 
-               }
-               ASC_DBG3(1,
-                        "advansys_board_found: sg_cnt %d * %u = %u bytes\n",
-                        sg_cnt, sizeof(adv_sgblk_t),
-                        (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
+/*
+ * The ISA IRQ number is found in bits 2 and 3 of the CfgLsw.  It decodes as:
+ * 00: 10
+ * 01: 11
+ * 10: 12
+ * 11: 15
+ */
+static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
+{
+       unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
+       unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
+       if (chip_irq == 13)
+               chip_irq = 15;
+       return chip_irq;
+}
 
-               /*
-                * If no request structures or scatter-gather structures could
-                * be allocated, then return an error. Otherwise continue with
-                * initialization.
-                */
- kmalloc_error:
-               if (carrp == NULL) {
-                       ASC_PRINT1
-                           ("advansys_board_found: board %d error: failed to kmalloc() carrier buffer.\n",
-                            boardp->id);
-                       err_code = ADV_ERROR;
-               } else if (reqp == NULL) {
-                       kfree(carrp);
-                       ASC_PRINT1
-                           ("advansys_board_found: board %d error: failed to kmalloc() adv_req_t buffer.\n",
-                            boardp->id);
-                       err_code = ADV_ERROR;
-               } else if (boardp->adv_sgblkp == NULL) {
-                       kfree(carrp);
-                       kfree(reqp);
-                       ASC_PRINT1
-                           ("advansys_board_found: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n",
-                            boardp->id);
-                       err_code = ADV_ERROR;
-               } else {
+static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
+{
+       int err = -ENODEV;
+       PortAddr iop_base = _asc_def_iop_base[id];
+       struct Scsi_Host *shost;
+       struct asc_board *board;
 
-                       /* Save carrier buffer pointer. */
-                       boardp->orig_carrp = carrp;
+       if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
+               ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
+               return -ENODEV;
+       }
+       ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
+       if (!AscFindSignature(iop_base))
+               goto release_region;
+       if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
+               goto release_region;
 
-                       /*
-                        * Save original pointer for kfree() in case the
-                        * driver is built as a module and can be unloaded.
-                        */
-                       boardp->orig_reqp = reqp;
+       err = -ENOMEM;
+       shost = scsi_host_alloc(&advansys_template, sizeof(*board));
+       if (!shost)
+               goto release_region;
 
-                       adv_dvc_varp->carrier_buf = carrp;
+       board = shost_priv(shost);
+       board->irq = advansys_isa_irq_no(iop_base);
+       board->dev = dev;
 
-                       /*
-                        * Point 'adv_reqp' to the request structures and
-                        * link them together.
-                        */
-                       req_cnt--;
-                       reqp[req_cnt].next_reqp = NULL;
-                       for (; req_cnt > 0; req_cnt--) {
-                               reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
-                       }
-                       boardp->adv_reqp = &reqp[0];
-
-                       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-                               ASC_DBG(2,
-                                       "advansys_board_found: AdvInitAsc3550Driver()\n");
-                               warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
-                       } else if (adv_dvc_varp->chip_type ==
-                                  ADV_CHIP_ASC38C0800) {
-                               ASC_DBG(2,
-                                       "advansys_board_found: AdvInitAsc38C0800Driver()\n");
-                               warn_code =
-                                   AdvInitAsc38C0800Driver(adv_dvc_varp);
-                       } else {
-                               ASC_DBG(2,
-                                       "advansys_board_found: AdvInitAsc38C1600Driver()\n");
-                               warn_code =
-                                   AdvInitAsc38C1600Driver(adv_dvc_varp);
-                       }
-                       err_code = adv_dvc_varp->err_code;
+       err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
+       if (err)
+               goto free_host;
 
-                       if (warn_code || err_code) {
-                               ASC_PRINT3
-                                   ("advansys_board_found: board %d error: warn 0x%x, error 0x%x\n",
-                                    boardp->id, warn_code, err_code);
-                       }
-               }
-       }
+       dev_set_drvdata(dev, shost);
+       return 0;
 
-       if (err_code != 0) {
-               release_region(shost->io_port, boardp->asc_n_io_port);
-               if (ASC_WIDE_BOARD(boardp)) {
-                       iounmap(boardp->ioremap_addr);
-                       kfree(boardp->orig_carrp);
-                       boardp->orig_carrp = NULL;
-                       if (boardp->orig_reqp) {
-                               kfree(boardp->orig_reqp);
-                               boardp->orig_reqp = boardp->adv_reqp = NULL;
-                       }
-                       while ((sgp = boardp->adv_sgblkp) != NULL) {
-                               boardp->adv_sgblkp = sgp->next_sgblkp;
-                               kfree(sgp);
-                       }
-               }
-               if (shost->dma_channel != NO_ISA_DMA) {
-                       free_dma(shost->dma_channel);
-               }
-#ifdef CONFIG_PROC_FS
-               kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-               free_irq(shost->irq, boardp);
-               scsi_unregister(shost);
-               asc_board_count--;
-               return NULL;
-       }
-       ASC_DBG_PRT_SCSI_HOST(2, shost);
+ free_host:
+       scsi_host_put(shost);
+ release_region:
+       release_region(iop_base, ASC_IOADR_GAP);
+       return err;
+}
 
-       return shost;
+static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
+{
+       int ioport = _asc_def_iop_base[id];
+       advansys_release(dev_get_drvdata(dev));
+       release_region(ioport, ASC_IOADR_GAP);
+       return 0;
 }
 
+static struct isa_driver advansys_isa_driver = {
+       .probe          = advansys_isa_probe,
+       .remove         = __devexit_p(advansys_isa_remove),
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
 /*
- * 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().
+ * The VLB IRQ number is found in bits 2 to 4 of the CfgLsw.  It decodes as:
+ * 000: invalid
+ * 001: 10
+ * 010: 11
+ * 011: 12
+ * 100: invalid
+ * 101: 14
+ * 110: 15
+ * 111: invalid
  */
-static int __init advansys_detect(struct scsi_host_template *tpnt)
+static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
 {
-       static int detect_called = ASC_FALSE;
-       int iop;
-       int bus;
-       int ioport = 0;
-       struct device *dev = NULL;
-#ifdef CONFIG_PCI
-       int pci_init_search = 0;
-       struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED];
-       int pci_card_cnt_max = 0;
-       int pci_card_cnt = 0;
-       struct pci_dev *pdev = NULL;
-       int pci_device_id_cnt = 0;
-       unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
-               PCI_DEVICE_ID_ASP_1200A,
-               PCI_DEVICE_ID_ASP_ABP940,
-               PCI_DEVICE_ID_ASP_ABP940U,
-               PCI_DEVICE_ID_ASP_ABP940UW,
-               PCI_DEVICE_ID_38C0800_REV1,
-               PCI_DEVICE_ID_38C1600_REV1
-       };
-#endif /* CONFIG_PCI */
-
-       if (detect_called == ASC_FALSE) {
-               detect_called = ASC_TRUE;
-       } else {
-               printk
-                   ("AdvanSys SCSI: advansys_detect() multiple calls ignored\n");
+       unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
+       unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
+       if ((chip_irq < 10) || (chip_irq == 13) || (chip_irq > 15))
                return 0;
-       }
-
-       ASC_DBG(1, "advansys_detect: begin\n");
+       return chip_irq;
+}
 
-       asc_board_count = 0;
+static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
+{
+       int err = -ENODEV;
+       PortAddr iop_base = _asc_def_iop_base[id];
+       struct Scsi_Host *shost;
+       struct asc_board *board;
 
+       if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) {
+               ASC_DBG(1, "I/O port 0x%x busy\n", iop_base);
+               return -ENODEV;
+       }
+       ASC_DBG(1, "probing I/O port 0x%x\n", iop_base);
+       if (!AscFindSignature(iop_base))
+               goto release_region;
        /*
-        * If I/O port probing has been modified, then verify and
-        * clean-up the 'asc_ioport' list.
+        * I don't think this condition can actually happen, but the old
+        * driver did it, and the chances of finding a VLB setup in 2007
+        * to do testing with is slight to none.
         */
-       if (asc_iopflag == ASC_TRUE) {
-               for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
-                       ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%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;
-       }
+       if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
+               goto release_region;
 
-       for (bus = 0; bus < ASC_NUM_BUS; bus++) {
+       err = -ENOMEM;
+       shost = scsi_host_alloc(&advansys_template, sizeof(*board));
+       if (!shost)
+               goto release_region;
 
-               ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
-                        bus, asc_bus_name[bus]);
-               iop = 0;
+       board = shost_priv(shost);
+       board->irq = advansys_vlb_irq_no(iop_base);
+       board->dev = dev;
 
-               while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
+       err = advansys_board_found(shost, iop_base, ASC_IS_VL);
+       if (err)
+               goto free_host;
 
-                       ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
-                                asc_board_count);
+       dev_set_drvdata(dev, shost);
+       return 0;
 
-                       switch (asc_bus[bus]) {
-                       case ASC_IS_ISA:
-                       case ASC_IS_VL:
-#ifdef CONFIG_ISA
-                               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_IOPORT_PROBE;
-                                            ioport++) {
-                                               if ((iop =
-                                                    asc_ioport[ioport]) != 0) {
-                                                       break;
-                                               }
-                                       }
-                                       if (iop) {
-                                               ASC_DBG1(1,
-                                                        "advansys_detect: probing I/O port 0x%x...\n",
-                                                        iop);
-                                               if (!request_region
-                                                   (iop, ASC_IOADR_GAP,
-                                                    "advansys")) {
-                                                       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. */
-                                                       release_region(iop,
-                                                                      ASC_IOADR_GAP);
-                                                       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++;
-                                                               release_region
-                                                                   (iop,
-                                                                    ASC_IOADR_GAP);
-                                                               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;
-                                       }
-                               }
-#endif /* CONFIG_ISA */
-                               break;
+ free_host:
+       scsi_host_put(shost);
+ release_region:
+       release_region(iop_base, ASC_IOADR_GAP);
+       return -ENODEV;
+}
 
-                       case ASC_IS_EISA:
-#ifdef CONFIG_ISA
-                               iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
-#endif /* CONFIG_ISA */
-                               break;
+static struct isa_driver advansys_vlb_driver = {
+       .probe          = advansys_vlb_probe,
+       .remove         = __devexit_p(advansys_isa_remove),
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "advansys_vlb",
+       },
+};
 
-                       case ASC_IS_PCI:
-#ifdef CONFIG_PCI
-                               if (pci_init_search == 0) {
-                                       int i, j;
-
-                                       pci_init_search = 1;
-
-                                       /* Find all PCI cards. */
-                                       while (pci_device_id_cnt <
-                                              ASC_PCI_DEVICE_ID_CNT) {
-                                               if ((pdev =
-                                                    pci_find_device
-                                                    (PCI_VENDOR_ID_ASP,
-                                                     pci_device_id
-                                                     [pci_device_id_cnt],
-                                                     pdev)) == NULL) {
-                                                       pci_device_id_cnt++;
-                                               } else {
-                                                       if (pci_enable_device
-                                                           (pdev) == 0) {
-                                                               pci_devicep
-                                                                   [pci_card_cnt_max++]
-                                                                   = pdev;
-                                                       }
-                                               }
-                                       }
+static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
+       { "ABP7401" },
+       { "ABP7501" },
+       { "" }
+};
 
-                                       /*
-                                        * Sort PCI cards in ascending order by PCI Bus, Slot,
-                                        * and Device Number.
-                                        */
-                                       for (i = 0; i < pci_card_cnt_max - 1;
-                                            i++) {
-                                               for (j = i + 1;
-                                                    j < pci_card_cnt_max;
-                                                    j++) {
-                                                       if ((pci_devicep[j]->
-                                                            bus->number <
-                                                            pci_devicep[i]->
-                                                            bus->number)
-                                                           ||
-                                                           ((pci_devicep[j]->
-                                                             bus->number ==
-                                                             pci_devicep[i]->
-                                                             bus->number)
-                                                            &&
-                                                            (pci_devicep[j]->
-                                                             devfn <
-                                                             pci_devicep[i]->
-                                                             devfn))) {
-                                                               pdev =
-                                                                   pci_devicep
-                                                                   [i];
-                                                               pci_devicep[i] =
-                                                                   pci_devicep
-                                                                   [j];
-                                                               pci_devicep[j] =
-                                                                   pdev;
-                                                       }
-                                               }
-                                       }
+MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
 
-                                       pci_card_cnt = 0;
-                               } else {
-                                       pci_card_cnt++;
-                               }
+/*
+ * EISA is a little more tricky than PCI; each EISA device may have two
+ * channels, and this driver is written to make each channel its own Scsi_Host
+ */
+struct eisa_scsi_data {
+       struct Scsi_Host *host[2];
+};
 
-                               if (pci_card_cnt == pci_card_cnt_max) {
-                                       iop = 0;
-                               } else {
-                                       pdev = pci_devicep[pci_card_cnt];
-
-                                       ASC_DBG2(2,
-                                                "advansys_detect: devfn %d, bus number %d\n",
-                                                pdev->devfn,
-                                                pdev->bus->number);
-                                       iop = pci_resource_start(pdev, 0);
-                                       ASC_DBG2(1,
-                                                "advansys_detect: vendorID %X, deviceID %X\n",
-                                                pdev->vendor,
-                                                pdev->device);
-                                       ASC_DBG2(2,
-                                                "advansys_detect: iop %X, irqLine %d\n",
-                                                iop, pdev->irq);
-                               }
-                               if (pdev)
-                                       dev = &pdev->dev;
+/*
+ * The EISA IRQ number is found in bits 8 to 10 of the CfgLsw.  It decodes as:
+ * 000: 10
+ * 001: 11
+ * 010: 12
+ * 011: invalid
+ * 100: 14
+ * 101: 15
+ * 110: invalid
+ * 111: invalid
+ */
+static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
+{
+       unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
+       unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
+       if ((chip_irq == 13) || (chip_irq > 15))
+               return 0;
+       return chip_irq;
+}
 
-#endif /* CONFIG_PCI */
-                               break;
+static int __devinit advansys_eisa_probe(struct device *dev)
+{
+       int i, ioport, irq = 0;
+       int err;
+       struct eisa_device *edev = to_eisa_device(dev);
+       struct eisa_scsi_data *data;
 
-                       default:
-                               ASC_PRINT1
-                                   ("advansys_detect: unknown bus type: %d\n",
-                                    asc_bus[bus]);
-                               break;
-                       }
-                       ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop);
+       err = -ENOMEM;
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               goto fail;
+       ioport = edev->base_addr + 0xc30;
 
-                       /*
-                        * Adapter not found, try next bus type.
-                        */
-                       if (iop == 0) {
-                               break;
-                       }
+       err = -ENODEV;
+       for (i = 0; i < 2; i++, ioport += 0x20) {
+               struct asc_board *board;
+               struct Scsi_Host *shost;
+               if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) {
+                       printk(KERN_WARNING "Region %x-%x busy\n", ioport,
+                              ioport + ASC_IOADR_GAP - 1);
+                       continue;
+               }
+               if (!AscFindSignature(ioport)) {
+                       release_region(ioport, ASC_IOADR_GAP);
+                       continue;
+               }
+
+               /*
+                * I don't know why we need to do this for EISA chips, but
+                * not for any others.  It looks to be equivalent to
+                * AscGetChipCfgMsw, but I may have overlooked something,
+                * so I'm not converting it until I get an EISA board to
+                * test with.
+                */
+               inw(ioport + 4);
 
-                       advansys_board_found(iop, dev, asc_bus[bus]);
+               if (!irq)
+                       irq = advansys_eisa_irq_no(edev);
+
+               err = -ENOMEM;
+               shost = scsi_host_alloc(&advansys_template, sizeof(*board));
+               if (!shost)
+                       goto release_region;
+
+               board = shost_priv(shost);
+               board->irq = irq;
+               board->dev = dev;
+
+               err = advansys_board_found(shost, ioport, ASC_IS_EISA);
+               if (!err) {
+                       data->host[i] = shost;
+                       continue;
                }
+
+               scsi_host_put(shost);
+ release_region:
+               release_region(ioport, ASC_IOADR_GAP);
+               break;
        }
 
-       ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n",
-                asc_board_count);
-       return asc_board_count;
+       if (err)
+               goto free_data;
+       dev_set_drvdata(dev, data);
+       return 0;
+
+ free_data:
+       kfree(data->host[0]);
+       kfree(data->host[1]);
+       kfree(data);
+ fail:
+       return err;
 }
 
-/*
- * advansys_release()
- *
- * Release resources allocated for a single AdvanSys adapter.
- */
-static int advansys_release(struct Scsi_Host *shost)
+static __devexit int advansys_eisa_remove(struct device *dev)
 {
-       asc_board_t *boardp;
+       int i;
+       struct eisa_scsi_data *data = dev_get_drvdata(dev);
 
-       ASC_DBG(1, "advansys_release: begin\n");
-       boardp = ASC_BOARDP(shost);
-       free_irq(shost->irq, boardp);
-       if (shost->dma_channel != NO_ISA_DMA) {
-               ASC_DBG(1, "advansys_release: free_dma()\n");
-               free_dma(shost->dma_channel);
+       for (i = 0; i < 2; i++) {
+               int ioport;
+               struct Scsi_Host *shost = data->host[i];
+               if (!shost)
+                       continue;
+               ioport = shost->io_port;
+               advansys_release(shost);
+               release_region(ioport, ASC_IOADR_GAP);
        }
-       release_region(shost->io_port, boardp->asc_n_io_port);
-       if (ASC_WIDE_BOARD(boardp)) {
-               adv_sgblk_t *sgp = NULL;
 
-               iounmap(boardp->ioremap_addr);
-               kfree(boardp->orig_carrp);
-               boardp->orig_carrp = NULL;
-               if (boardp->orig_reqp) {
-                       kfree(boardp->orig_reqp);
-                       boardp->orig_reqp = boardp->adv_reqp = NULL;
-               }
-               while ((sgp = boardp->adv_sgblkp) != NULL) {
-                       boardp->adv_sgblkp = sgp->next_sgblkp;
-                       kfree(sgp);
-               }
-       }
-#ifdef CONFIG_PROC_FS
-       ASC_ASSERT(boardp->prtbuf != NULL);
-       kfree(boardp->prtbuf);
-#endif /* CONFIG_PROC_FS */
-       scsi_unregister(shost);
-       ASC_DBG(1, "advansys_release: end\n");
+       kfree(data);
        return 0;
 }
 
-#ifdef CONFIG_PCI
+static struct eisa_driver advansys_eisa_driver = {
+       .id_table =             advansys_eisa_table,
+       .driver = {
+               .name =         DRV_NAME,
+               .probe =        advansys_eisa_probe,
+               .remove =       __devexit_p(advansys_eisa_remove),
+       }
+};
+
 /* PCI Devices supported by this driver */
 static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
        {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
@@ -19028,4 +14213,131 @@ static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
 };
 
 MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
-#endif /* CONFIG_PCI */
+
+static void __devinit advansys_set_latency(struct pci_dev *pdev)
+{
+       if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
+           (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
+               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
+       } else {
+               u8 latency;
+               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
+               if (latency < 0x20)
+                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
+       }
+}
+
+static int __devinit
+advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int err, ioport;
+       struct Scsi_Host *shost;
+       struct asc_board *board;
+
+       err = pci_enable_device(pdev);
+       if (err)
+               goto fail;
+       err = pci_request_regions(pdev, DRV_NAME);
+       if (err)
+               goto disable_device;
+       pci_set_master(pdev);
+       advansys_set_latency(pdev);
+
+       err = -ENODEV;
+       if (pci_resource_len(pdev, 0) == 0)
+               goto release_region;
+
+       ioport = pci_resource_start(pdev, 0);
+
+       err = -ENOMEM;
+       shost = scsi_host_alloc(&advansys_template, sizeof(*board));
+       if (!shost)
+               goto release_region;
+
+       board = shost_priv(shost);
+       board->irq = pdev->irq;
+       board->dev = &pdev->dev;
+
+       if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
+           pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
+           pdev->device == PCI_DEVICE_ID_38C1600_REV1) {
+               board->flags |= ASC_IS_WIDE_BOARD;
+       }
+
+       err = advansys_board_found(shost, ioport, ASC_IS_PCI);
+       if (err)
+               goto free_host;
+
+       pci_set_drvdata(pdev, shost);
+       return 0;
+
+ free_host:
+       scsi_host_put(shost);
+ release_region:
+       pci_release_regions(pdev);
+ disable_device:
+       pci_disable_device(pdev);
+ fail:
+       return err;
+}
+
+static void __devexit advansys_pci_remove(struct pci_dev *pdev)
+{
+       advansys_release(pci_get_drvdata(pdev));
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+}
+
+static struct pci_driver advansys_pci_driver = {
+       .name =         DRV_NAME,
+       .id_table =     advansys_pci_tbl,
+       .probe =        advansys_pci_probe,
+       .remove =       __devexit_p(advansys_pci_remove),
+};
+
+static int __init advansys_init(void)
+{
+       int error;
+
+       error = isa_register_driver(&advansys_isa_driver,
+                                   ASC_IOADR_TABLE_MAX_IX);
+       if (error)
+               goto fail;
+
+       error = isa_register_driver(&advansys_vlb_driver,
+                                   ASC_IOADR_TABLE_MAX_IX);
+       if (error)
+               goto unregister_isa;
+
+       error = eisa_driver_register(&advansys_eisa_driver);
+       if (error)
+               goto unregister_vlb;
+
+       error = pci_register_driver(&advansys_pci_driver);
+       if (error)
+               goto unregister_eisa;
+
+       return 0;
+
+ unregister_eisa:
+       eisa_driver_unregister(&advansys_eisa_driver);
+ unregister_vlb:
+       isa_unregister_driver(&advansys_vlb_driver);
+ unregister_isa:
+       isa_unregister_driver(&advansys_isa_driver);
+ fail:
+       return error;
+}
+
+static void __exit advansys_exit(void)
+{
+       pci_unregister_driver(&advansys_pci_driver);
+       eisa_driver_unregister(&advansys_eisa_driver);
+       isa_unregister_driver(&advansys_vlb_driver);
+       isa_unregister_driver(&advansys_isa_driver);
+}
+
+module_init(advansys_init);
+module_exit(advansys_exit);
+
+MODULE_LICENSE("GPL");
index d30a30786ddaaa976e3517472918f410707796ba..f08e71e0205a5f5a3e538701d44e80bd9a4822ca 100644 (file)
@@ -907,9 +907,10 @@ out_host_put:
 
 void aha152x_release(struct Scsi_Host *shpnt)
 {
-       if(!shpnt)
+       if (!shpnt)
                return;
 
+       scsi_remove_host(shpnt);
        if (shpnt->irq)
                free_irq(shpnt->irq, shpnt);
 
@@ -923,7 +924,6 @@ void aha152x_release(struct Scsi_Host *shpnt)
                pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
 #endif
 
-       scsi_remove_host(shpnt);
        list_del(&HOSTDATA(shpnt)->host_list);
        scsi_host_put(shpnt);
 }
index 4998bb850c49be1c8669067b93b4db829b4603ee..1a71b0236c974ef8ed3006f9a82756c163d0d3c6 100644 (file)
@@ -8416,10 +8416,9 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp)
     *p = *temp;
     p->host = host;
 
-    p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC);
-    if (p->scb_data != NULL)
+    p->scb_data = kzalloc(sizeof(scb_data_type), GFP_ATOMIC);
+    if (!p->scb_data)
     {
-      memset(p->scb_data, 0, sizeof(scb_data_type));
       scbq_init (&p->scb_data->free_scbs);
     }
     else
@@ -9196,10 +9195,9 @@ aic7xxx_detect(struct scsi_host_template *template)
             printk(KERN_INFO "         this driver, we are ignoring it.\n");
           }
         }
-        else if ( (temp_p = kmalloc(sizeof(struct aic7xxx_host),
+        else if ( (temp_p = kzalloc(sizeof(struct aic7xxx_host),
                                     GFP_ATOMIC)) != NULL )
         {
-          memset(temp_p, 0, sizeof(struct aic7xxx_host));
           temp_p->chip = aic_pdevs[i].chip | AHC_PCI;
           temp_p->flags = aic_pdevs[i].flags;
           temp_p->features = aic_pdevs[i].features;
index c6c3d18222fabea78ad3f6cfb3627ea97897bf20..491e5d8a98bcffe819a11998f5110ef265f4ca0a 100644 (file)
 #define ASD_MAX_PHYS       8
 #define ASD_PCBA_SN_SIZE   12
 
-/* Those are to be further named properly, the "RAZORx" part, and
- * subsequently included in include/linux/pci_ids.h.
- */
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR10 0x410
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR12 0x412
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR1E 0x41E
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR1F 0x41F
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR30 0x430
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR32 0x432
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR3E 0x43E
-#define PCI_DEVICE_ID_ADAPTEC2_RAZOR3F 0x43F
-
 struct asd_ha_addrspace {
        void __iomem  *addr;
        unsigned long  start;       /* pci resource start */
index 63bcde24644740baeadb8b956c6c0ab68f88b16e..b70d6e7f96e951e55829cc118337946e80dc7101 100644 (file)
@@ -583,7 +583,7 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
        asd_ha = kzalloc(sizeof(*asd_ha), GFP_KERNEL);
        if (!asd_ha) {
                asd_printk("out of memory\n");
-               goto Err;
+               goto Err_put;
        }
        asd_ha->pcidev = dev;
        asd_ha->sas_ha.dev = &asd_ha->pcidev->dev;
@@ -600,14 +600,12 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
        shost->max_cmd_len = 16;
 
        err = scsi_add_host(shost, &dev->dev);
-       if (err) {
-               scsi_host_put(shost);
+       if (err)
                goto Err_free;
-       }
 
        err = asd_dev->setup(asd_ha);
        if (err)
-               goto Err_free;
+               goto Err_remove;
 
        err = -ENODEV;
        if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)
@@ -618,14 +616,14 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
                ;
        else {
                asd_printk("no suitable DMA mask for %s\n", pci_name(dev));
-               goto Err_free;
+               goto Err_remove;
        }
 
        pci_set_drvdata(dev, asd_ha);
 
        err = asd_map_ha(asd_ha);
        if (err)
-               goto Err_free;
+               goto Err_remove;
 
        err = asd_create_ha_caches(asd_ha);
         if (err)
@@ -692,9 +690,12 @@ Err_free_cache:
        asd_destroy_ha_caches(asd_ha);
 Err_unmap:
        asd_unmap_ha(asd_ha);
+Err_remove:
+       scsi_remove_host(shost);
 Err_free:
        kfree(asd_ha);
-       scsi_remove_host(shost);
+Err_put:
+       scsi_host_put(shost);
 Err:
        pci_disable_device(dev);
        return err;
@@ -829,22 +830,15 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
 };
 
 static const struct pci_device_id aic94xx_pci_table[] __devinitdata = {
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR10),
-        0, 0, 1},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR12),
-        0, 0, 1},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1E),
-        0, 0, 1},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1F),
-        0, 0, 1},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR30),
-        0, 0, 2},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR32),
-        0, 0, 2},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR3E),
-        0, 0, 2},
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR3F),
-        0, 0, 2},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41E),0, 0, 1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41F),0, 0, 1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x430),0, 0, 2},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x432),0, 0, 2},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43E),0, 0, 2},
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43F),0, 0, 2},
        {}
 };
 
index ab13824df856594ec140ce9c23bb9888b71b4523..f2b23e01401ad95b825b73c8c0648edc2c09b874 100644 (file)
@@ -207,7 +207,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
                                            "stat(0x%x) is not CHECK_CONDITION"
                                            "\n",
                                            SAS_ADDR(task->dev->sas_addr),
-                                           ts->stat);
+                                           iu->status);
                        }
                }
        }  else {
index f0b8bf4534f0186c800667f3f511b29472452286..ace7a15b413e42ba499847b2e5912f0f2cc7b56f 100644 (file)
@@ -9,7 +9,7 @@
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved.
 **
 **     Web site: www.areca.com.tw
-**       E-mail: erich@areca.com.tw
+**       E-mail: support@areca.com.tw
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License version 2 as
 #include <linux/interrupt.h>
 
 struct class_device_attribute;
-
-#define ARCMSR_MAX_OUTSTANDING_CMD                                             256
-#define ARCMSR_MAX_FREECCB_NUM                                                 288
-#define ARCMSR_DRIVER_VERSION                          "Driver Version 1.20.00.14"
+/*The limit of outstanding scsi command that firmware can handle*/
+#define ARCMSR_MAX_OUTSTANDING_CMD                                             256
+#define ARCMSR_MAX_FREECCB_NUM                                                 320
+#define ARCMSR_DRIVER_VERSION               "Driver Version 1.20.00.15 2007/08/30"
 #define ARCMSR_SCSI_INITIATOR_ID                                               255
 #define ARCMSR_MAX_XFER_SECTORS                                                        512
-#define ARCMSR_MAX_XFER_SECTORS_B                                              4096
-#define ARCMSR_MAX_TARGETID                                                     17
-#define ARCMSR_MAX_TARGETLUN                                                     8
-#define ARCMSR_MAX_CMD_PERLUN                           ARCMSR_MAX_OUTSTANDING_CMD
-#define ARCMSR_MAX_QBUFFER                                                    4096
-#define ARCMSR_MAX_SG_ENTRIES                                                   38
-
+#define ARCMSR_MAX_XFER_SECTORS_B                                              4096
+#define ARCMSR_MAX_TARGETID                                                    17
+#define ARCMSR_MAX_TARGETLUN                                                   8
+#define ARCMSR_MAX_CMD_PERLUN                           ARCMSR_MAX_OUTSTANDING_CMD
+#define ARCMSR_MAX_QBUFFER                                                     4096
+#define ARCMSR_MAX_SG_ENTRIES                                                  38
+#define ARCMSR_MAX_HBB_POSTQUEUE                                               264
+/*
+**********************************************************************************
+**
+**********************************************************************************
+*/
+#define ARC_SUCCESS                                                       0
+#define ARC_FAILURE                                                       1
 /*
 *******************************************************************************
 **        split 64bits dma addressing
@@ -90,7 +97,7 @@ struct CMD_MESSAGE_FIELD
     uint8_t                            messagedatabuffer[1032];
 };
 /* IOP message transfer */
-#define ARCMSR_MESSAGE_FAIL             0x0001
+#define ARCMSR_MESSAGE_FAIL                    0x0001
 /* DeviceType */
 #define ARECA_SATA_RAID                                0x90000000
 /* FunctionCode */
@@ -163,27 +170,27 @@ struct QBUFFER
 };
 /*
 *******************************************************************************
-**      FIRMWARE INFO
+**      FIRMWARE INFO for Intel IOP R 80331 processor (Type A)
 *******************************************************************************
 */
 struct FIRMWARE_INFO
 {
-       uint32_t      signature;                /*0, 00-03*/
-       uint32_t      request_len;              /*1, 04-07*/
-       uint32_t      numbers_queue;            /*2, 08-11*/
+       uint32_t      signature;                /*0, 00-03*/
+       uint32_t      request_len;              /*1, 04-07*/
+       uint32_t      numbers_queue;            /*2, 08-11*/
        uint32_t      sdram_size;               /*3, 12-15*/
-       uint32_t      ide_channels;             /*4, 16-19*/
-       char          vendor[40];               /*5, 20-59*/
-       char          model[8];                 /*15, 60-67*/
-       char          firmware_ver[16];         /*17, 68-83*/
-       char          device_map[16];           /*21, 84-99*/
+       uint32_t      ide_channels;             /*4, 16-19*/
+       char          vendor[40];               /*5, 20-59*/
+       char          model[8];                 /*15, 60-67*/
+       char          firmware_ver[16];         /*17, 68-83*/
+       char          device_map[16];           /*21, 84-99*/
 };
 /* signature of set and get firmware config */
-#define ARCMSR_SIGNATURE_GET_CONFIG                   0x87974060
-#define ARCMSR_SIGNATURE_SET_CONFIG                   0x87974063
+#define ARCMSR_SIGNATURE_GET_CONFIG                  0x87974060
+#define ARCMSR_SIGNATURE_SET_CONFIG                  0x87974063
 /* message code of inbound message register */
-#define ARCMSR_INBOUND_MESG0_NOP                      0x00000000
-#define ARCMSR_INBOUND_MESG0_GET_CONFIG               0x00000001
+#define ARCMSR_INBOUND_MESG0_NOP                     0x00000000
+#define ARCMSR_INBOUND_MESG0_GET_CONFIG                      0x00000001
 #define ARCMSR_INBOUND_MESG0_SET_CONFIG               0x00000002
 #define ARCMSR_INBOUND_MESG0_ABORT_CMD                0x00000003
 #define ARCMSR_INBOUND_MESG0_STOP_BGRB                0x00000004
@@ -203,6 +210,60 @@ struct FIRMWARE_INFO
 #define ARCMSR_CCBREPLY_FLAG_ERROR                    0x10000000
 /* outbound firmware ok */
 #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK             0x80000000
+
+/*
+************************************************************************
+**                SPEC. for Areca Type B adapter
+************************************************************************
+*/
+/* ARECA HBB COMMAND for its FIRMWARE */
+/* window of "instruction flags" from driver to iop */
+#define ARCMSR_DRV2IOP_DOORBELL                       0x00020400
+#define ARCMSR_DRV2IOP_DOORBELL_MASK                  0x00020404
+/* window of "instruction flags" from iop to driver */
+#define ARCMSR_IOP2DRV_DOORBELL                       0x00020408
+#define ARCMSR_IOP2DRV_DOORBELL_MASK                  0x0002040C
+/* ARECA FLAG LANGUAGE */
+/* ioctl transfer */
+#define ARCMSR_IOP2DRV_DATA_WRITE_OK                  0x00000001
+/* ioctl transfer */
+#define ARCMSR_IOP2DRV_DATA_READ_OK                   0x00000002
+#define ARCMSR_IOP2DRV_CDB_DONE                       0x00000004
+#define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE               0x00000008
+
+#define ARCMSR_DOORBELL_HANDLE_INT                   0x0000000F
+#define ARCMSR_DOORBELL_INT_CLEAR_PATTERN            0xFF00FFF0
+#define ARCMSR_MESSAGE_INT_CLEAR_PATTERN             0xFF00FFF7
+/* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_GET_CONFIG                    0x00010008
+/* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_SET_CONFIG                    0x00020008
+/* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_ABORT_CMD                     0x00030008
+/* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_STOP_BGRB                     0x00040008
+/* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_FLUSH_CACHE                    0x00050008
+/* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_START_BGRB                    0x00060008
+#define ARCMSR_MESSAGE_START_DRIVER_MODE             0x000E0008
+#define ARCMSR_MESSAGE_SET_POST_WINDOW               0x000F0008
+/* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
+#define ARCMSR_MESSAGE_FIRMWARE_OK                   0x80000000
+/* ioctl transfer */
+#define ARCMSR_DRV2IOP_DATA_WRITE_OK                  0x00000001
+/* ioctl transfer */
+#define ARCMSR_DRV2IOP_DATA_READ_OK                   0x00000002
+#define ARCMSR_DRV2IOP_CDB_POSTED                     0x00000004
+#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED             0x00000008
+
+/* data tunnel buffer between user space program and its firmware */
+/* user space data to iop 128bytes */
+#define ARCMSR_IOCTL_WBUFFER                         0x0000fe00
+/* iop data to user space 128bytes */
+#define ARCMSR_IOCTL_RBUFFER                         0x0000ff00
+/* iop message_rwbuffer for message command */
+#define ARCMSR_MSGCODE_RWBUFFER                              0x0000fa00
 /*
 *******************************************************************************
 **    ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
@@ -214,7 +275,6 @@ struct ARCMSR_CDB
        uint8_t                                                 TargetID;
        uint8_t                                                 LUN;
        uint8_t                                                 Function;
-
        uint8_t                                                 CdbLength;
        uint8_t                                                 sgcount;
        uint8_t                                                 Flags;
@@ -224,20 +284,18 @@ struct ARCMSR_CDB
 #define ARCMSR_CDB_FLAG_SIMPLEQ            0x00
 #define ARCMSR_CDB_FLAG_HEADQ              0x08
 #define ARCMSR_CDB_FLAG_ORDEREDQ           0x10
-       uint8_t                                                 Reserved1;
 
+       uint8_t                                                 Reserved1;
        uint32_t                                                Context;
        uint32_t                                                DataLength;
-
        uint8_t                                                 Cdb[16];
-
        uint8_t                                                 DeviceStatus;
-#define ARCMSR_DEV_CHECK_CONDITION          0x02
-#define ARCMSR_DEV_SELECT_TIMEOUT                      0xF0
-#define ARCMSR_DEV_ABORTED                             0xF1
-#define ARCMSR_DEV_INIT_FAIL                           0xF2
-       uint8_t                                                 SenseData[15];
+#define ARCMSR_DEV_CHECK_CONDITION         0x02
+#define ARCMSR_DEV_SELECT_TIMEOUT          0xF0
+#define ARCMSR_DEV_ABORTED                 0xF1
+#define ARCMSR_DEV_INIT_FAIL               0xF2
 
+       uint8_t                                                 SenseData[15];
        union
        {
                struct SG32ENTRY                sg32entry[ARCMSR_MAX_SG_ENTRIES];
@@ -246,10 +304,10 @@ struct ARCMSR_CDB
 };
 /*
 *******************************************************************************
-**     Messaging Unit (MU) of the Intel R 80331 I/O processor (80331)
+**     Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor
 *******************************************************************************
 */
-struct MessageUnit
+struct MessageUnit_A
 {
        uint32_t        resrved0[4];                    /*0000 000F*/
        uint32_t        inbound_msgaddr0;               /*0010 0013*/
@@ -274,6 +332,30 @@ struct MessageUnit
        uint32_t        message_rbuffer[32];            /*0F00 0F7F  32*/
        uint32_t        reserved6[32];                  /*0F80 0FFF  32*/
 };
+
+struct MessageUnit_B
+{
+       uint32_t        post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
+       uint32_t        done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
+       uint32_t        postq_index;
+       uint32_t        doneq_index;
+       uint32_t        *drv2iop_doorbell_reg;
+       uint32_t        *drv2iop_doorbell_mask_reg;
+       uint32_t        *iop2drv_doorbell_reg;
+       uint32_t        *iop2drv_doorbell_mask_reg;
+       uint32_t        *msgcode_rwbuffer_reg;
+       uint32_t        *ioctl_wbuffer_reg;
+       uint32_t        *ioctl_rbuffer_reg;
+};
+
+struct MessageUnit
+{
+       union
+       {
+               struct MessageUnit_A    pmu_A;
+               struct MessageUnit_B    pmu_B;
+       } u;
+};
 /*
 *******************************************************************************
 **                 Adapter Control Block
@@ -281,37 +363,45 @@ struct MessageUnit
 */
 struct AdapterControlBlock
 {
+       uint32_t  adapter_type;                /* adapter A,B..... */
+       #define ACB_ADAPTER_TYPE_A            0x00000001        /* hba I IOP */
+       #define ACB_ADAPTER_TYPE_B            0x00000002        /* hbb M IOP */
+       #define ACB_ADAPTER_TYPE_C            0x00000004        /* hbc P IOP */
+       #define ACB_ADAPTER_TYPE_D            0x00000008        /* hbd A IOP */
        struct pci_dev *                pdev;
        struct Scsi_Host *              host;
        unsigned long                   vir2phy_offset;
        /* Offset is used in making arc cdb physical to virtual calculations */
        uint32_t                        outbound_int_enable;
 
-       struct MessageUnit __iomem *            pmu;
+       struct MessageUnit *                    pmu;
        /* message unit ATU inbound base address0 */
 
        uint32_t                        acb_flags;
-#define ACB_F_SCSISTOPADAPTER         0x0001
-#define ACB_F_MSG_STOP_BGRB           0x0002
+       #define ACB_F_SCSISTOPADAPTER           0x0001
+       #define ACB_F_MSG_STOP_BGRB             0x0002
        /* stop RAID background rebuild */
-#define ACB_F_MSG_START_BGRB          0x0004
+       #define ACB_F_MSG_START_BGRB            0x0004
        /* stop RAID background rebuild */
-#define ACB_F_IOPDATA_OVERFLOW        0x0008
+       #define ACB_F_IOPDATA_OVERFLOW          0x0008
        /* iop message data rqbuffer overflow */
-#define ACB_F_MESSAGE_WQBUFFER_CLEARED  0x0010
+       #define ACB_F_MESSAGE_WQBUFFER_CLEARED  0x0010
        /* message clear wqbuffer */
-#define ACB_F_MESSAGE_RQBUFFER_CLEARED  0x0020
+       #define ACB_F_MESSAGE_RQBUFFER_CLEARED  0x0020
        /* message clear rqbuffer */
-#define ACB_F_MESSAGE_WQBUFFER_READED   0x0040
-#define ACB_F_BUS_RESET               0x0080
-#define ACB_F_IOP_INITED              0x0100
+       #define ACB_F_MESSAGE_WQBUFFER_READED   0x0040
+       #define ACB_F_BUS_RESET                 0x0080
+       #define ACB_F_IOP_INITED                0x0100
        /* iop init */
 
        struct CommandControlBlock *                    pccb_pool[ARCMSR_MAX_FREECCB_NUM];
        /* used for memory free */
        struct list_head                ccb_free_list;
        /* head of free ccb list */
+
        atomic_t                        ccboutstandingcount;
+       /*The present outstanding command number that in the IOP that
+                                       waiting for being handled by FW*/
 
        void *                          dma_coherent;
        /* dma_coherent used for memory free */
@@ -353,7 +443,7 @@ struct CommandControlBlock
 {
        struct ARCMSR_CDB               arcmsr_cdb;
        /*
-       ** 0-503 (size of CDB=504):
+       ** 0-503 (size of CDB = 504):
        ** arcmsr messenger scsi command descriptor size 504 bytes
        */
        uint32_t                        cdb_shifted_phyaddr;
@@ -466,7 +556,9 @@ struct SENSE_DATA
 #define     ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE               0x01
 #define     ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE                    0x1F
 
-extern void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb);
+extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
+extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
+extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
 extern struct class_device_attribute *arcmsr_host_attrs[];
-extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb);
+extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
 void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
index 06c0dce3b83916095064eab9af2c440098a9bea3..d04d1aa28fa4512c1196768ac3511be520584e71 100644 (file)
@@ -8,7 +8,7 @@
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
 **
 **     Web site: www.areca.com.tw
-**       E-mail: erich@areca.com.tw
+**       E-mail: support@areca.com.tw
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License version 2 as
@@ -49,6 +49,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 
 struct class_device_attribute *arcmsr_host_attrs[];
 
-static ssize_t
-arcmsr_sysfs_iop_message_read(struct kobject *kobj,
-                             struct bin_attribute *bin_attr,
-                             char *buf, loff_t off, size_t count)
+static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+                                            struct bin_attribute *bin,
+                                            char *buf, loff_t off,
+                                            size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *host = class_to_shost(cdev);
        struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-       struct MessageUnit __iomem *reg = acb->pmu;
        uint8_t *pQbuffer,*ptmpQbuffer;
        int32_t allxfer_len = 0;
 
@@ -85,12 +85,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
                allxfer_len++;
        }
        if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-               struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *)
-                                       &reg->message_rbuffer;
-               uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data;
+               struct QBUFFER *prbuffer;
+               uint8_t *iop_data;
                int32_t iop_len;
 
                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
+               prbuffer = arcmsr_get_iop_rqbuffer(acb);
+               iop_data = (uint8_t *)prbuffer->data;
                iop_len = readl(&prbuffer->data_len);
                while (iop_len > 0) {
                        acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
@@ -99,16 +100,15 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
                        iop_data++;
                        iop_len--;
                }
-               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
-                               &reg->inbound_doorbell);
+               arcmsr_iop_message_read(acb);
        }
        return (allxfer_len);
 }
 
-static ssize_t
-arcmsr_sysfs_iop_message_write(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buf, loff_t off, size_t count)
+static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+                                             struct bin_attribute *bin,
+                                             char *buf, loff_t off,
+                                             size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *host = class_to_shost(cdev);
@@ -126,7 +126,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
        wqbuf_lastindex = acb->wqbuf_lastindex;
        wqbuf_firstindex = acb->wqbuf_firstindex;
        if (wqbuf_lastindex != wqbuf_firstindex) {
-               arcmsr_post_Qbuffer(acb);
+               arcmsr_post_ioctldata2iop(acb);
                return 0;       /*need retry*/
        } else {
                my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
@@ -144,7 +144,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
                        if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
                                acb->acb_flags &=
                                        ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-                               arcmsr_post_Qbuffer(acb);
+                               arcmsr_post_ioctldata2iop(acb);
                        }
                        return count;
                } else {
@@ -153,15 +153,14 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
        }
 }
 
-static ssize_t
-arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buf, loff_t off, size_t count)
+static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+                                             struct bin_attribute *bin,
+                                             char *buf, loff_t off,
+                                             size_t count)
 {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *host = class_to_shost(cdev);
        struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-       struct MessageUnit __iomem *reg = acb->pmu;
        uint8_t *pQbuffer;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -169,8 +168,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
 
        if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK
-                               , &reg->inbound_doorbell);
+               arcmsr_iop_message_read(acb);
        }
        acb->acb_flags |=
                (ACB_F_MESSAGE_WQBUFFER_CLEARED
@@ -191,6 +189,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
        .attr = {
                .name = "mu_read",
                .mode = S_IRUSR ,
+               .owner = THIS_MODULE,
        },
        .size = 1032,
        .read = arcmsr_sysfs_iop_message_read,
@@ -200,6 +199,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
        .attr = {
                .name = "mu_write",
                .mode = S_IWUSR,
+               .owner = THIS_MODULE,
        },
        .size = 1032,
        .write = arcmsr_sysfs_iop_message_write,
@@ -209,6 +209,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
        .attr = {
                .name = "mu_clear",
                .mode = S_IWUSR,
+               .owner = THIS_MODULE,
        },
        .size = 1,
        .write = arcmsr_sysfs_iop_message_clear,
@@ -219,31 +220,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
        struct Scsi_Host *host = acb->host;
        int error;
 
-       error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_read_attr);
+       error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
        if (error) {
                printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
                goto error_bin_file_message_read;
        }
-       error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_write_attr);
+       error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
        if (error) {
                printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
                goto error_bin_file_message_write;
        }
-       error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_clear_attr);
+       error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
        if (error) {
                printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
                goto error_bin_file_message_clear;
        }
        return 0;
 error_bin_file_message_clear:
-       sysfs_remove_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_write_attr);
+       sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
 error_bin_file_message_write:
-       sysfs_remove_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_read_attr);
+       sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
 error_bin_file_message_read:
        return error;
 }
@@ -252,12 +248,9 @@ void
 arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
        struct Scsi_Host *host = acb->host;
 
-       sysfs_remove_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_clear_attr);
-       sysfs_remove_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_write_attr);
-       sysfs_remove_bin_file(&host->shost_classdev.kobj,
-                               &arcmsr_sysfs_message_read_attr);
+       sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
+       sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
+       sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
 }
 
 
index 0ddfc21e9f7df3d6c54fc5a91737f31f75867db7..cfcf40159eab96e0d512dabec9b39c4c3c19296a 100644 (file)
@@ -9,7 +9,7 @@
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
 **
 **     Web site: www.areca.com.tw
-**       E-mail: erich@areca.com.tw
+**       E-mail: support@areca.com.tw
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License version 2 as
 #include <scsi/scsicam.h>
 #include "arcmsr.h"
 
-MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>");
+MODULE_AUTHOR("Erich Chen <support@areca.com.tw>");
 MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(ARCMSR_DRIVER_VERSION);
 
-static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd);
+static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
+                                       struct scsi_cmnd *cmd);
+static int arcmsr_iop_confirm(struct AdapterControlBlock *acb);
 static int arcmsr_abort(struct scsi_cmnd *);
 static int arcmsr_bus_reset(struct scsi_cmnd *);
 static int arcmsr_bios_param(struct scsi_device *sdev,
-                               struct block_device *bdev, sector_t capacity, int *info);
-static int arcmsr_queue_command(struct scsi_cmnd * cmd,
-                               void (*done) (struct scsi_cmnd *));
+               struct block_device *bdev, sector_t capacity, int *info);
+static int arcmsr_queue_command(struct scsi_cmnd *cmd,
+                                       void (*done) (struct scsi_cmnd *));
 static int arcmsr_probe(struct pci_dev *pdev,
                                const struct pci_device_id *id);
 static void arcmsr_remove(struct pci_dev *pdev);
 static void arcmsr_shutdown(struct pci_dev *pdev);
 static void arcmsr_iop_init(struct AdapterControlBlock *acb);
 static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb);
+static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb);
 static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
-static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
-static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb);
+static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb);
+static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb);
 static const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
-static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
-                                               pci_channel_state_t state);
-static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev);
-static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
+static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
+                                                               int queue_depth)
 {
        if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
                queue_depth = ARCMSR_MAX_CMD_PERLUN;
@@ -123,17 +124,25 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = arcmsr_host_attrs,
 };
+#ifdef CONFIG_SCSI_ARCMSR_AER
+static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev);
+static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t state);
+
 static struct pci_error_handlers arcmsr_pci_error_handlers = {
        .error_detected         = arcmsr_pci_error_detected,
        .slot_reset             = arcmsr_pci_slot_reset,
 };
-
+#endif
 static struct pci_device_id arcmsr_device_id_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1200)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)},
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)},
@@ -153,20 +162,20 @@ static struct pci_driver arcmsr_pci_driver = {
        .probe                  = arcmsr_probe,
        .remove                 = arcmsr_remove,
        .shutdown               = arcmsr_shutdown,
+       #ifdef CONFIG_SCSI_ARCMSR_AER
        .err_handler            = &arcmsr_pci_error_handlers,
+       #endif
 };
 
 static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
 {
        irqreturn_t handle_state;
-       struct AdapterControlBlock *acb;
-       unsigned long flags;
+       struct AdapterControlBlock *acb = dev_id;
 
-       acb = (struct AdapterControlBlock *)dev_id;
-
-       spin_lock_irqsave(acb->host->host_lock, flags);
+       spin_lock(acb->host->host_lock);
        handle_state = arcmsr_interrupt(acb);
-       spin_unlock_irqrestore(acb->host->host_lock, flags);
+       spin_unlock(acb->host->host_lock);
+
        return handle_state;
 }
 
@@ -198,68 +207,159 @@ static int arcmsr_bios_param(struct scsi_device *sdev,
        return 0;
 }
 
-static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
+static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb)
 {
        struct pci_dev *pdev = acb->pdev;
-       struct MessageUnit __iomem *reg = acb->pmu;
-       u32 ccb_phyaddr_hi32;
-       void *dma_coherent;
-       dma_addr_t dma_coherent_handle, dma_addr;
-       struct CommandControlBlock *ccb_tmp;
-       int i, j;
+       u16 dev_id;
+       pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id);
+       switch (dev_id) {
+       case 0x1201 : {
+               acb->adapter_type = ACB_ADAPTER_TYPE_B;
+               }
+               break;
 
-       dma_coherent = dma_alloc_coherent(&pdev->dev,
+       default : acb->adapter_type = ACB_ADAPTER_TYPE_A;
+       }
+}
+
+static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
+{
+
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               struct pci_dev *pdev = acb->pdev;
+               void *dma_coherent;
+               dma_addr_t dma_coherent_handle, dma_addr;
+               struct CommandControlBlock *ccb_tmp;
+               uint32_t intmask_org;
+               int i, j;
+
+               acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+               if (!acb->pmu) {
+                       printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n",
+                                                       acb->host->host_no);
+               }
+
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
                        ARCMSR_MAX_FREECCB_NUM *
                        sizeof (struct CommandControlBlock) + 0x20,
                        &dma_coherent_handle, GFP_KERNEL);
-       if (!dma_coherent)
-               return -ENOMEM;
+               if (!dma_coherent)
+                       return -ENOMEM;
 
-       acb->dma_coherent = dma_coherent;
-       acb->dma_coherent_handle = dma_coherent_handle;
+               acb->dma_coherent = dma_coherent;
+               acb->dma_coherent_handle = dma_coherent_handle;
 
-       if (((unsigned long)dma_coherent & 0x1F)) {
-               dma_coherent = dma_coherent +
-                       (0x20 - ((unsigned long)dma_coherent & 0x1F));
-               dma_coherent_handle = dma_coherent_handle +
-                       (0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
-       }
+               if (((unsigned long)dma_coherent & 0x1F)) {
+                       dma_coherent = dma_coherent +
+                               (0x20 - ((unsigned long)dma_coherent & 0x1F));
+                       dma_coherent_handle = dma_coherent_handle +
+                               (0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
+               }
 
-       dma_addr = dma_coherent_handle;
-       ccb_tmp = (struct CommandControlBlock *)dma_coherent;
-       for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
-               ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5;
-               ccb_tmp->acb = acb;
-               acb->pccb_pool[i] = ccb_tmp;
-               list_add_tail(&ccb_tmp->list, &acb->ccb_free_list);
-               dma_addr = dma_addr + sizeof (struct CommandControlBlock);
-               ccb_tmp++;
-       }
+               dma_addr = dma_coherent_handle;
+               ccb_tmp = (struct CommandControlBlock *)dma_coherent;
+               for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
+                       ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5;
+                       ccb_tmp->acb = acb;
+                       acb->pccb_pool[i] = ccb_tmp;
+                       list_add_tail(&ccb_tmp->list, &acb->ccb_free_list);
+                       dma_addr = dma_addr + sizeof(struct CommandControlBlock);
+                       ccb_tmp++;
+               }
 
-       acb->vir2phy_offset = (unsigned long)ccb_tmp -
-                             (unsigned long)dma_addr;
-       for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
-               for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
-                       acb->devstate[i][j] = ARECA_RAID_GOOD;
+               acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr;
+               for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
+                       for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
+                               acb->devstate[i][j] = ARECA_RAID_GONE;
 
-       /*
-       ** here we need to tell iop 331 our ccb_tmp.HighPart
-       ** if ccb_tmp.HighPart is not zero
-       */
-       ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16);
-       if (ccb_phyaddr_hi32 != 0) {
-               writel(ARCMSR_SIGNATURE_SET_CONFIG, &reg->message_rwbuffer[0]);
-               writel(ccb_phyaddr_hi32, &reg->message_rwbuffer[1]);
-               writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, &reg->inbound_msgaddr0);
-               if (arcmsr_wait_msgint_ready(acb))
-                       printk(KERN_NOTICE "arcmsr%d: "
-                              "'set ccb high part physical address' timeout\n",
-                               acb->host->host_no);
-       }
+               /*
+               ** here we need to tell iop 331 our ccb_tmp.HighPart
+               ** if ccb_tmp.HighPart is not zero
+               */
+               intmask_org = arcmsr_disable_outbound_ints(acb);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+
+               struct pci_dev *pdev = acb->pdev;
+               struct MessageUnit_B *reg;
+               void *mem_base0, *mem_base1;
+               void *dma_coherent;
+               dma_addr_t dma_coherent_handle, dma_addr;
+               uint32_t intmask_org;
+               struct CommandControlBlock *ccb_tmp;
+               int i, j;
+
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                       ((ARCMSR_MAX_FREECCB_NUM *
+                       sizeof(struct CommandControlBlock) + 0x20) +
+                       sizeof(struct MessageUnit_B)),
+                       &dma_coherent_handle, GFP_KERNEL);
+               if (!dma_coherent)
+                       return -ENOMEM;
+
+               acb->dma_coherent = dma_coherent;
+               acb->dma_coherent_handle = dma_coherent_handle;
+
+               if (((unsigned long)dma_coherent & 0x1F)) {
+                       dma_coherent = dma_coherent +
+                               (0x20 - ((unsigned long)dma_coherent & 0x1F));
+                       dma_coherent_handle = dma_coherent_handle +
+                               (0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
+               }
 
-       writel(readl(&reg->outbound_intmask) |
-                       ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE,
-              &reg->outbound_intmask);
+               reg = (struct MessageUnit_B *)(dma_coherent +
+               ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
+
+               dma_addr = dma_coherent_handle;
+               ccb_tmp = (struct CommandControlBlock *)dma_coherent;
+               for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
+                       ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5;
+                       ccb_tmp->acb = acb;
+                       acb->pccb_pool[i] = ccb_tmp;
+                       list_add_tail(&ccb_tmp->list, &acb->ccb_free_list);
+                       dma_addr = dma_addr + sizeof(struct CommandControlBlock);
+                       ccb_tmp++;
+               }
+
+               reg = (struct MessageUnit_B *)(dma_coherent +
+               ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
+               acb->pmu = (struct MessageUnit *)reg;
+               mem_base0 = ioremap(pci_resource_start(pdev, 0),
+                                       pci_resource_len(pdev, 0));
+               mem_base1 = ioremap(pci_resource_start(pdev, 2),
+                                       pci_resource_len(pdev, 2));
+               reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 +
+                                               ARCMSR_DRV2IOP_DOORBELL);
+               reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 +
+                                               ARCMSR_DRV2IOP_DOORBELL_MASK);
+               reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 +
+                                                       ARCMSR_IOP2DRV_DOORBELL);
+               reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 +
+                                               ARCMSR_IOP2DRV_DOORBELL_MASK);
+               reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 +
+                                                       ARCMSR_IOCTL_WBUFFER);
+               reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 +
+                                                       ARCMSR_IOCTL_RBUFFER);
+               reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 +
+                                                       ARCMSR_MSGCODE_RWBUFFER);
+
+               acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr;
+               for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
+                       for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
+                               acb->devstate[i][j] = ARECA_RAID_GOOD;
+
+               /*
+               ** here we need to tell iop 331 our ccb_tmp.HighPart
+               ** if ccb_tmp.HighPart is not zero
+               */
+               intmask_org = arcmsr_disable_outbound_ints(acb);
+               }
+               break;
+       }
        return 0;
 }
 
@@ -310,16 +410,11 @@ static int arcmsr_probe(struct pci_dev *pdev,
        host->unique_id = (bus << 8) | dev_fun;
        host->irq = pdev->irq;
        error = pci_request_regions(pdev, "arcmsr");
-       if (error)
+       if (error) {
                goto out_host_put;
-
-       acb->pmu = ioremap(pci_resource_start(pdev, 0),
-                          pci_resource_len(pdev, 0));
-       if (!acb->pmu) {
-               printk(KERN_NOTICE "arcmsr%d: memory"
-                       " mapping region fail \n", acb->host->host_no);
-               goto out_release_regions;
        }
+       arcmsr_define_adapter_type(acb);
+
        acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
                           ACB_F_MESSAGE_RQBUFFER_CLEARED |
                           ACB_F_MESSAGE_WQBUFFER_READED);
@@ -328,10 +423,10 @@ static int arcmsr_probe(struct pci_dev *pdev,
 
        error = arcmsr_alloc_ccb_pool(acb);
        if (error)
-               goto out_iounmap;
+               goto out_release_regions;
 
        error = request_irq(pdev->irq, arcmsr_do_interrupt,
-                       IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
+                           IRQF_SHARED, "arcmsr", acb);
        if (error)
                goto out_free_ccb_pool;
 
@@ -349,14 +444,15 @@ static int arcmsr_probe(struct pci_dev *pdev,
                goto out_free_sysfs;
 
        scsi_scan_host(host);
+       #ifdef CONFIG_SCSI_ARCMSR_AER
        pci_enable_pcie_error_reporting(pdev);
+       #endif
        return 0;
  out_free_sysfs:
  out_free_irq:
        free_irq(pdev->irq, acb);
  out_free_ccb_pool:
        arcmsr_free_ccb_pool(acb);
- out_iounmap:
        iounmap(acb->pmu);
  out_release_regions:
        pci_release_regions(pdev);
@@ -368,17 +464,84 @@ static int arcmsr_probe(struct pci_dev *pdev,
        return error;
 }
 
-static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
+static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+       uint32_t Index;
+       uint8_t Retries = 0x00;
+
+       do {
+               for (Index = 0; Index < 100; Index++) {
+                       if (readl(&reg->outbound_intstatus) &
+                                       ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+                               writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT,
+                                       &reg->outbound_intstatus);
+                               return 0x00;
+                       }
+                       msleep(10);
+               }/*max 1 seconds*/
+
+       } while (Retries++ < 20);/*max 20 sec*/
+       return 0xff;
+}
+
+static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+       uint32_t Index;
+       uint8_t Retries = 0x00;
+
+       do {
+               for (Index = 0; Index < 100; Index++) {
+                       if (readl(reg->iop2drv_doorbell_reg)
+                               & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
+                               writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN
+                                       , reg->iop2drv_doorbell_reg);
+                               return 0x00;
+                       }
+                       msleep(10);
+               }/*max 1 seconds*/
+
+       } while (Retries++ < 20);/*max 20 sec*/
+       return 0xff;
+}
+
+static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
 
        writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, &reg->inbound_msgaddr0);
-       if (arcmsr_wait_msgint_ready(acb))
+       if (arcmsr_hba_wait_msgint_ready(acb))
+               printk(KERN_NOTICE
+                       "arcmsr%d: wait 'abort all outstanding command' timeout \n"
+                       , acb->host->host_no);
+}
+
+static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+
+       writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg);
+       if (arcmsr_hbb_wait_msgint_ready(acb))
                printk(KERN_NOTICE
                        "arcmsr%d: wait 'abort all outstanding command' timeout \n"
                        , acb->host->host_no);
 }
 
+static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               arcmsr_abort_hba_allcmd(acb);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               arcmsr_abort_hbb_allcmd(acb);
+               }
+       }
+}
+
 static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
 {
        struct scsi_cmnd *pcmd = ccb->pcmd;
@@ -400,28 +563,239 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
        pcmd->scsi_done(pcmd);
 }
 
+static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+       int retry_count = 30;
+
+       writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
+       do {
+               if (!arcmsr_hba_wait_msgint_ready(acb))
+                       break;
+               else {
+                       retry_count--;
+                       printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \
+                       timeout, retry count down = %d \n", acb->host->host_no, retry_count);
+               }
+       } while (retry_count != 0);
+}
+
+static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+       int retry_count = 30;
+
+       writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg);
+       do {
+               if (!arcmsr_hbb_wait_msgint_ready(acb))
+                       break;
+               else {
+                       retry_count--;
+                       printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \
+                       timeout,retry count down = %d \n", acb->host->host_no, retry_count);
+               }
+       } while (retry_count != 0);
+}
+
+static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               arcmsr_flush_hba_cache(acb);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               arcmsr_flush_hbb_cache(acb);
+               }
+       }
+}
+
+static void arcmsr_report_sense_info(struct CommandControlBlock *ccb)
+{
+
+       struct scsi_cmnd *pcmd = ccb->pcmd;
+       struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer;
+
+       pcmd->result = DID_OK << 16;
+       if (sensebuffer) {
+               int sense_data_length =
+                       sizeof(struct SENSE_DATA) < sizeof(pcmd->sense_buffer)
+                       ? sizeof(struct SENSE_DATA) : sizeof(pcmd->sense_buffer);
+               memset(sensebuffer, 0, sizeof(pcmd->sense_buffer));
+               memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length);
+               sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS;
+               sensebuffer->Valid = 1;
+       }
+}
+
+static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
+{
+       u32 orig_mask = 0;
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A : {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+               orig_mask = readl(&reg->outbound_intmask)|\
+                               ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
+               writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \
+                                               &reg->outbound_intmask);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B : {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \
+                                       (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
+               writel(0, reg->iop2drv_doorbell_mask_reg);
+               }
+               break;
+       }
+       return orig_mask;
+}
+
+static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \
+                       struct CommandControlBlock *ccb, uint32_t flag_ccb)
+{
+
+       uint8_t id, lun;
+       id = ccb->pcmd->device->id;
+       lun = ccb->pcmd->device->lun;
+       if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
+               if (acb->devstate[id][lun] == ARECA_RAID_GONE)
+                       acb->devstate[id][lun] = ARECA_RAID_GOOD;
+                       ccb->pcmd->result = DID_OK << 16;
+                       arcmsr_ccb_complete(ccb, 1);
+       } else {
+               switch (ccb->arcmsr_cdb.DeviceStatus) {
+               case ARCMSR_DEV_SELECT_TIMEOUT: {
+                       acb->devstate[id][lun] = ARECA_RAID_GONE;
+                       ccb->pcmd->result = DID_NO_CONNECT << 16;
+                       arcmsr_ccb_complete(ccb, 1);
+                       }
+                       break;
+
+               case ARCMSR_DEV_ABORTED:
+
+               case ARCMSR_DEV_INIT_FAIL: {
+                       acb->devstate[id][lun] = ARECA_RAID_GONE;
+                       ccb->pcmd->result = DID_BAD_TARGET << 16;
+                       arcmsr_ccb_complete(ccb, 1);
+                       }
+                       break;
+
+               case ARCMSR_DEV_CHECK_CONDITION: {
+                       acb->devstate[id][lun] = ARECA_RAID_GOOD;
+                       arcmsr_report_sense_info(ccb);
+                       arcmsr_ccb_complete(ccb, 1);
+                       }
+                       break;
+
+               default:
+                               printk(KERN_NOTICE
+                                       "arcmsr%d: scsi id = %d lun = %d"
+                                       " isr get command error done, "
+                                       "but got unknown DeviceStatus = 0x%x \n"
+                                       , acb->host->host_no
+                                       , id
+                                       , lun
+                                       , ccb->arcmsr_cdb.DeviceStatus);
+                                       acb->devstate[id][lun] = ARECA_RAID_GONE;
+                                       ccb->pcmd->result = DID_NO_CONNECT << 16;
+                                       arcmsr_ccb_complete(ccb, 1);
+                       break;
+               }
+       }
+}
+
+static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t flag_ccb)
+
+{
+       struct CommandControlBlock *ccb;
+
+       ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5));
+       if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
+               if (ccb->startdone == ARCMSR_CCB_ABORTED) {
+                       struct scsi_cmnd *abortcmd = ccb->pcmd;
+                       if (abortcmd) {
+                               abortcmd->result |= DID_ABORT << 16;
+                               arcmsr_ccb_complete(ccb, 1);
+                               printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \
+                               isr got aborted command \n", acb->host->host_no, ccb);
+                       }
+               }
+               printk(KERN_NOTICE "arcmsr%d: isr get an illegal ccb command \
+                               done acb = '0x%p'"
+                               "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x"
+                               " ccboutstandingcount = %d \n"
+                               , acb->host->host_no
+                               , acb
+                               , ccb
+                               , ccb->acb
+                               , ccb->startdone
+                               , atomic_read(&acb->ccboutstandingcount));
+               }
+       arcmsr_report_ccb_state(acb, ccb, flag_ccb);
+}
+
+static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
+{
+       int i = 0;
+       uint32_t flag_ccb;
+
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A __iomem *reg = \
+                       (struct MessageUnit_A *)acb->pmu;
+               uint32_t outbound_intstatus;
+               outbound_intstatus = readl(&reg->outbound_intstatus) & \
+                                       acb->outbound_int_enable;
+               /*clear and abort all outbound posted Q*/
+               writel(outbound_intstatus, &reg->outbound_intstatus);/*clear interrupt*/
+               while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) \
+                               && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
+                       arcmsr_drain_donequeue(acb, flag_ccb);
+               }
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               /*clear all outbound posted Q*/
+               for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
+                       if ((flag_ccb = readl(&reg->done_qbuffer[i])) != 0) {
+                               writel(0, &reg->done_qbuffer[i]);
+                               arcmsr_drain_donequeue(acb, flag_ccb);
+                       }
+                       writel(0, &reg->post_qbuffer[i]);
+               }
+               reg->doneq_index = 0;
+               reg->postq_index = 0;
+               }
+               break;
+       }
+}
 static void arcmsr_remove(struct pci_dev *pdev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pdev);
        struct AdapterControlBlock *acb =
                (struct AdapterControlBlock *) host->hostdata;
-       struct MessageUnit __iomem *reg = acb->pmu;
        int poll_count = 0;
 
        arcmsr_free_sysfs_attr(acb);
        scsi_remove_host(host);
        arcmsr_stop_adapter_bgrb(acb);
        arcmsr_flush_adapter_cache(acb);
-       writel(readl(&reg->outbound_intmask) |
-               ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE,
-               &reg->outbound_intmask);
+       arcmsr_disable_outbound_ints(acb);
        acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
        acb->acb_flags &= ~ACB_F_IOP_INITED;
 
-       for (poll_count = 0; poll_count < 256; poll_count++) {
+       for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++) {
                if (!atomic_read(&acb->ccboutstandingcount))
                        break;
-               arcmsr_interrupt(acb);
+               arcmsr_interrupt(acb);/* FIXME: need spinlock */
                msleep(25);
        }
 
@@ -429,8 +803,7 @@ static void arcmsr_remove(struct pci_dev *pdev)
                int i;
 
                arcmsr_abort_allcmd(acb);
-               for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++)
-                       readl(&reg->outbound_queueport);
+               arcmsr_done4abort_postqueue(acb);
                for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
                        struct CommandControlBlock *ccb = acb->pccb_pool[i];
                        if (ccb->startdone == ARCMSR_CCB_START) {
@@ -477,77 +850,34 @@ static void arcmsr_module_exit(void)
 module_init(arcmsr_module_init);
 module_exit(arcmsr_module_exit);
 
-static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
-{
-       struct MessageUnit __iomem *reg = acb->pmu;
-       u32 orig_mask = readl(&reg->outbound_intmask);
-
-       writel(orig_mask | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE,
-                       &reg->outbound_intmask);
-       return orig_mask;
-}
-
-static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb,
-               u32 orig_mask)
+static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
+                                               u32 intmask_org)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
        u32 mask;
 
-       mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE |
-                            ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
-       writel(mask, &reg->outbound_intmask);
-}
-
-static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
-{
-       struct MessageUnit __iomem *reg = acb->pmu;
-
-       writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
-       if (arcmsr_wait_msgint_ready(acb))
-               printk(KERN_NOTICE
-                       "arcmsr%d: wait 'flush adapter cache' timeout \n"
-                       , acb->host->host_no);
-}
+       switch (acb->adapter_type) {
 
-static void arcmsr_report_sense_info(struct CommandControlBlock *ccb)
-{
-       struct scsi_cmnd *pcmd = ccb->pcmd;
-       struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer;
+       case ACB_ADAPTER_TYPE_A : {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+               mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE |
+                            ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
+               writel(mask, &reg->outbound_intmask);
+               acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
+               }
+               break;
 
-       pcmd->result = DID_OK << 16;
-       if (sensebuffer) {
-               int sense_data_length =
-                       sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer)
-                       ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer);
-               memset(sensebuffer, 0, sizeof (pcmd->sense_buffer));
-               memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length);
-               sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS;
-               sensebuffer->Valid = 1;
+       case ACB_ADAPTER_TYPE_B : {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \
+                       ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE);
+               writel(mask, reg->iop2drv_doorbell_mask_reg);
+               acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
+               }
        }
 }
 
-static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb)
-{
-       struct MessageUnit __iomem *reg = acb->pmu;
-       uint32_t Index;
-       uint8_t Retries = 0x00;
-
-       do {
-               for (Index = 0; Index < 100; Index++) {
-                       if (readl(&reg->outbound_intstatus)
-                               & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
-                               writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT
-                                       , &reg->outbound_intstatus);
-                               return 0x00;
-                       }
-                       msleep_interruptible(10);
-               }/*max 1 seconds*/
-       } while (Retries++ < 20);/*max 20 sec*/
-       return 0xff;
-}
-
-static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
-       struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd)
+static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
+       struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd)
 {
        struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
        int8_t *psge = (int8_t *)&arcmsr_cdb->u;
@@ -556,7 +886,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
        int nseg;
 
        ccb->pcmd = pcmd;
-       memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB));
+       memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
        arcmsr_cdb->Bus = 0;
        arcmsr_cdb->TargetID = pcmd->device->id;
        arcmsr_cdb->LUN = pcmd->device->lun;
@@ -609,52 +939,85 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
 
 static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
        uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr;
        struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
-
        atomic_inc(&acb->ccboutstandingcount);
        ccb->startdone = ARCMSR_CCB_START;
-       if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE)
-               writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,
+
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu;
+
+               if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE)
+                       writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,
                        &reg->inbound_queueport);
-       else
-               writel(cdb_shifted_phyaddr, &reg->inbound_queueport);
-}
+               else {
+                               writel(cdb_shifted_phyaddr, &reg->inbound_queueport);
+               }
+               }
+               break;
 
-void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb)
-{
-       struct MessageUnit __iomem *reg = acb->pmu;
-       struct QBUFFER __iomem *pwbuffer = (struct QBUFFER __iomem *) &reg->message_wbuffer;
-       uint8_t __iomem *iop_data = (uint8_t __iomem *) pwbuffer->data;
-       int32_t allxfer_len = 0;
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               uint32_t ending_index, index = reg->postq_index;
 
-       if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) {
-               acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
-               while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
-                       && (allxfer_len < 124)) {
-                       writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data);
-                       acb->wqbuf_firstindex++;
-                       acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
-                       iop_data++;
-                       allxfer_len++;
+               ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE);
+               writel(0, &reg->post_qbuffer[ending_index]);
+               if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
+                       writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\
+                                                &reg->post_qbuffer[index]);
+               }
+               else {
+                       writel(cdb_shifted_phyaddr, &reg->post_qbuffer[index]);
                }
-               writel(allxfer_len, &pwbuffer->data_len);
-               writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK
-                       , &reg->inbound_doorbell);
+               index++;
+               index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */
+               reg->postq_index = index;
+               writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell_reg);
+               }
+               break;
        }
 }
 
-static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
+static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
-
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
        acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
        writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, &reg->inbound_msgaddr0);
-       if (arcmsr_wait_msgint_ready(acb))
+
+       if (arcmsr_hba_wait_msgint_ready(acb)) {
+               printk(KERN_NOTICE
+                       "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
+                       , acb->host->host_no);
+       }
+}
+
+static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+       acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+       writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg);
+
+       if (arcmsr_hbb_wait_msgint_ready(acb)) {
                printk(KERN_NOTICE
                        "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
                        , acb->host->host_no);
+       }
+}
+
+static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               arcmsr_stop_hba_bgrb(acb);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               arcmsr_stop_hbb_bgrb(acb);
+               }
+               break;
+       }
 }
 
 static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
@@ -665,151 +1028,260 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
                acb->dma_coherent_handle);
 }
 
-static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
+void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
-       struct CommandControlBlock *ccb;
-       uint32_t flag_ccb, outbound_intstatus, outbound_doorbell;
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
+               }
+               break;
 
-       outbound_intstatus = readl(&reg->outbound_intstatus)
-               & acb->outbound_int_enable;
-       writel(outbound_intstatus, &reg->outbound_intstatus);
-       if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
-               outbound_doorbell = readl(&reg->outbound_doorbell);
-               writel(outbound_doorbell, &reg->outbound_doorbell);
-               if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
-                       struct QBUFFER __iomem * prbuffer =
-                               (struct QBUFFER __iomem *) &reg->message_rbuffer;
-                       uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data;
-                       int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
-
-                       rqbuf_lastindex = acb->rqbuf_lastindex;
-                       rqbuf_firstindex = acb->rqbuf_firstindex;
-                       iop_len = readl(&prbuffer->data_len);
-                       my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1)
-                                       &(ARCMSR_MAX_QBUFFER - 1);
-                       if (my_empty_len >= iop_len) {
-                               while (iop_len > 0) {
-                                       acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
-                                       acb->rqbuf_lastindex++;
-                                       acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
-                                       iop_data++;
-                                       iop_len--;
-                               }
-                               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
-                                       &reg->inbound_doorbell);
-                       } else
-                               acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
-               }
-               if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
-                       acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
-                       if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
-                               struct QBUFFER __iomem * pwbuffer =
-                                               (struct QBUFFER __iomem *) &reg->message_wbuffer;
-                               uint8_t __iomem * iop_data = (uint8_t __iomem *) pwbuffer->data;
-                               int32_t allxfer_len = 0;
-
-                               acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
-                               while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
-                                       && (allxfer_len < 124)) {
-                                       writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data);
-                                       acb->wqbuf_firstindex++;
-                                       acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
-                                       iop_data++;
-                                       allxfer_len++;
-                               }
-                               writel(allxfer_len, &pwbuffer->data_len);
-                               writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK,
-                                       &reg->inbound_doorbell);
-                       }
-                       if (acb->wqbuf_firstindex == acb->wqbuf_lastindex)
-                               acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg);
                }
+               break;
        }
-       if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
-               int id, lun;
+}
+
+static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
                /*
-               ****************************************************************
-               **            areca cdb command done
-               ****************************************************************
+               ** push inbound doorbell tell iop, driver data write ok
+               ** and wait reply on next hwinterrupt for next Qbuffer post
                */
-               while (1) {
-                       if ((flag_ccb = readl(&reg->outbound_queueport)) == 0xFFFFFFFF)
-                               break;/*chip FIFO no ccb for completion already*/
-                       /* check if command done with no error*/
-                       ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
-                               (flag_ccb << 5));
-                       if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
-                               if (ccb->startdone == ARCMSR_CCB_ABORTED) {
-                                       struct scsi_cmnd *abortcmd = ccb->pcmd;
-                                       if (abortcmd) {
-                                       abortcmd->result |= DID_ABORT >> 16;
-                                       arcmsr_ccb_complete(ccb, 1);
-                                       printk(KERN_NOTICE
-                                               "arcmsr%d: ccb ='0x%p' isr got aborted command \n"
-                                               , acb->host->host_no, ccb);
-                                       }
-                                       continue;
-                               }
-                               printk(KERN_NOTICE
-                                       "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'"
-                                       "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x"
-                                       " ccboutstandingcount = %d \n"
-                                       , acb->host->host_no
-                                       , acb
-                                       , ccb
-                                       , ccb->acb
-                                       , ccb->startdone
-                                       , atomic_read(&acb->ccboutstandingcount));
-                               continue;
-                       }
-                       id = ccb->pcmd->device->id;
-                       lun = ccb->pcmd->device->lun;
-                       if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
-                               if (acb->devstate[id][lun] == ARECA_RAID_GONE)
-                                       acb->devstate[id][lun] = ARECA_RAID_GOOD;
-                               ccb->pcmd->result = DID_OK << 16;
-                               arcmsr_ccb_complete(ccb, 1);
-                       } else {
-                               switch(ccb->arcmsr_cdb.DeviceStatus) {
-                               case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                               acb->devstate[id][lun] = ARECA_RAID_GONE;
-                                               ccb->pcmd->result = DID_NO_CONNECT << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
-                               case ARCMSR_DEV_ABORTED:
-                               case ARCMSR_DEV_INIT_FAIL: {
-                                               acb->devstate[id][lun] = ARECA_RAID_GONE;
-                                               ccb->pcmd->result = DID_BAD_TARGET << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
-                               case ARCMSR_DEV_CHECK_CONDITION: {
-                                               acb->devstate[id][lun] = ARECA_RAID_GOOD;
-                                               arcmsr_report_sense_info(ccb);
-                                               arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
-                               default:
-                                       printk(KERN_NOTICE
-                                               "arcmsr%d: scsi id = %d lun = %d"
-                                               " isr get command error done, "
-                                               "but got unknown DeviceStatus = 0x%x \n"
-                                               , acb->host->host_no
-                                               , id
-                                               , lun
-                                               , ccb->arcmsr_cdb.DeviceStatus);
-                                               acb->devstate[id][lun] = ARECA_RAID_GONE;
-                                               ccb->pcmd->result = DID_NO_CONNECT << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                                       break;
-                               }
-                       }
-               }/*drain reply FIFO*/
+               writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, &reg->inbound_doorbell);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               /*
+               ** push inbound doorbell tell iop, driver data write ok
+               ** and wait reply on next hwinterrupt for next Qbuffer post
+               */
+               writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell_reg);
+               }
+               break;
+       }
+}
+
+struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb)
+{
+       static struct QBUFFER *qbuffer;
+
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+               qbuffer = (struct QBUFFER __iomem *) &reg->message_rbuffer;
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg;
+               }
+               break;
+       }
+       return qbuffer;
+}
+
+static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
+{
+       static struct QBUFFER *pqbuffer;
+
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+               pqbuffer = (struct QBUFFER *) &reg->message_wbuffer;
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B  *reg = (struct MessageUnit_B *)acb->pmu;
+               pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg;
+               }
+               break;
+       }
+       return pqbuffer;
+}
+
+static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
+{
+       struct QBUFFER *prbuffer;
+       struct QBUFFER *pQbuffer;
+       uint8_t *iop_data;
+       int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
+
+       rqbuf_lastindex = acb->rqbuf_lastindex;
+       rqbuf_firstindex = acb->rqbuf_firstindex;
+       prbuffer = arcmsr_get_iop_rqbuffer(acb);
+       iop_data = (uint8_t *)prbuffer->data;
+       iop_len = prbuffer->data_len;
+       my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1);
+
+       if (my_empty_len >= iop_len)
+       {
+               while (iop_len > 0) {
+                       pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex];
+                       memcpy(pQbuffer, iop_data,1);
+                       rqbuf_lastindex++;
+                       rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+                       iop_data++;
+                       iop_len--;
+               }
+               acb->rqbuf_lastindex = rqbuf_lastindex;
+               arcmsr_iop_message_read(acb);
+       }
+
+       else {
+               acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
+       }
+}
+
+static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
+{
+       acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
+       if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
+               uint8_t *pQbuffer;
+               struct QBUFFER *pwbuffer;
+               uint8_t *iop_data;
+               int32_t allxfer_len = 0;
+
+               acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
+               pwbuffer = arcmsr_get_iop_wqbuffer(acb);
+               iop_data = (uint8_t __iomem *)pwbuffer->data;
+
+               while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) && \
+                                                       (allxfer_len < 124)) {
+                       pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
+                       memcpy(iop_data, pQbuffer, 1);
+                       acb->wqbuf_firstindex++;
+                       acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
+                       iop_data++;
+                       allxfer_len++;
+               }
+               pwbuffer->data_len = allxfer_len;
+
+               arcmsr_iop_message_wrote(acb);
+       }
+
+       if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) {
+               acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
+       }
+}
+
+static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
+{
+       uint32_t outbound_doorbell;
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+
+       outbound_doorbell = readl(&reg->outbound_doorbell);
+       writel(outbound_doorbell, &reg->outbound_doorbell);
+       if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
+               arcmsr_iop2drv_data_wrote_handle(acb);
+       }
+
+       if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK)    {
+               arcmsr_iop2drv_data_read_handle(acb);
+       }
+}
+
+static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
+{
+       uint32_t flag_ccb;
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+
+       while ((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) {
+               arcmsr_drain_donequeue(acb, flag_ccb);
+       }
+}
+
+static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
+{
+       uint32_t index;
+       uint32_t flag_ccb;
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+
+       index = reg->doneq_index;
+
+       while ((flag_ccb = readl(&reg->done_qbuffer[index])) != 0) {
+               writel(0, &reg->done_qbuffer[index]);
+               arcmsr_drain_donequeue(acb, flag_ccb);
+               index++;
+               index %= ARCMSR_MAX_HBB_POSTQUEUE;
+               reg->doneq_index = index;
+       }
+}
+
+static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
+{
+       uint32_t outbound_intstatus;
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+
+       outbound_intstatus = readl(&reg->outbound_intstatus) & \
+                                                       acb->outbound_int_enable;
+       if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT))      {
+               return 1;
+       }
+       writel(outbound_intstatus, &reg->outbound_intstatus);
+       if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT)       {
+               arcmsr_hba_doorbell_isr(acb);
+       }
+       if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
+               arcmsr_hba_postqueue_isr(acb);
+       }
+       return 0;
+}
+
+static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
+{
+       uint32_t outbound_doorbell;
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+
+       outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \
+                                                       acb->outbound_int_enable;
+       if (!outbound_doorbell)
+               return 1;
+
+       writel(~outbound_doorbell, reg->iop2drv_doorbell_reg);
+
+       if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK)   {
+               arcmsr_iop2drv_data_wrote_handle(acb);
+       }
+       if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) {
+               arcmsr_iop2drv_data_read_handle(acb);
+       }
+       if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
+               arcmsr_hbb_postqueue_isr(acb);
+       }
+
+       return 0;
+}
+
+static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               if (arcmsr_handle_hba_isr(acb)) {
+                       return IRQ_NONE;
+               }
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               if (arcmsr_handle_hbb_isr(acb)) {
+                       return IRQ_NONE;
+               }
+               }
+               break;
        }
-       if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT))
-               return IRQ_NONE;
        return IRQ_HANDLED;
 }
 
@@ -818,16 +1290,47 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
        if (acb) {
                /* stop adapter background rebuild */
                if (acb->acb_flags & ACB_F_MSG_START_BGRB) {
+                       uint32_t intmask_org;
                        acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+                       intmask_org = arcmsr_disable_outbound_ints(acb);
                        arcmsr_stop_adapter_bgrb(acb);
                        arcmsr_flush_adapter_cache(acb);
+                       arcmsr_enable_outbound_ints(acb, intmask_org);
+               }
+       }
+}
+
+void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
+{
+       int32_t wqbuf_firstindex, wqbuf_lastindex;
+       uint8_t *pQbuffer;
+       struct QBUFFER *pwbuffer;
+       uint8_t *iop_data;
+       int32_t allxfer_len = 0;
+
+       pwbuffer = arcmsr_get_iop_wqbuffer(acb);
+       iop_data = (uint8_t __iomem *)pwbuffer->data;
+       if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) {
+               acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
+               wqbuf_firstindex = acb->wqbuf_firstindex;
+               wqbuf_lastindex = acb->wqbuf_lastindex;
+               while ((wqbuf_firstindex != wqbuf_lastindex) && (allxfer_len < 124)) {
+                       pQbuffer = &acb->wqbuffer[wqbuf_firstindex];
+                       memcpy(iop_data, pQbuffer, 1);
+                       wqbuf_firstindex++;
+                       wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
+                       iop_data++;
+                       allxfer_len++;
                }
+               acb->wqbuf_firstindex = wqbuf_firstindex;
+               pwbuffer->data_len = allxfer_len;
+               arcmsr_iop_message_wrote(acb);
        }
 }
 
-static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd)
+static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
+                                       struct scsi_cmnd *cmd)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
        struct CMD_MESSAGE_FIELD *pcmdmessagefld;
        int retvalue = 0, transfer_len = 0;
        char *buffer;
@@ -836,7 +1339,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_
                                                (uint32_t ) cmd->cmnd[6] << 16 |
                                                (uint32_t ) cmd->cmnd[7] << 8  |
                                                (uint32_t ) cmd->cmnd[8];
-                                       /* 4 bytes: Areca io control code */
+                                               /* 4 bytes: Areca io control code */
 
        sg = scsi_sglist(cmd);
        buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
@@ -852,194 +1355,199 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_
        }
        pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
        switch(controlcode) {
+
        case ARCMSR_MESSAGE_READ_RQBUFFER: {
-                       unsigned long *ver_addr;
-                       dma_addr_t buf_handle;
-                       uint8_t *pQbuffer, *ptmpQbuffer;
-                       int32_t allxfer_len = 0;
+               unsigned long *ver_addr;
+               dma_addr_t buf_handle;
+               uint8_t *pQbuffer, *ptmpQbuffer;
+               int32_t allxfer_len = 0;
+
+               ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
+               if (!ver_addr) {
+                       retvalue = ARCMSR_MESSAGE_FAIL;
+                       goto message_out;
+               }
+               ptmpQbuffer = (uint8_t *) ver_addr;
+               while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
+                       && (allxfer_len < 1031)) {
+                       pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
+                       memcpy(ptmpQbuffer, pQbuffer, 1);
+                       acb->rqbuf_firstindex++;
+                       acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
+                       ptmpQbuffer++;
+                       allxfer_len++;
+               }
+               if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
 
-                       ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
-                       if (!ver_addr) {
-                               retvalue = ARCMSR_MESSAGE_FAIL;
-                               goto message_out;
-                       }
-                       ptmpQbuffer = (uint8_t *) ver_addr;
-                       while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
-                               && (allxfer_len < 1031)) {
-                               pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
-                               memcpy(ptmpQbuffer, pQbuffer, 1);
-                               acb->rqbuf_firstindex++;
-                               acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
-                               ptmpQbuffer++;
-                               allxfer_len++;
-                       }
-                       if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-                               struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *)
-                                                       &reg->message_rbuffer;
-                               uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data;
-                               int32_t iop_len;
-
-                               acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                               iop_len = readl(&prbuffer->data_len);
-                               while (iop_len > 0) {
-                                       acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
-                                       acb->rqbuf_lastindex++;
-                                       acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
-                                       iop_data++;
-                                       iop_len--;
-                               }
-                               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
-                                               &reg->inbound_doorbell);
+                       struct QBUFFER *prbuffer;
+                       uint8_t *iop_data;
+                       int32_t iop_len;
+
+                       acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
+                       prbuffer = arcmsr_get_iop_rqbuffer(acb);
+                       iop_data = (uint8_t *)prbuffer->data;
+                       iop_len = readl(&prbuffer->data_len);
+                       while (iop_len > 0) {
+                               acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
+                               acb->rqbuf_lastindex++;
+                               acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+                               iop_data++;
+                               iop_len--;
                        }
-                       memcpy(pcmdmessagefld->messagedatabuffer,
-                               (uint8_t *)ver_addr, allxfer_len);
-                       pcmdmessagefld->cmdmessage.Length = allxfer_len;
-                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
-                       pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
+                       arcmsr_iop_message_read(acb);
+               }
+               memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len);
+               pcmdmessagefld->cmdmessage.Length = allxfer_len;
+               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+               pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
                }
                break;
-       case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
-                       unsigned long *ver_addr;
-                       dma_addr_t buf_handle;
-                       int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
-                       uint8_t *pQbuffer, *ptmpuserbuffer;
 
-                       ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
-                       if (!ver_addr) {
-                               retvalue = ARCMSR_MESSAGE_FAIL;
-                               goto message_out;
-                       }
-                       ptmpuserbuffer = (uint8_t *)ver_addr;
-                       user_len = pcmdmessagefld->cmdmessage.Length;
-                       memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len);
-                       wqbuf_lastindex = acb->wqbuf_lastindex;
-                       wqbuf_firstindex = acb->wqbuf_firstindex;
-                       if (wqbuf_lastindex != wqbuf_firstindex) {
+       case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
+               unsigned long *ver_addr;
+               dma_addr_t buf_handle;
+               int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
+               uint8_t *pQbuffer, *ptmpuserbuffer;
+
+               ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
+               if (!ver_addr) {
+                       retvalue = ARCMSR_MESSAGE_FAIL;
+                       goto message_out;
+               }
+               ptmpuserbuffer = (uint8_t *)ver_addr;
+               user_len = pcmdmessagefld->cmdmessage.Length;
+               memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len);
+               wqbuf_lastindex = acb->wqbuf_lastindex;
+               wqbuf_firstindex = acb->wqbuf_firstindex;
+               if (wqbuf_lastindex != wqbuf_firstindex) {
+                       struct SENSE_DATA *sensebuffer =
+                               (struct SENSE_DATA *)cmd->sense_buffer;
+                       arcmsr_post_ioctldata2iop(acb);
+                       /* has error report sensedata */
+                       sensebuffer->ErrorCode = 0x70;
+                       sensebuffer->SenseKey = ILLEGAL_REQUEST;
+                       sensebuffer->AdditionalSenseLength = 0x0A;
+                       sensebuffer->AdditionalSenseCode = 0x20;
+                       sensebuffer->Valid = 1;
+                       retvalue = ARCMSR_MESSAGE_FAIL;
+               } else {
+                       my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
+                               &(ARCMSR_MAX_QBUFFER - 1);
+                       if (my_empty_len >= user_len) {
+                               while (user_len > 0) {
+                                       pQbuffer =
+                                       &acb->wqbuffer[acb->wqbuf_lastindex];
+                                       memcpy(pQbuffer, ptmpuserbuffer, 1);
+                                       acb->wqbuf_lastindex++;
+                                       acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+                                       ptmpuserbuffer++;
+                                       user_len--;
+                               }
+                               if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
+                                       acb->acb_flags &=
+                                               ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
+                                       arcmsr_post_ioctldata2iop(acb);
+                               }
+                       } else {
+                               /* has error report sensedata */
                                struct SENSE_DATA *sensebuffer =
                                        (struct SENSE_DATA *)cmd->sense_buffer;
-                               arcmsr_post_Qbuffer(acb);
-                               /* has error report sensedata */
                                sensebuffer->ErrorCode = 0x70;
                                sensebuffer->SenseKey = ILLEGAL_REQUEST;
                                sensebuffer->AdditionalSenseLength = 0x0A;
                                sensebuffer->AdditionalSenseCode = 0x20;
                                sensebuffer->Valid = 1;
                                retvalue = ARCMSR_MESSAGE_FAIL;
-                       } else {
-                               my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
-                                               &(ARCMSR_MAX_QBUFFER - 1);
-                               if (my_empty_len >= user_len) {
-                                       while (user_len > 0) {
-                                               pQbuffer =
-                                               &acb->wqbuffer[acb->wqbuf_lastindex];
-                                               memcpy(pQbuffer, ptmpuserbuffer, 1);
-                                               acb->wqbuf_lastindex++;
-                                               acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
-                                               ptmpuserbuffer++;
-                                               user_len--;
-                                       }
-                                       if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
-                                               acb->acb_flags &=
-                                                       ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-                                               arcmsr_post_Qbuffer(acb);
-                                       }
-                               } else {
-                                       /* has error report sensedata */
-                                       struct SENSE_DATA *sensebuffer =
-                                               (struct SENSE_DATA *)cmd->sense_buffer;
-                                       sensebuffer->ErrorCode = 0x70;
-                                       sensebuffer->SenseKey = ILLEGAL_REQUEST;
-                                       sensebuffer->AdditionalSenseLength = 0x0A;
-                                       sensebuffer->AdditionalSenseCode = 0x20;
-                                       sensebuffer->Valid = 1;
-                                       retvalue = ARCMSR_MESSAGE_FAIL;
-                               }
+                       }
                        }
                        pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
                }
                break;
+
        case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
-                       uint8_t *pQbuffer = acb->rqbuffer;
+               uint8_t *pQbuffer = acb->rqbuffer;
 
-                       if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-                               acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
-                                       &reg->inbound_doorbell);
-                       }
-                       acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
-                       acb->rqbuf_firstindex = 0;
-                       acb->rqbuf_lastindex = 0;
-                       memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
-                       pcmdmessagefld->cmdmessage.ReturnCode =
-                               ARCMSR_MESSAGE_RETURNCODE_OK;
+               if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
+                       acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
+                       arcmsr_iop_message_read(acb);
+               }
+               acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
+               acb->rqbuf_firstindex = 0;
+               acb->rqbuf_lastindex = 0;
+               memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
+               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
                }
                break;
+
        case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
-                       uint8_t *pQbuffer = acb->wqbuffer;
+               uint8_t *pQbuffer = acb->wqbuffer;
 
-                       if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-                               acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK
-                                               , &reg->inbound_doorbell);
-                       }
-                       acb->acb_flags |=
-                               (ACB_F_MESSAGE_WQBUFFER_CLEARED |
-                                       ACB_F_MESSAGE_WQBUFFER_READED);
-                       acb->wqbuf_firstindex = 0;
-                       acb->wqbuf_lastindex = 0;
-                       memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
-                       pcmdmessagefld->cmdmessage.ReturnCode =
-                               ARCMSR_MESSAGE_RETURNCODE_OK;
+               if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
+                       acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
+                       arcmsr_iop_message_read(acb);
+               }
+               acb->acb_flags |=
+                       (ACB_F_MESSAGE_WQBUFFER_CLEARED |
+                               ACB_F_MESSAGE_WQBUFFER_READED);
+               acb->wqbuf_firstindex = 0;
+               acb->wqbuf_lastindex = 0;
+               memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
+               pcmdmessagefld->cmdmessage.ReturnCode =
+                       ARCMSR_MESSAGE_RETURNCODE_OK;
                }
                break;
+
        case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
-                       uint8_t *pQbuffer;
+               uint8_t *pQbuffer;
 
-                       if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-                               acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK
-                                               , &reg->inbound_doorbell);
-                       }
-                       acb->acb_flags |=
-                               (ACB_F_MESSAGE_WQBUFFER_CLEARED
-                               | ACB_F_MESSAGE_RQBUFFER_CLEARED
-                               | ACB_F_MESSAGE_WQBUFFER_READED);
-                       acb->rqbuf_firstindex = 0;
-                       acb->rqbuf_lastindex = 0;
-                       acb->wqbuf_firstindex = 0;
-                       acb->wqbuf_lastindex = 0;
-                       pQbuffer = acb->rqbuffer;
-                       memset(pQbuffer, 0, sizeof (struct QBUFFER));
-                       pQbuffer = acb->wqbuffer;
-                       memset(pQbuffer, 0, sizeof (struct QBUFFER));
-                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+               if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
+                       acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
+                       arcmsr_iop_message_read(acb);
+               }
+               acb->acb_flags |=
+                       (ACB_F_MESSAGE_WQBUFFER_CLEARED
+                       | ACB_F_MESSAGE_RQBUFFER_CLEARED
+                       | ACB_F_MESSAGE_WQBUFFER_READED);
+               acb->rqbuf_firstindex = 0;
+               acb->rqbuf_lastindex = 0;
+               acb->wqbuf_firstindex = 0;
+               acb->wqbuf_lastindex = 0;
+               pQbuffer = acb->rqbuffer;
+               memset(pQbuffer, 0, sizeof(struct QBUFFER));
+               pQbuffer = acb->wqbuffer;
+               memset(pQbuffer, 0, sizeof(struct QBUFFER));
+               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
                }
                break;
+
        case ARCMSR_MESSAGE_RETURN_CODE_3F: {
-                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
+               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
                }
                break;
+
        case ARCMSR_MESSAGE_SAY_HELLO: {
-                       int8_t * hello_string = "Hello! I am ARCMSR";
+               int8_t *hello_string = "Hello! I am ARCMSR";
 
-                       memcpy(pcmdmessagefld->messagedatabuffer, hello_string
-                               , (int16_t)strlen(hello_string));
-                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+               memcpy(pcmdmessagefld->messagedatabuffer, hello_string
+                       , (int16_t)strlen(hello_string));
+               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
                }
                break;
+
        case ARCMSR_MESSAGE_SAY_GOODBYE:
                arcmsr_iop_parking(acb);
                break;
+
        case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
                arcmsr_flush_adapter_cache(acb);
                break;
+
        default:
                retvalue = ARCMSR_MESSAGE_FAIL;
        }
- message_out:
      message_out:
        sg = scsi_sglist(cmd);
        kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-
        return retvalue;
 }
 
@@ -1109,8 +1617,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
        void (* done)(struct scsi_cmnd *))
 {
        struct Scsi_Host *host = cmd->device->host;
-       struct AdapterControlBlock *acb =
-               (struct AdapterControlBlock *) host->hostdata;
+       struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
        struct CommandControlBlock *ccb;
        int target = cmd->device->id;
        int lun = cmd->device->lun;
@@ -1153,26 +1660,27 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
        ccb = arcmsr_get_freeccb(acb);
        if (!ccb)
                return SCSI_MLQUEUE_HOST_BUSY;
+
        arcmsr_build_ccb(acb, ccb, cmd);
        arcmsr_post_ccb(acb, ccb);
        return 0;
 }
 
-static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
+static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
        char *acb_firm_model = acb->firm_model;
        char *acb_firm_version = acb->firm_version;
-       char __iomem *iop_firm_model = (char __iomem *) &reg->message_rwbuffer[15];
-       char __iomem *iop_firm_version = (char __iomem *) &reg->message_rwbuffer[17];
+       char *iop_firm_model = (char *) (&reg->message_rwbuffer[15]);
+       char *iop_firm_version = (char *) (&reg->message_rwbuffer[17]);
        int count;
 
        writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
-       if (arcmsr_wait_msgint_ready(acb))
-               printk(KERN_NOTICE
-                       "arcmsr%d: wait "
-                       "'get adapter firmware miscellaneous data' timeout \n"
-                       , acb->host->host_no);
+       if (arcmsr_hba_wait_msgint_ready(acb)) {
+               printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
+                       miscellaneous data' timeout \n", acb->host->host_no);
+       }
+
        count = 8;
        while (count) {
                *acb_firm_model = readb(iop_firm_model);
@@ -1180,6 +1688,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
                iop_firm_model++;
                count--;
        }
+
        count = 16;
        while (count) {
                *acb_firm_version = readb(iop_firm_version);
@@ -1187,28 +1696,93 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
                iop_firm_version++;
                count--;
        }
-       printk(KERN_INFO
-               "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n"
+
+       printk(KERN_INFO        "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n"
                , acb->host->host_no
                , acb->firm_version);
+
        acb->firm_request_len = readl(&reg->message_rwbuffer[1]);
        acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]);
        acb->firm_sdram_size = readl(&reg->message_rwbuffer[3]);
        acb->firm_hd_channels = readl(&reg->message_rwbuffer[4]);
 }
 
-static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
+static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+       uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg;
+       char *acb_firm_model = acb->firm_model;
+       char *acb_firm_version = acb->firm_version;
+       char *iop_firm_model = (char *) (&lrwbuffer[15]);
+       /*firm_model,15,60-67*/
+       char *iop_firm_version = (char *) (&lrwbuffer[17]);
+       /*firm_version,17,68-83*/
+       int count;
+
+       writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg);
+       if (arcmsr_hbb_wait_msgint_ready(acb)) {
+               printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
+                       miscellaneous data' timeout \n", acb->host->host_no);
+       }
+
+       count = 8;
+       while (count)
+       {
+               *acb_firm_model = readb(iop_firm_model);
+               acb_firm_model++;
+               iop_firm_model++;
+               count--;
+       }
+
+       count = 16;
+       while (count)
+       {
+               *acb_firm_version = readb(iop_firm_version);
+               acb_firm_version++;
+               iop_firm_version++;
+               count--;
+       }
+
+       printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n",
+                       acb->host->host_no,
+                       acb->firm_version);
+
+       lrwbuffer++;
+       acb->firm_request_len = readl(lrwbuffer++);
+       /*firm_request_len,1,04-07*/
+       acb->firm_numbers_queue = readl(lrwbuffer++);
+       /*firm_numbers_queue,2,08-11*/
+       acb->firm_sdram_size = readl(lrwbuffer++);
+       /*firm_sdram_size,3,12-15*/
+       acb->firm_hd_channels = readl(lrwbuffer);
+       /*firm_ide_channels,4,16-19*/
+}
+
+static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               arcmsr_get_hba_config(acb);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               arcmsr_get_hbb_config(acb);
+               }
+               break;
+       }
+}
+
+static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
        struct CommandControlBlock *poll_ccb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
        struct CommandControlBlock *ccb;
        uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0;
-       int id, lun;
 
polling_ccb_retry:
      polling_hba_ccb_retry:
        poll_count++;
-       outbound_intstatus = readl(&reg->outbound_intstatus)
-                                       & acb->outbound_int_enable;
+       outbound_intstatus = readl(&reg->outbound_intstatus) & acb->outbound_int_enable;
        writel(outbound_intstatus, &reg->outbound_intstatus);/*clear interrupt*/
        while (1) {
                if ((flag_ccb = readl(&reg->outbound_queueport)) == 0xFFFFFFFF) {
@@ -1218,17 +1792,14 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
                                msleep(25);
                                if (poll_count > 100)
                                        break;
-                               goto polling_ccb_retry;
+                               goto polling_hba_ccb_retry;
                        }
                }
-               ccb = (struct CommandControlBlock *)
-                       (acb->vir2phy_offset + (flag_ccb << 5));
-               if ((ccb->acb != acb) ||
-                       (ccb->startdone != ARCMSR_CCB_START)) {
-                       if ((ccb->startdone == ARCMSR_CCB_ABORTED) ||
-                               (ccb == poll_ccb)) {
-                               printk(KERN_NOTICE
-                                       "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'"
+               ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5));
+               poll_ccb_done = (ccb == poll_ccb) ? 1:0;
+               if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
+                       if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) {
+                               printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'"
                                        " poll command abort successfully \n"
                                        , acb->host->host_no
                                        , ccb->pcmd->device->id
@@ -1239,176 +1810,280 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
                                poll_ccb_done = 1;
                                continue;
                        }
-                       printk(KERN_NOTICE
-                               "arcmsr%d: polling get an illegal ccb"
-                               " command done ccb ='0x%p'"
+                       printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb"
+                               " command done ccb = '0x%p'"
                                "ccboutstandingcount = %d \n"
                                , acb->host->host_no
                                , ccb
                                , atomic_read(&acb->ccboutstandingcount));
                        continue;
                }
-               id = ccb->pcmd->device->id;
-               lun = ccb->pcmd->device->lun;
-               if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
-                       if (acb->devstate[id][lun] == ARECA_RAID_GONE)
-                               acb->devstate[id][lun] = ARECA_RAID_GOOD;
-                       ccb->pcmd->result = DID_OK << 16;
-                       arcmsr_ccb_complete(ccb, 1);
-               } else {
-                       switch(ccb->arcmsr_cdb.DeviceStatus) {
-                       case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                       acb->devstate[id][lun] = ARECA_RAID_GONE;
-                                       ccb->pcmd->result = DID_NO_CONNECT << 16;
-                                       arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
-                       case ARCMSR_DEV_ABORTED:
-                       case ARCMSR_DEV_INIT_FAIL: {
-                                       acb->devstate[id][lun] = ARECA_RAID_GONE;
-                                       ccb->pcmd->result = DID_BAD_TARGET << 16;
-                                       arcmsr_ccb_complete(ccb, 1);
+               arcmsr_report_ccb_state(acb, ccb, flag_ccb);
+       }
+}
+
+static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
+                                       struct CommandControlBlock *poll_ccb)
+{
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               struct CommandControlBlock *ccb;
+               uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0;
+               int index;
+
+       polling_hbb_ccb_retry:
+               poll_count++;
+               /* clear doorbell interrupt */
+               writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg);
+               while (1) {
+                       index = reg->doneq_index;
+                       if ((flag_ccb = readl(&reg->done_qbuffer[index])) == 0) {
+                               if (poll_ccb_done)
+                                       break;
+                               else {
+                                       msleep(25);
+                                       if (poll_count > 100)
+                                               break;
+                                       goto polling_hbb_ccb_retry;
                                }
-                               break;
-                       case ARCMSR_DEV_CHECK_CONDITION: {
-                                       acb->devstate[id][lun] = ARECA_RAID_GOOD;
-                                       arcmsr_report_sense_info(ccb);
+                       }
+                       writel(0, &reg->done_qbuffer[index]);
+                       index++;
+                       /*if last index number set it to 0 */
+                       index %= ARCMSR_MAX_HBB_POSTQUEUE;
+                       reg->doneq_index = index;
+                       /* check ifcommand done with no error*/
+                       ccb = (struct CommandControlBlock *)\
+      (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/
+                       poll_ccb_done = (ccb == poll_ccb) ? 1:0;
+                       if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
+                               if (ccb->startdone == ARCMSR_CCB_ABORTED) {
+                                       printk(KERN_NOTICE "arcmsr%d: \
+               scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n"
+                                               ,acb->host->host_no
+                                               ,ccb->pcmd->device->id
+                                               ,ccb->pcmd->device->lun
+                                               ,ccb);
+                                       ccb->pcmd->result = DID_ABORT << 16;
                                        arcmsr_ccb_complete(ccb, 1);
+                                       continue;
                                }
-                               break;
-                       default:
-                               printk(KERN_NOTICE
-                                       "arcmsr%d: scsi id = %d lun = %d"
-                                       " polling and getting command error done"
-                                       "but got unknown DeviceStatus = 0x%x \n"
+                               printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb"
+                                       " command done ccb = '0x%p'"
+                                       "ccboutstandingcount = %d \n"
                                        , acb->host->host_no
-                                       , id
-                                       , lun
-                                       , ccb->arcmsr_cdb.DeviceStatus);
-                               acb->devstate[id][lun] = ARECA_RAID_GONE;
-                               ccb->pcmd->result = DID_BAD_TARGET << 16;
-                               arcmsr_ccb_complete(ccb, 1);
-                               break;
+                                       , ccb
+                                       , atomic_read(&acb->ccboutstandingcount));
+                               continue;
                        }
+                       arcmsr_report_ccb_state(acb, ccb, flag_ccb);
+               }       /*drain reply FIFO*/
+}
+
+static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \
+                                       struct CommandControlBlock *poll_ccb)
+{
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               arcmsr_polling_hba_ccbdone(acb,poll_ccb);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               arcmsr_polling_hbb_ccbdone(acb,poll_ccb);
                }
        }
 }
-static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb)
+
+static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
 {
-       int i = 0, found = 0;
-       int id, lun;
-       uint32_t flag_ccb, outbound_intstatus;
-       struct MessageUnit __iomem *reg = acb->pmu;
-       struct CommandControlBlock *ccb;
-       /*clear and abort all outbound posted Q*/
-
-       while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
-(i++ < 256)){
-               ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
-(flag_ccb << 5));
-       if (ccb){
-               if ((ccb->acb != acb)||(ccb->startdone != \
-ARCMSR_CCB_START)){
-                               printk(KERN_NOTICE "arcmsr%d: polling get \
-an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n",
-                                       acb->host->host_no, ccb,
-                                       atomic_read(&acb->ccboutstandingcount));
-                               continue;
+       uint32_t cdb_phyaddr, ccb_phyaddr_hi32;
+       dma_addr_t dma_coherent_handle;
+       /*
+       ********************************************************************
+       ** here we need to tell iop 331 our freeccb.HighPart
+       ** if freeccb.HighPart is not zero
+       ********************************************************************
+       */
+       dma_coherent_handle = acb->dma_coherent_handle;
+       cdb_phyaddr = (uint32_t)(dma_coherent_handle);
+       ccb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16);
+       /*
+       ***********************************************************************
+       **    if adapter type B, set window of "post command Q"
+       ***********************************************************************
+       */
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               if (ccb_phyaddr_hi32 != 0) {
+                       struct MessageUnit_A __iomem *reg = \
+                                       (struct MessageUnit_A *)acb->pmu;
+                       uint32_t intmask_org;
+                       intmask_org = arcmsr_disable_outbound_ints(acb);
+                       writel(ARCMSR_SIGNATURE_SET_CONFIG, \
+                                               &reg->message_rwbuffer[0]);
+                       writel(ccb_phyaddr_hi32, &reg->message_rwbuffer[1]);
+                       writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \
+                                                       &reg->inbound_msgaddr0);
+                       if (arcmsr_hba_wait_msgint_ready(acb)) {
+                               printk(KERN_NOTICE "arcmsr%d: ""set ccb high \
+                               part physical address timeout\n",
+                               acb->host->host_no);
+                               return 1;
                        }
+                       arcmsr_enable_outbound_ints(acb, intmask_org);
+               }
+               }
+               break;
 
-                       id = ccb->pcmd->device->id;
-                       lun = ccb->pcmd->device->lun;
-                       if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){
-                               if (acb->devstate[id][lun] == ARECA_RAID_GONE)
-                                       acb->devstate[id][lun] = ARECA_RAID_GOOD;
-                               ccb->pcmd->result = DID_OK << 16;
-                               arcmsr_ccb_complete(ccb, 1);
-                       }
-                       else {
-                               switch(ccb->arcmsr_cdb.DeviceStatus) {
-                               case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                               acb->devstate[id][lun] = ARECA_RAID_GONE;
-                                               ccb->pcmd->result = DID_NO_CONNECT << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
+       case ACB_ADAPTER_TYPE_B: {
+               unsigned long post_queue_phyaddr;
+               uint32_t *rwbuffer;
 
-                               case ARCMSR_DEV_ABORTED:
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               uint32_t intmask_org;
+               intmask_org = arcmsr_disable_outbound_ints(acb);
+               reg->postq_index = 0;
+               reg->doneq_index = 0;
+               writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell_reg);
+               if (arcmsr_hbb_wait_msgint_ready(acb)) {
+                       printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \
+                               acb->host->host_no);
+                       return 1;
+               }
+               post_queue_phyaddr = cdb_phyaddr + ARCMSR_MAX_FREECCB_NUM * \
+               sizeof(struct CommandControlBlock) + offsetof(struct MessageUnit_B, post_qbuffer) ;
+               rwbuffer = reg->msgcode_rwbuffer_reg;
+               /* driver "set config" signature */
+               writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++);
+               /* normal should be zero */
+               writel(ccb_phyaddr_hi32, rwbuffer++);
+               /* postQ size (256 + 8)*4        */
+               writel(post_queue_phyaddr, rwbuffer++);
+               /* doneQ size (256 + 8)*4        */
+               writel(post_queue_phyaddr + 1056, rwbuffer++);
+               /* ccb maxQ size must be --> [(256 + 8)*4]*/
+               writel(1056, rwbuffer);
+
+               writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell_reg);
+               if (arcmsr_hbb_wait_msgint_ready(acb)) {
+                       printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \
+                       timeout \n",acb->host->host_no);
+                       return 1;
+               }
 
-                               case ARCMSR_DEV_INIT_FAIL: {
-                                               acb->devstate[id][lun] =
-                                                       ARECA_RAID_GONE;
-                                               ccb->pcmd->result =
-                                                       DID_BAD_TARGET << 16;
-                               arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
+               writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell_reg);
+               if (arcmsr_hbb_wait_msgint_ready(acb)) {
+                       printk(KERN_NOTICE "arcmsr%d: 'can not set diver mode \n"\
+                       ,acb->host->host_no);
+                       return 1;
+               }
+               arcmsr_enable_outbound_ints(acb, intmask_org);
+               }
+               break;
+       }
+       return 0;
+}
 
-                               case ARCMSR_DEV_CHECK_CONDITION: {
-                                               acb->devstate[id][lun] =
-                                                       ARECA_RAID_GOOD;
-                                               arcmsr_report_sense_info(ccb);
-                                               arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
+static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
+{
+       uint32_t firmware_state = 0;
 
-                               default:
-                                               printk(KERN_NOTICE
-                                                     "arcmsr%d: scsi id = %d \
-                                                       lun = %d""polling and \
-                                                       getting command error \
-                                                       done""but got unknown \
-                                                       DeviceStatus = 0x%x \n",
-                                                       acb->host->host_no, id,
-                                          lun, ccb->arcmsr_cdb.DeviceStatus);
-                                               acb->devstate[id][lun] =
-                                                               ARECA_RAID_GONE;
-                                               ccb->pcmd->result =
-                                                       DID_BAD_TARGET << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                               break;
-                              }
-       }
-                      found = 1;
-              }
+       switch (acb->adapter_type) {
+
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+               do {
+                       firmware_state = readl(&reg->outbound_msgaddr1);
+               } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0);
+               }
+               break;
+
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               do {
+                       firmware_state = readl(reg->iop2drv_doorbell_reg);
+               } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
+               }
+               break;
        }
-       if (found){
-               outbound_intstatus = readl(&reg->outbound_intstatus) & \
-                       acb->outbound_int_enable;
-               writel(outbound_intstatus, &reg->outbound_intstatus);
-               /*clear interrupt*/
+}
+
+static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+       acb->acb_flags |= ACB_F_MSG_START_BGRB;
+       writel(ARCMSR_INBOUND_MESG0_START_BGRB, &reg->inbound_msgaddr0);
+       if (arcmsr_hba_wait_msgint_ready(acb)) {
+               printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \
+                               rebulid' timeout \n", acb->host->host_no);
        }
-       return;
 }
 
+static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
+{
+       struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+       acb->acb_flags |= ACB_F_MSG_START_BGRB;
+       writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg);
+       if (arcmsr_hbb_wait_msgint_ready(acb)) {
+               printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \
+                               rebulid' timeout \n",acb->host->host_no);
+       }
+}
 
-static void arcmsr_iop_init(struct AdapterControlBlock *acb)
+static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
 {
-       struct MessageUnit __iomem *reg = acb->pmu;
-       uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0;
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A:
+               arcmsr_start_hba_bgrb(acb);
+               break;
+       case ACB_ADAPTER_TYPE_B:
+               arcmsr_start_hbb_bgrb(acb);
+               break;
+       }
+}
 
-       do {
-               firmware_state = readl(&reg->outbound_msgaddr1);
-       } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK));
-       intmask_org = readl(&reg->outbound_intmask)
-                       | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
-       arcmsr_get_firmware_spec(acb);
+static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
+{
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A: {
+               struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu;
+               uint32_t outbound_doorbell;
+               /* empty doorbell Qbuffer if door bell ringed */
+               outbound_doorbell = readl(&reg->outbound_doorbell);
+               /*clear doorbell interrupt */
+               writel(outbound_doorbell, &reg->outbound_doorbell);
+               writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
+               }
+               break;
 
-       acb->acb_flags |= ACB_F_MSG_START_BGRB;
-       writel(ARCMSR_INBOUND_MESG0_START_BGRB, &reg->inbound_msgaddr0);
-       if (arcmsr_wait_msgint_ready(acb)) {
-               printk(KERN_NOTICE "arcmsr%d: "
-                       "wait 'start adapter background rebulid' timeout\n",
-                       acb->host->host_no);
+       case ACB_ADAPTER_TYPE_B: {
+               struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+               /*clear interrupt and message state*/
+               writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg);
+               writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg);
+               /* let IOP know data has been read */
+               }
+               break;
        }
+}
 
-       outbound_doorbell = readl(&reg->outbound_doorbell);
-       writel(outbound_doorbell, &reg->outbound_doorbell);
-       writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
-       mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE
-                       | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
-       writel(intmask_org & mask, &reg->outbound_intmask);
-       acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
+static void arcmsr_iop_init(struct AdapterControlBlock *acb)
+{
+       uint32_t intmask_org;
+
+       arcmsr_wait_firmware_ready(acb);
+       arcmsr_iop_confirm(acb);
+       /* disable all outbound interrupt */
+       intmask_org = arcmsr_disable_outbound_ints(acb);
+       arcmsr_get_firmware_spec(acb);
+       /*start background rebuild*/
+       arcmsr_start_adapter_bgrb(acb);
+       /* empty doorbell Qbuffer if door bell ringed */
+       arcmsr_clear_doorbell_queue_buffer(acb);
+       /* enable outbound Post Queue,outbound doorbell Interrupt */
+       arcmsr_enable_outbound_ints(acb, intmask_org);
        acb->acb_flags |= ACB_F_IOP_INITED;
 }
 
@@ -1421,22 +2096,24 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
        if (atomic_read(&acb->ccboutstandingcount) != 0) {
                /* talk to iop 331 outstanding command aborted */
                arcmsr_abort_allcmd(acb);
+
                /* wait for 3 sec for all command aborted*/
-               msleep_interruptible(3000);
+               ssleep(3);
+
                /* disable all outbound interrupt */
                intmask_org = arcmsr_disable_outbound_ints(acb);
                /* clear all outbound posted Q */
-               arcmsr_done4_abort_postqueue(acb);
+               arcmsr_done4abort_postqueue(acb);
                for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
                        ccb = acb->pccb_pool[i];
                        if (ccb->startdone == ARCMSR_CCB_START) {
                                ccb->startdone = ARCMSR_CCB_ABORTED;
+                               arcmsr_ccb_complete(ccb, 1);
                        }
                }
                /* enable all outbound interrupt */
                arcmsr_enable_outbound_ints(acb, intmask_org);
        }
-
 }
 
 static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
@@ -1450,7 +2127,7 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
        for (i = 0; i < 400; i++) {
                if (!atomic_read(&acb->ccboutstandingcount))
                        break;
-               arcmsr_interrupt(acb);
+               arcmsr_interrupt(acb);/* FIXME: need spinlock */
                msleep(25);
        }
        arcmsr_iop_reset(acb);
@@ -1468,7 +2145,7 @@ static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb,
        /*
        ** Wait for 3 sec for all command done.
        */
-       msleep_interruptible(3000);
+       ssleep(3);
 
        intmask = arcmsr_disable_outbound_ints(acb);
        arcmsr_polling_ccbdone(acb, ccb);
@@ -1515,6 +2192,8 @@ static const char *arcmsr_info(struct Scsi_Host *host)
 
        switch (acb->pdev->device) {
        case PCI_DEVICE_ID_ARECA_1110:
+       case PCI_DEVICE_ID_ARECA_1200:
+       case PCI_DEVICE_ID_ARECA_1202:
        case PCI_DEVICE_ID_ARECA_1210:
                raid6 = 0;
                /*FALLTHRU*/
@@ -1522,6 +2201,7 @@ static const char *arcmsr_info(struct Scsi_Host *host)
        case PCI_DEVICE_ID_ARECA_1130:
        case PCI_DEVICE_ID_ARECA_1160:
        case PCI_DEVICE_ID_ARECA_1170:
+       case PCI_DEVICE_ID_ARECA_1201:
        case PCI_DEVICE_ID_ARECA_1220:
        case PCI_DEVICE_ID_ARECA_1230:
        case PCI_DEVICE_ID_ARECA_1260:
@@ -1544,287 +2224,82 @@ static const char *arcmsr_info(struct Scsi_Host *host)
                        ARCMSR_DRIVER_VERSION);
        return buf;
 }
-
+#ifdef CONFIG_SCSI_ARCMSR_AER
 static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
 {
-       struct Scsi_Host *host;
-       struct AdapterControlBlock *acb;
-       uint8_t bus, dev_fun;
-       int error;
-
-       error = pci_enable_device(pdev);
-       if (error)
-               return PCI_ERS_RESULT_DISCONNECT;
-       pci_set_master(pdev);
-
-       host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \
-(struct AdapterControlBlock));
-       if (!host)
-               return PCI_ERS_RESULT_DISCONNECT;
-       acb = (struct AdapterControlBlock *)host->hostdata;
-       memset(acb, 0, sizeof (struct AdapterControlBlock));
-
-       error = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
-       if (error) {
-               error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-               if (error) {
-                       printk(KERN_WARNING
-                              "scsi%d: No suitable DMA mask available\n",
-                              host->host_no);
-                       return PCI_ERS_RESULT_DISCONNECT;
-               }
-       }
-       bus = pdev->bus->number;
-       dev_fun = pdev->devfn;
-       acb = (struct AdapterControlBlock *) host->hostdata;
-       memset(acb, 0, sizeof(struct AdapterControlBlock));
-       acb->pdev = pdev;
-       acb->host = host;
-       host->max_sectors = ARCMSR_MAX_XFER_SECTORS;
-       host->max_lun = ARCMSR_MAX_TARGETLUN;
-       host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/
-       host->max_cmd_len = 16;    /*this is issue of 64bit LBA, over 2T byte*/
-       host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES;
-       host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */
-       host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN;
-       host->this_id = ARCMSR_SCSI_INITIATOR_ID;
-       host->unique_id = (bus << 8) | dev_fun;
-       host->irq = pdev->irq;
-       error = pci_request_regions(pdev, "arcmsr");
-       if (error)
-               return PCI_ERS_RESULT_DISCONNECT;
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       struct AdapterControlBlock *acb =
+               (struct AdapterControlBlock *) host->hostdata;
+       uint32_t intmask_org;
+       int i, j;
 
-       acb->pmu = ioremap(pci_resource_start(pdev, 0),
-                          pci_resource_len(pdev, 0));
-       if (!acb->pmu) {
-               printk(KERN_NOTICE "arcmsr%d: memory"
-                       " mapping region fail \n", acb->host->host_no);
+       if (pci_enable_device(pdev)) {
                return PCI_ERS_RESULT_DISCONNECT;
        }
+       pci_set_master(pdev);
+       intmask_org = arcmsr_disable_outbound_ints(acb);
        acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
                           ACB_F_MESSAGE_RQBUFFER_CLEARED |
                           ACB_F_MESSAGE_WQBUFFER_READED);
        acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
-       INIT_LIST_HEAD(&acb->ccb_free_list);
-
-       error = arcmsr_alloc_ccb_pool(acb);
-       if (error)
-               return PCI_ERS_RESULT_DISCONNECT;
-
-       error = request_irq(pdev->irq, arcmsr_do_interrupt,
-                       IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
-       if (error)
-               return PCI_ERS_RESULT_DISCONNECT;
-
-       arcmsr_iop_init(acb);
-       if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
-             host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B;
-
-       pci_set_drvdata(pdev, host);
-
-       error = scsi_add_host(host, &pdev->dev);
-       if (error)
-               return PCI_ERS_RESULT_DISCONNECT;
+       for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
+               for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
+                       acb->devstate[i][j] = ARECA_RAID_GONE;
 
-       error = arcmsr_alloc_sysfs_attr(acb);
-       if (error)
-               return PCI_ERS_RESULT_DISCONNECT;
+       arcmsr_wait_firmware_ready(acb);
+       arcmsr_iop_confirm(acb);
+       /* disable all outbound interrupt */
+       arcmsr_get_firmware_spec(acb);
+       /*start background rebuild*/
+       arcmsr_start_adapter_bgrb(acb);
+       /* empty doorbell Qbuffer if door bell ringed */
+       arcmsr_clear_doorbell_queue_buffer(acb);
+       /* enable outbound Post Queue,outbound doorbell Interrupt */
+       arcmsr_enable_outbound_ints(acb, intmask_org);
+       acb->acb_flags |= ACB_F_IOP_INITED;
 
-       scsi_scan_host(host);
+       pci_enable_pcie_error_reporting(pdev);
        return PCI_ERS_RESULT_RECOVERED;
 }
 
 static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pdev);
-       struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-       struct MessageUnit __iomem *reg = acb->pmu;
+       struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata;
        struct CommandControlBlock *ccb;
-       /*clear and abort all outbound posted Q*/
-       int i = 0, found = 0;
-       int id, lun;
-       uint32_t flag_ccb, outbound_intstatus;
-
-       while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
-                                                               (i++ < 256)){
-                       ccb = (struct CommandControlBlock *)(acb->vir2phy_offset
-                                                        + (flag_ccb << 5));
-                       if (ccb){
-                               if ((ccb->acb != acb)||(ccb->startdone !=
-                                                       ARCMSR_CCB_START)){
-                                       printk(KERN_NOTICE "arcmsr%d: polling \
-                                       get an illegal ccb"" command done ccb = '0x%p'"
-                                       "ccboutstandingcount = %d \n",
-                                       acb->host->host_no, ccb,
-                                       atomic_read(&acb->ccboutstandingcount));
-                                       continue;
-                               }
-
-                               id = ccb->pcmd->device->id;
-                               lun = ccb->pcmd->device->lun;
-                               if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
-                                       if (acb->devstate[id][lun] ==
-                                                               ARECA_RAID_GONE)
-                                               acb->devstate[id][lun] =
-                                                               ARECA_RAID_GOOD;
-                                       ccb->pcmd->result = DID_OK << 16;
-                                       arcmsr_ccb_complete(ccb, 1);
-                               }
-                               else {
-                                       switch(ccb->arcmsr_cdb.DeviceStatus) {
-                                       case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                                       acb->devstate[id][lun] =
-                                                       ARECA_RAID_GONE;
-                                                       ccb->pcmd->result =
-                                                       DID_NO_CONNECT << 16;
-                                                       arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
-
-                                       case ARCMSR_DEV_ABORTED:
-
-                                       case ARCMSR_DEV_INIT_FAIL: {
-                                                       acb->devstate[id][lun] =
-                                                        ARECA_RAID_GONE;
-                                                       ccb->pcmd->result =
-                                                       DID_BAD_TARGET << 16;
-                                                       arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
-
-                                       case ARCMSR_DEV_CHECK_CONDITION: {
-                                                       acb->devstate[id][lun] =
-                                                        ARECA_RAID_GOOD;
-                                                       arcmsr_report_sense_info(ccb);
-                                                       arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
+       uint32_t intmask_org;
+       int i = 0;
 
-                                       default:
-                                                       printk(KERN_NOTICE
-                                                               "arcmsr%d: scsi \
-                                                               id = %d lun = %d"
-                                                               " polling and \
-                                                               getting command \
-                                                               error done"
-                                                               "but got unknown \
-                                                       DeviceStatus = 0x%x \n"
-                                                       , acb->host->host_no,
-                                                               id, lun,
-                                               ccb->arcmsr_cdb.DeviceStatus);
-                                                       acb->devstate[id][lun] =
-                                                               ARECA_RAID_GONE;
-                                                       ccb->pcmd->result =
-                                                       DID_BAD_TARGET << 16;
-                                                       arcmsr_ccb_complete(ccb, 1);
-                                       break;
-                                       }
-                               }
-                               found = 1;
+       if (atomic_read(&acb->ccboutstandingcount) != 0) {
+               /* talk to iop 331 outstanding command aborted */
+               arcmsr_abort_allcmd(acb);
+               /* wait for 3 sec for all command aborted*/
+               ssleep(3);
+               /* disable all outbound interrupt */
+               intmask_org = arcmsr_disable_outbound_ints(acb);
+               /* clear all outbound posted Q */
+               arcmsr_done4abort_postqueue(acb);
+               for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
+                       ccb = acb->pccb_pool[i];
+                       if (ccb->startdone == ARCMSR_CCB_START) {
+                               ccb->startdone = ARCMSR_CCB_ABORTED;
+                               arcmsr_ccb_complete(ccb, 1);
                        }
                }
-       if (found){
-               outbound_intstatus = readl(&reg->outbound_intstatus) &
-                                                       acb->outbound_int_enable;
-               writel(outbound_intstatus, &reg->outbound_intstatus);
-               /*clear interrupt*/
-                   }
-       return;
+               /* enable all outbound interrupt */
+               arcmsr_enable_outbound_ints(acb, intmask_org);
+       }
+       pci_disable_device(pdev);
 }
 
-
 static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev)
 {
-       struct Scsi_Host *host = pci_get_drvdata(pdev);
-       struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-       struct MessageUnit __iomem *reg = acb->pmu;
-       struct CommandControlBlock *ccb;
-       /*clear and abort all outbound posted Q*/
-       int i = 0, found = 0;
-       int id, lun;
-       uint32_t flag_ccb, outbound_intstatus;
-
-       while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
-                                                               (i++ < 256)){
-                       ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
-                                                       (flag_ccb << 5));
-                       if (ccb){
-                               if ((ccb->acb != acb)||(ccb->startdone !=
-                                                       ARCMSR_CCB_START)){
-                                       printk(KERN_NOTICE
-                                               "arcmsr%d: polling get an illegal ccb"
-                                               " command done ccb = '0x%p'"
-                                               "ccboutstandingcount = %d \n",
-                                               acb->host->host_no, ccb,
-                                               atomic_read(&acb->ccboutstandingcount));
-                                       continue;
-                       }
-
-                       id = ccb->pcmd->device->id;
-                       lun = ccb->pcmd->device->lun;
-                       if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR))   {
-                               if (acb->devstate[id][lun] == ARECA_RAID_GONE)
-                                       acb->devstate[id][lun] = ARECA_RAID_GOOD;
-                               ccb->pcmd->result = DID_OK << 16;
-                               arcmsr_ccb_complete(ccb, 1);
-                       }
-                       else {
-                               switch(ccb->arcmsr_cdb.DeviceStatus) {
-                               case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                               acb->devstate[id][lun] =
-                                                               ARECA_RAID_GONE;
-                                               ccb->pcmd->result =
-                                                       DID_NO_CONNECT << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
-
-                               case ARCMSR_DEV_ABORTED:
-
-                               case ARCMSR_DEV_INIT_FAIL: {
-                                               acb->devstate[id][lun] =
-                                                               ARECA_RAID_GONE;
-                                               ccb->pcmd->result =
-                                                       DID_BAD_TARGET << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
-
-                               case ARCMSR_DEV_CHECK_CONDITION: {
-                                               acb->devstate[id][lun] =
-                                                               ARECA_RAID_GOOD;
-                                               arcmsr_report_sense_info(ccb);
-                                               arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
+                       struct Scsi_Host *host = pci_get_drvdata(pdev);
+                       struct AdapterControlBlock *acb = \
+                               (struct AdapterControlBlock *)host->hostdata;
 
-                               default:
-                                               printk(KERN_NOTICE "arcmsr%d: \
-                                                       scsi id = %d lun = %d"
-                                                               " polling and \
-                                               getting command error done"
-                                                               "but got unknown \
-                                                DeviceStatus = 0x%x \n"
-                                                               , acb->host->host_no,
-                                       id, lun, ccb->arcmsr_cdb.DeviceStatus);
-                                                       acb->devstate[id][lun] =
-                                                               ARECA_RAID_GONE;
-                                                       ccb->pcmd->result =
-                                                       DID_BAD_TARGET << 16;
-                                                       arcmsr_ccb_complete(ccb, 1);
-                               break;
-                               }
-                       }
-                       found = 1;
-               }
-       }
-       if (found){
-               outbound_intstatus = readl(&reg->outbound_intstatus) &
-                                               acb->outbound_int_enable;
-               writel(outbound_intstatus, &reg->outbound_intstatus);
-               /*clear interrupt*/
-       }
-       return;
+                       arcmsr_stop_adapter_bgrb(acb);
+                       arcmsr_flush_adapter_cache(acb);
 }
 
 static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
@@ -1840,5 +2315,6 @@ static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
                        break;
        default:
                        return PCI_ERS_RESULT_NEED_RESET;
-       }
+         }
 }
+#endif
index 03dbe60c264aa5c4490654a9c528f59766b5faab..52d0b87e9aa48f06cabb7c86ea6fff4b9b23ede0 100644 (file)
@@ -2041,7 +2041,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                sink = 1;
                                do_abort(instance);
                                cmd->result = DID_ERROR << 16;
-                               cmd->done(cmd);
+                               cmd->scsi_done(cmd);
                                return;
 #endif
                        case PHASE_DATAIN:
@@ -2100,7 +2100,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                                sink = 1;
                                                do_abort(instance);
                                                cmd->result = DID_ERROR << 16;
-                                               cmd->done(cmd);
+                                               cmd->scsi_done(cmd);
                                                /* XXX - need to source or sink data here, as appropriate */
                                        } else {
 #ifdef REAL_DMA
@@ -2235,24 +2235,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                                cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
 #ifdef AUTOSENSE
+                                       if ((cmd->cmnd[0] == REQUEST_SENSE) &&
+                                               hostdata->ses.cmd_len) {
+                                               scsi_eh_restore_cmnd(cmd, &hostdata->ses);
+                                               hostdata->ses.cmd_len = 0 ;
+                                       }
+
                                        if ((cmd->cmnd[0] != REQUEST_SENSE) &&
                                            (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+                                               scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
+
                                                ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO);
-                                               cmd->cmnd[0] = REQUEST_SENSE;
-                                               cmd->cmnd[1] &= 0xe0;
-                                               cmd->cmnd[2] = 0;
-                                               cmd->cmnd[3] = 0;
-                                               cmd->cmnd[4] = sizeof(cmd->sense_buffer);
-                                               cmd->cmnd[5] = 0;
-                                               cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-
-                                               cmd->use_sg = 0;
-                                               /* this is initialized from initialize_SCp
-                                               cmd->SCp.buffer = NULL;
-                                               cmd->SCp.buffers_residual = 0;
-                                               */
-                                               cmd->request_buffer = (char *) cmd->sense_buffer;
-                                               cmd->request_bufflen = sizeof(cmd->sense_buffer);
 
                                                local_irq_save(flags);
                                                LIST(cmd,hostdata->issue_queue);
index cac354086737e9b937062dab6e026a52c9289614..d858f3d412744583d320202ac44bbb12bd6cece5 100644 (file)
@@ -36,19 +36,18 @@ static struct platform_device *bvme6000_scsi_device;
 static __devinit int
 bvme6000_probe(struct device *dev)
 {
-       struct Scsi_Host * host = NULL;
+       struct Scsi_Host *host;
        struct NCR_700_Host_Parameters *hostdata;
 
        if (!MACH_IS_BVME6000)
                goto out;
 
-       hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-       if (hostdata == NULL) {
+       hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+       if (!hostdata) {
                printk(KERN_ERR "bvme6000-scsi: "
                                "Failed to allocate host data\n");
                goto out;
        }
-       memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 
        /* Fill in the required pieces of hostdata */
        hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
index 2a458d66b6ffc7245255a060e95955c4fb00cd0f..024553f9c247c669ab4769aef2ee5ef0c58c361e 100644 (file)
@@ -1235,7 +1235,21 @@ scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
 }
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 
+/*
+ * Print normalized SCSI sense header with device information and a prefix.
+ */
 void
+scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc,
+                         struct scsi_sense_hdr *sshdr)
+{
+       scmd_printk(KERN_INFO, scmd, "%s: ", desc);
+       scsi_show_sense_hdr(sshdr);
+       scmd_printk(KERN_INFO, scmd, "%s: ", desc);
+       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
+EXPORT_SYMBOL(scsi_cmd_print_sense_hdr);
+
+static void
 scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
                       struct scsi_sense_hdr *sshdr)
 {
@@ -1258,7 +1272,7 @@ scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
        }
 }
 
-void
+static void
 scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len,
                         struct scsi_sense_hdr *sshdr)
 {
index 7b8a3457b6962c78734811fa918978aed2c9b07a..1591824cf4b3b7ed6c8c01202426b717032590e9 100644 (file)
@@ -778,7 +778,7 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb,
                struct ScsiReqBlk *srb)
 {
        dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
        list_add(&srb->list, &dcb->srb_waiting_list);
 }
 
@@ -787,7 +787,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb,
                struct ScsiReqBlk *srb)
 {
        dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n",
-                srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+                srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
        list_add_tail(&srb->list, &dcb->srb_waiting_list);
 }
 
@@ -795,7 +795,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb,
 static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
 {
        dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
        list_add_tail(&srb->list, &dcb->srb_going_list);
 }
 
@@ -805,7 +805,7 @@ static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
        struct ScsiReqBlk *i;
        struct ScsiReqBlk *tmp;
        dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
 
        list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list)
                if (i == srb) {
@@ -821,7 +821,7 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb,
        struct ScsiReqBlk *i;
        struct ScsiReqBlk *tmp;
        dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
 
        list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list)
                if (i == srb) {
@@ -836,7 +836,7 @@ static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb,
 {
        dprintkdbg(DBG_0,
                "srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
        list_move(&srb->list, &dcb->srb_waiting_list);
 }
 
@@ -846,7 +846,7 @@ static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb,
 {
        dprintkdbg(DBG_0,
                "srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
        list_move(&srb->list, &dcb->srb_going_list);
 }
 
@@ -982,7 +982,7 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
        int nseg;
        enum dma_data_direction dir = cmd->sc_data_direction;
        dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n",
-               cmd->pid, dcb->target_id, dcb->target_lun);
+               cmd->serial_number, dcb->target_id, dcb->target_lun);
 
        srb->dcb = dcb;
        srb->cmd = cmd;
@@ -1086,7 +1086,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
        struct AdapterCtlBlk *acb =
            (struct AdapterCtlBlk *)cmd->device->host->hostdata;
        dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n",
-               cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+               cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 
        /* Assume BAD_TARGET; will be cleared later */
        cmd->result = DID_BAD_TARGET << 16;
@@ -1139,7 +1139,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_
                /* process immediately */
                send_srb(acb, srb);
        }
-       dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->pid);
+       dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number);
        return 0;
 
 complete:
@@ -1203,7 +1203,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb,
                else
                        dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) "
                                 "cmnd=0x%02x <%02i-%i>\n",
-                               srb, srb->cmd, srb->cmd->pid,
+                               srb, srb->cmd, srb->cmd->serial_number,
                                srb->cmd->cmnd[0], srb->cmd->device->id,
                                srb->cmd->device->lun);
                printk("  sglist=%p cnt=%i idx=%i len=%zu\n",
@@ -1300,7 +1300,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
                (struct AdapterCtlBlk *)cmd->device->host->hostdata;
        dprintkl(KERN_INFO,
                "eh_bus_reset: (pid#%li) target=<%02i-%i> cmd=%p\n",
-               cmd->pid, cmd->device->id, cmd->device->lun, cmd);
+               cmd->serial_number, cmd->device->id, cmd->device->lun, cmd);
 
        if (timer_pending(&acb->waiting_timer))
                del_timer(&acb->waiting_timer);
@@ -1367,7 +1367,7 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd)
        struct DeviceCtlBlk *dcb;
        struct ScsiReqBlk *srb;
        dprintkl(KERN_INFO, "eh_abort: (pid#%li) target=<%02i-%i> cmd=%p\n",
-               cmd->pid, cmd->device->id, cmd->device->lun, cmd);
+               cmd->serial_number, cmd->device->id, cmd->device->lun, cmd);
 
        dcb = find_dcb(acb, cmd->device->id, cmd->device->lun);
        if (!dcb) {
@@ -1494,7 +1494,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
        u8 s_stat, scsicommand, i, identify_message;
        u8 *ptr;
        dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> srb=%p\n",
-               srb->cmd->pid, dcb->target_id, dcb->target_lun, srb);
+               srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
 
        srb->tag_number = TAG_NONE;     /* acb->tag_max_num: had error read in eeprom */
 
@@ -1504,7 +1504,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
 #if 1
        if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) {
                dprintkdbg(DBG_KG, "start_scsi: (pid#%li) BUSY %02x %04x\n",
-                       srb->cmd->pid, s_stat, s_stat2);
+                       srb->cmd->serial_number, s_stat, s_stat2);
                /*
                 * Try anyway?
                 *
@@ -1522,14 +1522,14 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
        if (acb->active_dcb) {
                dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a"
                        "command while another command (pid#%li) is active.",
-                       srb->cmd->pid,
+                       srb->cmd->serial_number,
                        acb->active_dcb->active_srb ?
-                           acb->active_dcb->active_srb->cmd->pid : 0);
+                           acb->active_dcb->active_srb->cmd->serial_number : 0);
                return 1;
        }
        if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) {
                dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n",
-                       srb->cmd->pid);
+                       srb->cmd->serial_number);
                return 1;
        }
        /* Allow starting of SCSI commands half a second before we allow the mid-level
@@ -1603,7 +1603,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
                if (tag_number >= dcb->max_command) {
                        dprintkl(KERN_WARNING, "start_scsi: (pid#%li) "
                                "Out of tags target=<%02i-%i>)\n",
-                               srb->cmd->pid, srb->cmd->device->id,
+                               srb->cmd->serial_number, srb->cmd->device->id,
                                srb->cmd->device->lun);
                        srb->state = SRB_READY;
                        DC395x_write16(acb, TRM_S1040_SCSI_CONTROL,
@@ -1622,7 +1622,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
 /*polling:*/
        /* Send CDB ..command block ......... */
        dprintkdbg(DBG_KG, "start_scsi: (pid#%li) <%02i-%i> cmnd=0x%02x tag=%i\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun,
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun,
                srb->cmd->cmnd[0], srb->tag_number);
        if (srb->flag & AUTO_REQSENSE) {
                DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE);
@@ -1647,7 +1647,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
                 * : Let's process it first!
                 */
                dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> Failed - busy\n",
-                       srb->cmd->pid, dcb->target_id, dcb->target_lun);
+                       srb->cmd->serial_number, dcb->target_id, dcb->target_lun);
                srb->state = SRB_READY;
                free_tag(dcb, srb);
                srb->msg_count = 0;
@@ -1842,7 +1842,7 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id)
 static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
-       dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->serial_number);
        if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT))
                *pscsi_status = PH_BUS_FREE;    /*.. initial phase */
 
@@ -1856,18 +1856,18 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 {
        u16 i;
        u8 *ptr;
-       dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->serial_number);
 
        clear_fifo(acb, "msgout_phase1");
        if (!(srb->state & SRB_MSGOUT)) {
                srb->state |= SRB_MSGOUT;
                dprintkl(KERN_DEBUG,
                        "msgout_phase1: (pid#%li) Phase unexpected\n",
-                       srb->cmd->pid); /* So what ? */
+                       srb->cmd->serial_number);       /* So what ? */
        }
        if (!srb->msg_count) {
                dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n",
-                       srb->cmd->pid);
+                       srb->cmd->serial_number);
                DC395x_write8(acb, TRM_S1040_SCSI_FIFO, MSG_NOP);
                DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);      /* it's important for atn stop */
                DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT);
@@ -1887,7 +1887,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
-       dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->serial_number);
        DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
 }
 
@@ -1898,7 +1898,7 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
        struct DeviceCtlBlk *dcb;
        u8 *ptr;
        u16 i;
-       dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->serial_number);
 
        clear_fifo(acb, "command_phase1");
        DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN);
@@ -2042,7 +2042,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
        u16 scsi_status = *pscsi_status;
        u32 d_left_counter = 0;
        dprintkdbg(DBG_0, "data_out_phase0: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
 
        /*
         * KG: We need to drain the buffers before we draw any conclusions!
@@ -2172,7 +2172,7 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
        dprintkdbg(DBG_0, "data_out_phase1: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
        clear_fifo(acb, "data_out_phase1");
        /* do prepare before transfer when data out phase */
        data_io_transfer(acb, srb, XFERDATAOUT);
@@ -2184,7 +2184,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
        u16 scsi_status = *pscsi_status;
 
        dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
 
        /*
         * KG: DataIn is much more tricky than DataOut. When the device is finished
@@ -2205,7 +2205,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 
                if (scsi_status & PARITYERROR) {
                        dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) "
-                               "Parity Error\n", srb->cmd->pid);
+                               "Parity Error\n", srb->cmd->serial_number);
                        srb->status |= PARITY_ERROR;
                }
                /*
@@ -2395,7 +2395,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
        dprintkdbg(DBG_0, "data_in_phase1: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
        data_io_transfer(acb, srb, XFERDATAIN);
 }
 
@@ -2407,7 +2407,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
        u8 bval;
        dprintkdbg(DBG_0,
                "data_io_transfer: (pid#%li) <%02i-%i> %c len=%i, sg=(%i/%i)\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun,
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun,
                ((io_dir & DMACMD_DIR) ? 'r' : 'w'),
                srb->total_xfer_length, srb->sg_index, srb->sg_count);
        if (srb == acb->tmp_srb)
@@ -2580,7 +2580,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
        dprintkdbg(DBG_0, "status_phase0: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
        srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
        srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);      /* get message */
        srb->state = SRB_COMPLETED;
@@ -2594,7 +2594,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
        dprintkdbg(DBG_0, "status_phase1: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
+               srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
        srb->state = SRB_STATUS;
        DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);      /* it's important for atn stop */
        DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP);
@@ -2636,7 +2636,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
        struct ScsiReqBlk *srb = NULL;
        struct ScsiReqBlk *i;
        dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) tag=%i srb=%p\n",
-                  srb->cmd->pid, tag, srb);
+                  srb->cmd->serial_number, tag, srb);
 
        if (!(dcb->tag_mask & (1 << tag)))
                dprintkl(KERN_DEBUG,
@@ -2655,7 +2655,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
                goto mingx0;
 
        dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) <%02i-%i>\n",
-               srb->cmd->pid, srb->dcb->target_id, srb->dcb->target_lun);
+               srb->cmd->serial_number, srb->dcb->target_id, srb->dcb->target_lun);
        if (dcb->flag & ABORT_DEV_) {
                /*srb->state = SRB_ABORT_SENT; */
                enable_msgout_abort(acb, srb);
@@ -2865,7 +2865,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
        struct DeviceCtlBlk *dcb = acb->active_dcb;
-       dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->serial_number);
 
        srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
        if (msgin_completed(srb->msgin_buf, acb->msg_len)) {
@@ -2933,7 +2933,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                         */
                        dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
                                "SAVE POINTER rem=%i Ignore\n",
-                               srb->cmd->pid, srb->total_xfer_length);
+                               srb->cmd->serial_number, srb->total_xfer_length);
                        break;
 
                case RESTORE_POINTERS:
@@ -2943,7 +2943,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                case ABORT:
                        dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
                                "<%02i-%i> ABORT msg\n",
-                               srb->cmd->pid, dcb->target_id,
+                               srb->cmd->serial_number, dcb->target_id,
                                dcb->target_lun);
                        dcb->flag |= ABORT_DEV_;
                        enable_msgout_abort(acb, srb);
@@ -2975,7 +2975,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
                u16 *pscsi_status)
 {
-       dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->serial_number);
        clear_fifo(acb, "msgin_phase1");
        DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1);
        if (!(srb->state & SRB_MSGIN)) {
@@ -3041,7 +3041,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
        }
        srb = dcb->active_srb;
        acb->active_dcb = NULL;
-       dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->pid);
+       dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->serial_number);
 
        srb->scsi_phase = PH_BUS_FREE;  /* initial phase */
        clear_fifo(acb, "disconnect");
@@ -3072,13 +3072,13 @@ static void disconnect(struct AdapterCtlBlk *acb)
                                srb->state = SRB_READY;
                                dprintkl(KERN_DEBUG,
                                        "disconnect: (pid#%li) Unexpected\n",
-                                       srb->cmd->pid);
+                                       srb->cmd->serial_number);
                                srb->target_status = SCSI_STAT_SEL_TIMEOUT;
                                goto disc1;
                        } else {
                                /* Normal selection timeout */
                                dprintkdbg(DBG_KG, "disconnect: (pid#%li) "
-                                       "<%02i-%i> SelTO\n", srb->cmd->pid,
+                                       "<%02i-%i> SelTO\n", srb->cmd->serial_number,
                                        dcb->target_id, dcb->target_lun);
                                if (srb->retry_count++ > DC395x_MAX_RETRIES
                                    || acb->scan_devices) {
@@ -3090,7 +3090,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
                                srb_going_to_waiting_move(dcb, srb);
                                dprintkdbg(DBG_KG,
                                        "disconnect: (pid#%li) Retry\n",
-                                       srb->cmd->pid);
+                                       srb->cmd->serial_number);
                                waiting_set_timer(acb, HZ / 20);
                        }
                } else if (srb->state & SRB_DISCONNECT) {
@@ -3144,7 +3144,7 @@ static void reselect(struct AdapterCtlBlk *acb)
                if (!acb->scan_devices) {
                        dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> "
                                "Arb lost but Resel win rsel=%i stat=0x%04x\n",
-                               srb->cmd->pid, dcb->target_id,
+                               srb->cmd->serial_number, dcb->target_id,
                                dcb->target_lun, rsel_tar_lun_id,
                                DC395x_read16(acb, TRM_S1040_SCSI_STATUS));
                        arblostflag = 1;
@@ -3318,7 +3318,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
        enum dma_data_direction dir = cmd->sc_data_direction;
        int ckc_only = 1;
 
-       dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid,
+       dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->serial_number,
                srb->cmd->device->id, srb->cmd->device->lun);
        dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
                   srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count,
@@ -3499,7 +3499,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
                if (srb->total_xfer_length)
                        dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> "
                                "cmnd=0x%02x Missed %i bytes\n",
-                               cmd->pid, cmd->device->id, cmd->device->lun,
+                               cmd->serial_number, cmd->device->id, cmd->device->lun,
                                cmd->cmnd[0], srb->total_xfer_length);
        }
 
@@ -3509,7 +3509,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
                dprintkl(KERN_ERR, "srb_done: ERROR! Completed cmd with tmp_srb\n");
        else {
                dprintkdbg(DBG_0, "srb_done: (pid#%li) done result=0x%08x\n",
-                       cmd->pid, cmd->result);
+                       cmd->serial_number, cmd->result);
                srb_free_insert(acb, srb);
        }
        pci_unmap_srb(acb, srb);
@@ -3538,7 +3538,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
                        p = srb->cmd;
                        dir = p->sc_data_direction;
                        result = MK_RES(0, did_flag, 0, 0);
-                       printk("G:%li(%02i-%i) ", p->pid,
+                       printk("G:%li(%02i-%i) ", p->serial_number,
                               p->device->id, p->device->lun);
                        srb_going_remove(dcb, srb);
                        free_tag(dcb, srb);
@@ -3568,7 +3568,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
                        p = srb->cmd;
 
                        result = MK_RES(0, did_flag, 0, 0);
-                       printk("W:%li<%02i-%i>", p->pid, p->device->id,
+                       printk("W:%li<%02i-%i>", p->serial_number, p->device->id,
                               p->device->lun);
                        srb_waiting_remove(dcb, srb);
                        srb_free_insert(acb, srb);
@@ -3678,7 +3678,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 {
        struct scsi_cmnd *cmd = srb->cmd;
        dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n",
-               cmd->pid, cmd->device->id, cmd->device->lun);
+               cmd->serial_number, cmd->device->id, cmd->device->lun);
 
        srb->flag |= AUTO_REQSENSE;
        srb->adapter_status = 0;
@@ -3709,7 +3709,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
        if (start_scsi(acb, dcb, srb)) {        /* Should only happen, if sb. else grabs the bus */
                dprintkl(KERN_DEBUG,
                        "request_sense: (pid#%li) failed <%02i-%i>\n",
-                       srb->cmd->pid, dcb->target_id, dcb->target_lun);
+                       srb->cmd->serial_number, dcb->target_id, dcb->target_lun);
                srb_going_to_waiting_move(dcb, srb);
                waiting_set_timer(acb, HZ / 100);
        }
@@ -4717,13 +4717,13 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
                                dcb->target_id, dcb->target_lun,
                                list_size(&dcb->srb_waiting_list));
                 list_for_each_entry(srb, &dcb->srb_waiting_list, list)
-                       SPRINTF(" %li", srb->cmd->pid);
+                       SPRINTF(" %li", srb->cmd->serial_number);
                if (!list_empty(&dcb->srb_going_list))
                        SPRINTF("\nDCB (%02i-%i): Going  : %i:",
                                dcb->target_id, dcb->target_lun,
                                list_size(&dcb->srb_going_list));
                list_for_each_entry(srb, &dcb->srb_going_list, list)
-                       SPRINTF(" %li", srb->cmd->pid);
+                       SPRINTF(" %li", srb->cmd->serial_number);
                if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list))
                        SPRINTF("\n");
        }
index 502732ac270ddcfa7cbecec1e282f9ff0c944c42..bea9d659af1549e0dd2e5a8cd1f996eb78d65c25 100644 (file)
@@ -949,16 +949,14 @@ static int adpt_install_hba(struct pci_dev* pDev)
        }
        
        // Allocate and zero the data structure
-       pHba = kmalloc(sizeof(adpt_hba), GFP_KERNEL);
-       if( pHba == NULL) {
-               if(msg_addr_virt != base_addr_virt){
+       pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL);
+       if (!pHba) {
+               if (msg_addr_virt != base_addr_virt)
                        iounmap(msg_addr_virt);
-               }
                iounmap(base_addr_virt);
                pci_release_regions(pDev);
                return -ENOMEM;
        }
-       memset(pHba, 0, sizeof(adpt_hba));
 
        mutex_lock(&adpt_configuration_lock);
 
@@ -2622,14 +2620,13 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
 
        msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
 
-       status = kmalloc(4,GFP_KERNEL|ADDR32);
-       if (status==NULL) {
+       status = kzalloc(4, GFP_KERNEL|ADDR32);
+       if (!status) {
                adpt_send_nop(pHba, m);
                printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
                        pHba->name);
                return -ENOMEM;
        }
-       memset(status, 0, 4);
 
        writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
        writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
@@ -2668,12 +2665,11 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
 
        kfree(pHba->reply_pool);
 
-       pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
-       if(!pHba->reply_pool){
-               printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name);
-               return -1;
+       pHba->reply_pool = kzalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
+       if (!pHba->reply_pool) {
+               printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
+               return -ENOMEM;
        }
-       memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
 
        ptr = pHba->reply_pool;
        for(i = 0; i < pHba->reply_fifo_size; i++) {
@@ -2884,12 +2880,11 @@ static int adpt_i2o_build_sys_table(void)
 
        kfree(sys_tbl);
 
-       sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL|ADDR32);
-       if(!sys_tbl) {
+       sys_tbl = kzalloc(sys_tbl_len, GFP_KERNEL|ADDR32);
+       if (!sys_tbl) {
                printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");     
                return -ENOMEM;
        }
-       memset(sys_tbl, 0, sys_tbl_len);
 
        sys_tbl->num_entries = hba_count;
        sys_tbl->version = I2OVERSION;
@@ -3351,7 +3346,7 @@ static int __init adpt_init(void)
        return count > 0 ? 0 : -ENODEV;
 }
 
-static void __exit adpt_exit(void)
+static void adpt_exit(void)
 {
        while (hba_chain)
                adpt_release(hba_chain);
index 9d52e45c7d36170a47f6e7da98ee179093a28336..2596165096d37f73c0ebbda03fb27d8686beffad 100644 (file)
@@ -137,11 +137,9 @@ static struct override {
 #ifdef OVERRIDE
 [] __initdata = OVERRIDE;
 #else
-[4] __initdata = { {
-0, IRQ_AUTO}, {
-0, IRQ_AUTO}, {
-0, IRQ_AUTO}, {
-0, IRQ_AUTO}};
+[4] __initdata = {
+       { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }
+};
 #endif
 
 #define NO_OVERRIDES ARRAY_SIZE(overrides)
@@ -176,7 +174,7 @@ static const struct signature {
  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  *     equal to the number of ints.
  *
-*/
+ */
 
 static void __init dtc_setup(char *str, int *ints)
 {
@@ -233,7 +231,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
                } else
                        for (; !addr && (current_base < NO_BASES); ++current_base) {
 #if (DTCDEBUG & DTCDEBUG_INIT)
-                               printk("scsi-dtc : probing address %08x\n", bases[current_base].address);
+                               printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address);
 #endif
                                if (bases[current_base].noauto)
                                        continue;
@@ -244,7 +242,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
                                        if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
                                                addr = bases[current_base].address;
 #if (DTCDEBUG & DTCDEBUG_INIT)
-                                               printk("scsi-dtc : detected board.\n");
+                                               printk(KERN_DEBUG "scsi-dtc : detected board.\n");
 #endif
                                                goto found;
                                        }
@@ -253,7 +251,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
                        }
 
 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
-               printk("scsi-dtc : base = %08x\n", addr);
+               printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr);
 #endif
 
                if (!addr)
index a83e9f150b97f4d0d798b5b2b1d6618c8c3dd2b4..ec2233114bc9b6bbaf74d9281e5d4e9b53376653 100644 (file)
@@ -1758,7 +1758,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
        if (SCpnt->host_scribble)
                panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
-                     ha->board_name, SCpnt->pid, SCpnt);
+                     ha->board_name, SCpnt->serial_number, SCpnt);
 
        /* i is the mailbox number, look for the first free mailbox
           starting from last_cp_used */
@@ -1792,7 +1792,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
        if (do_trace)
                scmd_printk(KERN_INFO, SCpnt,
-                       "qcomm, mbox %d, pid %ld.\n", i, SCpnt->pid);
+                       "qcomm, mbox %d, pid %ld.\n", i, SCpnt->serial_number);
 
        cpp->reqsen = 1;
        cpp->dispri = 1;
@@ -1825,7 +1825,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
                unmap_dma(i, ha);
                SCpnt->host_scribble = NULL;
                scmd_printk(KERN_INFO, SCpnt,
-                       "qcomm, pid %ld, adapter busy.\n", SCpnt->pid);
+                       "qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
                return 1;
        }
 
@@ -1841,13 +1841,13 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
 
        if (SCarg->host_scribble == NULL) {
                scmd_printk(KERN_INFO, SCarg,
-                       "abort, pid %ld inactive.\n", SCarg->pid);
+                       "abort, pid %ld inactive.\n", SCarg->serial_number);
                return SUCCESS;
        }
 
        i = *(unsigned int *)SCarg->host_scribble;
        scmd_printk(KERN_WARNING, SCarg,
-               "abort, mbox %d, pid %ld.\n", i, SCarg->pid);
+               "abort, mbox %d, pid %ld.\n", i, SCarg->serial_number);
 
        if (i >= shost->can_queue)
                panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name);
@@ -1892,7 +1892,7 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
                SCarg->host_scribble = NULL;
                ha->cp_stat[i] = FREE;
                printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-                      ha->board_name, i, SCarg->pid);
+                      ha->board_name, i, SCarg->serial_number);
                SCarg->scsi_done(SCarg);
                return SUCCESS;
        }
@@ -1909,12 +1909,12 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
        struct hostdata *ha = (struct hostdata *)shost->hostdata;
 
        scmd_printk(KERN_INFO, SCarg,
-               "reset, enter, pid %ld.\n", SCarg->pid);
+               "reset, enter, pid %ld.\n", SCarg->serial_number);
 
        spin_lock_irq(shost->host_lock);
 
        if (SCarg->host_scribble == NULL)
-               printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->pid);
+               printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->serial_number);
 
        if (ha->in_reset) {
                printk("%s: reset, exit, already in reset.\n", ha->board_name);
@@ -1954,13 +1954,13 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
                if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) {
                        ha->cp_stat[i] = ABORTING;
                        printk("%s: reset, mbox %d aborting, pid %ld.\n",
-                              ha->board_name, i, SCpnt->pid);
+                              ha->board_name, i, SCpnt->serial_number);
                }
 
                else {
                        ha->cp_stat[i] = IN_RESET;
                        printk("%s: reset, mbox %d in reset, pid %ld.\n",
-                              ha->board_name, i, SCpnt->pid);
+                              ha->board_name, i, SCpnt->serial_number);
                }
 
                if (SCpnt->host_scribble == NULL)
@@ -2015,7 +2015,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
 
                        printk
                            ("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-                            ha->board_name, i, SCpnt->pid);
+                            ha->board_name, i, SCpnt->serial_number);
                }
 
                else if (ha->cp_stat[i] == ABORTING) {
@@ -2029,7 +2029,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
 
                        printk
                            ("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-                            ha->board_name, i, SCpnt->pid);
+                            ha->board_name, i, SCpnt->serial_number);
                }
 
                else
@@ -2043,7 +2043,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
        do_trace = 0;
 
        if (arg_done)
-               printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->pid);
+               printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->serial_number);
        else
                printk("%s: reset, exit.\n", ha->board_name);
 
@@ -2182,7 +2182,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec,
                        cpp = &ha->cp[k];
                        SCpnt = cpp->SCpnt;
                        ll[n] = SCpnt->request->nr_sectors;
-                       pl[n] = SCpnt->pid;
+                       pl[n] = SCpnt->serial_number;
 
                        if (!n)
                                continue;
@@ -2230,7 +2230,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec,
                            "%s pid %ld mb %d fc %d nr %d sec %ld ns %ld"
                             " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n",
                             (ihdlr ? "ihdlr" : "qcomm"),
-                            SCpnt->pid, k, flushcount,
+                            SCpnt->serial_number, k, flushcount,
                             n_ready, SCpnt->request->sector,
                             SCpnt->request->nr_sectors, cursec, YESNO(s),
                             YESNO(r), YESNO(rev), YESNO(input_only),
@@ -2277,7 +2277,7 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec,
                            "%s, pid %ld, mbox %d, adapter"
                             " busy, will abort.\n",
                             (ihdlr ? "ihdlr" : "qcomm"),
-                            SCpnt->pid, k);
+                            SCpnt->serial_number, k);
                        ha->cp_stat[k] = ABORTING;
                        continue;
                }
@@ -2391,11 +2391,11 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
 
        if (SCpnt->host_scribble == NULL)
                panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", ha->board_name,
-                     i, SCpnt->pid, SCpnt);
+                     i, SCpnt->serial_number, SCpnt);
 
        if (*(unsigned int *)SCpnt->host_scribble != i)
                panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
-                     ha->board_name, i, SCpnt->pid,
+                     ha->board_name, i, SCpnt->serial_number,
                      *(unsigned int *)SCpnt->host_scribble);
 
        sync_dma(i, ha);
@@ -2445,12 +2445,12 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
                               "target_status 0x%x, sense key 0x%x.\n",
                               ha->board_name,
                               SCpnt->device->channel, SCpnt->device->id,
-                              SCpnt->device->lun, SCpnt->pid,
+                              SCpnt->device->lun, SCpnt->serial_number,
                               spp->target_status, SCpnt->sense_buffer[2]);
 
                ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0;
 
-               if (ha->last_retried_pid == SCpnt->pid)
+               if (ha->last_retried_pid == SCpnt->serial_number)
                        ha->retries = 0;
 
                break;
@@ -2485,7 +2485,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
 #endif
 
                        ha->retries++;
-                       ha->last_retried_pid = SCpnt->pid;
+                       ha->last_retried_pid = SCpnt->serial_number;
                } else
                        status = DID_ERROR << 16;
 
@@ -2516,7 +2516,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
                scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"
                       " pid %ld, reg 0x%x, count %d.\n",
                       i, spp->adapter_status, spp->target_status,
-                      SCpnt->pid, reg, ha->iocount);
+                      SCpnt->serial_number, reg, ha->iocount);
 
        unmap_dma(i, ha);
 
index f33ad01064a9d8b0f8696331bd6d90da1fbbef3a..96180bb47e4189c3fa8304df15fc52d520689915 100644 (file)
@@ -107,59 +107,44 @@ static struct scsi_host_template driver_template;
 static int eata_pio_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
                              int length, int rw)
 {
-    static u8 buff[512];
-    int size, len = 0;
-    off_t begin = 0, pos = 0;
+       int len = 0;
+       off_t begin = 0, pos = 0;
 
-    if (rw)
-       return -ENOSYS;
-    if (offset == 0)
-       memset(buff, 0, sizeof(buff));
+       if (rw)
+               return -ENOSYS;
 
-    size = sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: "
+       len += sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: "
                   "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB);
-    len += size; pos = begin + len;
-    size = sprintf(buffer + len, "queued commands:     %10ld\n"
+       len += sprintf(buffer + len, "queued commands:     %10ld\n"
                   "processed interrupts:%10ld\n", queue_counter, int_counter);
-    len += size; pos = begin + len;
-    
-    size = sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n",
+       len += sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n",
                   shost->host_no, SD(shost)->name);
-    len += size; 
-    pos = begin + len;
-    size = sprintf(buffer + len, "Firmware revision: v%s\n", 
+       len += sprintf(buffer + len, "Firmware revision: v%s\n",
                   SD(shost)->revision);
-    len += size;
-    pos = begin + len;
-    size = sprintf(buffer + len, "IO: PIO\n");
-    len += size; 
-    pos = begin + len;
-    size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base);
-    len += size; 
-    pos = begin + len;
-    size = sprintf(buffer + len, "Host Bus: %s\n", 
+       len += sprintf(buffer + len, "IO: PIO\n");
+       len += sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base);
+       len += sprintf(buffer + len, "Host Bus: %s\n",
                   (SD(shost)->bustype == 'P')?"PCI ":
                   (SD(shost)->bustype == 'E')?"EISA":"ISA ");
     
-    len += size; 
-    pos = begin + len;
+       pos = begin + len;
     
-    if (pos < offset) {
-       len = 0;
-       begin = pos;
-    }
-    if (pos > offset + length)
-       goto stop_output;
+       if (pos < offset) {
+               len = 0;
+               begin = pos;
+       }
+       if (pos > offset + length)
+               goto stop_output;
     
- stop_output:
-    DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
-    *start=buffer+(offset-begin);   /* Start of wanted data */
-    len-=(offset-begin);            /* Start slop */
-    if(len>length)
-       len = length;               /* Ending slop */
-    DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
+stop_output:
+       DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
+       *start = buffer + (offset - begin);   /* Start of wanted data */
+       len -= (offset - begin);            /* Start slop */
+       if (len > length)
+               len = length;               /* Ending slop */
+       DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
     
-    return (len);     
+       return len;
 }
 
 static int eata_pio_release(struct Scsi_Host *sh)
@@ -390,7 +375,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 
        DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
                "eata_pio_queue pid %ld, y %d\n",
-               cmd->pid, y));
+               cmd->serial_number, y));
 
        cmd->scsi_done = (void *) done;
 
@@ -435,10 +420,10 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
                cmd->result = DID_BUS_BUSY << 16;
                scmd_printk(KERN_NOTICE, cmd,
                        "eata_pio_queue pid %ld, HBA busy, "
-                       "returning DID_BUS_BUSY, done.\n", cmd->pid);
+                       "returning DID_BUS_BUSY, done.\n", cmd->serial_number);
                done(cmd);
                cp->status = FREE;
-               return (0);
+               return 0;
        }
        /* FIXME: timeout */
        while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
@@ -450,9 +435,9 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 
        DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
                "Queued base %#.4lx pid: %ld "
-               "slot %d irq %d\n", sh->base, cmd->pid, y, sh->irq));
+               "slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq));
 
-       return (0);
+       return 0;
 }
 
 static int eata_pio_abort(struct scsi_cmnd *cmd)
@@ -461,7 +446,7 @@ static int eata_pio_abort(struct scsi_cmnd *cmd)
 
        DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
                "eata_pio_abort called pid: %ld\n",
-               cmd->pid));
+               cmd->serial_number));
 
        while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
                if (--loop == 0) {
@@ -497,7 +482,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
 
        DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
                "eata_pio_reset called pid:%ld\n",
-               cmd->pid));
+               cmd->serial_number));
 
        spin_lock_irq(host->host_lock);
 
@@ -516,7 +501,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
 
                sp = HD(cmd)->ccb[x].cmd;
                HD(cmd)->ccb[x].status = RESET;
-               printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid);
+               printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->serial_number);
 
                if (sp == NULL)
                        panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
@@ -589,23 +574,28 @@ static char *get_pio_board_data(unsigned long base, unsigned int irq, unsigned i
        cp.cp_cdb[5] = 0;
 
        if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP))
-               return (NULL);
-       while (!(inb(base + HA_RSTATUS) & HA_SDRQ));
+               return NULL;
+
+       while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
+               cpu_relax();
+
        outsw(base + HA_RDATA, &cp, cplen);
        outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
        for (z = 0; z < cppadlen; z++)
                outw(0, base + HA_RDATA);
 
-       while (inb(base + HA_RSTATUS) & HA_SBUSY);
+       while (inb(base + HA_RSTATUS) & HA_SBUSY)
+               cpu_relax();
+
        if (inb(base + HA_RSTATUS) & HA_SERROR)
-               return (NULL);
+               return NULL;
        else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
-               return (NULL);
+               return NULL;
        else {
                insw(base + HA_RDATA, &buff, 127);
                while (inb(base + HA_RSTATUS) & HA_SDRQ)
                        inw(base + HA_RDATA);
-               return (buff);
+               return buff;
        }
 }
 
index 95cf7b6cd6225043f7a13ef33939b118303cba1c..4ed3a529706615f0bd94d51399cb39b5ee8b79b0 100644 (file)
@@ -2138,7 +2138,7 @@ irqreturn_t scsi_esp_intr(int irq, void *dev_id)
 }
 EXPORT_SYMBOL(scsi_esp_intr);
 
-static void __devinit esp_get_revision(struct esp *esp)
+static void esp_get_revision(struct esp *esp)
 {
        u8 val;
 
@@ -2187,7 +2187,7 @@ static void __devinit esp_get_revision(struct esp *esp)
        }
 }
 
-static void __devinit esp_init_swstate(struct esp *esp)
+static void esp_init_swstate(struct esp *esp)
 {
        int i;
 
@@ -2233,7 +2233,7 @@ static void esp_bootup_reset(struct esp *esp)
        esp_read8(ESP_INTRPT);
 }
 
-static void __devinit esp_set_clock_params(struct esp *esp)
+static void esp_set_clock_params(struct esp *esp)
 {
        int fmhz;
        u8 ccf;
@@ -2306,7 +2306,7 @@ static const char *esp_chip_names[] = {
 
 static struct scsi_transport_template *esp_transport_template;
 
-int __devinit scsi_esp_register(struct esp *esp, struct device *dev)
+int scsi_esp_register(struct esp *esp, struct device *dev)
 {
        static int instance;
        int err;
@@ -2346,7 +2346,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev)
 }
 EXPORT_SYMBOL(scsi_esp_register);
 
-void __devexit scsi_esp_unregister(struct esp *esp)
+void scsi_esp_unregister(struct esp *esp)
 {
        scsi_remove_host(esp->host);
 }
index 36169d597e9808b21d4d0203a958b3c171fe98f0..5d282e6a6ae1d14105492faea3934893d213d471 100644 (file)
@@ -387,7 +387,9 @@ static void __iomem *    bios_mem;
 static int               bios_major;
 static int               bios_minor;
 static int               PCI_bus;
+#ifdef CONFIG_PCI
 static struct pci_dev  *PCI_dev;
+#endif
 static int               Quantum;      /* Quantum board variant */
 static int               interrupt_level;
 static volatile int      in_command;
@@ -1764,6 +1766,7 @@ struct scsi_host_template fdomain_driver_template = {
 };
 
 #ifndef PCMCIA
+#ifdef CONFIG_PCI
 
 static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
        { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
@@ -1771,7 +1774,7 @@ static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
        { }
 };
 MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl);
-
+#endif
 #define driver_template fdomain_driver_template
 #include "scsi_module.c"
 
index 880f70d24e6511e9fe92d5db66abe27b8aab4487..607336f56d550b8a6d487d3c1a723877c7641b32 100644 (file)
@@ -556,7 +556,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 }
 #endif
 
-#if NCR53C400_PSEUDO_DMA
+#ifdef NCR53C400_PSEUDO_DMA
 
 /**
  *     NCR5380_pread           -       pseudo DMA read
index 55e4d2dc2bbe227ea62dcb730d7a50516e27f3c1..e8010a702e73c6a0c33d0cadbe624b5c8d89947e 100644 (file)
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Linux kernel 2.4.x, 2.6.x supported                                  *
+ * Linux kernel 2.6.x supported                                                *
  *                                                                      *
- * $Log: gdth.c,v $
- * Revision 1.74  2006/04/10 13:44:47  achim
- * Community changes for 2.6.x
- * Kernel 2.2.x no longer supported
- * scsi_request interface removed, thanks to Christoph Hellwig
- *
- * Revision 1.73  2004/03/31 13:33:03  achim
- * Special command 0xfd implemented to detect 64-bit DMA support
- *
- * Revision 1.72  2004/03/17 08:56:04  achim
- * 64-bit DMA only enabled if FW >= x.43
- *
- * Revision 1.71  2004/03/05 15:51:29  achim
- * Screen service: separate message buffer, bugfixes
- *
- * Revision 1.70  2004/02/27 12:19:07  achim
- * Bugfix: Reset bit in config (0xfe) call removed
- *
- * Revision 1.69  2004/02/20 09:50:24  achim
- * Compatibility changes for kernels < 2.4.20
- * Bugfix screen service command size
- * pci_set_dma_mask() error handling added
- *
- * Revision 1.68  2004/02/19 15:46:54  achim
- * 64-bit DMA bugfixes
- * Drive size bugfix for drives > 1TB
- *
- * Revision 1.67  2004/01/14 13:11:57  achim
- * Tool access over /proc no longer supported
- * Bugfixes IOCTLs
- *
- * Revision 1.66  2003/12/19 15:04:06  achim
- * Bugfixes support for drives > 2TB
- *
- * Revision 1.65  2003/12/15 11:21:56  achim
- * 64-bit DMA support added
- * Support for drives > 2 TB implemented
- * Kernels 2.2.x, 2.4.x, 2.6.x supported
- *
- * Revision 1.64  2003/09/17 08:30:26  achim
- * EISA/ISA controller scan disabled
- * Command line switch probe_eisa_isa added
- *
- * Revision 1.63  2003/07/12 14:01:00  Daniele Bellucci <bellucda@tiscali.it>
- * Minor cleanups in gdth_ioctl.
- *
- * Revision 1.62  2003/02/27 15:01:59  achim
- * Dynamic DMA mapping implemented
- * New (character device) IOCTL interface added
- * Other controller related changes made
- *
- * Revision 1.61  2002/11/08 13:09:52  boji
- * Added support for XSCALE based RAID Controllers
- * Fixed SCREENSERVICE initialization in SMP cases
- * Added checks for gdth_polling before GDTH_HA_LOCK
- *
- * Revision 1.60  2002/02/05 09:35:22  achim
- * MODULE_LICENSE only if kernel >= 2.4.11
- *
- * Revision 1.59  2002/01/30 09:46:33  achim
- * Small changes
- *
- * Revision 1.58  2002/01/29 15:30:02  achim
- * Set default value of shared_access to Y
- * New status S_CACHE_RESERV for clustering added
- *
- * Revision 1.57  2001/08/21 11:16:35  achim
- * Bugfix free_irq()
- *
- * Revision 1.56  2001/08/09 11:19:39  achim
- * Scsi_Host_Template changes
- *
- * Revision 1.55  2001/08/09 10:11:28  achim
- * Command HOST_UNFREEZE_IO before cache service init.
- *
- * Revision 1.54  2001/07/20 13:48:12  achim
- * Expand: gdth_analyse_hdrive() removed
- *
- * Revision 1.53  2001/07/17 09:52:49  achim
- * Small OEM related change
- *
- * Revision 1.52  2001/06/19 15:06:20  achim
- * New host command GDT_UNFREEZE_IO added
- *
- * Revision 1.51  2001/05/22 06:42:37  achim
- * PCI: Subdevice ID added
- *
- * Revision 1.50  2001/05/17 13:42:16  achim
- * Support for Intel Storage RAID Controllers added
- *
- * Revision 1.50  2001/05/17 12:12:34  achim
- * Support for Intel Storage RAID Controllers added
- *
- * Revision 1.49  2001/03/15 15:07:17  achim
- * New __setup interface for boot command line options added
- *
- * Revision 1.48  2001/02/06 12:36:28  achim
- * Bugfix Cluster protocol
- *
- * Revision 1.47  2001/01/10 14:42:06  achim
- * New switch shared_access added
- *
- * Revision 1.46  2001/01/09 08:11:35  achim
- * gdth_command() removed
- * meaning of Scsi_Pointer members changed
- *
- * Revision 1.45  2000/11/16 12:02:24  achim
- * Changes for kernel 2.4
- *
- * Revision 1.44  2000/10/11 08:44:10  achim
- * Clustering changes: New flag media_changed added
- *
- * Revision 1.43  2000/09/20 12:59:01  achim
- * DPMEM remap functions for all PCI controller types implemented
- * Small changes for ia64 platform
- *
- * Revision 1.42  2000/07/20 09:04:50  achim
- * Small changes for kernel 2.4
- *
- * Revision 1.41  2000/07/04 14:11:11  achim
- * gdth_analyse_hdrive() added to rescan drives after online expansion
- *
- * Revision 1.40  2000/06/27 11:24:16  achim
- * Changes Clustering, Screenservice
- *
- * Revision 1.39  2000/06/15 13:09:04  achim
- * Changes for gdth_do_cmd()
- *
- * Revision 1.38  2000/06/15 12:08:43  achim
- * Bugfix gdth_sync_event(), service SCREENSERVICE
- * Data direction for command 0xc2 changed to DOU
- *
- * Revision 1.37  2000/05/25 13:50:10  achim
- * New driver parameter virt_ctr added
- *
- * Revision 1.36  2000/05/04 08:50:46  achim
- * Event buffer now in gdth_ha_str
- *
- * Revision 1.35  2000/03/03 10:44:08  achim
- * New event_string only valid for the RP controller family
- *
- * Revision 1.34  2000/03/02 14:55:29  achim
- * New mechanism for async. event handling implemented
- *
- * Revision 1.33  2000/02/21 15:37:37  achim
- * Bugfix Alpha platform + DPMEM above 4GB
- *
- * Revision 1.32  2000/02/14 16:17:37  achim
- * Bugfix sense_buffer[] + raw devices
- *
- * Revision 1.31  2000/02/10 10:29:00  achim
- * Delete sense_buffer[0], if command OK
- *
- * Revision 1.30  1999/11/02 13:42:39  achim
- * ARRAY_DRV_LIST2 implemented
- * Now 255 log. and 100 host drives supported
- *
- * Revision 1.29  1999/10/05 13:28:47  achim
- * GDT_CLUST_RESET added
- *
- * Revision 1.28  1999/08/12 13:44:54  achim
- * MOUNTALL removed
- * Cluster drives -> removeable drives
- *
- * Revision 1.27  1999/06/22 07:22:38  achim
- * Small changes
- *
- * Revision 1.26  1999/06/10 16:09:12  achim
- * Cluster Host Drive support: Bugfixes
- *
- * Revision 1.25  1999/06/01 16:03:56  achim
- * gdth_init_pci(): Manipulate config. space to start RP controller
- *
- * Revision 1.24  1999/05/26 11:53:06  achim
- * Cluster Host Drive support added
- *
- * Revision 1.23  1999/03/26 09:12:31  achim
- * Default value for hdr_channel set to 0
- *
- * Revision 1.22  1999/03/22 16:27:16  achim
- * Bugfix: gdth_store_event() must not be locked with GDTH_LOCK_HA()
- *
- * Revision 1.21  1999/03/16 13:40:34  achim
- * Problems with reserved drives solved
- * gdth_eh_bus_reset() implemented
- *
- * Revision 1.20  1999/03/10 09:08:13  achim
- * Bugfix: Corrections in gdth_direction_tab[] made
- * Bugfix: Increase command timeout (gdth_update_timeout()) NOT in gdth_putq()
- *
- * Revision 1.19  1999/03/05 14:38:16  achim
- * Bugfix: Heads/Sectors mapping for reserved devices possibly wrong
- * -> gdth_eval_mapping() implemented, changes in gdth_bios_param()
- * INIT_RETRIES set to 100s to avoid DEINIT-Timeout for controllers
- * with BIOS disabled and memory test set to Intensive
- * Enhanced /proc support
- *
- * Revision 1.18  1999/02/24 09:54:33  achim
- * Command line parameter hdr_channel implemented
- * Bugfix for EISA controllers + Linux 2.2.x
- *
- * Revision 1.17  1998/12/17 15:58:11  achim
- * Command line parameters implemented
- * Changes for Alpha platforms
- * PCI controller scan changed
- * SMP support improved (spin_lock_irqsave(),...)
- * New async. events, new scan/reserve commands included
- *
- * Revision 1.16  1998/09/28 16:08:46  achim
- * GDT_PCIMPR: DPMEM remapping, if required
- * mdelay() added
- *
- * Revision 1.15  1998/06/03 14:54:06  achim
- * gdth_delay(), gdth_flush() implemented
- * Bugfix: gdth_release() changed
- *
- * Revision 1.14  1998/05/22 10:01:17  achim
- * mj: pcibios_strerror() removed
- * Improved SMP support (if version >= 2.1.95)
- * gdth_halt(): halt_called flag added (if version < 2.1)
- *
- * Revision 1.13  1998/04/16 09:14:57  achim
- * Reserve drives (for raw service) implemented
- * New error handling code enabled
- * Get controller name from board_info() IOCTL
- * Final round of PCI device driver patches by Martin Mares
- *
- * Revision 1.12  1998/03/03 09:32:37  achim
- * Fibre channel controller support added
- *
- * Revision 1.11  1998/01/27 16:19:14  achim
- * SA_SHIRQ added
- * add_timer()/del_timer() instead of GDTH_TIMER
- * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
- * New error handling included
- *
- * Revision 1.10  1997/10/31 12:29:57  achim
- * Read heads/sectors from host drive
- *
- * Revision 1.9  1997/09/04 10:07:25  achim
- * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
- * register_reboot_notifier() to get a notify on shutown used
- *
- * Revision 1.8  1997/04/02 12:14:30  achim
- * Version 1.00 (see gdth.h), tested with kernel 2.0.29
- *
- * Revision 1.7  1997/03/12 13:33:37  achim
- * gdth_reset() changed, new async. events
- *
- * Revision 1.6  1997/03/04 14:01:11  achim
- * Shutdown routine gdth_halt() implemented
- *
- * Revision 1.5  1997/02/21 09:08:36  achim
- * New controller included (RP, RP1, RP2 series)
- * IOCTL interface implemented
- *
- * Revision 1.4  1996/07/05 12:48:55  achim
- * Function gdth_bios_param() implemented
- * New constant GDTH_MAXC_P_L inserted
- * GDT_WRITE_THR, GDT_EXT_INFO implemented
- * Function gdth_reset() changed
- *
- * Revision 1.3  1996/05/10 09:04:41  achim
- * Small changes for Linux 1.2.13
- *
- * Revision 1.2  1996/05/09 12:45:27  achim
- * Loadable module support implemented
- * /proc support corrections made
- *
- * Revision 1.1  1996/04/11 07:35:57  achim
- * Initial revision
- *
  ************************************************************************/
 
 /* All GDT Disk Array Controllers are fully supported by this driver.
  * max_ids:x                    x - target ID count per channel (1..MAXID)
  * rescan:Y                     rescan all channels/IDs 
  * rescan:N                     use all devices found until now
- * virt_ctr:Y                   map every channel to a virtual controller 
- * virt_ctr:N                   use multi channel support 
  * hdr_channel:x                x - number of virtual bus for host drives
  * shared_access:Y              disable driver reserve/release protocol to 
  *                              access a shared resource from several nodes, 
  * force_dma32:N                use 64 bit DMA mode, if supported
  *
  * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
- *                          max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0,
+ *                          max_ids:127,rescan:N,hdr_channel:0,
  *                          shared_access:Y,probe_eisa_isa:N,force_dma32:N".
  * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
  * 
  * '1' in place of 'Y' and '0' in place of 'N'.
  * 
  * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
- *           max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 
+ *           max_ids=127 rescan=0 hdr_channel=0 shared_access=0
  *           probe_eisa_isa=0 force_dma32=0"
  * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
  */
 
 /* The meaning of the Scsi_Pointer members in this driver is as follows:
  * ptr:                     Chaining
- * this_residual:           Command priority
- * buffer:                  phys. DMA sense buffer 
- * dma_handle:              phys. DMA buffer (kernel >= 2.4.0)
- * buffers_residual:        Timeout value
- * Status:                  Command status (gdth_do_cmd()), DMA mem. mappings
- * Message:                 Additional info (gdth_do_cmd()), DMA direction
- * have_data_in:            Flag for gdth_wait_completion()
- * sent_command:            Opcode special command
- * phase:                   Service/parameter/return code special command
+ * this_residual:           gdth_bufflen
+ * buffer:                  gdth_sglist
+ * dma_handle:              unused
+ * buffers_residual:        gdth_sg_count
+ * Status:                  unused
+ * Message:                 unused
+ * have_data_in:            unused
+ * sent_command:            unused
+ * phase:                   unused
  */
 
 
 #include <linux/proc_fs.h>
 #include <linux/time.h>
 #include <linux/timer.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
 #include <linux/dma-mapping.h>
-#else
-#define DMA_32BIT_MASK 0x00000000ffffffffULL
-#define DMA_64BIT_MASK 0xffffffffffffffffULL
-#endif
+#include <linux/list.h>
 
 #ifdef GDTH_RTC
 #include <linux/mc146818rtc.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <linux/blkdev.h>
-#else
-#include <linux/blk.h>
-#include "sd.h"
-#endif
+#include <linux/scatterlist.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "gdth_kcompat.h"
 #include "gdth.h"
 
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
 static irqreturn_t gdth_interrupt(int irq, void *dev_id);
-static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
-static int gdth_async_event(int hanum);
+static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq,
+                                    int gdth_from_wait, int* pIndex);
+static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
+                                                               Scsi_Cmnd *scp);
+static int gdth_async_event(gdth_ha_str *ha);
 static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
 
-static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
-static void gdth_next(int hanum);
-static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
-static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp);
+static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority);
+static void gdth_next(gdth_ha_str *ha);
+static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b);
+static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp);
 static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
                                       ushort idx, gdth_evt_data *evt);
 static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
@@ -439,42 +159,34 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
                                gdth_evt_str *estr);
 static void gdth_clear_events(void);
 
-static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
-                                    char *buffer,ushort count);
-static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
-static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
+static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
+                                    char *buffer, ushort count, int to_buffer);
+static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp);
+static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive);
 
-static int gdth_search_eisa(ushort eisa_adr);
-static int gdth_search_isa(ulong32 bios_adr);
-static int gdth_search_pci(gdth_pci_str *pcistr);
-static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, 
-                            ushort vendor, ushort dev);
-static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt);
-static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
-static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha);
-static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
-
-static void gdth_enable_int(int hanum);
-static int gdth_get_status(unchar *pIStatus,int irq);
-static int gdth_test_busy(int hanum);
-static int gdth_get_cmd_index(int hanum);
-static void gdth_release_event(int hanum);
-static int gdth_wait(int hanum,int index,ulong32 time);
-static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
-                             ulong64 p2,ulong64 p3);
-static int gdth_search_drives(int hanum);
-static int gdth_analyse_hdrive(int hanum, ushort hdrive);
-
-static const char *gdth_ctr_name(int hanum);
+static void gdth_enable_int(gdth_ha_str *ha);
+static unchar gdth_get_status(gdth_ha_str *ha, int irq);
+static int gdth_test_busy(gdth_ha_str *ha);
+static int gdth_get_cmd_index(gdth_ha_str *ha);
+static void gdth_release_event(gdth_ha_str *ha);
+static int gdth_wait(gdth_ha_str *ha, int index,ulong32 time);
+static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode,
+                                             ulong32 p1, ulong64 p2,ulong64 p3);
+static int gdth_search_drives(gdth_ha_str *ha);
+static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive);
+
+static const char *gdth_ctr_name(gdth_ha_str *ha);
 
 static int gdth_open(struct inode *inode, struct file *filep);
 static int gdth_close(struct inode *inode, struct file *filep);
 static int gdth_ioctl(struct inode *inode, struct file *filep,
                       unsigned int cmd, unsigned long arg);
 
-static void gdth_flush(int hanum);
+static void gdth_flush(gdth_ha_str *ha);
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
 static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
+static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
+                               struct gdth_cmndinfo *cmndinfo);
 static void gdth_scsi_done(struct scsi_cmnd *scp);
 
 #ifdef DEBUG_GDTH
@@ -571,29 +283,17 @@ static struct timer_list gdth_timer;
 #define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)
 #define INDEX_OK(i,t)   ((i)<ARRAY_SIZE(t))
 
-#define NUMDATA(a)      ( (gdth_num_str  *)((a)->hostdata))
-#define HADATA(a)       (&((gdth_ext_str *)((a)->hostdata))->haext)
-#define CMDDATA(a)      (&((gdth_ext_str *)((a)->hostdata))->cmdext)
-
 #define BUS_L2P(a,b)    ((b)>(a)->virt_bus ? (b-1):(b))
 
-#define gdth_readb(addr)        readb(addr)
-#define gdth_readw(addr)        readw(addr)
-#define gdth_readl(addr)        readl(addr)
-#define gdth_writeb(b,addr)     writeb((b),(addr))
-#define gdth_writew(b,addr)     writew((b),(addr))
-#define gdth_writel(b,addr)     writel((b),(addr))
-
+#ifdef CONFIG_ISA
 static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
+#endif
+#if defined(CONFIG_EISA) || defined(CONFIG_ISA)
 static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
+#endif
 static unchar   gdth_polling;                           /* polling if TRUE */
-static unchar   gdth_from_wait  = FALSE;                /* gdth_wait() */
-static int      wait_index,wait_hanum;                  /* gdth_wait() */
 static int      gdth_ctr_count  = 0;                    /* controller count */
-static int      gdth_ctr_vcount = 0;                    /* virt. ctr. count */
-static int      gdth_ctr_released = 0;                  /* gdth_release() */
-static struct Scsi_Host *gdth_ctr_tab[MAXHA];           /* controller table */
-static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS];   /* virt. ctr. table */
+static LIST_HEAD(gdth_instances);                       /* controller list */
 static unchar   gdth_write_through = FALSE;             /* write through */
 static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
 static int elastidx;
@@ -645,8 +345,6 @@ static int hdr_channel = 0;
 static int max_ids = MAXID;
 /* rescan all IDs */
 static int rescan = 0;
-/* map channels to virtual controllers */
-static int virt_ctr = 0;
 /* shared access */
 static int shared_access = 1;
 /* enable support for EISA and ISA controllers */
@@ -655,7 +353,6 @@ static int probe_eisa_isa = 0;
 static int force_dma32 = 0;
 
 /* parameters for modprobe/insmod */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
 module_param_array(irq, int, NULL, 0);
 module_param(disable, int, 0);
 module_param(reserve_mode, int, 0);
@@ -664,24 +361,9 @@ module_param(reverse_scan, int, 0);
 module_param(hdr_channel, int, 0);
 module_param(max_ids, int, 0);
 module_param(rescan, int, 0);
-module_param(virt_ctr, int, 0);
 module_param(shared_access, int, 0);
 module_param(probe_eisa_isa, int, 0);
 module_param(force_dma32, int, 0);
-#else
-MODULE_PARM(irq, "i");
-MODULE_PARM(disable, "i");
-MODULE_PARM(reserve_mode, "i");
-MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
-MODULE_PARM(reverse_scan, "i");
-MODULE_PARM(hdr_channel, "i");
-MODULE_PARM(max_ids, "i");
-MODULE_PARM(rescan, "i");
-MODULE_PARM(virt_ctr, "i");
-MODULE_PARM(shared_access, "i");
-MODULE_PARM(probe_eisa_isa, "i");
-MODULE_PARM(force_dma32, "i");
-#endif
 MODULE_AUTHOR("Achim Leubner");
 MODULE_LICENSE("GPL");
 
@@ -692,6 +374,47 @@ static const struct file_operations gdth_fops = {
     .release = gdth_close,
 };
 
+/*
+ * gdth scsi_command access wrappers.
+ *   below 6 functions are used throughout the driver to access scsi_command's
+ *   io parameters. The reason we do not use the regular accessors from
+ *   scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for
+ *   llds to directly set scsi_cmnd's IO members. This driver will use SCp
+ *   members for IO parameters, and will copy scsi_cmnd's members to Scp
+ *   members in queuecommand. For internal commands through gdth_execute()
+ *   SCp's members will be set directly.
+ */
+static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd)
+{
+       return (unsigned)cmd->SCp.this_residual;
+}
+
+static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen)
+{
+       cmd->SCp.this_residual = bufflen;
+}
+
+static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd)
+{
+       return (unsigned)cmd->SCp.buffers_residual;
+}
+
+static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count)
+{
+       cmd->SCp.buffers_residual = sg_count;
+}
+
+static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd)
+{
+       return cmd->SCp.buffer;
+}
+
+static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
+                                   struct scatterlist *sglist)
+{
+       cmd->SCp.buffer = sglist;
+}
+
 #include "gdth_proc.h"
 #include "gdth_proc.c"
 
@@ -701,6 +424,45 @@ static struct notifier_block gdth_notifier = {
 };
 static int notifier_disabled = 0;
 
+static gdth_ha_str *gdth_find_ha(int hanum)
+{
+       gdth_ha_str *ha;
+
+       list_for_each_entry(ha, &gdth_instances, list)
+               if (hanum == ha->hanum)
+                       return ha;
+
+       return NULL;
+}
+
+static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha)
+{
+       struct gdth_cmndinfo *priv = NULL;
+       ulong flags;
+       int i;
+
+       spin_lock_irqsave(&ha->smp_lock, flags);
+
+       for (i=0; i<GDTH_MAXCMDS; ++i) {
+               if (ha->cmndinfo[i].index == 0) {
+                       priv = &ha->cmndinfo[i];
+                       priv->index = i+1;
+                       memset(priv, 0, sizeof(*priv));
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&ha->smp_lock, flags);
+
+       return priv;
+}
+
+static void gdth_put_cmndinfo(struct gdth_cmndinfo *priv)
+{
+       BUG_ON(!priv);
+       priv->index = 0;
+}
+
 static void gdth_delay(int milliseconds)
 {
     if (milliseconds == 0) {
@@ -710,80 +472,62 @@ static void gdth_delay(int milliseconds)
     }
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static void gdth_scsi_done(struct scsi_cmnd *scp)
 {
-    TRACE2(("gdth_scsi_done()\n"));
+       struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
+       int internal_command = cmndinfo->internal_command;
+
+       TRACE2(("gdth_scsi_done()\n"));
+
+       gdth_put_cmndinfo(cmndinfo);
+       scp->host_scribble = NULL;
 
-    if (scp->request)
-        complete((struct completion *)scp->request);
+       if (internal_command)
+               complete((struct completion *)scp->request);
+       else
+               scp->scsi_done(scp);
 }
 
 int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
                    int timeout, u32 *info)
 {
+    gdth_ha_str *ha = shost_priv(sdev->host);
     Scsi_Cmnd *scp;
+    struct gdth_cmndinfo cmndinfo;
+    struct scatterlist one_sg;
     DECLARE_COMPLETION_ONSTACK(wait);
     int rval;
 
-    scp = kmalloc(sizeof(*scp), GFP_KERNEL);
+    scp = kzalloc(sizeof(*scp), GFP_KERNEL);
     if (!scp)
         return -ENOMEM;
-    memset(scp, 0, sizeof(*scp));
+
     scp->device = sdev;
+    memset(&cmndinfo, 0, sizeof(cmndinfo));
+
     /* use request field to save the ptr. to completion struct. */
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
-    scp->request_buffer = gdtcmd;
+    sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd));
+    gdth_set_sglist(scp, &one_sg);
+    gdth_set_sg_count(scp, 1);
+    gdth_set_bufflen(scp, sizeof(*gdtcmd));
     scp->cmd_len = 12;
     memcpy(scp->cmnd, cmnd, 12);
-    scp->SCp.this_residual = IOCTL_PRI;   /* priority */
-    scp->done = gdth_scsi_done; /* some fn. test this */
-    gdth_queuecommand(scp, gdth_scsi_done);
-    wait_for_completion(&wait);
-
-    rval = scp->SCp.Status;
-    if (info)
-        *info = scp->SCp.Message;
-    kfree(scp);
-    return rval;
-}
-#else
-static void gdth_scsi_done(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_scsi_done()\n"));
-
-    scp->request.rq_status = RQ_SCSI_DONE;
-    if (scp->request.waiting)
-        complete(scp->request.waiting);
-}
+    cmndinfo.priority = IOCTL_PRI;
+    cmndinfo.internal_command = 1;
 
-int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
-                   int timeout, u32 *info)
-{
-    Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE);
-    unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0;
-    DECLARE_COMPLETION_ONSTACK(wait);
-    int rval;
+    TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0]));
+    __gdth_queuecommand(ha, scp, &cmndinfo);
 
-    if (!scp)
-        return -ENOMEM;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-    scp->SCp.this_residual = IOCTL_PRI;   /* priority */
-    scp->request.rq_status = RQ_SCSI_BUSY;
-    scp->request.waiting = &wait;
-    scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
     wait_for_completion(&wait);
 
-    rval = scp->SCp.Status;
+    rval = cmndinfo.status;
     if (info)
-        *info = scp->SCp.Message;
-
-    scsi_release_command(scp);
+        *info = cmndinfo.info;
+    kfree(scp);
     return rval;
 }
-#endif
 
 int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
                  int timeout, u32 *info)
@@ -815,7 +559,7 @@ static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs
 }
 
 /* controller search and initialization functions */
-
+#ifdef CONFIG_EISA
 static int __init gdth_search_eisa(ushort eisa_adr)
 {
     ulong32 id;
@@ -832,8 +576,9 @@ static int __init gdth_search_eisa(ushort eisa_adr)
 
     return 0;                                   
 }
+#endif /* CONFIG_EISA */
 
-
+#ifdef CONFIG_ISA
 static int __init gdth_search_isa(ulong32 bios_adr)
 {
     void __iomem *addr;
@@ -841,14 +586,18 @@ static int __init gdth_search_isa(ulong32 bios_adr)
 
     TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
     if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
-        id = gdth_readl(addr);
+        id = readl(addr);
         iounmap(addr);
         if (id == GDT2_ID)                          /* GDT2000 */
             return 1;
     }
     return 0;
 }
+#endif /* CONFIG_ISA */
 
+#ifdef CONFIG_PCI
+static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+                            ushort vendor, ushort dev);
 
 static int __init gdth_search_pci(gdth_pci_str *pcistr)
 {
@@ -928,7 +677,6 @@ static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
     }       
 }   
 
-
 static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
 {    
     gdth_pci_str temp;
@@ -965,8 +713,9 @@ static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
         }
     } while (changed);
 }
+#endif /* CONFIG_PCI */
 
-
+#ifdef CONFIG_EISA
 static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
 {
     ulong32 retries,id;
@@ -1058,8 +807,9 @@ static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
     ha->dma64_support = 0;
     return 1;
 }
+#endif /* CONFIG_EISA */
 
-       
+#ifdef CONFIG_ISA
 static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
 {
     register gdt2_dpram_str __iomem *dp2_ptr;
@@ -1075,22 +825,22 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
         return 0;
     }
     dp2_ptr = ha->brd;
-    gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
+    writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
     /* reset interface area */
     memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u));
-    if (gdth_readl(&dp2_ptr->u) != 0) {
+    if (readl(&dp2_ptr->u) != 0) {
         printk("GDT-ISA: Initialization error (DPMEM write error)\n");
         iounmap(ha->brd);
         return 0;
     }
 
     /* disable board interrupts, read DRQ and IRQ */
-    gdth_writeb(0xff, &dp2_ptr->io.irqdel);
-    gdth_writeb(0x00, &dp2_ptr->io.irqen);
-    gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status);
-    gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
+    writeb(0xff, &dp2_ptr->io.irqdel);
+    writeb(0x00, &dp2_ptr->io.irqen);
+    writeb(0x00, &dp2_ptr->u.ic.S_Status);
+    writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
 
-    irq_drq = gdth_readb(&dp2_ptr->io.rq);
+    irq_drq = readb(&dp2_ptr->io.rq);
     for (i=0; i<3; ++i) {
         if ((irq_drq & 1)==0)
             break;
@@ -1098,7 +848,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
     }
     ha->drq = gdth_drq_tab[i];
 
-    irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3;
+    irq_drq = readb(&dp2_ptr->io.rq) >> 3;
     for (i=1; i<5; ++i) {
         if ((irq_drq & 1)==0)
             break;
@@ -1107,12 +857,12 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
     ha->irq = gdth_irq_tab[i];
 
     /* deinitialize services */
-    gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
-    gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
-    gdth_writeb(0, &dp2_ptr->io.event);
+    writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
+    writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
+    writeb(0, &dp2_ptr->io.event);
     retries = INIT_RETRIES;
     gdth_delay(20);
-    while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
+    while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error (DEINIT failed)\n");
             iounmap(ha->brd);
@@ -1120,9 +870,9 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
         }
         gdth_delay(1);
     }
-    prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]);
-    gdth_writeb(0, &dp2_ptr->u.ic.Status);
-    gdth_writeb(0xff, &dp2_ptr->io.irqdel);
+    prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]);
+    writeb(0, &dp2_ptr->u.ic.Status);
+    writeb(0xff, &dp2_ptr->io.irqdel);
     if (prot_ver != PROTOCOL_VERSION) {
         printk("GDT-ISA: Illegal protocol version\n");
         iounmap(ha->brd);
@@ -1136,15 +886,15 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
     ha->brd_phys = bios_adr >> 4;
 
     /* special request to controller BIOS */
-    gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
-    gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
-    gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
-    gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
-    gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
-    gdth_writeb(0, &dp2_ptr->io.event);
+    writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
+    writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
+    writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
+    writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
+    writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
+    writeb(0, &dp2_ptr->io.event);
     retries = INIT_RETRIES;
     gdth_delay(20);
-    while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
+    while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error\n");
             iounmap(ha->brd);
@@ -1152,14 +902,15 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
         }
         gdth_delay(1);
     }
-    gdth_writeb(0, &dp2_ptr->u.ic.Status);
-    gdth_writeb(0xff, &dp2_ptr->io.irqdel);
+    writeb(0, &dp2_ptr->u.ic.Status);
+    writeb(0xff, &dp2_ptr->io.irqdel);
 
     ha->dma64_support = 0;
     return 1;
 }
+#endif /* CONFIG_ISA */
 
-
+#ifdef CONFIG_PCI
 static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 {
     register gdt6_dpram_str __iomem *dp6_ptr;
@@ -1190,8 +941,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         }
         /* check and reset interface area */
         dp6_ptr = ha->brd;
-        gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
-        if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
+        writel(DPMEM_MAGIC, &dp6_ptr->u);
+        if (readl(&dp6_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
                    pcistr->dpmem);
             found = FALSE;
@@ -1202,7 +953,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                if (gdth_readw(ha->brd) != 0xffff) {
+                if (readw(ha->brd) != 0xffff) {
                     TRACE2(("init_pci_old() address 0x%x busy\n", i));
                     continue;
                 }
@@ -1215,8 +966,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     return 0;
                 }
                 dp6_ptr = ha->brd;
-                gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
-                if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
+                writel(DPMEM_MAGIC, &dp6_ptr->u);
+                if (readl(&dp6_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
                     found = TRUE;
                     break;
@@ -1229,24 +980,24 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
         }
         memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u));
-        if (gdth_readl(&dp6_ptr->u) != 0) {
+        if (readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
             return 0;
         }
         
         /* disable board interrupts, deinit services */
-        gdth_writeb(0xff, &dp6_ptr->io.irqdel);
-        gdth_writeb(0x00, &dp6_ptr->io.irqen);
-        gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status);
-        gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
-
-        gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
-        gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
-        gdth_writeb(0, &dp6_ptr->io.event);
+        writeb(0xff, &dp6_ptr->io.irqdel);
+        writeb(0x00, &dp6_ptr->io.irqen);
+        writeb(0x00, &dp6_ptr->u.ic.S_Status);
+        writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
+
+        writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
+        writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
+        writeb(0, &dp6_ptr->io.event);
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
+        while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
@@ -1254,9 +1005,9 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]);
-        gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
-        gdth_writeb(0xff, &dp6_ptr->io.irqdel);
+        prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]);
+        writeb(0, &dp6_ptr->u.ic.S_Status);
+        writeb(0xff, &dp6_ptr->io.irqdel);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
             iounmap(ha->brd);
@@ -1267,15 +1018,15 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         ha->ic_all_size = sizeof(dp6_ptr->u);
         
         /* special command to controller BIOS */
-        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
-        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
-        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]);
-        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
-        gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
-        gdth_writeb(0, &dp6_ptr->io.event);
+        writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
+        writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
+        writel(0x00, &dp6_ptr->u.ic.S_Info[2]);
+        writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
+        writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
+        writeb(0, &dp6_ptr->io.event);
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
+        while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
                 iounmap(ha->brd);
@@ -1283,8 +1034,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
-        gdth_writeb(0xff, &dp6_ptr->io.irqdel);
+        writeb(0, &dp6_ptr->u.ic.S_Status);
+        writeb(0xff, &dp6_ptr->io.irqdel);
 
         ha->dma64_support = 0;
 
@@ -1300,8 +1051,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         }
         /* check and reset interface area */
         dp6c_ptr = ha->brd;
-        gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
-        if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
+        writel(DPMEM_MAGIC, &dp6c_ptr->u);
+        if (readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
                    pcistr->dpmem);
             found = FALSE;
@@ -1312,7 +1063,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                if (gdth_readw(ha->brd) != 0xffff) {
+                if (readw(ha->brd) != 0xffff) {
                     TRACE2(("init_pci_plx() address 0x%x busy\n", i));
                     continue;
                 }
@@ -1325,8 +1076,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     return 0;
                 }
                 dp6c_ptr = ha->brd;
-                gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
-                if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
+                writel(DPMEM_MAGIC, &dp6c_ptr->u);
+                if (readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
                     found = TRUE;
                     break;
@@ -1339,7 +1090,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
         }
         memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u));
-        if (gdth_readl(&dp6c_ptr->u) != 0) {
+        if (readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
             return 0;
@@ -1349,17 +1100,17 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         outb(0x00,PTR2USHORT(&ha->plx->control1));
         outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
         
-        gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
-        gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
+        writeb(0x00, &dp6c_ptr->u.ic.S_Status);
+        writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
 
-        gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
-        gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
+        writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
+        writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
 
         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
 
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
+        while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
@@ -1367,8 +1118,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]);
-        gdth_writeb(0, &dp6c_ptr->u.ic.Status);
+        prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]);
+        writeb(0, &dp6c_ptr->u.ic.Status);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
             iounmap(ha->brd);
@@ -1379,17 +1130,17 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         ha->ic_all_size = sizeof(dp6c_ptr->u);
 
         /* special command to controller BIOS */
-        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
-        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
-        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]);
-        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
-        gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
+        writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
+        writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
+        writel(0x00, &dp6c_ptr->u.ic.S_Info[2]);
+        writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
+        writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
         
         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
 
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
+        while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
                 iounmap(ha->brd);
@@ -1397,7 +1148,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
+        writeb(0, &dp6c_ptr->u.ic.S_Status);
 
         ha->dma64_support = 0;
 
@@ -1425,12 +1176,12 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 
         /* Ensure that it is safe to access the non HW portions of DPMEM.
          * Aditional check needed for Xscale based RAID controllers */
-        while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 )
+        while( ((int)readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 )
             gdth_delay(1);
         
         /* check and reset interface area */
-        gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
-        if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
+        writel(DPMEM_MAGIC, &dp6m_ptr->u);
+        if (readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
                    pcistr->dpmem);
             found = FALSE;
@@ -1441,7 +1192,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                if (gdth_readw(ha->brd) != 0xffff) {
+                if (readw(ha->brd) != 0xffff) {
                     TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
                     continue;
                 }
@@ -1454,8 +1205,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     return 0;
                 }
                 dp6m_ptr = ha->brd;
-                gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
-                if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
+                writel(DPMEM_MAGIC, &dp6m_ptr->u);
+                if (readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
                     found = TRUE;
                     break;
@@ -1470,18 +1221,18 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u));
         
         /* disable board interrupts, deinit services */
-        gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
+        writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
                     &dp6m_ptr->i960r.edoor_en_reg);
-        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status);
-        gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
+        writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        writeb(0x00, &dp6m_ptr->u.ic.S_Status);
+        writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
 
-        gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
-        gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
-        gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+        writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
+        writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
+        writeb(1, &dp6m_ptr->i960r.ldoor_reg);
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
+        while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
@@ -1489,8 +1240,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]);
-        gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
+        prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]);
+        writeb(0, &dp6m_ptr->u.ic.S_Status);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
             iounmap(ha->brd);
@@ -1501,15 +1252,15 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         ha->ic_all_size = sizeof(dp6m_ptr->u);
         
         /* special command to controller BIOS */
-        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
-        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
-        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]);
-        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
-        gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
-        gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+        writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
+        writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
+        writel(0x00, &dp6m_ptr->u.ic.S_Info[2]);
+        writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
+        writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
+        writeb(1, &dp6m_ptr->i960r.ldoor_reg);
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
+        while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
                 iounmap(ha->brd);
@@ -1517,14 +1268,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
+        writeb(0, &dp6m_ptr->u.ic.S_Status);
 
         /* read FW version to detect 64-bit DMA support */
-        gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx);
-        gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+        writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx);
+        writeb(1, &dp6m_ptr->i960r.ldoor_reg);
         retries = INIT_RETRIES;
         gdth_delay(20);
-        while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) {
+        while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
@@ -1532,8 +1283,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             gdth_delay(1);
         }
-        prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16);
-        gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
+        prot_ver = (unchar)(readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16);
+        writeb(0, &dp6m_ptr->u.ic.S_Status);
         if (prot_ver < 0x2b)      /* FW < x.43: no 64-bit DMA support */
             ha->dma64_support = 0;
         else 
@@ -1542,20 +1293,18 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 
     return 1;
 }
-
+#endif /* CONFIG_PCI */
 
 /* controller protocol functions */
 
-static void __init gdth_enable_int(int hanum)
+static void __init gdth_enable_int(gdth_ha_str *ha)
 {
-    gdth_ha_str *ha;
     ulong flags;
     gdt2_dpram_str __iomem *dp2_ptr;
     gdt6_dpram_str __iomem *dp6_ptr;
     gdt6m_dpram_str __iomem *dp6m_ptr;
 
-    TRACE(("gdth_enable_int() hanum %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE(("gdth_enable_int() hanum %d\n",ha->hanum));
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     if (ha->type == GDT_EISA) {
@@ -1564,93 +1313,80 @@ static void __init gdth_enable_int(int hanum)
         outb(0x01, ha->bmic + EINTENABREG);
     } else if (ha->type == GDT_ISA) {
         dp2_ptr = ha->brd;
-        gdth_writeb(1, &dp2_ptr->io.irqdel);
-        gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
-        gdth_writeb(1, &dp2_ptr->io.irqen);
+        writeb(1, &dp2_ptr->io.irqdel);
+        writeb(0, &dp2_ptr->u.ic.Cmd_Index);
+        writeb(1, &dp2_ptr->io.irqen);
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = ha->brd;
-        gdth_writeb(1, &dp6_ptr->io.irqdel);
-        gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
-        gdth_writeb(1, &dp6_ptr->io.irqen);
+        writeb(1, &dp6_ptr->io.irqdel);
+        writeb(0, &dp6_ptr->u.ic.Cmd_Index);
+        writeb(1, &dp6_ptr->io.irqen);
     } else if (ha->type == GDT_PCINEW) {
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
         outb(0x03, PTR2USHORT(&ha->plx->control1));
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = ha->brd;
-        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
+        writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
                     &dp6m_ptr->i960r.edoor_en_reg);
     }
     spin_unlock_irqrestore(&ha->smp_lock, flags);
 }
 
-
-static int gdth_get_status(unchar *pIStatus,int irq)
+/* return IStatus if interrupt was from this card else 0 */
+static unchar gdth_get_status(gdth_ha_str *ha, int irq)
 {
-    register gdth_ha_str *ha;
-    int i;
+    unchar IStatus = 0;
+
+    TRACE(("gdth_get_status() irq %d ctr_count %d\n", irq, gdth_ctr_count));
 
-    TRACE(("gdth_get_status() irq %d ctr_count %d\n",
-           irq,gdth_ctr_count));
-    
-    *pIStatus = 0;
-    for (i=0; i<gdth_ctr_count; ++i) {
-        ha = HADATA(gdth_ctr_tab[i]);
         if (ha->irq != (unchar)irq)             /* check IRQ */
-            continue;
+            return false;
         if (ha->type == GDT_EISA)
-            *pIStatus = inb((ushort)ha->bmic + EDOORREG);
+            IStatus = inb((ushort)ha->bmic + EDOORREG);
         else if (ha->type == GDT_ISA)
-            *pIStatus =
-                gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
+            IStatus =
+                readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCI)
-            *pIStatus =
-                gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
+            IStatus =
+                readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCINEW) 
-            *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
+            IStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
         else if (ha->type == GDT_PCIMPR)
-            *pIStatus =
-                gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg);
-   
-        if (*pIStatus)                                  
-            return i;                           /* board found */
-    }
-    return -1;
+            IStatus =
+                readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg);
+
+        return IStatus;
 }
-                 
-    
-static int gdth_test_busy(int hanum)
+
+static int gdth_test_busy(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
     register int gdtsema0 = 0;
 
-    TRACE(("gdth_test_busy() hanum %d\n",hanum));
-    
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE(("gdth_test_busy() hanum %d\n", ha->hanum));
+
     if (ha->type == GDT_EISA)
         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
     else if (ha->type == GDT_ISA)
-        gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCI)
-        gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCINEW) 
         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
     else if (ha->type == GDT_PCIMPR)
         gdtsema0 = 
-            (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
+            (int)readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
 
     return (gdtsema0 & 1);
 }
 
 
-static int gdth_get_cmd_index(int hanum)
+static int gdth_get_cmd_index(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
     int i;
 
-    TRACE(("gdth_get_cmd_index() hanum %d\n",hanum));
+    TRACE(("gdth_get_cmd_index() hanum %d\n", ha->hanum));
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     for (i=0; i<GDTH_MAXCMDS; ++i) {
         if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
             ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
@@ -1663,30 +1399,26 @@ static int gdth_get_cmd_index(int hanum)
 }
 
 
-static void gdth_set_sema0(int hanum)
+static void gdth_set_sema0(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
+    TRACE(("gdth_set_sema0() hanum %d\n", ha->hanum));
 
-    TRACE(("gdth_set_sema0() hanum %d\n",hanum));
-
-    ha = HADATA(gdth_ctr_tab[hanum]);
     if (ha->type == GDT_EISA) {
         outb(1, ha->bmic + SEMA0REG);
     } else if (ha->type == GDT_ISA) {
-        gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
+        writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     } else if (ha->type == GDT_PCI) {
-        gdth_writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
+        writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
     } else if (ha->type == GDT_PCIMPR) {
-        gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
+        writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
     }
 }
 
 
-static void gdth_copy_command(int hanum)
+static void gdth_copy_command(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
     register gdth_cmd_str *cmd_ptr;
     register gdt6m_dpram_str __iomem *dp6m_ptr;
     register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -1694,9 +1426,8 @@ static void gdth_copy_command(int hanum)
     gdt2_dpram_str __iomem *dp2_ptr;
     ushort cp_count,dp_offset,cmd_no;
     
-    TRACE(("gdth_copy_command() hanum %d\n",hanum));
+    TRACE(("gdth_copy_command() hanum %d\n", ha->hanum));
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     cp_count = ha->cmd_len;
     dp_offset= ha->cmd_offs_dpmem;
     cmd_no   = ha->cmd_cnt;
@@ -1715,42 +1446,39 @@ static void gdth_copy_command(int hanum)
     /* set offset and service, copy command to DPMEM */
     if (ha->type == GDT_ISA) {
         dp2_ptr = ha->brd;
-        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+        writew(dp_offset + DPMEM_COMMAND_OFFSET,
                     &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
-        gdth_writew((ushort)cmd_ptr->Service, 
+        writew((ushort)cmd_ptr->Service,
                     &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = ha->brd;
-        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+        writew(dp_offset + DPMEM_COMMAND_OFFSET,
                     &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
-        gdth_writew((ushort)cmd_ptr->Service, 
+        writew((ushort)cmd_ptr->Service,
                     &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCINEW) {
         dp6c_ptr = ha->brd;
-        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+        writew(dp_offset + DPMEM_COMMAND_OFFSET,
                     &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
-        gdth_writew((ushort)cmd_ptr->Service, 
+        writew((ushort)cmd_ptr->Service,
                     &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = ha->brd;
-        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+        writew(dp_offset + DPMEM_COMMAND_OFFSET,
                     &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
-        gdth_writew((ushort)cmd_ptr->Service, 
+        writew((ushort)cmd_ptr->Service,
                     &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     }
 }
 
 
-static void gdth_release_event(int hanum)
+static void gdth_release_event(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
-
-    TRACE(("gdth_release_event() hanum %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE(("gdth_release_event() hanum %d\n", ha->hanum));
 
 #ifdef GDTH_STATISTICS
     {
@@ -1774,56 +1502,50 @@ static void gdth_release_event(int hanum)
             outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
     } else if (ha->type == GDT_ISA) {
-        gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event);
+        writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event);
     } else if (ha->type == GDT_PCI) {
-        gdth_writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event);
+        writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event);
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
     } else if (ha->type == GDT_PCIMPR) {
-        gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg);
+        writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg);
     }
 }
 
-    
-static int gdth_wait(int hanum,int index,ulong32 time)
+static int gdth_wait(gdth_ha_str *ha, int index, ulong32 time)
 {
-    gdth_ha_str *ha;
     int answer_found = FALSE;
+    int wait_index = 0;
 
-    TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time));
+    TRACE(("gdth_wait() hanum %d index %d time %d\n", ha->hanum, index, time));
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     if (index == 0)
         return 1;                               /* no wait required */
 
-    gdth_from_wait = TRUE;
     do {
-        gdth_interrupt((int)ha->irq,ha);
-        if (wait_hanum==hanum && wait_index==index) {
+        __gdth_interrupt(ha, (int)ha->irq, true, &wait_index);
+        if (wait_index == index) {
             answer_found = TRUE;
             break;
         }
         gdth_delay(1);
     } while (--time);
-    gdth_from_wait = FALSE;
-    
-    while (gdth_test_busy(hanum))
+
+    while (gdth_test_busy(ha))
         gdth_delay(0);
 
     return (answer_found);
 }
 
 
-static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
-                             ulong64 p2,ulong64 p3)
+static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode,
+                                            ulong32 p1, ulong64 p2, ulong64 p3)
 {
-    register gdth_ha_str *ha;
     register gdth_cmd_str *cmd_ptr;
     int retries,index;
 
     TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     cmd_ptr = ha->pccb;
     memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
 
@@ -1831,11 +1553,11 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
     for (retries = INIT_RETRIES;;) {
         cmd_ptr->Service          = service;
         cmd_ptr->RequestBuffer    = INTERNAL_CMND;
-        if (!(index=gdth_get_cmd_index(hanum))) {
+        if (!(index=gdth_get_cmd_index(ha))) {
             TRACE(("GDT: No free command index found\n"));
             return 0;
         }
-        gdth_set_sema0(hanum);
+        gdth_set_sema0(ha);
         cmd_ptr->OpCode           = opcode;
         cmd_ptr->BoardNode        = LOCALBOARD;
         if (service == CACHESERVICE) {
@@ -1875,10 +1597,10 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
         ha->cmd_len          = sizeof(gdth_cmd_str);
         ha->cmd_offs_dpmem   = 0;
         ha->cmd_cnt          = 0;
-        gdth_copy_command(hanum);
-        gdth_release_event(hanum);
+        gdth_copy_command(ha);
+        gdth_release_event(ha);
         gdth_delay(20);
-        if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
+        if (!gdth_wait(ha, index, INIT_TIMEOUT)) {
             printk("GDT: Initialization error (timeout service %d)\n",service);
             return 0;
         }
@@ -1893,9 +1615,8 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
 
 /* search for devices */
 
-static int __init gdth_search_drives(int hanum)
+static int __init gdth_search_drives(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
     ushort cdev_cnt, i;
     int ok;
     ulong32 bus_no, drv_cnt, drv_no, j;
@@ -1915,22 +1636,21 @@ static int __init gdth_search_drives(int hanum)
     ulong flags;
 #endif     
    
-    TRACE(("gdth_search_drives() hanum %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE(("gdth_search_drives() hanum %d\n", ha->hanum));
     ok = 0;
 
     /* initialize controller services, at first: screen service */
     ha->screen_feat = 0;
     if (!force_dma32) {
-        ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0);
+        ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_X_INIT_SCR, 0, 0, 0);
         if (ok)
             ha->screen_feat = GDT_64BIT;
     }
     if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
-        ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0);
+        ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_INIT, 0, 0, 0);
     if (!ok) {
         printk("GDT-HA %d: Initialization error screen service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
     }
     TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
@@ -1954,25 +1674,26 @@ static int __init gdth_search_drives(int hanum)
     TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
     /* 3. send to controller firmware */
-    gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0],
+    gdth_internal_cmd(ha, SCREENSERVICE, GDT_REALTIME, *(ulong32 *)&rtc[0],
                       *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]);
 #endif  
  
     /* unfreeze all IOs */
-    gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0);
+    gdth_internal_cmd(ha, CACHESERVICE, GDT_UNFREEZE_IO, 0, 0, 0);
  
     /* initialize cache service */
     ha->cache_feat = 0;
     if (!force_dma32) {
-        ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0);
+        ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INIT_HOST, LINUX_OS,
+                                                                         0, 0);
         if (ok)
             ha->cache_feat = GDT_64BIT;
     }
     if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
-        ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0);
+        ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_INIT, LINUX_OS, 0, 0);
     if (!ok) {
         printk("GDT-HA %d: Initialization error cache service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
     }
     TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
@@ -2001,9 +1722,9 @@ static int __init gdth_search_drives(int hanum)
         pmod->cmd_buff_size    = 0;
         pmod->reserved1        = 0;            
         pmod->reserved2        = 0;            
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES,
+        if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, SET_PERF_MODES,
                               INVALID_CHANNEL,sizeof(gdth_perf_modes))) {
-            printk("GDT-HA %d: Interrupt coalescing activated\n", hanum);
+            printk("GDT-HA %d: Interrupt coalescing activated\n", ha->hanum);
         }
     }
 #endif
@@ -2015,7 +1736,7 @@ static int __init gdth_search_drives(int hanum)
     iocr->hdr.first_chan     = 0;
     iocr->hdr.last_chan      = MAXBUS-1;
     iocr->hdr.list_offset    = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC,
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_RAW_DESC,
                           INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
         TRACE2(("IOCHAN_RAW_DESC supported!\n"));
         ha->bus_cnt = iocr->hdr.chan_count;
@@ -2030,13 +1751,13 @@ static int __init gdth_search_drives(int hanum)
         chn = (gdth_getch_str *)ha->pscratch;
         for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
             chn->channel_no = bus_no;
-            if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+            if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
                                    SCSI_CHAN_CNT | L_CTRL_PATTERN,
                                    IO_CHANNEL | INVALID_CHANNEL,
                                    sizeof(gdth_getch_str))) {
                 if (bus_no == 0) {
                     printk("GDT-HA %d: Error detecting channel count (0x%x)\n",
-                           hanum, ha->status);
+                           ha->hanum, ha->status);
                     return 0;
                 }
                 break;
@@ -2051,10 +1772,10 @@ static int __init gdth_search_drives(int hanum)
     TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
 
     /* read cache configuration */
-    if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
+    if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_INFO,
                            INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
         printk("GDT-HA %d: Initialization error cache service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
     }
     ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
@@ -2064,11 +1785,11 @@ static int __init gdth_search_drives(int hanum)
 
     /* read board info and features */
     ha->more_proc = FALSE;
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_INFO,
                           INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
         memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
                sizeof(gdth_binfo_str));
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES,
+        if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_FEATURES,
                               INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
             TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
             ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
@@ -2076,7 +1797,7 @@ static int __init gdth_search_drives(int hanum)
         }
     } else {
         TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
-        strcpy(ha->binfo.type_string, gdth_ctr_name(hanum));
+        strcpy(ha->binfo.type_string, gdth_ctr_name(ha));
     }
     TRACE2(("Controller name: %s\n",ha->binfo.type_string));
 
@@ -2089,7 +1810,7 @@ static int __init gdth_search_drives(int hanum)
         ioc->hdr.first_chan     = 0;
         ioc->hdr.last_chan      = MAXBUS-1;
         ioc->hdr.list_offset    = GDTOFFSOF(gdth_iochan_str, list[0]);
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC,
+        if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_DESC,
                               INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
             for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
                 ha->raw[bus_no].address = ioc->list[bus_no].address;
@@ -2104,7 +1825,7 @@ static int __init gdth_search_drives(int hanum)
         for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
             chn = (gdth_getch_str *)ha->pscratch;
             chn->channel_no = ha->raw[bus_no].local_no;
-            if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+            if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
                                   SCSI_CHAN_CNT | L_CTRL_PATTERN,
                                   ha->raw[bus_no].address | INVALID_CHANNEL,
                                   sizeof(gdth_getch_str))) {
@@ -2116,7 +1837,7 @@ static int __init gdth_search_drives(int hanum)
                 drl = (gdth_drlist_str *)ha->pscratch;
                 drl->sc_no = ha->raw[bus_no].local_no;
                 drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
-                if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+                if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
                                       SCSI_DR_LIST | L_CTRL_PATTERN,
                                       ha->raw[bus_no].address | INVALID_CHANNEL,
                                       sizeof(gdth_drlist_str))) {
@@ -2129,10 +1850,10 @@ static int __init gdth_search_drives(int hanum)
         }
 
         /* logical drives */
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT,
+        if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_CNT,
                               INVALID_CHANNEL,sizeof(ulong32))) {
             drv_cnt = *(ulong32 *)ha->pscratch;
-            if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST,
+            if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_LIST,
                                   INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
                 for (j = 0; j < drv_cnt; ++j) {
                     drv_no = ((ulong32 *)ha->pscratch)[j];
@@ -2146,7 +1867,7 @@ static int __init gdth_search_drives(int hanum)
             alst->entries_avail = MAX_LDRIVES;
             alst->first_entry = 0;
             alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]);
-            if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+            if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
                                   ARRAY_DRV_LIST2 | LA_CTRL_PATTERN, 
                                   INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
                                   (alst->entries_avail-1) * sizeof(gdth_alist_str))) { 
@@ -2157,7 +1878,7 @@ static int __init gdth_search_drives(int hanum)
                     ha->hdr[j].is_hotfix = alst->list[j].is_hotfix;
                     ha->hdr[j].master_no = alst->list[j].cd_handle;
                 }
-            } else if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+            } else if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
                                          ARRAY_DRV_LIST | LA_CTRL_PATTERN,
                                          0, 35 * sizeof(gdth_alist_str))) {
                 for (j = 0; j < 35; ++j) {
@@ -2175,24 +1896,24 @@ static int __init gdth_search_drives(int hanum)
     /* initialize raw service */
     ha->raw_feat = 0;
     if (!force_dma32) {
-        ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0);
+        ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_X_INIT_RAW, 0, 0, 0);
         if (ok)
             ha->raw_feat = GDT_64BIT;
     }
     if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
-        ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0);
+        ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_INIT, 0, 0, 0);
     if (!ok) {
         printk("GDT-HA %d: Initialization error raw service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
     }
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
 
     /* set/get features raw service (scatter/gather) */
-    if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
-                          0,0)) {
+    if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_SET_FEAT, SCATTER_GATHER,
+                          0, 0)) {
         TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
-        if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
+        if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_GET_FEAT, 0, 0, 0)) {
             TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
                     ha->info));
             ha->raw_feat |= (ushort)ha->info;
@@ -2200,10 +1921,10 @@ static int __init gdth_search_drives(int hanum)
     } 
 
     /* set/get features cache service (equal to raw service) */
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0,
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_SET_FEAT, 0,
                           SCATTER_GATHER,0)) {
         TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
+        if (gdth_internal_cmd(ha, CACHESERVICE, GDT_GET_FEAT, 0, 0, 0)) {
             TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
                     ha->info));
             ha->cache_feat |= (ushort)ha->info;
@@ -2212,22 +1933,22 @@ static int __init gdth_search_drives(int hanum)
 
     /* reserve drives for raw service */
     if (reserve_mode != 0) {
-        gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL,
+        gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE_ALL,
                           reserve_mode == 1 ? 1 : 3, 0, 0);
         TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", 
                 ha->status));
     }
     for (i = 0; i < MAX_RES_ARGS; i += 4) {
-        if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt && 
+        if (reserve_list[i] == ha->hanum && reserve_list[i+1] < ha->bus_cnt &&
             reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) {
             TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
                     reserve_list[i], reserve_list[i+1],
                     reserve_list[i+2], reserve_list[i+3]));
-            if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
+            if (!gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE, 0,
                                    reserve_list[i+1], reserve_list[i+2] | 
                                    (reserve_list[i+3] << 8))) {
                 printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n",
-                       hanum, ha->status);
+                       ha->hanum, ha->status);
              }
         }
     }
@@ -2236,58 +1957,44 @@ static int __init gdth_search_drives(int hanum)
     oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
     oemstr->params.ctl_version = 0x01;
     oemstr->params.buffer_size = sizeof(oemstr->text);
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
                           CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
                           sizeof(gdth_oem_str_ioctl))) {
         TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
         printk("GDT-HA %d: Vendor: %s Name: %s\n",
-               hanum,oemstr->text.oem_company_name,ha->binfo.type_string);
+               ha->hanum, oemstr->text.oem_company_name, ha->binfo.type_string);
         /* Save the Host Drive inquiry data */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
         strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,
                 sizeof(ha->oem_name));
-#else
-        strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7);
-        ha->oem_name[7] = '\0';
-#endif
     } else {
         /* Old method, based on PCI ID */
         TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
         printk("GDT-HA %d: Name: %s\n",
-               hanum,ha->binfo.type_string);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+               ha->hanum, ha->binfo.type_string);
         if (ha->oem_id == OEM_ID_INTEL)
             strlcpy(ha->oem_name,"Intel  ", sizeof(ha->oem_name));
         else
             strlcpy(ha->oem_name,"ICP    ", sizeof(ha->oem_name));
-#else 
-        if (ha->oem_id == OEM_ID_INTEL)
-            strcpy(ha->oem_name,"Intel  ");
-        else
-            strcpy(ha->oem_name,"ICP    ");
-#endif
     }
 
     /* scanning for host drives */
     for (i = 0; i < cdev_cnt; ++i) 
-        gdth_analyse_hdrive(hanum,i);
+        gdth_analyse_hdrive(hai);
     
     TRACE(("gdth_search_drives() OK\n"));
     return 1;
 }
 
-static int gdth_analyse_hdrive(int hanum,ushort hdrive)
+static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive)
 {
-    register gdth_ha_str *ha;
     ulong32 drv_cyls;
     int drv_hds, drv_secs;
 
-    TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive));
+    TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n", ha->hanum, hdrive));
     if (hdrive >= MAX_HDRIVES)
         return 0;
-    ha = HADATA(gdth_ctr_tab[hanum]);
 
-    if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,hdrive,0,0)) 
+    if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_INFO, hdrive, 0, 0))
         return 0;
     ha->hdr[hdrive].present = TRUE;
     ha->hdr[hdrive].size = ha->info;
@@ -2307,7 +2014,7 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive)
     ha->hdr[hdrive].size  = drv_cyls * drv_hds * drv_secs;
     
     if (ha->cache_feat & GDT_64BIT) {
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0)
+        if (gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INFO, hdrive, 0, 0)
             && ha->info2 != 0) {
             ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info;
         }
@@ -2316,14 +2023,14 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive)
             hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
 
     /* get informations about device */
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) {
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_DEVTYPE, hdrive, 0, 0)) {
         TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
                 hdrive,ha->info));
         ha->hdr[hdrive].devtype = (ushort)ha->info;
     }
 
     /* cluster info */
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_CLUST_INFO,hdrive,0,0)) {
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_CLUST_INFO, hdrive, 0, 0)) {
         TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
                 hdrive,ha->info));
         if (!shared_access)
@@ -2331,7 +2038,7 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive)
     }
 
     /* R/W attributes */
-    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) {
+    if (gdth_internal_cmd(ha, CACHESERVICE, GDT_RW_ATTRIBS, hdrive, 0, 0)) {
         TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
                 hdrive,ha->info));
         ha->hdr[hdrive].rw_attribs = (unchar)ha->info;
@@ -2343,27 +2050,26 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive)
 
 /* command queueing/sending functions */
 
-static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
+static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority)
 {
-    register gdth_ha_str *ha;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
     register Scsi_Cmnd *pscp;
     register Scsi_Cmnd *nscp;
     ulong flags;
     unchar b, t;
 
     TRACE(("gdth_putq() priority %d\n",priority));
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
-    if (scp->done != gdth_scsi_done) {
-        scp->SCp.this_residual = (int)priority;
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel;
+    if (!cmndinfo->internal_command) {
+        cmndinfo->priority = priority;
+        b = scp->device->channel;
         t = scp->device->id;
         if (priority >= DEFAULT_PRI) {
             if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
                 (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
                 TRACE2(("gdth_putq(): locked IO ->update_timeout()\n"));
-                scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+                cmndinfo->timeout = gdth_update_timeout(scp, 0);
             }
         }
     }
@@ -2375,7 +2081,7 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
         pscp = ha->req_first;
         nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
         /* priority: 0-highest,..,0xff-lowest */
-        while (nscp && (unchar)nscp->SCp.this_residual <= priority) {
+        while (nscp && gdth_cmnd_priv(nscp)->priority <= priority) {
             pscp = nscp;
             nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
         }
@@ -2395,9 +2101,8 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
 #endif
 }
 
-static void gdth_next(int hanum)
+static void gdth_next(gdth_ha_str *ha)
 {
-    register gdth_ha_str *ha;
     register Scsi_Cmnd *pscp;
     register Scsi_Cmnd *nscp;
     unchar b, t, l, firsttime;
@@ -2405,8 +2110,7 @@ static void gdth_next(int hanum)
     ulong flags = 0;
     int cmd_index;
 
-    TRACE(("gdth_next() hanum %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE(("gdth_next() hanum %d\n", ha->hanum));
     if (!gdth_polling) 
         spin_lock_irqsave(&ha->smp_lock, flags);
 
@@ -2416,14 +2120,14 @@ static void gdth_next(int hanum)
     cmd_index = 0;
 
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
+        struct gdth_cmndinfo *nscp_cmndinfo = gdth_cmnd_priv(nscp);
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-        if (nscp->done != gdth_scsi_done) {
-            b = virt_ctr ?
-                NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
+        if (!nscp_cmndinfo->internal_command) {
+            b = nscp->device->channel;
             t = nscp->device->id;
             l = nscp->device->lun;
-            if (nscp->SCp.this_residual >= DEFAULT_PRI) {
+            if (nscp_cmndinfo->priority >= DEFAULT_PRI) {
                 if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
                     (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
                     continue;
@@ -2432,21 +2136,21 @@ static void gdth_next(int hanum)
             b = t = l = 0;
 
         if (firsttime) {
-            if (gdth_test_busy(hanum)) {        /* controller busy ? */
-                TRACE(("gdth_next() controller %d busy !\n",hanum));
+            if (gdth_test_busy(ha)) {        /* controller busy ? */
+                TRACE(("gdth_next() controller %d busy !\n", ha->hanum));
                 if (!gdth_polling) {
                     spin_unlock_irqrestore(&ha->smp_lock, flags);
                     return;
                 }
-                while (gdth_test_busy(hanum))
+                while (gdth_test_busy(ha))
                     gdth_delay(1);
             }   
             firsttime = FALSE;
         }
 
-        if (nscp->done != gdth_scsi_done) {
-        if (nscp->SCp.phase == -1) {
-            nscp->SCp.phase = CACHESERVICE;           /* default: cache svc. */ 
+        if (!nscp_cmndinfo->internal_command) {
+        if (nscp_cmndinfo->phase == -1) {
+            nscp_cmndinfo->phase = CACHESERVICE;           /* default: cache svc. */
             if (nscp->cmnd[0] == TEST_UNIT_READY) {
                 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", 
                         b, t, l));
@@ -2459,8 +2163,8 @@ static void gdth_next(int hanum)
                 } else if ((ha->scan_mode & 0x0f) == 1) {
                     if (b == 0 && ((t == 0 && l == 1) ||
                          (t == 1 && l == 0))) {
-                        nscp->SCp.sent_command = GDT_SCAN_START;
-                        nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) 
+                        nscp_cmndinfo->OpCode = GDT_SCAN_START;
+                        nscp_cmndinfo->phase = ((ha->scan_mode & 0x10 ? 1:0) << 8)
                             | SCSIRAWSERVICE;
                         ha->scan_mode = 0x12;
                         TRACE2(("Scan mode: 0x%x (SCAN_START)\n", 
@@ -2471,8 +2175,8 @@ static void gdth_next(int hanum)
                     }                   
                 } else if (ha->scan_mode == 0x12) {
                     if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
-                        nscp->SCp.phase = SCSIRAWSERVICE;
-                        nscp->SCp.sent_command = GDT_SCAN_END;
+                        nscp_cmndinfo->phase = SCSIRAWSERVICE;
+                        nscp_cmndinfo->OpCode = GDT_SCAN_END;
                         ha->scan_mode &= 0x10;
                         TRACE2(("Scan mode: 0x%x (SCAN_END)\n", 
                                 ha->scan_mode));
@@ -2483,18 +2187,18 @@ static void gdth_next(int hanum)
                 nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
                 (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
                 /* always GDT_CLUST_INFO! */
-                nscp->SCp.sent_command = GDT_CLUST_INFO;
+                nscp_cmndinfo->OpCode = GDT_CLUST_INFO;
             }
         }
         }
 
-        if (nscp->SCp.sent_command != -1) {
-            if ((nscp->SCp.phase & 0xff) == CACHESERVICE) {
-                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+        if (nscp_cmndinfo->OpCode != -1) {
+            if ((nscp_cmndinfo->phase & 0xff) == CACHESERVICE) {
+                if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
                     this_cmd = FALSE;
                 next_cmd = FALSE;
-            } else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
-                if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
+            } else if ((nscp_cmndinfo->phase & 0xff) == SCSIRAWSERVICE) {
+                if (!(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b))))
                     this_cmd = FALSE;
                 next_cmd = FALSE;
             } else {
@@ -2502,18 +2206,18 @@ static void gdth_next(int hanum)
                 nscp->sense_buffer[0] = 0x70;
                 nscp->sense_buffer[2] = NOT_READY;
                 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-                if (!nscp->SCp.have_data_in)
-                    nscp->SCp.have_data_in++;
+                if (!nscp_cmndinfo->wait_for_completion)
+                    nscp_cmndinfo->wait_for_completion++;
                 else
-                    nscp->scsi_done(nscp);
+                    gdth_scsi_done(nscp);
             }
-        } else if (nscp->done == gdth_scsi_done) {
-            if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
+        } else if (gdth_cmnd_priv(nscp)->internal_command) {
+            if (!(cmd_index=gdth_special_cmd(hanscp)))
                 this_cmd = FALSE;
             next_cmd = FALSE;
         } else if (b != ha->virt_bus) {
             if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
-                !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) 
+                !(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b))))
                 this_cmd = FALSE;
             else 
                 ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
@@ -2521,10 +2225,10 @@ static void gdth_next(int hanum)
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
                     nscp->cmnd[0], b, t, l));
             nscp->result = DID_BAD_TARGET << 16;
-            if (!nscp->SCp.have_data_in)
-                nscp->SCp.have_data_in++;
+            if (!nscp_cmndinfo->wait_for_completion)
+                nscp_cmndinfo->wait_for_completion++;
             else
-                nscp->scsi_done(nscp);
+                gdth_scsi_done(nscp);
         } else {
             switch (nscp->cmnd[0]) {
               case TEST_UNIT_READY:
@@ -2547,12 +2251,12 @@ static void gdth_next(int hanum)
                     nscp->sense_buffer[0] = 0x70;
                     nscp->sense_buffer[2] = UNIT_ATTENTION;
                     nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-                    if (!nscp->SCp.have_data_in)
-                        nscp->SCp.have_data_in++;
+                    if (!nscp_cmndinfo->wait_for_completion)
+                        nscp_cmndinfo->wait_for_completion++;
                     else
-                        nscp->scsi_done(nscp);
-                } else if (gdth_internal_cache_cmd(hanum,nscp))
-                    nscp->scsi_done(nscp);
+                        gdth_scsi_done(nscp);
+                } else if (gdth_internal_cache_cmd(hanscp))
+                    gdth_scsi_done(nscp);
                 break;
 
               case ALLOW_MEDIUM_REMOVAL:
@@ -2563,15 +2267,15 @@ static void gdth_next(int hanum)
                     TRACE(("Prevent r. nonremov. drive->do nothing\n"));
                     nscp->result = DID_OK << 16;
                     nscp->sense_buffer[0] = 0;
-                    if (!nscp->SCp.have_data_in)
-                        nscp->SCp.have_data_in++;
+                    if (!nscp_cmndinfo->wait_for_completion)
+                        nscp_cmndinfo->wait_for_completion++;
                     else
-                        nscp->scsi_done(nscp);
+                        gdth_scsi_done(nscp);
                 } else {
                     nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
                     TRACE(("Prevent/allow r. %d rem. drive %d\n",
                            nscp->cmnd[4],nscp->cmnd[3]));
-                    if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                    if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
                         this_cmd = FALSE;
                 }
                 break;
@@ -2580,7 +2284,7 @@ static void gdth_next(int hanum)
               case RELEASE:
                 TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
                         "RESERVE" : "RELEASE"));
-                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
                     this_cmd = FALSE;
                 break;
                 
@@ -2599,11 +2303,11 @@ static void gdth_next(int hanum)
                     nscp->sense_buffer[0] = 0x70;
                     nscp->sense_buffer[2] = UNIT_ATTENTION;
                     nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-                    if (!nscp->SCp.have_data_in)
-                        nscp->SCp.have_data_in++;
+                    if (!nscp_cmndinfo->wait_for_completion)
+                        nscp_cmndinfo->wait_for_completion++;
                     else
-                        nscp->scsi_done(nscp);
-                } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                        gdth_scsi_done(nscp);
+                } else if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
                     this_cmd = FALSE;
                 break;
 
@@ -2612,12 +2316,12 @@ static void gdth_next(int hanum)
                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                         nscp->cmnd[4],nscp->cmnd[5]));
                 printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n",
-                       hanum, nscp->cmnd[0]);
+                       ha->hanum, nscp->cmnd[0]);
                 nscp->result = DID_ABORT << 16;
-                if (!nscp->SCp.have_data_in)
-                    nscp->SCp.have_data_in++;
+                if (!nscp_cmndinfo->wait_for_completion)
+                    nscp_cmndinfo->wait_for_completion++;
                 else
-                    nscp->scsi_done(nscp);
+                    gdth_scsi_done(nscp);
                 break;
             }
         }
@@ -2633,79 +2337,77 @@ static void gdth_next(int hanum)
     }
 
     if (ha->cmd_cnt > 0) {
-        gdth_release_event(hanum);
+        gdth_release_event(ha);
     }
 
     if (!gdth_polling) 
         spin_unlock_irqrestore(&ha->smp_lock, flags);
 
     if (gdth_polling && ha->cmd_cnt > 0) {
-        if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
+        if (!gdth_wait(ha, cmd_index, POLL_TIMEOUT))
             printk("GDT-HA %d: Command %d timed out !\n",
-                   hanum,cmd_index);
+                   ha->hanum, cmd_index);
     }
 }
-   
-static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
-                                    char *buffer,ushort count)
+
+/*
+ * gdth_copy_internal_data() - copy to/from a buffer onto a scsi_cmnd's
+ * buffers, kmap_atomic() as needed.
+ */
+static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
+                                    char *buffer, ushort count, int to_buffer)
 {
-    ushort cpcount,i;
+    ushort cpcount,i, max_sg = gdth_sg_count(scp);
     ushort cpsum,cpnow;
     struct scatterlist *sl;
-    gdth_ha_str *ha;
     char *address;
 
-    cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen;
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    cpcount = min_t(ushort, count, gdth_bufflen(scp));
 
-    if (scp->use_sg) {
-        sl = (struct scatterlist *)scp->request_buffer;
-        for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
+    if (cpcount) {
+        cpsum=0;
+        scsi_for_each_sg(scp, sl, max_sg, i) {
             unsigned long flags;
             cpnow = (ushort)sl->length;
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
-                          cpnow,cpsum,cpcount,(ushort)scp->bufflen));
+                          cpnow, cpsum, cpcount, gdth_bufflen(scp)));
             if (cpsum+cpnow > cpcount) 
                 cpnow = cpcount - cpsum;
             cpsum += cpnow;
             if (!sl->page) {
                 printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
-                       hanum);
+                       ha->hanum);
                 return;
             }
             local_irq_save(flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
             address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
-            memcpy(address,buffer,cpnow);
+            if (to_buffer)
+                memcpy(buffer, address, cpnow);
+            else
+                memcpy(address, buffer, cpnow);
             flush_dcache_page(sl->page);
             kunmap_atomic(address, KM_BIO_SRC_IRQ);
-#else
-            address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset;
-            memcpy(address,buffer,cpnow);
-            flush_dcache_page(sl->page);
-            kunmap_atomic(address, KM_BH_IRQ);
-#endif
             local_irq_restore(flags);
             if (cpsum == cpcount)
                 break;
             buffer += cpnow;
         }
-    } else {
-        TRACE(("copy_internal() count %d\n",cpcount));
-        memcpy((char*)scp->request_buffer,buffer,cpcount);
+    } else if (count) {
+        printk("GDT-HA %d: SCSI command with no buffers but data transfer expected!\n",
+               ha->hanum);
+        WARN_ON(1);
     }
 }
 
-static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
+static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
 {
-    register gdth_ha_str *ha;
     unchar t;
     gdth_inq_data inq;
     gdth_rdcap_data rdc;
     gdth_sense_data sd;
     gdth_modep_data mpd;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     t  = scp->device->id;
     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
            scp->cmnd[0],t));
@@ -2736,7 +2438,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         strcpy(inq.vendor,ha->oem_name);
         sprintf(inq.product,"Host Drive  #%02d",t);
         strcpy(inq.revision,"   ");
-        gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data));
+        gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0);
         break;
 
       case REQUEST_SENSE:
@@ -2746,7 +2448,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         sd.key       = NO_SENSE;
         sd.info      = 0;
         sd.add_length= 0;
-        gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data));
+        gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0);
         break;
 
       case MODE_SENSE:
@@ -2758,7 +2460,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
         mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
-        gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data));
+        gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0);
         break;
 
       case READ_CAPACITY:
@@ -2768,7 +2470,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         else
             rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
         rdc.block_length  = cpu_to_be32(SECTOR_SIZE);
-        gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
+        gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0);
         break;
 
       case SERVICE_ACTION_IN:
@@ -2779,7 +2481,8 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
             TRACE2(("Read capacity (16) hdrive %d\n",t));
             rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
             rdc16.block_length  = cpu_to_be32(SECTOR_SIZE);
-            gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data));
+            gdth_copy_internal_data(ha, scp, (char*)&rdc16,
+                                                 sizeof(gdth_rdcap16_data), 0);
         } else { 
             scp->result = DID_ABORT << 16;
         }
@@ -2790,27 +2493,22 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         break;
     }
 
-    if (!scp->SCp.have_data_in)
-        scp->SCp.have_data_in++;
+    if (!cmndinfo->wait_for_completion)
+        cmndinfo->wait_for_completion++;
     else 
         return 1;
 
     return 0;
 }
-    
-static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
+
+static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive)
 {
-    register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
-    struct scatterlist *sl;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
     ulong32 cnt, blockcnt;
     ulong64 no, blockno;
-    dma_addr_t phys_addr;
     int i, cmd_index, read_write, sgcnt, mode64;
-    struct page *page;
-    ulong offset;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
     TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
                  scp->cmnd[0],scp->cmd_len,hdrive));
@@ -2826,18 +2524,18 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
     cmdp->Service = CACHESERVICE;
     cmdp->RequestBuffer = scp;
     /* search free command index */
-    if (!(cmd_index=gdth_get_cmd_index(hanum))) {
+    if (!(cmd_index=gdth_get_cmd_index(ha))) {
         TRACE(("GDT: No free command index found\n"));
         return 0;
     }
     /* if it's the first command, set command semaphore */
     if (ha->cmd_cnt == 0)
-        gdth_set_sema0(hanum);
+        gdth_set_sema0(ha);
 
     /* fill command */
     read_write = 0;
-    if (scp->SCp.sent_command != -1) 
-        cmdp->OpCode = scp->SCp.sent_command;   /* special cache cmd. */
+    if (cmndinfo->OpCode != -1)
+        cmdp->OpCode = cmndinfo->OpCode;   /* special cache cmd. */
     else if (scp->cmnd[0] == RESERVE) 
         cmdp->OpCode = GDT_RESERVE_DRV;
     else if (scp->cmnd[0] == RELEASE)
@@ -2898,17 +2596,17 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
             cmdp->u.cache.BlockCnt = blockcnt;
         }
 
-        if (scp->use_sg) {
-            sl = (struct scatterlist *)scp->request_buffer;
-            sgcnt = scp->use_sg;
-            scp->SCp.Status = GDTH_MAP_SG;
-            scp->SCp.Message = (read_write == 1 ? 
+        if (gdth_bufflen(scp)) {
+            cmndinfo->dma_dir = (read_write == 1 ?
                 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
-            sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
+            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+                               cmndinfo->dma_dir);
             if (mode64) {
+                struct scatterlist *sl;
+
                 cmdp->u.cache64.DestAddr= (ulong64)-1;
                 cmdp->u.cache64.sg_canz = sgcnt;
-                for (i=0; i<sgcnt; ++i,++sl) {
+                scsi_for_each_sg(scp, sl, sgcnt, i) {
                     cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
                     if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
@@ -2919,9 +2617,11 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
                     cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl);
                 }
             } else {
+                struct scatterlist *sl;
+
                 cmdp->u.cache.DestAddr= 0xffffffff;
                 cmdp->u.cache.sg_canz = sgcnt;
-                for (i=0; i<sgcnt; ++i,++sl) {
+                scsi_for_each_sg(scp, sl, sgcnt, i) {
                     cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
                     ha->dma32_cnt++;
@@ -2937,38 +2637,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
             }
 #endif
 
-        } else if (scp->request_bufflen) {
-            scp->SCp.Status = GDTH_MAP_SINGLE;
-            scp->SCp.Message = (read_write == 1 ? 
-                PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-            page = virt_to_page(scp->request_buffer);
-            offset = (ulong)scp->request_buffer & ~PAGE_MASK;
-            phys_addr = pci_map_page(ha->pdev,page,offset,
-                                     scp->request_bufflen,scp->SCp.Message);
-            scp->SCp.dma_handle = phys_addr;
-            if (mode64) {
-                if (ha->cache_feat & SCATTER_GATHER) {
-                    cmdp->u.cache64.DestAddr = (ulong64)-1;
-                    cmdp->u.cache64.sg_canz = 1;
-                    cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr;
-                    cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen;
-                    cmdp->u.cache64.sg_lst[1].sg_len = 0;
-                } else {
-                    cmdp->u.cache64.DestAddr  = phys_addr;
-                    cmdp->u.cache64.sg_canz= 0;
-                }
-            } else {
-                if (ha->cache_feat & SCATTER_GATHER) {
-                    cmdp->u.cache.DestAddr = 0xffffffff;
-                    cmdp->u.cache.sg_canz = 1;
-                    cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr;
-                    cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
-                    cmdp->u.cache.sg_lst[1].sg_len = 0;
-                } else {
-                    cmdp->u.cache.DestAddr  = phys_addr;
-                    cmdp->u.cache.sg_canz= 0;
-                }
-            }
         }
     }
     /* evaluate command size, check space */
@@ -3004,23 +2672,21 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
     }
 
     /* copy command */
-    gdth_copy_command(hanum);
+    gdth_copy_command(ha);
     return cmd_index;
 }
 
-static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
+static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
 {
-    register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
-    struct scatterlist *sl;
     ushort i;
-    dma_addr_t phys_addr, sense_paddr;
+    dma_addr_t sense_paddr;
     int cmd_index, sgcnt, mode64;
     unchar t,l;
     struct page *page;
     ulong offset;
+    struct gdth_cmndinfo *cmndinfo;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     t = scp->device->id;
     l = scp->device->lun;
     cmdp = ha->pccb;
@@ -3035,26 +2701,27 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
     cmdp->Service = SCSIRAWSERVICE;
     cmdp->RequestBuffer = scp;
     /* search free command index */
-    if (!(cmd_index=gdth_get_cmd_index(hanum))) {
+    if (!(cmd_index=gdth_get_cmd_index(ha))) {
         TRACE(("GDT: No free command index found\n"));
         return 0;
     }
     /* if it's the first command, set command semaphore */
     if (ha->cmd_cnt == 0)
-        gdth_set_sema0(hanum);
+        gdth_set_sema0(ha);
 
+    cmndinfo = gdth_cmnd_priv(scp);
     /* fill command */  
-    if (scp->SCp.sent_command != -1) {
-        cmdp->OpCode           = scp->SCp.sent_command; /* special raw cmd. */
+    if (cmndinfo->OpCode != -1) {
+        cmdp->OpCode           = cmndinfo->OpCode; /* special raw cmd. */
         cmdp->BoardNode        = LOCALBOARD;
         if (mode64) {
-            cmdp->u.raw64.direction = (scp->SCp.phase >> 8);
+            cmdp->u.raw64.direction = (cmndinfo->phase >> 8);
             TRACE2(("special raw cmd 0x%x param 0x%x\n", 
                     cmdp->OpCode, cmdp->u.raw64.direction));
             /* evaluate command size */
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst);
         } else {
-            cmdp->u.raw.direction  = (scp->SCp.phase >> 8);
+            cmdp->u.raw.direction  = (cmndinfo->phase >> 8);
             TRACE2(("special raw cmd 0x%x param 0x%x\n", 
                     cmdp->OpCode, cmdp->u.raw.direction));
             /* evaluate command size */
@@ -3066,9 +2733,8 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
         offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
         sense_paddr = pci_map_page(ha->pdev,page,offset,
                                    16,PCI_DMA_FROMDEVICE);
-        *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr;
-        /* high part, if 64bit */
-        *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32);
+
+       cmndinfo->sense_paddr  = sense_paddr;
         cmdp->OpCode           = GDT_WRITE;             /* always */
         cmdp->BoardNode        = LOCALBOARD;
         if (mode64) { 
@@ -3080,7 +2746,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
             cmdp->u.raw64.lun        = l;
             cmdp->u.raw64.bus        = b;
             cmdp->u.raw64.priority   = 0;
-            cmdp->u.raw64.sdlen      = scp->request_bufflen;
+            cmdp->u.raw64.sdlen      = gdth_bufflen(scp);
             cmdp->u.raw64.sense_len  = 16;
             cmdp->u.raw64.sense_data = sense_paddr;
             cmdp->u.raw64.direction  = 
@@ -3097,7 +2763,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
             cmdp->u.raw.bus        = b;
             cmdp->u.raw.priority   = 0;
             cmdp->u.raw.link_p     = 0;
-            cmdp->u.raw.sdlen      = scp->request_bufflen;
+            cmdp->u.raw.sdlen      = gdth_bufflen(scp);
             cmdp->u.raw.sense_len  = 16;
             cmdp->u.raw.sense_data = sense_paddr;
             cmdp->u.raw.direction  = 
@@ -3106,16 +2772,16 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
             cmdp->u.raw.sg_ranz    = 0;
         }
 
-        if (scp->use_sg) {
-            sl = (struct scatterlist *)scp->request_buffer;
-            sgcnt = scp->use_sg;
-            scp->SCp.Status = GDTH_MAP_SG;
-            scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
-            sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
+        if (gdth_bufflen(scp)) {
+            cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL;
+            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+                               cmndinfo->dma_dir);
             if (mode64) {
+                struct scatterlist *sl;
+
                 cmdp->u.raw64.sdata = (ulong64)-1;
                 cmdp->u.raw64.sg_ranz = sgcnt;
-                for (i=0; i<sgcnt; ++i,++sl) {
+                scsi_for_each_sg(scp, sl, sgcnt, i) {
                     cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
                     if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
@@ -3126,9 +2792,11 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
                     cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl);
                 }
             } else {
+                struct scatterlist *sl;
+
                 cmdp->u.raw.sdata = 0xffffffff;
                 cmdp->u.raw.sg_ranz = sgcnt;
-                for (i=0; i<sgcnt; ++i,++sl) {
+                scsi_for_each_sg(scp, sl, sgcnt, i) {
                     cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
                     ha->dma32_cnt++;
@@ -3144,38 +2812,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
             }
 #endif
 
-        } else if (scp->request_bufflen) {
-            scp->SCp.Status = GDTH_MAP_SINGLE;
-            scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
-            page = virt_to_page(scp->request_buffer);
-            offset = (ulong)scp->request_buffer & ~PAGE_MASK;
-            phys_addr = pci_map_page(ha->pdev,page,offset,
-                                     scp->request_bufflen,scp->SCp.Message);
-            scp->SCp.dma_handle = phys_addr;
-
-            if (mode64) {
-                if (ha->raw_feat & SCATTER_GATHER) {
-                    cmdp->u.raw64.sdata  = (ulong64)-1;
-                    cmdp->u.raw64.sg_ranz= 1;
-                    cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr;
-                    cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen;
-                    cmdp->u.raw64.sg_lst[1].sg_len = 0;
-                } else {
-                    cmdp->u.raw64.sdata  = phys_addr;
-                    cmdp->u.raw64.sg_ranz= 0;
-                }
-            } else {
-                if (ha->raw_feat & SCATTER_GATHER) {
-                    cmdp->u.raw.sdata  = 0xffffffff;
-                    cmdp->u.raw.sg_ranz= 1;
-                    cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr;
-                    cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
-                    cmdp->u.raw.sg_lst[1].sg_len = 0;
-                } else {
-                    cmdp->u.raw.sdata  = phys_addr;
-                    cmdp->u.raw.sg_ranz= 0;
-                }
-            }
         }
         if (mode64) {
             TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
@@ -3209,35 +2845,33 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
     }
 
     /* copy command */
-    gdth_copy_command(hanum);
+    gdth_copy_command(ha);
     return cmd_index;
 }
 
-static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
+static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
 {
-    register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
     int cmd_index;
 
-    ha  = HADATA(gdth_ctr_tab[hanum]);
     cmdp= ha->pccb;
     TRACE2(("gdth_special_cmd(): "));
 
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
         return 0;
 
-    memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str));
+    gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1);
     cmdp->RequestBuffer = scp;
 
     /* search free command index */
-    if (!(cmd_index=gdth_get_cmd_index(hanum))) {
+    if (!(cmd_index=gdth_get_cmd_index(ha))) {
         TRACE(("GDT: No free command index found\n"));
         return 0;
     }
 
     /* if it's the first command, set command semaphore */
     if (ha->cmd_cnt == 0)
-       gdth_set_sema0(hanum);
+       gdth_set_sema0(ha);
 
     /* evaluate command size, check space */
     if (cmdp->OpCode == GDT_IOCTL) {
@@ -3275,7 +2909,7 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
     }
 
     /* copy command */
-    gdth_copy_command(hanum);
+    gdth_copy_command(ha);
     return cmd_index;
 }    
 
@@ -3402,15 +3036,14 @@ static void gdth_clear_events(void)
 
 /* SCSI interface functions */
 
-static irqreturn_t gdth_interrupt(int irq,void *dev_id)
+static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq,
+                                    int gdth_from_wait, int* pIndex)
 {
-    gdth_ha_str *ha2 = (gdth_ha_str *)dev_id;
-    register gdth_ha_str *ha;
     gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
     gdt6_dpram_str __iomem *dp6_ptr;
     gdt2_dpram_str __iomem *dp2_ptr;
     Scsi_Cmnd *scp;
-    int hanum, rval, i;
+    int rval, i;
     unchar IStatus;
     ushort Service;
     ulong flags = 0;
@@ -3431,17 +3064,15 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
     }
 
     if (!gdth_polling)
-        spin_lock_irqsave(&ha2->smp_lock, flags);
-    wait_index = 0;
+        spin_lock_irqsave(&ha->smp_lock, flags);
 
     /* search controller */
-    if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
+    if (0 == (IStatus = gdth_get_status(ha, irq))) {
         /* spurious interrupt */
         if (!gdth_polling)
-            spin_unlock_irqrestore(&ha2->smp_lock, flags);
-            return IRQ_HANDLED;
+            spin_unlock_irqrestore(&ha->smp_lock, flags);
+        return IRQ_HANDLED;
     }
-    ha = HADATA(gdth_ctr_tab[hanum]);
 
 #ifdef GDTH_STATISTICS
     ++act_ints;
@@ -3482,32 +3113,32 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
             dp2_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
-                ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
+                ha->status = readw(&dp2_ptr->u.ic.Status);
                 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
             } else                                      /* no error */
                 ha->status = S_OK;
-            ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]);
-            ha->service = gdth_readw(&dp2_ptr->u.ic.Service);
-            ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
+            ha->info = readl(&dp2_ptr->u.ic.Info[0]);
+            ha->service = readw(&dp2_ptr->u.ic.Service);
+            ha->info2 = readl(&dp2_ptr->u.ic.Info[1]);
 
-            gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
-            gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */
-            gdth_writeb(0, &dp2_ptr->io.Sema1);     /* reset status semaphore */
+            writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
+            writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */
+            writeb(0, &dp2_ptr->io.Sema1);     /* reset status semaphore */
         } else if (ha->type == GDT_PCI) {
             dp6_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
-                ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
+                ha->status = readw(&dp6_ptr->u.ic.Status);
                 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
             } else                                      /* no error */
                 ha->status = S_OK;
-            ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]);
-            ha->service = gdth_readw(&dp6_ptr->u.ic.Service);
-            ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
+            ha->info = readl(&dp6_ptr->u.ic.Info[0]);
+            ha->service = readw(&dp6_ptr->u.ic.Service);
+            ha->info2 = readl(&dp6_ptr->u.ic.Info[1]);
 
-            gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
-            gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */
-            gdth_writeb(0, &dp6_ptr->io.Sema1);     /* reset status semaphore */
+            writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
+            writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */
+            writeb(0, &dp6_ptr->io.Sema1);     /* reset status semaphore */
         } else if (ha->type == GDT_PCINEW) {
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
@@ -3530,7 +3161,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
                     ha->status = pcs->ext_status & 0xffff;
                 else 
 #endif
-                    ha->status = gdth_readw(&dp6m_ptr->i960r.status);
+                    ha->status = readw(&dp6m_ptr->i960r.status);
                 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
             } else                                      /* no error */
                 ha->status = S_OK;
@@ -3543,18 +3174,18 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
             } else
 #endif
             {
-                ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]);
-                ha->service = gdth_readw(&dp6m_ptr->i960r.service);
-                ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+                ha->info = readl(&dp6m_ptr->i960r.info[0]);
+                ha->service = readw(&dp6m_ptr->i960r.service);
+                ha->info2 = readl(&dp6m_ptr->i960r.info[1]);
             }
             /* event string */
             if (IStatus == ASYNCINDEX) {
                 if (ha->service != SCREENSERVICE &&
                     (ha->fw_vers & 0xff) >= 0x1a) {
-                    ha->dvr.severity = gdth_readb
+                    ha->dvr.severity = readb
                         (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity);
                     for (i = 0; i < 256; ++i) {
-                        ha->dvr.event_string[i] = gdth_readb
+                        ha->dvr.event_string[i] = readb
                             (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]);
                         if (ha->dvr.event_string[i] == 0)
                             break;
@@ -3567,13 +3198,13 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
             if (!coalesced)
 #endif                          
             {
-                gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-                gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
+                writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+                writeb(0, &dp6m_ptr->i960r.sema1_reg);
             }
         } else {
             TRACE2(("gdth_interrupt() unknown controller type\n"));
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
         }
 
@@ -3581,26 +3212,25 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
                IStatus,ha->status,ha->info));
 
         if (gdth_from_wait) {
-            wait_hanum = hanum;
-            wait_index = (int)IStatus;
+            *pIndex = (int)IStatus;
         }
 
         if (IStatus == ASYNCINDEX) {
             TRACE2(("gdth_interrupt() async. event\n"));
-            gdth_async_event(hanum);
+            gdth_async_event(ha);
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
-            gdth_next(hanum);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
+            gdth_next(ha);
             return IRQ_HANDLED;
         } 
 
         if (IStatus == SPEZINDEX) {
             TRACE2(("Service unknown or not initialized !\n"));
             ha->dvr.size = sizeof(ha->dvr.eu.driver);
-            ha->dvr.eu.driver.ionode = hanum;
+            ha->dvr.eu.driver.ionode = ha->hanum;
             gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
         }
         scp     = ha->cmd_tab[IStatus-2].cmnd;
@@ -3609,28 +3239,28 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
         if (scp == UNUSED_CMND) {
             TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
             ha->dvr.size = sizeof(ha->dvr.eu.driver);
-            ha->dvr.eu.driver.ionode = hanum;
+            ha->dvr.eu.driver.ionode = ha->hanum;
             ha->dvr.eu.driver.index = IStatus;
             gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
         }
         if (scp == INTERNAL_CMND) {
             TRACE(("gdth_interrupt() answer to internal command\n"));
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
         }
 
         TRACE(("gdth_interrupt() sync. status\n"));
-        rval = gdth_sync_event(hanum,Service,IStatus,scp);
+        rval = gdth_sync_event(ha,Service,IStatus,scp);
         if (!gdth_polling)
-            spin_unlock_irqrestore(&ha2->smp_lock, flags);
+            spin_unlock_irqrestore(&ha->smp_lock, flags);
         if (rval == 2) {
-            gdth_putq(hanum,scp,scp->SCp.this_residual);
+            gdth_putq(ha, scp, gdth_cmnd_priv(scp)->priority);
         } else if (rval == 1) {
-            scp->scsi_done(scp);
+            gdth_scsi_done(scp);
         }
 
 #ifdef INT_COAL
@@ -3653,23 +3283,30 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
 
     /* coalescing only for new GDT_PCIMPR controllers available */      
     if (ha->type == GDT_PCIMPR && coalesced) {
-        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
+        writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        writeb(0, &dp6m_ptr->i960r.sema1_reg);
     }
 #endif
 
-    gdth_next(hanum);
+    gdth_next(ha);
     return IRQ_HANDLED;
 }
 
-static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
+static irqreturn_t gdth_interrupt(int irq, void *dev_id)
+{
+       gdth_ha_str *ha = (gdth_ha_str *)dev_id;
+
+       return __gdth_interrupt(ha, irq, false, NULL);
+}
+
+static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
+                                                              Scsi_Cmnd *scp)
 {
-    register gdth_ha_str *ha;
     gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
     unchar b, t;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
 
-    ha   = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
     TRACE(("gdth_sync_event() serv %d status %d\n",
            service,ha->status));
@@ -3687,12 +3324,12 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
             }
 
         if (msg->msg_ext && !msg->msg_answer) {
-            while (gdth_test_busy(hanum))
+            while (gdth_test_busy(ha))
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
-            gdth_get_cmd_index(hanum);
-            gdth_set_sema0(hanum);
+            gdth_get_cmd_index(ha);
+            gdth_set_sema0(ha);
             cmdp->OpCode        = GDT_READ;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
@@ -3702,8 +3339,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong64);
             ha->cmd_cnt = 0;
-            gdth_copy_command(hanum);
-            gdth_release_event(hanum);
+            gdth_copy_command(ha);
+            gdth_release_event(ha);
             return 0;
         }
 
@@ -3721,12 +3358,12 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
             }
             msg->msg_ext    = 0;
             msg->msg_answer = 0;
-            while (gdth_test_busy(hanum))
+            while (gdth_test_busy(ha))
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
-            gdth_get_cmd_index(hanum);
-            gdth_set_sema0(hanum);
+            gdth_get_cmd_index(ha);
+            gdth_set_sema0(ha);
             cmdp->OpCode        = GDT_WRITE;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
@@ -3736,74 +3373,67 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong64);
             ha->cmd_cnt = 0;
-            gdth_copy_command(hanum);
-            gdth_release_event(hanum);
+            gdth_copy_command(ha);
+            gdth_release_event(ha);
             return 0;
         }
         printk("\n");
 
     } else {
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        b = scp->device->channel;
         t = scp->device->id;
-        if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
+        if (cmndinfo->OpCode == -1 && b != ha->virt_bus) {
             ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
         }
         /* cache or raw service */
         if (ha->status == S_BSY) {
             TRACE2(("Controller busy -> retry !\n"));
-            if (scp->SCp.sent_command == GDT_MOUNT)
-                scp->SCp.sent_command = GDT_CLUST_INFO;
+            if (cmndinfo->OpCode == GDT_MOUNT)
+                cmndinfo->OpCode = GDT_CLUST_INFO;
             /* retry */
             return 2;
         }
-        if (scp->SCp.Status == GDTH_MAP_SG) 
-            pci_unmap_sg(ha->pdev,scp->request_buffer,
-                         scp->use_sg,scp->SCp.Message);
-        else if (scp->SCp.Status == GDTH_MAP_SINGLE) 
-            pci_unmap_page(ha->pdev,scp->SCp.dma_handle,
-                           scp->request_bufflen,scp->SCp.Message);
-        if (scp->SCp.buffer) {
-            dma_addr_t addr;
-            addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer;
-            if (scp->host_scribble)
-                addr += (dma_addr_t)
-                    ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32);
-            pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
-        }
+        if (gdth_bufflen(scp))
+            pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+                         cmndinfo->dma_dir);
+
+        if (cmndinfo->sense_paddr)
+            pci_unmap_page(ha->pdev, cmndinfo->sense_paddr, 16,
+                                                           PCI_DMA_FROMDEVICE);
 
         if (ha->status == S_OK) {
-            scp->SCp.Status = S_OK;
-            scp->SCp.Message = ha->info;
-            if (scp->SCp.sent_command != -1) {
+            cmndinfo->status = S_OK;
+            cmndinfo->info = ha->info;
+            if (cmndinfo->OpCode != -1) {
                 TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
-                        scp->SCp.sent_command));
+                        cmndinfo->OpCode));
                 /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
-                if (scp->SCp.sent_command == GDT_CLUST_INFO) {
+                if (cmndinfo->OpCode == GDT_CLUST_INFO) {
                     ha->hdr[t].cluster_type = (unchar)ha->info;
                     if (!(ha->hdr[t].cluster_type & 
                         CLUSTER_MOUNTED)) {
                         /* NOT MOUNTED -> MOUNT */
-                        scp->SCp.sent_command = GDT_MOUNT;
+                        cmndinfo->OpCode = GDT_MOUNT;
                         if (ha->hdr[t].cluster_type & 
                             CLUSTER_RESERVED) {
                             /* cluster drive RESERVED (on the other node) */
-                            scp->SCp.phase = -2;      /* reservation conflict */
+                            cmndinfo->phase = -2;      /* reservation conflict */
                         }
                     } else {
-                        scp->SCp.sent_command = -1;
+                        cmndinfo->OpCode = -1;
                     }
                 } else {
-                    if (scp->SCp.sent_command == GDT_MOUNT) {
+                    if (cmndinfo->OpCode == GDT_MOUNT) {
                         ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
                         ha->hdr[t].media_changed = TRUE;
-                    } else if (scp->SCp.sent_command == GDT_UNMOUNT) {
+                    } else if (cmndinfo->OpCode == GDT_UNMOUNT) {
                         ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
                         ha->hdr[t].media_changed = TRUE;
                     } 
-                    scp->SCp.sent_command = -1;
+                    cmndinfo->OpCode = -1;
                 }
                 /* retry */
-                scp->SCp.this_residual = HIGH_PRI;
+                cmndinfo->priority = HIGH_PRI;
                 return 2;
             } else {
                 /* RESERVE/RELEASE ? */
@@ -3816,17 +3446,17 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                 scp->sense_buffer[0] = 0;
             }
         } else {
-            scp->SCp.Status = ha->status;
-            scp->SCp.Message = ha->info;
+            cmndinfo->status = ha->status;
+            cmndinfo->info = ha->info;
 
-            if (scp->SCp.sent_command != -1) {
+            if (cmndinfo->OpCode != -1) {
                 TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
-                        scp->SCp.sent_command, ha->status));
-                if (scp->SCp.sent_command == GDT_SCAN_START ||
-                    scp->SCp.sent_command == GDT_SCAN_END) {
-                    scp->SCp.sent_command = -1;
+                        cmndinfo->OpCode, ha->status));
+                if (cmndinfo->OpCode == GDT_SCAN_START ||
+                    cmndinfo->OpCode == GDT_SCAN_END) {
+                    cmndinfo->OpCode = -1;
                     /* retry */
-                    scp->SCp.this_residual = HIGH_PRI;
+                    cmndinfo->priority = HIGH_PRI;
                     return 2;
                 }
                 memset((char*)scp->sense_buffer,0,16);
@@ -3848,9 +3478,9 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                     scp->sense_buffer[2] = NOT_READY;
                     scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                 }
-                if (scp->done != gdth_scsi_done) {
+                if (!cmndinfo->internal_command) {
                     ha->dvr.size = sizeof(ha->dvr.eu.sync);
-                    ha->dvr.eu.sync.ionode  = hanum;
+                    ha->dvr.eu.sync.ionode  = ha->hanum;
                     ha->dvr.eu.sync.service = service;
                     ha->dvr.eu.sync.status  = ha->status;
                     ha->dvr.eu.sync.info    = ha->info;
@@ -3869,8 +3499,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                 }
             }
         }
-        if (!scp->SCp.have_data_in)
-            scp->SCp.have_data_in++;
+        if (!cmndinfo->wait_for_completion)
+            cmndinfo->wait_for_completion++;
         else 
             return 1;
     }
@@ -4034,25 +3664,23 @@ static char *async_cache_tab[] = {
 };
 
 
-static int gdth_async_event(int hanum)
+static int gdth_async_event(gdth_ha_str *ha)
 {
-    gdth_ha_str *ha;
     gdth_cmd_str *cmdp;
     int cmd_index;
 
-    ha  = HADATA(gdth_ctr_tab[hanum]);
     cmdp= ha->pccb;
     TRACE2(("gdth_async_event() ha %d serv %d\n",
-            hanum,ha->service));
+            ha->hanum, ha->service));
 
     if (ha->service == SCREENSERVICE) {
         if (ha->status == MSG_REQUEST) {
-            while (gdth_test_busy(hanum))
+            while (gdth_test_busy(ha))
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
-            cmd_index = gdth_get_cmd_index(hanum);
-            gdth_set_sema0(hanum);
+            cmd_index = gdth_get_cmd_index(ha);
+            gdth_set_sema0(ha);
             cmdp->OpCode        = GDT_READ;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
@@ -4062,7 +3690,7 @@ static int gdth_async_event(int hanum)
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong64);
             ha->cmd_cnt = 0;
-            gdth_copy_command(hanum);
+            gdth_copy_command(ha);
             if (ha->type == GDT_EISA)
                 printk("[EISA slot %d] ",(ushort)ha->brd_phys);
             else if (ha->type == GDT_ISA)
@@ -4070,19 +3698,19 @@ static int gdth_async_event(int hanum)
             else 
                 printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
                        (ushort)((ha->brd_phys>>3)&0x1f));
-            gdth_release_event(hanum);
+            gdth_release_event(ha);
         }
 
     } else {
         if (ha->type == GDT_PCIMPR && 
             (ha->fw_vers & 0xff) >= 0x1a) {
             ha->dvr.size = 0;
-            ha->dvr.eu.async.ionode = hanum;
+            ha->dvr.eu.async.ionode = ha->hanum;
             ha->dvr.eu.async.status  = ha->status;
             /* severity and event_string already set! */
         } else {        
             ha->dvr.size = sizeof(ha->dvr.eu.async);
-            ha->dvr.eu.async.ionode   = hanum;
+            ha->dvr.eu.async.ionode   = ha->hanum;
             ha->dvr.eu.async.service = ha->service;
             ha->dvr.eu.async.status  = ha->status;
             ha->dvr.eu.async.info    = ha->info;
@@ -4164,9 +3792,8 @@ static void gdth_timeout(ulong data)
     Scsi_Cmnd *nscp;
     gdth_ha_str *ha;
     ulong flags;
-    int hanum = 0;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i) 
@@ -4229,8 +3856,6 @@ static void __init internal_setup(char *str,int *ints)
             max_ids = val;
         else if (!strncmp(argv, "rescan:", 7))
             rescan = val;
-        else if (!strncmp(argv, "virt_ctr:", 9))
-            virt_ctr = val;
         else if (!strncmp(argv, "shared_access:", 14))
             shared_access = val;
         else if (!strncmp(argv, "probe_eisa_isa:", 15))
@@ -4277,523 +3902,10 @@ int __init option_setup(char *str)
     return 1;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static int __init gdth_detect(struct scsi_host_template *shtp)
-#else
-static int __init gdth_detect(Scsi_Host_Template *shtp)
-#endif
-{
-    struct Scsi_Host *shp;
-    gdth_pci_str pcistr[MAXHA];
-    gdth_ha_str *ha;
-    ulong32 isa_bios;
-    ushort eisa_slot;
-    int i,hanum,cnt,ctr,err;
-    unchar b;
-    
-#ifdef DEBUG_GDTH
-    printk("GDT: This driver contains debugging information !! Trace level = %d\n",
-        DebugState);
-    printk("     Destination of debugging information: ");
-#ifdef __SERIAL__
-#ifdef __COM2__
-    printk("Serial port COM2\n");
-#else
-    printk("Serial port COM1\n");
-#endif
-#else
-    printk("Console\n");
-#endif
-    gdth_delay(3000);
-#endif
-
-    TRACE(("gdth_detect()\n"));
-
-    if (disable) {
-        printk("GDT-HA: Controller driver disabled from command line !\n");
-        return 0;
-    }
-
-    printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR);
-    /* initializations */
-    gdth_polling = TRUE; b = 0;
-    gdth_clear_events();
-
-    /* As default we do not probe for EISA or ISA controllers */
-    if (probe_eisa_isa) {    
-        /* scanning for controllers, at first: ISA controller */
-        for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
-            dma_addr_t scratch_dma_handle;
-            scratch_dma_handle = 0;
-
-            if (gdth_ctr_count >= MAXHA) 
-                break;
-            if (gdth_search_isa(isa_bios)) {        /* controller found */
-                shp = scsi_register(shtp,sizeof(gdth_ext_str));
-                if (shp == NULL)
-                    continue;  
-
-                ha = HADATA(shp);
-                if (!gdth_init_isa(isa_bios,ha)) {
-                    scsi_unregister(shp);
-                    continue;
-                }
-#ifdef __ia64__
-                break;
-#else
-                /* controller found and initialized */
-                printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
-                       isa_bios,ha->irq,ha->drq);
-
-                if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) {
-                    printk("GDT-ISA: Unable to allocate IRQ\n");
-                    scsi_unregister(shp);
-                    continue;
-                }
-                if (request_dma(ha->drq,"gdth")) {
-                    printk("GDT-ISA: Unable to allocate DMA channel\n");
-                    free_irq(ha->irq,ha);
-                    scsi_unregister(shp);
-                    continue;
-                }
-                set_dma_mode(ha->drq,DMA_MODE_CASCADE);
-                enable_dma(ha->drq);
-                shp->unchecked_isa_dma = 1;
-                shp->irq = ha->irq;
-                shp->dma_channel = ha->drq;
-                hanum = gdth_ctr_count;         
-                gdth_ctr_tab[gdth_ctr_count++] = shp;
-                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-
-                NUMDATA(shp)->hanum = (ushort)hanum;
-                NUMDATA(shp)->busnum= 0;
-
-                ha->pccb = CMDDATA(shp);
-                ha->ccb_phys = 0L;
-                ha->pdev = NULL;
-                ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
-                                                    &scratch_dma_handle);
-                ha->scratch_phys = scratch_dma_handle;
-                ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                                &scratch_dma_handle);
-                ha->msg_phys = scratch_dma_handle;
-#ifdef INT_COAL
-                ha->coal_stat = (gdth_coal_status *)
-                    pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                        MAXOFFSETS, &scratch_dma_handle);
-                ha->coal_stat_phys = scratch_dma_handle;
-#endif
-
-                ha->scratch_busy = FALSE;
-                ha->req_first = NULL;
-                ha->tid_cnt = MAX_HDRIVES;
-                if (max_ids > 0 && max_ids < ha->tid_cnt)
-                    ha->tid_cnt = max_ids;
-                for (i=0; i<GDTH_MAXCMDS; ++i)
-                    ha->cmd_tab[i].cmnd = UNUSED_CMND;
-                ha->scan_mode = rescan ? 0x10 : 0;
-
-                if (ha->pscratch == NULL || ha->pmsg == NULL || 
-                    !gdth_search_drives(hanum)) {
-                    printk("GDT-ISA: Error during device scan\n");
-                    --gdth_ctr_count;
-                    --gdth_ctr_vcount;
-
-#ifdef INT_COAL
-                    if (ha->coal_stat)
-                        pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                                            MAXOFFSETS, ha->coal_stat,
-                                            ha->coal_stat_phys);
-#endif
-                    if (ha->pscratch)
-                        pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
-                                            ha->pscratch, ha->scratch_phys);
-                    if (ha->pmsg)
-                        pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                            ha->pmsg, ha->msg_phys);
-
-                    free_irq(ha->irq,ha);
-                    scsi_unregister(shp);
-                    continue;
-                }
-                if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
-                    hdr_channel = ha->bus_cnt;
-                ha->virt_bus = hdr_channel;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
-    LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-                shp->highmem_io  = 0;
-#endif
-                if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) 
-                    shp->max_cmd_len = 16;
-
-                shp->max_id      = ha->tid_cnt;
-                shp->max_lun     = MAXLUN;
-                shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
-                if (virt_ctr) {
-                    virt_ctr = 1;
-                    /* register addit. SCSI channels as virtual controllers */
-                    for (b = 1; b < ha->bus_cnt + 1; ++b) {
-                        shp = scsi_register(shtp,sizeof(gdth_num_str));
-                        shp->unchecked_isa_dma = 1;
-                        shp->irq = ha->irq;
-                        shp->dma_channel = ha->drq;
-                        gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                        NUMDATA(shp)->hanum = (ushort)hanum;
-                        NUMDATA(shp)->busnum = b;
-                    }
-                }  
-
-                spin_lock_init(&ha->smp_lock);
-                gdth_enable_int(hanum);
-#endif /* !__ia64__ */
-            }
-        }
-
-        /* scanning for EISA controllers */
-        for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
-            dma_addr_t scratch_dma_handle;
-            scratch_dma_handle = 0;
-
-            if (gdth_ctr_count >= MAXHA) 
-                break;
-            if (gdth_search_eisa(eisa_slot)) {      /* controller found */
-                shp = scsi_register(shtp,sizeof(gdth_ext_str));
-                if (shp == NULL)
-                    continue;  
-
-                ha = HADATA(shp);
-                if (!gdth_init_eisa(eisa_slot,ha)) {
-                    scsi_unregister(shp);
-                    continue;
-                }
-                /* controller found and initialized */
-                printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
-                       eisa_slot>>12,ha->irq);
-
-                if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) {
-                    printk("GDT-EISA: Unable to allocate IRQ\n");
-                    scsi_unregister(shp);
-                    continue;
-                }
-                shp->unchecked_isa_dma = 0;
-                shp->irq = ha->irq;
-                shp->dma_channel = 0xff;
-                hanum = gdth_ctr_count;
-                gdth_ctr_tab[gdth_ctr_count++] = shp;
-                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-
-                NUMDATA(shp)->hanum = (ushort)hanum;
-                NUMDATA(shp)->busnum= 0;
-                TRACE2(("EISA detect Bus 0: hanum %d\n",
-                        NUMDATA(shp)->hanum));
-
-                ha->pccb = CMDDATA(shp);
-                ha->ccb_phys = 0L; 
-
-                ha->pdev = NULL;
-                ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
-                                                    &scratch_dma_handle);
-                ha->scratch_phys = scratch_dma_handle;
-                ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                                &scratch_dma_handle);
-                ha->msg_phys = scratch_dma_handle;
-#ifdef INT_COAL
-                ha->coal_stat = (gdth_coal_status *)
-                    pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                                         MAXOFFSETS, &scratch_dma_handle);
-                ha->coal_stat_phys = scratch_dma_handle;
-#endif
-                ha->ccb_phys = 
-                    pci_map_single(ha->pdev,ha->pccb,
-                                   sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-                ha->scratch_busy = FALSE;
-                ha->req_first = NULL;
-                ha->tid_cnt = MAX_HDRIVES;
-                if (max_ids > 0 && max_ids < ha->tid_cnt)
-                    ha->tid_cnt = max_ids;
-                for (i=0; i<GDTH_MAXCMDS; ++i)
-                    ha->cmd_tab[i].cmnd = UNUSED_CMND;
-                ha->scan_mode = rescan ? 0x10 : 0;
-
-                if (ha->pscratch == NULL || ha->pmsg == NULL || 
-                    !gdth_search_drives(hanum)) {
-                    printk("GDT-EISA: Error during device scan\n");
-                    --gdth_ctr_count;
-                    --gdth_ctr_vcount;
-#ifdef INT_COAL
-                    if (ha->coal_stat)
-                        pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                                            MAXOFFSETS, ha->coal_stat,
-                                            ha->coal_stat_phys);
-#endif
-                    if (ha->pscratch)
-                        pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
-                                            ha->pscratch, ha->scratch_phys);
-                    if (ha->pmsg)
-                        pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                            ha->pmsg, ha->msg_phys);
-                    if (ha->ccb_phys)
-                        pci_unmap_single(ha->pdev,ha->ccb_phys,
-                                        sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-                    free_irq(ha->irq,ha);
-                    scsi_unregister(shp);
-                    continue;
-                }
-                if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
-                    hdr_channel = ha->bus_cnt;
-                ha->virt_bus = hdr_channel;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
-    LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-                shp->highmem_io  = 0;
-#endif
-                if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) 
-                    shp->max_cmd_len = 16;
-
-                shp->max_id      = ha->tid_cnt;
-                shp->max_lun     = MAXLUN;
-                shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
-                if (virt_ctr) {
-                    virt_ctr = 1;
-                    /* register addit. SCSI channels as virtual controllers */
-                    for (b = 1; b < ha->bus_cnt + 1; ++b) {
-                        shp = scsi_register(shtp,sizeof(gdth_num_str));
-                        shp->unchecked_isa_dma = 0;
-                        shp->irq = ha->irq;
-                        shp->dma_channel = 0xff;
-                        gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                        NUMDATA(shp)->hanum = (ushort)hanum;
-                        NUMDATA(shp)->busnum = b;
-                    }
-                }  
-
-                spin_lock_init(&ha->smp_lock);
-                gdth_enable_int(hanum);
-            }
-        }
-    }
-
-    /* scanning for PCI controllers */
-    cnt = gdth_search_pci(pcistr);
-    printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt);
-    gdth_sort_pci(pcistr,cnt);
-    for (ctr = 0; ctr < cnt; ++ctr) {
-        dma_addr_t scratch_dma_handle;
-        scratch_dma_handle = 0;
-
-        if (gdth_ctr_count >= MAXHA)
-            break;
-        shp = scsi_register(shtp,sizeof(gdth_ext_str));
-        if (shp == NULL)
-            continue;  
-
-        ha = HADATA(shp);
-        if (!gdth_init_pci(&pcistr[ctr],ha)) {
-            scsi_unregister(shp);
-            continue;
-        }
-        /* controller found and initialized */
-        printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
-               pcistr[ctr].pdev->bus->number,
-              PCI_SLOT(pcistr[ctr].pdev->devfn), ha->irq);
-
-        if (request_irq(ha->irq, gdth_interrupt,
-                        IRQF_DISABLED|IRQF_SHARED, "gdth", ha))
-        {
-            printk("GDT-PCI: Unable to allocate IRQ\n");
-            scsi_unregister(shp);
-            continue;
-        }
-        shp->unchecked_isa_dma = 0;
-        shp->irq = ha->irq;
-        shp->dma_channel = 0xff;
-        hanum = gdth_ctr_count;
-        gdth_ctr_tab[gdth_ctr_count++] = shp;
-        gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-
-        NUMDATA(shp)->hanum = (ushort)hanum;
-        NUMDATA(shp)->busnum= 0;
-
-        ha->pccb = CMDDATA(shp);
-        ha->ccb_phys = 0L;
-
-        ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
-                                            &scratch_dma_handle);
-        ha->scratch_phys = scratch_dma_handle;
-        ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                        &scratch_dma_handle);
-        ha->msg_phys = scratch_dma_handle;
-#ifdef INT_COAL
-        ha->coal_stat = (gdth_coal_status *)
-            pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                                 MAXOFFSETS, &scratch_dma_handle);
-        ha->coal_stat_phys = scratch_dma_handle;
-#endif
-        ha->scratch_busy = FALSE;
-        ha->req_first = NULL;
-        ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
-        if (max_ids > 0 && max_ids < ha->tid_cnt)
-            ha->tid_cnt = max_ids;
-        for (i=0; i<GDTH_MAXCMDS; ++i)
-            ha->cmd_tab[i].cmnd = UNUSED_CMND;
-        ha->scan_mode = rescan ? 0x10 : 0;
-
-        err = FALSE;
-        if (ha->pscratch == NULL || ha->pmsg == NULL || 
-            !gdth_search_drives(hanum)) {
-            err = TRUE;
-        } else {
-            if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
-                hdr_channel = ha->bus_cnt;
-            ha->virt_bus = hdr_channel;
-
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-            scsi_set_pci_device(shp, pcistr[ctr].pdev);
-#endif
-            if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)||
-                /* 64-bit DMA only supported from FW >= x.43 */
-                (!ha->dma64_support)) {
-                if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
-                    printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum);
-                    err = TRUE;
-                }
-            } else {
-                shp->max_cmd_len = 16;
-                if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
-                    printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum);
-                } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
-                    printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum);
-                    err = TRUE;
-                }
-            }
-        }
-
-        if (err) {
-            printk("GDT-PCI %d: Error during device scan\n", hanum);
-            --gdth_ctr_count;
-            --gdth_ctr_vcount;
-#ifdef INT_COAL
-            if (ha->coal_stat)
-                pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                                    MAXOFFSETS, ha->coal_stat,
-                                    ha->coal_stat_phys);
-#endif
-            if (ha->pscratch)
-                pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
-                                    ha->pscratch, ha->scratch_phys);
-            if (ha->pmsg)
-                pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                    ha->pmsg, ha->msg_phys);
-            free_irq(ha->irq,ha);
-            scsi_unregister(shp);
-            continue;
-        }
-
-        shp->max_id      = ha->tid_cnt;
-        shp->max_lun     = MAXLUN;
-        shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
-        if (virt_ctr) {
-            virt_ctr = 1;
-            /* register addit. SCSI channels as virtual controllers */
-            for (b = 1; b < ha->bus_cnt + 1; ++b) {
-                shp = scsi_register(shtp,sizeof(gdth_num_str));
-                shp->unchecked_isa_dma = 0;
-                shp->irq = ha->irq;
-                shp->dma_channel = 0xff;
-                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                NUMDATA(shp)->hanum = (ushort)hanum;
-                NUMDATA(shp)->busnum = b;
-            }
-        }  
-
-        spin_lock_init(&ha->smp_lock);
-        gdth_enable_int(hanum);
-    }
-    
-    TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
-    if (gdth_ctr_count > 0) {
-#ifdef GDTH_STATISTICS
-        TRACE2(("gdth_detect(): Initializing timer !\n"));
-        init_timer(&gdth_timer);
-        gdth_timer.expires = jiffies + HZ;
-        gdth_timer.data = 0L;
-        gdth_timer.function = gdth_timeout;
-        add_timer(&gdth_timer);
-#endif
-        major = register_chrdev(0,"gdth",&gdth_fops);
-        notifier_disabled = 0;
-        register_reboot_notifier(&gdth_notifier);
-    }
-    gdth_polling = FALSE;
-    return gdth_ctr_vcount;
-}
-
-static int gdth_release(struct Scsi_Host *shp)
+static const char *gdth_ctr_name(gdth_ha_str *ha)
 {
-    int hanum;
-    gdth_ha_str *ha;
-
-    TRACE2(("gdth_release()\n"));
-    if (NUMDATA(shp)->busnum == 0) {
-        hanum = NUMDATA(shp)->hanum;
-        ha    = HADATA(gdth_ctr_tab[hanum]);
-        if (ha->sdev) {
-            scsi_free_host_dev(ha->sdev);
-            ha->sdev = NULL;
-        }
-        gdth_flush(hanum);
-
-        if (shp->irq) {
-            free_irq(shp->irq,ha);
-        }
-#ifndef __ia64__
-        if (shp->dma_channel != 0xff) {
-            free_dma(shp->dma_channel);
-        }
-#endif
-#ifdef INT_COAL
-        if (ha->coal_stat)
-            pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
-                                MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys);
-#endif
-        if (ha->pscratch)
-            pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
-                                ha->pscratch, ha->scratch_phys);
-        if (ha->pmsg)
-            pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
-                                ha->pmsg, ha->msg_phys);
-        if (ha->ccb_phys)
-            pci_unmap_single(ha->pdev,ha->ccb_phys,
-                             sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-        gdth_ctr_released++;
-        TRACE2(("gdth_release(): HA %d of %d\n", 
-                gdth_ctr_released, gdth_ctr_count));
-
-        if (gdth_ctr_released == gdth_ctr_count) {
-#ifdef GDTH_STATISTICS
-            del_timer(&gdth_timer);
-#endif
-            unregister_chrdev(major,"gdth");
-            unregister_reboot_notifier(&gdth_notifier);
-        }
-    }
-
-    scsi_unregister(shp);
-    return 0;
-}
-            
-
-static const char *gdth_ctr_name(int hanum)
-{
-    gdth_ha_str *ha;
-
     TRACE2(("gdth_ctr_name()\n"));
 
-    ha    = HADATA(gdth_ctr_tab[hanum]);
-
     if (ha->type == GDT_EISA) {
         switch (ha->stype) {
           case GDT3_ID:
@@ -4820,29 +3932,23 @@ static const char *gdth_ctr_name(int hanum)
 
 static const char *gdth_info(struct Scsi_Host *shp)
 {
-    int hanum;
-    gdth_ha_str *ha;
+    gdth_ha_str *ha = shost_priv(shp);
 
     TRACE2(("gdth_info()\n"));
-    hanum = NUMDATA(shp)->hanum;
-    ha    = HADATA(gdth_ctr_tab[hanum]);
-
     return ((const char *)ha->binfo.type_string);
 }
 
 static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
 {
-    int i, hanum;
-    gdth_ha_str *ha;
+    gdth_ha_str *ha = shost_priv(scp->device->host);
+    int i;
     ulong flags;
     Scsi_Cmnd *cmnd;
     unchar b;
 
     TRACE2(("gdth_eh_bus_reset()\n"));
 
-    hanum = NUMDATA(scp->device->host)->hanum;
-    b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-    ha    = HADATA(gdth_ctr_tab[hanum]);
+    b = scp->device->channel;
 
     /* clear command tab */
     spin_lock_irqsave(&ha->smp_lock, flags);
@@ -4859,9 +3965,9 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
             if (ha->hdr[i].present) {
                 spin_lock_irqsave(&ha->smp_lock, flags);
                 gdth_polling = TRUE;
-                while (gdth_test_busy(hanum))
+                while (gdth_test_busy(ha))
                     gdth_delay(0);
-                if (gdth_internal_cmd(hanum, CACHESERVICE, 
+                if (gdth_internal_cmd(ha, CACHESERVICE,
                                       GDT_CLUST_RESET, i, 0, 0))
                     ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
                 gdth_polling = FALSE;
@@ -4874,9 +3980,9 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
         for (i = 0; i < MAXID; ++i)
             ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
         gdth_polling = TRUE;
-        while (gdth_test_busy(hanum))
+        while (gdth_test_busy(ha))
             gdth_delay(0);
-        gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
+        gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESET_BUS,
                           BUS_L2P(ha,b), 0, 0);
         gdth_polling = FALSE;
         spin_unlock_irqrestore(&ha->smp_lock, flags);
@@ -4884,30 +3990,18 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
     return SUCCESS;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
-#else
-static int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
-#endif
 {
     unchar b, t;
-    int hanum;
-    gdth_ha_str *ha;
+    gdth_ha_str *ha = shost_priv(sdev->host);
     struct scsi_device *sd;
     unsigned capacity;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     sd = sdev;
     capacity = cap;
-#else
-    sd = disk->device;
-    capacity = disk->capacity;
-#endif
-    hanum = NUMDATA(sd->host)->hanum;
-    b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel;
+    b = sd->channel;
     t = sd->id;
-    TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); 
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", ha->hanum, b, t));
 
     if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
         /* raw device or host drive without mapping information */
@@ -4925,33 +4019,42 @@ static int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
 }
 
 
-static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
+static int gdth_queuecommand(struct scsi_cmnd *scp,
+                               void (*done)(struct scsi_cmnd *))
 {
-    int hanum;
-    int priority;
+    gdth_ha_str *ha = shost_priv(scp->device->host);
+    struct gdth_cmndinfo *cmndinfo;
 
     TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
-    
-    scp->scsi_done = (void *)done;
-    scp->SCp.have_data_in = 1;
-    scp->SCp.phase = -1;
-    scp->SCp.sent_command = -1;
-    scp->SCp.Status = GDTH_MAP_NONE;
-    scp->SCp.buffer = (struct scatterlist *)NULL;
-
-    hanum = NUMDATA(scp->device->host)->hanum;
+
+    cmndinfo = gdth_get_cmndinfo(ha);
+    BUG_ON(!cmndinfo);
+
+    scp->scsi_done = done;
+    gdth_update_timeout(scp, scp->timeout_per_command * 6);
+    cmndinfo->priority = DEFAULT_PRI;
+
+    gdth_set_bufflen(scp, scsi_bufflen(scp));
+    gdth_set_sg_count(scp, scsi_sg_count(scp));
+    gdth_set_sglist(scp, scsi_sglist(scp));
+
+    return __gdth_queuecommand(ha, scp, cmndinfo);
+}
+
+static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
+                               struct gdth_cmndinfo *cmndinfo)
+{
+    scp->host_scribble = (unsigned char *)cmndinfo;
+    cmndinfo->wait_for_completion = 1;
+    cmndinfo->phase = -1;
+    cmndinfo->OpCode = -1;
+
 #ifdef GDTH_STATISTICS
     ++act_ios;
 #endif
 
-    priority = DEFAULT_PRI;
-    if (scp->done == gdth_scsi_done)
-        priority = scp->SCp.this_residual;
-    else
-        gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
-
-    gdth_putq( hanum, scp, priority );
-    gdth_next( hanum );
+    gdth_putq(ha, scp, cmndinfo->priority);
+    gdth_next(ha);
     return 0;
 }
 
@@ -4959,12 +4062,10 @@ static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
 static int gdth_open(struct inode *inode, struct file *filep)
 {
     gdth_ha_str *ha;
-    int i;
 
-    for (i = 0; i < gdth_ctr_count; i++) {
-        ha = HADATA(gdth_ctr_tab[i]);
+    list_for_each_entry(ha, &gdth_instances, list) {
         if (!ha->sdev)
-            ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]);
+            ha->sdev = scsi_get_host_dev(ha->shost);
     }
 
     TRACE(("gdth_open()\n"));
@@ -4983,10 +4084,11 @@ static int ioc_event(void __user *arg)
     gdth_ha_str *ha;
     ulong flags;
 
-    if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event)) ||
-        evt.ionode >= gdth_ctr_count)
+    if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event)))
+        return -EFAULT;
+    ha = gdth_find_ha(evt.ionode);
+    if (!ha)
         return -EFAULT;
-    ha = HADATA(gdth_ctr_tab[evt.ionode]);
 
     if (evt.erase == 0xff) {
         if (evt.event.event_source == ES_TEST)
@@ -5020,11 +4122,12 @@ static int ioc_lockdrv(void __user *arg)
     ulong flags;
     gdth_ha_str *ha;
 
-    if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)) ||
-        ldrv.ionode >= gdth_ctr_count)
+    if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)))
         return -EFAULT;
-    ha = HADATA(gdth_ctr_tab[ldrv.ionode]);
+    ha = gdth_find_ha(ldrv.ionode);
+    if (!ha)
+        return -EFAULT;
+
     for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
         j = ldrv.drives[i];
         if (j >= MAX_HDRIVES || !ha->hdr[j].present)
@@ -5033,14 +4136,14 @@ static int ioc_lockdrv(void __user *arg)
             spin_lock_irqsave(&ha->smp_lock, flags);
             ha->hdr[j].lock = 1;
             spin_unlock_irqrestore(&ha->smp_lock, flags);
-            gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); 
-            gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); 
+            gdth_wait_completion(ha, ha->bus_cnt, j);
+            gdth_stop_timeout(ha, ha->bus_cnt, j);
         } else {
             spin_lock_irqsave(&ha->smp_lock, flags);
             ha->hdr[j].lock = 0;
             spin_unlock_irqrestore(&ha->smp_lock, flags);
-            gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); 
-            gdth_next(ldrv.ionode); 
+            gdth_start_timeout(ha, ha->bus_cnt, j);
+            gdth_next(ha);
         }
     } 
     return 0;
@@ -5050,16 +4153,16 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
 {
     gdth_ioctl_reset res;
     gdth_cmd_str cmd;
-    int hanum;
     gdth_ha_str *ha;
     int rval;
 
     if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
-        res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
+        res.number >= MAX_HDRIVES)
         return -EFAULT;
-    hanum = res.ionode;
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    ha = gdth_find_ha(res.ionode);
+    if (!ha)
+        return -EFAULT;
+
     if (!ha->hdr[res.number].present)
         return 0;
     memset(&cmd, 0, sizeof(gdth_cmd_str));
@@ -5085,22 +4188,21 @@ static int ioc_general(void __user *arg, char *cmnd)
     gdth_ioctl_general gen;
     char *buf = NULL;
     ulong64 paddr; 
-    int hanum;
     gdth_ha_str *ha;
     int rval;
-        
-    if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) ||
-        gen.ionode >= gdth_ctr_count)
+
+    if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)))
+        return -EFAULT;
+    ha = gdth_find_ha(gen.ionode);
+    if (!ha)
         return -EFAULT;
-    hanum = gen.ionode; 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     if (gen.data_len + gen.sense_len != 0) {
-        if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, 
+        if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len,
                                      FALSE, &paddr)))
             return -EFAULT;
         if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general),  
                            gen.data_len + gen.sense_len)) {
-            gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+            gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
             return -EFAULT;
         }
 
@@ -5174,7 +4276,7 @@ static int ioc_general(void __user *arg, char *cmnd)
                 gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len;
             }
         } else {
-            gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+            gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
             return -EFAULT;
         }
     }
@@ -5186,15 +4288,15 @@ static int ioc_general(void __user *arg, char *cmnd)
 
     if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, 
                      gen.data_len + gen.sense_len)) {
-        gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+        gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
         return -EFAULT; 
     } 
     if (copy_to_user(arg, &gen, 
         sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
-        gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+        gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
         return -EFAULT;
     }
-    gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+    gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
     return 0;
 }
  
@@ -5204,7 +4306,7 @@ static int ioc_hdrlist(void __user *arg, char *cmnd)
     gdth_cmd_str *cmd;
     gdth_ha_str *ha;
     unchar i;
-    int hanum, rc = -ENOMEM;
+    int rc = -ENOMEM;
     u32 cluster_type = 0;
 
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
@@ -5213,12 +4315,10 @@ static int ioc_hdrlist(void __user *arg, char *cmnd)
         goto free_fail;
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
-        rsc->ionode >= gdth_ctr_count) {
+        (NULL == (ha = gdth_find_ha(rsc->ionode)))) {
         rc = -EFAULT;
         goto free_fail;
     }
-    hanum = rsc->ionode;
-    ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
    
     for (i = 0; i < MAX_HDRIVES; ++i) { 
@@ -5259,7 +4359,7 @@ static int ioc_rescan(void __user *arg, char *cmnd)
     gdth_cmd_str *cmd;
     ushort i, status, hdr_cnt;
     ulong32 info;
-    int hanum, cyls, hds, secs;
+    int cyls, hds, secs;
     int rc = -ENOMEM;
     ulong flags;
     gdth_ha_str *ha; 
@@ -5270,12 +4370,10 @@ static int ioc_rescan(void __user *arg, char *cmnd)
         goto free_fail;
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
-        rsc->ionode >= gdth_ctr_count) {
+        (NULL == (ha = gdth_find_ha(rsc->ionode)))) {
         rc = -EFAULT;
         goto free_fail;
     }
-    hanum = rsc->ionode;
-    ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
 
     if (rsc->flag == 0) {
@@ -5432,9 +4530,9 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
         gdth_ioctl_ctrtype ctrt;
         
         if (copy_from_user(&ctrt, argp, sizeof(gdth_ioctl_ctrtype)) ||
-            ctrt.ionode >= gdth_ctr_count)
+            (NULL == (ha = gdth_find_ha(ctrt.ionode))))
             return -EFAULT;
-        ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
+
         if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
             ctrt.type = (unchar)((ha->stype>>20) - 0x10);
         } else {
@@ -5473,10 +4571,9 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
         unchar i, j;
 
         if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) ||
-            lchn.ionode >= gdth_ctr_count)
+            (NULL == (ha = gdth_find_ha(lchn.ionode))))
             return -EFAULT;
-        ha = HADATA(gdth_ctr_tab[lchn.ionode]);
-        
+
         i = lchn.channel;
         if (i < ha->bus_cnt) {
             if (lchn.lock) {
@@ -5484,16 +4581,16 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
                 ha->raw[i].lock = 1;
                 spin_unlock_irqrestore(&ha->smp_lock, flags);
                 for (j = 0; j < ha->tid_cnt; ++j) {
-                    gdth_wait_completion(lchn.ionode, i, j); 
-                    gdth_stop_timeout(lchn.ionode, i, j); 
+                    gdth_wait_completion(ha, i, j);
+                    gdth_stop_timeout(ha, i, j);
                 }
             } else {
                 spin_lock_irqsave(&ha->smp_lock, flags);
                 ha->raw[i].lock = 0;
                 spin_unlock_irqrestore(&ha->smp_lock, flags);
                 for (j = 0; j < ha->tid_cnt; ++j) {
-                    gdth_start_timeout(lchn.ionode, i, j); 
-                    gdth_next(lchn.ionode); 
+                    gdth_start_timeout(ha, i, j);
+                    gdth_next(ha);
                 }
             }
         } 
@@ -5509,37 +4606,22 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
       case GDTIOCTL_RESET_BUS:
       {
         gdth_ioctl_reset res;
-        int hanum, rval;
+        int rval;
 
         if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) ||
-            res.ionode >= gdth_ctr_count)
+            (NULL == (ha = gdth_find_ha(res.ionode))))
             return -EFAULT;
-        hanum = res.ionode; 
-        ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        scp  = kmalloc(sizeof(*scp), GFP_KERNEL);
+        scp  = kzalloc(sizeof(*scp), GFP_KERNEL);
         if (!scp)
             return -ENOMEM;
-        memset(scp, 0, sizeof(*scp));
         scp->device = ha->sdev;
         scp->cmd_len = 12;
-        scp->use_sg = 0;
-        scp->device->channel = virt_ctr ? 0 : res.number;
+        scp->device->channel = res.number;
         rval = gdth_eh_bus_reset(scp);
         res.status = (rval == SUCCESS ? S_OK : S_GENERR);
         kfree(scp);
-#else
-        scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
-        if (!scp)
-            return -ENOMEM;
-        scp->cmd_len = 12;
-        scp->use_sg = 0;
-        scp->channel = virt_ctr ? 0 : res.number;
-        rval = gdth_eh_bus_reset(scp);
-        res.status = (rval == SUCCESS ? S_OK : S_GENERR);
-        scsi_release_command(scp);
-#endif
+
         if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset)))
             return -EFAULT;
         break;
@@ -5556,16 +4638,14 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
 
 
 /* flush routine */
-static void gdth_flush(int hanum)
+static void gdth_flush(gdth_ha_str *ha)
 {
     int             i;
-    gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     char            cmnd[MAX_COMMAND_SIZE];   
     memset(cmnd, 0xff, MAX_COMMAND_SIZE);
 
-    TRACE2(("gdth_flush() hanum %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE2(("gdth_flush() hanum %d\n", ha->hanum));
 
     for (i = 0; i < MAX_HDRIVES; ++i) {
         if (ha->hdr[i].present) {
@@ -5581,9 +4661,9 @@ static void gdth_flush(int hanum)
                 gdtcmd.u.cache.BlockNo = 1;
                 gdtcmd.u.cache.sg_canz = 0;
             }
-            TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
+            TRACE2(("gdth_flush(): flush ha %d drive %d\n", ha->hanum, i));
 
-            gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL);
+            gdth_execute(ha->shost, &gdtcmd, cmnd, 30, NULL);
         }
     }
 }
@@ -5591,7 +4671,7 @@ static void gdth_flush(int hanum)
 /* shutdown routine */
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
 {
-    int             hanum;
+    gdth_ha_str *ha;
 #ifndef __alpha__
     gdth_cmd_str    gdtcmd;
     char            cmnd[MAX_COMMAND_SIZE];   
@@ -5606,8 +4686,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
 
     notifier_disabled = 1;
     printk("GDT-HA: Flushing all host drives .. ");
-    for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
-        gdth_flush(hanum);
+    list_for_each_entry(ha, &gdth_instances, list) {
+        gdth_flush(ha);
 
 #ifndef __alpha__
         /* controller reset */
@@ -5615,8 +4695,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
         gdtcmd.BoardNode = LOCALBOARD;
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_RESET;
-        TRACE2(("gdth_halt(): reset controller %d\n", hanum));
-        gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL);
+        TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum));
+        gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL);
 #endif
     }
     printk("Done.\n");
@@ -5627,7 +4707,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
     return NOTIFY_OK;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 /* configure lun */
 static int gdth_slave_configure(struct scsi_device *sdev)
 {
@@ -5636,40 +4715,536 @@ static int gdth_slave_configure(struct scsi_device *sdev)
     sdev->skip_ms_page_8 = 1;
     return 0;
 }
-#endif
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static struct scsi_host_template driver_template = {
-#else
-static Scsi_Host_Template driver_template = {
-#endif
-        .proc_name              = "gdth", 
-        .proc_info              = gdth_proc_info,
+static struct scsi_host_template gdth_template = {
         .name                   = "GDT SCSI Disk Array Controller",
-        .detect                 = gdth_detect, 
-        .release                = gdth_release,
         .info                   = gdth_info, 
         .queuecommand           = gdth_queuecommand,
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
+        .slave_configure        = gdth_slave_configure,
         .bios_param             = gdth_bios_param,
+        .proc_info              = gdth_proc_info,
+        .proc_name              = "gdth",
         .can_queue              = GDTH_MAXCMDS,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        .slave_configure        = gdth_slave_configure,
-#endif
         .this_id                = -1,
         .sg_tablesize           = GDTH_MAXSG,
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .unchecked_isa_dma      = 1,
         .use_clustering         = ENABLE_CLUSTERING,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-        .use_new_eh_code        = 1,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
-        .highmem_io             = 1,
+};
+
+#ifdef CONFIG_ISA
+static int gdth_isa_probe_one(ulong32 isa_bios)
+{
+       struct Scsi_Host *shp;
+       gdth_ha_str *ha;
+       dma_addr_t scratch_dma_handle = 0;
+       int error, i;
+
+       if (!gdth_search_isa(isa_bios))
+               return -ENXIO;
+
+       shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
+       if (!shp)
+               return -ENOMEM;
+       ha = shost_priv(shp);
+
+       error = -ENODEV;
+       if (!gdth_init_isa(isa_bios,ha))
+               goto out_host_put;
+
+       /* controller found and initialized */
+       printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
+               isa_bios, ha->irq, ha->drq);
+
+       error = request_irq(ha->irq, gdth_interrupt, IRQF_DISABLED, "gdth", ha);
+       if (error) {
+               printk("GDT-ISA: Unable to allocate IRQ\n");
+               goto out_host_put;
+       }
+
+       error = request_dma(ha->drq, "gdth");
+       if (error) {
+               printk("GDT-ISA: Unable to allocate DMA channel\n");
+               goto out_free_irq;
+       }
+
+       set_dma_mode(ha->drq,DMA_MODE_CASCADE);
+       enable_dma(ha->drq);
+       shp->unchecked_isa_dma = 1;
+       shp->irq = ha->irq;
+       shp->dma_channel = ha->drq;
+
+       ha->hanum = gdth_ctr_count++;
+       ha->shost = shp;
+
+       ha->pccb = &ha->cmdext;
+       ha->ccb_phys = 0L;
+       ha->pdev = NULL;
+
+       error = -ENOMEM;
+
+       ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
+                                               &scratch_dma_handle);
+       if (!ha->pscratch)
+               goto out_dec_counters;
+       ha->scratch_phys = scratch_dma_handle;
+
+       ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str),
+                                               &scratch_dma_handle);
+       if (!ha->pmsg)
+               goto out_free_pscratch;
+       ha->msg_phys = scratch_dma_handle;
+
+#ifdef INT_COAL
+       ha->coal_stat = pci_alloc_consistent(ha->pdev,
+                               sizeof(gdth_coal_status) * MAXOFFSETS,
+                               &scratch_dma_handle);
+       if (!ha->coal_stat)
+               goto out_free_pmsg;
+       ha->coal_stat_phys = scratch_dma_handle;
+#endif
+
+       ha->scratch_busy = FALSE;
+       ha->req_first = NULL;
+       ha->tid_cnt = MAX_HDRIVES;
+       if (max_ids > 0 && max_ids < ha->tid_cnt)
+               ha->tid_cnt = max_ids;
+       for (i = 0; i < GDTH_MAXCMDS; ++i)
+               ha->cmd_tab[i].cmnd = UNUSED_CMND;
+       ha->scan_mode = rescan ? 0x10 : 0;
+
+       error = -ENODEV;
+       if (!gdth_search_drives(ha)) {
+               printk("GDT-ISA: Error during device scan\n");
+               goto out_free_coal_stat;
+       }
+
+       if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+               hdr_channel = ha->bus_cnt;
+       ha->virt_bus = hdr_channel;
+
+       if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
+               shp->max_cmd_len = 16;
+
+       shp->max_id      = ha->tid_cnt;
+       shp->max_lun     = MAXLUN;
+       shp->max_channel = ha->bus_cnt;
+
+       spin_lock_init(&ha->smp_lock);
+       gdth_enable_int(ha);
+
+       error = scsi_add_host(shp, NULL);
+       if (error)
+               goto out_free_coal_stat;
+       list_add_tail(&ha->list, &gdth_instances);
+       return 0;
+
+ out_free_coal_stat:
+#ifdef INT_COAL
+       pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * MAXOFFSETS,
+                               ha->coal_stat, ha->coal_stat_phys);
+ out_free_pmsg:
+#endif
+       pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
+                               ha->pmsg, ha->msg_phys);
+ out_free_pscratch:
+       pci_free_consistent(ha->pdev, GDTH_SCRATCH,
+                               ha->pscratch, ha->scratch_phys);
+ out_dec_counters:
+       gdth_ctr_count--;
+ out_free_irq:
+       free_irq(ha->irq, ha);
+ out_host_put:
+       scsi_host_put(shp);
+       return error;
+}
+#endif /* CONFIG_ISA */
+
+#ifdef CONFIG_EISA
+static int gdth_eisa_probe_one(ushort eisa_slot)
+{
+       struct Scsi_Host *shp;
+       gdth_ha_str *ha;
+       dma_addr_t scratch_dma_handle = 0;
+       int error, i;
+
+       if (!gdth_search_eisa(eisa_slot))
+               return -ENXIO;
+
+       shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
+       if (!shp)
+               return -ENOMEM;
+       ha = shost_priv(shp);
+
+       error = -ENODEV;
+       if (!gdth_init_eisa(eisa_slot,ha))
+               goto out_host_put;
+
+       /* controller found and initialized */
+       printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
+               eisa_slot >> 12, ha->irq);
+
+       error = request_irq(ha->irq, gdth_interrupt, IRQF_DISABLED, "gdth", ha);
+       if (error) {
+               printk("GDT-EISA: Unable to allocate IRQ\n");
+               goto out_host_put;
+       }
+
+       shp->unchecked_isa_dma = 0;
+       shp->irq = ha->irq;
+       shp->dma_channel = 0xff;
+
+       ha->hanum = gdth_ctr_count++;
+       ha->shost = shp;
+
+       TRACE2(("EISA detect Bus 0: hanum %d\n", ha->hanum));
+
+       ha->pccb = &ha->cmdext;
+       ha->ccb_phys = 0L;
+
+       error = -ENOMEM;
+
+       ha->pdev = NULL;
+       ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
+                                               &scratch_dma_handle);
+       if (!ha->pscratch)
+               goto out_free_irq;
+       ha->scratch_phys = scratch_dma_handle;
+
+       ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str),
+                                               &scratch_dma_handle);
+       if (!ha->pmsg)
+               goto out_free_pscratch;
+       ha->msg_phys = scratch_dma_handle;
+
+#ifdef INT_COAL
+       ha->coal_stat = pci_alloc_consistent(ha->pdev,
+                       sizeof(gdth_coal_status) * MAXOFFSETS,
+                       &scratch_dma_handle);
+       if (!ha->coal_stat)
+               goto out_free_pmsg;
+       ha->coal_stat_phys = scratch_dma_handle;
 #endif
+
+       ha->ccb_phys = pci_map_single(ha->pdev,ha->pccb,
+                       sizeof(gdth_cmd_str), PCI_DMA_BIDIRECTIONAL);
+       if (!ha->ccb_phys)
+               goto out_free_coal_stat;
+
+       ha->scratch_busy = FALSE;
+       ha->req_first = NULL;
+       ha->tid_cnt = MAX_HDRIVES;
+       if (max_ids > 0 && max_ids < ha->tid_cnt)
+               ha->tid_cnt = max_ids;
+       for (i = 0; i < GDTH_MAXCMDS; ++i)
+               ha->cmd_tab[i].cmnd = UNUSED_CMND;
+       ha->scan_mode = rescan ? 0x10 : 0;
+
+       if (!gdth_search_drives(ha)) {
+               printk("GDT-EISA: Error during device scan\n");
+               error = -ENODEV;
+               goto out_free_ccb_phys;
+       }
+
+       if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+               hdr_channel = ha->bus_cnt;
+       ha->virt_bus = hdr_channel;
+
+       if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
+               shp->max_cmd_len = 16;
+
+       shp->max_id      = ha->tid_cnt;
+       shp->max_lun     = MAXLUN;
+       shp->max_channel = ha->bus_cnt;
+
+       spin_lock_init(&ha->smp_lock);
+       gdth_enable_int(ha);
+
+       error = scsi_add_host(shp, NULL);
+       if (error)
+               goto out_free_coal_stat;
+       list_add_tail(&ha->list, &gdth_instances);
+       return 0;
+
+ out_free_ccb_phys:
+       pci_unmap_single(ha->pdev,ha->ccb_phys, sizeof(gdth_cmd_str),
+                       PCI_DMA_BIDIRECTIONAL);
+ out_free_coal_stat:
+#ifdef INT_COAL
+       pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * MAXOFFSETS,
+                               ha->coal_stat, ha->coal_stat_phys);
+ out_free_pmsg:
 #endif
-};
+       pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
+                               ha->pmsg, ha->msg_phys);
+ out_free_pscratch:
+       pci_free_consistent(ha->pdev, GDTH_SCRATCH,
+                               ha->pscratch, ha->scratch_phys);
+ out_free_irq:
+       free_irq(ha->irq, ha);
+       gdth_ctr_count--;
+ out_host_put:
+       scsi_host_put(shp);
+       return error;
+}
+#endif /* CONFIG_EISA */
+
+#ifdef CONFIG_PCI
+static int gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+{
+       struct Scsi_Host *shp;
+       gdth_ha_str *ha;
+       dma_addr_t scratch_dma_handle = 0;
+       int error, i;
+
+       shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
+       if (!shp)
+               return -ENOMEM;
+       ha = shost_priv(shp);
+
+       error = -ENODEV;
+       if (!gdth_init_pci(&pcistr[ctr],ha))
+               goto out_host_put;
+
+       /* controller found and initialized */
+       printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
+               pcistr[ctr].pdev->bus->number,
+               PCI_SLOT(pcistr[ctr].pdev->devfn),
+               ha->irq);
+
+       error = request_irq(ha->irq, gdth_interrupt,
+                               IRQF_DISABLED|IRQF_SHARED, "gdth", ha);
+       if (error) {
+               printk("GDT-PCI: Unable to allocate IRQ\n");
+               goto out_host_put;
+       }
+
+       shp->unchecked_isa_dma = 0;
+       shp->irq = ha->irq;
+       shp->dma_channel = 0xff;
+
+       ha->hanum = gdth_ctr_count++;
+       ha->shost = shp;
+
+       ha->pccb = &ha->cmdext;
+       ha->ccb_phys = 0L;
+
+       error = -ENOMEM;
+
+       ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
+                                               &scratch_dma_handle);
+       if (!ha->pscratch)
+               goto out_free_irq;
+       ha->scratch_phys = scratch_dma_handle;
+
+       ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str),
+                                       &scratch_dma_handle);
+       if (!ha->pmsg)
+               goto out_free_pscratch;
+       ha->msg_phys = scratch_dma_handle;
+
+#ifdef INT_COAL
+       ha->coal_stat = pci_alloc_consistent(ha->pdev,
+                       sizeof(gdth_coal_status) * MAXOFFSETS,
+                       &scratch_dma_handle);
+       if (!ha->coal_stat)
+               goto out_free_pmsg;
+       ha->coal_stat_phys = scratch_dma_handle;
+#endif
+
+       ha->scratch_busy = FALSE;
+       ha->req_first = NULL;
+       ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
+       if (max_ids > 0 && max_ids < ha->tid_cnt)
+               ha->tid_cnt = max_ids;
+       for (i = 0; i < GDTH_MAXCMDS; ++i)
+               ha->cmd_tab[i].cmnd = UNUSED_CMND;
+       ha->scan_mode = rescan ? 0x10 : 0;
+
+       error = -ENODEV;
+       if (!gdth_search_drives(ha)) {
+               printk("GDT-PCI %d: Error during device scan\n", ha->hanum);
+               goto out_free_coal_stat;
+       }
+
+       if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+               hdr_channel = ha->bus_cnt;
+       ha->virt_bus = hdr_channel;
+
+       /* 64-bit DMA only supported from FW >= x.43 */
+       if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
+           !ha->dma64_support) {
+               if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+                       printk(KERN_WARNING "GDT-PCI %d: "
+                               "Unable to set 32-bit DMA\n", ha->hanum);
+                               goto out_free_coal_stat;
+               }
+       } else {
+               shp->max_cmd_len = 16;
+               if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
+                       printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
+               } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+                       printk(KERN_WARNING "GDT-PCI %d: "
+                               "Unable to set 64/32-bit DMA\n", ha->hanum);
+                       goto out_free_coal_stat;
+               }
+       }
+
+       shp->max_id      = ha->tid_cnt;
+       shp->max_lun     = MAXLUN;
+       shp->max_channel = ha->bus_cnt;
+
+       spin_lock_init(&ha->smp_lock);
+       gdth_enable_int(ha);
+
+       error = scsi_add_host(shp, &pcistr[ctr].pdev->dev);
+       if (error)
+               goto out_free_coal_stat;
+       list_add_tail(&ha->list, &gdth_instances);
+       return 0;
+
+ out_free_coal_stat:
+#ifdef INT_COAL
+       pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * MAXOFFSETS,
+                               ha->coal_stat, ha->coal_stat_phys);
+ out_free_pmsg:
+#endif
+       pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
+                               ha->pmsg, ha->msg_phys);
+ out_free_pscratch:
+       pci_free_consistent(ha->pdev, GDTH_SCRATCH,
+                               ha->pscratch, ha->scratch_phys);
+ out_free_irq:
+       free_irq(ha->irq, ha);
+       gdth_ctr_count--;
+ out_host_put:
+       scsi_host_put(shp);
+       return error;
+}
+#endif /* CONFIG_PCI */
+
+static void gdth_remove_one(gdth_ha_str *ha)
+{
+       struct Scsi_Host *shp = ha->shost;
+
+       TRACE2(("gdth_remove_one()\n"));
+
+       scsi_remove_host(shp);
+
+       if (ha->sdev) {
+               scsi_free_host_dev(ha->sdev);
+               ha->sdev = NULL;
+       }
+
+       gdth_flush(ha);
+
+       if (shp->irq)
+               free_irq(shp->irq,ha);
+
+#ifdef CONFIG_ISA
+       if (shp->dma_channel != 0xff)
+               free_dma(shp->dma_channel);
+#endif
+#ifdef INT_COAL
+       if (ha->coal_stat)
+               pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                       MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys);
+#endif
+       if (ha->pscratch)
+               pci_free_consistent(ha->pdev, GDTH_SCRATCH,
+                       ha->pscratch, ha->scratch_phys);
+       if (ha->pmsg)
+               pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
+                       ha->pmsg, ha->msg_phys);
+       if (ha->ccb_phys)
+               pci_unmap_single(ha->pdev,ha->ccb_phys,
+                       sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
+
+       scsi_host_put(shp);
+}
+
+static int __init gdth_init(void)
+{
+       if (disable) {
+               printk("GDT-HA: Controller driver disabled from"
+                       " command line !\n");
+               return 0;
+       }
+
+       printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",
+              GDTH_VERSION_STR);
+
+       /* initializations */
+       gdth_polling = TRUE;
+       gdth_clear_events();
+
+       /* As default we do not probe for EISA or ISA controllers */
+       if (probe_eisa_isa) {
+               /* scanning for controllers, at first: ISA controller */
+#ifdef CONFIG_ISA
+               ulong32 isa_bios;
+               for (isa_bios = 0xc8000UL; isa_bios <= 0xd8000UL;
+                               isa_bios += 0x8000UL)
+                       gdth_isa_probe_one(isa_bios);
+#endif
+#ifdef CONFIG_EISA
+               {
+                       ushort eisa_slot;
+                       for (eisa_slot = 0x1000; eisa_slot <= 0x8000;
+                                                eisa_slot += 0x1000)
+                               gdth_eisa_probe_one(eisa_slot);
+               }
+#endif
+       }
+
+#ifdef CONFIG_PCI
+       /* scanning for PCI controllers */
+       {
+               gdth_pci_str pcistr[MAXHA];
+               int cnt,ctr;
+
+               cnt = gdth_search_pci(pcistr);
+               printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
+               gdth_sort_pci(pcistr,cnt);
+               for (ctr = 0; ctr < cnt; ++ctr)
+                       gdth_pci_probe_one(pcistr, ctr);
+       }
+#endif /* CONFIG_PCI */
+
+       TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
+#ifdef GDTH_STATISTICS
+       TRACE2(("gdth_detect(): Initializing timer !\n"));
+       init_timer(&gdth_timer);
+       gdth_timer.expires = jiffies + HZ;
+       gdth_timer.data = 0L;
+       gdth_timer.function = gdth_timeout;
+       add_timer(&gdth_timer);
+#endif
+       major = register_chrdev(0,"gdth", &gdth_fops);
+       notifier_disabled = 0;
+       register_reboot_notifier(&gdth_notifier);
+       gdth_polling = FALSE;
+       return 0;
+}
+
+static void __exit gdth_exit(void)
+{
+       gdth_ha_str *ha;
+
+       list_for_each_entry(ha, &gdth_instances, list)
+               gdth_remove_one(ha);
+
+#ifdef GDTH_STATISTICS
+       del_timer(&gdth_timer);
+#endif
+       unregister_chrdev(major,"gdth");
+       unregister_reboot_notifier(&gdth_notifier);
+}
+
+module_init(gdth_init);
+module_exit(gdth_exit);
 
-#include "scsi_module.c"
 #ifndef MODULE
 __setup("gdth=", option_setup);
 #endif
index 37423300592e68825b38798023fffbaf9d572331..1434c6b0297c6977f17c73166ddcd6b9c48bb7ed 100644 (file)
@@ -13,7 +13,6 @@
  * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $
  */
 
-#include <linux/version.h>
 #include <linux/types.h>
 
 #ifndef TRUE
 #define MAILBOXREG      0x0c90                  /* mailbox reg. (16 bytes) */
 #define EISAREG         0x0cc0                  /* EISA configuration */
 
-/* DMA memory mappings */
-#define GDTH_MAP_NONE   0
-#define GDTH_MAP_SINGLE 1
-#define GDTH_MAP_SG     2
-#define GDTH_MAP_IOCTL  3 
-
 /* other defines */
 #define LINUX_OS        8                       /* used for cache optim. */
-#define SCATTER_GATHER  1                       /* s/g feature */
 #define SECS32          0x1f                    /* round capacity */
 #define BIOS_ID_OFFS    0x10                    /* offset contr-ID in ISABIOS */
 #define LOCALBOARD      0                       /* board node always 0 */
@@ -854,6 +846,9 @@ typedef struct {
 
 /* controller information structure */
 typedef struct {
+    struct Scsi_Host    *shost;
+    struct list_head    list;
+    ushort             hanum;
     ushort              oem_id;                 /* OEM */
     ushort              type;                   /* controller class */
     ulong32             stype;                  /* subtype (PCI: device ID) */
@@ -865,6 +860,7 @@ typedef struct {
     void __iomem        *brd;                   /* DPRAM address */
     ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
+    gdth_cmd_str        cmdext;
     gdth_cmd_str        *pccb;                  /* address command structure */
     ulong32             ccb_phys;               /* phys. address */
 #ifdef INT_COAL
@@ -916,6 +912,19 @@ typedef struct {
         Scsi_Cmnd       *cmnd;                  /* pending request */
         ushort          service;                /* service */
     } cmd_tab[GDTH_MAXCMDS];                    /* table of pend. requests */
+    struct gdth_cmndinfo {                      /* per-command private info */
+        int index;
+        int internal_command;                   /* don't call scsi_done */
+        dma_addr_t sense_paddr;                 /* sense dma-addr */
+        unchar priority;
+        int timeout;
+        volatile int wait_for_completion;
+        ushort status;
+        ulong32 info;
+        enum dma_data_direction dma_dir;
+        int phase;                              /* ???? */
+        int OpCode;
+    } cmndinfo[GDTH_MAXCMDS];                   /* index==0 is free */
     unchar              bus_cnt;                /* SCSI bus count */
     unchar              tid_cnt;                /* Target ID count */
     unchar              bus_id[MAXBUS];         /* IOP IDs */
@@ -938,19 +947,10 @@ typedef struct {
     struct scsi_device         *sdev;
 } gdth_ha_str;
 
-/* structure for scsi_register(), SCSI bus != 0 */
-typedef struct {
-    ushort      hanum;
-    ushort      busnum;
-} gdth_num_str;
-
-/* structure for scsi_register() */
-typedef struct {
-    gdth_num_str        numext;                 /* must be the first element */
-    gdth_ha_str         haext;
-    gdth_cmd_str        cmdext;
-} gdth_ext_str;
-
+static inline struct gdth_cmndinfo *gdth_cmnd_priv(struct scsi_cmnd* cmd)
+{
+       return (struct gdth_cmndinfo *)cmd->host_scribble;
+}
 
 /* INQUIRY data format */
 typedef struct {
diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h
deleted file mode 100644 (file)
index 2a302ee..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef IRQ_HANDLED
-typedef void irqreturn_t;
-#define IRQ_NONE
-#define IRQ_HANDLED
-#endif
-
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(x)
-#endif
-
-#ifndef __iomem
-#define __iomem
-#endif
-
-#ifndef __attribute_used__
-#define __attribute_used__     __devinitdata
-#endif
-
-#ifndef __user
-#define __user
-#endif
-
-#ifndef SERVICE_ACTION_IN
-#define SERVICE_ACTION_IN      0x9e
-#endif
-#ifndef READ_16
-#define READ_16                        0x88
-#endif
-#ifndef WRITE_16
-#define WRITE_16               0x8a
-#endif
index 32982eb75c84195aaa1c222d8cde5734cdcd82bd..de5773443c62802e746cee05f4e34ed8f643f3aa 100644 (file)
@@ -4,62 +4,32 @@
 
 #include <linux/completion.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,   
                    int inout)
 {
-    int hanum,busnum;
+    gdth_ha_str *ha = shost_priv(host);
 
     TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
             length,(int)offset,inout));
 
-    hanum = NUMDATA(host)->hanum;
-    busnum= NUMDATA(host)->busnum;
-
-    if (inout)
-        return(gdth_set_info(buffer,length,host,hanum,busnum));
-    else
-        return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum));
-}
-#else
-int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno,   
-                   int inout)
-{
-    int hanum,busnum,i;
-
-    TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
-            length,(int)offset,inout));
-
-    for (i = 0; i < gdth_ctr_vcount; ++i) {
-        if (gdth_ctr_vtab[i]->host_no == hostno)
-            break;
-    }
-    if (i == gdth_ctr_vcount)
-        return(-EINVAL);
-
-    hanum = NUMDATA(gdth_ctr_vtab[i])->hanum;
-    busnum= NUMDATA(gdth_ctr_vtab[i])->busnum;
-
     if (inout)
-        return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum));
+        return(gdth_set_info(buffer,length,host,ha));
     else
-        return(gdth_get_info(buffer,start,offset,length,
-                             gdth_ctr_vtab[i],hanum,busnum));
+        return(gdth_get_info(buffer,start,offset,length,host,ha));
 }
-#endif
 
 static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
-                         int hanum,int busnum)
+                         gdth_ha_str *ha)
 {
     int ret_val = -EINVAL;
 
-    TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
+    TRACE2(("gdth_set_info() ha %d\n",ha->hanum,));
 
     if (length >= 4) {
         if (strncmp(buffer,"gdth",4) == 0) {
             buffer += 5;
             length -= 5;
-            ret_val = gdth_set_asc_info(host, buffer, length, hanum);
+            ret_val = gdth_set_asc_info(host, buffer, length, ha);
         }
     }
 
@@ -67,11 +37,10 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
 }
          
 static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
-                        int length,int hanum)
+                        int length, gdth_ha_str *ha)
 {
     int orig_length, drive, wb_mode;
     int i, found;
-    gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
     ulong64         paddr;
@@ -80,8 +49,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
     memset(cmnd, 0xff, 12);
     memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
 
-    TRACE2(("gdth_set_asc_info() ha %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE2(("gdth_set_asc_info() ha %d\n",ha->hanum));
     orig_length = length + 5;
     drive = -1;
     wb_mode = 0;
@@ -157,7 +125,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
     }
 
     if (wb_mode) {
-        if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr))
+        if (!gdth_ioctl_alloc(ha, sizeof(gdth_cpar_str), TRUE, &paddr))
             return(-EBUSY);
         pcpar = (gdth_cpar_str *)ha->pscratch;
         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
@@ -171,7 +139,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
 
         gdth_execute(host, &gdtcmd, cmnd, 30, NULL);
 
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, ha->pscratch, paddr);
         printk("Done.\n");
         return(orig_length);
     }
@@ -181,11 +149,10 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
 }
 
 static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
-                         struct Scsi_Host *host,int hanum,int busnum)
+                         struct Scsi_Host *host, gdth_ha_str *ha)
 {
     int size = 0,len = 0;
     off_t begin = 0,pos = 0;
-    gdth_ha_str *ha;
     int id, i, j, k, sec, flag;
     int no_mdrv = 0, drv_no, is_mirr;
     ulong32 cnt;
@@ -214,8 +181,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
     memset(cmnd, 0xff, 12);
     memset(gdtcmd, 0, sizeof(gdth_cmd_str));
 
-    TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
+    TRACE2(("gdth_get_info() ha %d\n",ha->hanum));
 
     
     /* request is i.e. "cat /proc/scsi/gdth/0" */ 
@@ -245,13 +211,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
     /* controller information */
     size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
     len += size;  pos = begin + len;
-    if (virt_ctr)
-        sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
-    else
-        strcpy(hrec, ha->binfo.type_string);
+    strcpy(hrec, ha->binfo.type_string);
     size = sprintf(buffer+len,
                    " Number:       \t%d         \tName:          \t%s\n",
-                   hanum, hrec);
+                   ha->hanum, hrec);
     len += size;  pos = begin + len;
 
     if (ha->more_proc)
@@ -301,7 +264,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
         len += size;  pos = begin + len;
         flag = FALSE;
             
-        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
         if (!buf) 
             goto stop_output;
         for (i = 0; i < ha->bus_cnt; ++i) {
@@ -404,7 +367,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     goto stop_output;
             }
         }
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
 
         if (!flag) {
             size = sprintf(buffer+len, "\n --\n");
@@ -416,7 +379,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
         len += size;  pos = begin + len;
         flag = FALSE;
 
-        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
         if (!buf) 
             goto stop_output;
         for (i = 0; i < MAX_LDRIVES; ++i) {
@@ -510,7 +473,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
             if (pos > offset + length)
                 goto stop_output;
         }       
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
         if (!flag) {
             size = sprintf(buffer+len, "\n --\n");
@@ -522,7 +485,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
         len += size;  pos = begin + len;
         flag = FALSE;
 
-        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
         if (!buf) 
             goto stop_output;
         for (i = 0; i < MAX_LDRIVES; ++i) {
@@ -581,7 +544,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     goto stop_output;
             }
         }
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
         if (!flag) {
             size = sprintf(buffer+len, "\n --\n");
@@ -593,7 +556,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
         len += size;  pos = begin + len;
         flag = FALSE;
 
-        buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr);
         if (!buf) 
             goto stop_output;
         for (i = 0; i < MAX_LDRIVES; ++i) {
@@ -626,7 +589,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                 }
             }
         }
-        gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr);
+        gdth_ioctl_free(ha, sizeof(gdth_hget_str), buf, paddr);
 
         for (i = 0; i < MAX_HDRIVES; ++i) {
             if (!(ha->hdr[i].present))
@@ -664,7 +627,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
         id = gdth_read_event(ha, id, estr);
         if (estr->event_source == 0)
             break;
-        if (estr->event_data.eu.driver.ionode == hanum &&
+        if (estr->event_data.eu.driver.ionode == ha->hanum &&
             estr->event_source == ES_ASYNC) { 
             gdth_log_event(&estr->event_data, hrec);
             do_gettimeofday(&tv);
@@ -699,17 +662,15 @@ free_fail:
     return rc;
 }
 
-static char *gdth_ioctl_alloc(int hanum, int size, int scratch, 
+static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch,
                               ulong64 *paddr)
 {
-    gdth_ha_str *ha;
     ulong flags;
     char *ret_val;
 
     if (size == 0)
         return NULL;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
@@ -729,12 +690,10 @@ static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
     return ret_val;
 }
 
-static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr)
+static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr)
 {
-    gdth_ha_str *ha;
     ulong flags;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     if (buf == ha->pscratch) {
@@ -747,13 +706,11 @@ static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr)
 }
 
 #ifdef GDTH_IOCTL_PROC
-static int gdth_ioctl_check_bin(int hanum, ushort size)
+static int gdth_ioctl_check_bin(gdth_ha_str *ha, ushort size)
 {
-    gdth_ha_str *ha;
     ulong flags;
     int ret_val;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     ret_val = FALSE;
@@ -766,27 +723,27 @@ static int gdth_ioctl_check_bin(int hanum, ushort size)
 }
 #endif
 
-static void gdth_wait_completion(int hanum, int busnum, int id)
+static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id)
 {
-    gdth_ha_str *ha;
     ulong flags;
     int i;
     Scsi_Cmnd *scp;
+    struct gdth_cmndinfo *cmndinfo;
     unchar b, t;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         scp = ha->cmd_tab[i].cmnd;
+        cmndinfo = gdth_cmnd_priv(scp);
 
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        b = scp->device->channel;
         t = scp->device->id;
         if (!SPECIAL_SCP(scp) && t == (unchar)id && 
             b == (unchar)busnum) {
-            scp->SCp.have_data_in = 0;
+            cmndinfo->wait_for_completion = 0;
             spin_unlock_irqrestore(&ha->smp_lock, flags);
-            while (!scp->SCp.have_data_in)
+            while (!cmndinfo->wait_for_completion)
                 barrier();
             spin_lock_irqsave(&ha->smp_lock, flags);
         }
@@ -794,55 +751,51 @@ static void gdth_wait_completion(int hanum, int busnum, int id)
     spin_unlock_irqrestore(&ha->smp_lock, flags);
 }
 
-static void gdth_stop_timeout(int hanum, int busnum, int id)
+static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id)
 {
-    gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
     unchar b, t;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        if (scp->done != gdth_scsi_done) {
-            b = virt_ctr ?
-                NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
+        if (!cmndinfo->internal_command) {
+            b = scp->device->channel;
             t = scp->device->id;
             if (t == (unchar)id && b == (unchar)busnum) {
                 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
-                scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+                cmndinfo->timeout = gdth_update_timeout(scp, 0);
             }
         }
     }
     spin_unlock_irqrestore(&ha->smp_lock, flags);
 }
 
-static void gdth_start_timeout(int hanum, int busnum, int id)
+static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id)
 {
-    gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
     unchar b, t;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        if (scp->done != gdth_scsi_done) {
-            b = virt_ctr ?
-                NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
+        if (!cmndinfo->internal_command) {
+            b = scp->device->channel;
             t = scp->device->id;
             if (t == (unchar)id && b == (unchar)busnum) {
                 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
-                gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
+                gdth_update_timeout(scp, cmndinfo->timeout);
             }
         }
     }
     spin_unlock_irqrestore(&ha->smp_lock, flags);
 }
 
-static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
+static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout)
 {
     int oldto;
 
index a679eeb6820bddf17ff5a277bf000f82f8d55333..45e6fdacf36e39d06eee15ba10e7c12f396673a5 100644 (file)
@@ -9,20 +9,20 @@ int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
                  int timeout, u32 *info);
 
 static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
-                         int hanum,int busnum);
+                         gdth_ha_str *ha);
 static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
-                         struct Scsi_Host *host,int hanum,int busnum);
+                         struct Scsi_Host *host, gdth_ha_str *ha);
 
 static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
-                             int length, int hanum);
+                             int length, gdth_ha_str *ha);
 
-static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
-                              ulong64 *paddr);  
-static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr);
-static void gdth_wait_completion(int hanum, int busnum, int id);
-static void gdth_stop_timeout(int hanum, int busnum, int id);
-static void gdth_start_timeout(int hanum, int busnum, int id);
-static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
+static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch,
+                              ulong64 *paddr);
+static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr);
+static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id);
+static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id);
+static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id);
+static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout);
 
 #endif
 
index 96bc31266c98a258aefbcbd6ff54fde95f80a560..adc9559cb6f40b20e4666d93550bc0b8b6fc8e83 100644 (file)
@@ -342,6 +342,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->unchecked_isa_dma = sht->unchecked_isa_dma;
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
+       shost->active_mode = sht->supported_mode;
 
        if (sht->max_host_blocked)
                shost->max_host_blocked = sht->max_host_blocked;
index 0e579ca45814d4a0794f99ba7594dfc315ff88b5..8b384fa7f048c96a92d555e74377ab3d1a4bb22d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx controller driver for Linux
- * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver");
 
 static char driver_name[] = "hptiop";
 static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver";
-static const char driver_ver[] = "v1.0 (060426)";
+static const char driver_ver[] = "v1.2 (070830)";
 
 static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag);
 static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag);
@@ -76,7 +76,7 @@ static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec)
 
 static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag)
 {
-       if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT)
+       if (tag & IOPMU_QUEUE_ADDR_HOST_BIT)
                return hptiop_host_request_callback(hba,
                                tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
        else
@@ -323,12 +323,22 @@ static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req)
        hba->req_list = req;
 }
 
-static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag)
+static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag)
 {
        struct hpt_iop_request_scsi_command *req;
        struct scsi_cmnd *scp;
+       u32 tag;
+
+       if (hba->iopintf_v2) {
+               tag = _tag & ~ IOPMU_QUEUE_REQUEST_RESULT_BIT;
+               req = hba->reqs[tag].req_virt;
+               if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))
+                       req->header.result = IOP_RESULT_SUCCESS;
+       } else {
+               tag = _tag;
+               req = hba->reqs[tag].req_virt;
+       }
 
-       req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt;
        dprintk("hptiop_host_request_callback: req=%p, type=%d, "
                        "result=%d, context=0x%x tag=%d\n",
                        req, req->header.type, req->header.result,
@@ -497,7 +507,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
                goto cmd_done;
        }
 
-       req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
+       req = _req->req_virt;
 
        /* build S/G table */
        sg_count = hptiop_buildsgl(scp, req->sg_list);
@@ -521,8 +531,19 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 
        memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
 
-       writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy,
-                       &hba->iop->inbound_queue);
+       if (hba->iopintf_v2) {
+               u32 size_bits;
+               if (req->header.size < 256)
+                       size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
+               else if (req->header.size < 512)
+                       size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
+               else
+                       size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT |
+                                               IOPMU_QUEUE_ADDR_HOST_BIT;
+               writel(_req->req_shifted_phy | size_bits, &hba->iop->inbound_queue);
+       } else
+               writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT,
+                                       &hba->iop->inbound_queue);
 
        return 0;
 
@@ -688,6 +709,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        hba->pcidev = pcidev;
        hba->host = host;
        hba->initialized = 0;
+       hba->iopintf_v2 = 0;
 
        atomic_set(&hba->resetting, 0);
        atomic_set(&hba->reset_count, 0);
@@ -722,8 +744,13 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        hba->max_request_size = le32_to_cpu(iop_config.request_size);
        hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);
        hba->firmware_version = le32_to_cpu(iop_config.firmware_version);
+       hba->interface_version = le32_to_cpu(iop_config.interface_version);
        hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
 
+       if (hba->firmware_version > 0x01020000 ||
+                       hba->interface_version > 0x01020000)
+               hba->iopintf_v2 = 1;
+
        host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9;
        host->max_id = le32_to_cpu(iop_config.max_devices);
        host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count);
@@ -731,8 +758,15 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
        host->max_cmd_len = 16;
 
-       set_config.vbus_id = cpu_to_le32(host->host_no);
+       req_size = sizeof(struct hpt_iop_request_scsi_command)
+               + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1);
+       if ((req_size & 0x1f) != 0)
+               req_size = (req_size + 0x1f) & ~0x1f;
+
+       memset(&set_config, 0, sizeof(struct hpt_iop_request_set_config));
        set_config.iop_id = cpu_to_le32(host->host_no);
+       set_config.vbus_id = cpu_to_le16(host->host_no);
+       set_config.max_host_request_size = cpu_to_le16(req_size);
 
        if (iop_set_config(hba, &set_config)) {
                printk(KERN_ERR "scsi%d: set config failed\n",
@@ -750,10 +784,6 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        }
 
        /* Allocate request mem */
-       req_size = sizeof(struct hpt_iop_request_scsi_command)
-               + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1);
-       if ((req_size& 0x1f) != 0)
-               req_size = (req_size + 0x1f) & ~0x1f;
 
        dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests);
 
@@ -879,8 +909,10 @@ static void hptiop_remove(struct pci_dev *pcidev)
 }
 
 static struct pci_device_id hptiop_id_table[] = {
-       { PCI_DEVICE(0x1103, 0x3220) },
-       { PCI_DEVICE(0x1103, 0x3320) },
+       { PCI_VDEVICE(TTI, 0x3220) },
+       { PCI_VDEVICE(TTI, 0x3320) },
+       { PCI_VDEVICE(TTI, 0x3520) },
+       { PCI_VDEVICE(TTI, 0x4320) },
        {},
 };
 
@@ -910,3 +942,4 @@ module_init(hptiop_module_init);
 module_exit(hptiop_module_exit);
 
 MODULE_LICENSE("GPL");
+
index f04f7e81d1ae8e52d9ab5b00837c2d3fd92b02d2..2a5e46e001cba5ebd2357354b26d5352887ea3da 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx controller driver for Linux
- * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #ifndef _HPTIOP_H_
 #define _HPTIOP_H_
 
-/*
- * logical device type.
- * Identify array (logical device) and physical device.
- */
-#define LDT_ARRAY   1
-#define LDT_DEVICE  2
-
-/*
- * Array types
- */
-#define AT_UNKNOWN  0
-#define AT_RAID0    1
-#define AT_RAID1    2
-#define AT_RAID5    3
-#define AT_RAID6    4
-#define AT_JBOD     7
-
-#define MAX_NAME_LENGTH     36
-#define MAX_ARRAYNAME_LEN   16
-
-#define MAX_ARRAY_MEMBERS_V1 8
-#define MAX_ARRAY_MEMBERS_V2 16
-
-/* keep definition for source code compatiblity */
-#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1
-
-/*
- * array flags
- */
-#define ARRAY_FLAG_DISABLED         0x00000001 /* The array is disabled */
-#define ARRAY_FLAG_NEEDBUILDING     0x00000002 /* need to be rebuilt */
-#define ARRAY_FLAG_REBUILDING       0x00000004 /* in rebuilding process */
-#define ARRAY_FLAG_BROKEN           0x00000008 /* broken but still working */
-#define ARRAY_FLAG_BOOTDISK         0x00000010 /* has a active partition */
-#define ARRAY_FLAG_BOOTMARK         0x00000040 /* array has boot mark set */
-#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */
-#define ARRAY_FLAG_VERIFYING        0x00000100 /* is being verified */
-#define ARRAY_FLAG_INITIALIZING     0x00000200 /* is being initialized */
-#define ARRAY_FLAG_TRANSFORMING     0x00000400 /* tranform in progress */
-#define ARRAY_FLAG_NEEDTRANSFORM    0x00000800 /* array need tranform */
-#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */
-#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */
-
-/*
- * device flags
- */
-#define DEVICE_FLAG_DISABLED        0x00000001 /* device is disabled */
-#define DEVICE_FLAG_UNINITIALIZED   0x00010000 /* device is not initialized */
-#define DEVICE_FLAG_LEGACY          0x00020000 /* lagacy drive */
-#define DEVICE_FLAG_IS_SPARE        0x80000000 /* is a spare disk */
-
-/*
- * ioctl codes
- */
-#define HPT_CTL_CODE(x) (x+0xFF00)
-#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00)
-
-#define HPT_IOCTL_GET_CONTROLLER_INFO       HPT_CTL_CODE(2)
-#define HPT_IOCTL_GET_CHANNEL_INFO          HPT_CTL_CODE(3)
-#define HPT_IOCTL_GET_LOGICAL_DEVICES       HPT_CTL_CODE(4)
-#define HPT_IOCTL_GET_DRIVER_CAPABILITIES   HPT_CTL_CODE(19)
-#define HPT_IOCTL_GET_DEVICE_INFO_V3        HPT_CTL_CODE(46)
-#define HPT_IOCTL_GET_CONTROLLER_INFO_V2    HPT_CTL_CODE(47)
-
-/*
- * Controller information.
- */
-struct hpt_controller_info {
-       u8      chip_type;                    /* chip type */
-       u8      interrupt_level;              /* IRQ level */
-       u8      num_buses;                    /* bus count */
-       u8      chip_flags;
-
-       u8      product_id[MAX_NAME_LENGTH];/* product name */
-       u8      vendor_id[MAX_NAME_LENGTH]; /* vendor name */
-}
-__attribute__((packed));
-
-/*
- * Channel information.
- */
-struct hpt_channel_info {
-       __le32  io_port;         /* IDE Base Port Address */
-       __le32  control_port;    /* IDE Control Port Address */
-       __le32  devices[2];      /* device connected to this channel */
-}
-__attribute__((packed));
-
-/*
- * Array information.
- */
-struct hpt_array_info_v3 {
-       u8      name[MAX_ARRAYNAME_LEN]; /* array name */
-       u8      description[64];         /* array description */
-       u8      create_manager[16];      /* who created it */
-       __le32  create_time;             /* when created it */
-
-       u8      array_type;              /* array type */
-       u8      block_size_shift;        /* stripe size */
-       u8      ndisk;                   /* Number of ID in Members[] */
-       u8      reserved;
-
-       __le32  flags;                   /* working flags, see ARRAY_FLAG_XXX */
-       __le32  members[MAX_ARRAY_MEMBERS_V2];  /* member array/disks */
-
-       __le32  rebuilding_progress;
-       __le64  rebuilt_sectors; /* rebuilding point (LBA) for single member */
-
-       __le32  transform_source;
-       __le32  transform_target;    /* destination device ID */
-       __le32  transforming_progress;
-       __le32  signature;              /* persistent identification*/
-       __le16  critical_members;       /* bit mask of critical members */
-       __le16  reserve2;
-       __le32  reserve;
-}
-__attribute__((packed));
-
-/*
- * physical device information.
- */
-#define MAX_PARENTS_PER_DISK    8
-
-struct hpt_device_info_v2 {
-       u8   ctlr_id;             /* controller id */
-       u8   path_id;             /* bus */
-       u8   target_id;           /* id */
-       u8   device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */
-                                 /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */
-       u8   device_type;         /* device type */
-       u8   usable_mode;         /* highest usable mode */
-
-#ifdef __BIG_ENDIAN_BITFIELD
-       u8   NCQ_enabled: 1;
-       u8   NCQ_supported: 1;
-       u8   TCQ_enabled: 1;
-       u8   TCQ_supported: 1;
-       u8   write_cache_enabled: 1;
-       u8   write_cache_supported: 1;
-       u8   read_ahead_enabled: 1;
-       u8   read_ahead_supported: 1;
-       u8   reserved6: 6;
-       u8   spin_up_mode: 2;
-#else
-       u8   read_ahead_supported: 1;
-       u8   read_ahead_enabled: 1;
-       u8   write_cache_supported: 1;
-       u8   write_cache_enabled: 1;
-       u8   TCQ_supported: 1;
-       u8   TCQ_enabled: 1;
-       u8   NCQ_supported: 1;
-       u8   NCQ_enabled: 1;
-       u8   spin_up_mode: 2;
-       u8   reserved6: 6;
-#endif
-
-       __le32  flags;         /* working flags, see DEVICE_FLAG_XXX */
-       u8      ident[150];    /* (partitial) Identify Data of this device */
-
-       __le64  total_free;
-       __le64  max_free;
-       __le64  bad_sectors;
-       __le32  parent_arrays[MAX_PARENTS_PER_DISK];
-}
-__attribute__((packed));
-
-/*
- * Logical device information.
- */
-#define INVALID_TARGET_ID   0xFF
-#define INVALID_BUS_ID      0xFF
-
-struct hpt_logical_device_info_v3 {
-       u8       type;                   /* LDT_ARRAY or LDT_DEVICE */
-       u8       cache_policy;           /* refer to CACHE_POLICY_xxx */
-       u8       vbus_id;                /* vbus sequence in vbus_list */
-       u8       target_id;              /* OS target id. 0xFF is invalid */
-                                        /* OS name: DISK $VBusId_$TargetId */
-       __le64   capacity;               /* array capacity */
-       __le32   parent_array;           /* don't use this field for physical
-                                           device. use ParentArrays field in
-                                           hpt_device_info_v2 */
-       /* reserved statistic fields */
-       __le32   stat1;
-       __le32   stat2;
-       __le32   stat3;
-       __le32   stat4;
-
-       union {
-               struct hpt_array_info_v3 array;
-               struct hpt_device_info_v2 device;
-       } __attribute__((packed)) u;
-
-}
-__attribute__((packed));
-
-/*
- * ioctl structure
- */
-#define HPT_IOCTL_MAGIC   0xA1B2C3D4
-
-struct hpt_ioctl_u {
-       u32   magic;            /* used to check if it's a valid ioctl packet */
-       u32   ioctl_code;       /* operation control code */
-       void __user *inbuf;     /* input data buffer */
-       u32   inbuf_size;       /* size of input data buffer */
-       void __user *outbuf;    /* output data buffer */
-       u32   outbuf_size;      /* size of output data buffer */
-       void __user *bytes_returned;   /* count of bytes returned */
-}
-__attribute__((packed));
-
-
 struct hpt_iopmu
 {
        __le32 resrved0[4];
@@ -252,6 +39,8 @@ struct hpt_iopmu
 #define IOPMU_QUEUE_EMPTY            0xffffffff
 #define IOPMU_QUEUE_MASK_HOST_BITS   0xf0000000
 #define IOPMU_QUEUE_ADDR_HOST_BIT    0x80000000
+#define IOPMU_QUEUE_REQUEST_SIZE_BIT    0x40000000
+#define IOPMU_QUEUE_REQUEST_RESULT_BIT   0x40000000
 
 #define IOPMU_OUTBOUND_INT_MSG0      1
 #define IOPMU_OUTBOUND_INT_MSG1      2
@@ -336,7 +125,8 @@ struct hpt_iop_request_set_config
 {
        struct hpt_iop_request_header header;
        __le32 iop_id;
-       __le32 vbus_id;
+       __le16 vbus_id;
+       __le16 max_host_request_size;
        __le32 reserve[6];
 };
 
@@ -412,9 +202,8 @@ struct hptiop_hba {
        struct Scsi_Host * host;
        struct pci_dev * pcidev;
 
-       struct list_head link;
-
        /* IOP config info */
+       u32     interface_version;
        u32     firmware_version;
        u32     sdram_size;
        u32     max_devices;
@@ -423,8 +212,10 @@ struct hptiop_hba {
        u32     max_sg_descriptors;
 
        u32     req_size; /* host-allocated request buffer size */
-       int     initialized;
-       int     msg_done;
+
+       int     iopintf_v2: 1;
+       int     initialized: 1;
+       int     msg_done: 1;
 
        struct hptiop_request * req_list;
        struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];
index 4275d1b04ced7f24b6c89d54b6a403e7cff9357a..1a924e9b02718f405dac5e9be65a13979b4a502a 100644 (file)
@@ -460,13 +460,6 @@ module_param(boot_options, charp, 0);
 module_param_array(io_port, int, NULL, 0);
 module_param_array(scsi_id, int, NULL, 0);
 
-#if 0 /* FIXME: No longer exist? --RR */
-MODULE_PARM(display, "1i");
-MODULE_PARM(adisplay, "1i");
-MODULE_PARM(normal, "1i");
-MODULE_PARM(ansi, "1i");
-#endif
-
 MODULE_LICENSE("GPL");
 #endif
 /*counter of concurrent disk read/writes, to turn on/off disk led */
@@ -1693,6 +1686,7 @@ static int __devexit ibmmca_remove(struct device *dev)
        scsi_remove_host(shpnt);
        release_region(shpnt->io_port, shpnt->n_io_port);
        free_irq(shpnt->irq, dev);
+       scsi_host_put(shpnt);
        return 0;
 }
 
index f67d9efc7a99abe8c4c5e8a16ab09e0acf866610..6ac0633d5452af8c36a0683653485980335950e3 100644 (file)
@@ -1,9 +1,7 @@
 obj-$(CONFIG_SCSI_IBMVSCSI)    += ibmvscsic.o
 
 ibmvscsic-y                    += ibmvscsi.o
-ifndef CONFIG_PPC_PSERIES
 ibmvscsic-$(CONFIG_PPC_ISERIES)        += iseries_vscsi.o 
-endif
 ibmvscsic-$(CONFIG_PPC_PSERIES)        += rpa_vscsi.o 
 
 obj-$(CONFIG_SCSI_IBMVSCSIS)   += ibmvstgt.o
index 5ecc63d1b43602e10f9a64ecad246dbcd1403c52..cda0cc3d182fde457f4b15259d8a10eb476489af 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <asm/firmware.h>
 #include <asm/vio.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_srp.h>
 #include "ibmvscsi.h"
 
 /* The values below are somewhat arbitrary default values, but 
@@ -87,8 +89,12 @@ static int max_channel = 3;
 static int init_timeout = 5;
 static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
 
+static struct scsi_transport_template *ibmvscsi_transport_template;
+
 #define IBMVSCSI_VERSION "1.5.8"
 
+static struct ibmvscsi_ops *ibmvscsi_ops;
+
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
 MODULE_LICENSE("GPL");
@@ -506,8 +512,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
        atomic_set(&hostdata->request_limit, 0);
 
        purge_requests(hostdata, DID_ERROR);
-       if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) ||
-           (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) ||
+       if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) ||
+           (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) ||
            (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
                atomic_set(&hostdata->request_limit, -1);
                dev_err(hostdata->dev, "error after reset\n");
@@ -612,7 +618,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
        }
 
        if ((rc =
-            ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+            ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
                list_del(&evt_struct->list);
                del_timer(&evt_struct->timer);
 
@@ -1211,8 +1217,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                case 0x01:      /* Initialization message */
                        dev_info(hostdata->dev, "partner initialized\n");
                        /* Send back a response */
-                       if ((rc = ibmvscsi_send_crq(hostdata,
-                                                   0xC002000000000000LL, 0)) == 0) {
+                       if ((rc = ibmvscsi_ops->send_crq(hostdata,
+                                                        0xC002000000000000LL, 0)) == 0) {
                                /* Now login */
                                send_srp_login(hostdata);
                        } else {
@@ -1237,10 +1243,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                        /* We need to re-setup the interpartition connection */
                        dev_info(hostdata->dev, "Re-enabling adapter!\n");
                        purge_requests(hostdata, DID_REQUEUE);
-                       if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
-                                                       hostdata)) ||
-                           (ibmvscsi_send_crq(hostdata,
-                                              0xC001000000000000LL, 0))) {
+                       if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue,
+                                                             hostdata)) ||
+                           (ibmvscsi_ops->send_crq(hostdata,
+                                                   0xC001000000000000LL, 0))) {
                                        atomic_set(&hostdata->request_limit,
                                                   -1);
                                        dev_err(hostdata->dev, "error after enable\n");
@@ -1250,10 +1256,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                                crq->format);
 
                        purge_requests(hostdata, DID_ERROR);
-                       if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
-                                                       hostdata)) ||
-                           (ibmvscsi_send_crq(hostdata,
-                                              0xC001000000000000LL, 0))) {
+                       if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue,
+                                                          hostdata)) ||
+                           (ibmvscsi_ops->send_crq(hostdata,
+                                                   0xC001000000000000LL, 0))) {
                                        atomic_set(&hostdata->request_limit,
                                                   -1);
                                        dev_err(hostdata->dev, "error after reset\n");
@@ -1553,6 +1559,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        struct ibmvscsi_host_data *hostdata;
        struct Scsi_Host *host;
        struct device *dev = &vdev->dev;
+       struct srp_rport_identifiers ids;
+       struct srp_rport *rport;
        unsigned long wait_switch = 0;
        int rc;
 
@@ -1565,6 +1573,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
                goto scsi_host_alloc_failed;
        }
 
+       host->transportt = ibmvscsi_transport_template;
        hostdata = shost_priv(host);
        memset(hostdata, 0x00, sizeof(*hostdata));
        INIT_LIST_HEAD(&hostdata->sent);
@@ -1573,7 +1582,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        atomic_set(&hostdata->request_limit, -1);
        hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 
-       rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+       rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
        if (rc != 0 && rc != H_RESOURCE) {
                dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
                goto init_crq_failed;
@@ -1590,11 +1599,19 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        if (scsi_add_host(hostdata->host, hostdata->dev))
                goto add_host_failed;
 
+       /* we don't have a proper target_port_id so let's use the fake one */
+       memcpy(ids.port_id, hostdata->madapter_info.partition_name,
+              sizeof(ids.port_id));
+       ids.roles = SRP_RPORT_ROLE_TARGET;
+       rport = srp_rport_add(host, &ids);
+       if (IS_ERR(rport))
+               goto add_srp_port_failed;
+
        /* Try to send an initialization message.  Note that this is allowed
         * to fail if the other end is not acive.  In that case we don't
         * want to scan
         */
-       if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+       if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
            || rc == H_RESOURCE) {
                /*
                 * Wait around max init_timeout secs for the adapter to finish
@@ -1617,10 +1634,12 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        vdev->dev.driver_data = hostdata;
        return 0;
 
+      add_srp_port_failed:
+       scsi_remove_host(hostdata->host);
       add_host_failed:
        release_event_pool(&hostdata->pool, hostdata);
       init_pool_failed:
-       ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+       ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
       init_crq_failed:
        scsi_host_put(host);
       scsi_host_alloc_failed:
@@ -1631,9 +1650,10 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
 {
        struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
        release_event_pool(&hostdata->pool, hostdata);
-       ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
-                                  max_requests);
-       
+       ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
+                                       max_requests);
+
+       srp_remove_host(hostdata->host);
        scsi_remove_host(hostdata->host);
        scsi_host_put(hostdata->host);
 
@@ -1660,14 +1680,35 @@ static struct vio_driver ibmvscsi_driver = {
        }
 };
 
+static struct srp_function_template ibmvscsi_transport_functions = {
+};
+
 int __init ibmvscsi_module_init(void)
 {
-       return vio_register_driver(&ibmvscsi_driver);
+       int ret;
+
+       if (firmware_has_feature(FW_FEATURE_ISERIES))
+               ibmvscsi_ops = &iseriesvscsi_ops;
+       else if (firmware_has_feature(FW_FEATURE_VIO))
+               ibmvscsi_ops = &rpavscsi_ops;
+       else
+               return -ENODEV;
+
+       ibmvscsi_transport_template =
+               srp_attach_transport(&ibmvscsi_transport_functions);
+       if (!ibmvscsi_transport_template)
+               return -ENOMEM;
+
+       ret = vio_register_driver(&ibmvscsi_driver);
+       if (ret)
+               srp_release_transport(ibmvscsi_transport_template);
+       return ret;
 }
 
 void __exit ibmvscsi_module_exit(void)
 {
        vio_unregister_driver(&ibmvscsi_driver);
+       srp_release_transport(ibmvscsi_transport_template);
 }
 
 module_init(ibmvscsi_module_init);
index b19c2e26c2a541853ab01bccb803146fb78d3db5..46e850e302c7918306d96218ff606229ae230183 100644 (file)
@@ -98,21 +98,25 @@ struct ibmvscsi_host_data {
 };
 
 /* routines for managing a command/response queue */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-                           struct ibmvscsi_host_data *hostdata,
-                           int max_requests);
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-                               struct ibmvscsi_host_data *hostdata,
-                               int max_requests);
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-                             struct ibmvscsi_host_data *hostdata);
-
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-                               struct ibmvscsi_host_data *hostdata);
-
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                         struct ibmvscsi_host_data *hostdata);
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
-                     u64 word1, u64 word2);
+
+struct ibmvscsi_ops {
+       int (*init_crq_queue)(struct crq_queue *queue,
+                             struct ibmvscsi_host_data *hostdata,
+                             int max_requests);
+       void (*release_crq_queue)(struct crq_queue *queue,
+                                 struct ibmvscsi_host_data *hostdata,
+                                 int max_requests);
+       int (*reset_crq_queue)(struct crq_queue *queue,
+                              struct ibmvscsi_host_data *hostdata);
+       int (*reenable_crq_queue)(struct crq_queue *queue,
+                                 struct ibmvscsi_host_data *hostdata);
+       int (*send_crq)(struct ibmvscsi_host_data *hostdata,
+                      u64 word1, u64 word2);
+};
+
+extern struct ibmvscsi_ops iseriesvscsi_ops;
+extern struct ibmvscsi_ops rpavscsi_ops;
 
 #endif                         /* IBMVSCSI_H */
index 8ba7dd09d01d53e4cfc9bee44e94892f1b116243..82bcab688b44895fa0a17389100c65af7d95cf1c 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_srp.h>
 #include <scsi/scsi_tgt.h>
 #include <scsi/libsrp.h>
 #include <asm/hvcall.h>
@@ -68,9 +69,12 @@ struct vio_port {
        unsigned long liobn;
        unsigned long riobn;
        struct srp_target *target;
+
+       struct srp_rport *rport;
 };
 
 static struct workqueue_struct *vtgtd;
+static struct scsi_transport_template *ibmvstgt_transport_template;
 
 /*
  * These are fixed for the system and come from the Open Firmware device tree.
@@ -188,6 +192,7 @@ static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc,
 static void handle_cmd_queue(struct srp_target *target)
 {
        struct Scsi_Host *shost = target->shost;
+       struct srp_rport *rport = target_to_port(target)->rport;
        struct iu_entry *iue;
        struct srp_cmd *cmd;
        unsigned long flags;
@@ -200,7 +205,8 @@ retry:
                if (!test_and_set_bit(V_FLYING, &iue->flags)) {
                        spin_unlock_irqrestore(&target->lock, flags);
                        cmd = iue->sbuf->buf;
-                       err = srp_cmd_queue(shost, cmd, iue, 0);
+                       err = srp_cmd_queue(shost, cmd, iue,
+                                           (unsigned long)rport, 0);
                        if (err) {
                                eprintk("cannot queue cmd %p %d\n", cmd, err);
                                srp_iu_put(iue);
@@ -359,6 +365,16 @@ static void process_login(struct iu_entry *iue)
        union viosrp_iu *iu = vio_iu(iue);
        struct srp_login_rsp *rsp = &iu->srp.login_rsp;
        uint64_t tag = iu->srp.rsp.tag;
+       struct Scsi_Host *shost = iue->target->shost;
+       struct srp_target *target = host_to_srp_target(shost);
+       struct vio_port *vport = target_to_port(target);
+       struct srp_rport_identifiers ids;
+
+       memset(&ids, 0, sizeof(ids));
+       sprintf(ids.port_id, "%x", vport->dma_dev->unit_address);
+       ids.roles = SRP_RPORT_ROLE_INITIATOR;
+       if (!vport->rport)
+               vport->rport = srp_rport_add(shost, &ids);
 
        /* TODO handle case that requested size is wrong and
         * buffer format is wrong
@@ -412,7 +428,9 @@ static int process_tsk_mgmt(struct iu_entry *iue)
                fn = 0;
        }
        if (fn)
-               scsi_tgt_tsk_mgmt_request(iue->target->shost, fn,
+               scsi_tgt_tsk_mgmt_request(iue->target->shost,
+                                         (unsigned long)iue->target->shost,
+                                         fn,
                                          iu->srp.tsk_mgmt.task_tag,
                                          (struct scsi_lun *) &iu->srp.tsk_mgmt.lun,
                                          iue);
@@ -721,7 +739,8 @@ static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc)
        return 0;
 }
 
-static int ibmvstgt_tsk_mgmt_response(u64 mid, int result)
+static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost,
+                                     u64 itn_id, u64 mid, int result)
 {
        struct iu_entry *iue = (struct iu_entry *) ((void *) mid);
        union viosrp_iu *iu = vio_iu(iue);
@@ -747,6 +766,20 @@ static int ibmvstgt_tsk_mgmt_response(u64 mid, int result)
        return 0;
 }
 
+static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id,
+                                     int result)
+{
+       struct srp_target *target = host_to_srp_target(shost);
+       struct vio_port *vport = target_to_port(target);
+
+       if (result) {
+               eprintk("%p %d\n", shost, result);
+               srp_rport_del(vport->rport);
+               vport->rport = NULL;
+       }
+       return 0;
+}
+
 static ssize_t system_id_show(struct class_device *cdev, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
@@ -785,9 +818,9 @@ static struct scsi_host_template ibmvstgt_sht = {
        .max_sectors            = DEFAULT_MAX_SECTORS,
        .transfer_response      = ibmvstgt_cmd_done,
        .eh_abort_handler       = ibmvstgt_eh_abort_handler,
-       .tsk_mgmt_response      = ibmvstgt_tsk_mgmt_response,
        .shost_attrs            = ibmvstgt_attrs,
        .proc_name              = TGT_NAME,
+       .supported_mode         = MODE_TARGET,
 };
 
 static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
@@ -804,6 +837,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
        shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target));
        if (!shost)
                goto free_vport;
+       shost->transportt = ibmvstgt_transport_template;
        err = scsi_tgt_alloc_queue(shost);
        if (err)
                goto put_host;
@@ -837,8 +871,8 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
        err = scsi_add_host(shost, target->dev);
        if (err)
                goto destroy_queue;
-       return 0;
 
+       return 0;
 destroy_queue:
        crq_queue_destroy(target);
 free_srp_target:
@@ -857,6 +891,7 @@ static int ibmvstgt_remove(struct vio_dev *dev)
        struct vio_port *vport = target->ldata;
 
        crq_queue_destroy(target);
+       srp_remove_host(shost);
        scsi_remove_host(shost);
        scsi_tgt_free_queue(shost);
        srp_target_free(target);
@@ -909,15 +944,25 @@ static int get_system_info(void)
        return 0;
 }
 
+static struct srp_function_template ibmvstgt_transport_functions = {
+       .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response,
+       .it_nexus_response = ibmvstgt_it_nexus_response,
+};
+
 static int ibmvstgt_init(void)
 {
        int err = -ENOMEM;
 
        printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n");
 
+       ibmvstgt_transport_template =
+               srp_attach_transport(&ibmvstgt_transport_functions);
+       if (!ibmvstgt_transport_template)
+               return err;
+
        vtgtd = create_workqueue("ibmvtgtd");
        if (!vtgtd)
-               return err;
+               goto release_transport;
 
        err = get_system_info();
        if (err)
@@ -928,9 +973,10 @@ static int ibmvstgt_init(void)
                goto destroy_wq;
 
        return 0;
-
 destroy_wq:
        destroy_workqueue(vtgtd);
+release_transport:
+       srp_release_transport(ibmvstgt_transport_template);
        return err;
 }
 
@@ -940,6 +986,7 @@ static void ibmvstgt_exit(void)
 
        destroy_workqueue(vtgtd);
        vio_unregister_driver(&ibmvstgt_driver);
+       srp_release_transport(ibmvstgt_transport_template);
 }
 
 MODULE_DESCRIPTION("IBM Virtual SCSI Target");
index 6aeb5f003c3c912a0e53099d7d86c126f2ed505e..0775fdee5fa80cc4f9609167c8fc2e1769596d30 100644 (file)
@@ -53,7 +53,7 @@ struct srp_lp_event {
 /** 
  * standard interface for handling logical partition events.
  */
-static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
 {
        struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
 
@@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
 /* ------------------------------------------------------------
  * Routines for driver initialization
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-                           struct ibmvscsi_host_data *hostdata,
-                           int max_requests)
+static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
+                                      struct ibmvscsi_host_data *hostdata,
+                                      int max_requests)
 {
        int rc;
 
@@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
                goto viopath_open_failed;
        }
 
-       rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+       rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
        if (rc < 0) {
                printk("vio_setHandler failed with rc %d in open_event_path\n",
                       rc);
@@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        return -1;
 }
 
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-                               struct ibmvscsi_host_data *hostdata,
-                               int max_requests)
+static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
+                                          struct ibmvscsi_host_data *hostdata,
+                                          int max_requests)
 {
        vio_clearHandler(viomajorsubtype_scsi);
        viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
@@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
  *
  * no-op for iSeries
  */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-                             struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
+                                       struct ibmvscsi_host_data *hostdata)
 {
        return 0;
 }
@@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
  *
  * no-op for iSeries
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-                               struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
+                                          struct ibmvscsi_host_data *hostdata)
 {
        return 0;
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * iseriesvscsi_send_crq: - Send a CRQ
  * @hostdata:  the adapter
  * @word1:     the first 64 bits of the data
  * @word2:     the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+                                u64 word1, u64 word2)
 {
        single_host_data = hostdata;
        return HvCallEvent_signalLpEventFast(viopath_hostLp,
@@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
                                             VIOVERSION << 16, word1, word2, 0,
                                             0);
 }
+
+struct ibmvscsi_ops iseriesvscsi_ops = {
+       .init_crq_queue = iseriesvscsi_init_crq_queue,
+       .release_crq_queue = iseriesvscsi_release_crq_queue,
+       .reset_crq_queue = iseriesvscsi_reset_crq_queue,
+       .reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
+       .send_crq = iseriesvscsi_send_crq,
+};
index 9c14e789df5f875ad006ce179299a8fe864ace7c..182146100dc12220ee20e55d44cb8e0d3a7bf618 100644 (file)
@@ -42,14 +42,14 @@ static unsigned int partition_number = -1;
  * Routines for managing the command/response queue
  */
 /**
- * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * rpavscsi_handle_event: - Interrupt handler for crq events
  * @irq:       number of irq to handle, not used
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
  *
  * Disables interrupts and schedules srp_task
  * Always returns IRQ_HANDLED
  */
-static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
+static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
 {
        struct ibmvscsi_host_data *hostdata =
            (struct ibmvscsi_host_data *)dev_instance;
@@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
  * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
  * the crq with the hypervisor.
  */
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-                               struct ibmvscsi_host_data *hostdata,
-                               int max_requests)
+static void rpavscsi_release_crq_queue(struct crq_queue *queue,
+                                      struct ibmvscsi_host_data *hostdata,
+                                      int max_requests)
 {
        long rc;
        struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * rpavscsi_send_crq: - Send a CRQ
  * @hostdata:  the adapter
  * @word1:     the first 64 bits of the data
  * @word2:     the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+                            u64 word1, u64 word2)
 {
        struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 
@@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
 }
 
 /**
- * ibmvscsi_task: - Process srps asynchronously
+ * rpavscsi_task: - Process srps asynchronously
  * @data:      ibmvscsi_host_data of host
  */
-static void ibmvscsi_task(void *data)
+static void rpavscsi_task(void *data)
 {
        struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
        struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -189,6 +190,42 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
        hostdata->madapter_info.os_type = 2;
 }
 
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:     crq_queue to initialize and register
+ * @hostdata:  ibmvscsi_host_data of host
+ *
+ */
+static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
+                                   struct ibmvscsi_host_data *hostdata)
+{
+       int rc;
+       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+       /* Close the CRQ */
+       do {
+               rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+       } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
+
+       /* Clean out the queue */
+       memset(queue->msgs, 0x00, PAGE_SIZE);
+       queue->cur = 0;
+
+       set_adapter_info(hostdata);
+
+       /* And re-open it again */
+       rc = plpar_hcall_norets(H_REG_CRQ,
+                               vdev->unit_address,
+                               queue->msg_token, PAGE_SIZE);
+       if (rc == 2) {
+               /* Adapter is good, but other end is not ready */
+               dev_warn(hostdata->dev, "Partner adapter not ready\n");
+       } else if (rc != 0) {
+               dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
+       }
+       return rc;
+}
+
 /**
  * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
  * @queue:     crq_queue to initialize and register
@@ -198,9 +235,9 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
  * the crq with the hypervisor.
  * Returns zero on success.
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-                           struct ibmvscsi_host_data *hostdata,
-                           int max_requests)
+static int rpavscsi_init_crq_queue(struct crq_queue *queue,
+                                  struct ibmvscsi_host_data *hostdata,
+                                  int max_requests)
 {
        int rc;
        int retrc;
@@ -227,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
                                queue->msg_token, PAGE_SIZE);
        if (rc == H_RESOURCE)
                /* maybe kexecing and resource is busy. try a reset */
-               rc = ibmvscsi_reset_crq_queue(queue,
+               rc = rpavscsi_reset_crq_queue(queue,
                                              hostdata);
 
        if (rc == 2) {
@@ -240,7 +277,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        }
 
        if (request_irq(vdev->irq,
-                       ibmvscsi_handle_event,
+                       rpavscsi_handle_event,
                        0, "ibmvscsi", (void *)hostdata) != 0) {
                dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
                        vdev->irq);
@@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        queue->cur = 0;
        spin_lock_init(&queue->lock);
 
-       tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+       tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
                     (unsigned long)hostdata);
 
        return retrc;
@@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
  * @hostdata:  ibmvscsi_host_data of host
  *
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-                                struct ibmvscsi_host_data *hostdata)
+static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
+                                      struct ibmvscsi_host_data *hostdata)
 {
        int rc;
        struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -297,38 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
        return rc;
 }
 
-/**
- * reset_crq_queue: - resets a crq after a failure
- * @queue:     crq_queue to initialize and register
- * @hostdata:  ibmvscsi_host_data of host
- *
- */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-                             struct ibmvscsi_host_data *hostdata)
-{
-       int rc;
-       struct vio_dev *vdev = to_vio_dev(hostdata->dev);
-
-       /* Close the CRQ */
-       do {
-               rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-       } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
-
-       /* Clean out the queue */
-       memset(queue->msgs, 0x00, PAGE_SIZE);
-       queue->cur = 0;
-
-       set_adapter_info(hostdata);
-
-       /* And re-open it again */
-       rc = plpar_hcall_norets(H_REG_CRQ,
-                               vdev->unit_address,
-                               queue->msg_token, PAGE_SIZE);
-       if (rc == 2) {
-               /* Adapter is good, but other end is not ready */
-               dev_warn(hostdata->dev, "Partner adapter not ready\n");
-       } else if (rc != 0) {
-               dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
-       }
-       return rc;
-}
+struct ibmvscsi_ops rpavscsi_ops = {
+       .init_crq_queue = rpavscsi_init_crq_queue,
+       .release_crq_queue = rpavscsi_release_crq_queue,
+       .reset_crq_queue = rpavscsi_reset_crq_queue,
+       .reenable_crq_queue = rpavscsi_reenable_crq_queue,
+       .send_crq = rpavscsi_send_crq,
+};
index 1cc01acc28089060b6aa39f677e630b06c3a83f9..d81bb076a15a887b062f8325061cb2f9d46b6430 100644 (file)
@@ -82,14 +82,12 @@ typedef struct idescsi_pc_s {
  */
 #define PC_DMA_IN_PROGRESS             0       /* 1 while DMA in progress */
 #define PC_WRITING                     1       /* Data direction */
-#define PC_TRANSFORM                   2       /* transform SCSI commands */
 #define PC_TIMEDOUT                    3       /* command timed out */
 #define PC_DMA_OK                      4       /* Use DMA */
 
 /*
  *     SCSI command transformation layer
  */
-#define IDESCSI_TRANSFORM              0       /* Enable/Disable transformation */
 #define IDESCSI_SG_TRANSFORM           1       /* /dev/sg transformation */
 
 /*
@@ -175,7 +173,8 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
        char *buf;
 
        while (bcount) {
-               if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
+               if (pc->sg - scsi_sglist(pc->scsi_cmd) >
+                                                scsi_sg_count(pc->scsi_cmd)) {
                        printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
                        idescsi_discard_data (drive, bcount);
                        return;
@@ -210,7 +209,8 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
        char *buf;
 
        while (bcount) {
-               if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
+               if (pc->sg - scsi_sglist(pc->scsi_cmd) >
+                                                scsi_sg_count(pc->scsi_cmd)) {
                        printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
                        idescsi_output_zeros (drive, bcount);
                        return;
@@ -239,77 +239,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
        }
 }
 
-/*
- *     Most of the SCSI commands are supported directly by ATAPI devices.
- *     idescsi_transform_pc handles the few exceptions.
- */
-static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc)
-{
-       u8 *c = pc->c, *scsi_buf = pc->buffer, *sc = pc->scsi_cmd->cmnd;
-       char *atapi_buf;
-
-       if (!test_bit(PC_TRANSFORM, &pc->flags))
-               return;
-       if (drive->media == ide_cdrom || drive->media == ide_optical) {
-               if (c[0] == READ_6 || c[0] == WRITE_6) {
-                       c[8] = c[4];            c[5] = c[3];            c[4] = c[2];
-                       c[3] = c[1] & 0x1f;     c[2] = 0;               c[1] &= 0xe0;
-                       c[0] += (READ_10 - READ_6);
-               }
-               if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
-                       unsigned short new_len;
-                       if (!scsi_buf)
-                               return;
-                       if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL)
-                               return;
-                       memset(atapi_buf, 0, pc->buffer_size + 4);
-                       memset (c, 0, 12);
-                       c[0] = sc[0] | 0x40;
-                       c[1] = sc[1];
-                       c[2] = sc[2];
-                       new_len = sc[4] + 4;
-                       c[8] = new_len;
-                       c[7] = new_len >> 8;
-                       c[9] = sc[5];
-                       if (c[0] == MODE_SELECT_10) {
-                               atapi_buf[1] = scsi_buf[0];     /* Mode data length */
-                               atapi_buf[2] = scsi_buf[1];     /* Medium type */
-                               atapi_buf[3] = scsi_buf[2];     /* Device specific parameter */
-                               atapi_buf[7] = scsi_buf[3];     /* Block descriptor length */
-                               memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4);
-                       }
-                       pc->buffer = atapi_buf;
-                       pc->request_transfer += 4;
-                       pc->buffer_size += 4;
-               }
-       }
-}
-
-static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc)
-{
-       u8 *atapi_buf = pc->buffer;
-       u8 *sc = pc->scsi_cmd->cmnd;
-       u8 *scsi_buf = pc->scsi_cmd->request_buffer;
-
-       if (!test_bit(PC_TRANSFORM, &pc->flags))
-               return;
-       if (drive->media == ide_cdrom || drive->media == ide_optical) {
-               if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) {
-                       scsi_buf[0] = atapi_buf[1];             /* Mode data length */
-                       scsi_buf[1] = atapi_buf[2];             /* Medium type */
-                       scsi_buf[2] = atapi_buf[3];             /* Device specific parameter */
-                       scsi_buf[3] = atapi_buf[7];             /* Block descriptor length */
-                       memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8);
-               }
-               if (pc->c[0] == INQUIRY) {
-                       scsi_buf[2] |= 2;                       /* ansi_revision */
-                       scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; /* response data format */
-               }
-       }
-       if (atapi_buf && atapi_buf != scsi_buf)
-               kfree(atapi_buf);
-}
-
 static void hexdump(u8 *x, int len)
 {
        int i;
@@ -393,7 +322,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
        idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
        int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
        struct Scsi_Host *host;
-       u8 *scsi_buf;
        int errors = rq->errors;
        unsigned long flags;
 
@@ -434,15 +362,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
                pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
        } else {
                pc->scsi_cmd->result = DID_OK << 16;
-               idescsi_transform_pc2 (drive, pc);
-               if (log) {
-                       printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number);
-                       if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) {
-                               printk(", rst = ");
-                               scsi_buf = pc->scsi_cmd->request_buffer;
-                               hexdump(scsi_buf, min_t(unsigned, 16, pc->scsi_cmd->request_bufflen));
-                       } else printk("\n");
-               }
        }
        host = pc->scsi_cmd->device->host;
        spin_lock_irqsave(host->host_lock, flags);
@@ -637,19 +556,14 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
                return 1;
 
        sg = hwif->sg_table;
-       scsi_sg = pc->scsi_cmd->request_buffer;
-       segments = pc->scsi_cmd->use_sg;
+       scsi_sg = scsi_sglist(pc->scsi_cmd);
+       segments = scsi_sg_count(pc->scsi_cmd);
 
        if (segments > hwif->sg_max_nents)
                return 1;
 
-       if (!segments) {
-               hwif->sg_nents = 1;
-               sg_init_one(sg, pc->scsi_cmd->request_buffer, pc->request_transfer);
-       } else {
-               hwif->sg_nents = segments;
-               memcpy(sg, scsi_sg, sizeof(*sg) * segments);
-       }
+       hwif->sg_nents = segments;
+       memcpy(sg, scsi_sg, sizeof(*sg) * segments);
 
        return 0;
 }
@@ -744,7 +658,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
 {
        if (drive->id && (drive->id->config & 0x0060) == 0x20)
                set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
-       set_bit(IDESCSI_TRANSFORM, &scsi->transform);
        clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 #if IDESCSI_DEBUG_LOG
        set_bit(IDESCSI_LOG_CMD, &scsi->log);
@@ -758,6 +671,7 @@ static void ide_scsi_remove(ide_drive_t *drive)
        struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
        struct gendisk *g = scsi->disk;
 
+       scsi_remove_host(scsihost);
        ide_proc_unregister_driver(drive, scsi->driver);
 
        ide_unregister_region(g);
@@ -766,7 +680,6 @@ static void ide_scsi_remove(ide_drive_t *drive)
        g->private_data = NULL;
        put_disk(g);
 
-       scsi_remove_host(scsihost);
        ide_scsi_put(scsi);
 }
 
@@ -838,6 +751,8 @@ static struct block_device_operations idescsi_ops = {
 static int idescsi_slave_configure(struct scsi_device * sdp)
 {
        /* Configure detected device */
+       sdp->use_10_for_rw = 1;
+       sdp->use_10_for_ms = 1;
        scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);
        return 0;
 }
@@ -862,24 +777,6 @@ static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg)
        return -EINVAL;
 }
 
-static inline int should_transform(ide_drive_t *drive, struct scsi_cmnd *cmd)
-{
-       idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
-       /* this was a layering violation and we can't support it
-          anymore, sorry. */
-#if 0
-       struct gendisk *disk = cmd->request->rq_disk;
-
-       if (disk) {
-               struct struct scsi_device_Template **p = disk->private_data;
-               if (strcmp((*p)->scsi_driverfs_driver.name, "sg") == 0)
-                       return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
-       }
-#endif
-       return test_bit(IDESCSI_TRANSFORM, &scsi->transform);
-}
-
 static int idescsi_queue (struct scsi_cmnd *cmd,
                void (*done)(struct scsi_cmnd *))
 {
@@ -905,23 +802,14 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
        pc->flags = 0;
        pc->rq = rq;
        memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
-       if (cmd->use_sg) {
-               pc->buffer = NULL;
-               pc->sg = cmd->request_buffer;
-       } else {
-               pc->buffer = cmd->request_buffer;
-               pc->sg = NULL;
-       }
+       pc->buffer = NULL;
+       pc->sg = scsi_sglist(cmd);
        pc->b_count = 0;
-       pc->request_transfer = pc->buffer_size = cmd->request_bufflen;
+       pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd);
        pc->scsi_cmd = cmd;
        pc->done = done;
        pc->timeout = jiffies + cmd->timeout_per_command;
 
-       if (should_transform(drive, cmd))
-               set_bit(PC_TRANSFORM, &pc->flags);
-       idescsi_transform_pc1 (drive, pc);
-
        if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
                printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
                hexdump(cmd->cmnd, cmd->cmd_len);
index 005d2b05f32d2fbbec6dc50b54f0cff850cd2808..74cdc1f0a78f976bbf2d64397566430caba7ca32 100644 (file)
@@ -740,10 +740,6 @@ static void imm_interrupt(struct work_struct *work)
        struct Scsi_Host *host = cmd->device->host;
        unsigned long flags;
 
-       if (!cmd) {
-               printk("IMM: bug in imm_interrupt\n");
-               return;
-       }
        if (imm_engine(dev, cmd)) {
                schedule_delayed_work(&dev->imm_tq, 1);
                return;
index 312190a6938903ddb1e7206a8ce4af7eefa2444a..ab7cbf3449ce07639880a8b55daadad03a751c4f 100644 (file)
@@ -343,7 +343,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
        instance = cmd->device->host;
        hostdata = (struct IN2000_hostdata *) instance->hostdata;
 
-       DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->pid))
+       DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->serial_number))
 
 /* Set up a few fields in the Scsi_Cmnd structure for our own use:
  *  - host_scribble is the pointer to the next cmd in the input queue
@@ -427,7 +427,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 
        in2000_execute(cmd->device->host);
 
-       DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid))
+       DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
            return 0;
 }
 
@@ -703,7 +703,7 @@ static void in2000_execute(struct Scsi_Host *instance)
         * to search the input_Q again...
         */
 
-       DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid))
+       DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number))
 
 }
 
@@ -1147,7 +1147,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
        case CSR_XFER_DONE | PHS_COMMAND:
        case CSR_UNEXP | PHS_COMMAND:
        case CSR_SRV_REQ | PHS_COMMAND:
-               DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid))
+               DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number))
                    transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
                hostdata->state = S_CONNECTED;
                break;
@@ -1189,7 +1189,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
                switch (msg) {
 
                case COMMAND_COMPLETE:
-                       DB(DB_INTR, printk("CCMP-%ld", cmd->pid))
+                       DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number))
                            write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
                        hostdata->state = S_PRE_CMP_DISC;
                        break;
@@ -1327,7 +1327,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 
                write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
                if (phs == 0x60) {
-                       DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid))
+                       DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number))
                            cmd->SCp.Message = COMMAND_COMPLETE;
                        lun = read_3393(hostdata, WD_TARGET_LUN);
                        DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
@@ -1348,7 +1348,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 
                        in2000_execute(instance);
                } else {
-                       printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->pid);
+                       printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->serial_number);
                }
                break;
 
@@ -1415,7 +1415,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
                        spin_unlock_irqrestore(instance->host_lock, flags);
                        return IRQ_HANDLED;
                }
-               DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid))
+               DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number))
                    hostdata->connected = NULL;
                hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
                hostdata->state = S_UNCONNECTED;
@@ -1440,7 +1440,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
  */
 
                write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
-               DB(DB_INTR, printk("DISC-%ld", cmd->pid))
+               DB(DB_INTR, printk("DISC-%ld", cmd->serial_number))
                    if (cmd == NULL) {
                        printk(" - Already disconnected! ");
                        hostdata->state = S_UNCONNECTED;
@@ -1573,7 +1573,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
                } else
                        hostdata->state = S_CONNECTED;
 
-               DB(DB_INTR, printk("-%ld", cmd->pid))
+               DB(DB_INTR, printk("-%ld", cmd->serial_number))
                    break;
 
        default:
@@ -1702,7 +1702,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd)
                                prev->host_scribble = cmd->host_scribble;
                        cmd->host_scribble = NULL;
                        cmd->result = DID_ABORT << 16;
-                       printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->pid);
+                       printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->serial_number);
                        cmd->scsi_done(cmd);
                        return SUCCESS;
                }
@@ -1723,7 +1723,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd)
 
        if (hostdata->connected == cmd) {
 
-               printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->pid);
+               printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->serial_number);
 
                printk("sending wd33c93 ABORT command - ");
                write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
@@ -2268,7 +2268,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
                strcat(bp, "\nconnected:     ");
                if (hd->connected) {
                        cmd = (Scsi_Cmnd *) hd->connected;
-                       sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+                       sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
                        strcat(bp, tbuf);
                }
        }
@@ -2276,7 +2276,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
                strcat(bp, "\ninput_Q:       ");
                cmd = (Scsi_Cmnd *) hd->input_Q;
                while (cmd) {
-                       sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+                       sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
                        strcat(bp, tbuf);
                        cmd = (Scsi_Cmnd *) cmd->host_scribble;
                }
@@ -2285,7 +2285,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
                strcat(bp, "\ndisconnected_Q:");
                cmd = (Scsi_Cmnd *) hd->disconnected_Q;
                while (cmd) {
-                       sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+                       sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
                        strcat(bp, tbuf);
                        cmd = (Scsi_Cmnd *) cmd->host_scribble;
                }
index 492a51bd6aa899bb8d64a5cf60ab304913d8d7c2..2ed099e2c20d50ae6d91dacd3832c57f61de6c24 100644 (file)
@@ -204,8 +204,8 @@ module_param(ips, charp, 0);
 /*
  * DRIVER_VER
  */
-#define IPS_VERSION_HIGH        "7.12"
-#define IPS_VERSION_LOW         ".05 "
+#define IPS_VERSION_HIGH        IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING
+#define IPS_VERSION_LOW         "." IPS_VER_BUILD_STRING " "
 
 #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
@@ -656,6 +656,8 @@ ips_release(struct Scsi_Host *sh)
 
        METHOD_TRACE("ips_release", 1);
 
+       scsi_remove_host(sh);
+
        for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ;
 
        if (i == IPS_MAX_ADAPTERS) {
@@ -707,7 +709,6 @@ ips_release(struct Scsi_Host *sh)
        /* free IRQ */
        free_irq(ha->irq, ha);
 
-       scsi_remove_host(sh);
        scsi_host_put(sh);
 
        ips_released_controllers++;
@@ -6946,7 +6947,7 @@ module_exit(ips_module_exit);
 static int __devinit
 ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
 {
-       int index;
+       int uninitialized_var(index);
        int rc;
 
        METHOD_TRACE("ips_insert_device", 1);
index 24123d537c5859be2b76e58bcbb2f18037a2dc0a..3bcbd9ff056b07f124608ac8fbd979cdecb0175a 100644 (file)
@@ -1172,12 +1172,13 @@ typedef struct {
 *************************************************************************/
 
 #define IPS_VER_MAJOR 7
-#define IPS_VER_MAJOR_STRING "7"
+#define IPS_VER_MAJOR_STRING __stringify(IPS_VER_MAJOR)
 #define IPS_VER_MINOR 12
-#define IPS_VER_MINOR_STRING "12"
-#define IPS_VER_BUILD 02
-#define IPS_VER_BUILD_STRING "02"
-#define IPS_VER_STRING "7.12.02"
+#define IPS_VER_MINOR_STRING __stringify(IPS_VER_MINOR)
+#define IPS_VER_BUILD 05
+#define IPS_VER_BUILD_STRING __stringify(IPS_VER_BUILD)
+#define IPS_VER_STRING IPS_VER_MAJOR_STRING "." \
+               IPS_VER_MINOR_STRING "." IPS_VER_BUILD_STRING
 #define IPS_RELEASE_ID 0x00020000
 #define IPS_BUILD_IDENT 761
 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
index 732446e63963557dab5136c10c361acbc1a18a9a..2ad0a27dbaabf534718c67c7e9ef8ed5b93f70bb 100644 (file)
@@ -392,7 +392,7 @@ static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir)
 }
 
 int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
-                 u64 addr)
+                 u64 itn_id, u64 addr)
 {
        enum dma_data_direction dir;
        struct scsi_cmnd *sc;
@@ -428,7 +428,8 @@ int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
        sc->request_bufflen = len;
        sc->request_buffer = (void *) (unsigned long) addr;
        sc->tag = tag;
-       err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag);
+       err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
+                                    cmd->tag);
        if (err)
                scsi_host_put_command(shost, sc);
 
index 2e3c01bebed6801541ffab6c63c9c0a2f0f50d13..149fdd25f8e83d982c1db15f6d103798a6e1b1c8 100644 (file)
@@ -43,7 +43,6 @@
 #include "lpfc_crtn.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
-#include "lpfc_vport.h"
 #include "lpfc_debugfs.h"
 
 #ifdef CONFIG_LPFC_DEBUG_FS
@@ -902,7 +901,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                }
        }
 
-       vport->disc_trc = kmalloc(
+       vport->disc_trc = kmzlloc(
                (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
                GFP_KERNEL);
 
@@ -913,8 +912,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                goto debug_failed;
        }
        atomic_set(&vport->disc_trc_cnt, 0);
-       memset(vport->disc_trc, 0,
-               (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc));
 
        snprintf(name, sizeof(name), "discovery_trace");
        vport->debug_disc_trc =
index 414350ab584e4f755f7c2ff0d5264f7170d94839..ecebdfa0047007fd4385427eea0805522101093a 100644 (file)
@@ -43,7 +43,6 @@
 #include "lpfc_crtn.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
-#include "lpfc_vport.h"
 
 static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
 static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
@@ -1266,11 +1265,10 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
        uint32_t *HashWorking;
        uint32_t *pwwnn = (uint32_t *) phba->wwnn;
 
-       HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL);
+       HashWorking = kcalloc(80, sizeof(uint32_t), GFP_KERNEL);
        if (!HashWorking)
                return;
 
-       memset(HashWorking, 0, (80 * sizeof(uint32_t)));
        HashWorking[0] = HashWorking[78] = *pwwnn++;
        HashWorking[1] = HashWorking[79] = *pwwnn;
 
index 17d7dc05149b29a232680a85906b292d848c84a3..cd674938ccd53ab2c5f7ebe7a7e563930f6dcd68 100644 (file)
@@ -202,10 +202,9 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport)
        dma_addr_t pdma_phys;
        uint16_t iotag;
 
-       psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
+       psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
        if (!psb)
                return NULL;
-       memset(psb, 0, sizeof (struct lpfc_scsi_buf));
 
        /*
         * Get memory from the pci pool to map the virt space to pci bus space
index ce5ff2bccba68198f0a3570029bb8a4cdec6441e..e5337ad4121efd36f9d6493dc6ea011cd9404b6c 100644 (file)
@@ -675,7 +675,7 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
        uint32_t hbqno;
 
        hbqno = tag >> 16;
-       if (hbqno > LPFC_MAX_HBQS)
+       if (hbqno >= LPFC_MAX_HBQS)
                return NULL;
 
        list_for_each_entry(d_buf, &phba->hbqs[hbqno].hbq_buffer_list, list) {
index da56163c30a8f6404b02c16743595561a7b2a692..e7e11f282c8f4357d419e8508746871cdda1a492 100644 (file)
@@ -4416,8 +4416,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
        scmd = &adapter->int_scmd;
        memset(scmd, 0, sizeof(Scsi_Cmnd));
 
-       sdev = kmalloc(sizeof(struct scsi_device), GFP_KERNEL);
-       memset(sdev, 0, sizeof(struct scsi_device));
+       sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
        scmd->device = sdev;
 
        scmd->device->host = adapter->host;
index 1bdddad48571d812895ae6824689ab7fa25bc4dc..b264b499d982203e00134e19f1aa80c41014c750 100644 (file)
@@ -48,13 +48,12 @@ mvme16x_probe(struct device *dev)
                goto out;
        }
 
-       hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+       hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
        if (hostdata == NULL) {
                printk(KERN_ERR "mvme16x-scsi: "
                                "Failed to allocate host data\n");
                goto out;
        }
-       memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 
        /* Fill in the required pieces of hostdata */
        hostdata->base = (void __iomem *)0xfff47000UL;
index 030ba49f33ff3f4a338da8331456f47a0a9ebcff..016c462bc771a80fddce05894445fc1cdb7dd384 100644 (file)
@@ -8143,12 +8143,7 @@ static int ncr53c8xx_abort(struct scsi_cmnd *cmd)
        unsigned long flags;
        struct scsi_cmnd *done_list;
 
-#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
-       printk("ncr53c8xx_abort: pid=%lu serial_number=%ld\n",
-               cmd->pid, cmd->serial_number);
-#else
-       printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid);
-#endif
+       printk("ncr53c8xx_abort: command pid %lu\n", cmd->serial_number);
 
        NCR_LOCK_NCB(np, flags);
 
@@ -8528,18 +8523,15 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
 }
 
 
-int ncr53c8xx_release(struct Scsi_Host *host)
+void ncr53c8xx_release(struct Scsi_Host *host)
 {
-       struct host_data *host_data;
+       struct host_data *host_data = shost_priv(host);
 #ifdef DEBUG_NCR53C8XX
        printk("ncr53c8xx: release\n");
 #endif
-       if (!host)
-               return 1;
-       host_data = (struct host_data *)host->hostdata;
-       if (host_data && host_data->ncb)
+       if (host_data->ncb)
                ncr_detach(host_data->ncb);
-       return 1;
+       scsi_host_put(host);
 }
 
 static void ncr53c8xx_set_period(struct scsi_target *starget, int period)
index b39357d9af8d1bcb82ab063e39784d2ef84bfe18..0e008dacf679c0df060c9af4c50efb7272a2e2ea 100644 (file)
@@ -1321,7 +1321,7 @@ struct ncr_device {
 };
 
 extern struct Scsi_Host *ncr_attach(struct scsi_host_template *tpnt, int unit, struct ncr_device *device);
-extern int ncr53c8xx_release(struct Scsi_Host *host);
+extern void ncr53c8xx_release(struct Scsi_Host *host);
 irqreturn_t ncr53c8xx_intr(int irq, void *dev_id);
 extern int ncr53c8xx_init(void);
 extern void ncr53c8xx_exit(void);
index 08060fb478b621e453bae3e46e7ca8611d185b93..331b789937c4e0a700e4d1406f8e6a708e9a3e03 100644 (file)
@@ -3298,7 +3298,7 @@ static ssize_t osst_write(struct file * filp, const char __user * buf, size_t co
        char                * name = tape_name(STp);
 
 
-       if (down_interruptible(&STp->lock))
+       if (mutex_lock_interruptible(&STp->lock))
                return (-ERESTARTSYS);
 
        /*
@@ -3600,7 +3600,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name
 out:
        if (SRpnt != NULL) osst_release_request(SRpnt);
 
-       up(&STp->lock);
+       mutex_unlock(&STp->lock);
 
        return retval;
 }
@@ -3619,7 +3619,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo
        char                * name  = tape_name(STp);
 
 
-       if (down_interruptible(&STp->lock))
+       if (mutex_lock_interruptible(&STp->lock))
                return (-ERESTARTSYS);
 
        /*
@@ -3785,7 +3785,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo
 out:
        if (SRpnt != NULL) osst_release_request(SRpnt);
 
-       up(&STp->lock);
+       mutex_unlock(&STp->lock);
 
        return retval;
 }
@@ -4852,7 +4852,7 @@ static int osst_ioctl(struct inode * inode,struct file * file,
        char                * name  = tape_name(STp);
        void        __user  * p     = (void __user *)arg;
 
-       if (down_interruptible(&STp->lock))
+       if (mutex_lock_interruptible(&STp->lock))
                return -ERESTARTSYS;
 
 #if DEBUG
@@ -5163,14 +5163,14 @@ static int osst_ioctl(struct inode * inode,struct file * file,
        }
        if (SRpnt) osst_release_request(SRpnt);
 
-       up(&STp->lock);
+       mutex_unlock(&STp->lock);
 
        return scsi_ioctl(STp->device, cmd_in, p);
 
 out:
        if (SRpnt) osst_release_request(SRpnt);
 
-       up(&STp->lock);
+       mutex_unlock(&STp->lock);
 
        return retval;
 }
@@ -5778,13 +5778,12 @@ static int osst_probe(struct device *dev)
        dev_num = i;
 
        /* allocate a struct osst_tape for this device */
-       tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
-       if (tpnt == NULL) {
+       tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
+       if (!tpnt) {
                write_unlock(&os_scsi_tapes_lock);
                printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
                goto out_put_disk;
        }
-       memset(tpnt, 0, sizeof(struct osst_tape));
 
        /* allocate a buffer for this device */
        i = SDp->host->sg_tablesize;
@@ -5866,7 +5865,7 @@ static int osst_probe(struct device *dev)
        tpnt->modes[2].defined = 1;
        tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
 
-       init_MUTEX(&tpnt->lock);
+       mutex_init(&tpnt->lock);
        osst_nr_dev++;
        write_unlock(&os_scsi_tapes_lock);
 
index 2cc7b5a1606a089b0346d0e8d53a914929bdde8e..5aa22740b5dfaebcb3d0f812c318620177cc14de 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <asm/byteorder.h>
 #include <linux/completion.h>
+#include <linux/mutex.h>
 
 /*     FIXME - rename and use the following two types or delete them!
  *              and the types really should go to st.h anyway...
@@ -532,7 +533,7 @@ struct osst_tape {
   struct scsi_driver *driver;
   unsigned capacity;
   struct scsi_device *device;
-  struct semaphore lock;       /* for serialization */
+  struct mutex lock;           /* for serialization */
   struct completion wait;      /* for SCSI commands */
   struct osst_buffer * buffer;
 
index 445cfbbca9b3c9faa1a85dab07d01d5b1a10f0dd..a45d89b14147576fac94963774c4ec1241f15183 100644 (file)
@@ -25,8 +25,6 @@
 
 ***********************************************************************/
 
-/* $Id: nsp_cs.c,v 1.23 2003/08/18 11:09:19 elca Exp $ */
-
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -59,7 +57,7 @@
 #include "nsp_cs.h"
 
 MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
-MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.23 $");
+MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");
 MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
@@ -83,10 +81,6 @@ static struct scsi_host_template nsp_driver_template = {
        .proc_name               = "nsp_cs",
        .proc_info               = nsp_proc_info,
        .name                    = "WorkBit NinjaSCSI-3/32Bi(16bit)",
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-       .detect                  = nsp_detect_old,
-       .release                 = nsp_release_old,
-#endif
        .info                    = nsp_info,
        .queuecommand            = nsp_queuecommand,
 /*     .eh_abort_handler        = nsp_eh_abort,*/
@@ -97,9 +91,6 @@ static struct scsi_host_template nsp_driver_template = {
        .sg_tablesize            = SG_ALL,
        .cmd_per_lun             = 1,
        .use_clustering          = DISABLE_CLUSTERING,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
-       .use_new_eh_code         = 1,
-#endif
 };
 
 static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
@@ -1313,11 +1304,7 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht)
        nsp_hw_data *data_b = &nsp_data_base, *data;
 
        nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
        host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data));
-#else
-       host = scsi_register(sht, sizeof(nsp_hw_data));
-#endif
        if (host == NULL) {
                nsp_dbg(NSP_DEBUG_INIT, "host failed");
                return NULL;
@@ -1354,37 +1341,6 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht)
        return host; /* detect done. */
 }
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int nsp_detect_old(struct scsi_host_template *sht)
-{
-       if (nsp_detect(sht) == NULL) {
-               return 0;
-       } else {
-               //MOD_INC_USE_COUNT;
-               return 1;
-       }
-}
-
-
-static int nsp_release_old(struct Scsi_Host *shpnt)
-{
-       //nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;
-
-       /* PCMCIA Card Service dose same things below. */
-       /* So we do nothing.                           */
-       //if (shpnt->irq) {
-       //      free_irq(shpnt->irq, data->ScsiInfo);
-       //}
-       //if (shpnt->io_port) {
-       //      release_region(shpnt->io_port, shpnt->n_io_port);
-       //}
-
-       //MOD_DEC_USE_COUNT;
-
-       return 0;
-}
-#endif
-
 /*----------------------------------------------------------------*/
 /* return info string                                            */
 /*----------------------------------------------------------------*/
@@ -1403,19 +1359,9 @@ static const char *nsp_info(struct Scsi_Host *shpnt)
                        nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
                } \
        } while(0)
-static int
-nsp_proc_info(
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       struct Scsi_Host *host,
-#endif
-       char  *buffer,
-       char **start,
-       off_t  offset,
-       int    length,
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       int    hostno,
-#endif
-       int    inout)
+
+static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+                        off_t offset, int length, int inout)
 {
        int id;
        char *pos = buffer;
@@ -1423,24 +1369,13 @@ nsp_proc_info(
        int speed;
        unsigned long flags;
        nsp_hw_data *data;
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       struct Scsi_Host *host;
-#else
        int hostno;
-#endif
+
        if (inout) {
                return -EINVAL;
        }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
        hostno = host->host_no;
-#else
-       /* search this HBA host */
-       host = scsi_host_hn_get(hostno);
-       if (host == NULL) {
-               return -ESRCH;
-       }
-#endif
        data = (nsp_hw_data *)host->hostdata;
 
 
@@ -1675,10 +1610,6 @@ static int nsp_cs_config(struct pcmcia_device *link)
        cistpl_cftable_entry_t dflt = { 0 };
        struct Scsi_Host *host;
        nsp_hw_data      *data = &nsp_data_base;
-#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
-       struct scsi_device       *dev;
-       dev_node_t      **tail, *node;
-#endif
 
        nsp_dbg(NSP_DEBUG_INIT, "in");
 
@@ -1811,17 +1742,7 @@ static int nsp_cs_config(struct pcmcia_device *link)
                goto cs_failed;
        }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2))
        host = nsp_detect(&nsp_driver_template);
-#else
-       scsi_register_host(&nsp_driver_template);
-       for (host = scsi_host_get_next(NULL); host != NULL;
-            host = scsi_host_get_next(host)) {
-               if (host->hostt == &nsp_driver_template) {
-                       break;
-               }
-       }
-#endif
 
        if (host == NULL) {
                nsp_dbg(NSP_DEBUG_INIT, "detect failed");
@@ -1829,7 +1750,6 @@ static int nsp_cs_config(struct pcmcia_device *link)
        }
 
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
        ret = scsi_add_host (host, NULL);
        if (ret)
                goto cs_failed;
@@ -1840,52 +1760,6 @@ static int nsp_cs_config(struct pcmcia_device *link)
        link->dev_node  = &info->node;
        info->host = host;
 
-#else
-       nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
-       tail = &link->dev_node;
-       info->ndev = 0;
-
-       nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
-
-       for (dev = host->host_queue; dev != NULL; dev = dev->next) {
-               unsigned long id;
-               id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) +
-                       ((dev->channel & 0x0f) << 8) +
-                       ((dev->host->host_no & 0x0f) << 12);
-               node = &info->node[info->ndev];
-               node->minor = 0;
-               switch (dev->type) {
-               case TYPE_TAPE:
-                       node->major = SCSI_TAPE_MAJOR;
-                       snprintf(node->dev_name, sizeof(node->dev_name), "st#%04lx", id);
-                       break;
-               case TYPE_DISK:
-               case TYPE_MOD:
-                       node->major = SCSI_DISK0_MAJOR;
-                       snprintf(node->dev_name, sizeof(node->dev_name), "sd#%04lx", id);
-                       break;
-               case TYPE_ROM:
-               case TYPE_WORM:
-                       node->major = SCSI_CDROM_MAJOR;
-                       snprintf(node->dev_name, sizeof(node->dev_name), "sr#%04lx", id);
-                       break;
-               default:
-                       node->major = SCSI_GENERIC_MAJOR;
-                       snprintf(node->dev_name, sizeof(node->dev_name), "sg#%04lx", id);
-                       break;
-               }
-               *tail = node; tail = &node->next;
-               info->ndev++;
-               info->host = dev->host;
-       }
-
-       *tail = NULL;
-       if (info->ndev == 0) {
-               nsp_msg(KERN_INFO, "no SCSI devices found");
-       }
-       nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
-#endif
-
        /* Finally, report what we've done */
        printk(KERN_INFO "nsp_cs: index 0x%02x: ",
               link->conf.ConfigIndex);
@@ -1938,13 +1812,9 @@ static void nsp_cs_release(struct pcmcia_device *link)
        nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
 
        /* Unlink the device chain */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
        if (info->host != NULL) {
                scsi_remove_host(info->host);
        }
-#else
-       scsi_unregister_host(&nsp_driver_template);
-#endif
        link->dev_node = NULL;
 
        if (link->win) {
@@ -1954,11 +1824,9 @@ static void nsp_cs_release(struct pcmcia_device *link)
        }
        pcmcia_disable_device(link);
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
        if (info->host != NULL) {
                scsi_host_put(info->host);
        }
-#endif
 } /* nsp_cs_release */
 
 static int nsp_cs_suspend(struct pcmcia_device *link)
@@ -2005,7 +1873,6 @@ static int nsp_cs_resume(struct pcmcia_device *link)
 /*======================================================================*
  *     module entry point
  *====================================================================*/
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
 static struct pcmcia_device_id nsp_cs_ids[] = {
        PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16       ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a),
        PCMCIA_DEVICE_PROD_ID123("KME    ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a),
@@ -2029,28 +1896,12 @@ static struct pcmcia_driver nsp_driver = {
        .suspend        = nsp_cs_suspend,
        .resume         = nsp_cs_resume,
 };
-#endif
 
 static int __init nsp_cs_init(void)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
        nsp_msg(KERN_INFO, "loading...");
 
        return pcmcia_register_driver(&nsp_driver);
-#else
-       servinfo_t serv;
-
-       nsp_msg(KERN_INFO, "loading...");
-       pcmcia_get_card_services_info(&serv);
-       if (serv.Revision != CS_RELEASE_CODE) {
-               nsp_msg(KERN_DEBUG, "Card Services release does not match!");
-               return -EINVAL;
-       }
-       register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);
-
-       nsp_dbg(NSP_DEBUG_INIT, "out");
-       return 0;
-#endif
 }
 
 static void __exit nsp_cs_exit(void)
index 9102cbdf13594321724195fba9f80b907b4d9ca0..b7f0fa24641396ca147a6ba894045adaa13e5327 100644 (file)
@@ -10,8 +10,6 @@
 
 =========================================================*/
 
-/* $Id: nsp_cs.h,v 1.19 2003/08/18 11:09:19 elca Exp $ */
-
 #ifndef  __nsp_cs__
 #define  __nsp_cs__
 
 typedef struct scsi_info_t {
        struct pcmcia_device    *p_dev;
        struct Scsi_Host      *host;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
        dev_node_t             node;
-#else
-       int                    ndev;
-       dev_node_t             node[8];
-       struct bus_operations *bus;
-#endif
        int                    stop;
 } scsi_info_t;
 
index d953d43fe2e6146e62ab43ee392d3a3c0df0c2af..0363c1cd68c1faa310ec06f64f16fc6e41a8004f 100644 (file)
@@ -111,13 +111,12 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
 #endif
                        return 0;
        }
-       fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
+       fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA);
        if (!fcs) {
                printk ("PLUTO: Not enough memory to probe\n");
                return 0;
        }
        
-       memset (fcs, 0, sizeof (struct ctrl_inquiry) * fcscount);
        memset (&dev, 0, sizeof(dev));
        atomic_set (&fcss, fcscount);
        
@@ -161,7 +160,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
        
                SCpnt->request->cmd_flags &= ~REQ_STARTED;
                
-               SCpnt->done = pluto_detect_done;
                SCpnt->request_bufflen = 256;
                SCpnt->request_buffer = fcs[i].inquiry;
                PLD(("set up %d %08lx\n", i, (long)SCpnt))
@@ -196,7 +194,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
                SCpnt = &(fcs[i].cmd);
                
                /* Let FC mid-level free allocated resources */
-               SCpnt->done (SCpnt);
+               pluto_detect_scsi_done(SCpnt);
                
                if (!SCpnt->result) {
                        struct pluto_inquiry *inq;
@@ -211,7 +209,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
                                char *p;
                                long *ages;
                                
-                               ages = kmalloc (((inq->channels + 1) * inq->targets) * sizeof(long), GFP_KERNEL);
+                               ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL);
                                if (!ages) continue;
                                
                                host = scsi_register (tpnt, sizeof (struct pluto));
@@ -238,7 +236,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
                                fc->channels = inq->channels + 1;
                                fc->targets = inq->targets;
                                fc->ages = ages;
-                               memset (ages, 0, ((inq->channels + 1) * inq->targets) * sizeof(long));
                                
                                pluto->fc = fc;
                                memcpy (pluto->rev_str, inq->revision, 4);
@@ -260,7 +257,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
                } else
                        fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
        }
-       kfree((char *)fcs);
+       kfree(fcs);
        if (nplutos)
                printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos);
        return nplutos;
index b50f1e14f2a5618dab46e1a600a43d85fdc02ab3..0f43d1d046d950af370e5fc902fdbee37d4edd4a 100644 (file)
@@ -100,16 +100,16 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
        struct scatterlist *sgpnt;
        unsigned int buflen;
 
-       buflen = cmd->request_bufflen;
+       buflen = scsi_bufflen(cmd);
        if (!buflen)
                return 0;
 
-       if (!cmd->request_buffer)
+       if (!scsi_sglist(cmd))
                return -1;
 
-       sgpnt = cmd->request_buffer;
        active = 1;
-       for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) {
+       req_len = act_len = 0;
+       scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
                if (active) {
                        kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
                        len = sgpnt->length;
@@ -124,7 +124,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
                }
                req_len += sgpnt->length;
        }
-       cmd->resid = req_len - act_len;
+       scsi_set_resid(cmd, req_len - act_len);
        return 0;
 }
 
@@ -138,15 +138,15 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
        struct scatterlist *sgpnt;
        unsigned int buflen;
 
-       buflen = cmd->request_bufflen;
+       buflen = scsi_bufflen(cmd);
        if (!buflen)
                return 0;
 
-       if (!cmd->request_buffer)
+       if (!scsi_sglist(cmd))
                return -1;
 
-       sgpnt = cmd->request_buffer;
-       for (k = 0, req_len = 0, fin = 0; k < cmd->use_sg; ++k, ++sgpnt) {
+       req_len = fin = 0;
+       scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
                kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
                len = sgpnt->length;
                if ((req_len + len) > buflen) {
@@ -177,12 +177,12 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
        memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12);
        atapi_cmnd.pktlen = 12;
        atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */
-       atapi_cmnd.blocks = atapi_cmnd.arglen = cmd->request_bufflen;
+       atapi_cmnd.blocks = atapi_cmnd.arglen = scsi_bufflen(cmd);
        atapi_cmnd.buffer = dev->bounce_lpar;
 
        switch (cmd->sc_data_direction) {
        case DMA_FROM_DEVICE:
-               if (cmd->request_bufflen >= CD_FRAMESIZE)
+               if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
                        atapi_cmnd.proto = DMA_PROTO;
                else
                        atapi_cmnd.proto = PIO_DATA_IN_PROTO;
@@ -190,7 +190,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
                break;
 
        case DMA_TO_DEVICE:
-               if (cmd->request_bufflen >= CD_FRAMESIZE)
+               if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
                        atapi_cmnd.proto = DMA_PROTO;
                else
                        atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
index 54d8bdf86852b7541542298b05ce1f20b0c55c9e..fba8aa8a81b58c8f689d136cd65435d5873f5192 100644 (file)
@@ -4086,7 +4086,7 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd)
           } */
        printk("  tag=%d, transfersize=0x%x \n",
               cmd->tag, cmd->transfersize);
-       printk("  Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd));
+       printk("  Pid=%li, SP=0x%p\n", cmd->serial_number, CMD_SP(cmd));
        printk(" underflow size = 0x%x, direction=0x%x\n",
               cmd->underflow, cmd->sc_data_direction);
 }
index 0f2a9f5d801c77efb918dd140c3941051e7f41c4..05fa7796a559d325a1c44f7eb04e6b3da08f5a8b 100644 (file)
@@ -18,7 +18,7 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
                           struct bin_attribute *bin_attr,
                           char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        char *rbuf = (char *)ha->fw_dump;
 
@@ -39,7 +39,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
                            struct bin_attribute *bin_attr,
                            char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        int reading;
 
@@ -89,7 +89,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
                         struct bin_attribute *bin_attr,
                         char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        int             size = ha->nvram_size;
        char            *nvram_cache = ha->nvram;
@@ -112,7 +112,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
                          struct bin_attribute *bin_attr,
                          char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        unsigned long   flags;
        uint16_t        cnt;
@@ -146,7 +146,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
        /* Write NVRAM. */
        spin_lock_irqsave(&ha->hardware_lock, flags);
        ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
-       ha->isp_ops->read_nvram(ha, (uint8_t *)&ha->nvram, ha->nvram_base,
+       ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
            count);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
@@ -170,15 +170,15 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
                          struct bin_attribute *bin_attr,
                          char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
 
        if (ha->optrom_state != QLA_SREADING)
                return 0;
-       if (off > ha->optrom_size)
+       if (off > ha->optrom_region_size)
                return 0;
-       if (off + count > ha->optrom_size)
-               count = ha->optrom_size - off;
+       if (off + count > ha->optrom_region_size)
+               count = ha->optrom_region_size - off;
 
        memcpy(buf, &ha->optrom_buffer[off], count);
 
@@ -190,15 +190,15 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj,
                           struct bin_attribute *bin_attr,
                           char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
 
        if (ha->optrom_state != QLA_SWRITING)
                return -EINVAL;
-       if (off > ha->optrom_size)
+       if (off > ha->optrom_region_size)
                return -ERANGE;
-       if (off + count > ha->optrom_size)
-               count = ha->optrom_size - off;
+       if (off + count > ha->optrom_region_size)
+               count = ha->optrom_region_size - off;
 
        memcpy(&ha->optrom_buffer[off], buf, count);
 
@@ -220,14 +220,18 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
                               struct bin_attribute *bin_attr,
                               char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
-       int val;
+       uint32_t start = 0;
+       uint32_t size = ha->optrom_size;
+       int val, valid;
 
        if (off)
                return 0;
 
-       if (sscanf(buf, "%d", &val) != 1)
+       if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
+               return -EINVAL;
+       if (start > ha->optrom_size)
                return -EINVAL;
 
        switch (val) {
@@ -237,6 +241,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
                        break;
 
                ha->optrom_state = QLA_SWAITING;
+
+               DEBUG2(qla_printk(KERN_INFO, ha,
+                   "Freeing flash region allocation -- 0x%x bytes.\n",
+                   ha->optrom_region_size));
+
                vfree(ha->optrom_buffer);
                ha->optrom_buffer = NULL;
                break;
@@ -244,44 +253,107 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
                if (ha->optrom_state != QLA_SWAITING)
                        break;
 
+               if (start & 0xfff) {
+                       qla_printk(KERN_WARNING, ha,
+                           "Invalid start region 0x%x/0x%x.\n", start, size);
+                       return -EINVAL;
+               }
+
+               ha->optrom_region_start = start;
+               ha->optrom_region_size = start + size > ha->optrom_size ?
+                   ha->optrom_size - start : size;
+
                ha->optrom_state = QLA_SREADING;
-               ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
+               ha->optrom_buffer = vmalloc(ha->optrom_region_size);
                if (ha->optrom_buffer == NULL) {
                        qla_printk(KERN_WARNING, ha,
                            "Unable to allocate memory for optrom retrieval "
-                           "(%x).\n", ha->optrom_size);
+                           "(%x).\n", ha->optrom_region_size);
 
                        ha->optrom_state = QLA_SWAITING;
                        return count;
                }
 
-               memset(ha->optrom_buffer, 0, ha->optrom_size);
-               ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0,
-                   ha->optrom_size);
+               DEBUG2(qla_printk(KERN_INFO, ha,
+                   "Reading flash region -- 0x%x/0x%x.\n",
+                   ha->optrom_region_start, ha->optrom_region_size));
+
+               memset(ha->optrom_buffer, 0, ha->optrom_region_size);
+               ha->isp_ops->read_optrom(ha, ha->optrom_buffer,
+                   ha->optrom_region_start, ha->optrom_region_size);
                break;
        case 2:
                if (ha->optrom_state != QLA_SWAITING)
                        break;
 
+               /*
+                * We need to be more restrictive on which FLASH regions are
+                * allowed to be updated via user-space.  Regions accessible
+                * via this method include:
+                *
+                * ISP21xx/ISP22xx/ISP23xx type boards:
+                *
+                *      0x000000 -> 0x020000 -- Boot code.
+                *
+                * ISP2322/ISP24xx type boards:
+                *
+                *      0x000000 -> 0x07ffff -- Boot code.
+                *      0x080000 -> 0x0fffff -- Firmware.
+                *
+                * ISP25xx type boards:
+                *
+                *      0x000000 -> 0x07ffff -- Boot code.
+                *      0x080000 -> 0x0fffff -- Firmware.
+                *      0x120000 -> 0x12ffff -- VPD and HBA parameters.
+                */
+               valid = 0;
+               if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
+                       valid = 1;
+               else if (start == (FA_BOOT_CODE_ADDR*4) ||
+                   start == (FA_RISC_CODE_ADDR*4))
+                       valid = 1;
+               else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4))
+                   valid = 1;
+               if (!valid) {
+                       qla_printk(KERN_WARNING, ha,
+                           "Invalid start region 0x%x/0x%x.\n", start, size);
+                       return -EINVAL;
+               }
+
+               ha->optrom_region_start = start;
+               ha->optrom_region_size = start + size > ha->optrom_size ?
+                   ha->optrom_size - start : size;
+
                ha->optrom_state = QLA_SWRITING;
-               ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
+               ha->optrom_buffer = vmalloc(ha->optrom_region_size);
                if (ha->optrom_buffer == NULL) {
                        qla_printk(KERN_WARNING, ha,
                            "Unable to allocate memory for optrom update "
-                           "(%x).\n", ha->optrom_size);
+                           "(%x).\n", ha->optrom_region_size);
 
                        ha->optrom_state = QLA_SWAITING;
                        return count;
                }
-               memset(ha->optrom_buffer, 0, ha->optrom_size);
+
+               DEBUG2(qla_printk(KERN_INFO, ha,
+                   "Staging flash region write -- 0x%x/0x%x.\n",
+                   ha->optrom_region_start, ha->optrom_region_size));
+
+               memset(ha->optrom_buffer, 0, ha->optrom_region_size);
                break;
        case 3:
                if (ha->optrom_state != QLA_SWRITING)
                        break;
 
-               ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0,
-                   ha->optrom_size);
+               DEBUG2(qla_printk(KERN_INFO, ha,
+                   "Writing flash region -- 0x%x/0x%x.\n",
+                   ha->optrom_region_start, ha->optrom_region_size));
+
+               ha->isp_ops->write_optrom(ha, ha->optrom_buffer,
+                   ha->optrom_region_start, ha->optrom_region_size);
                break;
+       default:
+               count = -EINVAL;
        }
        return count;
 }
@@ -300,7 +372,7 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
                       struct bin_attribute *bin_attr,
                       char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        int           size = ha->vpd_size;
        char          *vpd_cache = ha->vpd;
@@ -323,7 +395,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
                        struct bin_attribute *bin_attr,
                        char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        unsigned long flags;
 
@@ -354,7 +426,7 @@ qla2x00_sysfs_read_sfp(struct kobject *kobj,
                       struct bin_attribute *bin_attr,
                       char *buf, loff_t off, size_t count)
 {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+       struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        uint16_t iter, addr, offset;
        int rval;
@@ -459,7 +531,7 @@ qla2x00_drvr_version_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_fw_version_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        char fw_str[30];
 
        return snprintf(buf, PAGE_SIZE, "%s\n",
@@ -469,7 +541,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_serial_num_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        uint32_t sn;
 
        sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
@@ -480,14 +552,14 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_isp_name_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
 }
 
 static ssize_t
 qla2x00_isp_id_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
            ha->product_id[0], ha->product_id[1], ha->product_id[2],
            ha->product_id[3]);
@@ -496,14 +568,14 @@ qla2x00_isp_id_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_model_name_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
 }
 
 static ssize_t
 qla2x00_model_desc_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        return snprintf(buf, PAGE_SIZE, "%s\n",
            ha->model_desc ? ha->model_desc: "");
 }
@@ -511,7 +583,7 @@ qla2x00_model_desc_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_pci_info_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        char pci_info[30];
 
        return snprintf(buf, PAGE_SIZE, "%s\n",
@@ -521,7 +593,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_state_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        int len = 0;
 
        if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
@@ -559,7 +631,7 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_zio_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        int len = 0;
 
        switch (ha->zio_mode) {
@@ -576,7 +648,7 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        int val = 0;
        uint16_t zio_mode;
 
@@ -602,7 +674,7 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
 static ssize_t
 qla2x00_zio_timer_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
 
        return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
 }
@@ -611,7 +683,7 @@ static ssize_t
 qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
     size_t count)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        int val = 0;
        uint16_t zio_timer;
 
@@ -629,7 +701,7 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
 static ssize_t
 qla2x00_beacon_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        int len = 0;
 
        if (ha->beacon_blink_led)
@@ -643,7 +715,7 @@ static ssize_t
 qla2x00_beacon_store(struct class_device *cdev, const char *buf,
     size_t count)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
        int val = 0;
        int rval;
 
@@ -673,7 +745,7 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
 static ssize_t
 qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
 
        return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
            ha->bios_revision[0]);
@@ -682,7 +754,7 @@ qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
 
        return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
            ha->efi_revision[0]);
@@ -691,7 +763,7 @@ qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
 
        return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
            ha->fcode_revision[0]);
@@ -700,7 +772,7 @@ qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf)
 static ssize_t
 qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf)
 {
-       scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+       scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
 
        return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
            ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
@@ -757,7 +829,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
 static void
 qla2x00_get_host_port_id(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        fc_host_port_id(shost) = ha->d_id.b.domain << 16 |
            ha->d_id.b.area << 8 | ha->d_id.b.al_pa;
@@ -766,7 +838,7 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost)
 static void
 qla2x00_get_host_speed(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
        uint32_t speed = 0;
 
        switch (ha->link_data_rate) {
@@ -786,7 +858,7 @@ qla2x00_get_host_speed(struct Scsi_Host *shost)
 static void
 qla2x00_get_host_port_type(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
        uint32_t port_type = FC_PORTTYPE_UNKNOWN;
 
        switch (ha->current_topology) {
@@ -810,7 +882,7 @@ static void
 qla2x00_get_starget_node_name(struct scsi_target *starget)
 {
        struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
-       scsi_qla_host_t *ha = to_qla_host(host);
+       scsi_qla_host_t *ha = shost_priv(host);
        fc_port_t *fcport;
        u64 node_name = 0;
 
@@ -828,7 +900,7 @@ static void
 qla2x00_get_starget_port_name(struct scsi_target *starget)
 {
        struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
-       scsi_qla_host_t *ha = to_qla_host(host);
+       scsi_qla_host_t *ha = shost_priv(host);
        fc_port_t *fcport;
        u64 port_name = 0;
 
@@ -846,7 +918,7 @@ static void
 qla2x00_get_starget_port_id(struct scsi_target *starget)
 {
        struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
-       scsi_qla_host_t *ha = to_qla_host(host);
+       scsi_qla_host_t *ha = shost_priv(host);
        fc_port_t *fcport;
        uint32_t port_id = ~0U;
 
@@ -865,7 +937,7 @@ static void
 qla2x00_get_rport_loss_tmo(struct fc_rport *rport)
 {
        struct Scsi_Host *host = rport_to_shost(rport);
-       scsi_qla_host_t *ha = to_qla_host(host);
+       scsi_qla_host_t *ha = shost_priv(host);
 
        rport->dev_loss_tmo = ha->port_down_retry_count + 5;
 }
@@ -874,7 +946,7 @@ static void
 qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
 {
        struct Scsi_Host *host = rport_to_shost(rport);
-       scsi_qla_host_t *ha = to_qla_host(host);
+       scsi_qla_host_t *ha = shost_priv(host);
 
        if (timeout)
                ha->port_down_retry_count = timeout;
@@ -887,7 +959,7 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
 static int
 qla2x00_issue_lip(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags);
        return 0;
@@ -896,7 +968,7 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
 static struct fc_host_statistics *
 qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
        int rval;
        uint16_t mb_stat[1];
        link_stat_t stat_buf;
@@ -934,7 +1006,7 @@ done:
 static void
 qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost));
 }
@@ -942,7 +1014,7 @@ qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
 static void
 qla2x00_set_host_system_hostname(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 }
@@ -950,7 +1022,7 @@ qla2x00_set_host_system_hostname(struct Scsi_Host *shost)
 static void
 qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
        u64 node_name;
 
        if (ha->device_flags & SWITCH_FOUND)
@@ -964,7 +1036,7 @@ qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
 static void
 qla2x00_get_host_port_state(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = to_qla_host(shost);
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        if (!ha->flags.online)
                fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
@@ -978,7 +1050,7 @@ static int
 qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
 {
        int     ret = 0;
-       scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+       scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
        scsi_qla_host_t *vha;
 
        ret = qla24xx_vport_create_req_sanity_check(fc_vport);
@@ -1047,7 +1119,7 @@ vport_create_failed_2:
 int
 qla24xx_vport_delete(struct fc_vport *fc_vport)
 {
-       scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+       scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
        scsi_qla_host_t *vha = fc_vport->dd_data;
 
        qla24xx_disable_vp(vha);
@@ -1178,6 +1250,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha)
        fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
        fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
        fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
-       fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC;
+       fc_host_max_npiv_vports(ha->host) = ha->max_npiv_vports;;
        fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
 }
index c6680348b64847be9c18290181fbe01acc45d3bf..eaa04dabcdf6b4fd331f6572e46691a727fe8fd4 100644 (file)
@@ -38,7 +38,7 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
 }
 
 static int
-qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
+qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
     uint32_t cram_size, uint32_t *ext_mem, void **nxt)
 {
        int rval;
@@ -152,6 +152,103 @@ qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
        return rval;
 }
 
+static uint32_t *
+qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
+    uint32_t count, uint32_t *buf)
+{
+       uint32_t __iomem *dmp_reg;
+
+       WRT_REG_DWORD(&reg->iobase_addr, iobase);
+       dmp_reg = &reg->iobase_window;
+       while (count--)
+               *buf++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       return buf;
+}
+
+static inline int
+qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
+{
+       int rval = QLA_SUCCESS;
+       uint32_t cnt;
+
+       if (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE)
+               return rval;
+
+       WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
+       for (cnt = 30000; (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0 &&
+           rval == QLA_SUCCESS; cnt--) {
+               if (cnt)
+                       udelay(100);
+               else
+                       rval = QLA_FUNCTION_TIMEOUT;
+       }
+
+       return rval;
+}
+
+static int
+qla24xx_soft_reset(scsi_qla_host_t *ha)
+{
+       int rval = QLA_SUCCESS;
+       uint32_t cnt;
+       uint16_t mb0, wd;
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+       /* Reset RISC. */
+       WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
+       for (cnt = 0; cnt < 30000; cnt++) {
+               if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
+                       break;
+
+               udelay(10);
+       }
+
+       WRT_REG_DWORD(&reg->ctrl_status,
+           CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
+       pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
+
+       udelay(100);
+       /* Wait for firmware to complete NVRAM accesses. */
+       mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
+       for (cnt = 10000 ; cnt && mb0; cnt--) {
+               udelay(5);
+               mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
+               barrier();
+       }
+
+       /* Wait for soft-reset to complete. */
+       for (cnt = 0; cnt < 30000; cnt++) {
+               if ((RD_REG_DWORD(&reg->ctrl_status) &
+                   CSRX_ISP_SOFT_RESET) == 0)
+                       break;
+
+               udelay(10);
+       }
+       WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
+       RD_REG_DWORD(&reg->hccr);             /* PCI Posting. */
+
+       for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
+           rval == QLA_SUCCESS; cnt--) {
+               if (cnt)
+                       udelay(100);
+               else
+                       rval = QLA_FUNCTION_TIMEOUT;
+       }
+
+       return rval;
+}
+
+static inline void
+qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
+    uint16_t *buf)
+{
+       uint16_t __iomem *dmp_reg = &reg->u.isp2300.fb_cmd;
+
+       while (count--)
+               *buf++ = htons(RD_REG_WORD(dmp_reg++));
+}
+
 /**
  * qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
  * @ha: HA context
@@ -214,88 +311,61 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        }
 
        if (rval == QLA_SUCCESS) {
-               dmp_reg = (uint16_t __iomem *)(reg + 0);
+               dmp_reg = &reg->flash_address;
                for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
                        fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
+               dmp_reg = &reg->u.isp2300.req_q_in;
                for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
                        fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40);
+               dmp_reg = &reg->u.isp2300.mailbox0;
                for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
                        fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x40);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++)
-                       fw->resp_dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x50);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
-                       fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 48, fw->dma_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x00);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0);
+               dmp_reg = &reg->risc_hw;
                for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
                        fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2000);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++)
-                       fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2200);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++)
-                       fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2400);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++)
-                       fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2600);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++)
-                       fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2800);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++)
-                       fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2A00);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++)
-                       fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2C00);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++)
-                       fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2E00);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++)
-                       fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x10);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++)
-                       fw->frame_buf_hdw_reg[cnt] =
-                           htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x20);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++)
-                       fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x30);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++)
-                       fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
 
                /* Reset RISC. */
                WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
@@ -567,83 +637,59 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                        rval = QLA_FUNCTION_TIMEOUT;
        }
        if (rval == QLA_SUCCESS) {
-               dmp_reg = (uint16_t __iomem *)(reg + 0);
+               dmp_reg = &reg->flash_address;
                for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
                        fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
+               dmp_reg = &reg->u.isp2100.mailbox0;
                for (cnt = 0; cnt < ha->mbx_count; cnt++) {
-                       if (cnt == 8) {
-                               dmp_reg = (uint16_t __iomem *)
-                                       ((uint8_t __iomem *)reg + 0xe0);
-                       }
+                       if (cnt == 8)
+                               dmp_reg = &reg->u_end.isp2200.mailbox8;
+
                        fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
                }
 
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20);
+               dmp_reg = &reg->u.isp2100.unused_2[0];
                for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
                        fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x00);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0);
+               dmp_reg = &reg->risc_hw;
                for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
                        fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2000);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++)
-                       fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2100);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++)
-                       fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2200);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++)
-                       fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2300);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++)
-                       fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2400);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++)
-                       fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2500);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++)
-                       fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2600);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++)
-                       fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
 
                WRT_REG_WORD(&reg->pcr, 0x2700);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++)
-                       fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x10);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++)
-                       fw->frame_buf_hdw_reg[cnt] =
-                           htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x20);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++)
-                       fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
 
                WRT_REG_WORD(&reg->ctrl_status, 0x30);
-               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
-               for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++)
-                       fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
+               qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
 
                /* Reset the ISP. */
                WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
@@ -750,7 +796,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        int             rval;
        uint32_t        cnt;
        uint32_t        risc_address;
-       uint16_t        mb0, wd;
 
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
        uint32_t __iomem *dmp_reg;
@@ -782,547 +827,198 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        fw = &ha->fw_dump->isp.isp24;
        qla2xxx_prep_dump(ha, ha->fw_dump);
 
-       rval = QLA_SUCCESS;
        fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
 
        /* Pause RISC. */
-       if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
-               WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
-                   HCCRX_CLR_HOST_INT);
-               RD_REG_DWORD(&reg->hccr);               /* PCI Posting. */
-               WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
-               for (cnt = 30000;
-                   (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0 &&
-                   rval == QLA_SUCCESS; cnt--) {
-                       if (cnt)
-                               udelay(100);
-                       else
-                               rval = QLA_FUNCTION_TIMEOUT;
-               }
-       }
-
-       if (rval == QLA_SUCCESS) {
-               /* Host interface registers. */
-               dmp_reg = (uint32_t __iomem *)(reg + 0);
-               for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
-                       fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Disable interrupts. */
-               WRT_REG_DWORD(&reg->ictrl, 0);
-               RD_REG_DWORD(&reg->ictrl);
-
-               /* Shadow registers. */
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
-               RD_REG_DWORD(&reg->iobase_addr);
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
-               fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
-               fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
-               fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
-               fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
-               fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
-               fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
-               fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               /* Mailbox registers. */
-               mbx_reg = &reg->mailbox0;
-               for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
-                       fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
-
-               /* Transfer sequence registers. */
-               iter_reg = fw->xseq_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF10);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF20);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF30);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF40);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF50);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF60);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF70);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBFE0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++)
-                       fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBFF0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++)
-                       fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Receive sequence registers. */
-               iter_reg = fw->rseq_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF10);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF20);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF30);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF40);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF50);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF60);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF70);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFD0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++)
-                       fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFE0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++)
-                       fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFF0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++)
-                       fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Command DMA registers. */
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7100);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++)
-                       fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Queues. */
-               iter_reg = fw->req0_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7200);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               dmp_reg = &reg->iobase_q;
-               for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->resp0_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7300);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               dmp_reg = &reg->iobase_q;
-               for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->req1_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7400);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               dmp_reg = &reg->iobase_q;
-               for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Transmit DMA registers. */
-               iter_reg = fw->xmt0_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7600);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7610);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt1_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7620);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7630);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt2_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7640);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7650);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt3_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7660);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7670);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt4_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7680);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7690);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x76A0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++)
-                       fw->xmt_data_dma_reg[cnt] =
-                           htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Receive DMA registers. */
-               iter_reg = fw->rcvt0_data_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7700);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7710);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->rcvt1_data_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7720);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7730);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* RISC registers. */
-               iter_reg = fw->risc_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F10);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F20);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F30);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F40);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F50);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F60);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Local memory controller registers. */
-               iter_reg = fw->lmc_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3050);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3060);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Fibre Protocol Module registers. */
-               iter_reg = fw->fpm_hdw_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4050);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4060);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4070);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4080);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4090);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x40A0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x40B0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Frame Buffer registers. */
-               iter_reg = fw->fb_hdw_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6100);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6130);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6150);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6170);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6190);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x61B0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Reset RISC. */
-               WRT_REG_DWORD(&reg->ctrl_status,
-                   CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
-               for (cnt = 0; cnt < 30000; cnt++) {
-                       if ((RD_REG_DWORD(&reg->ctrl_status) &
-                           CSRX_DMA_ACTIVE) == 0)
-                               break;
-
-                       udelay(10);
-               }
-
-               WRT_REG_DWORD(&reg->ctrl_status,
-                   CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
-               pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
-
-               udelay(100);
-               /* Wait for firmware to complete NVRAM accesses. */
-               mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
-               for (cnt = 10000 ; cnt && mb0; cnt--) {
-                       udelay(5);
-                       mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
-                       barrier();
-               }
-
-               /* Wait for soft-reset to complete. */
-               for (cnt = 0; cnt < 30000; cnt++) {
-                       if ((RD_REG_DWORD(&reg->ctrl_status) &
-                           CSRX_ISP_SOFT_RESET) == 0)
-                               break;
-
-                       udelay(10);
-               }
-               WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
-               RD_REG_DWORD(&reg->hccr);             /* PCI Posting. */
-       }
-
-       for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
-           rval == QLA_SUCCESS; cnt--) {
-               if (cnt)
-                       udelay(100);
-               else
-                       rval = QLA_FUNCTION_TIMEOUT;
-       }
-
-       if (rval == QLA_SUCCESS)
-               rval = qla2xxx_dump_memory(ha, fw->code_ram,
-                   sizeof(fw->code_ram), fw->ext_mem, &nxt);
-
-       if (rval == QLA_SUCCESS) {
-               nxt = qla2xxx_copy_queues(ha, nxt);
-               if (ha->eft)
-                       memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
-       }
-
+       rval = qla24xx_pause_risc(reg);
+       if (rval != QLA_SUCCESS)
+               goto qla24xx_fw_dump_failed_0;
+
+       /* Host interface registers. */
+       dmp_reg = &reg->flash_addr;
+       for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
+               fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
+
+       /* Disable interrupts. */
+       WRT_REG_DWORD(&reg->ictrl, 0);
+       RD_REG_DWORD(&reg->ictrl);
+
+       /* Shadow registers. */
+       WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
+       RD_REG_DWORD(&reg->iobase_addr);
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
+       fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
+       fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
+       fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
+       fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
+       fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
+       fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
+       fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       /* Mailbox registers. */
+       mbx_reg = &reg->mailbox0;
+       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
+               fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
+
+       /* Transfer sequence registers. */
+       iter_reg = fw->xseq_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
+       qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg);
+       qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
+
+       /* Receive sequence registers. */
+       iter_reg = fw->rseq_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
+       qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg);
+       qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
+       qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
+
+       /* Command DMA registers. */
+       qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
+
+       /* Queues. */
+       iter_reg = fw->req0_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
+       dmp_reg = &reg->iobase_q;
+       for (cnt = 0; cnt < 7; cnt++)
+               *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       iter_reg = fw->resp0_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
+       dmp_reg = &reg->iobase_q;
+       for (cnt = 0; cnt < 7; cnt++)
+               *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       iter_reg = fw->req1_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
+       dmp_reg = &reg->iobase_q;
+       for (cnt = 0; cnt < 7; cnt++)
+               *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       /* Transmit DMA registers. */
+       iter_reg = fw->xmt0_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7610, 16, iter_reg);
+
+       iter_reg = fw->xmt1_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7630, 16, iter_reg);
+
+       iter_reg = fw->xmt2_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7650, 16, iter_reg);
+
+       iter_reg = fw->xmt3_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7670, 16, iter_reg);
+
+       iter_reg = fw->xmt4_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7690, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
+
+       /* Receive DMA registers. */
+       iter_reg = fw->rcvt0_data_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7710, 16, iter_reg);
+
+       iter_reg = fw->rcvt1_data_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7730, 16, iter_reg);
+
+       /* RISC registers. */
+       iter_reg = fw->risc_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
+       qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
+
+       /* Local memory controller registers. */
+       iter_reg = fw->lmc_reg;
+       iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
+       qla24xx_read_window(reg, 0x3060, 16, iter_reg);
+
+       /* Fibre Protocol Module registers. */
+       iter_reg = fw->fpm_hdw_reg;
+       iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
+       qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
+
+       /* Frame Buffer registers. */
+       iter_reg = fw->fb_hdw_reg;
+       iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
+       qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
+
+       rval = qla24xx_soft_reset(ha);
+       if (rval != QLA_SUCCESS)
+               goto qla24xx_fw_dump_failed_0;
+
+       rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
+           fw->ext_mem, &nxt);
+       if (rval != QLA_SUCCESS)
+               goto qla24xx_fw_dump_failed_0;
+
+       nxt = qla2xxx_copy_queues(ha, nxt);
+       if (ha->eft)
+               memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
+
+qla24xx_fw_dump_failed_0:
        if (rval != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to dump firmware (%x)!!!\n", rval);
@@ -1346,7 +1042,6 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        int             rval;
        uint32_t        cnt;
        uint32_t        risc_address;
-       uint16_t        mb0, wd;
 
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
        uint32_t __iomem *dmp_reg;
@@ -1377,655 +1072,260 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        }
        fw = &ha->fw_dump->isp.isp25;
        qla2xxx_prep_dump(ha, ha->fw_dump);
+       ha->fw_dump->version = __constant_htonl(2);
 
-       rval = QLA_SUCCESS;
        fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
 
        /* Pause RISC. */
-       if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
-               WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
-                   HCCRX_CLR_HOST_INT);
-               RD_REG_DWORD(&reg->hccr);               /* PCI Posting. */
-               WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
-               for (cnt = 30000;
-                   (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0 &&
-                   rval == QLA_SUCCESS; cnt--) {
-                       if (cnt)
-                               udelay(100);
-                       else
-                               rval = QLA_FUNCTION_TIMEOUT;
-               }
-       }
-
-       if (rval == QLA_SUCCESS) {
-               /* Host interface registers. */
-               dmp_reg = (uint32_t __iomem *)(reg + 0);
-               for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
-                       fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Disable interrupts. */
-               WRT_REG_DWORD(&reg->ictrl, 0);
-               RD_REG_DWORD(&reg->ictrl);
-
-               /* Shadow registers. */
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
-               RD_REG_DWORD(&reg->iobase_addr);
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
-               fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
-               fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
-               fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
-               fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
-               fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
-               fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
-               fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
-               fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
-               fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
-               fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
-               fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
-
-               /* RISC I/O register. */
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
-               RD_REG_DWORD(&reg->iobase_addr);
-               fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
-
-               /* Mailbox registers. */
-               mbx_reg = &reg->mailbox0;
-               for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
-                       fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
-
-               /* Transfer sequence registers. */
-               iter_reg = fw->xseq_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF10);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF20);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF30);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF40);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF50);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF60);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBF70);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xseq_0_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBFC0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBFD0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBFE0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xBFF0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++)
-                       fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Receive sequence registers. */
-               iter_reg = fw->rseq_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF10);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF20);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF30);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF40);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF50);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF60);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFF70);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->rseq_0_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFC0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFD0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFE0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++)
-                       fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xFFF0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++)
-                       fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Auxiliary sequence registers. */
-               iter_reg = fw->aseq_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB050);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB060);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB070);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->aseq_0_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB0C0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB0D0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB0E0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->aseq_1_reg) / 4; cnt++)
-                       fw->aseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0xB0F0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->aseq_2_reg) / 4; cnt++)
-                       fw->aseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Command DMA registers. */
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7100);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++)
-                       fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Queues. */
-               iter_reg = fw->req0_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7200);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               dmp_reg = &reg->iobase_q;
-               for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->resp0_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7300);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               dmp_reg = &reg->iobase_q;
-               for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->req1_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7400);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               dmp_reg = &reg->iobase_q;
-               for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Transmit DMA registers. */
-               iter_reg = fw->xmt0_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7600);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7610);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt1_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7620);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7630);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt2_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7640);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7650);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt3_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7660);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7670);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->xmt4_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7680);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7690);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x76A0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++)
-                       fw->xmt_data_dma_reg[cnt] =
-                           htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Receive DMA registers. */
-               iter_reg = fw->rcvt0_data_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7700);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7710);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               iter_reg = fw->rcvt1_data_dma_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7720);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x7730);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* RISC registers. */
-               iter_reg = fw->risc_gp_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F10);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F20);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F30);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F40);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F50);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F60);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Local memory controller registers. */
-               iter_reg = fw->lmc_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3050);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3060);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x3070);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Fibre Protocol Module registers. */
-               iter_reg = fw->fpm_hdw_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4050);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4060);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4070);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4080);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x4090);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x40A0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x40B0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Frame Buffer registers. */
-               iter_reg = fw->fb_hdw_reg;
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6000);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6010);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6020);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6030);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6040);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6100);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6130);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6150);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6170);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6190);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x61B0);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               WRT_REG_DWORD(&reg->iobase_addr, 0x6F00);
-               dmp_reg = &reg->iobase_window;
-               for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
-
-               /* Reset RISC. */
-               WRT_REG_DWORD(&reg->ctrl_status,
-                   CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
-               for (cnt = 0; cnt < 30000; cnt++) {
-                       if ((RD_REG_DWORD(&reg->ctrl_status) &
-                           CSRX_DMA_ACTIVE) == 0)
-                               break;
-
-                       udelay(10);
-               }
-
-               WRT_REG_DWORD(&reg->ctrl_status,
-                   CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
-               pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
-
-               udelay(100);
-               /* Wait for firmware to complete NVRAM accesses. */
-               mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
-               for (cnt = 10000 ; cnt && mb0; cnt--) {
-                       udelay(5);
-                       mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
-                       barrier();
-               }
-
-               /* Wait for soft-reset to complete. */
-               for (cnt = 0; cnt < 30000; cnt++) {
-                       if ((RD_REG_DWORD(&reg->ctrl_status) &
-                           CSRX_ISP_SOFT_RESET) == 0)
-                               break;
-
-                       udelay(10);
-               }
-               WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
-               RD_REG_DWORD(&reg->hccr);             /* PCI Posting. */
-       }
-
-       for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
-           rval == QLA_SUCCESS; cnt--) {
-               if (cnt)
-                       udelay(100);
-               else
-                       rval = QLA_FUNCTION_TIMEOUT;
-       }
-
-       if (rval == QLA_SUCCESS)
-               rval = qla2xxx_dump_memory(ha, fw->code_ram,
-                   sizeof(fw->code_ram), fw->ext_mem, &nxt);
-
-       if (rval == QLA_SUCCESS) {
-               nxt = qla2xxx_copy_queues(ha, nxt);
-               if (ha->eft)
-                       memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
-       }
-
+       rval = qla24xx_pause_risc(reg);
+       if (rval != QLA_SUCCESS)
+               goto qla25xx_fw_dump_failed_0;
+
+       /* Host/Risc registers. */
+       iter_reg = fw->host_risc_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7010, 16, iter_reg);
+
+       /* PCIe registers. */
+       WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
+       RD_REG_DWORD(&reg->iobase_addr);
+       WRT_REG_DWORD(&reg->iobase_window, 0x01);
+       dmp_reg = &reg->iobase_c4;
+       fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
+       fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
+       fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
+       fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
+       WRT_REG_DWORD(&reg->iobase_window, 0x00);
+       RD_REG_DWORD(&reg->iobase_window);
+
+       /* Host interface registers. */
+       dmp_reg = &reg->flash_addr;
+       for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
+               fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
+
+       /* Disable interrupts. */
+       WRT_REG_DWORD(&reg->ictrl, 0);
+       RD_REG_DWORD(&reg->ictrl);
+
+       /* Shadow registers. */
+       WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
+       RD_REG_DWORD(&reg->iobase_addr);
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
+       fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
+       fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
+       fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
+       fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
+       fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
+       fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
+       fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
+       fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
+       fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
+       fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
+       fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+       /* RISC I/O register. */
+       WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
+       fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
+
+       /* Mailbox registers. */
+       mbx_reg = &reg->mailbox0;
+       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
+               fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
+
+       /* Transfer sequence registers. */
+       iter_reg = fw->xseq_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
+       qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
+
+       iter_reg = fw->xseq_0_reg;
+       iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
+       qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
+
+       /* Receive sequence registers. */
+       iter_reg = fw->rseq_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
+       qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
+
+       iter_reg = fw->rseq_0_reg;
+       iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
+       qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
+       qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
+
+       /* Auxiliary sequence registers. */
+       iter_reg = fw->aseq_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
+       qla24xx_read_window(reg, 0xB070, 16, iter_reg);
+
+       iter_reg = fw->aseq_0_reg;
+       iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
+       qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
+       qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
+
+       /* Command DMA registers. */
+       qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
+
+       /* Queues. */
+       iter_reg = fw->req0_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
+       dmp_reg = &reg->iobase_q;
+       for (cnt = 0; cnt < 7; cnt++)
+               *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       iter_reg = fw->resp0_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
+       dmp_reg = &reg->iobase_q;
+       for (cnt = 0; cnt < 7; cnt++)
+               *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       iter_reg = fw->req1_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
+       dmp_reg = &reg->iobase_q;
+       for (cnt = 0; cnt < 7; cnt++)
+               *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+       /* Transmit DMA registers. */
+       iter_reg = fw->xmt0_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7610, 16, iter_reg);
+
+       iter_reg = fw->xmt1_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7630, 16, iter_reg);
+
+       iter_reg = fw->xmt2_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7650, 16, iter_reg);
+
+       iter_reg = fw->xmt3_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7670, 16, iter_reg);
+
+       iter_reg = fw->xmt4_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7690, 16, iter_reg);
+
+       qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
+
+       /* Receive DMA registers. */
+       iter_reg = fw->rcvt0_data_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7710, 16, iter_reg);
+
+       iter_reg = fw->rcvt1_data_dma_reg;
+       iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
+       qla24xx_read_window(reg, 0x7730, 16, iter_reg);
+
+       /* RISC registers. */
+       iter_reg = fw->risc_gp_reg;
+       iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
+       qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
+
+       /* Local memory controller registers. */
+       iter_reg = fw->lmc_reg;
+       iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
+       qla24xx_read_window(reg, 0x3070, 16, iter_reg);
+
+       /* Fibre Protocol Module registers. */
+       iter_reg = fw->fpm_hdw_reg;
+       iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
+       qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
+
+       /* Frame Buffer registers. */
+       iter_reg = fw->fb_hdw_reg;
+       iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
+       iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
+       qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
+
+       rval = qla24xx_soft_reset(ha);
+       if (rval != QLA_SUCCESS)
+               goto qla25xx_fw_dump_failed_0;
+
+       rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
+           fw->ext_mem, &nxt);
+       if (rval != QLA_SUCCESS)
+               goto qla25xx_fw_dump_failed_0;
+
+       nxt = qla2xxx_copy_queues(ha, nxt);
+       if (ha->eft)
+               memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
+
+qla25xx_fw_dump_failed_0:
        if (rval != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to dump firmware (%x)!!!\n", rval);
@@ -2102,7 +1402,7 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
        struct scsi_qla_host *ha;
        srb_t *sp;
 
-       ha = (struct scsi_qla_host *)cmd->device->host->hostdata;
+       ha = shost_priv(cmd->device->host);
 
        sp = (srb_t *) cmd->SCp.ptr;
        printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
index cca4b0d8253eae3c164f73adb57dc8ec68ce20bb..a50ecf0b7c8452b144b1459d247897a9bfef6b4f 100644 (file)
@@ -215,6 +215,8 @@ struct qla24xx_fw_dump {
 
 struct qla25xx_fw_dump {
        uint32_t host_status;
+       uint32_t host_risc_reg[32];
+       uint32_t pcie_regs[4];
        uint32_t host_reg[32];
        uint32_t shadow_reg[11];
        uint32_t risc_io_reg;
index c1964866a4234338e52fa47b68895f77bf25fd79..1900fbf6cd74ddfbc7eb7a9ef7e6c233d8686012 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
+#include <linux/aer.h>
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
  * SCSI Request Block
  */
 typedef struct srb {
-       struct list_head list;
-
        struct scsi_qla_host *ha;       /* HA the SP is queued on */
        struct fc_port *fcport;
 
@@ -316,7 +315,9 @@ struct device_reg_2xxx {
        } u;
 
        uint16_t fpm_diag_config;
-       uint16_t unused_5[0x6];         /* Gap */
+       uint16_t unused_5[0x4];         /* Gap */
+       uint16_t risc_hw;
+       uint16_t unused_5_1;            /* Gap */
        uint16_t pcr;                   /* Processor Control Register. */
        uint16_t unused_6[0x5];         /* Gap */
        uint16_t mctr;                  /* Memory Configuration and Timing. */
@@ -1702,7 +1703,7 @@ struct ct_fdmi_hba_attributes {
 /*
  * Port attribute types.
  */
-#define FDMI_PORT_ATTR_COUNT           5
+#define FDMI_PORT_ATTR_COUNT           6
 #define FDMI_PORT_FC4_TYPES            1
 #define FDMI_PORT_SUPPORT_SPEED                2
 #define FDMI_PORT_CURRENT_SPEED                3
@@ -2476,6 +2477,8 @@ typedef struct scsi_qla_host {
 #define QLA_SWAITING   0
 #define QLA_SREADING   1
 #define QLA_SWRITING   2
+       uint32_t        optrom_region_start;
+       uint32_t        optrom_region_size;
 
         /* PCI expansion ROM image information. */
 #define ROM_CODE_TYPE_BIOS     0
@@ -2529,7 +2532,7 @@ typedef struct scsi_qla_host {
 #define VP_ERR_FAB_NORESOURCES 3
 #define VP_ERR_FAB_LOGOUT      4
 #define VP_ERR_ADAP_NORESOURCES        5
-       int             max_npiv_vports;        /* 63 or 125 per topoloty */
+       uint16_t        max_npiv_vports;        /* 63 or 125 per topoloty */
        int             cur_vport_count;
 } scsi_qla_host_t;
 
@@ -2542,8 +2545,6 @@ typedef struct scsi_qla_host {
         test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
         atomic_read(&ha->loop_state) == LOOP_DOWN)
 
-#define to_qla_host(x)         ((scsi_qla_host_t *) (x)->hostdata)
-
 #define qla_printk(level, ha, format, arg...) \
        dev_printk(level , &((ha)->pdev->dev) , format , ## arg)
 
index 99fe49618d6134c5342478755e701ac4d6f32b76..25364b1aaf12327daf2dac3e1ea34ce8286f147d 100644 (file)
@@ -779,6 +779,8 @@ struct device_reg_24xx {
 #define FA_NVRAM_VPD_SIZE      0x200
 #define FA_NVRAM_VPD0_ADDR     0x00
 #define FA_NVRAM_VPD1_ADDR     0x100
+
+#define FA_BOOT_CODE_ADDR      0x00000
                                        /*
                                         * RISC code begins at offset 512KB
                                         * within flash. Consisting of two
@@ -940,7 +942,9 @@ struct device_reg_24xx {
        uint16_t mailbox31;
 
        uint32_t iobase_window;
-       uint32_t unused_4[8];           /* Gap. */
+       uint32_t iobase_c4;
+       uint32_t iobase_c8;
+       uint32_t unused_4_1[6];         /* Gap. */
        uint32_t iobase_q;
        uint32_t unused_5[2];           /* Gap. */
        uint32_t iobase_select;
index aa1e41152283dee8992c3df86391c187b9c087e8..09cb2a9080597afc6d28bb051b8f626fdd9985d1 100644 (file)
@@ -133,6 +133,9 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
 extern int
 qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
 
+extern int
+qla2x00_dump_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
+
 extern int
 qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
 
@@ -212,8 +215,8 @@ extern int
 qla2x00_get_id_list(scsi_qla_host_t *, void *, dma_addr_t, uint16_t *);
 
 extern int
-qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
-    uint16_t *);
+qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *,
+    uint16_t *, uint16_t *, uint16_t *);
 
 extern int
 qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
@@ -302,6 +305,8 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
     uint32_t, uint32_t);
 extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
     uint32_t, uint32_t);
+extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+    uint32_t, uint32_t);
 
 extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
 extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
index a7e23583f89959d1c8150381573bb11a02d30d41..eb0784c9ff83af88fa9c291eaed5281041cb541b 100644 (file)
@@ -1517,7 +1517,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
 
        /* Attributes */
        ct_req->req.rpa.attrs.count =
-           __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
+           __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
        entries = ct_req->req.rpa.port_name;
 
        /* FC4 types. */
@@ -1600,7 +1600,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
        /* OS device name. */
        eiter = (struct ct_fdmi_port_attr *) (entries + size);
        eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
-       sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no);
+       strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME);
        alen = strlen(eiter->a.os_dev_name);
        alen += (alen & 3) ? (4 - (alen & 3)) : 4;
        eiter->len = cpu_to_be16(4 + alen);
@@ -1611,6 +1611,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
 
        /* Hostname. */
        if (strlen(fc_host_system_hostname(ha->host))) {
+               ct_req->req.rpa.attrs.count =
+                   __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
                eiter = (struct ct_fdmi_port_attr *) (entries + size);
                eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
                snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
index 1a058ec9bd0c6ced39b11be2a2fe17ced35ce83b..191dafd89be080763c520bfef2b41e62bba8d0f7 100644 (file)
@@ -849,7 +849,8 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha)
                return;
 
        /* Retrieve IOCB counts available to the firmware. */
-       rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt);
+       rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt,
+           &ha->max_npiv_vports);
        if (rval)
                return;
        /* No point in continuing if current settings are sufficient. */
@@ -916,9 +917,15 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
                                    &ha->fw_attributes, &ha->fw_memory_size);
                                qla2x00_resize_request_q(ha);
                                ha->flags.npiv_supported = 0;
-                               if (IS_QLA24XX(ha) &&
-                                   (ha->fw_attributes & BIT_2))
+                               if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) &&
+                                   (ha->fw_attributes & BIT_2)) {
                                        ha->flags.npiv_supported = 1;
+                                       if ((!ha->max_npiv_vports) ||
+                                           ((ha->max_npiv_vports + 1) %
+                                           MAX_MULTI_ID_FABRIC))
+                                               ha->max_npiv_vports =
+                                                   MAX_NUM_VPORT_FABRIC;
+                               }
 
                                if (ql2xallocfwdump)
                                        qla2x00_alloc_fw_dump(ha);
@@ -1155,8 +1162,7 @@ qla2x00_init_rings(scsi_qla_host_t *ha)
 
        DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
 
-       mid_init_cb->count = MAX_NUM_VPORT_FABRIC;
-       ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC;
+       mid_init_cb->count = ha->max_npiv_vports;
 
        rval = qla2x00_init_firmware(ha, ha->init_cb_size);
        if (rval) {
@@ -1786,12 +1792,11 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
 {
        fc_port_t *fcport;
 
-       fcport = kmalloc(sizeof(fc_port_t), flags);
-       if (fcport == NULL)
-               return (fcport);
+       fcport = kzalloc(sizeof(fc_port_t), flags);
+       if (!fcport)
+               return NULL;
 
        /* Setup fcport template structure. */
-       memset(fcport, 0, sizeof (fc_port_t));
        fcport->ha = ha;
        fcport->vp_idx = ha->vp_idx;
        fcport->port_type = FCT_UNKNOWN;
@@ -1801,7 +1806,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
        fcport->supported_classes = FC_COS_UNSPECIFIED;
        spin_lock_init(&fcport->rport_lock);
 
-       return (fcport);
+       return fcport;
 }
 
 /*
@@ -2127,15 +2132,9 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
        if (!IS_IIDMA_CAPABLE(ha))
                return;
 
-       if (fcport->fp_speed == PORT_SPEED_UNKNOWN) {
-               DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- "
-                   "unsupported FM port operating speed.\n",
-                   ha->host_no, fcport->port_name[0], fcport->port_name[1],
-                   fcport->port_name[2], fcport->port_name[3],
-                   fcport->port_name[4], fcport->port_name[5],
-                   fcport->port_name[6], fcport->port_name[7]));
+       if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
+           fcport->fp_speed > ha->link_data_rate)
                return;
-       }
 
        rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed,
            mb);
@@ -2473,13 +2472,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
        rval = QLA_SUCCESS;
 
        /* Try GID_PT to get device list, else GAN. */
-       swl = kmalloc(sizeof(sw_info_t) * MAX_FIBRE_DEVICES, GFP_ATOMIC);
-       if (swl == NULL) {
+       swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC);
+       if (!swl) {
                /*EMPTY*/
                DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback "
                    "on GA_NXT\n", ha->host_no));
        } else {
-               memset(swl, 0, sizeof(sw_info_t) * MAX_FIBRE_DEVICES);
                if (qla2x00_gid_pt(ha, swl) != QLA_SUCCESS) {
                        kfree(swl);
                        swl = NULL;
index 3a5e78cb6b3f62c156ba0133a06fdbf00cb6ad35..7f6a89bd94f3400f2d9987586b20c7423ae7c4cc 100644 (file)
@@ -308,7 +308,7 @@ qla2x00_start_scsi(srb_t *sp)
                handle++;
                if (handle == MAX_OUTSTANDING_COMMANDS)
                        handle = 1;
-               if (ha->outstanding_cmds[handle] == 0)
+               if (!ha->outstanding_cmds[handle])
                        break;
        }
        if (index == MAX_OUTSTANDING_COMMANDS)
@@ -711,7 +711,7 @@ qla24xx_start_scsi(srb_t *sp)
                handle++;
                if (handle == MAX_OUTSTANDING_COMMANDS)
                        handle = 1;
-               if (ha->outstanding_cmds[handle] == 0)
+               if (!ha->outstanding_cmds[handle])
                        break;
        }
        if (index == MAX_OUTSTANDING_COMMANDS)
index eecae9905ece16b2af17e3d133115778b5a7fb2a..c4768c4f39904f0fe80f53e0aeb5d17b01adde01 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include "qla_def.h"
 
+#include <linux/delay.h>
 #include <scsi/scsi_tcq.h>
 
 static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
@@ -34,6 +35,7 @@ qla2100_intr_handler(int irq, void *dev_id)
        int             status;
        unsigned long   flags;
        unsigned long   iter;
+       uint16_t        hccr;
        uint16_t        mb[4];
 
        ha = (scsi_qla_host_t *) dev_id;
@@ -48,7 +50,23 @@ qla2100_intr_handler(int irq, void *dev_id)
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        for (iter = 50; iter--; ) {
-               if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
+               hccr = RD_REG_WORD(&reg->hccr);
+               if (hccr & HCCR_RISC_PAUSE) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
+                       /*
+                        * Issue a "HARD" reset in order for the RISC interrupt
+                        * bit to be cleared.  Schedule a big hammmer to get
+                        * out of the RISC PAUSED state.
+                        */
+                       WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
+                       RD_REG_WORD(&reg->hccr);
+
+                       ha->isp_ops->fw_dump(ha, 1);
+                       set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+                       break;
+               } else if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
                        break;
 
                if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
@@ -127,6 +145,9 @@ qla2300_intr_handler(int irq, void *dev_id)
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
                if (stat & HSR_RISC_PAUSED) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
                        hccr = RD_REG_WORD(&reg->hccr);
                        if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
                                qla_printk(KERN_INFO, ha, "Parity error -- "
@@ -1464,6 +1485,52 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
        WRT_REG_DWORD(&reg->rsp_q_out, ha->rsp_ring_index);
 }
 
+static void
+qla2xxx_check_risc_status(scsi_qla_host_t *ha)
+{
+       int rval;
+       uint32_t cnt;
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+       if (!IS_QLA25XX(ha))
+               return;
+
+       rval = QLA_SUCCESS;
+       WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
+       RD_REG_DWORD(&reg->iobase_addr);
+       WRT_REG_DWORD(&reg->iobase_window, 0x0001);
+       for (cnt = 10000; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
+           rval == QLA_SUCCESS; cnt--) {
+               if (cnt) {
+                       WRT_REG_DWORD(&reg->iobase_window, 0x0001);
+                       udelay(10);
+               } else
+                       rval = QLA_FUNCTION_TIMEOUT;
+       }
+       if (rval == QLA_SUCCESS)
+               goto next_test;
+
+       WRT_REG_DWORD(&reg->iobase_window, 0x0003);
+       for (cnt = 100; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
+           rval == QLA_SUCCESS; cnt--) {
+               if (cnt) {
+                       WRT_REG_DWORD(&reg->iobase_window, 0x0003);
+                       udelay(10);
+               } else
+                       rval = QLA_FUNCTION_TIMEOUT;
+       }
+       if (rval != QLA_SUCCESS)
+               goto done;
+
+next_test:
+       if (RD_REG_DWORD(&reg->iobase_c8) & BIT_3)
+               qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n");
+
+done:
+       WRT_REG_DWORD(&reg->iobase_window, 0x0000);
+       RD_REG_DWORD(&reg->iobase_window);
+}
+
 /**
  * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
  * @irq:
@@ -1499,10 +1566,16 @@ qla24xx_intr_handler(int irq, void *dev_id)
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
                            "Dumping firmware!\n", hccr);
+
+                       qla2xxx_check_risc_status(ha);
+
                        ha->isp_ops->fw_dump(ha, 1);
                        set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                        break;
@@ -1606,7 +1679,6 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
        qla24xx_process_response_queue(ha);
 
        WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-       RD_REG_DWORD_RELAXED(&reg->hccr);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
@@ -1620,7 +1692,6 @@ qla24xx_msix_default(int irq, void *dev_id)
        struct device_reg_24xx __iomem *reg;
        int             status;
        unsigned long   flags;
-       unsigned long   iter;
        uint32_t        stat;
        uint32_t        hccr;
        uint16_t        mb[4];
@@ -1630,13 +1701,19 @@ qla24xx_msix_default(int irq, void *dev_id)
        status = 0;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       for (iter = 50; iter--; ) {
+       do {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
                            "Dumping firmware!\n", hccr);
+
+                       qla2xxx_check_risc_status(ha);
+
                        ha->isp_ops->fw_dump(ha, 1);
                        set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                        break;
@@ -1669,8 +1746,7 @@ qla24xx_msix_default(int irq, void *dev_id)
                        break;
                }
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-               RD_REG_DWORD_RELAXED(&reg->hccr);
-       }
+       } while (0);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
index d3746ec80a857a3e1b9557378055382259b72dca..c53ec67c47f4df600445f960ad503040248650e0 100644 (file)
@@ -391,7 +391,8 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
                mcp->mb[1] = MSW(risc_addr);
                mcp->mb[2] = LSW(risc_addr);
                mcp->mb[3] = 0;
-               mcp->out_mb |= MBX_3|MBX_2|MBX_1;
+               mcp->mb[4] = 0;
+               mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1;
                mcp->in_mb |= MBX_1;
        } else {
                mcp->mb[1] = LSW(risc_addr);
@@ -1919,7 +1920,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
  */
 int
 qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
-    uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, uint16_t *orig_iocb_cnt)
+    uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt,
+    uint16_t *orig_iocb_cnt, uint16_t *max_npiv_vports)
 {
        int rval;
        mbx_cmd_t mc;
@@ -1929,7 +1931,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
 
        mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
        mcp->out_mb = MBX_0;
-       mcp->in_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->tov = 30;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
@@ -1940,9 +1942,9 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
                    ha->host_no, mcp->mb[0]));
        } else {
                DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x "
-                   "mb7=%x mb10=%x.\n", __func__, ha->host_no,
+                   "mb7=%x mb10=%x mb11=%x.\n", __func__, ha->host_no,
                    mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[6], mcp->mb[7],
-                   mcp->mb[10]));
+                   mcp->mb[10], mcp->mb[11]));
 
                if (cur_xchg_cnt)
                        *cur_xchg_cnt = mcp->mb[3];
@@ -1952,6 +1954,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
                        *cur_iocb_cnt = mcp->mb[7];
                if (orig_iocb_cnt)
                        *orig_iocb_cnt = mcp->mb[10];
+               if (max_npiv_vports)
+                       *max_npiv_vports = mcp->mb[11];
        }
 
        return (rval);
@@ -2980,3 +2984,51 @@ qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format,
 
        return rval;
 }
+
+int
+qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
+    uint32_t size)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+       if (MSW(addr) || IS_FWI2_CAPABLE(ha)) {
+               mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
+               mcp->mb[8] = MSW(addr);
+               mcp->out_mb = MBX_8|MBX_0;
+       } else {
+               mcp->mb[0] = MBC_DUMP_RISC_RAM;
+               mcp->out_mb = MBX_0;
+       }
+       mcp->mb[1] = LSW(addr);
+       mcp->mb[2] = MSW(req_dma);
+       mcp->mb[3] = LSW(req_dma);
+       mcp->mb[6] = MSW(MSD(req_dma));
+       mcp->mb[7] = LSW(MSD(req_dma));
+       mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
+       if (IS_FWI2_CAPABLE(ha)) {
+               mcp->mb[4] = MSW(size);
+               mcp->mb[5] = LSW(size);
+               mcp->out_mb |= MBX_5|MBX_4;
+       } else {
+               mcp->mb[4] = LSW(size);
+               mcp->out_mb |= MBX_4;
+       }
+
+       mcp->in_mb = MBX_0;
+       mcp->tov = 30;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(ha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
+                   ha->host_no, rval, mcp->mb[0]));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+       }
+
+       return rval;
+}
index 54dc415d8b535850db36a155532aca4efbe84750..821ee74aadc675ed4a7f3f5a1157000d76079413 100644 (file)
@@ -104,7 +104,7 @@ qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name)
  *
  * Context:
  */
-void
+static void
 qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
 {
        fc_port_t *fcport;
@@ -179,37 +179,7 @@ enable_failed:
        return 1;
 }
 
-/**
- * qla24xx_modify_vport() -  Modifies the virtual fabric port's configuration
- * @ha: HA context
- * @vp: pointer to buffer of virtual port parameters.
- * @ret_code: return error code:
- *
- * Returns the virtual port id, or MAX_VSAN_ID, if couldn't create.
- */
-uint32_t
-qla24xx_modify_vhba(scsi_qla_host_t *ha, vport_params_t *vp, uint32_t *vp_id)
-{
-       scsi_qla_host_t *vha;
-
-       vha = qla24xx_find_vhost_by_name(ha, vp->port_name);
-       if (!vha) {
-               *vp_id = MAX_NUM_VPORT_LOOP;
-               return VP_RET_CODE_WWPN;
-       }
-
-       if (qla24xx_enable_vp(vha)) {
-               scsi_host_put(vha->host);
-               qla2x00_mem_free(vha);
-               *vp_id = MAX_NUM_VPORT_LOOP;
-               return VP_RET_CODE_RESOURCES;
-       }
-
-       *vp_id = vha->vp_idx;
-       return VP_RET_CODE_OK;
-}
-
-void
+static void
 qla24xx_configure_vp(scsi_qla_host_t *vha)
 {
        struct fc_vport *fc_vport;
@@ -363,7 +333,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha)
 int
 qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
 {
-       scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+       scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
        scsi_qla_host_t *vha;
        uint8_t port_name[WWN_SIZE];
 
@@ -397,7 +367,7 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
 scsi_qla_host_t *
 qla24xx_create_vhost(struct fc_vport *fc_vport)
 {
-       scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+       scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
        scsi_qla_host_t *vha;
        struct Scsi_Host *host;
 
@@ -409,7 +379,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
                return(NULL);
        }
 
-       vha = (scsi_qla_host_t *)host->hostdata;
+       vha = shost_priv(host);
 
        /* clone the parent hba */
        memcpy(vha, ha, sizeof (scsi_qla_host_t));
index acca898ce0a2efb4773e4c76bbdd9ccd04585764..a6bb8d0ecf139fe46de567eb773abd8fead11dba 100644 (file)
@@ -379,12 +379,17 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport,
 static int
 qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
-       scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
        struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
        srb_t *sp;
        int rval;
 
+       if (unlikely(pci_channel_offline(ha->pdev))) {
+               cmd->result = DID_REQUEUE << 16;
+               goto qc_fail_command;
+       }
+
        rval = fc_remote_port_chkready(rport);
        if (rval) {
                cmd->result = rval;
@@ -440,13 +445,18 @@ qc_fail_command:
 static int
 qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
-       scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
        struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
        srb_t *sp;
        int rval;
        scsi_qla_host_t *pha = to_qla_parent(ha);
 
+       if (unlikely(pci_channel_offline(ha->pdev))) {
+               cmd->result = DID_REQUEUE << 16;
+               goto qc24_fail_command;
+       }
+
        rval = fc_remote_port_chkready(rport);
        if (rval) {
                cmd->result = rval;
@@ -653,7 +663,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
 static int
 qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 {
-       scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        srb_t *sp;
        int ret, i;
        unsigned int id, lun;
@@ -793,7 +803,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
 static int
 qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
 {
-       scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
        int ret = FAILED;
        unsigned int id, lun;
@@ -922,7 +932,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
 static int
 qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
 {
-       scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        scsi_qla_host_t *pha = to_qla_parent(ha);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
        int ret = FAILED;
@@ -982,7 +992,7 @@ eh_bus_reset_done:
 static int
 qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 {
-       scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
        int ret = FAILED;
        unsigned int id, lun;
@@ -1132,7 +1142,7 @@ qla2xxx_slave_alloc(struct scsi_device *sdev)
 static int
 qla2xxx_slave_configure(struct scsi_device *sdev)
 {
-       scsi_qla_host_t *ha = to_qla_host(sdev->host);
+       scsi_qla_host_t *ha = shost_priv(sdev->host);
        struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 
        if (sdev->tagged_supported)
@@ -1384,7 +1394,7 @@ static struct isp_operations qla25xx_isp_ops = {
        .beacon_on              = qla24xx_beacon_on,
        .beacon_off             = qla24xx_beacon_off,
        .beacon_blink           = qla24xx_beacon_blink,
-       .read_optrom            = qla24xx_read_optrom_data,
+       .read_optrom            = qla25xx_read_optrom_data,
        .write_optrom           = qla24xx_write_optrom_data,
        .get_flash_version      = qla24xx_get_flash_version,
 };
@@ -1533,7 +1543,7 @@ iospace_error_exit:
 static void
 qla2xxx_scan_start(struct Scsi_Host *shost)
 {
-       scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
        set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
@@ -1543,7 +1553,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost)
 static int
 qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
 {
-       scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
+       scsi_qla_host_t *ha = shost_priv(shost);
 
        if (!ha->host)
                return 1;
@@ -1571,6 +1581,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        if (pci_enable_device(pdev))
                goto probe_out;
 
+       if (pci_find_aer_capability(pdev))
+               if (pci_enable_pcie_error_reporting(pdev))
+                       goto probe_out;
+
        sht = &qla2x00_driver_template;
        if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
@@ -1586,7 +1600,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* Clear our data area */
-       ha = (scsi_qla_host_t *)host->hostdata;
+       ha = shost_priv(host);
        memset(ha, 0, sizeof(scsi_qla_host_t));
 
        ha->pdev = pdev;
@@ -2423,7 +2437,6 @@ qla2x00_do_dpc(void *data)
                                if (atomic_read(&fcport->state) != FCS_ONLINE &&
                                    fcport->login_retry) {
 
-                                       fcport->login_retry--;
                                        if (fcport->flags & FCF_FABRIC_DEVICE) {
                                                if (fcport->flags &
                                                    FCF_TAPE_PRESENT)
@@ -2439,6 +2452,7 @@ qla2x00_do_dpc(void *data)
                                                    qla2x00_local_device_login(
                                                        ha, fcport);
 
+                                       fcport->login_retry--;
                                        if (status == QLA_SUCCESS) {
                                                fcport->old_loop_id = fcport->loop_id;
 
@@ -2456,6 +2470,8 @@ qla2x00_do_dpc(void *data)
                                        } else {
                                                fcport->login_retry = 0;
                                        }
+                                       if (fcport->login_retry == 0)
+                                               fcport->loop_id = FC_NO_LOOP_ID;
                                }
                                if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
                                        break;
@@ -2814,6 +2830,105 @@ qla2x00_release_firmware(void)
        up(&qla_fw_lock);
 }
 
+static pci_ers_result_t
+qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+       switch (state) {
+       case pci_channel_io_normal:
+               return PCI_ERS_RESULT_CAN_RECOVER;
+       case pci_channel_io_frozen:
+               pci_disable_device(pdev);
+               return PCI_ERS_RESULT_NEED_RESET;
+       case pci_channel_io_perm_failure:
+               qla2x00_remove_one(pdev);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t
+qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
+{
+       int risc_paused = 0;
+       uint32_t stat;
+       unsigned long flags;
+       scsi_qla_host_t *ha = pci_get_drvdata(pdev);
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+       struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
+
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       if (IS_QLA2100(ha) || IS_QLA2200(ha)){
+               stat = RD_REG_DWORD(&reg->hccr);
+               if (stat & HCCR_RISC_PAUSE)
+                       risc_paused = 1;
+       } else if (IS_QLA23XX(ha)) {
+               stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
+               if (stat & HSR_RISC_PAUSED)
+                       risc_paused = 1;
+       } else if (IS_FWI2_CAPABLE(ha)) {
+               stat = RD_REG_DWORD(&reg24->host_status);
+               if (stat & HSRX_RISC_PAUSED)
+                       risc_paused = 1;
+       }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+       if (risc_paused) {
+               qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, "
+                   "Dumping firmware!\n");
+               ha->isp_ops->fw_dump(ha, 0);
+
+               return PCI_ERS_RESULT_NEED_RESET;
+       } else
+               return PCI_ERS_RESULT_RECOVERED;
+}
+
+static pci_ers_result_t
+qla2xxx_pci_slot_reset(struct pci_dev *pdev)
+{
+       pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
+       scsi_qla_host_t *ha = pci_get_drvdata(pdev);
+
+       if (pci_enable_device(pdev)) {
+               qla_printk(KERN_WARNING, ha,
+                   "Can't re-enable PCI device after reset.\n");
+
+               return ret;
+       }
+       pci_set_master(pdev);
+
+       if (ha->isp_ops->pci_config(ha))
+               return ret;
+
+       set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
+       if (qla2x00_abort_isp(ha)== QLA_SUCCESS)
+               ret =  PCI_ERS_RESULT_RECOVERED;
+       clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
+
+       return ret;
+}
+
+static void
+qla2xxx_pci_resume(struct pci_dev *pdev)
+{
+       scsi_qla_host_t *ha = pci_get_drvdata(pdev);
+       int ret;
+
+       ret = qla2x00_wait_for_hba_online(ha);
+       if (ret != QLA_SUCCESS) {
+               qla_printk(KERN_ERR, ha,
+                   "the device failed to resume I/O "
+                   "from slot/link_reset");
+       }
+       pci_cleanup_aer_uncorrect_error_status(pdev);
+}
+
+static struct pci_error_handlers qla2xxx_err_handler = {
+       .error_detected = qla2xxx_pci_error_detected,
+       .mmio_enabled = qla2xxx_pci_mmio_enabled,
+       .slot_reset = qla2xxx_pci_slot_reset,
+       .resume = qla2xxx_pci_resume,
+};
+
 static struct pci_device_id qla2xxx_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) },
@@ -2839,6 +2954,7 @@ static struct pci_driver qla2xxx_pci_driver = {
        .id_table       = qla2xxx_pci_tbl,
        .probe          = qla2x00_probe_one,
        .remove         = __devexit_p(qla2x00_remove_one),
+       .err_handler    = &qla2xxx_err_handler,
 };
 
 /**
index a925a3f179f959e196b7e12bf5bff46c82e06743..40b059fc19813db3c5c3f41bd0b2482d09db4731 100644 (file)
@@ -425,6 +425,9 @@ qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat)
 /* Flash Manipulation Routines                                               */
 /*****************************************************************************/
 
+#define OPTROM_BURST_SIZE      0x1000
+#define OPTROM_BURST_DWORDS    (OPTROM_BURST_SIZE / 4)
+
 static inline uint32_t
 flash_conf_to_access_addr(uint32_t faddr)
 {
@@ -544,41 +547,59 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
     uint32_t dwords)
 {
        int ret;
-       uint32_t liter;
-       uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask;
+       uint32_t liter, miter;
+       uint32_t sec_mask, rest_addr, conf_addr;
        uint32_t fdata, findex ;
        uint8_t man_id, flash_id;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+       dma_addr_t optrom_dma;
+       void *optrom = NULL;
+       uint32_t *s, *d;
 
        ret = QLA_SUCCESS;
 
+       /* Prepare burst-capable write on supported ISPs. */
+       if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
+           dwords > OPTROM_BURST_DWORDS) {
+               optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+                   &optrom_dma, GFP_KERNEL);
+               if (!optrom) {
+                       qla_printk(KERN_DEBUG, ha,
+                           "Unable to allocate memory for optrom burst write "
+                           "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+               }
+       }
+
        qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
        DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
            ha->host_no, man_id, flash_id));
 
-       sec_end_mask = 0;
        conf_addr = flash_conf_to_access_addr(0x03d8);
        switch (man_id) {
        case 0xbf: /* STT flash. */
-               rest_addr = 0x1fff;
-               sec_mask = 0x3e000;
+               if (flash_id == 0x8e) {
+                       rest_addr = 0x3fff;
+                       sec_mask = 0x7c000;
+               } else {
+                       rest_addr = 0x1fff;
+                       sec_mask = 0x7e000;
+               }
                if (flash_id == 0x80)
                        conf_addr = flash_conf_to_access_addr(0x0352);
                break;
        case 0x13: /* ST M25P80. */
                rest_addr = 0x3fff;
-               sec_mask = 0x3c000;
+               sec_mask = 0x7c000;
                break;
        case 0x1f: // Atmel 26DF081A
-               rest_addr = 0x0fff;
-               sec_mask = 0xff000;
-               sec_end_mask = 0x003ff;
+               rest_addr = 0x3fff;
+               sec_mask = 0x7c000;
                conf_addr = flash_conf_to_access_addr(0x0320);
                break;
        default:
                /* Default to 64 kb sector size. */
                rest_addr = 0x3fff;
-               sec_mask = 0x3c000;
+               sec_mask = 0x7c000;
                break;
        }
 
@@ -592,56 +613,81 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
        /* Some flash parts need an additional zero-write to clear bits.*/
        qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
 
-       do {    /* Loop once to provide quick error exit. */
-               for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
-                       if (man_id == 0x1f) {
-                               findex = faddr << 2;
-                               fdata = findex & sec_mask;
-                       } else {
-                               findex = faddr;
-                               fdata = (findex & sec_mask) << 2;
-                       }
+       for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
+               if (man_id == 0x1f) {
+                       findex = faddr << 2;
+                       fdata = findex & sec_mask;
+               } else {
+                       findex = faddr;
+                       fdata = (findex & sec_mask) << 2;
+               }
 
-                       /* Are we at the beginning of a sector? */
-                       if ((findex & rest_addr) == 0) {
-                               /*
-                                * Do sector unprotect at 4K boundry for Atmel
-                                * part.
-                                */
-                               if (man_id == 0x1f)
-                                       qla24xx_write_flash_dword(ha,
-                                           flash_conf_to_access_addr(0x0339),
-                                           (fdata & 0xff00) | ((fdata << 16) &
-                                           0xff0000) | ((fdata >> 16) & 0xff));
-                               ret = qla24xx_write_flash_dword(ha, conf_addr,
-                                   (fdata & 0xff00) |((fdata << 16) &
+               /* Are we at the beginning of a sector? */
+               if ((findex & rest_addr) == 0) {
+                       /* Do sector unprotect at 4K boundry for Atmel part. */
+                       if (man_id == 0x1f)
+                               qla24xx_write_flash_dword(ha,
+                                   flash_conf_to_access_addr(0x0339),
+                                   (fdata & 0xff00) | ((fdata << 16) &
                                    0xff0000) | ((fdata >> 16) & 0xff));
-                               if (ret != QLA_SUCCESS) {
-                                       DEBUG9(printk("%s(%ld) Unable to flash "
-                                           "sector: address=%x.\n", __func__,
-                                           ha->host_no, faddr));
-                                       break;
-                               }
+                       ret = qla24xx_write_flash_dword(ha, conf_addr,
+                           (fdata & 0xff00) |((fdata << 16) &
+                           0xff0000) | ((fdata >> 16) & 0xff));
+                       if (ret != QLA_SUCCESS) {
+                               DEBUG9(printk("%s(%ld) Unable to flash "
+                                   "sector: address=%x.\n", __func__,
+                                   ha->host_no, faddr));
+                               break;
                        }
-                       ret = qla24xx_write_flash_dword(ha,
+               }
+
+               /* Go with burst-write. */
+               if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) {
+                       /* Copy data to DMA'ble buffer. */
+                       for (miter = 0, s = optrom, d = dwptr;
+                           miter < OPTROM_BURST_DWORDS; miter++, s++, d++)
+                               *s = cpu_to_le32(*d);
+
+                       ret = qla2x00_load_ram(ha, optrom_dma,
                            flash_data_to_access_addr(faddr),
-                           cpu_to_le32(*dwptr));
+                           OPTROM_BURST_DWORDS);
                        if (ret != QLA_SUCCESS) {
-                               DEBUG9(printk("%s(%ld) Unable to program flash "
-                                   "address=%x data=%x.\n", __func__,
-                                   ha->host_no, faddr, *dwptr));
-                               break;
+                               qla_printk(KERN_WARNING, ha,
+                                   "Unable to burst-write optrom segment "
+                                   "(%x/%x/%llx).\n", ret,
+                                   flash_data_to_access_addr(faddr),
+                                   optrom_dma);
+                               qla_printk(KERN_WARNING, ha,
+                                   "Reverting to slow-write.\n");
+
+                               dma_free_coherent(&ha->pdev->dev,
+                                   OPTROM_BURST_SIZE, optrom, optrom_dma);
+                               optrom = NULL;
+                       } else {
+                               liter += OPTROM_BURST_DWORDS - 1;
+                               faddr += OPTROM_BURST_DWORDS - 1;
+                               dwptr += OPTROM_BURST_DWORDS - 1;
+                               continue;
                        }
+               }
 
-                       /* Do sector protect at 4K boundry for Atmel part. */
-                       if (man_id == 0x1f &&
-                           ((faddr & sec_end_mask) == 0x3ff))
-                               qla24xx_write_flash_dword(ha,
-                                   flash_conf_to_access_addr(0x0336),
-                                   (fdata & 0xff00) | ((fdata << 16) &
-                                   0xff0000) | ((fdata >> 16) & 0xff));
+               ret = qla24xx_write_flash_dword(ha,
+                   flash_data_to_access_addr(faddr), cpu_to_le32(*dwptr));
+               if (ret != QLA_SUCCESS) {
+                       DEBUG9(printk("%s(%ld) Unable to program flash "
+                           "address=%x data=%x.\n", __func__,
+                           ha->host_no, faddr, *dwptr));
+                       break;
                }
-       } while (0);
+
+               /* Do sector protect at 4K boundry for Atmel part. */
+               if (man_id == 0x1f &&
+                   ((faddr & rest_addr) == rest_addr))
+                       qla24xx_write_flash_dword(ha,
+                           flash_conf_to_access_addr(0x0336),
+                           (fdata & 0xff00) | ((fdata << 16) &
+                           0xff0000) | ((fdata >> 16) & 0xff));
+       }
 
        /* Enable flash write-protection. */
        qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
@@ -651,6 +697,10 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
            RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
        RD_REG_DWORD(&reg->ctrl_status);        /* PCI Posting. */
 
+       if (optrom)
+               dma_free_coherent(&ha->pdev->dev,
+                   OPTROM_BURST_SIZE, optrom, optrom_dma);
+
        return ret;
 }
 
@@ -1728,7 +1778,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
 {
        /* Suspend HBA. */
        scsi_block_requests(ha->host);
-       ha->isp_ops->disable_intrs(ha);
        set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
 
        /* Go with read. */
@@ -1736,7 +1785,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
 
        /* Resume HBA. */
        clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
-       ha->isp_ops->enable_intrs(ha);
        scsi_unblock_requests(ha->host);
 
        return buf;
@@ -1750,7 +1798,6 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
 
        /* Suspend HBA. */
        scsi_block_requests(ha->host);
-       ha->isp_ops->disable_intrs(ha);
        set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
 
        /* Go with write. */
@@ -1767,6 +1814,70 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
        return rval;
 }
 
+uint8_t *
+qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+    uint32_t offset, uint32_t length)
+{
+       int rval;
+       dma_addr_t optrom_dma;
+       void *optrom;
+       uint8_t *pbuf;
+       uint32_t faddr, left, burst;
+
+       if (offset & 0xfff)
+               goto slow_read;
+       if (length < OPTROM_BURST_SIZE)
+               goto slow_read;
+
+       optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+           &optrom_dma, GFP_KERNEL);
+       if (!optrom) {
+               qla_printk(KERN_DEBUG, ha,
+                   "Unable to allocate memory for optrom burst read "
+                   "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+
+               goto slow_read;
+       }
+
+       pbuf = buf;
+       faddr = offset >> 2;
+       left = length >> 2;
+       burst = OPTROM_BURST_DWORDS;
+       while (left != 0) {
+               if (burst > left)
+                       burst = left;
+
+               rval = qla2x00_dump_ram(ha, optrom_dma,
+                   flash_data_to_access_addr(faddr), burst);
+               if (rval) {
+                       qla_printk(KERN_WARNING, ha,
+                           "Unable to burst-read optrom segment "
+                           "(%x/%x/%llx).\n", rval,
+                           flash_data_to_access_addr(faddr), optrom_dma);
+                       qla_printk(KERN_WARNING, ha,
+                           "Reverting to slow-read.\n");
+
+                       dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+                           optrom, optrom_dma);
+                       goto slow_read;
+               }
+
+               memcpy(pbuf, optrom, burst * 4);
+
+               left -= burst;
+               faddr += burst;
+               pbuf += burst * 4;
+       }
+
+       dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom,
+           optrom_dma);
+
+       return buf;
+
+slow_read:
+    return qla24xx_read_optrom_data(ha, buf, offset, length);
+}
+
 /**
  * qla2x00_get_fcode_version() - Determine an FCODE image's version.
  * @ha: HA context
index 18095b9b76f487553ac0a4ec7ecc30a047d79246..2d551a3006f6a2e23280c5514c01d35cf44f140a 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.02.00-k3"
+#define QLA2XXX_VERSION      "8.02.00-k4"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   2
index 94baca840efe45308070d964c4fb8612c9208198..1e874f1fb5c64a403fd6e7da8365edce51b929df 100644 (file)
@@ -166,6 +166,7 @@ static int qlogicfas_release(struct Scsi_Host *shost)
 {
        struct qlogicfas408_priv *priv = get_priv_by_host(shost);
 
+       scsi_remove_host(shost);
        if (shost->irq) {
                qlogicfas408_disable_ints(priv);        
                free_irq(shost->irq, shost);
@@ -174,7 +175,6 @@ static int qlogicfas_release(struct Scsi_Host *shost)
                free_dma(shost->dma_channel);
        if (shost->io_port && shost->n_io_port)
                release_region(shost->io_port, shost->n_io_port);
-       scsi_remove_host(shost);
        scsi_host_put(shost);
 
        return 0;
index 594887205b0fe7876a3fea97493a89f9402d9fb9..e93f80316a19369d7d3416c887ece96bed1117c6 100644 (file)
@@ -310,8 +310,6 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
                }
                qpti->dev_param[i].device_enable = 1;
        }
-       /* this is very important to set! */
-       qpti->sbits = 1 << qpti->scsi_id;
 }
 
 static int qlogicpti_reset_hardware(struct Scsi_Host *host)
@@ -951,153 +949,35 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int
        host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
 }
 
-static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out)
+static int qlogicpti_slave_configure(struct scsi_device *sdev)
 {
-       unsigned char *buf;
-       unsigned int buflen;
-
-       if (cmd->use_sg) {
-               struct scatterlist *sg;
+       struct qlogicpti *qpti = shost_priv(sdev->host);
+       int tgt = sdev->id;
+       u_short param[6];
 
-               sg = (struct scatterlist *) cmd->request_buffer;
-               buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-               buflen = sg->length;
+       /* tags handled in midlayer */
+       /* enable sync mode? */
+       if (sdev->sdtr) {
+               qpti->dev_param[tgt].device_flags |= 0x10;
        } else {
-               buf = cmd->request_buffer;
-               buflen = cmd->request_bufflen;
+               qpti->dev_param[tgt].synchronous_offset = 0;
+               qpti->dev_param[tgt].synchronous_period = 0;
        }
-
-       *buf_out = buf;
-       return buflen;
-}
-
-static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf)
-{
-       if (cmd->use_sg) {
-               struct scatterlist *sg;
-
-               sg = (struct scatterlist *) cmd->request_buffer;
-               kunmap_atomic(buf - sg->offset, KM_IRQ0);
-       }
-}
-
-/*
- * Until we scan the entire bus with inquiries, go throught this fella...
- */
-static void ourdone(struct scsi_cmnd *Cmnd)
-{
-       struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
-       int tgt = Cmnd->device->id;
-       void (*done) (struct scsi_cmnd *);
-
-       /* This grot added by DaveM, blame him for ugliness.
-        * The issue is that in the 2.3.x driver we use the
-        * host_scribble portion of the scsi command as a
-        * completion linked list at interrupt service time,
-        * so we have to store the done function pointer elsewhere.
-        */
-       done = (void (*)(struct scsi_cmnd *))
-               (((unsigned long) Cmnd->SCp.Message)
-#ifdef __sparc_v9__
-                | ((unsigned long) Cmnd->SCp.Status << 32UL)
-#endif
-                );
-
-       if ((qpti->sbits & (1 << tgt)) == 0) {
-               int ok = host_byte(Cmnd->result) == DID_OK;
-               if (Cmnd->cmnd[0] == 0x12 && ok) {
-                       unsigned char *iqd;
-                       unsigned int iqd_len;
-
-                       iqd_len = scsi_rbuf_get(Cmnd, &iqd);
-
-                       /* tags handled in midlayer */
-                       /* enable sync mode? */
-                       if (iqd[7] & 0x10) {
-                               qpti->dev_param[tgt].device_flags |= 0x10;
-                       } else {
-                               qpti->dev_param[tgt].synchronous_offset = 0;
-                               qpti->dev_param[tgt].synchronous_period = 0;
-                       }
-                       /* are we wide capable? */
-                       if (iqd[7] & 0x20) {
-                               qpti->dev_param[tgt].device_flags |= 0x20;
-                       }
-
-                       scsi_rbuf_put(Cmnd, iqd);
-
-                       qpti->sbits |= (1 << tgt);
-               } else if (!ok) {
-                       qpti->sbits |= (1 << tgt);
-               }
-       }
-       done(Cmnd);
-}
-
-static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *));
-
-static int qlogicpti_queuecommand_slow(struct scsi_cmnd *Cmnd,
-                                      void (*done)(struct scsi_cmnd *))
-{
-       struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
-
-       /*
-        * done checking this host adapter?
-        * If not, then rewrite the command
-        * to finish through ourdone so we
-        * can peek at Inquiry data results.
-        */
-       if (qpti->sbits && qpti->sbits != 0xffff) {
-               /* See above about in ourdone this ugliness... */
-               Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff;
-#ifdef CONFIG_SPARC64
-               Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff;
-#endif
-               return qlogicpti_queuecommand(Cmnd, ourdone);
-       }
-
-       /*
-        * We've peeked at all targets for this bus- time
-        * to set parameters for devices for real now.
-        */
-       if (qpti->sbits == 0xffff) {
-               int i;
-               for(i = 0; i < MAX_TARGETS; i++) {
-                       u_short param[6];
-                       param[0] = MBOX_SET_TARGET_PARAMS;
-                       param[1] = (i << 8);
-                       param[2] = (qpti->dev_param[i].device_flags << 8);
-                       if (qpti->dev_param[i].device_flags & 0x10) {
-                               param[3] = (qpti->dev_param[i].synchronous_offset << 8) |
-                                       qpti->dev_param[i].synchronous_period;
-                       } else {
-                               param[3] = 0;
-                       }
-                       (void) qlogicpti_mbox_command(qpti, param, 0);
-               }
-               /*
-                * set to zero so any traverse through ourdone
-                * doesn't start the whole process again,
-                */
-               qpti->sbits = 0;
-       }
-
-       /* check to see if we're done with all adapters... */
-       for (qpti = qptichain; qpti != NULL; qpti = qpti->next) {
-               if (qpti->sbits) {
-                       break;
-               }
+       /* are we wide capable? */
+       if (sdev->wdtr)
+               qpti->dev_param[tgt].device_flags |= 0x20;
+
+       param[0] = MBOX_SET_TARGET_PARAMS;
+       param[1] = (tgt << 8);
+       param[2] = (qpti->dev_param[tgt].device_flags << 8);
+       if (qpti->dev_param[tgt].device_flags & 0x10) {
+               param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) |
+                       qpti->dev_param[tgt].synchronous_period;
+       } else {
+               param[3] = 0;
        }
-
-       /*
-        * if we hit the end of the chain w/o finding adapters still
-        * capability-configuring, then we're done with all adapters
-        * and can rock on..
-        */
-       if (qpti == NULL)
-               Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand;
-
-       return qlogicpti_queuecommand(Cmnd, done);
+       qlogicpti_mbox_command(qpti, param, 0);
+       return 0;
 }
 
 /*
@@ -1390,7 +1270,8 @@ static struct scsi_host_template qpti_template = {
        .module                 = THIS_MODULE,
        .name                   = "qlogicpti",
        .info                   = qlogicpti_info,
-       .queuecommand           = qlogicpti_queuecommand_slow,
+       .queuecommand           = qlogicpti_queuecommand,
+       .slave_configure        = qlogicpti_slave_configure,
        .eh_abort_handler       = qlogicpti_abort,
        .eh_bus_reset_handler   = qlogicpti_reset,
        .can_queue              = QLOGICPTI_REQ_QUEUE_LEN,
index 6cd1c0771d29a515d74a1587f8e6b58c0ffbbe4d..ef6da2df584ba29fbfddcbb19e105d0fe7b1a319 100644 (file)
@@ -380,8 +380,7 @@ struct qlogicpti {
        unsigned char             swsreg;
        unsigned int    
                gotirq  :       1,      /* this instance got an irq */
-               is_pti  :       1,      /* Non-zero if this is a PTI board. */
-               sbits   :       16;     /* syncmode known bits */
+               is_pti  :       1;      /* Non-zero if this is a PTI board. */
 };
 
 /* How to twiddle them bits... */
index a5de1a829a76dbb2bba8d6baaa4cc8e7bd580805..192948822455fd666ee8b7516ecedb812ac5744a 100644 (file)
@@ -59,6 +59,7 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
@@ -367,9 +368,8 @@ void scsi_log_send(struct scsi_cmnd *cmd)
                        scsi_print_command(cmd);
                        if (level > 3) {
                                printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
-                                      " done = 0x%p, queuecommand 0x%p\n",
+                                      " queuecommand 0x%p\n",
                                        scsi_sglist(cmd), scsi_bufflen(cmd),
-                                       cmd->done,
                                        cmd->device->host->hostt->queuecommand);
 
                        }
@@ -442,7 +442,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
 #endif
 
 /* 
- * Assign a serial number and pid to the request for error recovery
+ * Assign a serial number to the request for error recovery
  * and debugging purposes.  Protected by the Host_Lock of host.
  */
 static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
@@ -450,10 +450,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd
        cmd->serial_number = host->cmd_serial_number++;
        if (cmd->serial_number == 0) 
                cmd->serial_number = host->cmd_serial_number++;
-       
-       cmd->pid = host->cmd_pid++;
-       if (cmd->pid == 0)
-               cmd->pid = host->cmd_pid++;
 }
 
 /*
@@ -658,6 +654,12 @@ void __scsi_done(struct scsi_cmnd *cmd)
        blk_complete_request(rq);
 }
 
+/* Move this to a header if it becomes more generally useful */
+static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
+{
+       return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
+}
+
 /*
  * Function:    scsi_finish_command
  *
@@ -669,6 +671,8 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
        struct Scsi_Host *shost = sdev->host;
+       struct scsi_driver *drv;
+       unsigned int good_bytes;
 
        scsi_device_unbusy(sdev);
 
@@ -694,7 +698,13 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
                                "Notifying upper driver of completion "
                                "(result %x)\n", cmd->result));
 
-       cmd->done(cmd);
+       good_bytes = cmd->request_bufflen;
+        if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+               drv = scsi_cmd_to_driver(cmd);
+               if (drv->done)
+                       good_bytes = drv->done(cmd);
+       }
+       scsi_io_completion(cmd, good_bytes);
 }
 EXPORT_SYMBOL(scsi_finish_command);
 
index e2ea739e33df121dae6b91b25339efee7cdf3696..348cc5a6e3cdf002b091ea73762e16f0baf5b6d7 100644 (file)
@@ -214,6 +214,7 @@ static struct {
        {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
        {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
        {"Promise", "", NULL, BLIST_SPARSELUN},
+       {"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
        {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
        {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
        {"SEAGATE", "ST34555N", "0930", BLIST_NOTQ},    /* Chokes on tagged INQUIRY */
index 8a525abda30fcad2d7b5cf54dfab5b46bc067e68..d29f8464b74fadd26de9e5535ede03cfa21d08dd 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
+#include "scsi_transport_api.h"
 
 #define SENSE_TIMEOUT          (10*HZ)
 
@@ -589,39 +590,23 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 }
 
 /**
- * scsi_send_eh_cmnd  - submit a scsi command as part of error recory
+ * scsi_eh_prep_cmnd  - Save a scsi command info as part of error recory
  * @scmd:       SCSI command structure to hijack
- * @cmnd:       CDB to send
+ * @ses:        structure to save restore information
+ * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
  * @cmnd_size:  size in bytes of @cmnd
- * @timeout:    timeout for this request
- * @copy_sense: request sense data if set to 1
- *
- * This function is used to send a scsi command down to a target device
- * as part of the error recovery process.  If @copy_sense is 0 the command
- * sent must be one that does not transfer any data.  If @copy_sense is 1
- * the command must be REQUEST_SENSE and this functions copies out the
- * sense buffer it got into @scmd->sense_buffer.
+ * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
  *
- * Return value:
- *    SUCCESS or FAILED or NEEDS_RETRY
+ * This function is used to save a scsi command information before re-execution
+ * as part of the error recovery process.  If @sense_bytes is 0 the command
+ * sent must be one that does not transfer any data.  If @sense_bytes != 0
+ * @cmnd is ignored and this functions sets up a REQUEST_SENSE command
+ * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer.
  **/
-static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
-                            int cmnd_size, int timeout, int copy_sense)
+void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
+                       unsigned char *cmnd, int cmnd_size, unsigned sense_bytes)
 {
        struct scsi_device *sdev = scmd->device;
-       struct Scsi_Host *shost = sdev->host;
-       int old_result = scmd->result;
-       DECLARE_COMPLETION_ONSTACK(done);
-       unsigned long timeleft;
-       unsigned long flags;
-       struct scatterlist sgl;
-       unsigned char old_cmnd[MAX_COMMAND_SIZE];
-       enum dma_data_direction old_data_direction;
-       unsigned short old_use_sg;
-       unsigned char old_cmd_len;
-       unsigned old_bufflen;
-       void *old_buffer;
-       int rtn;
 
        /*
         * We need saved copies of a number of fields - this is because
@@ -630,35 +615,42 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
         * we will need to restore these values prior to running the actual
         * command.
         */
-       old_buffer = scmd->request_buffer;
-       old_bufflen = scmd->request_bufflen;
-       memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd));
-       old_data_direction = scmd->sc_data_direction;
-       old_cmd_len = scmd->cmd_len;
-       old_use_sg = scmd->use_sg;
-
-       memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
-       memcpy(scmd->cmnd, cmnd, cmnd_size);
-
-       if (copy_sense) {
-               sg_init_one(&sgl, scmd->sense_buffer,
-                           sizeof(scmd->sense_buffer));
-
+       ses->cmd_len = scmd->cmd_len;
+       memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+       ses->data_direction = scmd->sc_data_direction;
+       ses->bufflen = scmd->request_bufflen;
+       ses->buffer = scmd->request_buffer;
+       ses->use_sg = scmd->use_sg;
+       ses->resid = scmd->resid;
+       ses->result = scmd->result;
+
+       if (sense_bytes) {
+               scmd->request_bufflen = min_t(unsigned,
+                                      sizeof(scmd->sense_buffer), sense_bytes);
+               sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
+                                                      scmd->request_bufflen);
+               scmd->request_buffer = &ses->sense_sgl;
                scmd->sc_data_direction = DMA_FROM_DEVICE;
-               scmd->request_bufflen = sgl.length;
-               scmd->request_buffer = &sgl;
                scmd->use_sg = 1;
+               memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+               scmd->cmnd[0] = REQUEST_SENSE;
+               scmd->cmnd[4] = scmd->request_bufflen;
+               scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
        } else {
                scmd->request_buffer = NULL;
                scmd->request_bufflen = 0;
                scmd->sc_data_direction = DMA_NONE;
                scmd->use_sg = 0;
+               if (cmnd) {
+                       memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+                       memcpy(scmd->cmnd, cmnd, cmnd_size);
+                       scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
+               }
        }
 
        scmd->underflow = 0;
-       scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 
-       if (sdev->scsi_level <= SCSI_2)
+       if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN)
                scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
                        (sdev->lun << 5 & 0xe0);
 
@@ -667,7 +659,58 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
         * untransferred sense data should be interpreted as being zero.
         */
        memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
+}
+EXPORT_SYMBOL(scsi_eh_prep_cmnd);
+
+/**
+ * scsi_eh_restore_cmnd  - Restore a scsi command info as part of error recory
+ * @scmd:       SCSI command structure to restore
+ * @ses:        saved information from a coresponding call to scsi_prep_eh_cmnd
+ *
+ * Undo any damage done by above scsi_prep_eh_cmnd().
+ **/
+void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
+{
+       /*
+        * Restore original data
+        */
+       scmd->cmd_len = ses->cmd_len;
+       memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+       scmd->sc_data_direction = ses->data_direction;
+       scmd->request_bufflen = ses->bufflen;
+       scmd->request_buffer = ses->buffer;
+       scmd->use_sg = ses->use_sg;
+       scmd->resid = ses->resid;
+       scmd->result = ses->result;
+}
+EXPORT_SYMBOL(scsi_eh_restore_cmnd);
 
+/**
+ * scsi_send_eh_cmnd  - submit a scsi command as part of error recory
+ * @scmd:       SCSI command structure to hijack
+ * @cmnd:       CDB to send
+ * @cmnd_size:  size in bytes of @cmnd
+ * @timeout:    timeout for this request
+ * @sense_bytes: size of sense data to copy or 0
+ *
+ * This function is used to send a scsi command down to a target device
+ * as part of the error recovery process. See also scsi_eh_prep_cmnd() above.
+ *
+ * Return value:
+ *    SUCCESS or FAILED or NEEDS_RETRY
+ **/
+static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
+                            int cmnd_size, int timeout, unsigned sense_bytes)
+{
+       struct scsi_device *sdev = scmd->device;
+       struct Scsi_Host *shost = sdev->host;
+       DECLARE_COMPLETION_ONSTACK(done);
+       unsigned long timeleft;
+       unsigned long flags;
+       struct scsi_eh_save ses;
+       int rtn;
+
+       scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes);
        shost->eh_action = &done;
 
        spin_lock_irqsave(shost->host_lock, flags);
@@ -711,17 +754,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                rtn = FAILED;
        }
 
-
-       /*
-        * Restore original data
-        */
-       scmd->request_buffer = old_buffer;
-       scmd->request_bufflen = old_bufflen;
-       memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd));
-       scmd->sc_data_direction = old_data_direction;
-       scmd->cmd_len = old_cmd_len;
-       scmd->use_sg = old_use_sg;
-       scmd->result = old_result;
+       scsi_eh_restore_cmnd(scmd, &ses);
        return rtn;
 }
 
@@ -736,10 +769,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
  **/
 static int scsi_request_sense(struct scsi_cmnd *scmd)
 {
-       static unsigned char generic_sense[6] =
-               {REQUEST_SENSE, 0, 0, 0, 252, 0};
-
-       return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1);
+       return scsi_send_eh_cmnd(scmd, NULL, 0, SENSE_TIMEOUT, ~0);
 }
 
 /**
@@ -1136,9 +1166,8 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
        struct scsi_cmnd *scmd, *next;
 
        list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
-               sdev_printk(KERN_INFO, scmd->device,
-                           "scsi: Device offlined - not"
-                           " ready after error recovery\n");
+               sdev_printk(KERN_INFO, scmd->device, "Device offlined - "
+                           "not ready after error recovery\n");
                scsi_device_set_state(scmd->device, SDEV_OFFLINE);
                if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) {
                        /*
@@ -1671,7 +1700,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
        memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
     
        scmd->scsi_done         = scsi_reset_provider_done_command;
-       scmd->done                      = NULL;
        scmd->request_buffer            = NULL;
        scmd->request_bufflen           = 0;
 
@@ -1681,12 +1709,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 
        init_timer(&scmd->eh_timeout);
 
-       /*
-        * Sometimes the command can get back into the timer chain,
-        * so use the pid as an identifier.
-        */
-       scmd->pid                       = 0;
-
        spin_lock_irqsave(shost->host_lock, flags);
        shost->tmf_in_progress = 1;
        spin_unlock_irqrestore(shost->host_lock, flags);
index 604f4d7179334a3cb1ce61d354f842285eb2234d..207f1aa08869f209be7ba1bde8f727534796701b 100644 (file)
@@ -288,7 +288,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
 {
        struct request_queue *q = rq->q;
        int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       unsigned int data_len = 0, len, bytes, off;
+       unsigned int data_len = bufflen, len, bytes, off;
        struct page *page;
        struct bio *bio = NULL;
        int i, err, nr_vecs = 0;
@@ -297,10 +297,15 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
                page = sgl[i].page;
                off = sgl[i].offset;
                len = sgl[i].length;
-               data_len += len;
 
-               while (len > 0) {
+               while (len > 0 && data_len > 0) {
+                       /*
+                        * sg sends a scatterlist that is larger than
+                        * the data_len it wants transferred for certain
+                        * IO sizes
+                        */
                        bytes = min_t(unsigned int, len, PAGE_SIZE - off);
+                       bytes = min(bytes, data_len);
 
                        if (!bio) {
                                nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
@@ -332,12 +337,13 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
 
                        page++;
                        len -= bytes;
+                       data_len -=bytes;
                        off = 0;
                }
        }
 
        rq->buffer = rq->data = NULL;
-       rq->data_len = data_len;
+       rq->data_len = bufflen;
        return 0;
 
 free_bios:
@@ -430,6 +436,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
 static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 {
        cmd->serial_number = 0;
+       cmd->resid = 0;
        memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
        if (cmd->cmd_len == 0)
                cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
@@ -924,11 +931,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                        break;
                                }
                        }
-                       if (!(req->cmd_flags & REQ_QUIET)) {
-                               scmd_printk(KERN_INFO, cmd,
-                                           "Device not ready: ");
-                               scsi_print_sense_hdr("", &sshdr);
-                       }
+                       if (!(req->cmd_flags & REQ_QUIET))
+                               scsi_cmd_print_sense_hdr(cmd,
+                                                        "Device not ready",
+                                                        &sshdr);
+
                        scsi_end_request(cmd, 0, this_count, 1);
                        return;
                case VOLUME_OVERFLOW:
@@ -962,7 +969,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        }
        scsi_end_request(cmd, 0, this_count, !result);
 }
-EXPORT_SYMBOL(scsi_io_completion);
 
 /*
  * Function:    scsi_init_io()
@@ -1019,9 +1025,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
        printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors,
                        req->current_nr_sectors);
 
-       /* release the command and kill it */
-       scsi_release_buffers(cmd);
-       scsi_put_command(cmd);
        return BLKPREP_KILL;
 }
 
@@ -1046,21 +1049,13 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
        return cmd;
 }
 
-static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
-{
-       BUG_ON(!blk_pc_request(cmd->request));
-       /*
-        * This will complete the whole command with uptodate=1 so
-        * as far as the block layer is concerned the command completed
-        * successfully. Since this is a REQ_BLOCK_PC command the
-        * caller should check the request's errors value
-        */
-       scsi_io_completion(cmd, cmd->request_bufflen);
-}
-
-static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
+int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 {
        struct scsi_cmnd *cmd;
+       int ret = scsi_prep_state_check(sdev, req);
+
+       if (ret != BLKPREP_OK)
+               return ret;
 
        cmd = scsi_get_cmd_from_req(sdev, req);
        if (unlikely(!cmd))
@@ -1103,21 +1098,22 @@ static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
        cmd->transfersize = req->data_len;
        cmd->allowed = req->retries;
        cmd->timeout_per_command = req->timeout;
-       cmd->done = scsi_blk_pc_done;
        return BLKPREP_OK;
 }
+EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd);
 
 /*
  * Setup a REQ_TYPE_FS command.  These are simple read/write request
  * from filesystems that still need to be translated to SCSI CDBs from
  * the ULD.
  */
-static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
+int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 {
        struct scsi_cmnd *cmd;
-       struct scsi_driver *drv;
-       int ret;
+       int ret = scsi_prep_state_check(sdev, req);
 
+       if (ret != BLKPREP_OK)
+               return ret;
        /*
         * Filesystem requests must transfer data.
         */
@@ -1127,26 +1123,12 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
        if (unlikely(!cmd))
                return BLKPREP_DEFER;
 
-       ret = scsi_init_io(cmd);
-       if (unlikely(ret))
-               return ret;
-
-       /*
-        * Initialize the actual SCSI command for this request.
-        */
-       drv = *(struct scsi_driver **)req->rq_disk->private_data;
-       if (unlikely(!drv->init_command(cmd))) {
-               scsi_release_buffers(cmd);
-               scsi_put_command(cmd);
-               return BLKPREP_KILL;
-       }
-
-       return BLKPREP_OK;
+       return scsi_init_io(cmd);
 }
+EXPORT_SYMBOL(scsi_setup_fs_cmnd);
 
-static int scsi_prep_fn(struct request_queue *q, struct request *req)
+int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
 {
-       struct scsi_device *sdev = q->queuedata;
        int ret = BLKPREP_OK;
 
        /*
@@ -1192,35 +1174,25 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                                ret = BLKPREP_KILL;
                        break;
                }
-
-               if (ret != BLKPREP_OK)
-                       goto out;
        }
+       return ret;
+}
+EXPORT_SYMBOL(scsi_prep_state_check);
 
-       switch (req->cmd_type) {
-       case REQ_TYPE_BLOCK_PC:
-               ret = scsi_setup_blk_pc_cmnd(sdev, req);
-               break;
-       case REQ_TYPE_FS:
-               ret = scsi_setup_fs_cmnd(sdev, req);
-               break;
-       default:
-               /*
-                * All other command types are not supported.
-                *
-                * Note that these days the SCSI subsystem does not use
-                * REQ_TYPE_SPECIAL requests anymore.  These are only used
-                * (directly or via blk_insert_request) by non-SCSI drivers.
-                */
-               blk_dump_rq_flags(req, "SCSI bad req");
-               ret = BLKPREP_KILL;
-               break;
-       }
+int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
+{
+       struct scsi_device *sdev = q->queuedata;
 
- out:
        switch (ret) {
        case BLKPREP_KILL:
                req->errors = DID_NO_CONNECT << 16;
+               /* release the command and kill it */
+               if (req->special) {
+                       struct scsi_cmnd *cmd = req->special;
+                       scsi_release_buffers(cmd);
+                       scsi_put_command(cmd);
+                       req->special = NULL;
+               }
                break;
        case BLKPREP_DEFER:
                /*
@@ -1237,6 +1209,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
 
        return ret;
 }
+EXPORT_SYMBOL(scsi_prep_return);
+
+static int scsi_prep_fn(struct request_queue *q, struct request *req)
+{
+       struct scsi_device *sdev = q->queuedata;
+       int ret = BLKPREP_KILL;
+
+       if (req->cmd_type == REQ_TYPE_BLOCK_PC)
+               ret = scsi_setup_blk_pc_cmnd(sdev, req);
+       return scsi_prep_return(q, req, ret);
+}
 
 /*
  * scsi_dev_queue_ready: if we can send requests to sdev, return 1 else
index ee8efe849bf41c0c906c5a9f0769e9a054d483a2..eff0059518954b26c62b116cd737f9e11e78da6a 100644 (file)
@@ -68,6 +68,7 @@ extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
 extern void scsi_device_unbusy(struct scsi_device *sdev);
 extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
 extern void scsi_next_command(struct scsi_cmnd *cmd);
+extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
 extern void scsi_run_host_queues(struct Scsi_Host *shost);
 extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);
 extern void scsi_free_queue(struct request_queue *q);
index a86e62f4b3ba86b934cdaaecc7f7213d1ef45d68..b53c5f67e372684cc23c81a9f0ce19a41109e1ac 100644 (file)
@@ -85,7 +85,7 @@ static unsigned int max_scsi_luns = MAX_SCSI_LUNS;
 static unsigned int max_scsi_luns = 1;
 #endif
 
-module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR);
+module_param_named(max_luns, max_scsi_luns, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(max_luns,
                 "last scsi LUN (should be between 1 and 2^32-1)");
 
@@ -109,18 +109,19 @@ MODULE_PARM_DESC(scan, "sync, async or none");
  */
 static unsigned int max_scsi_report_luns = 511;
 
-module_param_named(max_report_luns, max_scsi_report_luns, int, S_IRUGO|S_IWUSR);
+module_param_named(max_report_luns, max_scsi_report_luns, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(max_report_luns,
                 "REPORT LUNS maximum number of LUNS received (should be"
                 " between 1 and 16384)");
 
 static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3;
 
-module_param_named(inq_timeout, scsi_inq_timeout, int, S_IRUGO|S_IWUSR);
+module_param_named(inq_timeout, scsi_inq_timeout, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(inq_timeout, 
                 "Timeout (in seconds) waiting for devices to answer INQUIRY."
                 " Default is 5. Some non-compliant devices need more.");
 
+/* This lock protects only this list */
 static DEFINE_SPINLOCK(async_scan_lock);
 static LIST_HEAD(scanning_hosts);
 
@@ -1466,14 +1467,14 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
        if (strncmp(scsi_scan_type, "none", 4) == 0)
                return ERR_PTR(-ENODEV);
 
-       if (!shost->async_scan)
-               scsi_complete_async_scans();
-
        starget = scsi_alloc_target(parent, channel, id);
        if (!starget)
                return ERR_PTR(-ENOMEM);
 
        mutex_lock(&shost->scan_mutex);
+       if (!shost->async_scan)
+               scsi_complete_async_scans();
+
        if (scsi_host_scan_allowed(shost))
                scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
        mutex_unlock(&shost->scan_mutex);
@@ -1586,10 +1587,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
        if (strncmp(scsi_scan_type, "none", 4) == 0)
                return;
 
+       mutex_lock(&shost->scan_mutex);
        if (!shost->async_scan)
                scsi_complete_async_scans();
 
-       mutex_lock(&shost->scan_mutex);
        if (scsi_host_scan_allowed(shost))
                __scsi_scan_target(parent, channel, id, lun, rescan);
        mutex_unlock(&shost->scan_mutex);
@@ -1634,15 +1635,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
                "%s: <%u:%u:%u>\n",
                __FUNCTION__, channel, id, lun));
 
-       if (!shost->async_scan)
-               scsi_complete_async_scans();
-
        if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
            ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
            ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
                return -EINVAL;
 
        mutex_lock(&shost->scan_mutex);
+       if (!shost->async_scan)
+               scsi_complete_async_scans();
+
        if (scsi_host_scan_allowed(shost)) {
                if (channel == SCAN_WILD_CARD)
                        for (channel = 0; channel <= shost->max_channel;
@@ -1661,7 +1662,8 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
 {
        struct scsi_device *sdev;
        shost_for_each_device(sdev, shost) {
-               if (scsi_sysfs_add_sdev(sdev) != 0)
+               if (!scsi_host_scan_allowed(shost) ||
+                   scsi_sysfs_add_sdev(sdev) != 0)
                        scsi_destroy_sdev(sdev);
        }
 }
@@ -1679,6 +1681,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
 static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 {
        struct async_scan_data *data;
+       unsigned long flags;
 
        if (strncmp(scsi_scan_type, "sync", 4) == 0)
                return NULL;
@@ -1698,8 +1701,13 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
                goto err;
        init_completion(&data->prev_finished);
 
-       spin_lock(&async_scan_lock);
+       mutex_lock(&shost->scan_mutex);
+       spin_lock_irqsave(shost->host_lock, flags);
        shost->async_scan = 1;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+       mutex_unlock(&shost->scan_mutex);
+
+       spin_lock(&async_scan_lock);
        if (list_empty(&scanning_hosts))
                complete(&data->prev_finished);
        list_add_tail(&data->list, &scanning_hosts);
@@ -1723,11 +1731,15 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 static void scsi_finish_async_scan(struct async_scan_data *data)
 {
        struct Scsi_Host *shost;
+       unsigned long flags;
 
        if (!data)
                return;
 
        shost = data->shost;
+
+       mutex_lock(&shost->scan_mutex);
+
        if (!shost->async_scan) {
                printk("%s called twice for host %d", __FUNCTION__,
                                shost->host_no);
@@ -1739,8 +1751,13 @@ static void scsi_finish_async_scan(struct async_scan_data *data)
 
        scsi_sysfs_add_devices(shost);
 
-       spin_lock(&async_scan_lock);
+       spin_lock_irqsave(shost->host_lock, flags);
        shost->async_scan = 0;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+
+       mutex_unlock(&shost->scan_mutex);
+
+       spin_lock(&async_scan_lock);
        list_del(&data->list);
        if (!list_empty(&scanning_hosts)) {
                struct async_scan_data *next = list_entry(scanning_hosts.next,
@@ -1782,6 +1799,7 @@ static int do_scan_async(void *_data)
  **/
 void scsi_scan_host(struct Scsi_Host *shost)
 {
+       struct task_struct *p;
        struct async_scan_data *data;
 
        if (strncmp(scsi_scan_type, "none", 4) == 0)
@@ -1793,7 +1811,9 @@ void scsi_scan_host(struct Scsi_Host *shost)
                return;
        }
 
-       kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
+       p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
+       if (unlikely(IS_ERR(p)))
+               do_scan_async(data);
 }
 EXPORT_SYMBOL(scsi_scan_host);
 
index ede9986d349ad00ee4baa1ffbb14fe157fa5d65c..daed37df00b14eb6fb11160cabaf77b46a8f8d27 100644 (file)
@@ -190,6 +190,46 @@ show_shost_state(struct class_device *class_dev, char *buf)
 
 static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
 
+static ssize_t
+show_shost_mode(unsigned int mode, char *buf)
+{
+       ssize_t len = 0;
+
+       if (mode & MODE_INITIATOR)
+               len = sprintf(buf, "%s", "Initiator");
+
+       if (mode & MODE_TARGET)
+               len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target");
+
+       len += sprintf(buf + len, "\n");
+
+       return len;
+}
+
+static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+
+       if (shost->hostt->supported_mode == MODE_UNKNOWN)
+               return snprintf(buf, 20, "unknown\n");
+       else
+               return show_shost_mode(shost->hostt->supported_mode, buf);
+}
+
+static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
+
+static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(class_dev);
+
+       if (shost->active_mode == MODE_UNKNOWN)
+               return snprintf(buf, 20, "unknown\n");
+       else
+               return show_shost_mode(shost->active_mode, buf);
+}
+
+static CLASS_DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
+
 shost_rd_attr(unique_id, "%u\n");
 shost_rd_attr(host_busy, "%hu\n");
 shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -208,6 +248,8 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
        &class_device_attr_proc_name,
        &class_device_attr_scan,
        &class_device_attr_state,
+       &class_device_attr_supported_mode,
+       &class_device_attr_active_mode,
        NULL
 };
 
@@ -571,24 +613,31 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
 
 /* Default template for device attributes.  May NOT be modified */
-static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
-       &dev_attr_device_blocked,
-       &dev_attr_queue_depth,
-       &dev_attr_queue_type,
-       &dev_attr_type,
-       &dev_attr_scsi_level,
-       &dev_attr_vendor,
-       &dev_attr_model,
-       &dev_attr_rev,
-       &dev_attr_rescan,
-       &dev_attr_delete,
-       &dev_attr_state,
-       &dev_attr_timeout,
-       &dev_attr_iocounterbits,
-       &dev_attr_iorequest_cnt,
-       &dev_attr_iodone_cnt,
-       &dev_attr_ioerr_cnt,
-       &dev_attr_modalias,
+static struct attribute *scsi_sdev_attrs[] = {
+       &dev_attr_device_blocked.attr,
+       &dev_attr_type.attr,
+       &dev_attr_scsi_level.attr,
+       &dev_attr_vendor.attr,
+       &dev_attr_model.attr,
+       &dev_attr_rev.attr,
+       &dev_attr_rescan.attr,
+       &dev_attr_delete.attr,
+       &dev_attr_state.attr,
+       &dev_attr_timeout.attr,
+       &dev_attr_iocounterbits.attr,
+       &dev_attr_iorequest_cnt.attr,
+       &dev_attr_iodone_cnt.attr,
+       &dev_attr_ioerr_cnt.attr,
+       &dev_attr_modalias.attr,
+       NULL
+};
+
+static struct attribute_group scsi_sdev_attr_group = {
+       .attrs =        scsi_sdev_attrs,
+};
+
+static struct attribute_group *scsi_sdev_attr_groups[] = {
+       &scsi_sdev_attr_group,
        NULL
 };
 
@@ -650,56 +699,6 @@ static struct device_attribute sdev_attr_queue_type_rw =
        __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
               sdev_store_queue_type_rw);
 
-static struct device_attribute *attr_changed_internally(
-               struct Scsi_Host *shost,
-               struct device_attribute * attr)
-{
-       if (!strcmp("queue_depth", attr->attr.name)
-           && shost->hostt->change_queue_depth)
-               return &sdev_attr_queue_depth_rw;
-       else if (!strcmp("queue_type", attr->attr.name)
-           && shost->hostt->change_queue_type)
-               return &sdev_attr_queue_type_rw;
-       return attr;
-}
-
-
-static struct device_attribute *attr_overridden(
-               struct device_attribute **attrs,
-               struct device_attribute *attr)
-{
-       int i;
-
-       if (!attrs)
-               return NULL;
-       for (i = 0; attrs[i]; i++)
-               if (!strcmp(attrs[i]->attr.name, attr->attr.name))
-                       return attrs[i];
-       return NULL;
-}
-
-static int attr_add(struct device *dev, struct device_attribute *attr)
-{
-       struct device_attribute *base_attr;
-
-       /*
-        * Spare the caller from having to copy things it's not interested in.
-        */
-       base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
-       if (base_attr) {
-               /* extend permissions */
-               attr->attr.mode |= base_attr->attr.mode;
-
-               /* override null show/store with default */
-               if (!attr->show)
-                       attr->show = base_attr->show;
-               if (!attr->store)
-                       attr->store = base_attr->store;
-       }
-
-       return device_create_file(dev, attr);
-}
-
 /**
  * scsi_sysfs_add_sdev - add scsi device to sysfs
  * @sdev:      scsi_device to add
@@ -731,6 +730,24 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
         * released by the sdev_class .release */
        get_device(&sdev->sdev_gendev);
 
+       /* create queue files, which may be writable, depending on the host */
+       if (sdev->host->hostt->change_queue_depth)
+               error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
+       else
+               error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
+       if (error) {
+               __scsi_remove_device(sdev);
+               goto out;
+       }
+       if (sdev->host->hostt->change_queue_type)
+               error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
+       else
+               error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
+       if (error) {
+               __scsi_remove_device(sdev);
+               goto out;
+       }
+
        error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);
 
        if (error)
@@ -741,9 +758,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
         * nothing went wrong */
        error = 0;
 
+       /* add additional host specific attributes */
        if (sdev->host->hostt->sdev_attrs) {
                for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
-                       error = attr_add(&sdev->sdev_gendev,
+                       error = device_create_file(&sdev->sdev_gendev,
                                        sdev->host->hostt->sdev_attrs[i]);
                        if (error) {
                                __scsi_remove_device(sdev);
@@ -751,20 +769,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                        }
                }
        }
-       
-       for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
-               if (!attr_overridden(sdev->host->hostt->sdev_attrs,
-                                       scsi_sysfs_sdev_attrs[i])) {
-                       struct device_attribute * attr = 
-                               attr_changed_internally(sdev->host, 
-                                                       scsi_sysfs_sdev_attrs[i]);
-                       error = device_create_file(&sdev->sdev_gendev, attr);
-                       if (error) {
-                               __scsi_remove_device(sdev);
-                               goto out;
-                       }
-               }
-       }
 
        transport_add_device(&sdev->sdev_gendev);
  out:
@@ -951,6 +955,12 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
        return 0;
 }
 
+static struct device_type scsi_dev_type = {
+       .name =         "scsi_device",
+       .release =      scsi_device_dev_release,
+       .groups =       scsi_sdev_attr_groups,
+};
+
 void scsi_sysfs_device_initialize(struct scsi_device *sdev)
 {
        unsigned long flags;
@@ -959,7 +969,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
 
        device_initialize(&sdev->sdev_gendev);
        sdev->sdev_gendev.bus = &scsi_bus_type;
-       sdev->sdev_gendev.release = scsi_device_dev_release;
+       sdev->sdev_gendev.type = &scsi_dev_type;
        sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
                sdev->host->host_no, sdev->channel, sdev->id,
                sdev->lun);
@@ -980,7 +990,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
 
 int scsi_is_sdev_device(const struct device *dev)
 {
-       return dev->release == scsi_device_dev_release;
+       return dev->type == &scsi_dev_type;
 }
 EXPORT_SYMBOL(scsi_is_sdev_device);
 
index ca22ddf8174639d2349ccc6c8a42e2d4976ade5f..9815a1a2db24a4c671ee769a670bfc3d6035fbbe 100644 (file)
@@ -102,7 +102,8 @@ static int tgt_uspace_send_event(u32 type, struct tgt_event *p)
        return 0;
 }
 
-int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag)
+int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id,
+                            struct scsi_lun *lun, u64 tag)
 {
        struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
        struct tgt_event ev;
@@ -110,6 +111,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta
 
        memset(&ev, 0, sizeof(ev));
        ev.p.cmd_req.host_no = shost->host_no;
+       ev.p.cmd_req.itn_id = itn_id;
        ev.p.cmd_req.data_len = cmd->request_bufflen;
        memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb));
        memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun));
@@ -127,7 +129,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta
        return err;
 }
 
-int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
+int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag)
 {
        struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
        struct tgt_event ev;
@@ -135,6 +137,7 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
 
        memset(&ev, 0, sizeof(ev));
        ev.p.cmd_done.host_no = shost->host_no;
+       ev.p.cmd_done.itn_id = itn_id;
        ev.p.cmd_done.tag = tag;
        ev.p.cmd_done.result = cmd->result;
 
@@ -149,14 +152,15 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
        return err;
 }
 
-int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
-                                 struct scsi_lun *scsilun, void *data)
+int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function,
+                                 u64 tag, struct scsi_lun *scsilun, void *data)
 {
        struct tgt_event ev;
        int err;
 
        memset(&ev, 0, sizeof(ev));
        ev.p.tsk_mgmt_req.host_no = host_no;
+       ev.p.tsk_mgmt_req.itn_id = itn_id;
        ev.p.tsk_mgmt_req.function = function;
        ev.p.tsk_mgmt_req.tag = tag;
        memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun));
@@ -172,6 +176,29 @@ int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
        return err;
 }
 
+int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id,
+                                         int function, char *initiator_id)
+{
+       struct tgt_event ev;
+       int err;
+
+       memset(&ev, 0, sizeof(ev));
+       ev.p.it_nexus_req.host_no = host_no;
+       ev.p.it_nexus_req.function = function;
+       ev.p.it_nexus_req.itn_id = itn_id;
+       if (initiator_id)
+               strncpy(ev.p.it_nexus_req.initiator_id, initiator_id,
+                       sizeof(ev.p.it_nexus_req.initiator_id));
+
+       dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id);
+
+       err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev);
+       if (err)
+               eprintk("tx buf is full, could not send\n");
+
+       return err;
+}
+
 static int event_recv_msg(struct tgt_event *ev)
 {
        int err = 0;
@@ -179,6 +206,7 @@ static int event_recv_msg(struct tgt_event *ev)
        switch (ev->hdr.type) {
        case TGT_UEVENT_CMD_RSP:
                err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
+                                          ev->p.cmd_rsp.itn_id,
                                           ev->p.cmd_rsp.result,
                                           ev->p.cmd_rsp.tag,
                                           ev->p.cmd_rsp.uaddr,
@@ -189,9 +217,15 @@ static int event_recv_msg(struct tgt_event *ev)
                break;
        case TGT_UEVENT_TSK_MGMT_RSP:
                err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no,
+                                              ev->p.tsk_mgmt_rsp.itn_id,
                                               ev->p.tsk_mgmt_rsp.mid,
                                               ev->p.tsk_mgmt_rsp.result);
                break;
+       case TGT_UEVENT_IT_NEXUS_RSP:
+               err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no,
+                                                  ev->p.it_nexus_rsp.itn_id,
+                                                  ev->p.it_nexus_rsp.result);
+               break;
        default:
                eprintk("unknown type %d\n", ev->hdr.type);
                err = -EINVAL;
index 371b69c110bcc5403b81d4b046ba31dc9888cc9e..66c692ffa3054a2ddafa8c8435bbe642e3737e5c 100644 (file)
@@ -27,6 +27,7 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
 #include <scsi/scsi_tgt.h>
 
 #include "scsi_tgt_priv.h"
@@ -46,6 +47,7 @@ struct scsi_tgt_cmd {
 
        struct list_head hash_list;
        struct request *rq;
+       u64 itn_id;
        u64 tag;
 };
 
@@ -185,12 +187,13 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work)
 }
 
 static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
-                             u64 tag)
+                             u64 itn_id, u64 tag)
 {
        struct scsi_tgt_queuedata *qdata = rq->q->queuedata;
        unsigned long flags;
        struct list_head *head;
 
+       tcmd->itn_id = itn_id;
        tcmd->tag = tag;
        tcmd->bio = NULL;
        INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
@@ -234,7 +237,7 @@ int scsi_tgt_alloc_queue(struct Scsi_Host *shost)
         * command as is recvd to userspace. uspace can then make
         * sure we do not overload the HBA
         */
-       q->nr_requests = shost->hostt->can_queue;
+       q->nr_requests = shost->can_queue;
        /*
         * We currently only support software LLDs so this does
         * not matter for now. Do we need this for the cards we support?
@@ -301,14 +304,14 @@ EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host);
  * @scsilun:   scsi lun
  * @tag:       unique value to identify this command for tmf
  */
-int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun,
-                          u64 tag)
+int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id,
+                          struct scsi_lun *scsilun, u64 tag)
 {
        struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
        int err;
 
-       init_scsi_tgt_cmd(cmd->request, tcmd, tag);
-       err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag);
+       init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag);
+       err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag);
        if (err)
                cmd_hashlist_del(cmd);
 
@@ -326,7 +329,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
 
        dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
 
-       scsi_tgt_uspace_send_status(cmd, tcmd->tag);
+       scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag);
 
        if (cmd->request_buffer)
                scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
@@ -459,7 +462,7 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag)
        return rq;
 }
 
-int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag,
                         unsigned long uaddr, u32 len, unsigned long sense_uaddr,
                         u32 sense_len, u8 rw)
 {
@@ -541,21 +544,22 @@ done:
        return err;
 }
 
-int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag,
-                             struct scsi_lun *scsilun, void *data)
+int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id,
+                             int function, u64 tag, struct scsi_lun *scsilun,
+                             void *data)
 {
        int err;
 
        /* TODO: need to retry if this fails. */
-       err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function,
-                                           tag, scsilun, data);
+       err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id,
+                                           function, tag, scsilun, data);
        if (err < 0)
                eprintk("The task management request lost!\n");
        return err;
 }
 EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request);
 
-int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result)
+int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result)
 {
        struct Scsi_Host *shost;
        int err = -EINVAL;
@@ -573,7 +577,60 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result)
                goto done;
        }
 
-       err = shost->hostt->tsk_mgmt_response(mid, result);
+       err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result);
+done:
+       scsi_host_put(shost);
+       return err;
+}
+
+int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
+                            char *initiator)
+{
+       int err;
+
+       /* TODO: need to retry if this fails. */
+       err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0,
+                                                   initiator);
+       if (err < 0)
+               eprintk("The i_t_neuxs request lost, %d %llx!\n",
+                       shost->host_no, (unsigned long long)itn_id);
+       return err;
+}
+EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create);
+
+int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
+{
+       int err;
+
+       /* TODO: need to retry if this fails. */
+       err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no,
+                                                   itn_id, 1, NULL);
+       if (err < 0)
+               eprintk("The i_t_neuxs request lost, %d %llx!\n",
+                       shost->host_no, (unsigned long long)itn_id);
+       return err;
+}
+EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy);
+
+int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result)
+{
+       struct Scsi_Host *shost;
+       int err = -EINVAL;
+
+       dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
+
+       shost = scsi_host_lookup(host_no);
+       if (IS_ERR(shost)) {
+               printk(KERN_ERR "Could not find host no %d\n", host_no);
+               return err;
+       }
+
+       if (!shost->uspace_req_q) {
+               printk(KERN_ERR "Not target scsi host %d\n", host_no);
+               goto done;
+       }
+
+       err = shost->transportt->it_nexus_response(shost, itn_id, result);
 done:
        scsi_host_put(shost);
        return err;
index e9e6db1c417f38543bedd8415d93e1ce30a6b0c8..cb92888948f9a04756a19bf994e389c02c03a350 100644 (file)
@@ -15,12 +15,18 @@ do {                                                                \
 extern void scsi_tgt_if_exit(void);
 extern int scsi_tgt_if_init(void);
 
-extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun,
-                                   u64 tag);
-extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag);
-extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
-                               unsigned long uaddr, u32 len, unsigned long sense_uaddr,
-                               u32 sense_len, u8 rw);
-extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
+extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id,
+                                   struct scsi_lun *lun, u64 tag);
+extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id,
+                                      u64 tag);
+extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag,
+                               unsigned long uaddr, u32 len,
+                               unsigned long sense_uaddr, u32 sense_len, u8 rw);
+extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id,
+                                        int function, u64 tag,
                                         struct scsi_lun *scsilun, void *data);
-extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result);
+extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id,
+                                   u64 mid, int result);
+extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id,
+                                                int function, char *initiator);
+extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result);
index 47057254850dae0cf3d7f4b86811474c953455bd..7a7cfe583b2ab46171bb51929465aca2abad2ae5 100644 (file)
@@ -36,6 +36,7 @@
 #include <net/netlink.h>
 #include <scsi/scsi_netlink_fc.h>
 #include "scsi_priv.h"
+#include "scsi_transport_fc_internal.h"
 
 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
 static void fc_vport_sched_delete(struct work_struct *work);
@@ -473,7 +474,7 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_class,
  */
 static unsigned int fc_dev_loss_tmo = 60;              /* seconds */
 
-module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR);
+module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(dev_loss_tmo,
                 "Maximum number of seconds that the FC transport should"
                 " insulate the loss of a remote port. Once this value is"
@@ -1956,6 +1957,19 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel,
        return 0;
 }
 
+static int fc_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id,
+                               int result)
+{
+       struct fc_internal *i = to_fc_internal(shost->transportt);
+       return i->f->tsk_mgmt_response(shost, nexus, tm_id, result);
+}
+
+static int fc_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result)
+{
+       struct fc_internal *i = to_fc_internal(shost->transportt);
+       return i->f->it_nexus_response(shost, nexus, result);
+}
+
 struct scsi_transport_template *
 fc_attach_transport(struct fc_function_template *ft)
 {
@@ -1999,6 +2013,10 @@ fc_attach_transport(struct fc_function_template *ft)
 
        i->t.user_scan = fc_user_scan;
 
+       /* target-mode drivers' functions */
+       i->t.tsk_mgmt_response = fc_tsk_mgmt_response;
+       i->t.it_nexus_response = fc_it_nexus_response;
+
        /*
         * Setup SCSI Target Attributes.
         */
@@ -2756,6 +2774,10 @@ fc_remote_port_delete(struct fc_rport  *rport)
 
        spin_unlock_irqrestore(shost->host_lock, flags);
 
+       if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR &&
+           shost->active_mode & MODE_TARGET)
+               fc_tgt_it_nexus_destroy(shost, (unsigned long)rport);
+
        scsi_target_block(&rport->dev);
 
        /* see if we need to kill io faster than waiting for device loss */
@@ -2796,6 +2818,7 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
        struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
        unsigned long flags;
        int create = 0;
+       int ret;
 
        spin_lock_irqsave(shost->host_lock, flags);
        if (roles & FC_PORT_ROLE_FCP_TARGET) {
@@ -2804,6 +2827,12 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
                        create = 1;
                } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
                        create = 1;
+       } else if (shost->active_mode & MODE_TARGET) {
+               ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport,
+                                            (char *)&rport->node_name);
+               if (ret)
+                       printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n",
+                              ret);
        }
 
        rport->roles = roles;
@@ -2988,10 +3017,12 @@ fc_scsi_scan_rport(struct work_struct *work)
        struct fc_rport *rport =
                container_of(work, struct fc_rport, scan_work);
        struct Scsi_Host *shost = rport_to_shost(rport);
+       struct fc_internal *i = to_fc_internal(shost->transportt);
        unsigned long flags;
 
        if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
-           (rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
+           (rport->roles & FC_PORT_ROLE_FCP_TARGET) &&
+           !(i->f->disable_target_scan)) {
                scsi_scan_target(&rport->dev, rport->channel,
                        rport->scsi_target_id, SCAN_WILD_CARD, 1);
        }
diff --git a/drivers/scsi/scsi_transport_fc_internal.h b/drivers/scsi/scsi_transport_fc_internal.h
new file mode 100644 (file)
index 0000000..e7bfbe7
--- /dev/null
@@ -0,0 +1,26 @@
+#include <scsi/scsi_tgt.h>
+
+#ifdef CONFIG_SCSI_FC_TGT_ATTRS
+static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
+                                        char *initiator)
+{
+       return scsi_tgt_it_nexus_create(shost, itn_id, initiator);
+}
+
+static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
+{
+       return scsi_tgt_it_nexus_destroy(shost, itn_id);
+}
+#else
+static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
+                                        char *initiator)
+{
+       return 0;
+}
+
+static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
+{
+       return 0;
+}
+
+#endif
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
new file mode 100644 (file)
index 0000000..44a340b
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * SCSI RDMA (SRP) transport class
+ *
+ * Copyright (C) 2007 FUJITA Tomonori <tomof@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_srp.h>
+#include "scsi_transport_srp_internal.h"
+
+struct srp_host_attrs {
+       atomic_t next_port_id;
+};
+#define to_srp_host_attrs(host)        ((struct srp_host_attrs *)(host)->shost_data)
+
+#define SRP_HOST_ATTRS 0
+#define SRP_RPORT_ATTRS 2
+
+struct srp_internal {
+       struct scsi_transport_template t;
+       struct srp_function_template *f;
+
+       struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
+
+       struct class_device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
+       struct class_device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
+       struct transport_container rport_attr_cont;
+};
+
+#define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t)
+
+#define        dev_to_rport(d) container_of(d, struct srp_rport, dev)
+#define transport_class_to_srp_rport(cdev) dev_to_rport((cdev)->dev)
+
+static int srp_host_setup(struct transport_container *tc, struct device *dev,
+                         struct class_device *cdev)
+{
+       struct Scsi_Host *shost = dev_to_shost(dev);
+       struct srp_host_attrs *srp_host = to_srp_host_attrs(shost);
+
+       atomic_set(&srp_host->next_port_id, 0);
+       return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(srp_host_class, "srp_host", srp_host_setup,
+                              NULL, NULL);
+
+static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
+                              NULL, NULL, NULL);
+
+#define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm)     \
+       i->private_##attrb[count] = class_device_attr_##field;          \
+       i->private_##attrb[count].attr.mode = perm;                     \
+       if (ro_test) {                                                  \
+               i->private_##attrb[count].attr.mode = ro_perm;          \
+               i->private_##attrb[count].store = NULL;                 \
+       }                                                               \
+       i->attrb[count] = &i->private_##attrb[count];                   \
+       if (test)                                                       \
+               count++
+
+#define SETUP_RPORT_ATTRIBUTE_RD(field)                                        \
+       SETUP_TEMPLATE(rport_attrs, field, S_IRUGO, 1, 0, 0)
+
+#define SETUP_RPORT_ATTRIBUTE_RW(field)                                        \
+       SETUP_TEMPLATE(rport_attrs, field, S_IRUGO | S_IWUSR,           \
+                      1, 1, S_IRUGO)
+
+#define SRP_PID(p) \
+       (p)->port_id[0], (p)->port_id[1], (p)->port_id[2], (p)->port_id[3], \
+       (p)->port_id[4], (p)->port_id[5], (p)->port_id[6], (p)->port_id[7], \
+       (p)->port_id[8], (p)->port_id[9], (p)->port_id[10], (p)->port_id[11], \
+       (p)->port_id[12], (p)->port_id[13], (p)->port_id[14], (p)->port_id[15]
+
+#define SRP_PID_FMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
+       "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+
+static ssize_t
+show_srp_rport_id(struct class_device *cdev, char *buf)
+{
+       struct srp_rport *rport = transport_class_to_srp_rport(cdev);
+       return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport));
+}
+
+static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL);
+
+static const struct {
+       u32 value;
+       char *name;
+} srp_rport_role_names[] = {
+       {SRP_RPORT_ROLE_INITIATOR, "SRP Initiator"},
+       {SRP_RPORT_ROLE_TARGET, "SRP Target"},
+};
+
+static ssize_t
+show_srp_rport_roles(struct class_device *cdev, char *buf)
+{
+       struct srp_rport *rport = transport_class_to_srp_rport(cdev);
+       int i;
+       char *name = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(srp_rport_role_names); i++)
+               if (srp_rport_role_names[i].value == rport->roles) {
+                       name = srp_rport_role_names[i].name;
+                       break;
+               }
+       return sprintf(buf, "%s\n", name ? : "unknown");
+}
+
+static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
+
+static void srp_rport_release(struct device *dev)
+{
+       struct srp_rport *rport = dev_to_rport(dev);
+
+       put_device(dev->parent);
+       kfree(rport);
+}
+
+static int scsi_is_srp_rport(const struct device *dev)
+{
+       return dev->release == srp_rport_release;
+}
+
+static int srp_rport_match(struct attribute_container *cont,
+                          struct device *dev)
+{
+       struct Scsi_Host *shost;
+       struct srp_internal *i;
+
+       if (!scsi_is_srp_rport(dev))
+               return 0;
+
+       shost = dev_to_shost(dev->parent);
+       if (!shost->transportt)
+               return 0;
+       if (shost->transportt->host_attrs.ac.class != &srp_host_class.class)
+               return 0;
+
+       i = to_srp_internal(shost->transportt);
+       return &i->rport_attr_cont.ac == cont;
+}
+
+static int srp_host_match(struct attribute_container *cont, struct device *dev)
+{
+       struct Scsi_Host *shost;
+       struct srp_internal *i;
+
+       if (!scsi_is_host_device(dev))
+               return 0;
+
+       shost = dev_to_shost(dev);
+       if (!shost->transportt)
+               return 0;
+       if (shost->transportt->host_attrs.ac.class != &srp_host_class.class)
+               return 0;
+
+       i = to_srp_internal(shost->transportt);
+       return &i->t.host_attrs.ac == cont;
+}
+
+/**
+ * srp_rport_add - add a SRP remote port to the device hierarchy
+ *
+ * @shost:     scsi host the remote port is connected to.
+ * @ids:       The port id for the remote port.
+ *
+ * publishes a port to the rest of the system
+ */
+struct srp_rport *srp_rport_add(struct Scsi_Host *shost,
+                               struct srp_rport_identifiers *ids)
+{
+       struct srp_rport *rport;
+       struct device *parent = &shost->shost_gendev;
+       int id, ret;
+
+       rport = kzalloc(sizeof(*rport), GFP_KERNEL);
+       if (!rport)
+               return ERR_PTR(-ENOMEM);
+
+       device_initialize(&rport->dev);
+
+       rport->dev.parent = get_device(parent);
+       rport->dev.release = srp_rport_release;
+
+       memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id));
+       rport->roles = ids->roles;
+
+       id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id);
+       sprintf(rport->dev.bus_id, "port-%d:%d", shost->host_no, id);
+
+       transport_setup_device(&rport->dev);
+
+       ret = device_add(&rport->dev);
+       if (ret) {
+               transport_destroy_device(&rport->dev);
+               put_device(&rport->dev);
+               return ERR_PTR(ret);
+       }
+
+       if (shost->active_mode & MODE_TARGET &&
+           ids->roles == SRP_RPORT_ROLE_INITIATOR) {
+               ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport,
+                                             rport->port_id);
+               if (ret) {
+                       device_del(&rport->dev);
+                       transport_destroy_device(&rport->dev);
+                       put_device(&rport->dev);
+                       return ERR_PTR(ret);
+               }
+       }
+
+       transport_add_device(&rport->dev);
+       transport_configure_device(&rport->dev);
+
+       return rport;
+}
+EXPORT_SYMBOL_GPL(srp_rport_add);
+
+/**
+ * srp_rport_del  --  remove a SRP remote port
+ * @port:      SRP remote port to remove
+ *
+ * Removes the specified SRP remote port.
+ */
+void srp_rport_del(struct srp_rport *rport)
+{
+       struct device *dev = &rport->dev;
+       struct Scsi_Host *shost = dev_to_shost(dev->parent);
+
+       if (shost->active_mode & MODE_TARGET &&
+           rport->roles == SRP_RPORT_ROLE_INITIATOR)
+               srp_tgt_it_nexus_destroy(shost, (unsigned long)rport);
+
+       transport_remove_device(dev);
+       device_del(dev);
+       transport_destroy_device(dev);
+       put_device(dev);
+}
+EXPORT_SYMBOL_GPL(srp_rport_del);
+
+static int do_srp_rport_del(struct device *dev, void *data)
+{
+       srp_rport_del(dev_to_rport(dev));
+       return 0;
+}
+
+/**
+ * srp_remove_host  --  tear down a Scsi_Host's SRP data structures
+ * @shost:     Scsi Host that is torn down
+ *
+ * Removes all SRP remote ports for a given Scsi_Host.
+ * Must be called just before scsi_remove_host for SRP HBAs.
+ */
+void srp_remove_host(struct Scsi_Host *shost)
+{
+       device_for_each_child(&shost->shost_gendev, NULL, do_srp_rport_del);
+}
+EXPORT_SYMBOL_GPL(srp_remove_host);
+
+static int srp_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id,
+                                int result)
+{
+       struct srp_internal *i = to_srp_internal(shost->transportt);
+       return i->f->tsk_mgmt_response(shost, nexus, tm_id, result);
+}
+
+static int srp_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result)
+{
+       struct srp_internal *i = to_srp_internal(shost->transportt);
+       return i->f->it_nexus_response(shost, nexus, result);
+}
+
+/**
+ * srp_attach_transport  --  instantiate SRP transport template
+ * @ft:                SRP transport class function template
+ */
+struct scsi_transport_template *
+srp_attach_transport(struct srp_function_template *ft)
+{
+       int count;
+       struct srp_internal *i;
+
+       i = kzalloc(sizeof(*i), GFP_KERNEL);
+       if (!i)
+               return NULL;
+
+       i->t.tsk_mgmt_response = srp_tsk_mgmt_response;
+       i->t.it_nexus_response = srp_it_nexus_response;
+
+       i->t.host_size = sizeof(struct srp_host_attrs);
+       i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+       i->t.host_attrs.ac.class = &srp_host_class.class;
+       i->t.host_attrs.ac.match = srp_host_match;
+       i->host_attrs[0] = NULL;
+       transport_container_register(&i->t.host_attrs);
+
+       i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
+       i->rport_attr_cont.ac.class = &srp_rport_class.class;
+       i->rport_attr_cont.ac.match = srp_rport_match;
+       transport_container_register(&i->rport_attr_cont);
+
+       count = 0;
+       SETUP_RPORT_ATTRIBUTE_RD(port_id);
+       SETUP_RPORT_ATTRIBUTE_RD(roles);
+       i->rport_attrs[count] = NULL;
+
+       i->f = ft;
+
+       return &i->t;
+}
+EXPORT_SYMBOL_GPL(srp_attach_transport);
+
+/**
+ * srp_release_transport  --  release SRP transport template instance
+ * @t:         transport template instance
+ */
+void srp_release_transport(struct scsi_transport_template *t)
+{
+       struct srp_internal *i = to_srp_internal(t);
+
+       transport_container_unregister(&i->t.host_attrs);
+       transport_container_unregister(&i->rport_attr_cont);
+
+       kfree(i);
+}
+EXPORT_SYMBOL_GPL(srp_release_transport);
+
+static __init int srp_transport_init(void)
+{
+       int ret;
+
+       ret = transport_class_register(&srp_host_class);
+       if (ret)
+               return ret;
+       ret = transport_class_register(&srp_rport_class);
+       if (ret)
+               goto unregister_host_class;
+
+       return 0;
+unregister_host_class:
+       transport_class_unregister(&srp_host_class);
+       return ret;
+}
+
+static void __exit srp_transport_exit(void)
+{
+       transport_class_unregister(&srp_host_class);
+       transport_class_unregister(&srp_rport_class);
+}
+
+MODULE_AUTHOR("FUJITA Tomonori");
+MODULE_DESCRIPTION("SRP Transport Attributes");
+MODULE_LICENSE("GPL");
+
+module_init(srp_transport_init);
+module_exit(srp_transport_exit);
diff --git a/drivers/scsi/scsi_transport_srp_internal.h b/drivers/scsi/scsi_transport_srp_internal.h
new file mode 100644 (file)
index 0000000..8a79747
--- /dev/null
@@ -0,0 +1,25 @@
+#include <scsi/scsi_tgt.h>
+
+#ifdef CONFIG_SCSI_SRP_TGT_ATTRS
+static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
+                                         char *initiator)
+{
+       return scsi_tgt_it_nexus_create(shost, itn_id, initiator);
+}
+
+static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
+{
+       return scsi_tgt_it_nexus_destroy(shost, itn_id);
+}
+
+#else
+static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
+                                         char *initiator)
+{
+       return 0;
+}
+static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
+{
+       return 0;
+}
+#endif
index 2c6116fd457818a27be8552119425030a6143e68..0a3a528212c2f3fca24f39a9951caba2f2d4e2d0 100644 (file)
@@ -86,6 +86,19 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 
+static int  sd_revalidate_disk(struct gendisk *);
+static int  sd_probe(struct device *);
+static int  sd_remove(struct device *);
+static void sd_shutdown(struct device *);
+static int sd_suspend(struct device *, pm_message_t state);
+static int sd_resume(struct device *);
+static void sd_rescan(struct device *);
+static int sd_done(struct scsi_cmnd *);
+static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
+static void scsi_disk_release(struct class_device *cdev);
+static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
+static void sd_print_result(struct scsi_disk *, int);
+
 static DEFINE_IDR(sd_index_idr);
 static DEFINE_SPINLOCK(sd_index_lock);
 
@@ -240,7 +253,7 @@ static struct scsi_driver sd_template = {
                .shutdown       = sd_shutdown,
        },
        .rescan                 = sd_rescan,
-       .init_command           = sd_init_command,
+       .done                   = sd_done,
 };
 
 /*
@@ -331,14 +344,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
  *
  *     Returns 1 if successful and 0 if error (or cannot be done now).
  **/
-static int sd_init_command(struct scsi_cmnd * SCpnt)
+static int sd_prep_fn(struct request_queue *q, struct request *rq)
 {
-       struct scsi_device *sdp = SCpnt->device;
-       struct request *rq = SCpnt->request;
+       struct scsi_cmnd *SCpnt;
+       struct scsi_device *sdp = q->queuedata;
        struct gendisk *disk = rq->rq_disk;
        sector_t block = rq->sector;
-       unsigned int this_count = SCpnt->request_bufflen >> 9;
+       unsigned int this_count = rq->nr_sectors;
        unsigned int timeout = sdp->timeout;
+       int ret;
+
+       if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
+               ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+               goto out;
+       } else if (rq->cmd_type != REQ_TYPE_FS) {
+               ret = BLKPREP_KILL;
+               goto out;
+       }
+       ret = scsi_setup_fs_cmnd(sdp, rq);
+       if (ret != BLKPREP_OK)
+               goto out;
+       SCpnt = rq->special;
+
+       /* from here on until we're complete, any goto out
+        * is used for a killable error condition */
+       ret = BLKPREP_KILL;
 
        SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
                                        "sd_init_command: block=%llu, "
@@ -353,7 +383,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                                                rq->nr_sectors));
                SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
                                                "Retry with 0x%p\n", SCpnt));
-               return 0;
+               goto out;
        }
 
        if (sdp->changed) {
@@ -362,8 +392,9 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                 * the changed bit has been reset
                 */
                /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
-               return 0;
+               goto out;
        }
+
        SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
                                        (unsigned long long)block));
 
@@ -382,7 +413,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                if ((block & 1) || (rq->nr_sectors & 1)) {
                        scmd_printk(KERN_ERR, SCpnt,
                                    "Bad block number requested\n");
-                       return 0;
+                       goto out;
                } else {
                        block = block >> 1;
                        this_count = this_count >> 1;
@@ -392,7 +423,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                if ((block & 3) || (rq->nr_sectors & 3)) {
                        scmd_printk(KERN_ERR, SCpnt,
                                    "Bad block number requested\n");
-                       return 0;
+                       goto out;
                } else {
                        block = block >> 2;
                        this_count = this_count >> 2;
@@ -402,7 +433,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                if ((block & 7) || (rq->nr_sectors & 7)) {
                        scmd_printk(KERN_ERR, SCpnt,
                                    "Bad block number requested\n");
-                       return 0;
+                       goto out;
                } else {
                        block = block >> 3;
                        this_count = this_count >> 3;
@@ -410,7 +441,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
        }
        if (rq_data_dir(rq) == WRITE) {
                if (!sdp->writeable) {
-                       return 0;
+                       goto out;
                }
                SCpnt->cmnd[0] = WRITE_6;
                SCpnt->sc_data_direction = DMA_TO_DEVICE;
@@ -419,7 +450,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                SCpnt->sc_data_direction = DMA_FROM_DEVICE;
        } else {
                scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags);
-               return 0;
+               goto out;
        }
 
        SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
@@ -470,7 +501,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                         */
                        scmd_printk(KERN_ERR, SCpnt,
                                    "FUA write on READ/WRITE(6) drive\n");
-                       return 0;
+                       goto out;
                }
 
                SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
@@ -491,17 +522,13 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
        SCpnt->allowed = SD_MAX_RETRIES;
        SCpnt->timeout_per_command = timeout;
 
-       /*
-        * This is the completion routine we use.  This is matched in terms
-        * of capability to this function.
-        */
-       SCpnt->done = sd_rw_intr;
-
        /*
         * This indicates that the command is ready from our end to be
         * queued.
         */
-       return 1;
+       ret = BLKPREP_OK;
+ out:
+       return scsi_prep_return(q, rq, ret);
 }
 
 /**
@@ -889,13 +916,13 @@ static struct block_device_operations sd_fops = {
 };
 
 /**
- *     sd_rw_intr - bottom half handler: called when the lower level
+ *     sd_done - bottom half handler: called when the lower level
  *     driver has completed (successfully or otherwise) a scsi command.
  *     @SCpnt: mid-level's per command structure.
  *
  *     Note: potentially run from within an ISR. Must not block.
  **/
-static void sd_rw_intr(struct scsi_cmnd * SCpnt)
+static int sd_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
        unsigned int xfer_size = SCpnt->request_bufflen;
@@ -916,7 +943,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
        SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt));
        if (sense_valid) {
                SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
-                                                  "sd_rw_intr: sb[respc,sk,asc,"
+                                                  "sd_done: sb[respc,sk,asc,"
                                                   "ascq]=%x,%x,%x,%x\n",
                                                   sshdr.response_code,
                                                   sshdr.sense_key, sshdr.asc,
@@ -988,7 +1015,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
                break;
        }
  out:
-       scsi_io_completion(SCpnt, good_bytes);
+       return good_bytes;
 }
 
 static int media_not_present(struct scsi_disk *sdkp,
@@ -1669,6 +1696,7 @@ static int sd_probe(struct device *dev)
 
        sd_revalidate_disk(gd);
 
+       blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
        blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush);
 
        gd->driverfs_dev = &sdp->sdev_gendev;
index 85d38940a6c91e2b0d5b546bb0705bdd3ab37f8a..f6f5fc7d0ceeed80a55e7c1a53d95928c767efcf 100644 (file)
@@ -43,6 +43,7 @@ static int sg_version_num = 30534;    /* 2 digits for each component */
 #include <linux/poll.h>
 #include <linux/moduleparam.h>
 #include <linux/cdev.h>
+#include <linux/idr.h>
 #include <linux/seq_file.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -99,12 +100,11 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
 #define SG_SECTOR_SZ 512
 #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
 
-#define SG_DEV_ARR_LUMP 32     /* amount to over allocate sg_dev_arr by */
-
 static int sg_add(struct class_device *, struct class_interface *);
 static void sg_remove(struct class_device *, struct class_interface *);
 
-static DEFINE_RWLOCK(sg_dev_arr_lock); /* Also used to lock
+static DEFINE_IDR(sg_index_idr);
+static DEFINE_RWLOCK(sg_index_lock);   /* Also used to lock
                                                           file descriptor list for device */
 
 static struct class_interface sg_interface = {
@@ -114,7 +114,7 @@ static struct class_interface sg_interface = {
 
 typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
        unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
-       unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
+       unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */
        unsigned bufflen;       /* Size of (aggregate) data buffer */
        unsigned b_malloc_len;  /* actual len malloc'ed in buffer */
        struct scatterlist *buffer;/* scatter list */
@@ -162,6 +162,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
        struct scsi_device *device;
        wait_queue_head_t o_excl_wait;  /* queue open() when O_EXCL in use */
        int sg_tablesize;       /* adapter's max scatter-gather table size */
+       u32 index;              /* device index number */
        Sg_fd *headfp;          /* first open fd belonging to this device */
        volatile char detached; /* 0->attached, 1->detached pending removal */
        volatile char exclude;  /* opened for exclusive access */
@@ -209,10 +210,6 @@ static Sg_device *sg_get_dev(int dev);
 static int sg_last_dev(void);
 #endif
 
-static Sg_device **sg_dev_arr = NULL;
-static int sg_dev_max;
-static int sg_nr_dev;
-
 #define SZ_SG_HEADER sizeof(struct sg_header)
 #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
 #define SZ_SG_IOVEC sizeof(sg_iovec_t)
@@ -1331,40 +1328,35 @@ static struct class *sg_sysfs_class;
 
 static int sg_sysfs_valid = 0;
 
-static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 {
        struct request_queue *q = scsidp->request_queue;
        Sg_device *sdp;
        unsigned long iflags;
-       void *old_sg_dev_arr = NULL;
-       int k, error;
+       int error;
+       u32 k;
 
        sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL);
        if (!sdp) {
                printk(KERN_WARNING "kmalloc Sg_device failure\n");
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
+       }
+       error = -ENOMEM;
+       if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) {
+               printk(KERN_WARNING "idr expansion Sg_device failure\n");
+               goto out;
        }
 
-       write_lock_irqsave(&sg_dev_arr_lock, iflags);
-       if (unlikely(sg_nr_dev >= sg_dev_max)) {        /* try to resize */
-               Sg_device **tmp_da;
-               int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP;
-               write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
-
-               tmp_da = kzalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL);
-               if (unlikely(!tmp_da))
-                       goto expand_failed;
+       write_lock_irqsave(&sg_index_lock, iflags);
+       error = idr_get_new(&sg_index_idr, sdp, &k);
+       write_unlock_irqrestore(&sg_index_lock, iflags);
 
-               write_lock_irqsave(&sg_dev_arr_lock, iflags);
-               memcpy(tmp_da, sg_dev_arr, sg_dev_max * sizeof(Sg_device *));
-               old_sg_dev_arr = sg_dev_arr;
-               sg_dev_arr = tmp_da;
-               sg_dev_max = tmp_dev_max;
+       if (error) {
+               printk(KERN_WARNING "idr allocation Sg_device failure: %d\n",
+                      error);
+               goto out;
        }
 
-       for (k = 0; k < sg_dev_max; k++)
-               if (!sg_dev_arr[k])
-                       break;
        if (unlikely(k >= SG_MAX_DEVS))
                goto overflow;
 
@@ -1375,25 +1367,17 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
        sdp->device = scsidp;
        init_waitqueue_head(&sdp->o_excl_wait);
        sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments);
+       sdp->index = k;
 
-       sg_nr_dev++;
-       sg_dev_arr[k] = sdp;
-       write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
-       error = k;
-
+       error = 0;
  out:
-       if (error < 0)
+       if (error) {
                kfree(sdp);
-       kfree(old_sg_dev_arr);
-       return error;
-
- expand_failed:
-       printk(KERN_WARNING "sg_alloc: device array cannot be resized\n");
-       error = -ENOMEM;
-       goto out;
+               return ERR_PTR(error);
+       }
+       return sdp;
 
  overflow:
-       write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
        sdev_printk(KERN_WARNING, scsidp,
                    "Unable to attach sg device type=%d, minor "
                    "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1);
@@ -1408,7 +1392,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
        struct gendisk *disk;
        Sg_device *sdp = NULL;
        struct cdev * cdev = NULL;
-       int error, k;
+       int error;
        unsigned long iflags;
 
        disk = alloc_disk(1);
@@ -1427,15 +1411,15 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
        cdev->owner = THIS_MODULE;
        cdev->ops = &sg_fops;
 
-       error = sg_alloc(disk, scsidp);
-       if (error < 0) {
+       sdp = sg_alloc(disk, scsidp);
+       if (IS_ERR(sdp)) {
                printk(KERN_WARNING "sg_alloc failed\n");
+               error = PTR_ERR(sdp);
                goto out;
        }
-       k = error;
-       sdp = sg_dev_arr[k];
 
-       error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1);
+       class_set_devdata(cl_dev, sdp);
+       error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), 1);
        if (error)
                goto cdev_add_err;
 
@@ -1444,8 +1428,8 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
                struct class_device * sg_class_member;
 
                sg_class_member = class_device_create(sg_sysfs_class, NULL,
-                               MKDEV(SCSI_GENERIC_MAJOR, k), 
-                               cl_dev->dev, "%s", 
+                               MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
+                               cl_dev->dev, "%s",
                                disk->disk_name);
                if (IS_ERR(sg_class_member))
                        printk(KERN_WARNING "sg_add: "
@@ -1455,21 +1439,21 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
                                          &sg_class_member->kobj, "generic");
                if (error)
                        printk(KERN_ERR "sg_add: unable to make symlink "
-                                       "'generic' back to sg%d\n", k);
+                                       "'generic' back to sg%d\n", sdp->index);
        } else
-               printk(KERN_WARNING "sg_add: sg_sys INvalid\n");
+               printk(KERN_WARNING "sg_add: sg_sys Invalid\n");
 
        sdev_printk(KERN_NOTICE, scsidp,
-                   "Attached scsi generic sg%d type %d\n", k,scsidp->type);
+                   "Attached scsi generic sg%d type %d\n", sdp->index,
+                   scsidp->type);
 
        return 0;
 
 cdev_add_err:
-       write_lock_irqsave(&sg_dev_arr_lock, iflags);
-       kfree(sg_dev_arr[k]);
-       sg_dev_arr[k] = NULL;
-       sg_nr_dev--;
-       write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
+       write_lock_irqsave(&sg_index_lock, iflags);
+       idr_remove(&sg_index_idr, sdp->index);
+       write_unlock_irqrestore(&sg_index_lock, iflags);
+       kfree(sdp);
 
 out:
        put_disk(disk);
@@ -1482,64 +1466,56 @@ static void
 sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
 {
        struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
-       Sg_device *sdp = NULL;
+       Sg_device *sdp = class_get_devdata(cl_dev);
        unsigned long iflags;
        Sg_fd *sfp;
        Sg_fd *tsfp;
        Sg_request *srp;
        Sg_request *tsrp;
-       int k, delay;
+       int delay;
 
-       if (NULL == sg_dev_arr)
+       if (!sdp)
                return;
+
        delay = 0;
-       write_lock_irqsave(&sg_dev_arr_lock, iflags);
-       for (k = 0; k < sg_dev_max; k++) {
-               sdp = sg_dev_arr[k];
-               if ((NULL == sdp) || (sdp->device != scsidp))
-                       continue;       /* dirty but lowers nesting */
-               if (sdp->headfp) {
-                       sdp->detached = 1;
-                       for (sfp = sdp->headfp; sfp; sfp = tsfp) {
-                               tsfp = sfp->nextfp;
-                               for (srp = sfp->headrp; srp; srp = tsrp) {
-                                       tsrp = srp->nextrp;
-                                       if (sfp->closed || (0 == sg_srp_done(srp, sfp)))
-                                               sg_finish_rem_req(srp);
-                               }
-                               if (sfp->closed) {
-                                       scsi_device_put(sdp->device);
-                                       __sg_remove_sfp(sdp, sfp);
-                               } else {
-                                       delay = 1;
-                                       wake_up_interruptible(&sfp->read_wait);
-                                       kill_fasync(&sfp->async_qp, SIGPOLL,
-                                                   POLL_HUP);
-                               }
+       write_lock_irqsave(&sg_index_lock, iflags);
+       if (sdp->headfp) {
+               sdp->detached = 1;
+               for (sfp = sdp->headfp; sfp; sfp = tsfp) {
+                       tsfp = sfp->nextfp;
+                       for (srp = sfp->headrp; srp; srp = tsrp) {
+                               tsrp = srp->nextrp;
+                               if (sfp->closed || (0 == sg_srp_done(srp, sfp)))
+                                       sg_finish_rem_req(srp);
                        }
-                       SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", k));
-                       if (NULL == sdp->headfp) {
-                               sg_dev_arr[k] = NULL;
+                       if (sfp->closed) {
+                               scsi_device_put(sdp->device);
+                               __sg_remove_sfp(sdp, sfp);
+                       } else {
+                               delay = 1;
+                               wake_up_interruptible(&sfp->read_wait);
+                               kill_fasync(&sfp->async_qp, SIGPOLL,
+                                           POLL_HUP);
                        }
-               } else {        /* nothing active, simple case */
-                       SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", k));
-                       sg_dev_arr[k] = NULL;
                }
-               sg_nr_dev--;
-               break;
-       }
-       write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
-
-       if (sdp) {
-               sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
-               class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k));
-               cdev_del(sdp->cdev);
-               sdp->cdev = NULL;
-               put_disk(sdp->disk);
-               sdp->disk = NULL;
-               if (NULL == sdp->headfp)
-                       kfree((char *) sdp);
-       }
+               SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", sdp->index));
+               if (NULL == sdp->headfp) {
+                       idr_remove(&sg_index_idr, sdp->index);
+               }
+       } else {        /* nothing active, simple case */
+               SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", sdp->index));
+               idr_remove(&sg_index_idr, sdp->index);
+       }
+       write_unlock_irqrestore(&sg_index_lock, iflags);
+
+       sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
+       class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
+       cdev_del(sdp->cdev);
+       sdp->cdev = NULL;
+       put_disk(sdp->disk);
+       sdp->disk = NULL;
+       if (NULL == sdp->headfp)
+               kfree(sdp);
 
        if (delay)
                msleep(10);     /* dirty detach so delay device destruction */
@@ -1609,9 +1585,7 @@ exit_sg(void)
        sg_sysfs_valid = 0;
        unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
                                 SG_MAX_DEVS);
-       kfree((char *)sg_dev_arr);
-       sg_dev_arr = NULL;
-       sg_dev_max = 0;
+       idr_destroy(&sg_index_idr);
 }
 
 static int
@@ -2331,10 +2305,10 @@ sg_get_nth_sfp(Sg_device * sdp, int nth)
        unsigned long iflags;
        int k;
 
-       read_lock_irqsave(&sg_dev_arr_lock, iflags);
+       read_lock_irqsave(&sg_index_lock, iflags);
        for (k = 0, resp = sdp->headfp; resp && (k < nth);
             ++k, resp = resp->nextfp) ;
-       read_unlock_irqrestore(&sg_dev_arr_lock, iflags);
+       read_unlock_irqrestore(&sg_index_lock, iflags);
        return resp;
 }
 #endif
@@ -2361,7 +2335,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
        sfp->cmd_q = SG_DEF_COMMAND_Q;
        sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
        sfp->parentdp = sdp;
-       write_lock_irqsave(&sg_dev_arr_lock, iflags);
+       write_lock_irqsave(&sg_index_lock, iflags);
        if (!sdp->headfp)
                sdp->headfp = sfp;
        else {                  /* add to tail of existing list */
@@ -2370,7 +2344,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
                        pfp = pfp->nextfp;
                pfp->nextfp = sfp;
        }
-       write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
+       write_unlock_irqrestore(&sg_index_lock, iflags);
        SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
        if (unlikely(sg_big_buff != def_reserved_size))
                sg_big_buff = def_reserved_size;
@@ -2431,22 +2405,14 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
        if (0 == dirty) {
                unsigned long iflags;
 
-               write_lock_irqsave(&sg_dev_arr_lock, iflags);
+               write_lock_irqsave(&sg_index_lock, iflags);
                __sg_remove_sfp(sdp, sfp);
                if (sdp->detached && (NULL == sdp->headfp)) {
-                       int k, maxd;
-
-                       maxd = sg_dev_max;
-                       for (k = 0; k < maxd; ++k) {
-                               if (sdp == sg_dev_arr[k])
-                                       break;
-                       }
-                       if (k < maxd)
-                               sg_dev_arr[k] = NULL;
-                       kfree((char *) sdp);
+                       idr_remove(&sg_index_idr, sdp->index);
+                       kfree(sdp);
                        res = 1;
                }
-               write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
+               write_unlock_irqrestore(&sg_index_lock, iflags);
        } else {
                /* MOD_INC's to inhibit unloading sg and associated adapter driver */
                /* only bump the access_count if we actually succeeded in
@@ -2545,17 +2511,26 @@ sg_allow_access(unsigned char opcode, char dev_type)
 }
 
 #ifdef CONFIG_SCSI_PROC_FS
+static int
+sg_idr_max_id(int id, void *p, void *data)
+{
+       int *k = data;
+
+       if (*k < id)
+               *k = id;
+
+       return 0;
+}
+
 static int
 sg_last_dev(void)
 {
-       int k;
+       int k = 0;
        unsigned long iflags;
 
-       read_lock_irqsave(&sg_dev_arr_lock, iflags);
-       for (k = sg_dev_max - 1; k >= 0; --k)
-               if (sg_dev_arr[k] && sg_dev_arr[k]->device)
-                       break;
-       read_unlock_irqrestore(&sg_dev_arr_lock, iflags);
+       read_lock_irqsave(&sg_index_lock, iflags);
+       idr_for_each(&sg_index_idr, sg_idr_max_id, &k);
+       read_unlock_irqrestore(&sg_index_lock, iflags);
        return k + 1;           /* origin 1 */
 }
 #endif
@@ -2563,15 +2538,13 @@ sg_last_dev(void)
 static Sg_device *
 sg_get_dev(int dev)
 {
-       Sg_device *sdp = NULL;
+       Sg_device *sdp;
        unsigned long iflags;
 
-       if (sg_dev_arr && (dev >= 0)) {
-               read_lock_irqsave(&sg_dev_arr_lock, iflags);
-               if (dev < sg_dev_max)
-                       sdp = sg_dev_arr[dev];
-               read_unlock_irqrestore(&sg_dev_arr_lock, iflags);
-       }
+       read_lock_irqsave(&sg_index_lock, iflags);
+       sdp = idr_find(&sg_index_idr, dev);
+       read_unlock_irqrestore(&sg_index_lock, iflags);
+
        return sdp;
 }
 
@@ -2805,8 +2778,6 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos)
        if (! it)
                return NULL;
 
-       if (NULL == sg_dev_arr)
-               return NULL;
        it->index = *pos;
        it->max = sg_last_dev();
        if (it->index >= it->max)
@@ -2942,8 +2913,8 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v)
        Sg_device *sdp;
 
        if (it && (0 == it->index)) {
-               seq_printf(s, "dev_max(currently)=%d max_active_device=%d "
-                          "(origin 1)\n", sg_dev_max, (int)it->max);
+               seq_printf(s, "max_active_device=%d(origin 1)\n",
+                          (int)it->max);
                seq_printf(s, " def_reserved_size=%d\n", sg_big_buff);
        }
        sdp = it ? sg_get_dev(it->index) : NULL;
index 902eb11ffe8a1110d0c911a367432f06865dd3a0..c61999031141ca8912a3ac0cecd441bae53cc2db 100644 (file)
@@ -78,7 +78,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
 
 static int sr_probe(struct device *);
 static int sr_remove(struct device *);
-static int sr_init_command(struct scsi_cmnd *);
+static int sr_done(struct scsi_cmnd *);
 
 static struct scsi_driver sr_template = {
        .owner                  = THIS_MODULE,
@@ -87,7 +87,7 @@ static struct scsi_driver sr_template = {
                .probe          = sr_probe,
                .remove         = sr_remove,
        },
-       .init_command           = sr_init_command,
+       .done                   = sr_done,
 };
 
 static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG];
@@ -210,12 +210,12 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot)
 }
  
 /*
- * rw_intr is the interrupt routine for the device driver.
+ * sr_done is the interrupt routine for the device driver.
  *
- * It will be notified on the end of a SCSI read / write, and will take on
+ * It will be notified on the end of a SCSI read / write, and will take one
  * of several actions based on success or failure.
  */
-static void rw_intr(struct scsi_cmnd * SCpnt)
+static int sr_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
        int this_count = SCpnt->request_bufflen;
@@ -288,27 +288,42 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
                }
        }
 
-       /*
-        * This calls the generic completion function, now that we know
-        * how many actual sectors finished, and how many sectors we need
-        * to say have failed.
-        */
-       scsi_io_completion(SCpnt, good_bytes);
+       return good_bytes;
 }
 
-static int sr_init_command(struct scsi_cmnd * SCpnt)
+static int sr_prep_fn(struct request_queue *q, struct request *rq)
 {
        int block=0, this_count, s_size, timeout = SR_TIMEOUT;
-       struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk);
+       struct scsi_cd *cd;
+       struct scsi_cmnd *SCpnt;
+       struct scsi_device *sdp = q->queuedata;
+       int ret;
+
+       if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
+               ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+               goto out;
+       } else if (rq->cmd_type != REQ_TYPE_FS) {
+               ret = BLKPREP_KILL;
+               goto out;
+       }
+       ret = scsi_setup_fs_cmnd(sdp, rq);
+       if (ret != BLKPREP_OK)
+               goto out;
+       SCpnt = rq->special;
+       cd = scsi_cd(rq->rq_disk);
+
+       /* from here on until we're complete, any goto out
+        * is used for a killable error condition */
+       ret = BLKPREP_KILL;
 
        SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n",
                                cd->disk->disk_name, block));
 
        if (!cd->device || !scsi_device_online(cd->device)) {
                SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n",
-                                       SCpnt->request->nr_sectors));
+                                       rq->nr_sectors));
                SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
-               return 0;
+               goto out;
        }
 
        if (cd->device->changed) {
@@ -316,7 +331,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
                 * quietly refuse to do anything to a changed disc until the
                 * changed bit has been reset
                 */
-               return 0;
+               goto out;
        }
 
        /*
@@ -333,21 +348,21 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
 
        if (s_size != 512 && s_size != 1024 && s_size != 2048) {
                scmd_printk(KERN_ERR, SCpnt, "bad sector size %d\n", s_size);
-               return 0;
+               goto out;
        }
 
-       if (rq_data_dir(SCpnt->request) == WRITE) {
+       if (rq_data_dir(rq) == WRITE) {
                if (!cd->device->writeable)
-                       return 0;
+                       goto out;
                SCpnt->cmnd[0] = WRITE_10;
                SCpnt->sc_data_direction = DMA_TO_DEVICE;
                cd->cdi.media_written = 1;
-       } else if (rq_data_dir(SCpnt->request) == READ) {
+       } else if (rq_data_dir(rq) == READ) {
                SCpnt->cmnd[0] = READ_10;
                SCpnt->sc_data_direction = DMA_FROM_DEVICE;
        } else {
-               blk_dump_rq_flags(SCpnt->request, "Unknown sr command");
-               return 0;
+               blk_dump_rq_flags(rq, "Unknown sr command");
+               goto out;
        }
 
        {
@@ -368,10 +383,10 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
        /*
         * request doesn't start on hw block boundary, add scatter pads
         */
-       if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) ||
+       if (((unsigned int)rq->sector % (s_size >> 9)) ||
            (SCpnt->request_bufflen % s_size)) {
                scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n");
-               return 0;
+               goto out;
        }
 
        this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
@@ -379,12 +394,12 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
 
        SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
                                cd->cdi.name,
-                               (rq_data_dir(SCpnt->request) == WRITE) ?
+                               (rq_data_dir(rq) == WRITE) ?
                                        "writing" : "reading",
-                               this_count, SCpnt->request->nr_sectors));
+                               this_count, rq->nr_sectors));
 
        SCpnt->cmnd[1] = 0;
-       block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
+       block = (unsigned int)rq->sector / (s_size >> 9);
 
        if (this_count > 0xffff) {
                this_count = 0xffff;
@@ -409,17 +424,13 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
        SCpnt->allowed = MAX_RETRIES;
        SCpnt->timeout_per_command = timeout;
 
-       /*
-        * This is the completion routine we use.  This is matched in terms
-        * of capability to this function.
-        */
-       SCpnt->done = rw_intr;
-
        /*
         * This indicates that the command is ready from our end to be
         * queued.
         */
-       return 1;
+       ret = BLKPREP_OK;
+ out:
+       return scsi_prep_return(q, rq, ret);
 }
 
 static int sr_block_open(struct inode *inode, struct file *file)
@@ -590,6 +601,7 @@ static int sr_probe(struct device *dev)
 
        /* FIXME: need to handle a get_capabilities failure properly ?? */
        get_capabilities(cd);
+       blk_queue_prep_rq(sdev->request_queue, sr_prep_fn);
        sr_vendor_init(cd);
 
        disk->driverfs_dev = &sdev->sdev_gendev;
index 98e3fe10c1dcfe8d6be2c12f9c8da461afcae710..dc15a22105f71ac6102cd4b63e5b60c2ab4ca3ef 100644 (file)
@@ -2055,7 +2055,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                sink = 1;
                do_abort(instance);
                cmd->result = DID_ERROR  << 16;
-               cmd->done(cmd);
+               cmd->scsi_done(cmd);
                return;
 #endif
            case PHASE_DATAIN:
@@ -2115,7 +2115,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                        sink = 1;
                        do_abort(instance);
                        cmd->result = DID_ERROR  << 16;
-                       cmd->done(cmd);
+                       cmd->scsi_done(cmd);
                        /* XXX - need to source or sink data here, as appropriate */
                    } else {
 #ifdef REAL_DMA
@@ -2254,25 +2254,21 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                        cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
                    
 #ifdef AUTOSENSE
+                   if ((cmd->cmnd[0] == REQUEST_SENSE) &&
+                                               hostdata->ses.cmd_len) {
+                       scsi_eh_restore_cmnd(cmd, &hostdata->ses);
+                       hostdata->ses.cmd_len = 0 ;
+                   }
+
                    if ((cmd->cmnd[0] != REQUEST_SENSE) && 
                        (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+                       scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
                        ASEN_PRINTK("scsi%d: performing request sense\n",
                                    HOSTNO);
-                       cmd->cmnd[0] = REQUEST_SENSE;
-                       cmd->cmnd[1] &= 0xe0;
-                       cmd->cmnd[2] = 0;
-                       cmd->cmnd[3] = 0;
-                       cmd->cmnd[4] = sizeof(cmd->sense_buffer);
-                       cmd->cmnd[5] = 0;
-                       cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-
-                       cmd->use_sg = 0;
                        /* this is initialized from initialize_SCp 
                        cmd->SCp.buffer = NULL;
                        cmd->SCp.buffers_residual = 0;
                        */
-                       cmd->request_buffer = (char *) cmd->sense_buffer;
-                       cmd->request_bufflen = sizeof(cmd->sense_buffer);
 
                        local_irq_save(flags);
                        LIST(cmd,hostdata->issue_queue);
index 5db1520f8ba968a48a9bcc783d2e100cc5d0c98f..5c72ca31a47a9d69a11915f76d7f9e645071b685 100644 (file)
@@ -567,12 +567,12 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr
        pDCB->TagMask |= 1 << tag[1];
        pSRB->TagNumber = tag[1];
        DC390_write8(ScsiFifo, tag[1]);
-       DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->pid, pSRB, tag[1]));
+       DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->serial_number, pSRB, tag[1]));
        cmd = SEL_W_ATN3;
     } else {
        /* No TagQ */
 //no_tag:
-       DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->pid, pSRB));
+       DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->serial_number, pSRB));
     }
 
     pSRB->SRBState = SRB_START_;
@@ -623,7 +623,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr
     {
        dc390_freetag (pDCB, pSRB);
        DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n",
-               scmd->pid, scmd->device->id, scmd->device->lun));
+               scmd->serial_number, scmd->device->id, scmd->device->lun));
        pSRB->SRBState = SRB_READY;
        //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
        pACB->SelLost++;
@@ -1708,7 +1708,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb*
     status = pSRB->TargetStatus;
 
     DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
-               pSRB, pcmd->pid));
+               pSRB, pcmd->serial_number));
     if(pSRB->SRBFlag & AUTO_REQSENSE)
     {  /* Last command was a Request Sense */
        pSRB->SRBFlag &= ~AUTO_REQSENSE;
@@ -1729,7 +1729,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb*
            } else {
                SET_RES_DRV(pcmd->result, DRIVER_SENSE);
                //pSRB->ScsiCmdLen       = (u8) (pSRB->Segment1[0] >> 8);
-               DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
+               DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
                pSRB->TotalXferredLen = 0;
                SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
            }
@@ -1749,7 +1749,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb*
        else if (status == SAM_STAT_TASK_SET_FULL)
        {
            scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
-           DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
+           DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
            pSRB->TotalXferredLen = 0;
            SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
        }
@@ -1803,7 +1803,7 @@ cmd_done:
     /* Add to free list */
     dc390_Free_insert (pACB, pSRB);
 
-    DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid));
+    DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->serial_number));
     pcmd->scsi_done (pcmd);
 
     return;
@@ -1998,7 +1998,7 @@ static int DC390_abort(struct scsi_cmnd *cmd)
        struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
 
        scmd_printk(KERN_WARNING, cmd,
-               "DC390: Abort command (pid %li)\n", cmd->pid);
+               "DC390: Abort command (pid %li)\n", cmd->serial_number);
 
        /* abort() is too stupid for already sent commands at the moment. 
         * If it's called we are in trouble anyway, so let's dump some info 
@@ -2006,7 +2006,7 @@ static int DC390_abort(struct scsi_cmnd *cmd)
        dc390_dumpinfo(pACB, pDCB, NULL);
 
        pDCB->DCBFlag |= ABORT_DEV_;
-       printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid);
+       printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->serial_number);
 
        return FAILED;
 }
index 9e8232a1f16966efdd87b2257ac6706560b265b1..fc9f51818e8f3fb2b6e4a0d48027250d67a4eeaa 100644 (file)
@@ -1254,7 +1254,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
 
    if (SCpnt->host_scribble)
       panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
-            BN(j), SCpnt->pid, SCpnt);
+            BN(j), SCpnt->serial_number, SCpnt);
 
    /* i is the mailbox number, look for the first free mailbox
       starting from last_cp_used */
@@ -1285,7 +1285,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
                         BN(j), i, SCpnt->device->channel, SCpnt->device->id,
-                        SCpnt->device->lun, SCpnt->pid);
+                        SCpnt->device->lun, SCpnt->serial_number);
 
    cpp->opcode = OP_SCSI;
    cpp->channel = SCpnt->device->channel;
@@ -1312,7 +1312,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs
       unmap_dma(i, j);
       SCpnt->host_scribble = NULL;
       scmd_printk(KERN_INFO, SCpnt,
-               "qcomm, pid %ld, adapter busy.\n", SCpnt->pid);
+               "qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
       return 1;
       }
 
@@ -1333,13 +1333,13 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) {
 
    if (SCarg->host_scribble == NULL) {
       scmd_printk(KERN_INFO, SCarg, "abort, pid %ld inactive.\n",
-             SCarg->pid);
+             SCarg->serial_number);
       return SUCCESS;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
    scmd_printk(KERN_INFO, SCarg, "abort, mbox %d, pid %ld.\n",
-              i, SCarg->pid);
+              i, SCarg->serial_number);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -1383,7 +1383,7 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) {
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
       printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-             BN(j), i, SCarg->pid);
+             BN(j), i, SCarg->serial_number);
       SCarg->scsi_done(SCarg);
       return SUCCESS;
       }
@@ -1397,12 +1397,12 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
    struct scsi_cmnd *SCpnt;
 
    j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number;
-   scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->pid);
+   scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->serial_number);
 
    spin_lock_irq(sh[j]->host_lock);
 
    if (SCarg->host_scribble == NULL)
-      printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
+      printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->serial_number);
 
    if (HD(j)->in_reset) {
       printk("%s: reset, exit, already in reset.\n", BN(j));
@@ -1440,13 +1440,13 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
       if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
          HD(j)->cp_stat[i] = ABORTING;
          printk("%s: reset, mbox %d aborting, pid %ld.\n",
-                BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->serial_number);
          }
 
       else {
          HD(j)->cp_stat[i] = IN_RESET;
          printk("%s: reset, mbox %d in reset, pid %ld.\n",
-                BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->serial_number);
          }
 
       if (SCpnt->host_scribble == NULL)
@@ -1495,7 +1495,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
          HD(j)->cp_stat[i] = LOCKED;
 
          printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-                BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->serial_number);
          }
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
@@ -1508,7 +1508,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
          HD(j)->cp_stat[i] = FREE;
 
          printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-                BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->serial_number);
          }
 
       else
@@ -1522,7 +1522,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
    HD(j)->in_reset = FALSE;
    do_trace = FALSE;
 
-   if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid);
+   if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->serial_number);
    else          printk("%s: reset, exit.\n", BN(j));
 
    spin_unlock_irq(sh[j]->host_lock);
@@ -1639,7 +1639,7 @@ static int reorder(unsigned int j, unsigned long cursec,
 
    if (!input_only) for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
-      ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->pid;
+      ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->serial_number;
 
       if (!n) continue;
 
@@ -1666,7 +1666,7 @@ static int reorder(unsigned int j, unsigned long cursec,
          printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"\
                 " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n",
                 (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
-                SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
+                SCpnt->lun, SCpnt->serial_number, k, flushcount, n_ready,
                 SCpnt->request->sector, SCpnt->request->nr_sectors, cursec,
                 YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
                 YESNO(overlap), cpp->xdir);
@@ -1703,7 +1703,7 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned in
          scmd_printk(KERN_INFO, SCpnt,
                "%s, pid %ld, mbox %d, adapter"
                 " busy, will abort.\n", (ihdlr ? "ihdlr" : "qcomm"),
-                SCpnt->pid, k);
+                SCpnt->serial_number, k);
          HD(j)->cp_stat[k] = ABORTING;
          continue;
          }
@@ -1787,11 +1787,11 @@ static irqreturn_t ihdlr(int irq, unsigned int j) {
 
    if (SCpnt->host_scribble == NULL)
       panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
-            SCpnt->pid, SCpnt);
+            SCpnt->serial_number, SCpnt);
 
    if (*(unsigned int *)SCpnt->host_scribble != i)
       panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
-            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
+            BN(j), i, SCpnt->serial_number, *(unsigned int *)SCpnt->host_scribble);
 
    sync_dma(i, j);
 
@@ -1835,12 +1835,12 @@ static irqreturn_t ihdlr(int irq, unsigned int j) {
                (SCpnt->sense_buffer[2] & 0xf) == NOT_READY)))
             scmd_printk(KERN_INFO, SCpnt,
                "ihdlr, pid %ld, target_status 0x%x, sense key 0x%x.\n",
-                   SCpnt->pid, spp->target_status,
+                   SCpnt->serial_number, spp->target_status,
                    SCpnt->sense_buffer[2]);
 
          HD(j)->target_to[scmd_id(SCpnt)][scmd_channel(SCpnt)] = 0;
 
-         if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+         if (HD(j)->last_retried_pid == SCpnt->serial_number) HD(j)->retries = 0;
 
          break;
       case ASST:     /* Selection Time Out */
@@ -1877,7 +1877,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) {
 #endif
 
             HD(j)->retries++;
-            HD(j)->last_retried_pid = SCpnt->pid;
+            HD(j)->last_retried_pid = SCpnt->serial_number;
             }
          else
             status = DID_ERROR << 16;
@@ -1907,7 +1907,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) {
 #endif
       scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"\
              " pid %ld, reg 0x%x, count %d.\n",
-             i, spp->adapter_status, spp->target_status, SCpnt->pid,
+             i, spp->adapter_status, spp->target_status, SCpnt->serial_number,
              reg, HD(j)->iocount);
 
    unmap_dma(i, j);
index b92ff047af381c223333aca9b6ac9a4449ccabd8..0e8e642fd3b031f28dbea5adec68b41e64206474 100644 (file)
@@ -381,7 +381,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
        hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
 
        DB(DB_QUEUE_COMMAND,
-          printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->pid))
+          printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->serial_number))
 
 /* Set up a few fields in the scsi_cmnd structure for our own use:
  *  - host_scribble is the pointer to the next cmd in the input queue
@@ -463,7 +463,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
 
        wd33c93_execute(cmd->device->host);
 
-       DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid))
+       DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
 
        spin_unlock_irq(&hostdata->lock);
        return 0;
@@ -686,7 +686,7 @@ wd33c93_execute(struct Scsi_Host *instance)
         */
 
        DB(DB_EXECUTE,
-          printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid))
+          printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number))
 }
 
 static void
@@ -963,7 +963,7 @@ wd33c93_intr(struct Scsi_Host *instance)
        case CSR_XFER_DONE | PHS_COMMAND:
        case CSR_UNEXP | PHS_COMMAND:
        case CSR_SRV_REQ | PHS_COMMAND:
-               DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid))
+               DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number))
                    transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR,
                                 hostdata);
                hostdata->state = S_CONNECTED;
@@ -1007,7 +1007,7 @@ wd33c93_intr(struct Scsi_Host *instance)
                switch (msg) {
 
                case COMMAND_COMPLETE:
-                       DB(DB_INTR, printk("CCMP-%ld", cmd->pid))
+                       DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number))
                            write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
                        hostdata->state = S_PRE_CMP_DISC;
                        break;
@@ -1174,7 +1174,7 @@ wd33c93_intr(struct Scsi_Host *instance)
 
                write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
                if (phs == 0x60) {
-                       DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid))
+                       DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number))
                            cmd->SCp.Message = COMMAND_COMPLETE;
                        lun = read_wd33c93(regs, WD_TARGET_LUN);
                        DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
@@ -1201,7 +1201,7 @@ wd33c93_intr(struct Scsi_Host *instance)
                } else {
                        printk
                            ("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",
-                            asr, sr, phs, cmd->pid);
+                            asr, sr, phs, cmd->serial_number);
                        spin_unlock_irqrestore(&hostdata->lock, flags);
                }
                break;
@@ -1266,7 +1266,7 @@ wd33c93_intr(struct Scsi_Host *instance)
                        spin_unlock_irqrestore(&hostdata->lock, flags);
                        return;
                }
-               DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid))
+               DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number))
                    hostdata->connected = NULL;
                hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
                hostdata->state = S_UNCONNECTED;
@@ -1292,7 +1292,7 @@ wd33c93_intr(struct Scsi_Host *instance)
  */
 
                write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
-               DB(DB_INTR, printk("DISC-%ld", cmd->pid))
+               DB(DB_INTR, printk("DISC-%ld", cmd->serial_number))
                    if (cmd == NULL) {
                        printk(" - Already disconnected! ");
                        hostdata->state = S_UNCONNECTED;
@@ -1491,7 +1491,7 @@ wd33c93_intr(struct Scsi_Host *instance)
                } else
                        hostdata->state = S_CONNECTED;
 
-               DB(DB_INTR, printk("-%ld", cmd->pid))
+               DB(DB_INTR, printk("-%ld", cmd->serial_number))
                    spin_unlock_irqrestore(&hostdata->lock, flags);
                break;
 
@@ -1638,7 +1638,7 @@ wd33c93_abort(struct scsi_cmnd * cmd)
                        cmd->result = DID_ABORT << 16;
                        printk
                            ("scsi%d: Abort - removing command %ld from input_Q. ",
-                            instance->host_no, cmd->pid);
+                            instance->host_no, cmd->serial_number);
                        enable_irq(cmd->device->host->irq);
                        cmd->scsi_done(cmd);
                        return SUCCESS;
@@ -1663,7 +1663,7 @@ wd33c93_abort(struct scsi_cmnd * cmd)
                unsigned long timeout;
 
                printk("scsi%d: Aborting connected command %ld - ",
-                      instance->host_no, cmd->pid);
+                      instance->host_no, cmd->serial_number);
 
                printk("stopping DMA - ");
                if (hostdata->dma == D_DMA_RUNNING) {
@@ -1730,7 +1730,7 @@ wd33c93_abort(struct scsi_cmnd * cmd)
                if (tmp == cmd) {
                        printk
                            ("scsi%d: Abort - command %ld found on disconnected_Q - ",
-                            instance->host_no, cmd->pid);
+                            instance->host_no, cmd->serial_number);
                        printk("Abort SNOOZE. ");
                        enable_irq(cmd->device->host->irq);
                        return FAILED;
@@ -2184,7 +2184,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
                if (hd->connected) {
                        cmd = (struct scsi_cmnd *) hd->connected;
                        sprintf(tbuf, " %ld-%d:%d(%02x)",
-                               cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+                               cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
                        strcat(bp, tbuf);
                }
        }
@@ -2193,7 +2193,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
                cmd = (struct scsi_cmnd *) hd->input_Q;
                while (cmd) {
                        sprintf(tbuf, " %ld-%d:%d(%02x)",
-                               cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+                               cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
                        strcat(bp, tbuf);
                        cmd = (struct scsi_cmnd *) cmd->host_scribble;
                }
@@ -2203,7 +2203,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
                cmd = (struct scsi_cmnd *) hd->disconnected_Q;
                while (cmd) {
                        sprintf(tbuf, " %ld-%d:%d(%02x)",
-                               cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+                               cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
                        strcat(bp, tbuf);
                        cmd = (struct scsi_cmnd *) cmd->host_scribble;
                }
index c822debc2668ef687368443907c9ad2d1bca87f7..ac67394c737319582f808fe779c1e2ef8f7c134e 100644 (file)
@@ -69,7 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
 static int __devinit zorro7xx_init_one(struct zorro_dev *z,
                                       const struct zorro_device_id *ent)
 {
-       struct Scsi_Host * host = NULL;
+       struct Scsi_Host *host;
        struct NCR_700_Host_Parameters *hostdata;
        struct zorro_driver_data *zdd;
        unsigned long board, ioaddr;
@@ -89,14 +89,12 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z,
                return -EBUSY;
        }
 
-       hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-       if (hostdata == NULL) {
+       hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+       if (!hostdata) {
                printk(KERN_ERR "zorro7xx: Failed to allocate host data\n");
                goto out_release;
        }
 
-       memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
-
        /* Fill in the required pieces of hostdata */
        if (ioaddr > 0x01000000)
                hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
index 768b2c11a2311d6efa8237e7868c4c642d8998dc..e7d982a71548d819e08272a93eb9788defa14f48 100644 (file)
@@ -446,7 +446,8 @@ static void mts_data_done( struct urb* transfer )
        MTS_INT_INIT();
 
        if ( context->data_length != transfer->actual_length ) {
-               context->srb->resid = context->data_length - transfer->actual_length;
+               scsi_set_resid(context->srb, context->data_length -
+                              transfer->actual_length);
        } else if ( unlikely(status) ) {
                context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
        }
@@ -490,7 +491,8 @@ static void mts_command_done( struct urb *transfer )
                                           context->data_pipe,
                                           context->data,
                                           context->data_length,
-                                          context->srb->use_sg > 1 ? mts_do_sg : mts_data_done);
+                                          scsi_sg_count(context->srb) > 1 ?
+                                                  mts_do_sg : mts_data_done);
                } else {
                        mts_get_status(transfer);
                }
@@ -505,21 +507,23 @@ static void mts_do_sg (struct urb* transfer)
        int status = transfer->status;
        MTS_INT_INIT();
 
-       MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
+       MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,
+                                                 scsi_sg_count(context->srb));
 
        if (unlikely(status)) {
                 context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
                mts_transfer_cleanup(transfer);
         }
 
-       sg = context->srb->request_buffer;
+       sg = scsi_sglist(context->srb);
        context->fragment++;
        mts_int_submit_urb(transfer,
                           context->data_pipe,
                           page_address(sg[context->fragment].page) +
                           sg[context->fragment].offset,
                           sg[context->fragment].length,
-                          context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
+                          context->fragment + 1 == scsi_sg_count(context->srb) ?
+                          mts_data_done : mts_do_sg);
        return;
 }
 
@@ -547,20 +551,12 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc)
        desc->context.srb = srb;
        desc->context.fragment = 0;
 
-       if (!srb->use_sg) {
-               if ( !srb->request_bufflen ){
-                       desc->context.data = NULL;
-                       desc->context.data_length = 0;
-                       return;
-               } else {
-                       desc->context.data = srb->request_buffer;
-                       desc->context.data_length = srb->request_bufflen;
-                       MTS_DEBUG("length = %d or %d\n",
-                                 srb->request_bufflen, srb->bufflen);
-               }
+       if (!scsi_bufflen(srb)) {
+               desc->context.data = NULL;
+               desc->context.data_length = 0;
+               return;
        } else {
-               MTS_DEBUG("Using scatter/gather\n");
-               sg = srb->request_buffer;
+               sg = scsi_sglist(srb);
                desc->context.data = page_address(sg[0].page) + sg[0].offset;
                desc->context.data_length = sg[0].length;
        }
index 323293a3e61f08936ab16fcbc9820fdcc9056492..c646750ccc3076ddba7d6f9187c04a3d55da809c 100644 (file)
@@ -50,7 +50,7 @@
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_device.h>
 
 #include "usb.h"
@@ -580,25 +580,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
        /* Now, if we need to do the auto-sense, let's do it */
        if (need_auto_sense) {
                int temp_result;
-               void* old_request_buffer;
-               unsigned short old_sg;
-               unsigned old_request_bufflen;
-               unsigned char old_sc_data_direction;
-               unsigned char old_cmd_len;
-               unsigned char old_cmnd[MAX_COMMAND_SIZE];
-               int old_resid;
+               struct scsi_eh_save ses;
 
                US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
 
-               /* save the old command */
-               memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
-               old_cmd_len = srb->cmd_len;
-
-               /* set the command and the LUN */
-               memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
-               srb->cmnd[0] = REQUEST_SENSE;
-               srb->cmnd[1] = old_cmnd[1] & 0xE0;
-               srb->cmnd[4] = 18;
+               scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
 
                /* FIXME: we must do the protocol translation here */
                if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
@@ -606,36 +592,12 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                else
                        srb->cmd_len = 12;
 
-               /* set the transfer direction */
-               old_sc_data_direction = srb->sc_data_direction;
-               srb->sc_data_direction = DMA_FROM_DEVICE;
-
-               /* use the new buffer we have */
-               old_request_buffer = srb->request_buffer;
-               srb->request_buffer = us->sensebuf;
-
-               /* set the buffer length for transfer */
-               old_request_bufflen = srb->request_bufflen;
-               srb->request_bufflen = US_SENSE_SIZE;
-
-               /* set up for no scatter-gather use */
-               old_sg = srb->use_sg;
-               srb->use_sg = 0;
-
                /* issue the auto-sense command */
-               old_resid = srb->resid;
                srb->resid = 0;
                temp_result = us->transport(us->srb, us);
 
                /* let's clean up right away */
-               memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE);
-               srb->resid = old_resid;
-               srb->request_buffer = old_request_buffer;
-               srb->request_bufflen = old_request_bufflen;
-               srb->use_sg = old_sg;
-               srb->sc_data_direction = old_sc_data_direction;
-               srb->cmd_len = old_cmd_len;
-               memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
+               scsi_eh_restore_cmnd(srb, &ses);
 
                if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
                        US_DEBUGP("-- auto-sense aborted\n");
index 87439ad94685c639056377cf84762089ba590ef7..2aaf1c16ce981ed83e35caa1e16f7cef3beb5a3e 100644 (file)
 #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC    0x0108
 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
 
+#define PCI_VENDOR_ID_ATTO             0x117c
+
 #define PCI_VENDOR_ID_RICOH            0x1180
 #define PCI_DEVICE_ID_RICOH_RL5C465    0x0465
 #define PCI_DEVICE_ID_RICOH_RL5C466    0x0466
 #define PCI_DEVICE_ID_ARECA_1130       0x1130
 #define PCI_DEVICE_ID_ARECA_1160       0x1160
 #define PCI_DEVICE_ID_ARECA_1170       0x1170
+#define PCI_DEVICE_ID_ARECA_1200       0x1200
+#define PCI_DEVICE_ID_ARECA_1201       0x1201
+#define PCI_DEVICE_ID_ARECA_1202       0x1202
 #define PCI_DEVICE_ID_ARECA_1210       0x1210
 #define PCI_DEVICE_ID_ARECA_1220       0x1220
 #define PCI_DEVICE_ID_ARECA_1230       0x1230
index d143171896ae89d4d9fdff31744ad06e5698c663..ba615e4c1d7c324ee93e59c78c17f027c3fb3dd4 100644 (file)
@@ -59,7 +59,7 @@ extern void srp_target_free(struct srp_target *);
 extern struct iu_entry *srp_iu_get(struct srp_target *);
 extern void srp_iu_put(struct iu_entry *);
 
-extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64);
+extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64, u64);
 extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *,
                             srp_rdma_t, int, int);
 
index 53e170586c26c190a304c9a7c5f8100de1fd866a..65ab5145a09befcc23a78de1090676d7f8fdd42e 100644 (file)
@@ -33,20 +33,17 @@ struct scsi_cmnd {
        struct list_head list;  /* scsi_cmnd participates in queue lists */
        struct list_head eh_entry; /* entry for the host eh_cmd_q */
        int eh_eflags;          /* Used by error handlr */
-       void (*done) (struct scsi_cmnd *);      /* Mid-level done function */
 
        /*
         * A SCSI Command is assigned a nonzero serial_number before passed
         * to the driver's queue command function.  The serial_number is
         * cleared when scsi_done is entered indicating that the command
-        * has been completed.  It currently doesn't have much use other
-        * than printk's.  Some lldd's use this number for other purposes.
-        * It's almost certain that such usages are either incorrect or
-        * meaningless.  Please kill all usages other than printk's.  Also,
-        * as this number is always identical to ->pid, please convert
-        * printk's to use ->pid, so that we can kill this field.
+        * has been completed.  It is a bug for LLDDs to use this number
+        * for purposes other than printk (and even that is only useful
+        * for debugging).
         */
        unsigned long serial_number;
+
        /*
         * This is set to jiffies as it was when the command was first
         * allocated.  It is used to time how long the command has
@@ -116,7 +113,6 @@ struct scsi_cmnd {
        int result;             /* Status code from lower level driver */
 
        unsigned char tag;      /* SCSI-II queued command tag */
-       unsigned long pid;      /* Process ID, starts at 0. Unique per host. */
 };
 
 extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
@@ -124,7 +120,6 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t);
 extern void scsi_put_command(struct scsi_cmnd *);
 extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *,
                               struct device *);
-extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
 extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd);
 
index 5a43a4cd96c6f6ea9f11d9818fb4e4c5780046a5..e89844cc2cd359bf281574f45f942826b1af9056 100644 (file)
@@ -9,6 +9,8 @@ extern void __scsi_print_command(unsigned char *);
 extern void scsi_show_extd_sense(unsigned char, unsigned char);
 extern void scsi_show_sense_hdr(struct scsi_sense_hdr *);
 extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
+extern void scsi_cmd_print_sense_hdr(struct scsi_cmnd *, const char *,
+                                    struct scsi_sense_hdr *);
 extern void scsi_print_sense(char *, struct scsi_cmnd *);
 extern void __scsi_print_sense(const char *name,
                               const unsigned char *sense_buffer,
index 3465f31a21c4c5bb83980db6dcf6ab721ff0678e..1f5ca7f621165797ff559203e99b5a1deebe1624 100644 (file)
@@ -5,14 +5,17 @@
 
 struct module;
 struct scsi_cmnd;
+struct scsi_device;
+struct request;
+struct request_queue;
 
 
 struct scsi_driver {
        struct module           *owner;
        struct device_driver    gendrv;
 
-       int (*init_command)(struct scsi_cmnd *);
        void (*rescan)(struct device *);
+       int (*done)(struct scsi_cmnd *);
 };
 #define to_scsi_driver(drv) \
        container_of((drv), struct scsi_driver, gendrv)
@@ -25,4 +28,9 @@ extern int scsi_register_interface(struct class_interface *);
 #define scsi_unregister_interface(intf) \
        class_interface_unregister(intf)
 
+int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req);
+int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req);
+int scsi_prep_state_check(struct scsi_device *sdev, struct request *req);
+int scsi_prep_return(struct request_queue *q, struct request *req, int ret);
+
 #endif /* _SCSI_SCSI_DRIVER_H */
index c5c0f6762a013b0ebcd186e668e4a6f61a9f18cd..44224ba4dd9065cb89d93a10aa1c7daf95b2f6bd 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _SCSI_SCSI_EH_H
 #define _SCSI_SCSI_EH_H
 
-struct scsi_cmnd;
+#include <scsi/scsi_cmnd.h>
 struct scsi_device;
 struct Scsi_Host;
 
@@ -65,4 +65,25 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
 
 extern int scsi_reset_provider(struct scsi_device *, int);
 
+struct scsi_eh_save {
+       int result;
+       enum dma_data_direction data_direction;
+       unsigned char cmd_len;
+       unsigned char cmnd[MAX_COMMAND_SIZE];
+
+       void *buffer;
+       unsigned bufflen;
+       unsigned short use_sg;
+       int resid;
+
+       struct scatterlist sense_sgl;
+};
+
+extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
+               struct scsi_eh_save *ses, unsigned char *cmnd,
+               int cmnd_size, unsigned sense_bytes);
+
+extern void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd,
+               struct scsi_eh_save *ses);
+
 #endif /* _SCSI_SCSI_EH_H */
index 3b8a6a85c2f818e64435968136472fa7d2317bc1..7d210cd6c38d03a476b4f06fe563126d69db42c2 100644 (file)
@@ -32,6 +32,9 @@ struct blk_queue_tags;
 #define SG_NONE 0
 #define SG_ALL 0xff
 
+#define MODE_UNKNOWN 0x00
+#define MODE_INITIATOR 0x01
+#define MODE_TARGET 0x02
 
 #define DISABLE_CLUSTERING 0
 #define ENABLE_CLUSTERING 1
@@ -145,9 +148,6 @@ struct scsi_host_template {
        int (* transfer_response)(struct scsi_cmnd *,
                                  void (*done)(struct scsi_cmnd *));
 
-       /* Used as callback for the completion of task management request. */
-       int (* tsk_mgmt_response)(u64 mid, int result);
-
        /*
         * This is an error handling strategy routine.  You don't need to
         * define one of these if you don't want to - there is a default
@@ -407,6 +407,11 @@ struct scsi_host_template {
         */
        unsigned char present;
 
+       /*
+        * This specifies the mode that a LLD supports.
+        */
+       unsigned supported_mode:2;
+
        /*
         * true if this host adapter uses unchecked DMA onto an ISA bus.
         */
@@ -575,8 +580,9 @@ struct Scsi_Host {
         * Used to assign serial numbers to the cmds.
         * Protected by the host lock.
         */
-       unsigned long cmd_serial_number, cmd_pid; 
+       unsigned long cmd_serial_number;
        
+       unsigned active_mode:2;
        unsigned unchecked_isa_dma:1;
        unsigned use_clustering:1;
        unsigned use_blk_tcq:1;
index 4f4427937af277764cc74d119dc99f82f43cfa18..d0fefb96158f3dd52a007035113e8b80dc1bcf58 100644 (file)
@@ -11,9 +11,11 @@ struct scsi_lun;
 extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *);
 extern int scsi_tgt_alloc_queue(struct Scsi_Host *);
 extern void scsi_tgt_free_queue(struct Scsi_Host *);
-extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64);
-extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *,
-                                    void *);
+extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64);
+extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64,
+                                    struct scsi_lun *, void *);
 extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *,
                                               enum dma_data_direction, gfp_t);
 extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *);
+extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *);
+extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64);
index 4cf9dff29a2f69e792ef91395a120448dda8673c..f2ee7c238a4544d112e63c6c57a283dd7474c579 100644 (file)
 #define __SCSI_TARGET_IF_H
 
 /* user -> kernel */
-#define        TGT_UEVENT_CMD_RSP      0x0001
-#define        TGT_UEVENT_TSK_MGMT_RSP 0x0002
+#define        TGT_UEVENT_CMD_RSP              0x0001
+#define        TGT_UEVENT_IT_NEXUS_RSP         0x0002
+#define        TGT_UEVENT_TSK_MGMT_RSP         0x0003
 
 /* kernel -> user */
-#define        TGT_KEVENT_CMD_REQ      0x1001
-#define        TGT_KEVENT_CMD_DONE     0x1002
-#define        TGT_KEVENT_TSK_MGMT_REQ 0x1003
+#define        TGT_KEVENT_CMD_REQ              0x1001
+#define        TGT_KEVENT_CMD_DONE             0x1002
+#define        TGT_KEVENT_IT_NEXUS_REQ         0x1003
+#define        TGT_KEVENT_TSK_MGMT_REQ         0x1004
 
 struct tgt_event_hdr {
        uint16_t version;
@@ -46,6 +48,7 @@ struct tgt_event {
                struct {
                        int host_no;
                        int result;
+                       aligned_u64 itn_id;
                        aligned_u64 tag;
                        aligned_u64 uaddr;
                        aligned_u64 sense_uaddr;
@@ -55,15 +58,22 @@ struct tgt_event {
                } cmd_rsp;
                struct {
                        int host_no;
-                       aligned_u64 mid;
                        int result;
+                       aligned_u64 itn_id;
+                       aligned_u64 mid;
                } tsk_mgmt_rsp;
-
+               struct {
+                       __s32 host_no;
+                       __s32 result;
+                       aligned_u64 itn_id;
+                       __u32 function;
+               } it_nexus_rsp;
 
                /* kernel -> user */
                struct {
                        int host_no;
                        uint32_t data_len;
+                       aligned_u64 itn_id;
                        uint8_t scb[16];
                        uint8_t lun[8];
                        int attribute;
@@ -71,16 +81,25 @@ struct tgt_event {
                } cmd_req;
                struct {
                        int host_no;
-                       aligned_u64 tag;
                        int result;
+                       aligned_u64 itn_id;
+                       aligned_u64 tag;
                } cmd_done;
                struct {
                        int host_no;
                        int function;
+                       aligned_u64 itn_id;
                        aligned_u64 tag;
                        uint8_t lun[8];
                        aligned_u64 mid;
                } tsk_mgmt_req;
+               struct {
+                       __s32 host_no;
+                       __u32 function;
+                       aligned_u64 itn_id;
+                       __u32 max_cmds;
+                       __u8 initiator_id[16];
+               } it_nexus_req;
        } p;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
index 3c18baa65a729cd1578ab45b281ed1d5ba2d01dd..0dfef752f0e27c7c9009a2dbe378522322d453a4 100644 (file)
@@ -65,6 +65,18 @@ struct scsi_transport_template {
         * EH_NOT_HANDLED       Begin normal error recovery
         */
        enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
+       /*
+        * Used as callback for the completion of i_t_nexus request
+        * for target drivers.
+        */
+       int (* it_nexus_response)(struct Scsi_Host *, u64, int);
+
+       /*
+        * Used as callback for the completion of task management
+        * request for target drivers.
+        */
+       int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
 };
 
 #define transport_class_to_shost(tc) \
index a0d80bcaa93d489c909a4f67f3142dbdbd040ef4..e466d886e19283621c2e6af4f6087ce7eafa2d1e 100644 (file)
@@ -589,6 +589,10 @@ struct fc_function_template {
        int     (*vport_disable)(struct fc_vport *, bool);
        int     (*vport_delete)(struct fc_vport *);
 
+       /* target-mode drivers' functions */
+       int     (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
+       int     (* it_nexus_response)(struct Scsi_Host *, u64, int);
+
        /* allocation lengths for host-specific data */
        u32                             dd_fcrport_size;
        u32                             dd_fcvport_size;
@@ -632,6 +636,8 @@ struct fc_function_template {
        unsigned long   show_host_fabric_name:1;
        unsigned long   show_host_symbolic_name:1;
        unsigned long   show_host_system_hostname:1;
+
+       unsigned long   disable_target_scan:1;
 };
 
 
index 706c0cd36c14ffcfc69339ac8dc57544470d5928..7ff6199cbd55bef57c55b58b8c5a58f20a5d115a 100644 (file)
@@ -24,6 +24,8 @@
 #define SCSI_TRANSPORT_ISCSI_H
 
 #include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 #include <scsi/iscsi_if.h>
 
 struct scsi_transport_template;
diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h
new file mode 100644 (file)
index 0000000..9c60ca1
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef SCSI_TRANSPORT_SRP_H
+#define SCSI_TRANSPORT_SRP_H
+
+#include <linux/transport_class.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+#define SRP_RPORT_ROLE_INITIATOR 0
+#define SRP_RPORT_ROLE_TARGET 1
+
+struct srp_rport_identifiers {
+       u8 port_id[16];
+       u8 roles;
+};
+
+struct srp_rport {
+       struct device dev;
+
+       u8 port_id[16];
+       u8 roles;
+};
+
+struct srp_function_template {
+       /* for target drivers */
+       int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
+       int (* it_nexus_response)(struct Scsi_Host *, u64, int);
+};
+
+extern struct scsi_transport_template *
+srp_attach_transport(struct srp_function_template *);
+extern void srp_release_transport(struct scsi_transport_template *);
+
+extern struct srp_rport *srp_rport_add(struct Scsi_Host *,
+                                      struct srp_rport_identifiers *);
+extern void srp_rport_del(struct srp_rport *);
+
+extern void srp_remove_host(struct Scsi_Host *);
+
+#endif
index ce02ad1f518569cedefdb3f76fff5d8b055c0dba..f7513313ef0d5d5bdd85194dfb6771ac294cc22d 100644 (file)
@@ -47,20 +47,6 @@ struct scsi_disk {
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
 
-static int  sd_revalidate_disk(struct gendisk *disk);
-static void sd_rw_intr(struct scsi_cmnd * SCpnt);
-static int  sd_probe(struct device *);
-static int  sd_remove(struct device *);
-static void sd_shutdown(struct device *dev);
-static int sd_suspend(struct device *dev, pm_message_t state);
-static int sd_resume(struct device *dev);
-static void sd_rescan(struct device *);
-static int  sd_init_command(struct scsi_cmnd *);
-static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
-static void scsi_disk_release(struct class_device *cdev);
-static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
-static void sd_print_result(struct scsi_disk *, int);
-
 #define sd_printk(prefix, sdsk, fmt, a...)                             \
         (sdsk)->disk ?                                                 \
        sdev_printk(prefix, (sdsk)->device, "[%s] " fmt,                \