浏览代码

Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* 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
  ...
Linus Torvalds 18 年之前
父节点
当前提交
df3d80f5a5
共有 100 个文件被更改,包括 16024 次插入20061 次删除
  1. 31 3
      Documentation/scsi/00-INDEX
  2. 16 1
      Documentation/scsi/ChangeLog.arcmsr
  3. 6 2
      Documentation/scsi/aacraid.txt
  4. 243 0
      Documentation/scsi/advansys.txt
  5. 12 1
      MAINTAINERS
  6. 7 2
      arch/ia64/hp/sim/simscsi.c
  7. 15 26
      drivers/fc4/fc.c
  8. 1 0
      drivers/infiniband/ulp/srp/Kconfig
  9. 28 0
      drivers/infiniband/ulp/srp/ib_srp.c
  10. 15 11
      drivers/message/fusion/Kconfig
  11. 1 1
      drivers/message/fusion/lsi/mpi.h
  12. 1 1
      drivers/message/fusion/lsi/mpi_cnfg.h
  13. 1 1
      drivers/message/fusion/lsi/mpi_fc.h
  14. 1 1
      drivers/message/fusion/lsi/mpi_history.txt
  15. 1 1
      drivers/message/fusion/lsi/mpi_init.h
  16. 1 1
      drivers/message/fusion/lsi/mpi_ioc.h
  17. 1 1
      drivers/message/fusion/lsi/mpi_lan.h
  18. 1 1
      drivers/message/fusion/lsi/mpi_log_fc.h
  19. 1 1
      drivers/message/fusion/lsi/mpi_log_sas.h
  20. 1 1
      drivers/message/fusion/lsi/mpi_raid.h
  21. 1 1
      drivers/message/fusion/lsi/mpi_sas.h
  22. 1 1
      drivers/message/fusion/lsi/mpi_targ.h
  23. 1 1
      drivers/message/fusion/lsi/mpi_tool.h
  24. 1 1
      drivers/message/fusion/lsi/mpi_type.h
  25. 344 258
      drivers/message/fusion/mptbase.c
  26. 56 24
      drivers/message/fusion/mptbase.h
  27. 182 182
      drivers/message/fusion/mptctl.c
  28. 2 2
      drivers/message/fusion/mptctl.h
  29. 108 41
      drivers/message/fusion/mptfc.c
  30. 11 21
      drivers/message/fusion/mptlan.c
  31. 4 4
      drivers/message/fusion/mptlan.h
  32. 199 269
      drivers/message/fusion/mptsas.c
  33. 158 0
      drivers/message/fusion/mptsas.h
  34. 355 288
      drivers/message/fusion/mptscsih.c
  35. 2 2
      drivers/message/fusion/mptscsih.h
  36. 114 97
      drivers/message/fusion/mptspi.c
  37. 10 3
      drivers/s390/scsi/zfcp_aux.c
  38. 1 7
      drivers/s390/scsi/zfcp_ccw.c
  39. 23 23
      drivers/s390/scsi/zfcp_def.h
  40. 70 70
      drivers/s390/scsi/zfcp_erp.c
  41. 20 18
      drivers/s390/scsi/zfcp_ext.h
  42. 197 96
      drivers/s390/scsi/zfcp_fsf.c
  43. 15 15
      drivers/s390/scsi/zfcp_fsf.h
  44. 3 4
      drivers/s390/scsi/zfcp_qdio.c
  45. 23 24
      drivers/s390/scsi/zfcp_scsi.c
  46. 2 2
      drivers/s390/scsi/zfcp_sysfs_unit.c
  47. 41 7
      drivers/scsi/Kconfig
  48. 1 0
      drivers/scsi/Makefile
  49. 13 18
      drivers/scsi/NCR5380.c
  50. 7 0
      drivers/scsi/NCR5380.h
  51. 1 1
      drivers/scsi/NCR53C9x.c
  52. 2 3
      drivers/scsi/NCR_D700.c
  53. 3 4
      drivers/scsi/a4000t.c
  54. 4 4
      drivers/scsi/aacraid/aachba.c
  55. 1 1
      drivers/scsi/aacraid/aacraid.h
  56. 3 2
      drivers/scsi/aacraid/commsup.c
  57. 10263 14951
      drivers/scsi/advansys.c
  58. 2 2
      drivers/scsi/aha152x.c
  59. 3 5
      drivers/scsi/aic7xxx_old.c
  60. 0 12
      drivers/scsi/aic94xx/aic94xx_hwi.h
  61. 18 24
      drivers/scsi/aic94xx/aic94xx_init.c
  62. 1 1
      drivers/scsi/aic94xx/aic94xx_task.c
  63. 142 50
      drivers/scsi/arcmsr/arcmsr.h
  64. 33 40
      drivers/scsi/arcmsr/arcmsr_attr.c
  65. 1369 893
      drivers/scsi/arcmsr/arcmsr_hba.c
  66. 10 17
      drivers/scsi/atari_NCR5380.c
  67. 3 4
      drivers/scsi/bvme6000_scsi.c
  68. 15 1
      drivers/scsi/constants.c
  69. 55 55
      drivers/scsi/dc395x.c
  70. 12 17
      drivers/scsi/dpt_i2o.c
  71. 7 9
      drivers/scsi/dtc.c
  72. 22 22
      drivers/scsi/eata.c
  73. 45 55
      drivers/scsi/eata_pio.c
  74. 5 5
      drivers/scsi/esp_scsi.c
  75. 4 1
      drivers/scsi/fdomain.c
  76. 1 1
      drivers/scsi/g_NCR5380.c
  77. 1254 1679
      drivers/scsi/gdth.c
  78. 21 21
      drivers/scsi/gdth.h
  79. 0 31
      drivers/scsi/gdth_kcompat.h
  80. 43 90
      drivers/scsi/gdth_proc.c
  81. 10 10
      drivers/scsi/gdth_proc.h
  82. 1 0
      drivers/scsi/hosts.c
  83. 48 15
      drivers/scsi/hptiop.c
  84. 10 219
      drivers/scsi/hptiop.h
  85. 1 7
      drivers/scsi/ibmmca.c
  86. 0 2
      drivers/scsi/ibmvscsi/Makefile
  87. 61 20
      drivers/scsi/ibmvscsi/ibmvscsi.c
  88. 18 14
      drivers/scsi/ibmvscsi/ibmvscsi.h
  89. 54 7
      drivers/scsi/ibmvscsi/ibmvstgt.c
  90. 23 14
      drivers/scsi/ibmvscsi/iseries_vscsi.c
  91. 61 52
      drivers/scsi/ibmvscsi/rpa_vscsi.c
  92. 14 126
      drivers/scsi/ide-scsi.c
  93. 0 4
      drivers/scsi/imm.c
  94. 15 15
      drivers/scsi/in2000.c
  95. 5 4
      drivers/scsi/ips.c
  96. 6 5
      drivers/scsi/ips.h
  97. 3 2
      drivers/scsi/libsrp.c
  98. 1 4
      drivers/scsi/lpfc/lpfc_debugfs.c
  99. 1 3
      drivers/scsi/lpfc/lpfc_init.c
  100. 1 2
      drivers/scsi/lpfc/lpfc_scsi.c

+ 31 - 3
Documentation/scsi/00-INDEX

@@ -2,14 +2,20 @@
 	- this file
 	- this file
 53c700.txt
 53c700.txt
 	- info on driver for 53c700 based adapters
 	- info on driver for 53c700 based adapters
-AM53C974.txt
-	- info on driver for AM53c974 based adapters
 BusLogic.txt
 BusLogic.txt
 	- info on driver for adapters with BusLogic chips
 	- info on driver for adapters with BusLogic chips
-ChangeLog
+ChangeLog.1992-1997
 	- Changes to scsi files, if not listed elsewhere
 	- Changes to scsi files, if not listed elsewhere
+ChangeLog.arcmsr
+	- Changes to driver for ARECA's SATA RAID controller cards
 ChangeLog.ips
 ChangeLog.ips
 	- IBM ServeRAID driver Changelog
 	- 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
 ChangeLog.ncr53c8xx
 	- Changes to ncr53c8xx driver
 	- Changes to ncr53c8xx driver
 ChangeLog.sym53c8xx
 ChangeLog.sym53c8xx
@@ -20,26 +26,44 @@ FlashPoint.txt
 	- info on driver for BusLogic FlashPoint adapters
 	- info on driver for BusLogic FlashPoint adapters
 LICENSE.FlashPoint
 LICENSE.FlashPoint
 	- Licence of the Flashpoint driver
 	- Licence of the Flashpoint driver
+LICENSE.qla2xxx
+	- License for QLogic Linux Fibre Channel HBA Driver firmware.
 Mylex.txt
 Mylex.txt
 	- info on driver for Mylex adapters
 	- info on driver for Mylex adapters
 NinjaSCSI.txt
 NinjaSCSI.txt
 	- info on WorkBiT NinjaSCSI-32/32Bi driver
 	- info on WorkBiT NinjaSCSI-32/32Bi driver
+aacraid.txt
+	- Driver supporting Adaptec RAID controllers
 aha152x.txt
 aha152x.txt
 	- info on driver for Adaptec AHA152x based adapters
 	- info on driver for Adaptec AHA152x based adapters
+aic79xx.txt
+	- Adaptec Ultra320 SCSI host adapters
 aic7xxx.txt
 aic7xxx.txt
 	- info on driver for Adaptec controllers
 	- info on driver for Adaptec controllers
 aic7xxx_old.txt
 aic7xxx_old.txt
 	- info on driver for Adaptec controllers, old generation
 	- 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
 dpti.txt
 	- info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters
 	- info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters
 dtc3x80.txt
 dtc3x80.txt
 	- info on driver for DTC 2x80 based adapters
 	- info on driver for DTC 2x80 based adapters
 g_NCR5380.txt
 g_NCR5380.txt
 	- info on driver for NCR5380 and NCR53c400 based adapters
 	- info on driver for NCR5380 and NCR53c400 based adapters
+hptiop.txt
+	- HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
 ibmmca.txt
 ibmmca.txt
 	- info on driver for IBM adapters with MCA bus
 	- info on driver for IBM adapters with MCA bus
 in2000.txt
 in2000.txt
 	- info on in2000 driver
 	- 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
 ncr53c7xx.txt
 	- info on driver for NCR53c7xx based adapters
 	- info on driver for NCR53c7xx based adapters
 ncr53c8xx.txt
 ncr53c8xx.txt
@@ -50,6 +74,8 @@ ppa.txt
 	- info on driver for IOmega zip drive
 	- info on driver for IOmega zip drive
 qlogicfas.txt
 qlogicfas.txt
 	- info on driver for QLogic FASxxx based adapters
 	- info on driver for QLogic FASxxx based adapters
+scsi-changer.txt
+	- README for the SCSI media changer driver
 scsi-generic.txt
 scsi-generic.txt
 	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
 	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
 scsi.txt
 scsi.txt
@@ -58,6 +84,8 @@ scsi_mid_low_api.txt
 	- info on API between SCSI layer and low level drivers
 	- info on API between SCSI layer and low level drivers
 scsi_eh.txt
 scsi_eh.txt
 	- info on SCSI midlayer error handling infrastructure
 	- info on SCSI midlayer error handling infrastructure
+scsi_fc_transport.txt
+	- SCSI Fiber Channel Tansport
 st.txt
 st.txt
 	- info on scsi tape driver
 	- info on scsi tape driver
 sym53c500_cs.txt
 sym53c500_cs.txt

+ 16 - 1
Documentation/scsi/ChangeLog.arcmsr

@@ -53,4 +53,19 @@
 **						for linux standard list
 **						for linux standard list
 **						enable usage of pci message signal interrupt
 **						enable usage of pci message signal interrupt
 **						follow Randy.Danlup kindness suggestion cleanup this code
 **						follow Randy.Danlup kindness suggestion cleanup this code
-**************************************************************************
+** 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
+**************************************************************************

+ 6 - 2
Documentation/scsi/aacraid.txt

@@ -38,10 +38,8 @@ Supported Cards/Chipsets
 	9005:0286:9005:02ac	Adaptec	1800 (Typhoon44)
 	9005:0286:9005:02ac	Adaptec	1800 (Typhoon44)
 	9005:0285:9005:02b5	Adaptec	5445 (Voodoo44)
 	9005:0285:9005:02b5	Adaptec	5445 (Voodoo44)
 	9005:0285:15d9:02b5	SMC	AOC-USAS-S4i
 	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:9005:02b6	Adaptec	5805 (Voodoo80)
 	9005:0285:15d9:02b6	SMC	AOC-USAS-S8i
 	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:02b7	Adaptec	5085 (Voodoo08)
 	9005:0285:9005:02bb	Adaptec	3405 (Marauder40LP)
 	9005:0285:9005:02bb	Adaptec	3405 (Marauder40LP)
 	9005:0285:9005:02bc	Adaptec	3805 (Marauder80LP)
 	9005:0285:9005:02bc	Adaptec	3805 (Marauder80LP)
@@ -50,9 +48,14 @@ Supported Cards/Chipsets
 	9005:0285:9005:02be	Adaptec	31605 (Marauder160)
 	9005:0285:9005:02be	Adaptec	31605 (Marauder160)
 	9005:0285:9005:02c3	Adaptec	51205 (Voodoo120)
 	9005:0285:9005:02c3	Adaptec	51205 (Voodoo120)
 	9005:0285:9005:02c4	Adaptec	51605 (Voodoo160)
 	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:02ce	Adaptec	51245 (Voodoo124)
 	9005:0285:9005:02cf	Adaptec	51645 (Voodoo164)
 	9005:0285:9005:02cf	Adaptec	51645 (Voodoo164)
 	9005:0285:9005:02d0	Adaptec	52445 (Voodoo244)
 	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)
 	1011:0046:9005:0364	Adaptec	5400S (Mustang)
 	9005:0287:9005:0800	Adaptec	Themisto (Jupiter)
 	9005:0287:9005:0800	Adaptec	Themisto (Jupiter)
 	9005:0200:9005:0200	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:7aac	SUN	STK RAID REM (Voodoo44 Coyote)
 	9005:0285:108e:0286	SUN	STK RAID INT (Cougar)
 	9005:0285:108e:0286	SUN	STK RAID INT (Cougar)
 	9005:0285:108e:0287	SUN	STK RAID EXT (Prometheus)
 	9005:0285:108e:0287	SUN	STK RAID EXT (Prometheus)
+	9005:0285:108e:7aae	SUN	STK RAID EM (Narvi)
 
 
 People
 People
 -------------------------
 -------------------------

+ 243 - 0
Documentation/scsi/advansys.txt

@@ -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.

+ 12 - 1
MAINTAINERS

@@ -297,6 +297,12 @@ P:	Colin Leroy
 M:	colin@colino.net
 M:	colin@colino.net
 S:	Maintained
 S:	Maintained
 
 
+ADVANSYS SCSI DRIVER
+P:	Matthew Wilcox
+M:	matthew@wil.cx
+L:	linux-scsi@vger.kernel.org
+S:	Maintained
+
 AEDSP16 DRIVER
 AEDSP16 DRIVER
 P:	Riccardo Facchetti
 P:	Riccardo Facchetti
 M:	fizban@tin.it
 M:	fizban@tin.it
@@ -1889,6 +1895,11 @@ M:	Gadi Oxman <gadio@netvision.net.il>
 L:	linux-kernel@vger.kernel.org
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 S:	Maintained
 
 
+IDE-SCSI DRIVER
+L:	linux-ide@vger.kernel.org
+L:	linux-scsi@vger.kernel.org
+S:	Orphan
+
 IEEE 1394 SUBSYSTEM
 IEEE 1394 SUBSYSTEM
 P:	Ben Collins
 P:	Ben Collins
 M:	ben.collins@ubuntu.com
 M:	ben.collins@ubuntu.com
@@ -2404,7 +2415,7 @@ LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
 P:	Eric Moore
 P:	Eric Moore
 M:	Eric.Moore@lsi.com
 M:	Eric.Moore@lsi.com
 M:	support@lsi.com
 M:	support@lsi.com
-L:	mpt_linux_developer@lsi.com
+L:	DL-MPTFusionLinux@lsi.com
 L:	linux-scsi@vger.kernel.org
 L:	linux-scsi@vger.kernel.org
 W:	http://www.lsilogic.com/support
 W:	http://www.lsilogic.com/support
 S:	Supported
 S:	Supported

+ 7 - 2
arch/ia64/hp/sim/simscsi.c

@@ -372,8 +372,13 @@ simscsi_init(void)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	error = scsi_add_host(host, NULL);
 	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;
 	return error;
 }
 }
 
 

+ 15 - 26
drivers/fc4/fc.c

@@ -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);
 			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;
 		break;
 	default:
 	default:
 		host_status=DID_ERROR; /* FIXME */
 		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;
 				fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
 		} else
 		} else
 			fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
 			fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
-		if (!SCpnt->request_bufflen && !SCpnt->use_sg) {
+
+		if (!scsi_bufflen(SCpnt)) {
 			cmd->fcp_cntl = fcp_cntl;
 			cmd->fcp_cntl = fcp_cntl;
 			fcmd->data = (dma_addr_t)NULL;
 			fcmd->data = (dma_addr_t)NULL;
 		} else {
 		} else {
+			struct scatterlist *sg;
+			int nents;
+
 			switch (SCpnt->cmnd[0]) {
 			switch (SCpnt->cmnd[0]) {
 			case WRITE_6:
 			case WRITE_6:
 			case WRITE_10:
 			case WRITE_10:
@@ -805,22 +804,12 @@ static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt,
 			default:
 			default:
 				cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break;
 				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);
 		memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
 		memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
 		memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);

+ 1 - 0
drivers/infiniband/ulp/srp/Kconfig

@@ -1,6 +1,7 @@
 config INFINIBAND_SRP
 config INFINIBAND_SRP
 	tristate "InfiniBand SCSI RDMA Protocol"
 	tristate "InfiniBand SCSI RDMA Protocol"
 	depends on SCSI
 	depends on SCSI
+	select SCSI_SRP_ATTRS
 	---help---
 	---help---
 	  Support for the SCSI RDMA Protocol over InfiniBand.  This
 	  Support for the SCSI RDMA Protocol over InfiniBand.  This
 	  allows you to access storage devices that speak SRP over
 	  allows you to access storage devices that speak SRP over

+ 28 - 0
drivers/infiniband/ulp/srp/ib_srp.c

@@ -47,6 +47,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/srp.h>
 #include <scsi/srp.h>
+#include <scsi/scsi_transport_srp.h>
 
 
 #include <rdma/ib_cache.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 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 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 = {
 static struct ib_client srp_client = {
 	.name   = "srp",
 	.name   = "srp",
 	.add    = srp_add_one,
 	.add    = srp_add_one,
@@ -420,6 +423,7 @@ static void srp_remove_work(struct work_struct *work)
 	list_del(&target->list);
 	list_del(&target->list);
 	spin_unlock(&target->srp_host->target_lock);
 	spin_unlock(&target->srp_host->target_lock);
 
 
+	srp_remove_host(target->scsi_host);
 	scsi_remove_host(target->scsi_host);
 	scsi_remove_host(target->scsi_host);
 	ib_destroy_cm_id(target->cm_id);
 	ib_destroy_cm_id(target->cm_id);
 	srp_free_target_ib(target);
 	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)
 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",
 	sprintf(target->target_name, "SRP.T10:%016llX",
 		 (unsigned long long) be64_to_cpu(target->id_ext));
 		 (unsigned long long) be64_to_cpu(target->id_ext));
 
 
 	if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
 	if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
 		return -ENODEV;
 		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);
 	spin_lock(&host->target_lock);
 	list_add_tail(&target->list, &host->target_list);
 	list_add_tail(&target->list, &host->target_list);
 	spin_unlock(&host->target_lock);
 	spin_unlock(&host->target_lock);
@@ -1775,6 +1791,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
 	if (!target_host)
 	if (!target_host)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	target_host->transportt = ib_srp_transport_template;
 	target_host->max_lun     = SRP_MAX_LUN;
 	target_host->max_lun     = SRP_MAX_LUN;
 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
 	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);
 	kfree(srp_dev);
 }
 }
 
 
+static struct srp_function_template ib_srp_transport_functions = {
+};
+
 static int __init srp_init_module(void)
 static int __init srp_init_module(void)
 {
 {
 	int ret;
 	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_template.sg_tablesize = srp_sg_tablesize;
 	srp_max_iu_len = (sizeof (struct srp_cmd) +
 	srp_max_iu_len = (sizeof (struct srp_cmd) +
 			  sizeof (struct srp_indirect_buf) +
 			  sizeof (struct srp_indirect_buf) +
@@ -2066,6 +2091,7 @@ static int __init srp_init_module(void)
 	ret = class_register(&srp_class);
 	ret = class_register(&srp_class);
 	if (ret) {
 	if (ret) {
 		printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
 		printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
+		srp_release_transport(ib_srp_transport_template);
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -2074,6 +2100,7 @@ static int __init srp_init_module(void)
 	ret = ib_register_client(&srp_client);
 	ret = ib_register_client(&srp_client);
 	if (ret) {
 	if (ret) {
 		printk(KERN_ERR PFX "couldn't register IB client\n");
 		printk(KERN_ERR PFX "couldn't register IB client\n");
+		srp_release_transport(ib_srp_transport_template);
 		ib_sa_unregister_client(&srp_sa_client);
 		ib_sa_unregister_client(&srp_sa_client);
 		class_unregister(&srp_class);
 		class_unregister(&srp_class);
 		return ret;
 		return ret;
@@ -2087,6 +2114,7 @@ static void __exit srp_cleanup_module(void)
 	ib_unregister_client(&srp_client);
 	ib_unregister_client(&srp_client);
 	ib_sa_unregister_client(&srp_sa_client);
 	ib_sa_unregister_client(&srp_sa_client);
 	class_unregister(&srp_class);
 	class_unregister(&srp_class);
+	srp_release_transport(ib_srp_transport_template);
 }
 }
 
 
 module_init(srp_init_module);
 module_init(srp_init_module);

+ 15 - 11
drivers/message/fusion/Kconfig

@@ -1,15 +1,19 @@
 
 
-menu "Fusion MPT device support"
+menuconfig FUSION
+	bool "Fusion MPT device support"
 	depends on PCI
 	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
 config FUSION_SPI
 	tristate "Fusion MPT ScsiHost drivers for SPI"
 	tristate "Fusion MPT ScsiHost drivers for SPI"
 	depends on PCI && SCSI
 	depends on PCI && SCSI
-	select FUSION
 	select SCSI_SPI_ATTRS
 	select SCSI_SPI_ATTRS
 	---help---
 	---help---
 	  SCSI HOST support for a parallel SCSI host adapters.
 	  SCSI HOST support for a parallel SCSI host adapters.
@@ -20,11 +24,11 @@ config FUSION_SPI
 	  LSI53C1020A
 	  LSI53C1020A
 	  LSI53C1030
 	  LSI53C1030
 	  LSI53C1035
 	  LSI53C1035
+	  ATTO UL4D
 
 
 config FUSION_FC
 config FUSION_FC
 	tristate "Fusion MPT ScsiHost drivers for FC"
 	tristate "Fusion MPT ScsiHost drivers for FC"
 	depends on PCI && SCSI
 	depends on PCI && SCSI
-	select FUSION
 	select SCSI_FC_ATTRS
 	select SCSI_FC_ATTRS
 	---help---
 	---help---
 	  SCSI HOST support for a Fiber Channel host adapters.
 	  SCSI HOST support for a Fiber Channel host adapters.
@@ -37,12 +41,13 @@ config FUSION_FC
 	  LSIFC929
 	  LSIFC929
 	  LSIFC929X
 	  LSIFC929X
 	  LSIFC929XL
 	  LSIFC929XL
+	  LSIFC949X
+	  LSIFC949E
 	  Brocade FC 410/420
 	  Brocade FC 410/420
 
 
 config FUSION_SAS
 config FUSION_SAS
 	tristate "Fusion MPT ScsiHost drivers for SAS"
 	tristate "Fusion MPT ScsiHost drivers for SAS"
 	depends on PCI && SCSI
 	depends on PCI && SCSI
- 	select FUSION
 	select SCSI_SAS_ATTRS
 	select SCSI_SAS_ATTRS
 	---help---
 	---help---
 	  SCSI HOST support for a SAS host adapters.
 	  SCSI HOST support for a SAS host adapters.
@@ -53,10 +58,10 @@ config FUSION_SAS
 	  LSISAS1068
 	  LSISAS1068
 	  LSISAS1064E
 	  LSISAS1064E
 	  LSISAS1068E
 	  LSISAS1068E
+	  LSISAS1078
 
 
 config FUSION_MAX_SGE
 config FUSION_MAX_SGE
 	int "Maximum number of scatter gather entries (16 - 128)"
 	int "Maximum number of scatter gather entries (16 - 128)"
-	depends on FUSION
 	default "128"
 	default "128"
 	range 16 128
 	range 16 128
 	help
 	help
@@ -104,7 +109,6 @@ config FUSION_LAN
 
 
 config FUSION_LOGGING
 config FUSION_LOGGING
 	bool "Fusion MPT logging facility"
 	bool "Fusion MPT logging facility"
-	depends on FUSION
 	---help---
 	---help---
 	  This turns on a logging facility that can be used to debug a number
 	  This turns on a logging facility that can be used to debug a number
 	  of Fusion MPT related problems.
 	  of Fusion MPT related problems.
@@ -113,7 +117,7 @@ config FUSION_LOGGING
 
 
 	  echo [level] > /sys/class/scsi_host/host#/debug_level
 	  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
 	  file:drivers/message/fusion/mptdebug.h
 
 
-endmenu
+endif # FUSION

+ 1 - 1
drivers/message/fusion/lsi/mpi.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi.h
  *           Name:  mpi.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_cnfg.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_cnfg.h
  *           Name:  mpi_cnfg.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_fc.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_fc.h
  *           Name:  mpi_fc.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_history.txt

@@ -3,7 +3,7 @@
  MPI Header File Change History
  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
  Header Set Release Version:    01.05.16

+ 1 - 1
drivers/message/fusion/lsi/mpi_init.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_init.h
  *           Name:  mpi_init.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_ioc.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2007 LSI Logic Corporation.
+ *  Copyright (c) 2000-2007 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_ioc.h
  *           Name:  mpi_ioc.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_lan.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_lan.h
  *           Name:  mpi_lan.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_log_fc.h

@@ -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
  *  NAME:           fc_log.h
  *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
  *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips

+ 1 - 1
drivers/message/fusion/lsi/mpi_log_sas.h

@@ -1,6 +1,6 @@
 /***************************************************************************
 /***************************************************************************
  *                                                                         *
  *                                                                         *
- *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
+ *  Copyright 2003 LSI Corporation.  All rights reserved.            *
  *                                                                         *
  *                                                                         *
  * Description                                                             *
  * Description                                                             *
  * ------------                                                            *
  * ------------                                                            *

+ 1 - 1
drivers/message/fusion/lsi/mpi_raid.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2001-2007 LSI Logic Corporation.
+ *  Copyright (c) 2001-2007 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_raid.h
  *           Name:  mpi_raid.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_sas.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2004-2006 LSI Logic Corporation.
+ *  Copyright (c) 2004-2006 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_sas.h
  *           Name:  mpi_sas.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_targ.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_targ.h
  *           Name:  mpi_targ.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_tool.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2001-2005 LSI Logic Corporation.
+ *  Copyright (c) 2001-2005 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_tool.h
  *           Name:  mpi_tool.h

+ 1 - 1
drivers/message/fusion/lsi/mpi_type.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (c) 2000-2004 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Corporation.
  *
  *
  *
  *
  *           Name:  mpi_type.h
  *           Name:  mpi_type.h

+ 344 - 258
drivers/message/fusion/mptbase.c

@@ -2,10 +2,10 @@
  *  linux/drivers/message/fusion/mptbase.c
  *  linux/drivers/message/fusion/mptbase.c
  *      This is the Fusion MPT base driver which supports multiple
  *      This is the Fusion MPT base driver which supports multiple
  *      (SCSI + LAN) specialized protocol drivers.
  *      (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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */
@@ -102,8 +102,6 @@ static int mfcounter = 0;
 /*
 /*
  *  Public data...
  *  Public data...
  */
  */
-int mpt_lan_index = -1;
-int mpt_stm_index = -1;
 
 
 struct proc_dir_entry *mpt_proc_root_dir;
 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 MPT_RESETHANDLER		 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 static struct mpt_pci_driver 	*MptDeviceDriverHandlers[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);
 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...
  *  Forward protos...
@@ -235,6 +236,23 @@ static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
 	return 0;
 	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...
  *  Process turbo (context) reply...
  */
  */
@@ -243,8 +261,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
 {
 {
 	MPT_FRAME_HDR *mf = NULL;
 	MPT_FRAME_HDR *mf = NULL;
 	MPT_FRAME_HDR *mr = 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",
 	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
 				ioc->name, pa));
 				ioc->name, pa));
@@ -256,7 +274,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
 		mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 		mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 		break;
 		break;
 	case MPI_CONTEXT_REPLY_TYPE_LAN:
 	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
 		 *  Blind set of mf to NULL here was fatal
 		 *  after lan_reply says "freeme"
 		 *  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);
 		mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
 		break;
 		break;
 	case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
 	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);
 		mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
 		break;
 		break;
 	default:
 	default:
@@ -286,8 +304,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
 	}
 	}
 
 
 	/*  Check for (valid) IO callback!  */
 	/*  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",
 		printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
 				__FUNCTION__, ioc->name, cb_idx);
 				__FUNCTION__, ioc->name, cb_idx);
 		goto out;
 		goto out;
@@ -304,8 +322,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 {
 {
 	MPT_FRAME_HDR	*mf;
 	MPT_FRAME_HDR	*mf;
 	MPT_FRAME_HDR	*mr;
 	MPT_FRAME_HDR	*mr;
-	int		 req_idx;
-	int		 cb_idx;
+	u16		 req_idx;
+	u8		 cb_idx;
 	int		 freeme;
 	int		 freeme;
 
 
 	u32 reply_dma_low;
 	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",
 	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));
 			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
 	 /*  Check/log IOC log info
 	 */
 	 */
@@ -350,8 +368,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 		mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
 		mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
 
 
 	/*  Check for (valid) IO callback!  */
 	/*  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",
 		printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
 				__FUNCTION__, ioc->name, cb_idx);
 				__FUNCTION__, ioc->name, cb_idx);
 		freeme = 0;
 		freeme = 0;
@@ -433,8 +451,9 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 #ifdef CONFIG_FUSION_LOGGING
 #ifdef CONFIG_FUSION_LOGGING
 	if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
 	if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
 			!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
 			!(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
 #endif
 
 
@@ -499,8 +518,8 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 				u16		 status;
 				u16		 status;
 
 
 				status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 				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;
 				pCfg->status = status;
 				if (status == MPI_IOCSTATUS_SUCCESS) {
 				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;
  *	in order to register separate callbacks; one for "normal" SCSI IO;
  *	one for MptScsiTaskMgmt requests; one for Scan/DV requests.
  *	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)
 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}
 	 *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
 	 *  (slot/handle 0 is reserved!)
 	 *  (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;
 			break;
 		}
 		}
 	}
 	}
@@ -601,9 +619,9 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
  *	module is unloaded.
  *	module is unloaded.
  */
  */
 void
 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;
 		MptCallbacks[cb_idx] = NULL;
 		MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
 		MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
 		MptEvHandlers[cb_idx] = NULL;
 		MptEvHandlers[cb_idx] = NULL;
@@ -625,9 +643,9 @@ mpt_deregister(int cb_idx)
  *	Returns 0 for success.
  *	Returns 0 for success.
  */
  */
 int
 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;
 		return -1;
 
 
 	MptEvHandlers[cb_idx] = ev_cbfunc;
 	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.
  *	or when its module is unloaded.
  */
  */
 void
 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;
 		return;
 
 
 	MptEvHandlers[cb_idx] = NULL;
 	MptEvHandlers[cb_idx] = NULL;
@@ -665,9 +683,9 @@ mpt_event_deregister(int cb_idx)
  *	Returns 0 for success.
  *	Returns 0 for success.
  */
  */
 int
 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;
 		return -1;
 
 
 	MptResetHandlers[cb_idx] = reset_func;
 	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.
  *	or when its module is unloaded.
  */
  */
 void
 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;
 		return;
 
 
 	MptResetHandlers[cb_idx] = NULL;
 	MptResetHandlers[cb_idx] = NULL;
@@ -699,12 +717,12 @@ mpt_reset_deregister(int cb_idx)
  *	@cb_idx: MPT protocol driver index
  *	@cb_idx: MPT protocol driver index
  */
  */
 int
 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;
 	MPT_ADAPTER	*ioc;
 	const struct pci_device_id *id;
 	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;
 		return -EINVAL;
 
 
 	MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
 	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
  *	@cb_idx: MPT protocol driver index
  */
  */
 void
 void
-mpt_device_driver_deregister(int cb_idx)
+mpt_device_driver_deregister(u8 cb_idx)
 {
 {
 	struct mpt_pci_driver *dd_cbfunc;
 	struct mpt_pci_driver *dd_cbfunc;
 	MPT_ADAPTER	*ioc;
 	MPT_ADAPTER	*ioc;
 
 
-	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
+	if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 		return;
 		return;
 
 
 	dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
 	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)
  *	mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
  *	allocated per MPT adapter.
  *	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
  *	@ioc: Pointer to MPT adapter structure
  *
  *
  *	Returns pointer to a MPT request frame or %NULL if none are available
  *	Returns pointer to a MPT request frame or %NULL if none are available
  *	or IOC is not active.
  *	or IOC is not active.
  */
  */
 MPT_FRAME_HDR*
 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;
 	MPT_FRAME_HDR *mf;
 	unsigned long flags;
 	unsigned long flags;
@@ -766,7 +784,8 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 
 
 #ifdef MFCNT
 #ifdef MFCNT
 	if (!ioc->active)
 	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
 #endif
 
 
 	/* If interrupts are not attached, do not return a request frame */
 	/* 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);
 				u.frame.linkage.list);
 		list_del(&mf->u.frame.linkage.list);
 		list_del(&mf->u.frame.linkage.list);
 		mf->u.frame.linkage.arg1 = 0;
 		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;
 		req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 								/* u16! */
 								/* u16! */
 		req_idx = req_offset / ioc->req_sz;
 		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.req_idx = cpu_to_le16(req_idx);
 		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 		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
 #ifdef MFCNT
 		ioc->mfcnt++;
 		ioc->mfcnt++;
 #endif
 #endif
@@ -798,14 +818,17 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 
 
 #ifdef MFCNT
 #ifdef MFCNT
 	if (mf == NULL)
 	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++;
 	mfcounter++;
 	if (mfcounter == PRINT_MF_COUNT)
 	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
 #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;
 	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
  *	mpt_put_msg_frame - Send a protocol specific MPT request frame
  *	to a IOC.
  *	to a IOC.
- *	@handle: Handle of registered MPT protocol driver
+ *	@cb_idx: Handle of registered MPT protocol driver
  *	@ioc: Pointer to MPT adapter structure
  *	@ioc: Pointer to MPT adapter structure
  *	@mf: Pointer to MPT request frame
  *	@mf: Pointer to MPT request frame
  *
  *
@@ -821,14 +844,14 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
  *	specific MPT adapter.
  *	specific MPT adapter.
  */
  */
 void
 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;
 	u32 mf_dma_addr;
 	int req_offset;
 	int req_offset;
 	u16	 req_idx;	/* Request index */
 	u16	 req_idx;	/* Request index */
 
 
 	/* ensure values are reset properly! */
 	/* 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;
 	req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 								/* u16! */
 								/* u16! */
 	req_idx = req_offset / ioc->req_sz;
 	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);
 	DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
 
 
 	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
 	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);
 	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.
  *	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.
  *	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
  *	@ioc: Pointer to MPT adapter structure
  *	@reqBytes: Size of the request in bytes
  *	@reqBytes: Size of the request in bytes
  *	@req: Pointer to MPT request frame
  *	@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.
  *	Returns 0 for success, non-zero for failure.
  */
  */
 int
 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;
 	int	r = 0;
 	u8	*req_as_bytes;
 	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) {
 	if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
 		MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
 		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.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 */
 	/* 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))
 	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
 		return -5;
 		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));
 		ioc->name, ii));
 
 
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 	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;
 	MPT_ADAPTER	*ioc;
 	u8		__iomem *mem;
 	u8		__iomem *mem;
+	u8		__iomem *pmem;
 	unsigned long	 mem_phys;
 	unsigned long	 mem_phys;
 	unsigned long	 port;
 	unsigned long	 port;
 	u32		 msize;
 	u32		 msize;
 	u32		 psize;
 	u32		 psize;
 	int		 ii;
 	int		 ii;
+	u8		 cb_idx;
 	int		 r = -ENODEV;
 	int		 r = -ENODEV;
 	u8		 revision;
 	u8		 revision;
 	u8		 pcixcmd;
 	u8		 pcixcmd;
@@ -1408,35 +1467,39 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	struct proc_dir_entry *dent, *ent;
 	struct proc_dir_entry *dent, *ent;
 #endif
 #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);
 	ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
 	if (ioc == NULL) {
 	if (ioc == NULL) {
 		printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
 		printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-
 	ioc->debug_level = mpt_debug_level;
 	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)) {
 	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)) {
 	} 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;
 		return r;
 	}
 	}
 
 
 	if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
 	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 {
 	} 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);
 	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. */
 	/* Find lookup slot. */
 	INIT_LIST_HEAD(&ioc->list);
 	INIT_LIST_HEAD(&ioc->list);
-	ioc->id = mpt_ids++;
 
 
 	mem_phys = msize = 0;
 	mem_phys = msize = 0;
 	port = psize = 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);*/
 	mem = ioremap(mem_phys, msize);
 	mem = ioremap(mem_phys, msize);
 	if (mem == NULL) {
 	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);
 		kfree(ioc);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	ioc->memmap = mem;
 	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->mem_phys = mem_phys;
 	ioc->chip = (SYSIF_REGS __iomem *)mem;
 	ioc->chip = (SYSIF_REGS __iomem *)mem;
 
 
 	/* Save Port IO values in case we need to do downloadboot */
 	/* 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);
 	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
 	mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
 	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)
 	if (ioc->errata_flag_1064)
 		pci_disable_io_access(pdev);
 		pci_disable_io_access(pdev);
 
 
-	sprintf(ioc->name, "ioc%d", ioc->id);
-
 	spin_lock_init(&ioc->FreeQlock);
 	spin_lock_init(&ioc->FreeQlock);
 
 
 	/* Disable all! */
 	/* 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,
 	if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
 	    CAN_SLEEP)) != 0){
 	    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);
 		list_del(&ioc->list);
 		if (ioc->alt_ioc)
 		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 */
 	/* 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);
 	MPT_ADAPTER 	*ioc = pci_get_drvdata(pdev);
 	char pname[32];
 	char pname[32];
-	int ii;
+	u8 cb_idx;
 
 
 	sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
 	sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
 	remove_proc_entry(pname, NULL);
 	remove_proc_entry(pname, NULL);
@@ -1673,10 +1730,10 @@ mpt_detach(struct pci_dev *pdev)
 	remove_proc_entry(pname, NULL);
 	remove_proc_entry(pname, NULL);
 
 
 	/* call per device driver remove entry point */
 	/* 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
 #endif
 
 
 static int
 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 &&
 	if ((MptDriverClass[index] == MPTSPI_DRIVER &&
 	     ioc->bus_type != SPI) ||
 	     ioc->bus_type != SPI) ||
@@ -1830,14 +1887,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	int	 hard;
 	int	 hard;
 	int	 rc=0;
 	int	 rc=0;
 	int	 ii;
 	int	 ii;
+	u8	 cb_idx;
 	int	 handlers;
 	int	 handlers;
 	int	 ret = 0;
 	int	 ret = 0;
 	int	 reset_alt_ioc_active = 0;
 	int	 reset_alt_ioc_active = 0;
 	int	 irq_allocated = 0;
 	int	 irq_allocated = 0;
 	u8	*a;
 	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) */
 	/* Disable reply interrupts (also blocks FreeQ) */
 	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
 	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 = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
 		if (hard_reset_done == -4) {
 		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) {
 			if (reset_alt_ioc_active && ioc->alt_ioc) {
 				/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
 				/* (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);
 				CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
 				ioc->alt_ioc->active = 1;
 				ioc->alt_ioc->active = 1;
 			}
 			}
 
 
 		} else {
 		} else {
-			printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
-					ioc->name);
+			printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
 		}
 		}
 		return -1;
 		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)
 		if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
 			alt_ioc_ready = 1;
 			alt_ioc_ready = 1;
 		else
 		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++) {
 	for (ii=0; ii<5; ii++) {
@@ -1897,7 +1951,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 
 
 
 
 	if (ii == 5) {
 	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;
 		ret = -2;
 	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 		MptDisplayIocCapabilities(ioc);
 		MptDisplayIocCapabilities(ioc);
@@ -1906,14 +1961,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	if (alt_ioc_ready) {
 	if (alt_ioc_ready) {
 		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
 		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
 			dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 			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
 			/* Retry - alt IOC was initialized once
 			 */
 			 */
 			rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
 			rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
 		}
 		}
 		if (rc) {
 		if (rc) {
 			dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 			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;
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
 			reset_alt_ioc_active = 0;
 		} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 		} 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 (ioc->pcidev->irq) {
 			if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
 			if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
 				printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
 				printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
-					ioc->name);
+				    ioc->name);
 			rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
 			rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
-					IRQF_SHARED, ioc->name, ioc);
+			    IRQF_SHARED, ioc->name, ioc);
 			if (rc < 0) {
 			if (rc < 0) {
 				printk(MYIOC_s_ERR_FMT "Unable to allocate "
 				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)
 				if (mpt_msi_enable)
 					pci_disable_msi(ioc->pcidev);
 					pci_disable_msi(ioc->pcidev);
 				return -EBUSY;
 				return -EBUSY;
@@ -1946,8 +2000,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 			ioc->pci_irq = ioc->pcidev->irq;
 			ioc->pci_irq = ioc->pcidev->irq;
 			pci_set_master(ioc->pcidev);		/* ?? */
 			pci_set_master(ioc->pcidev);		/* ?? */
 			pci_set_drvdata(ioc->pcidev, ioc);
 			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;
 		ret = -4;
 // NEW!
 // NEW!
 	if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
 	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;
 		alt_ioc_ready = 0;
 		reset_alt_ioc_active = 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) {
 		if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
 			alt_ioc_ready = 0;
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 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 (reason == MPT_HOSTEVENT_IOC_BRINGUP){
 		if (ioc->upload_fw) {
 		if (ioc->upload_fw) {
 			ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 			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
 			/* 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)
 						 * mpt_diag_reset)
 						 */
 						 */
 						ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 						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;
 						ioc->alt_ioc->cached_fw = NULL;
 					}
 					}
 				} else {
 				} else {
-					printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+					printk(MYIOC_s_WARN_FMT
+					    "firmware upload failure!\n", ioc->name);
 					ret = -5;
 					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) {
 	if (reset_alt_ioc_active && ioc->alt_ioc) {
 		/* (re)Enable alt-IOC! (reply interrupt) */
 		/* (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);
 		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
 		ioc->alt_ioc->active = 1;
 		ioc->alt_ioc->active = 1;
 	}
 	}
@@ -2075,10 +2129,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 				(void) GetLanConfigPages(ioc);
 				(void) GetLanConfigPages(ioc);
 				a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
 				a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
 				dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 				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 {
 		} else {
@@ -2114,20 +2166,20 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	 */
 	 */
 	if (hard_reset_done) {
 	if (hard_reset_done) {
 		rc = handlers = 0;
 		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
 				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++;
 				handlers++;
 			}
 			}
 
 
-			if (alt_ioc_ready && MptResetHandlers[ii]) {
+			if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
 				drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 				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++;
 				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,"
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
 	    " searching for devfn match on %x or %x\n",
 	    " 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));
 	peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
 	if (!peer) {
 	if (!peer) {
@@ -2181,15 +2233,15 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
 		if (_pcidev == peer) {
 		if (_pcidev == peer) {
 			/* Paranoia checks */
 			/* Paranoia checks */
 			if (ioc->alt_ioc != NULL) {
 			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);
 					ioc->name, ioc->alt_ioc->name);
 				break;
 				break;
 			} else if (ioc_srch->alt_ioc != NULL) {
 			} 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);
 					ioc_srch->name, ioc_srch->alt_ioc->name);
 				break;
 				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->name, ioc_srch->name));
 			ioc_srch->alt_ioc = ioc;
 			ioc_srch->alt_ioc = ioc;
 			ioc->alt_ioc = ioc_srch;
 			ioc->alt_ioc = ioc_srch;
@@ -2210,10 +2262,11 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 	int ret;
 	int ret;
 
 
 	if (ioc->cached_fw != NULL) {
 	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) {
 		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) {
 	if (ioc->alloc != NULL) {
 		sz = ioc->alloc_sz;
 		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,
 		pci_free_consistent(ioc->pcidev, sz,
 				ioc->alloc, ioc->alloc_dma);
 				ioc->alloc, ioc->alloc_dma);
 		ioc->reply_frames = NULL;
 		ioc->reply_frames = NULL;
@@ -2286,15 +2339,14 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 	if (ioc->HostPageBuffer != NULL) {
 	if (ioc->HostPageBuffer != NULL) {
 		if((ret = mpt_host_page_access_control(ioc,
 		if((ret = mpt_host_page_access_control(ioc,
 		    MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
 		    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));
 		 	ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
 		pci_free_consistent(ioc->pcidev, 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 = NULL;
 		ioc->HostPageBuffer_sz = 0;
 		ioc->HostPageBuffer_sz = 0;
 		ioc->alloc_total -= ioc->HostPageBuffer_sz;
 		ioc->alloc_total -= ioc->HostPageBuffer_sz;
@@ -2336,7 +2388,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
 #if defined(CONFIG_MTRR) && 0
 #if defined(CONFIG_MTRR) && 0
 	if (ioc->mtrr_reg > 0) {
 	if (ioc->mtrr_reg > 0) {
 		mtrr_del(ioc->mtrr_reg, 0, 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
 #endif
 
 
@@ -2344,8 +2396,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
 	list_del(&ioc->list);
 	list_del(&ioc->list);
 
 
 	sz_last = ioc->alloc_total;
 	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)
 	if (ioc->alt_ioc)
 		ioc->alt_ioc->alt_ioc = NULL;
 		ioc->alt_ioc->alt_ioc = NULL;
@@ -2424,7 +2476,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
 
 
 	/* Get current [raw] IOC state  */
 	/* Get current [raw] IOC state  */
 	ioc_state = mpt_GetIocState(ioc, 0);
 	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
 	 *	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) {
 	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
 		statefault = 2;
 		statefault = 2;
 		printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
 		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
 		 * Else, fall through to KickStart case
 		 */
 		 */
 		whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
 		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)
 		if (whoinit == MPI_WHOINIT_PCI_PEER)
 			return -4;
 			return -4;
 		else {
 		else {
@@ -2549,7 +2601,6 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
 
 
 	/*  Get!  */
 	/*  Get!  */
 	s = CHIPREG_READ32(&ioc->chip->Doorbell);
 	s = CHIPREG_READ32(&ioc->chip->Doorbell);
-//	dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
 	sc = s & MPI_IOC_STATE_MASK;
 	sc = s & MPI_IOC_STATE_MASK;
 
 
 	/*  Save!  */
 	/*  Save!  */
@@ -2581,9 +2632,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 
 
 	/* IOC *must* NOT be in RESET state! */
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
 	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;
 		return -44;
 	}
 	}
 
 
@@ -2703,8 +2753,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 		}
 		}
 		ioc->NBShiftFactor  = shiftFactor;
 		ioc->NBShiftFactor  = shiftFactor;
 		dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		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) {
 		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! */
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
 	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;
 		return -4;
 	}
 	}
 
 
@@ -2934,7 +2983,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 		state = mpt_GetIocState(ioc, 1);
 		state = mpt_GetIocState(ioc, 1);
 		count++;
 		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->name, count));
 
 
 	ioc->aen_event_read_flag=0;
 	ioc->aen_event_read_flag=0;
@@ -3027,10 +3076,9 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
 	int sz;
 	int sz;
 
 
 	sz = ioc->facts.FWImageSize;
 	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;
 	ioc->cached_fw = NULL;
 
 
 	return;
 	return;
@@ -3054,7 +3102,6 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
 static int
 static int
 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 {
 {
-	u8			 request[ioc->req_sz];
 	u8			 reply[sizeof(FWUploadReply_t)];
 	u8			 reply[sizeof(FWUploadReply_t)];
 	FWUpload_t		*prequest;
 	FWUpload_t		*prequest;
 	FWUploadReply_t		*preply;
 	FWUploadReply_t		*preply;
@@ -3071,8 +3118,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 
 
 	mpt_alloc_fw_memory(ioc, sz);
 	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) {
 	if (ioc->cached_fw == NULL) {
 		/* Major Failure.
 		/* Major Failure.
@@ -3080,11 +3127,16 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 		return -ENOMEM;
 		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);
 	reply_sz = sizeof(reply);
 	memset(preply, 0, reply_sz);
 	memset(preply, 0, reply_sz);
@@ -3096,21 +3148,22 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 	ptcsge->DetailsLength = 12;
 	ptcsge->DetailsLength = 12;
 	ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
 	ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
 	ptcsge->ImageSize = cpu_to_le32(sz);
 	ptcsge->ImageSize = cpu_to_le32(sz);
+	ptcsge++;
 
 
 	sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
 	sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
 
 
 	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
 	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);
 	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,
 	ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
 				reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
 				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;
 	cmdStatus = -EFAULT;
 	if (ii == 0) {
 	if (ii == 0) {
@@ -3135,6 +3188,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 			ioc->name));
 			ioc->name));
 		mpt_free_fw_memory(ioc);
 		mpt_free_fw_memory(ioc);
 	}
 	}
+	kfree(prequest);
 
 
 	return cmdStatus;
 	return cmdStatus;
 }
 }
@@ -3381,7 +3435,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 	u32 ioc_state=0;
 	u32 ioc_state=0;
 	int cnt,cntdn;
 	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) {
 	if (ioc->bus_type == SPI) {
 		/* Always issue a Msg Unit Reset first. This will clear some
 		/* Always issue a Msg Unit Reset first. This will clear some
 		 * SCSI bus hang conditions.
 		 * SCSI bus hang conditions.
@@ -3400,7 +3454,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 		return hard_reset_done;
 		return hard_reset_done;
 
 
 	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
 	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
-			ioc->name));
+		ioc->name));
 
 
 	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;	/* 2 seconds */
 	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;	/* 2 seconds */
 	for (cnt=0; cnt<cntdn; cnt++) {
 	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;
 	return -1;
 }
 }
 
 
@@ -3560,20 +3614,20 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 		 * MptResetHandlers[] registered yet.
 		 * MptResetHandlers[] registered yet.
 		 */
 		 */
 		{
 		{
-			int	 ii;
+			u8	 cb_idx;
 			int	 r = 0;
 			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
 					dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 						"Calling IOC pre_reset handler #%d\n",
 						"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) {
 					if (ioc->alt_ioc) {
 						dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 						dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 							"Calling alt-%s pre_reset handler #%d\n",
 							"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,
 			if ((count = mpt_downloadboot(ioc,
 				(MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
 				(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 {
 		} else {
@@ -3750,8 +3804,8 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
 			if (sleepFlag != CAN_SLEEP)
 			if (sleepFlag != CAN_SLEEP)
 				count *= 10;
 				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;
 			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));
 		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",
 		dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
 				ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
 				ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
@@ -4349,7 +4403,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 #endif
 #endif
 
 
 	dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
 	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",
 	dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
 			ioc->name, t, u16cnt/2));
 			ioc->name, t, u16cnt/2));
@@ -4824,8 +4878,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
 
 
 				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
 				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
 					ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
 					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->name, pPP0->Capabilities));
 				}
 				}
 				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
 				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
 				/* Nvram data is left with INVALID mark
 				 */
 				 */
 				rc = 1;
 				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 {
 			} else {
 				SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
 				SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
 				MpiDeviceInfo_t	*pdevice = NULL;
 				MpiDeviceInfo_t	*pdevice = NULL;
@@ -5701,10 +5787,10 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 	CONFIGPARMS *pCfg;
 	CONFIGPARMS *pCfg;
 	unsigned long flags;
 	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) {
 	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
 static int
 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
 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;
 	int	 scsi, fc, sas, lan, ctl, targ, dmp;
 	char	*drvname;
 	char	*drvname;
 	int	 len;
 	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");
 	len += sprintf(buf+len, "  Fusion MPT base driver\n");
 
 
 	scsi = fc = sas = lan = ctl = targ = dmp = 0;
 	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;
 		drvname = NULL;
-		if (MptCallbacks[ii]) {
-			switch (MptDriverClass[ii]) {
+		if (MptCallbacks[cb_idx]) {
+			switch (MptDriverClass[cb_idx]) {
 			case MPTSPI_DRIVER:
 			case MPTSPI_DRIVER:
 				if (!scsi++) drvname = "SPI host";
 				if (!scsi++) drvname = "SPI host";
 				break;
 				break;
@@ -6099,26 +6185,25 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 	 * For all other protocol drivers, this is a no-op.
 	 * For all other protocol drivers, this is a no-op.
 	 */
 	 */
 	{
 	{
-		int	 ii;
+		u8	 cb_idx;
 		int	 r = 0;
 		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",
 				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) {
 				if (ioc->alt_ioc) {
 					dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
 					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) {
 	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;
 	ioc->reload_fw = 0;
 	if (ioc->alt_ioc)
 	if (ioc->alt_ioc)
@@ -6515,6 +6600,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	u32 evData0 = 0;
 	u32 evData0 = 0;
 //	u32 evCtx;
 //	u32 evCtx;
 	int ii;
 	int ii;
+	u8 cb_idx;
 	int r = 0;
 	int r = 0;
 	int handlers = 0;
 	int handlers = 0;
 	char evStr[EVENT_DESCR_STR_SZ];
 	char evStr[EVENT_DESCR_STR_SZ];
@@ -6537,12 +6623,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 			evStr));
 			evStr));
 
 
 #ifdef CONFIG_FUSION_LOGGING
 #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++)
 	for (ii = 0; ii < evDataLen; ii++)
 		devtverboseprintk(ioc, printk(" %08x",
 		devtverboseprintk(ioc, printk(" %08x",
 		    le32_to_cpu(pEventReply->Data[ii])));
 		    le32_to_cpu(pEventReply->Data[ii])));
-	devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
+	devtverboseprintk(ioc, printk("\n"));
 #endif
 #endif
 
 
 	/*
 	/*
@@ -6595,11 +6681,11 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	/*
 	/*
 	 *  Call each currently registered protocol event handler.
 	 *  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",
 			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++;
 			handlers++;
 		}
 		}
 	}
 	}
@@ -7034,8 +7120,8 @@ mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 	if (!desc)
 	if (!desc)
 		return;
 		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)
 	if (!desc)
 		return;
 		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_device_driver_deregister);
 EXPORT_SYMBOL(mpt_get_msg_frame);
 EXPORT_SYMBOL(mpt_get_msg_frame);
 EXPORT_SYMBOL(mpt_put_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_free_msg_frame);
 EXPORT_SYMBOL(mpt_add_sge);
 EXPORT_SYMBOL(mpt_add_sge);
 EXPORT_SYMBOL(mpt_send_handshake_request);
 EXPORT_SYMBOL(mpt_send_handshake_request);
 EXPORT_SYMBOL(mpt_verify_adapter);
 EXPORT_SYMBOL(mpt_verify_adapter);
 EXPORT_SYMBOL(mpt_GetIocState);
 EXPORT_SYMBOL(mpt_GetIocState);
 EXPORT_SYMBOL(mpt_print_ioc_summary);
 EXPORT_SYMBOL(mpt_print_ioc_summary);
-EXPORT_SYMBOL(mpt_lan_index);
-EXPORT_SYMBOL(mpt_stm_index);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_config);
 EXPORT_SYMBOL(mpt_config);
 EXPORT_SYMBOL(mpt_findImVolumes);
 EXPORT_SYMBOL(mpt_findImVolumes);
@@ -7308,16 +7394,16 @@ EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
 static int __init
 static int __init
 fusion_init(void)
 fusion_init(void)
 {
 {
-	int i;
+	u8 cb_idx;
 
 
 	show_mptmod_ver(my_NAME, my_VERSION);
 	show_mptmod_ver(my_NAME, my_VERSION);
 	printk(KERN_INFO COPYRIGHT "\n");
 	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
 	/*  Register ourselves (mptbase) in order to facilitate

+ 56 - 24
drivers/message/fusion/mptbase.h

@@ -3,9 +3,9 @@
  *      High performance SCSI + LAN / Fibre Channel device drivers.
  *      High performance SCSI + LAN / Fibre Channel device drivers.
  *      For use with PCI chip/adapter(s):
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
  *          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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */
@@ -68,15 +68,15 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 
 #ifndef MODULEAUTHOR
 #ifndef MODULEAUTHOR
-#define MODULEAUTHOR	"LSI Logic Corporation"
+#define MODULEAUTHOR	"LSI Corporation"
 #endif
 #endif
 
 
 #ifndef COPYRIGHT
 #ifndef COPYRIGHT
 #define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
 #define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
 #endif
 #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 WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 
 #define show_mptmod_ver(s,ver)  \
 #define show_mptmod_ver(s,ver)  \
@@ -186,12 +186,42 @@
  * MPT drivers.  NOTE: Users of these macro defs must
  * MPT drivers.  NOTE: Users of these macro defs must
  * themselves define their own MYNAM.
  * themselves define their own MYNAM.
  */
  */
+#define MYIOC_s_FMT			MYNAM ": %s: "
 #define MYIOC_s_DEBUG_FMT		KERN_DEBUG MYNAM ": %s: "
 #define MYIOC_s_DEBUG_FMT		KERN_DEBUG MYNAM ": %s: "
 #define MYIOC_s_INFO_FMT		KERN_INFO MYNAM ": %s: "
 #define MYIOC_s_INFO_FMT		KERN_INFO MYNAM ": %s: "
 #define MYIOC_s_NOTE_FMT		KERN_NOTICE MYNAM ": %s: "
 #define MYIOC_s_NOTE_FMT		KERN_NOTICE MYNAM ": %s: "
 #define MYIOC_s_WARN_FMT		KERN_WARNING MYNAM ": %s: WARNING - "
 #define MYIOC_s_WARN_FMT		KERN_WARNING MYNAM ": %s: WARNING - "
 #define MYIOC_s_ERR_FMT			KERN_ERR MYNAM ": %s: ERROR - "
 #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...
  *  MPT protocol driver defs...
@@ -307,7 +337,8 @@ typedef struct _SYSIF_REGS
 	u32	Reserved2[2];	/* 38-3F  reserved for future use    */
 	u32	Reserved2[2];	/* 38-3F  reserved for future use    */
 	u32	RequestFifo;	/* 40     Request Post/Free FIFO     */
 	u32	RequestFifo;	/* 40     Request Post/Free FIFO     */
 	u32	ReplyFifo;	/* 44     Reply   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	HostIndex;	/* 50     Host Index register        */
 	u32	Reserved4[15];	/* 54-8F                             */
 	u32	Reserved4[15];	/* 54-8F                             */
 	u32	Fubar;		/* 90     For Fubar usage            */
 	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			 reload_fw;	/* Force a FW Reload on next reset */
 	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
 	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
 	u8			 pad1[4];
 	u8			 pad1[4];
-	int			 DoneCtx;
-	int			 TaskCtx;
-	int			 InternalCtx;
+	u8			 DoneCtx;
+	u8			 TaskCtx;
+	u8			 InternalCtx;
 	spinlock_t		 initializing_hba_lock;
 	spinlock_t		 initializing_hba_lock;
 	int 	 		 initializing_hba_lock_flag;
 	int 	 		 initializing_hba_lock_flag;
 	struct list_head	 list;
 	struct list_head	 list;
@@ -668,10 +699,14 @@ typedef struct _MPT_ADAPTER
 
 
 	struct work_struct	 fc_setup_reset_work;
 	struct work_struct	 fc_setup_reset_work;
 	struct list_head	 fc_rports;
 	struct list_head	 fc_rports;
+	struct work_struct	 fc_lsc_work;
+	u8			 fc_link_speed[2];
 	spinlock_t		 fc_rescan_work_lock;
 	spinlock_t		 fc_rescan_work_lock;
 	struct work_struct	 fc_rescan_work;
 	struct work_struct	 fc_rescan_work;
 	char			 fc_rescan_work_q_name[KOBJ_NAME_LEN];
 	char			 fc_rescan_work_q_name[KOBJ_NAME_LEN];
 	struct workqueue_struct *fc_rescan_work_q;
 	struct workqueue_struct *fc_rescan_work_q;
+	struct scsi_cmnd	**ScsiLookup;
+	spinlock_t		  scsi_lookup_lock;
 } MPT_ADAPTER;
 } MPT_ADAPTER;
 
 
 /*
 /*
@@ -785,7 +820,6 @@ typedef struct _MPT_SCSI_HOST {
 	MPT_ADAPTER		 *ioc;
 	MPT_ADAPTER		 *ioc;
 	int			  port;
 	int			  port;
 	u32			  pad0;
 	u32			  pad0;
-	struct scsi_cmnd	**ScsiLookup;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
 	struct timer_list	  timer;
 	struct timer_list	  timer;
 		/* Pool of memory for holding SCpnts before doing
 		/* 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_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int	 mpt_resume(struct pci_dev *pdev);
 extern int	 mpt_resume(struct pci_dev *pdev);
 #endif
 #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_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 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 int	 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
 extern u32	 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
 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);
 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 list_head	  ioc_list;
 extern struct proc_dir_entry	*mpt_proc_root_dir;
 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__ */
 #endif		/* } __KERNEL__ */
 
 

+ 182 - 182
drivers/message/fusion/mptctl.c

@@ -1,10 +1,10 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptctl.c
  *  linux/drivers/message/fusion/mptctl.c
  *      mpt Ioctl driver.
  *      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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */
@@ -66,8 +66,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.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 "mptbase.h"
 #include "mptctl.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 );
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
 
@@ -181,7 +181,6 @@ static inline int
 mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
 mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
 {
 {
 	int rc = 0;
 	int rc = 0;
-//	dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
 
 
 	if (nonblock) {
 	if (nonblock) {
 		if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
 		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))
 		if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
 			rc = -ERESTARTSYS;
 			rc = -ERESTARTSYS;
 	}
 	}
-//	dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down return %d\n", rc));
 	return rc;
 	return rc;
 }
 }
 
 
@@ -342,7 +340,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 	SCSITaskMgmt_t	*pScsiTm;
 	SCSITaskMgmt_t	*pScsiTm;
 	MPT_SCSI_HOST	*hd;
 	MPT_SCSI_HOST	*hd;
 	int		 ii;
 	int		 ii;
-	int		 retval;
+	int		 retval=0;
 
 
 
 
 	ioctl->reset &= ~MPTCTL_RESET_OK;
 	ioctl->reset &= ~MPTCTL_RESET_OK;
@@ -350,7 +348,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 	if (ioctl->ioc->sh == NULL)
 	if (ioctl->ioc->sh == NULL)
 		return -EPERM;
 		return -EPERM;
 
 
-	hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata;
+	hd = shost_priv(ioctl->ioc->sh);
 	if (hd == NULL)
 	if (hd == NULL)
 		return -EPERM;
 		return -EPERM;
 
 
@@ -395,12 +393,19 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 	DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf);
 	DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf);
 
 
 	ioctl->wait_done=0;
 	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 */
 	/* Now wait for the command to complete */
@@ -444,7 +449,7 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
 	MPT_SCSI_HOST * hd;
 	MPT_SCSI_HOST * hd;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+	hd = shost_priv(ioc->sh);
 	if (hd == NULL)
 	if (hd == NULL)
 		return;
 		return;
 
 
@@ -468,7 +473,7 @@ static int
 mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
 {
 	MPT_IOCTL *ioctl = ioc->ioctl;
 	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_SETUP_RESET ? "setup" : (
 		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 		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;
 	MPT_ADAPTER *iocp = NULL;
 
 
 	if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
 	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",
 				"Unable to copy mpt_ioctl_header data @ %p\n",
 				__FILE__, __LINE__, uhdr);
 				__FILE__, __LINE__, uhdr);
 		return -EFAULT;
 		return -EFAULT;
@@ -587,13 +592,13 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	iocnumX = khdr.iocnum & 0xFF;
 	iocnumX = khdr.iocnum & 0xFF;
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	    (iocp == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnumX);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
 	if (!iocp->active) {
 	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__);
 				__FILE__, __LINE__);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -660,14 +665,14 @@ static int mptctl_do_reset(unsigned long arg)
 	MPT_ADAPTER		*iocp;
 	MPT_ADAPTER		*iocp;
 
 
 	if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
 	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",
 				"Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
 				__FILE__, __LINE__, urinfo);
 				__FILE__, __LINE__, urinfo);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
 	if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
 	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);
 				__FILE__, __LINE__, krinfo.hdr.iocnum);
 		return -ENODEV; /* (-6) No such device or address */
 		return -ENODEV; /* (-6) No such device or address */
 	}
 	}
@@ -676,8 +681,8 @@ static int mptctl_do_reset(unsigned long arg)
 	    iocp->name));
 	    iocp->name));
 
 
 	if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) {
 	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;
 		return -1;
 	}
 	}
 
 
@@ -708,7 +713,7 @@ mptctl_fw_download(unsigned long arg)
 	struct mpt_fw_xfer	 kfwdl;
 	struct mpt_fw_xfer	 kfwdl;
 
 
 	if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
 	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",
 				"Unable to copy mpt_fw_xfer struct @ %p\n",
 				__FILE__, __LINE__, ufwdl);
 				__FILE__, __LINE__, ufwdl);
 		return -EFAULT;
 		return -EFAULT;
@@ -756,7 +761,8 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 	pFWDownloadReply_t	 ReplyMsg = NULL;
 	pFWDownloadReply_t	 ReplyMsg = NULL;
 
 
 	if (mpt_verify_adapter(ioc, &iocp) < 0) {
 	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 */
 		return -ENODEV; /* (-6) No such device or address */
 	} else {
 	} 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);
 			mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
 			n++;
 			n++;
 			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
 			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;
 				goto fwdl_out;
 			}
 			}
 			fw_bytes_copied += bl->len;
 			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;
 	ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
 	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
 	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
 	if (iocstat == MPI_IOCSTATUS_SUCCESS) {
 	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;
 		return 0;
 	} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
 	} 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;
 		return -EBADRQC;
 	} else if (iocstat == MPI_IOCSTATUS_BUSY) {
 	} 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;
 		return -EBUSY;
 	} else {
 	} 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 -ENOMSG;
 	}
 	}
 	return 0;
 	return 0;
@@ -970,10 +977,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
 	 * structures for the SG elements.
 	 * structures for the SG elements.
 	 */
 	 */
 	i = MAX_SGL_BYTES / 8;
 	i = MAX_SGL_BYTES / 8;
-	buflist = kmalloc(i, GFP_USER);
-	if (buflist == NULL)
+	buflist = kzalloc(i, GFP_USER);
+	if (!buflist)
 		return NULL;
 		return NULL;
-	memset(buflist, 0, i);
 	buflist_ent = 0;
 	buflist_ent = 0;
 
 
 	/* Allocate a single block of memory to store the sg elements and
 	/* 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) {
 		if (buflist[buflist_ent].kptr == NULL) {
 			alloc_sz = alloc_sz / 2;
 			alloc_sz = alloc_sz / 2;
 			if (alloc_sz == 0) {
 			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;
 				goto free_and_fail;
 			}
 			}
 			continue;
 			continue;
@@ -1034,18 +1040,19 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
 
 
 		/* Need to chain? */
 		/* Need to chain? */
 		if (fragcnt == sg_spill) {
 		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;
 			goto free_and_fail;
 		}
 		}
 
 
 		/* overflow check... */
 		/* overflow check... */
 		if (numfrags*8 > MAX_SGL_BYTES){
 		if (numfrags*8 > MAX_SGL_BYTES){
 			/* GRRRRR... */
 			/* 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;
 			goto free_and_fail;
 		}
 		}
 	}
 	}
@@ -1066,8 +1073,6 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
 
 
 free_and_fail:
 free_and_fail:
 	if (sglbuf != NULL) {
 	if (sglbuf != NULL) {
-		int i;
-
 		for (i = 0; i < numfrags; i++) {
 		for (i = 0; i < numfrags; i++) {
 			dma_addr_t dma_addr;
 			dma_addr_t dma_addr;
 			u8 *kptr;
 			u8 *kptr;
@@ -1170,7 +1175,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 	int			cim_rev;
 	int			cim_rev;
 	u8			revision;
 	u8			revision;
 	struct scsi_device 	*sdev;
 	struct scsi_device 	*sdev;
-	VirtDevice		*vdev;
+	VirtDevice		*vdevice;
 
 
 	/* Add of PCI INFO results in unaligned access for
 	/* Add of PCI INFO results in unaligned access for
 	 * IA64 and Sparc. Reset long to int. Return no PCI
 	 * 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);
 	karg = kmalloc(data_size, GFP_KERNEL);
 	if (karg == NULL) {
 	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__);
 				__FILE__, __LINE__);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
 	if (copy_from_user(karg, uarg, data_size)) {
 	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",
 			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		kfree(karg);
 		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) ||
 	if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		kfree(karg);
 		kfree(karg);
 		return -ENODEV;
 		return -ENODEV;
@@ -1212,9 +1217,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 
 
 	/* Verify the data transfer size is correct. */
 	/* Verify the data transfer size is correct. */
 	if (karg->hdr.maxDataSize != data_size) {
 	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",
 			"Structure size mismatch. Command not completed.\n",
-				__FILE__, __LINE__);
+			ioc->name, __FILE__, __LINE__);
 		kfree(karg);
 		kfree(karg);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -1265,8 +1270,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 	karg->numDevices = 0;
 	karg->numDevices = 0;
 	if (ioc->sh) {
 	if (ioc->sh) {
 		shost_for_each_device(sdev, 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)
 			    MPT_TARGET_FLAGS_RAID_COMPONENT)
 				continue;
 				continue;
 			karg->numDevices++;
 			karg->numDevices++;
@@ -1290,9 +1295,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 	/* Copy the data from kernel memory to user memory
 	/* Copy the data from kernel memory to user memory
 	 */
 	 */
 	if (copy_to_user((char __user *)arg, karg, data_size)) {
 	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",
 			"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
-				__FILE__, __LINE__, uarg);
+			ioc->name, __FILE__, __LINE__, uarg);
 		kfree(karg);
 		kfree(karg);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -1317,7 +1322,7 @@ mptctl_gettargetinfo (unsigned long arg)
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
 	struct mpt_ioctl_targetinfo karg;
 	MPT_ADAPTER		*ioc;
 	MPT_ADAPTER		*ioc;
-	VirtDevice		*vdev;
+	VirtDevice		*vdevice;
 	char			*pmem;
 	char			*pmem;
 	int			*pdata;
 	int			*pdata;
 	int			iocnum;
 	int			iocnum;
@@ -1329,7 +1334,7 @@ mptctl_gettargetinfo (unsigned long arg)
 	struct scsi_device 	*sdev;
 	struct scsi_device 	*sdev;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
 	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",
 			"Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1337,7 +1342,7 @@ mptctl_gettargetinfo (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1353,8 +1358,8 @@ mptctl_gettargetinfo (unsigned long arg)
 	port = karg.hdr.port;
 	port = karg.hdr.port;
 
 
 	if (maxWordsLeft <= 0) {
 	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;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -1372,13 +1377,12 @@ mptctl_gettargetinfo (unsigned long arg)
 	 *      15- 8: Bus Number
 	 *      15- 8: Bus Number
 	 *       7- 0: Target ID
 	 *       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;
 		return -ENOMEM;
 	}
 	}
-	memset(pmem, 0, numBytes);
 	pdata =  (int *) pmem;
 	pdata =  (int *) pmem;
 
 
 	/* Get number of devices
 	/* Get number of devices
@@ -1387,13 +1391,13 @@ mptctl_gettargetinfo (unsigned long arg)
 		shost_for_each_device(sdev, ioc->sh) {
 		shost_for_each_device(sdev, ioc->sh) {
 			if (!maxWordsLeft)
 			if (!maxWordsLeft)
 				continue;
 				continue;
-			vdev = sdev->hostdata;
-			if (vdev->vtarget->tflags &
+			vdevice = sdev->hostdata;
+			if (vdevice->vtarget->tflags &
 			    MPT_TARGET_FLAGS_RAID_COMPONENT)
 			    MPT_TARGET_FLAGS_RAID_COMPONENT)
 				continue;
 				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++;
 			pdata++;
 			numDevices++;
 			numDevices++;
 			--maxWordsLeft;
 			--maxWordsLeft;
@@ -1405,9 +1409,9 @@ mptctl_gettargetinfo (unsigned long arg)
 	 */
 	 */
 	if (copy_to_user((char __user *)arg, &karg,
 	if (copy_to_user((char __user *)arg, &karg,
 				sizeof(struct mpt_ioctl_targetinfo))) {
 				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",
 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, uarg);
+			ioc->name, __FILE__, __LINE__, uarg);
 		kfree(pmem);
 		kfree(pmem);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -1415,9 +1419,9 @@ mptctl_gettargetinfo (unsigned long arg)
 	/* Copy the remaining data from kernel memory to user memory
 	/* Copy the remaining data from kernel memory to user memory
 	 */
 	 */
 	if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
 	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",
 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, pdata);
+			ioc->name, __FILE__, __LINE__, pdata);
 		kfree(pmem);
 		kfree(pmem);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -1444,7 +1448,7 @@ mptctl_readtest (unsigned long arg)
 	int iocnum;
 	int iocnum;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
 	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",
 			"Unable to read in mpt_ioctl_test struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1452,7 +1456,7 @@ mptctl_readtest (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1476,9 +1480,9 @@ mptctl_readtest (unsigned long arg)
 	/* Copy the data from kernel memory to user memory
 	/* Copy the data from kernel memory to user memory
 	 */
 	 */
 	if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
 	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",
 			"Unable to write out mpt_ioctl_test struct @ %p\n",
-				__FILE__, __LINE__, uarg);
+			ioc->name, __FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
@@ -1505,7 +1509,7 @@ mptctl_eventquery (unsigned long arg)
 	int iocnum;
 	int iocnum;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
 	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",
 			"Unable to read in mpt_ioctl_eventquery struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1513,7 +1517,7 @@ mptctl_eventquery (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1526,9 +1530,9 @@ mptctl_eventquery (unsigned long arg)
 	/* Copy the data from kernel memory to user memory
 	/* Copy the data from kernel memory to user memory
 	 */
 	 */
 	if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
 	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",
 			"Unable to write out mpt_ioctl_eventquery struct @ %p\n",
-				__FILE__, __LINE__, uarg);
+			ioc->name, __FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 	return 0;
 	return 0;
@@ -1544,7 +1548,7 @@ mptctl_eventenable (unsigned long arg)
 	int iocnum;
 	int iocnum;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
 	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",
 			"Unable to read in mpt_ioctl_eventenable struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1552,7 +1556,7 @@ mptctl_eventenable (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1563,12 +1567,13 @@ mptctl_eventenable (unsigned long arg)
 		/* Have not yet allocated memory - do so now.
 		/* Have not yet allocated memory - do so now.
 		 */
 		 */
 		int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
 		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;
 			return -ENOMEM;
 		}
 		}
-		memset(ioc->events, 0, sz);
 		ioc->alloc_total += sz;
 		ioc->alloc_total += sz;
 
 
 		ioc->eventContext = 0;
 		ioc->eventContext = 0;
@@ -1592,7 +1597,7 @@ mptctl_eventreport (unsigned long arg)
 	int			 numBytes, maxEvents, max;
 	int			 numBytes, maxEvents, max;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
 	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",
 			"Unable to read in mpt_ioctl_eventreport struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1600,7 +1605,7 @@ mptctl_eventreport (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1626,9 +1631,9 @@ mptctl_eventreport (unsigned long arg)
 	 */
 	 */
 	numBytes = max * sizeof(MPT_IOCTL_EVENTS);
 	numBytes = max * sizeof(MPT_IOCTL_EVENTS);
 	if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
 	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",
 			"Unable to write out mpt_ioctl_eventreport struct @ %p\n",
-				__FILE__, __LINE__, ioc->events);
+			ioc->name, __FILE__, __LINE__, ioc->events);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
@@ -1646,7 +1651,7 @@ mptctl_replace_fw (unsigned long arg)
 	int			 newFwSize;
 	int			 newFwSize;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
 	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",
 			"Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1654,7 +1659,7 @@ mptctl_replace_fw (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1684,9 +1689,9 @@ mptctl_replace_fw (unsigned long arg)
 	/* Copy the data from user memory to kernel space
 	/* Copy the data from user memory to kernel space
 	 */
 	 */
 	if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
 	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 "
 				"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);
 		mpt_free_fw_memory(ioc);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -1720,7 +1725,7 @@ mptctl_mpt_command (unsigned long arg)
 
 
 
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
 	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",
 			"Unable to read in mpt_ioctl_command struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -1728,7 +1733,7 @@ mptctl_mpt_command (unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1769,21 +1774,24 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	ulong 		timeout;
 	ulong 		timeout;
 	struct scsi_device *sdev;
 	struct scsi_device *sdev;
 
 
+	/* bufIn and bufOut are used for user to kernel space transfers
+	 */
 	bufIn.kptr = bufOut.kptr = NULL;
 	bufIn.kptr = bufOut.kptr = NULL;
+	bufIn.len = bufOut.len = 0;
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 	if (!ioc->ioctl) {
 	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",
 			"No memory available during driver init.\n",
 				__FILE__, __LINE__);
 				__FILE__, __LINE__);
 		return -ENOMEM;
 		return -ENOMEM;
 	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
 	} 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__);
 			"Busy with IOC Reset \n", __FILE__, __LINE__);
 		return -EBUSY;
 		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);
 		sz += sizeof(dma_addr_t) + sizeof(u32);
 
 
 	if (sz > ioc->req_sz) {
 	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",
 			"Request frame too large (%d) maximum (%d)\n",
-				__FILE__, __LINE__, sz, ioc->req_sz);
+			ioc->name, __FILE__, __LINE__, sz, ioc->req_sz);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
@@ -1817,9 +1825,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	 * Request frame in user space
 	 * Request frame in user space
 	 */
 	 */
 	if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
 	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",
 			"Unable to read MF from mpt_ioctl_command struct @ %p\n",
-			__FILE__, __LINE__, mfPtr);
+			ioc->name, __FILE__, __LINE__, mfPtr);
 		rc = -EFAULT;
 		rc = -EFAULT;
 		goto done_free_mem;
 		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;
 			id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
 			if (pScsiReq->TargetID > id) {
 			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",
 					"Target ID out of bounds. \n",
-					__FILE__, __LINE__);
+					ioc->name, __FILE__, __LINE__);
 				rc = -ENODEV;
 				rc = -ENODEV;
 				goto done_free_mem;
 				goto done_free_mem;
 			}
 			}
 
 
 			if (pScsiReq->Bus >= ioc->number_of_buses) {
 			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",
 					"Target Bus out of bounds. \n",
-					__FILE__, __LINE__);
+					ioc->name, __FILE__, __LINE__);
 				rc = -ENODEV;
 				rc = -ENODEV;
 				goto done_free_mem;
 				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;
 			ioc->ioctl->id = pScsiReq->TargetID;
 
 
 		} else {
 		} 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",
 				"SCSI driver is not loaded. \n",
-					__FILE__, __LINE__);
+				ioc->name, __FILE__, __LINE__);
 			rc = -EFAULT;
 			rc = -EFAULT;
 			goto done_free_mem;
 			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:
 	case MPI_FUNCTION_SATA_PASSTHROUGH:
 		if (!ioc->sh) {
 		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",
 				"SCSI driver is not loaded. \n",
-					__FILE__, __LINE__);
+				ioc->name, __FILE__, __LINE__);
 			rc = -EFAULT;
 			rc = -EFAULT;
 			goto done_free_mem;
 			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->reset = MPTCTL_RESET_OK;
 			ioc->ioctl->id = pScsiReq->TargetID;
 			ioc->ioctl->id = pScsiReq->TargetID;
 		} else {
 		} 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",
 				"SCSI driver is not loaded. \n",
-					__FILE__, __LINE__);
+				ioc->name, __FILE__, __LINE__);
 			rc = -EFAULT;
 			rc = -EFAULT;
 			goto done_free_mem;
 			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:
 	case MPI_FUNCTION_SCSI_TASK_MGMT:
 		{
 		{
 			MPT_SCSI_HOST *hd = NULL;
 			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",
 					"SCSI driver not loaded or SCSI host not found. \n",
-					__FILE__, __LINE__);
+					ioc->name, __FILE__, __LINE__);
 				rc = -EFAULT;
 				rc = -EFAULT;
 				goto done_free_mem;
 				goto done_free_mem;
 			} else if (mptctl_set_tm_flags(hd) != 0) {
 			} 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->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
 				(pInit->HostMfaHighAddr != high_addr) ||
 				(pInit->HostMfaHighAddr != high_addr) ||
 				(pInit->SenseBufferHighAddr != sense_high)) {
 				(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",
 					"IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",
-					__FILE__, __LINE__);
+					ioc->name, __FILE__, __LINE__);
 				rc = -EFAULT;
 				rc = -EFAULT;
 				goto done_free_mem;
 				goto done_free_mem;
 			}
 			}
@@ -2088,9 +2096,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 		 	MPI_FUNCTION_LAN_RESET
 		 	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",
 			"Illegal request (function 0x%x) \n",
-			__FILE__, __LINE__, hdr->Function);
+			ioc->name, __FILE__, __LINE__, hdr->Function);
 		rc = -EFAULT;
 		rc = -EFAULT;
 		goto done_free_mem;
 		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);
 	psge = (char *) (((int *) mf) + karg.dataSgeOffset);
 	flagsLength = 0;
 	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)
 	if (karg.dataOutSize > 0)
 		sgSize ++;
 		sgSize ++;
 
 
@@ -2147,11 +2150,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 				if (copy_from_user(bufOut.kptr,
 				if (copy_from_user(bufOut.kptr,
 						karg.dataOutBufPtr,
 						karg.dataOutBufPtr,
 						bufOut.len)) {
 						bufOut.len)) {
-					printk(KERN_ERR
+					printk(MYIOC_s_ERR_FMT
 						"%s@%d::mptctl_do_mpt_command - Unable "
 						"%s@%d::mptctl_do_mpt_command - Unable "
 						"to read user data "
 						"to read user data "
 						"struct @ %p\n",
 						"struct @ %p\n",
-						__FILE__, __LINE__,karg.dataOutBufPtr);
+						ioc->name, __FILE__, __LINE__,karg.dataOutBufPtr);
 					rc =  -EFAULT;
 					rc =  -EFAULT;
 					goto done_free_mem;
 					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);
 		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
 	} else
@@ -2233,10 +2241,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 		if (sz > 0) {
 		if (sz > 0) {
 			if (copy_to_user(karg.replyFrameBufPtr,
 			if (copy_to_user(karg.replyFrameBufPtr,
 				 &ioc->ioctl->ReplyFrame, sz)){
 				 &ioc->ioctl->ReplyFrame, sz)){
-				 printk(KERN_ERR
+				 printk(MYIOC_s_ERR_FMT
 				     "%s@%d::mptctl_do_mpt_command - "
 				     "%s@%d::mptctl_do_mpt_command - "
 				 "Unable to write out reply frame %p\n",
 				 "Unable to write out reply frame %p\n",
-				 __FILE__, __LINE__, karg.replyFrameBufPtr);
+				 ioc->name, __FILE__, __LINE__, karg.replyFrameBufPtr);
 				 rc =  -ENODATA;
 				 rc =  -ENODATA;
 				 goto done_free_mem;
 				 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);
 		sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
 		if (sz > 0) {
 		if (sz > 0) {
 			if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
 			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",
 				"Unable to write sense data to user %p\n",
-				__FILE__, __LINE__,
+				ioc->name, __FILE__, __LINE__,
 				karg.senseDataPtr);
 				karg.senseDataPtr);
 				rc =  -ENODATA;
 				rc =  -ENODATA;
 				goto done_free_mem;
 				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,
 		if (copy_to_user(karg.dataInBufPtr,
 				 bufIn.kptr, karg.dataInSize)) {
 				 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",
 				"Unable to write data to user %p\n",
-				__FILE__, __LINE__,
+				ioc->name, __FILE__, __LINE__,
 				karg.dataInBufPtr);
 				karg.dataInBufPtr);
 			rc =  -ENODATA;
 			rc =  -ENODATA;
 		}
 		}
@@ -2340,7 +2348,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 		return -EFAULT;
 		return -EFAULT;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
 	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",
 			"Unable to read in hp_host_info struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		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) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
 	    (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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -2456,7 +2464,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 	karg.soft_resets = 0;
 	karg.soft_resets = 0;
 	karg.timeouts = 0;
 	karg.timeouts = 0;
 	if (ioc->sh != NULL) {
 	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)) {
 		if (hd && (cim_rev == 1)) {
 			karg.hard_resets = hd->hard_resets;
 			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
 	/* Copy the data from kernel memory to user memory
 	 */
 	 */
 	if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
 	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",
 			"Unable to write out hp_host_info @ %p\n",
-				__FILE__, __LINE__, uarg);
+			ioc->name, __FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
@@ -2567,7 +2575,7 @@ mptctl_hp_targetinfo(unsigned long arg)
 	int			tmp, np, rc = 0;
 	int			tmp, np, rc = 0;
 
 
 	if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
 	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",
 			"Unable to read in hp_host_targetinfo struct @ %p\n",
 				__FILE__, __LINE__, uarg);
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
@@ -2575,11 +2583,11 @@ mptctl_hp_targetinfo(unsigned long arg)
 
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 		(ioc == NULL)) {
 		(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);
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 		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));
 	    ioc->name));
 
 
 	/*  There is nothing to do for FCP parts.
 	/*  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);
 			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)
 	if (hd != NULL)
 		karg.select_timeouts = hd->sel_timeout[karg.hdr.id];
 		karg.select_timeouts = hd->sel_timeout[karg.hdr.id];
 
 
 	/* Copy the data from kernel memory to user memory
 	/* Copy the data from kernel memory to user memory
 	 */
 	 */
 	if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
 	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",
 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, uarg);
+			ioc->name, __FILE__, __LINE__, uarg);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
@@ -2732,7 +2740,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	    (iocp == NULL)) {
 	    (iocp == NULL)) {
 		printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
 		printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
-				__LINE__, iocnumX);
+			__LINE__, iocnumX);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -2772,7 +2780,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	    (iocp == NULL)) {
 	    (iocp == NULL)) {
 		printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
 		printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
-				__LINE__, iocnumX);
+			__LINE__, iocnumX);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -2853,31 +2861,22 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a
 static int
 static int
 mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 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);
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
 
 	/*
 	/*
 	 * Allocate and inite a MPT_IOCTL structure
 	 * 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;
 	ioc->ioctl->ioc = ioc;
 	mutex_init(&ioc->ioctl->ioctl_mutex);
 	mutex_init(&ioc->ioctl->ioctl_mutex);
 	return 0;
 	return 0;
-
-out_fail:
-
-	mptctl_remove(pdev);
-	return err;
 }
 }
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2924,7 +2923,8 @@ static int __init mptctl_init(void)
 	 *  Install our handler
 	 *  Install our handler
 	 */
 	 */
 	++where;
 	++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");
 		printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
 		misc_deregister(&mptctl_miscdev);
 		misc_deregister(&mptctl_miscdev);
 		err = -EBUSY;
 		err = -EBUSY;

+ 2 - 2
drivers/message/fusion/mptctl.h

@@ -3,9 +3,9 @@
  *      Fusion MPT misc device (ioctl) driver.
  *      Fusion MPT misc device (ioctl) driver.
  *      For use with PCI chip/adapter(s):
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
  *          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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */

+ 108 - 41
drivers/message/fusion/mptfc.c

@@ -1,9 +1,9 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptfc.c
  *  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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */
@@ -90,9 +90,9 @@ static int max_lun = MPTFC_MAX_LUN;
 module_param(max_lun, int, 0);
 module_param(max_lun, int, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 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_target_alloc(struct scsi_target *starget);
 static int mptfc_slave_alloc(struct scsi_device *sdev);
 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));
 	struct fc_rport		*rport = starget_to_rport(scsi_target(sdev));
 	unsigned long		flags;
 	unsigned long		flags;
 	int			ready;
 	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);
 	spin_lock_irqsave(shost->host_lock, flags);
 	while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
 	while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
 		spin_unlock_irqrestore(shost->host_lock, flags);
 		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 "
 			"mptfc_block_error_handler.%d: %d:%d, port status is "
 			"DID_IMM_RETRY, deferring %s recovery.\n",
 			"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);
 		msleep(1000);
 		spin_lock_irqsave(shost->host_lock, flags);
 		spin_lock_irqsave(shost->host_lock, flags);
 	}
 	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
 
 	if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
 	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, "
 			"%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));
 			SCpnt->device->hostdata));
 		return FAILED;
 		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,
 		"%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);
 	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,
 			 * if already mapped, remap here.  If not mapped,
 			 * target_alloc will allocate vtarget and map,
 			 * 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) {
 			if (ri->starget) {
 				vtarget = ri->starget->hostdata;
 				vtarget = ri->starget->hostdata;
@@ -602,10 +601,10 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 {
 {
 	MPT_SCSI_HOST		*hd;
 	MPT_SCSI_HOST		*hd;
 	VirtTarget		*vtarget;
 	VirtTarget		*vtarget;
-	VirtDevice		*vdev;
+	VirtDevice		*vdevice;
 	struct scsi_target	*starget;
 	struct scsi_target	*starget;
 	struct fc_rport		*rport;
 	struct fc_rport		*rport;
-
+	MPT_ADAPTER 		*ioc;
 
 
 	starget = scsi_target(sdev);
 	starget = scsi_target(sdev);
 	rport = starget_to_rport(starget);
 	rport = starget_to_rport(starget);
@@ -613,31 +612,32 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 	if (!rport || fc_remote_port_chkready(rport))
 	if (!rport || fc_remote_port_chkready(rport))
 		return -ENXIO;
 		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",
 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
-				hd->ioc->name, sizeof(VirtDevice));
+				ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
 
 
-	sdev->hostdata = vdev;
+	sdev->hostdata = vdevice;
 	vtarget = starget->hostdata;
 	vtarget = starget->hostdata;
 
 
 	if (vtarget->num_luns == 0) {
 	if (vtarget->num_luns == 0) {
-		vtarget->ioc_id = hd->ioc->id;
+		vtarget->ioc_id = ioc->id;
 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
 	}
 	}
 
 
-	vdev->vtarget = vtarget;
-	vdev->lun = sdev->lun;
+	vdevice->vtarget = vtarget;
+	vdevice->lun = sdev->lun;
 
 
 	vtarget->num_luns++;
 	vtarget->num_luns++;
 
 
 
 
-	mptfc_dump_lun_info(hd->ioc, rport, sdev, vtarget);
+	mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -648,9 +648,9 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct mptfc_rport_info	*ri;
 	struct mptfc_rport_info	*ri;
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
 	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;
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		done(SCpnt);
 		return 0;
 		return 0;
@@ -674,6 +674,50 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	return mptscsih_qcmd(SCpnt,done);
 	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.
  *	mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@ioc: Pointer to MPT_ADAPTER structure
@@ -773,6 +817,7 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
 							" complete.\n",
 							" complete.\n",
 						ioc->name);
 						ioc->name);
 			}
 			}
+			mptfc_display_port_link_speed(ioc, portnum, pp0dest);
 		}
 		}
 
 
 		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
 		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
 static void
 mptfc_setup_reset(struct work_struct *work)
 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);
 	spin_lock_init(&ioc->fc_rescan_work_lock);
 	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
 	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
 	INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
 	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);
 	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);
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 
-	hd = (MPT_SCSI_HOST *) sh->hostdata;
+	hd = shost_priv(sh);
 	hd->ioc = ioc;
 	hd->ioc = ioc;
 
 
 	/* SCSI needs scsi_cmnd lookup table!
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 * (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;
 		error = -ENOMEM;
 		goto out_mptfc_probe;
 		goto out_mptfc_probe;
 	}
 	}
+	spin_lock_init(&ioc->scsi_lookup_lock);
 
 
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
-		 ioc->name, hd->ScsiLookup));
+		 ioc->name, ioc->ScsiLookup));
 
 
 	/* Clear the TM flags
 	/* 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;
 	sh->transportt = mptfc_transport_template;
 	error = scsi_add_host (sh, &ioc->pcidev->dev);
 	error = scsi_add_host (sh, &ioc->pcidev->dev);
 	if(error) {
 	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;
 		goto out_mptfc_probe;
 	}
 	}
 
 
@@ -1325,7 +1384,7 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 			ioc->name, event));
 			ioc->name, event));
 
 
 	if (ioc->sh == NULL ||
 	if (ioc->sh == NULL ||
-		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+		((hd = shost_priv(ioc->sh)) == NULL))
 		return 1;
 		return 1;
 
 
 	switch (event) {
 	switch (event) {
@@ -1337,6 +1396,14 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 		}
 		}
 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
 		break;
 		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:
 	default:
 		rc = mptscsih_event_process(ioc,pEvReply);
 		rc = mptscsih_event_process(ioc,pEvReply);
 		break;
 		break;

+ 11 - 21
drivers/message/fusion/mptlan.c

@@ -1,10 +1,10 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptlan.c
  *  linux/drivers/message/fusion/mptlan.c
  *      IP Over Fibre Channel device driver.
  *      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)
  *  (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
  *  Fusion MPT LAN private data
  */
  */
-static int LanCtx = -1;
+static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS;
 
 
 static u32 max_buckets_out = 127;
 static u32 max_buckets_out = 127;
 static u32 tx_max_out_p = 127 - 16;
 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);
 DEFINE_RWLOCK(bad_naa_lock);
 #endif
 #endif
 
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Fusion MPT LAN external data
- */
-extern int mpt_lan_index;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
 /**
  *	lan_reply - Handle all data sent from the hardware.
  *	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;
 		pRecvReq = (LANReceivePostRequest_t *) mf;
 
 
+		i = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+		mpt_dev->RequestNB[i] = 0;
 		count = buckets;
 		count = buckets;
 		if (count > max)
 		if (count > max)
 			count = max;
 			count = max;
@@ -1351,10 +1347,11 @@ mpt_lan_post_receive_buckets_work(struct work_struct *work)
 static struct net_device *
 static struct net_device *
 mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
 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;
 	u8 HWaddr[FC_ALEN], *a;
 
 
+	dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
 	if (!dev)
 	if (!dev)
 		return NULL;
 		return NULL;
 
 
@@ -1366,7 +1363,6 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
 	priv->mpt_dev = mpt_dev;
 	priv->mpt_dev = mpt_dev;
 	priv->pnum = pnum;
 	priv->pnum = pnum;
 
 
-	memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task));
 	INIT_DELAYED_WORK(&priv->post_buckets_task,
 	INIT_DELAYED_WORK(&priv->post_buckets_task,
 			  mpt_lan_post_receive_buckets_work);
 			  mpt_lan_post_receive_buckets_work);
 	priv->post_buckets_active = 0;
 	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->txfidx_lock);
 	spin_lock_init(&priv->rxfidx_lock);
 	spin_lock_init(&priv->rxfidx_lock);
 
 
-	memset(&priv->stats, 0, sizeof(priv->stats));
-
 	/*  Grab pre-fetched LANPage1 stuff. :-) */
 	/*  Grab pre-fetched LANPage1 stuff. :-) */
 	a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow;
 	a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow;
 
 
@@ -1508,9 +1502,6 @@ static int __init mpt_lan_init (void)
 		return -EBUSY;
 		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));
 	dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
 
 
 	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) {
 	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_device_driver_deregister(MPTLAN_DRIVER);
 	mpt_reset_deregister(LanCtx);
 	mpt_reset_deregister(LanCtx);
 
 
-	if (LanCtx >= 0) {
+	if (LanCtx) {
 		mpt_deregister(LanCtx);
 		mpt_deregister(LanCtx);
-		LanCtx = -1;
-		mpt_lan_index = 0;
+		LanCtx = MPT_MAX_PROTOCOL_DRIVERS;
 	}
 	}
 }
 }
 
 

+ 4 - 4
drivers/message/fusion/mptlan.h

@@ -1,10 +1,10 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptlan.h
  *  linux/drivers/message/fusion/mptlan.h
  *      IP Over Fibre Channel device driver.
  *      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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */
@@ -75,7 +75,7 @@
 #include <asm/io.h>
 #include <asm/io.h>
 
 
     /* Override mptbase.h by pre-defining these! */
     /* Override mptbase.h by pre-defining these! */
-#define MODULEAUTHOR	"LSI Logic Corporation"
+#define MODULEAUTHOR	"LSI Corporation"
 
 
 #include "mptbase.h"
 #include "mptbase.h"
 
 

+ 199 - 269
drivers/message/fusion/mptsas.c

@@ -1,11 +1,10 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptsas.c
  *  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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
- *  Copyright (c) 2005-2007 Dell
  */
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
 /*
@@ -61,6 +60,7 @@
 
 
 #include "mptbase.h"
 #include "mptbase.h"
 #include "mptscsih.h"
 #include "mptscsih.h"
+#include "mptsas.h"
 
 
 
 
 #define my_NAME		"Fusion MPT SAS Host driver"
 #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_param(max_lun, int, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 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);
 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,
 static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
 					MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
 					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)
 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));
 	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)
 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)
 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));
 	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)
 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)
 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;
 	port_info = port_details->port_info;
 	phy_info = port_info->phy_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->num_phys, (unsigned long long)
 	    port_details->phy_bitmask));
 	    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) {
 	if (phy_info->port_details) {
 		phy_info->port_details->rphy = rphy;
 		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) {
 	if (rphy) {
 		dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
 		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) {
 	if (port) {
 		dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
 		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
 		 * Removing a phy from a port, letting the last
 		 * phy be removed by firmware events.
 		 * 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->num_phys--;
 		port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
 		port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
 		memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
 		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;
 	phy_info = port_info->phy_info;
 	for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 	for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 		sas_address = phy_info->attached.sas_address;
 		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)
 		if (!sas_address)
 			continue;
 			continue;
 		port_details = phy_info->port_details;
 		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 |=
 				port_details->phy_bitmask |=
 				    (1 << phy_info->phy_id);
 				    (1 << phy_info->phy_id);
 			phy_info->sas_port_add_phy=1;
 			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",
 			    "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;
 			phy_info->port_details = port_details;
 		}
 		}
 
 
@@ -515,9 +447,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 				continue;
 				continue;
 			if (phy_info_cmp->port_details == port_details )
 			if (phy_info_cmp->port_details == port_details )
 				continue;
 				continue;
-			dsaswideprintk(ioc, printk(KERN_DEBUG
+			dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 			    "\t\tphy_id=%d sas_address=0x%018llX\n",
 			    "\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));
 			    phy_info_cmp->attached.sas_address));
 			if (phy_info_cmp->port_details) {
 			if (phy_info_cmp->port_details) {
 				port_details->rphy =
 				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;
 		port_details = port_info->phy_info[i].port_details;
 		if (!port_details)
 		if (!port_details)
 			continue;
 			continue;
-		dsaswideprintk(ioc, printk(KERN_DEBUG
+		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		    "%s: [%p]: phy_id=%02d num_phys=%02d "
 		    "%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,
 		    port_details, i, port_details->num_phys,
 		    (unsigned long long)port_details->phy_bitmask));
 		    (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);
 	mutex_unlock(&ioc->sas_topology_mutex);
 }
 }
 
 
@@ -573,15 +505,15 @@ static VirtTarget *
 mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
 mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
 {
 	struct scsi_device 		*sdev;
 	struct scsi_device 		*sdev;
-	VirtDevice			*vdev;
+	VirtDevice			*vdevice;
 	VirtTarget 			*vtarget = NULL;
 	VirtTarget 			*vtarget = NULL;
 
 
 	shost_for_each_device(sdev, ioc->sh) {
 	shost_for_each_device(sdev, ioc->sh) {
-		if ((vdev = sdev->hostdata) == NULL)
+		if ((vdevice = sdev->hostdata) == NULL)
 			continue;
 			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;
 	return vtarget;
 }
 }
@@ -623,13 +555,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
 
 
 	DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
 	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;
 	return 1;
 }
 }
@@ -649,7 +575,7 @@ static void
 mptsas_target_reset_queue(MPT_ADAPTER *ioc,
 mptsas_target_reset_queue(MPT_ADAPTER *ioc,
     EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
     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;
 	VirtTarget *vtarget = NULL;
 	struct mptsas_target_reset_event *target_reset_list;
 	struct mptsas_target_reset_event *target_reset_list;
 	u8		id, channel;
 	u8		id, channel;
@@ -696,7 +622,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
 static void
 static void
 mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
 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 list_head *head = &hd->target_reset_list;
 	struct mptsas_target_reset_event *target_reset_list;
 	struct mptsas_target_reset_event *target_reset_list;
 	struct mptsas_hotplug_event *ev;
 	struct mptsas_hotplug_event *ev;
@@ -813,7 +739,7 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
 
 	if (!ioc->sh || !ioc->sh->hostdata)
 	if (!ioc->sh || !ioc->sh->hostdata)
 		goto out;
 		goto out;
-	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	hd = shost_priv(ioc->sh);
 	if (!hd->ioc)
 	if (!hd->ioc)
 		goto out;
 		goto out;
 
 
@@ -913,19 +839,20 @@ static int
 mptsas_target_alloc(struct scsi_target *starget)
 mptsas_target_alloc(struct scsi_target *starget)
 {
 {
 	struct Scsi_Host *host = dev_to_shost(&starget->dev);
 	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;
 	VirtTarget		*vtarget;
 	u8			id, channel;
 	u8			id, channel;
 	struct sas_rphy		*rphy;
 	struct sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
 	struct mptsas_portinfo	*p;
 	int 			 i;
 	int 			 i;
+	MPT_ADAPTER		*ioc = hd->ioc;
 
 
 	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
 	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
 	if (!vtarget)
 	if (!vtarget)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	vtarget->starget = starget;
 	vtarget->starget = starget;
-	vtarget->ioc_id = hd->ioc->id;
+	vtarget->ioc_id = ioc->id;
 	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
 	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
 	id = starget->id;
 	id = starget->id;
 	channel = 0;
 	channel = 0;
@@ -934,15 +861,15 @@ mptsas_target_alloc(struct scsi_target *starget)
 	 * RAID volumes placed beyond the last expected port.
 	 * RAID volumes placed beyond the last expected port.
 	 */
 	 */
 	if (starget->channel == MPTSAS_RAID_CHANNEL) {
 	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;
 		goto out;
 	}
 	}
 
 
 	rphy = dev_to_rphy(starget->dev.parent);
 	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++) {
 		for (i = 0; i < p->num_phys; i++) {
 			if (p->phy_info[i].attached.sas_address !=
 			if (p->phy_info[i].attached.sas_address !=
 					rphy->identify.sas_address)
 					rphy->identify.sas_address)
@@ -954,18 +881,18 @@ mptsas_target_alloc(struct scsi_target *starget)
 			/*
 			/*
 			 * Exposing hidden raid components
 			 * 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);
 						channel, id);
 				vtarget->tflags |=
 				vtarget->tflags |=
 				    MPT_TARGET_FLAGS_RAID_COMPONENT;
 				    MPT_TARGET_FLAGS_RAID_COMPONENT;
 				p->phy_info[i].attached.phys_disk_num = id;
 				p->phy_info[i].attached.phys_disk_num = id;
 			}
 			}
-			mutex_unlock(&hd->ioc->sas_topology_mutex);
+			mutex_unlock(&ioc->sas_topology_mutex);
 			goto out;
 			goto out;
 		}
 		}
 	}
 	}
-	mutex_unlock(&hd->ioc->sas_topology_mutex);
+	mutex_unlock(&ioc->sas_topology_mutex);
 
 
 	kfree(vtarget);
 	kfree(vtarget);
 	return -ENXIO;
 	return -ENXIO;
@@ -981,10 +908,11 @@ static void
 mptsas_target_destroy(struct scsi_target *starget)
 mptsas_target_destroy(struct scsi_target *starget)
 {
 {
 	struct Scsi_Host *host = dev_to_shost(&starget->dev);
 	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 sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
 	struct mptsas_portinfo	*p;
 	int 			 i;
 	int 			 i;
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	if (!starget->hostdata)
 	if (!starget->hostdata)
 		return;
 		return;
@@ -993,7 +921,7 @@ mptsas_target_destroy(struct scsi_target *starget)
 		goto out;
 		goto out;
 
 
 	rphy = dev_to_rphy(starget->dev.parent);
 	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++) {
 		for (i = 0; i < p->num_phys; i++) {
 			if (p->phy_info[i].attached.sas_address !=
 			if (p->phy_info[i].attached.sas_address !=
 					rphy->identify.sas_address)
 					rphy->identify.sas_address)
@@ -1013,61 +941,62 @@ static int
 mptsas_slave_alloc(struct scsi_device *sdev)
 mptsas_slave_alloc(struct scsi_device *sdev)
 {
 {
 	struct Scsi_Host	*host = sdev->host;
 	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 sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
 	struct mptsas_portinfo	*p;
-	VirtDevice		*vdev;
+	VirtDevice		*vdevice;
 	struct scsi_target 	*starget;
 	struct scsi_target 	*starget;
 	int 			i;
 	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",
 		printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
-				hd->ioc->name, sizeof(VirtDevice));
+				ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 	starget = scsi_target(sdev);
 	starget = scsi_target(sdev);
-	vdev->vtarget = starget->hostdata;
+	vdevice->vtarget = starget->hostdata;
 
 
 	if (sdev->channel == MPTSAS_RAID_CHANNEL)
 	if (sdev->channel == MPTSAS_RAID_CHANNEL)
 		goto out;
 		goto out;
 
 
 	rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
 	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++) {
 		for (i = 0; i < p->num_phys; i++) {
 			if (p->phy_info[i].attached.sas_address !=
 			if (p->phy_info[i].attached.sas_address !=
 					rphy->identify.sas_address)
 					rphy->identify.sas_address)
 				continue;
 				continue;
-			vdev->lun = sdev->lun;
+			vdevice->lun = sdev->lun;
 			/*
 			/*
 			 * Exposing hidden raid components
 			 * 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.channel,
 			    p->phy_info[i].attached.id))
 			    p->phy_info[i].attached.id))
 				sdev->no_uld_attach = 1;
 				sdev->no_uld_attach = 1;
-			mutex_unlock(&hd->ioc->sas_topology_mutex);
+			mutex_unlock(&ioc->sas_topology_mutex);
 			goto out;
 			goto out;
 		}
 		}
 	}
 	}
-	mutex_unlock(&hd->ioc->sas_topology_mutex);
+	mutex_unlock(&ioc->sas_topology_mutex);
 
 
-	kfree(vdev);
+	kfree(vdevice);
 	return -ENXIO;
 	return -ENXIO;
 
 
  out:
  out:
-	vdev->vtarget->num_luns++;
-	sdev->hostdata = vdev;
+	vdevice->vtarget->num_luns++;
+	sdev->hostdata = vdevice;
 	return 0;
 	return 0;
 }
 }
 
 
 static int
 static int
 mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 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;
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		done(SCpnt);
 		return 0;
 		return 0;
@@ -1239,10 +1168,8 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
 	/* process the completed Reply Message Frame */
 	/* process the completed Reply Message Frame */
 	reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
 	reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
 	if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
 	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;
 		error = -ENXIO;
 		goto out_unlock;
 		goto out_unlock;
 	}
 	}
@@ -1328,16 +1255,16 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	u64 sas_address = 0;
 	u64 sas_address = 0;
 
 
 	if (!rsp) {
 	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;
 		return -EINVAL;
 	}
 	}
 
 
 	/* do we need to support multiple segments? */
 	/* do we need to support multiple segments? */
 	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
 	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;
 		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);
 	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
 	if (!timeleft) {
 	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 */
 		/* On timeout reset the board */
 		mpt_HardResetHandler(ioc, CAN_SLEEP);
 		mpt_HardResetHandler(ioc, CAN_SLEEP);
 		ret = -ETIMEDOUT;
 		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));
 		memcpy(req->sense, smprep, sizeof(*smprep));
 		req->sense_len = sizeof(*smprep);
 		req->sense_len = sizeof(*smprep);
 	} else {
 	} 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;
 		ret = -ENXIO;
 	}
 	}
 unmap:
 unmap:
@@ -2062,12 +1989,12 @@ static int mptsas_probe_one_phy(struct device *dev,
 				goto out;
 				goto out;
 			}
 			}
 			mptsas_set_port(ioc, phy_info, port);
 			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",
 			    "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);
 		sas_port_add_phy(port, phy_info->phy);
 		phy_info->sas_port_add_phy = 0;
 		phy_info->sas_port_add_phy = 0;
 	}
 	}
@@ -2369,8 +2296,9 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
 					expander_sas_address)
 					expander_sas_address)
 					continue;
 					continue;
 				dsaswideprintk(ioc,
 				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);
 				sas_port_delete(port);
 				mptsas_port_delete(ioc, phy_info->port_details);
 				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);
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
 		if (!ev) {
-			printk(KERN_WARNING "mptsas: lost hotplug event\n");
+			printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
 			goto out;
 			goto out;
 		}
 		}
 
 
@@ -2754,8 +2682,8 @@ mptsas_hotplug_work(struct work_struct *work)
 		printk(MYIOC_s_INFO_FMT
 		printk(MYIOC_s_INFO_FMT
 		       "removing %s device, channel %d, id %d, phy %d\n",
 		       "removing %s device, channel %d, id %d, phy %d\n",
 		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
 		       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);
 		sas_port_delete(port);
 		mptsas_port_delete(ioc, phy_info->port_details);
 		mptsas_port_delete(ioc, phy_info->port_details);
 		break;
 		break;
@@ -2796,8 +2724,8 @@ mptsas_hotplug_work(struct work_struct *work)
 
 
 			if (!vtarget) {
 			if (!vtarget) {
 				dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
 				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;
 				break;
 			}
 			}
 			/*
 			/*
@@ -2930,7 +2858,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
 	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
 		if (!ev) {
-			printk(KERN_WARNING "mptsas: lost hotplug event\n");
+			printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
 			break;
 			break;
 		}
 		}
 
 
@@ -2989,7 +2917,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
 
 
 	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 	if (!ev) {
 	if (!ev) {
-		printk(KERN_WARNING "mptsas: lost hotplug event\n");
+		printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
 		return;
 		return;
 	}
 	}
 
 
@@ -3288,20 +3216,22 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		sh->sg_tablesize = numSGE;
 		sh->sg_tablesize = numSGE;
 	}
 	}
 
 
-	hd = (MPT_SCSI_HOST *) sh->hostdata;
+	hd = shost_priv(sh);
 	hd->ioc = ioc;
 	hd->ioc = ioc;
 
 
 	/* SCSI needs scsi_cmnd lookup table!
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 * (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;
 		error = -ENOMEM;
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		goto out_mptsas_probe;
 		goto out_mptsas_probe;
 	}
 	}
+	spin_lock_init(&ioc->scsi_lookup_lock);
 
 
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
-		 ioc->name, hd->ScsiLookup));
+		 ioc->name, ioc->ScsiLookup));
 
 
 	/* Clear the TM flags
 	/* 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);
 	error = scsi_add_host(sh, &ioc->pcidev->dev);
 	if (error) {
 	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;
 		goto out_mptsas_probe;
 	}
 	}
 
 

+ 158 - 0
drivers/message/fusion/mptsas.h

@@ -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

+ 355 - 288
drivers/message/fusion/mptscsih.c

@@ -1,9 +1,9 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptscsih.c
  *  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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */
@@ -80,6 +80,10 @@ MODULE_VERSION(my_VERSION);
 /*
 /*
  *  Other private/forward protos...
  *  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);
 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);
 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);
 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 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_pending_wait(MPT_SCSI_HOST * hd);
 static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 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);
 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;
 	int chain_idx;
 
 
 	dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
 	dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
-			ioc->name));
+	    ioc->name));
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	if (!list_empty(&ioc->FreeChainQ)) {
 	if (!list_empty(&ioc->FreeChainQ)) {
 		int offset;
 		int offset;
@@ -203,13 +206,14 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
 		offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
 		offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
 		chain_idx = offset / ioc->req_sz;
 		chain_idx = offset / ioc->req_sz;
 		rc = SUCCESS;
 		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 {
 	} else {
 		rc = FAILED;
 		rc = FAILED;
 		chain_idx = MPT_HOST_NO_CHAIN;
 		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);
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 
@@ -419,8 +423,8 @@ nextSGEset:
 		 *   out the Address and Flags fields.
 		 *   out the Address and Flags fields.
 		 */
 		 */
 		chainSge = (char *) psge;
 		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
 		/* Start the SGE for the next buffer
 		 */
 		 */
@@ -428,8 +432,8 @@ nextSGEset:
 		sgeOffset = 0;
 		sgeOffset = 0;
 		sg_done = 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
 		/* 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);
 	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);
 	    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",
 	    "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);
 	    pScsiReply->SCSIState);
 
 
 	if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
 	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];
 		asc = sc->sense_buffer[12];
 		ascq = sc->sense_buffer[13];
 		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 &&
 	if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
 	    pScsiReply->ResponseInfo)
 	    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
 #endif
 
 
@@ -645,11 +647,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 	SCSIIORequest_t	*pScsiReq;
 	SCSIIORequest_t	*pScsiReq;
 	SCSIIOReply_t	*pScsiReply;
 	SCSIIOReply_t	*pScsiReply;
 	u16		 req_idx, req_idx_MR;
 	u16		 req_idx, req_idx_MR;
-	VirtDevice	 *vdev;
+	VirtDevice	 *vdevice;
 	VirtTarget	 *vtarget;
 	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 = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 	req_idx_MR = (mr != NULL) ?
 	req_idx_MR = (mr != NULL) ?
 	    le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
 	    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
 		printk (MYIOC_s_ERR_FMT
 		    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
 		    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
 		    ioc->name, req_idx, req_idx_MR, mf, mr,
 		    ioc->name, req_idx, req_idx_MR, mf, mr,
-		    hd->ScsiLookup[req_idx_MR]);
+		    mptscsih_get_scsi_lookup(ioc, req_idx_MR));
 		return 0;
 		return 0;
 	}
 	}
 
 
-	sc = hd->ScsiLookup[req_idx];
-	hd->ScsiLookup[req_idx] = NULL;
+	sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
 	if (sc == NULL) {
 	if (sc == NULL) {
 		MPIHeader_t *hdr = (MPIHeader_t *)mf;
 		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 &&
 		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
 		    pScsiReply->ResponseInfo) {
 		    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->host->host_no, sc->device->channel,
 			sc->device->id, sc->device->lun,
 			sc->device->id, sc->device->lun,
 			le32_to_cpu(pScsiReply->ResponseInfo));
 			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)
 			if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
 				hd->sel_timeout[pScsiReq->TargetID]++;
 				hd->sel_timeout[pScsiReq->TargetID]++;
 
 
-			vdev = sc->device->hostdata;
-			if (!vdev)
+			vdevice = sc->device->hostdata;
+			if (!vdevice)
 				break;
 				break;
-			vtarget = vdev->vtarget;
+			vtarget = vdevice->vtarget;
 			if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
 			if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
 				mptscsih_issue_sep_command(ioc, vtarget,
 				mptscsih_issue_sep_command(ioc, vtarget,
 				    MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
 				    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;
 				sc->result=DID_SOFT_ERROR << 16;
 			else /* Sufficient data transfer occurred */
 			else /* Sufficient data transfer occurred */
 				sc->result = (DID_OK << 16) | scsi_status;
 				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",
 			    "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;
 			break;
 
 
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
 		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
 			/* Report Queue Full
 			 */
 			 */
@@ -969,48 +971,32 @@ static void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
 {
 	MPT_ADAPTER *ioc = hd->ioc;
 	MPT_ADAPTER *ioc = hd->ioc;
-	struct scsi_cmnd	*SCpnt;
-	MPT_FRAME_HDR	*mf;
+	struct scsi_cmnd *sc;
+	SCSIIORequest_t	*mf = NULL;
 	int		 ii;
 	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;
 	SCSIIORequest_t	*mf = NULL;
 	int		 ii;
 	int		 ii;
-	int		 max = hd->ioc->req_depth;
 	struct scsi_cmnd *sc;
 	struct scsi_cmnd *sc;
 	struct scsi_lun  lun;
 	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)
 			if (mf == NULL)
 				continue;
 				continue;
 			/* If the device is a hidden raid component, then its
 			/* 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))
 			    memcmp(lun.scsi_lun, mf->LUN, 8))
 				continue;
 				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)
 			if ((unsigned char *)mf != sc->host_scribble)
 				continue;
 				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);
 			scsi_dma_unmap(sc);
 			sc->host_scribble = NULL;
 			sc->host_scribble = NULL;
 			sc->result = DID_NO_CONNECT << 16;
 			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);
 			   vdevice->vtarget->id, sc, mf, ii);
 			sc->scsi_done(sc);
 			sc->scsi_done(sc);
+			spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
 		}
 		}
 	}
 	}
+	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 	return;
 	return;
 }
 }
 
 
@@ -1097,17 +1083,18 @@ mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSI
 {
 {
 	long time = jiffies;
 	long time = jiffies;
 	MPT_SCSI_HOST		*hd;
 	MPT_SCSI_HOST		*hd;
+	MPT_ADAPTER	*ioc;
 
 
 	if (sc->device == NULL)
 	if (sc->device == NULL)
 		return;
 		return;
 	if (sc->device->host == NULL)
 	if (sc->device->host == NULL)
 		return;
 		return;
-	if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
+	if ((hd = shost_priv(sc->device->host)) == NULL)
 		return;
 		return;
-
+	ioc = hd->ioc;
 	if (time - hd->last_queue_full > 10 * HZ) {
 	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;
 		hd->last_queue_full = time;
 	}
 	}
 }
 }
@@ -1134,28 +1121,28 @@ mptscsih_remove(struct pci_dev *pdev)
 
 
 	scsi_remove_host(host);
 	scsi_remove_host(host);
 
 
-	if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
+	if((hd = shost_priv(host)) == NULL)
 		return;
 		return;
 
 
 	mptscsih_shutdown(pdev);
 	mptscsih_shutdown(pdev);
 
 
 	sz1=0;
 	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",
 	    "Free'd ScsiLookup (%d) memory\n",
-	    hd->ioc->name, sz1));
+	    ioc->name, sz1));
 
 
 	kfree(hd->info_kbuf);
 	kfree(hd->info_kbuf);
 
 
 	/* NULL the Scsi_Host pointer
 	/* NULL the Scsi_Host pointer
 	 */
 	 */
-	hd->ioc->sh = NULL;
+	ioc->sh = NULL;
 
 
 	scsi_host_put(host);
 	scsi_host_put(host);
 
 
@@ -1171,15 +1158,6 @@ mptscsih_remove(struct pci_dev *pdev)
 void
 void
 mptscsih_shutdown(struct pci_dev *pdev)
 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
 #ifdef CONFIG_PM
@@ -1225,7 +1203,7 @@ mptscsih_info(struct Scsi_Host *SChost)
 	MPT_SCSI_HOST *h;
 	MPT_SCSI_HOST *h;
 	int size = 0;
 	int size = 0;
 
 
-	h = (MPT_SCSI_HOST *)SChost->hostdata;
+	h = shost_priv(SChost);
 
 
 	if (h) {
 	if (h) {
 		if (h->info_kbuf == NULL)
 		if (h->info_kbuf == NULL)
@@ -1319,7 +1297,7 @@ int
 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 			int length, int func)
 			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;
 	MPT_ADAPTER	*ioc = hd->ioc;
 	int size = 0;
 	int size = 0;
 
 
@@ -1358,7 +1336,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	MPT_SCSI_HOST		*hd;
 	MPT_SCSI_HOST		*hd;
 	MPT_FRAME_HDR		*mf;
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
 	SCSIIORequest_t		*pScsiReq;
-	VirtDevice		*vdev = SCpnt->device->hostdata;
+	VirtDevice		*vdevice = SCpnt->device->hostdata;
 	int	 lun;
 	int	 lun;
 	u32	 datalen;
 	u32	 datalen;
 	u32	 scsictl;
 	u32	 scsictl;
@@ -1368,7 +1346,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	int	 ii;
 	int	 ii;
 	MPT_ADAPTER *ioc;
 	MPT_ADAPTER *ioc;
 
 
-	hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+	hd = shost_priv(SCpnt->device->host);
 	ioc = hd->ioc;
 	ioc = hd->ioc;
 	lun = SCpnt->device->lun;
 	lun = SCpnt->device->lun;
 	SCpnt->scsi_done = done;
 	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...
 	 *  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",
 		dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
 				ioc->name));
 				ioc->name));
 		return SCSI_MLQUEUE_HOST_BUSY;
 		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,
 	/* Default to untagged. Once a target structure has been allocated,
 	 * use the Inquiry data to determine if device supports tagged.
 	 * 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)) {
 	    && (SCpnt->device->tagged_supported)) {
 		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
 		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
 	} else {
 	} 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
 	/* 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;
 	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;
 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
 	else
 	else
 		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
 		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);
 	pScsiReq->DataLength = cpu_to_le32(datalen);
 
 
 	/* SenseBuffer low address */
 	/* 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));
 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
 
 	/* Now add the SG list
 	/* Now add the SG list
@@ -1465,23 +1443,22 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 			(dma_addr_t) -1);
 			(dma_addr_t) -1);
 	} else {
 	} else {
 		/* Add a 32 or 64 bit SGE */
 		/* 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;
 			goto fail;
 	}
 	}
 
 
 	SCpnt->host_scribble = (unsigned char *)mf;
 	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",
 	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
 			ioc->name, SCpnt, mf, my_idx));
 			ioc->name, SCpnt, mf, my_idx));
-	DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf)
+	DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
 	return 0;
 	return 0;
 
 
  fail:
  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;
 	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 (mptscsih_tm_pending_wait(hd) == FAILED) {
 		if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
 		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",
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			   ioc->name, hd->tmPending));
 			   ioc->name, hd->tmPending));
 			return FAILED;
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
 		} 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) "
 				"reset: Timed out waiting for last TM (%d) "
 				"to complete! \n", ioc->name,
 				"to complete! \n", ioc->name,
 				hd->tmPending));
 				hd->tmPending));
 			return FAILED;
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
 		} 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",
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			  ioc->name, hd->tmPending));
 			  ioc->name, hd->tmPending));
 			return FAILED;
 			return FAILED;
 		}
 		}
 	} else {
 	} else {
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
 		hd->tmPending |=  (1 << type);
 		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) {
 	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
 		printk(MYIOC_s_WARN_FMT
 		printk(MYIOC_s_WARN_FMT
 			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
 			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
 			ioc->name, type, ioc_raw_state);
 			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)
 		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;
 		return FAILED;
 	}
 	}
 
 
@@ -1680,16 +1657,17 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i
 	SCSITaskMgmt_t	*pScsiTm;
 	SCSITaskMgmt_t	*pScsiTm;
 	int		 ii;
 	int		 ii;
 	int		 retval;
 	int		 retval;
+	MPT_ADAPTER 	*ioc = hd->ioc;
 
 
 	/* Return Fail to calling function if no message frames available.
 	/* 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;
 		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
 	/* 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;
 	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);
 	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) {
 	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;
 		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
 	 * 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->tmPending = 0;
 	hd->tmState = TM_STATE_NONE;
 	hd->tmState = TM_STATE_NONE;
 	return FAILED;
 	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 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->result = DID_RESET << 16;
 		SCpnt->scsi_done(SCpnt);
 		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;
 		return FAILED;
 	}
 	}
 
 
@@ -1812,8 +1796,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
 
 	vdevice = SCpnt->device->hostdata;
 	vdevice = SCpnt->device->hostdata;
 	if (!vdevice || !vdevice->vtarget) {
 	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->result = DID_NO_CONNECT << 16;
 		SCpnt->scsi_done(SCpnt);
 		SCpnt->scsi_done(SCpnt);
 		retval = 0;
 		retval = 0;
@@ -1823,8 +1808,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	/* Task aborts are not supported for hidden raid components.
 	/* Task aborts are not supported for hidden raid components.
 	 */
 	 */
 	if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
 	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;
 		SCpnt->result = DID_RESET << 16;
 		retval = FAILED;
 		retval = FAILED;
 		goto out;
 		goto out;
@@ -1832,12 +1818,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
 
 	/* Find this command
 	/* 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.
 		/* Cmd not found in ScsiLookup.
 		 * Do OS callback.
 		 * Do OS callback.
 		 */
 		 */
 		SCpnt->result = DID_RESET << 16;
 		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,
 		   "Command not in the active list! (sc=%p)\n", ioc->name,
 		   SCpnt));
 		   SCpnt));
 		retval = 0;
 		retval = 0;
@@ -1859,7 +1845,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	 *	 swap it here either.  It is an opaque cookie to
 	 *	 swap it here either.  It is an opaque cookie to
 	 *	 the controller, so it does not matter. -DaveM
 	 *	 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;
 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
 
 
 	hd->abortSCpnt = SCpnt;
 	hd->abortSCpnt = SCpnt;
@@ -1868,7 +1854,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
 	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
 	    ctx2abort, mptscsih_get_tm_timeout(ioc));
 	    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)
 	    SCpnt->serial_number == sn)
 		retval = FAILED;
 		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 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;
 		return FAILED;
 	}
 	}
 
 
@@ -1959,14 +1945,14 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
 {
 	MPT_SCSI_HOST	*hd;
 	MPT_SCSI_HOST	*hd;
 	int		 retval;
 	int		 retval;
-	VirtDevice	 *vdev;
+	VirtDevice	 *vdevice;
 	MPT_ADAPTER	*ioc;
 	MPT_ADAPTER	*ioc;
 
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	/* 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;
 		return FAILED;
 	}
 	}
 
 
@@ -1978,9 +1964,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 	if (hd->timeouts < -1)
 	if (hd->timeouts < -1)
 		hd->timeouts++;
 		hd->timeouts++;
 
 
-	vdev = SCpnt->device->hostdata;
+	vdevice = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 	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",
 	printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
 	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2008,9 +1994,9 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 	MPT_ADAPTER	*ioc;
 	MPT_ADAPTER	*ioc;
 
 
 	/*  If we can't locate the host to reset, then we failed. */
 	/*  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;
 		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
 	/*  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.
 	 *  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;
 		retval = FAILED;
 	} else {
 	} else {
 		/*  Make sure TM pending is cleared and TM state is set to
 		/*  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;
 	unsigned long  flags;
 	int            loop_count = 4 * 10;  /* Wait 10 seconds */
 	int            loop_count = 4 * 10;  /* Wait 10 seconds */
 	int            status = FAILED;
 	int            status = FAILED;
+	MPT_ADAPTER	*ioc = hd->ioc;
 
 
 	do {
 	do {
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
 		if (hd->tmState == TM_STATE_NONE) {
 		if (hd->tmState == TM_STATE_NONE) {
 			hd->tmState = TM_STATE_IN_PROGRESS;
 			hd->tmState = TM_STATE_IN_PROGRESS;
 			hd->tmPending = 1;
 			hd->tmPending = 1;
-			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 			status = SUCCESS;
 			status = SUCCESS;
 			break;
 			break;
 		}
 		}
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		msleep(250);
 		msleep(250);
 	} while (--loop_count);
 	} while (--loop_count);
 
 
@@ -2082,15 +2069,16 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
 	unsigned long  flags;
 	unsigned long  flags;
 	int            loop_count = 4 * timeout;
 	int            loop_count = 4 * timeout;
 	int            status = FAILED;
 	int            status = FAILED;
+	MPT_ADAPTER	*ioc = hd->ioc;
 
 
 	do {
 	do {
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
 		if(hd->tmPending == 0) {
 		if(hd->tmPending == 0) {
 			status = SUCCESS;
 			status = SUCCESS;
- 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 			break;
 			break;
 		}
 		}
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		msleep(250);
 		msleep(250);
 	} while (--loop_count);
 	} while (--loop_count);
 
 
@@ -2172,7 +2160,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 		return 1;
 		return 1;
 	}
 	}
 
 
-	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	hd = shost_priv(ioc->sh);
 	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
 	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
 	pScsiTmReq = (SCSITaskMgmt_t*)mf;
 	pScsiTmReq = (SCSITaskMgmt_t*)mf;
 	tmType = pScsiTmReq->TaskType;
 	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 ||
 		if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
 		    hd->cmdPtr)
 		    hd->cmdPtr)
 			if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
 			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;
 		break;
 
 
 	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
 	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2366,7 +2354,7 @@ void
 mptscsih_slave_destroy(struct scsi_device *sdev)
 mptscsih_slave_destroy(struct scsi_device *sdev)
 {
 {
 	struct Scsi_Host	*host = sdev->host;
 	struct Scsi_Host	*host = sdev->host;
-	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
+	MPT_SCSI_HOST		*hd = shost_priv(host);
 	VirtTarget		*vtarget;
 	VirtTarget		*vtarget;
 	VirtDevice		*vdevice;
 	VirtDevice		*vdevice;
 	struct scsi_target 	*starget;
 	struct scsi_target 	*starget;
@@ -2393,16 +2381,17 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
 int
 int
 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 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;
 	VirtTarget 		*vtarget;
 	struct scsi_target 	*starget;
 	struct scsi_target 	*starget;
 	int			max_depth;
 	int			max_depth;
 	int			tagged;
 	int			tagged;
+	MPT_ADAPTER		*ioc = hd->ioc;
 
 
 	starget = scsi_target(sdev);
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 	vtarget = starget->hostdata;
 
 
-	if (hd->ioc->bus_type == SPI) {
+	if (ioc->bus_type == SPI) {
 		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
 		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
 			max_depth = 1;
 			max_depth = 1;
 		else if (sdev->type == TYPE_DISK &&
 		else if (sdev->type == TYPE_DISK &&
@@ -2437,19 +2426,20 @@ mptscsih_slave_configure(struct scsi_device *sdev)
 	VirtTarget		*vtarget;
 	VirtTarget		*vtarget;
 	VirtDevice		*vdevice;
 	VirtDevice		*vdevice;
 	struct scsi_target 	*starget;
 	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);
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 	vtarget = starget->hostdata;
 	vdevice = sdev->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",
 		"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",
 		    "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));
 		    sdev->ppr, sdev->inquiry_len));
 
 
 	if (sdev->id > sh->max_id) {
 	if (sdev->id > sh->max_id) {
@@ -2461,21 +2451,21 @@ mptscsih_slave_configure(struct scsi_device *sdev)
 	vdevice->configured_lun = 1;
 	vdevice->configured_lun = 1;
 	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 	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",
 		"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",
 		    "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
-		    hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+		    ioc->name, vtarget->negoFlags, vtarget->maxOffset,
 		    vtarget->minSyncFactor));
 		    vtarget->minSyncFactor));
 
 
 slave_configure_exit:
 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",
 		"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));
 		sdev->ordered_tags));
 
 
 	return 0;
 	return 0;
@@ -2494,14 +2484,15 @@ slave_configure_exit:
 static void
 static void
 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
 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;
 	SCSIIORequest_t	*pReq;
 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
+	MPT_ADAPTER 	*ioc = hd->ioc;
 
 
 	/* Get target structure
 	/* Get target structure
 	 */
 	 */
 	pReq = (SCSIIORequest_t *) mf;
 	pReq = (SCSIIORequest_t *) mf;
-	vdev = sc->device->hostdata;
+	vdevice = sc->device->hostdata;
 
 
 	if (sense_count) {
 	if (sense_count) {
 		u8 *sense_data;
 		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. */
 		/* Copy the sense received into the scsi command block. */
 		req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 		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));
 		memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
 
 
 		/* Log SMART data (asc = 0x5D, non-IM case only) if required.
 		/* 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;
 				int idx;
-				MPT_ADAPTER *ioc = hd->ioc;
 
 
 				idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
 				idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
 				ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
 				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->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
 
 
 				ioc->eventContext++;
 				ioc->eventContext++;
-				if (hd->ioc->pcidev->vendor ==
+				if (ioc->pcidev->vendor ==
 				    PCI_VENDOR_ID_IBM) {
 				    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;
 					    MPT_TARGET_FLAGS_LED_ON;
 				}
 				}
 			}
 			}
 		}
 		}
 	} else {
 	} 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;
 	MPT_SCSI_HOST	*hd;
 	unsigned long	 flags;
 	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
 	/* If a FW reload request arrives after base installed but
 	 * before all scsi hosts have been attached, then an alt_ioc
 	 * before all scsi hosts have been attached, then an alt_ioc
 	 * may have a NULL sh pointer.
 	 * 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;
 		return 0;
 	else
 	else
-		hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+		hd = shost_priv(ioc->sh);
 
 
 	if (reset_phase == MPT_IOC_SETUP_RESET) {
 	if (reset_phase == MPT_IOC_SETUP_RESET) {
 		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
 		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.
 		 * Init all control structures.
 		 */
 		 */
 
 
-		/* ScsiLookup initialization
-		 */
-		for (ii=0; ii < hd->ioc->req_depth; ii++)
-			hd->ScsiLookup[ii] = NULL;
-
 		/* 2. Chain Buffer initialization
 		/* 2. Chain Buffer initialization
 		 */
 		 */
 
 
@@ -2675,7 +2739,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 			ioc->name, event));
 			ioc->name, event));
 
 
 	if (ioc->sh == NULL ||
 	if (ioc->sh == NULL ||
-		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+		((hd = shost_priv(ioc->sh)) == NULL))
 		return 1;
 		return 1;
 
 
 	switch (event) {
 	switch (event) {
@@ -2713,7 +2777,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 	case MPI_EVENT_STATE_CHANGE:			/* 02 */
 	case MPI_EVENT_STATE_CHANGE:			/* 02 */
 	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
 	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
 	default:
 	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;
 		break;
 	}
 	}
 
 
@@ -2753,7 +2818,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 	int		 completionCode;
 	int		 completionCode;
 	u16		 req_idx;
 	u16		 req_idx;
 
 
-	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+	hd = shost_priv(ioc->sh);
 
 
 	if ((mf == NULL) ||
 	if ((mf == NULL) ||
 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
 	    (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);
 	del_timer(&hd->timer);
 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 	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;
 	pReq = (SCSIIORequest_t *) mf;
 
 
 	if (mf != hd->cmdPtr) {
 	if (mf != hd->cmdPtr) {
 		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
 		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;
 	hd->cmdPtr = NULL;
 
 
 	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
 	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 = &hd->localReply;
 	hd->pLocal->scsiStatus = 0;
 	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;
 				completionCode = MPT_SCANDV_SENSE;
 				hd->pLocal->scsiStatus = scsi_status;
 				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));
 					(req_idx * MPT_SENSE_BUFFER_ALLOC));
 
 
 				sz = min_t(int, pReq->SenseBufferLength,
 				sz = min_t(int, pReq->SenseBufferLength,
 							SCSI_STD_SENSE_BYTES);
 							SCSI_STD_SENSE_BYTES);
 				memcpy(hd->pLocal->sense, sense_data, sz);
 				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) {
 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
 				if (pReq->CDB[0] == INQUIRY)
 				if (pReq->CDB[0] == INQUIRY)
 					completionCode = MPT_SCANDV_ISSUE_SENSE;
 					completionCode = MPT_SCANDV_ISSUE_SENSE;
@@ -2906,8 +2971,9 @@ void
 mptscsih_timer_expired(unsigned long data)
 mptscsih_timer_expired(unsigned long data)
 {
 {
 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) 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) {
 	if (hd->cmdPtr) {
 		MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
 		MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
@@ -2921,13 +2987,13 @@ mptscsih_timer_expired(unsigned long data)
 			 */
 			 */
 		} else {
 		} else {
 			/* Perform a FW reload */
 			/* 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 {
 	} else {
 		/* This should NEVER happen */
 		/* 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.
 	/* 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.
 	 * The FW will reply to all outstanding commands, callback will finish cleanup.
 	 * Hard reset clean-up will free all resources.
 	 * 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;
 	return;
 }
 }
@@ -2973,11 +3039,12 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 	char		 cmdLen;
 	char		 cmdLen;
 	char		 CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 	char		 CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 	char		 cmd = io->cmd;
 	char		 cmd = io->cmd;
+	MPT_ADAPTER 	*ioc = hd->ioc;
 
 
 	in_isr = in_interrupt();
 	in_isr = in_interrupt();
 	if (in_isr) {
 	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;
 		return -EPERM;
 	}
 	}
 
 
@@ -3078,9 +3145,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
 
 	/* Get and Populate a free Frame
 	/* 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;
 		return -EBUSY;
 	}
 	}
 
 
@@ -3119,19 +3186,19 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
 
 	if (cmd == REQUEST_SENSE) {
 	if (cmd == REQUEST_SENSE) {
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 		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++)
 	for (ii=0; ii < 16; ii++)
 		pScsiReq->CDB[ii] = CDB[ii];
 		pScsiReq->CDB[ii] = CDB[ii];
 
 
 	pScsiReq->DataLength = cpu_to_le32(io->size);
 	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));
 					   + (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) {
 	if (dir == MPI_SCSIIO_CONTROL_READ) {
 		mpt_add_sge((char *) &pScsiReq->SGL,
 		mpt_add_sge((char *) &pScsiReq->SGL,
@@ -3166,7 +3233,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 	hd->cmdPtr = mf;
 	hd->cmdPtr = mf;
 
 
 	add_timer(&hd->timer);
 	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);
 	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
 
 	if (hd->pLocal) {
 	if (hd->pLocal) {
@@ -3182,8 +3249,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 	} else {
 	} else {
 		rc = -EFAULT;
 		rc = -EFAULT;
 		/* This should never happen. */
 		/* 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;
 	return rc;
@@ -3235,7 +3302,7 @@ static ssize_t
 mptscsih_version_fw_show(struct class_device *cdev, char *buf)
 mptscsih_version_fw_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
 	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)
 mptscsih_version_bios_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
 	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)
 mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
 	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)
 mptscsih_version_product_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
 	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)
 mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%02xh\n",
 	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)
 mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
 	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)
 mptscsih_board_name_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
 	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)
 mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
 	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)
 mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
 	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)
 mptscsih_io_delay_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
 	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)
 mptscsih_device_delay_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
 	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)
 mptscsih_debug_level_show(struct class_device *cdev, char *buf)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
 	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)
 								size_t count)
 {
 {
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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;
 	MPT_ADAPTER *ioc = hd->ioc;
 	int val = 0;
 	int val = 0;
 
 

+ 2 - 2
drivers/message/fusion/mptscsih.h

@@ -3,9 +3,9 @@
  *      High performance SCSI / Fibre Channel SCSI Host device driver.
  *      High performance SCSI / Fibre Channel SCSI Host device driver.
  *      For use with PCI chip/adapter(s):
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
  *          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)
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  *
  */
  */

+ 114 - 97
drivers/message/fusion/mptspi.c

@@ -1,9 +1,9 @@
 /*
 /*
  *  linux/drivers/message/fusion/mptspi.c
  *  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)
  *  (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 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
  * 	mptspi_setTargetNegoParms  - Update the target negotiation parameters
@@ -107,7 +107,8 @@ static void
 mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
 mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
 			    struct scsi_device *sdev)
 			    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  id = (int) target->id;
 	int  nvram;
 	int  nvram;
 	u8 width = MPT_NARROW;
 	u8 width = MPT_NARROW;
@@ -138,9 +139,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
 				else {
 				else {
 					factor = MPT_ULTRA320;
 					factor = MPT_ULTRA320;
 					if (scsi_device_qas(sdev)) {
 					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;
 						noQas = 0;
 					}
 					}
 					if (sdev->type == TYPE_TAPE &&
 					if (sdev->type == TYPE_TAPE &&
@@ -227,8 +229,8 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
 		/* Disable QAS in a mixed configuration case
 		/* 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
 	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
 		"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);
 	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 
 
@@ -374,14 +376,15 @@ static int
 mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
 mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
 {
 {
 	int i, rc = 0;
 	int i, rc = 0;
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
-	if (!hd->ioc->raid_data.pIocPg2)
+	if (!ioc->raid_data.pIocPg2)
 		goto out;
 		goto out;
 
 
-	if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
+	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
 		goto out;
 		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;
 			rc = 1;
 			goto out;
 			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)
 static int mptspi_target_alloc(struct scsi_target *starget)
 {
 {
 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
 	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;
 	VirtTarget		*vtarget;
+	MPT_ADAPTER *ioc;
 
 
 	if (hd == NULL)
 	if (hd == NULL)
 		return -ENODEV;
 		return -ENODEV;
 
 
+	ioc = hd->ioc;
 	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
 	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
 	if (!vtarget)
 	if (!vtarget)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	vtarget->ioc_id = hd->ioc->id;
+	vtarget->ioc_id = ioc->id;
 	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
 	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
 	vtarget->id = (u8)starget->id;
 	vtarget->id = (u8)starget->id;
 	vtarget->channel = (u8)starget->channel;
 	vtarget->channel = (u8)starget->channel;
@@ -412,34 +417,34 @@ static int mptspi_target_alloc(struct scsi_target *starget)
 	starget->hostdata = vtarget;
 	starget->hostdata = vtarget;
 
 
 	if (starget->channel == 1) {
 	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;
 			return 0;
 		vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
 		vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
 		/* The real channel for this device is zero */
 		/* The real channel for this device is zero */
 		vtarget->channel = 0;
 		vtarget->channel = 0;
 		/* The actual physdisknum (for RAID passthrough) */
 		/* 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);
 		    starget->id);
 	}
 	}
 
 
 	if (starget->channel == 0 &&
 	if (starget->channel == 0 &&
 	    mptspi_is_raid(hd, starget->id)) {
 	    mptspi_is_raid(hd, starget->id)) {
 		vtarget->raidVolume = 1;
 		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));
 		    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_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
 		spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
 		spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
 	} else {
 	} 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;
 	spi_offset(starget) = 0;
 	mptspi_write_width(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 _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
 {
 {
 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
 	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 _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;
 	int size;
 	struct _x_config_parms cfg;
 	struct _x_config_parms cfg;
 	struct _CONFIG_PAGE_HEADER hdr;
 	struct _CONFIG_PAGE_HEADER hdr;
@@ -530,9 +535,10 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
 	size += 2048;
 	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;
 		return -EINVAL;
 	}
 	}
 
 
@@ -546,22 +552,22 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
 	memset(&cfg, 0, sizeof(cfg));
 	memset(&cfg, 0, sizeof(cfg));
 
 
 	cfg.cfghdr.hdr = &hdr;
 	cfg.cfghdr.hdr = &hdr;
-	cfg.physAddr = pg0_dma;
+	cfg.physAddr = spi_dev_pg0_dma;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 	cfg.dir = 0;
 	cfg.dir = 0;
 	cfg.pageAddr = starget->id;
 	cfg.pageAddr = starget->id;
 
 
 	if (mpt_config(ioc, &cfg)) {
 	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;
 		goto out_free;
 	}
 	}
 	err = 0;
 	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:
  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;
 	return err;
 }
 }
 
 
@@ -588,11 +594,11 @@ static u32 mptspi_getRP(struct scsi_target *starget)
 static void mptspi_read_parameters(struct scsi_target *starget)
 static void mptspi_read_parameters(struct scsi_target *starget)
 {
 {
 	int nego;
 	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_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
 	spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 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;
 	MpiRaidActionRequest_t	*pReq;
 	MPT_FRAME_HDR		*mf;
 	MPT_FRAME_HDR		*mf;
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	/* Get and Populate a free Frame
 	/* 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;
 		return -EAGAIN;
 	}
 	}
 	pReq = (MpiRaidActionRequest_t *)mf;
 	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_add_sge((char *)&pReq->ActionDataSGE,
 		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
 		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->pLocal = NULL;
 	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
 	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;
 	hd->cmdPtr = mf;
 
 
 	add_timer(&hd->timer);
 	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);
 	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
 
 	if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
 	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)
 			     struct scsi_device *sdev)
 {
 {
 	VirtTarget *vtarget = scsi_target(sdev)->hostdata;
 	VirtTarget *vtarget = scsi_target(sdev)->hostdata;
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	/* no DV on RAID devices */
 	/* no DV on RAID devices */
 	if (sdev->channel == 0 &&
 	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 this is a piece of a RAID, then quiesce first */
 	if (sdev->channel == 1 &&
 	if (sdev->channel == 1 &&
 	    mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
 	    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;
 		return;
 	}
 	}
 
 
@@ -684,8 +692,8 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
 
 
 	if (sdev->channel == 1 &&
 	if (sdev->channel == 1 &&
 	    mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
 	    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);
 	mptspi_read_parameters(sdev->sdev_target);
 	spi_display_xfer_agreement(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)
 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;
 	VirtTarget		*vtarget;
-	VirtDevice		*vdev;
+	VirtDevice		*vdevice;
 	struct scsi_target 	*starget;
 	struct scsi_target 	*starget;
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	if (sdev->channel == 1 &&
 	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;
 			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",
 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
-				hd->ioc->name, sizeof(VirtDevice));
+				ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	vdev->lun = sdev->lun;
-	sdev->hostdata = vdev;
+	vdevice->lun = sdev->lun;
+	sdev->hostdata = vdevice;
 
 
 	starget = scsi_target(sdev);
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 	vtarget = starget->hostdata;
-	vdev->vtarget = vtarget;
+	vdevice->vtarget = vtarget;
 	vtarget->num_luns++;
 	vtarget->num_luns++;
 
 
 	if (sdev->channel == 1)
 	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)
 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;
 	VirtTarget *vtarget = scsi_target(sdev)->hostdata;
 	int ret;
 	int ret;
 
 
@@ -755,24 +763,25 @@ static int mptspi_slave_configure(struct scsi_device *sdev)
 static int
 static int
 mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 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;
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		done(SCpnt);
 		return 0;
 		return 0;
 	}
 	}
 
 
 	if (SCpnt->device->channel == 1 &&
 	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;
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		done(SCpnt);
 		return 0;
 		return 0;
 	}
 	}
 
 
 	if (spi_dv_pending(scsi_target(SCpnt->device)))
 	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);
 	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 _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
 {
 {
 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
 	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 _MPT_ADAPTER *ioc = hd->ioc;
 	struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
 	struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
 	dma_addr_t pg1_dma;
 	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);
 	pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
 	if (pg1 == NULL) {
 	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;
 		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));
 	mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
 
 
 	if (mpt_config(ioc, &cfg)) {
 	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;
 		goto out_free;
 	}
 	}
 	err = 0;
 	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 _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
 	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;
 	VirtTarget *vtarget = starget->hostdata;
 	u32 nego;
 	u32 nego;
 
 
@@ -1067,15 +1078,16 @@ static void mpt_work_wrapper(struct work_struct *work)
 	struct work_queue_wrapper *wqw =
 	struct work_queue_wrapper *wqw =
 		container_of(work, struct work_queue_wrapper, work);
 		container_of(work, struct work_queue_wrapper, work);
 	struct _MPT_SCSI_HOST *hd = wqw->hd;
 	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;
 	struct scsi_device *sdev;
 	int disk = wqw->disk;
 	int disk = wqw->disk;
 	struct _CONFIG_PAGE_IOC_3 *pg3;
 	struct _CONFIG_PAGE_IOC_3 *pg3;
 
 
 	kfree(wqw);
 	kfree(wqw);
 
 
-	mpt_findImVolumes(hd->ioc);
-	pg3 = hd->ioc->raid_data.pIocPg3;
+	mpt_findImVolumes(ioc);
+	pg3 = ioc->raid_data.pIocPg3;
 	if (!pg3)
 	if (!pg3)
 		return;
 		return;
 
 
@@ -1092,24 +1104,25 @@ static void mpt_work_wrapper(struct work_struct *work)
 		if(vtarget->id != disk)
 		if(vtarget->id != disk)
 			continue;
 			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);
 		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)
 static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
 {
 {
 	struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
 	struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	if (!wqw) {
 	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;
 		return;
 	}
 	}
 	INIT_WORK(&wqw->work, mpt_work_wrapper);
 	INIT_WORK(&wqw->work, mpt_work_wrapper);
@@ -1123,7 +1136,7 @@ static int
 mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
 {
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
 	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) {
 	if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {
 		int reason
 		int reason
@@ -1190,6 +1203,8 @@ static struct spi_function_template mptspi_transport_functions = {
 static struct pci_device_id mptspi_pci_table[] = {
 static struct pci_device_id mptspi_pci_table[] = {
 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
 	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
 		PCI_ANY_ID, PCI_ANY_ID },
 		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_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
 		PCI_ANY_ID, PCI_ANY_ID },
 		PCI_ANY_ID, PCI_ANY_ID },
 	{0}	/* Terminating entry */
 	{0}	/* Terminating entry */
@@ -1210,11 +1225,12 @@ mptspi_dv_renegotiate_work(struct work_struct *work)
 	struct scsi_target *starget;
 	struct scsi_target *starget;
 	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
 	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
 	u32 nego;
 	u32 nego;
+	MPT_ADAPTER *ioc = hd->ioc;
 
 
 	kfree(wqw);
 	kfree(wqw);
 
 
 	if (hd->spi_pending) {
 	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))
 			if  (hd->spi_pending & (1 << sdev->id))
 				continue;
 				continue;
 			starget = scsi_target(sdev);
 			starget = scsi_target(sdev);
@@ -1225,7 +1241,7 @@ mptspi_dv_renegotiate_work(struct work_struct *work)
 			mptspi_write_spi_device_pg1(starget, &pg1);
 			mptspi_write_spi_device_pg1(starget, &pg1);
 		}
 		}
 	} else {
 	} else {
-		shost_for_each_device(sdev, hd->ioc->sh)
+		shost_for_each_device(sdev, ioc->sh)
 			mptspi_dv_device(hd, sdev);
 			mptspi_dv_device(hd, sdev);
 	}
 	}
 }
 }
@@ -1250,7 +1266,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
 static int
 static int
 mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 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;
 	int rc;
 
 
 	rc = mptscsih_ioc_reset(ioc, reset_phase);
 	rc = mptscsih_ioc_reset(ioc, reset_phase);
@@ -1269,7 +1285,7 @@ static int
 mptspi_resume(struct pci_dev *pdev)
 mptspi_resume(struct pci_dev *pdev)
 {
 {
 	MPT_ADAPTER 	*ioc = pci_get_drvdata(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;
 	int rc;
 
 
 	rc = mptscsih_resume(pdev);
 	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) {
 	if (numSGE < sh->sg_tablesize) {
 		/* Reset this value */
 		/* 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",
 		  "Resetting sg_tablesize to %d from %d\n",
 		  ioc->name, numSGE, sh->sg_tablesize));
 		  ioc->name, numSGE, sh->sg_tablesize));
 		sh->sg_tablesize = numSGE;
 		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);
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 
-	hd = (MPT_SCSI_HOST *) sh->hostdata;
+	hd = shost_priv(sh);
 	hd->ioc = ioc;
 	hd->ioc = ioc;
 
 
 	/* SCSI needs scsi_cmnd lookup table!
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 * (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;
 		error = -ENOMEM;
 		goto out_mptspi_probe;
 		goto out_mptspi_probe;
 	}
 	}
+	spin_lock_init(&ioc->scsi_lookup_lock);
 
 
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
-		 ioc->name, hd->ScsiLookup));
+		 ioc->name, ioc->ScsiLookup));
 
 
 	/* Clear the TM flags
 	/* 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
 	/* Some versions of the firmware don't support page 0; without
 	 * that we can't get the parameters */
 	 * 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;
 		sh->transportt = mptspi_transport_template;
 
 
 	error = scsi_add_host (sh, &ioc->pcidev->dev);
 	error = scsi_add_host (sh, &ioc->pcidev->dev);
 	if(error) {
 	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;
 		goto out_mptspi_probe;
 	}
 	}
 
 

+ 10 - 3
drivers/s390/scsi/zfcp_aux.c

@@ -891,7 +891,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit)
 /*
 /*
  * Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI
  * Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI
  * commands.
  * 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.
  * status read fsf_req buffers.
  *
  *
  * locks:       must only be called with zfcp_data.config_sema taken
  * 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;
 	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
 	 * 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->san_dbf_lock);
 	spin_lock_init(&adapter->scsi_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 */
 	/* initialize error recovery stuff */
 
 
 	rwlock_init(&adapter->erp_lock);
 	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 */
 	/* mark adapter unusable as long as sysfs registration is not complete */
 	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
 	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
 
 
-	adapter->ccw_device = ccw_device;
 	dev_set_drvdata(&ccw_device->dev, adapter);
 	dev_set_drvdata(&ccw_device->dev, adapter);
 
 
 	if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
 	if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
@@ -1085,6 +1088,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
  generic_services_failed:
  generic_services_failed:
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
  sysfs_failed:
  sysfs_failed:
+	zfcp_adapter_debug_unregister(adapter);
+ debug_register_failed:
 	dev_set_drvdata(&ccw_device->dev, NULL);
 	dev_set_drvdata(&ccw_device->dev, NULL);
 	zfcp_reqlist_free(adapter);
 	zfcp_reqlist_free(adapter);
  failed_low_mem_buffers:
  failed_low_mem_buffers:
@@ -1130,6 +1135,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
 		goto out;
 		goto out;
 	}
 	}
 
 
+	zfcp_adapter_debug_unregister(adapter);
+
 	/* remove specified adapter data structure from list */
 	/* remove specified adapter data structure from list */
 	write_lock_irq(&zfcp_data.config_lock);
 	write_lock_irq(&zfcp_data.config_lock);
 	list_del(&adapter->list);
 	list_del(&adapter->list);

+ 1 - 7
drivers/s390/scsi/zfcp_ccw.c

@@ -148,15 +148,12 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
 	down(&zfcp_data.config_sema);
 	down(&zfcp_data.config_sema);
 	adapter = dev_get_drvdata(&ccw_device->dev);
 	adapter = dev_get_drvdata(&ccw_device->dev);
 
 
-	retval = zfcp_adapter_debug_register(adapter);
-	if (retval)
-		goto out;
 	retval = zfcp_erp_thread_setup(adapter);
 	retval = zfcp_erp_thread_setup(adapter);
 	if (retval) {
 	if (retval) {
 		ZFCP_LOG_INFO("error: start of error recovery thread for "
 		ZFCP_LOG_INFO("error: start of error recovery thread for "
 			      "adapter %s failed\n",
 			      "adapter %s failed\n",
 			      zfcp_get_busid_by_adapter(adapter));
 			      zfcp_get_busid_by_adapter(adapter));
-		goto out_erp_thread;
+		goto out;
 	}
 	}
 
 
 	retval = zfcp_adapter_scsi_register(adapter);
 	retval = zfcp_adapter_scsi_register(adapter);
@@ -175,8 +172,6 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
 
 
  out_scsi_register:
  out_scsi_register:
 	zfcp_erp_thread_kill(adapter);
 	zfcp_erp_thread_kill(adapter);
- out_erp_thread:
-	zfcp_adapter_debug_unregister(adapter);
  out:
  out:
 	up(&zfcp_data.config_sema);
 	up(&zfcp_data.config_sema);
 	return retval;
 	return retval;
@@ -199,7 +194,6 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 	zfcp_erp_adapter_shutdown(adapter, 0);
 	zfcp_erp_adapter_shutdown(adapter, 0);
 	zfcp_erp_wait(adapter);
 	zfcp_erp_wait(adapter);
 	zfcp_erp_thread_kill(adapter);
 	zfcp_erp_thread_kill(adapter);
-	zfcp_adapter_debug_unregister(adapter);
 	up(&zfcp_data.config_sema);
 	up(&zfcp_data.config_sema);
 	return 0;
 	return 0;
 }
 }

+ 23 - 23
drivers/s390/scsi/zfcp_def.h

@@ -1,23 +1,23 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  * FCP adapters for IBM System z9 and zSeries.
  *
  *
  * (C) Copyright IBM Corp. 2002, 2006
  * (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
 #ifndef ZFCP_DEF_H
 #define 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_TYPE        0x1732
 #define ZFCP_DEVICE_MODEL       0x03
 #define ZFCP_DEVICE_MODEL       0x03
 #define ZFCP_DEVICE_MODEL_PRIV	0x04
 #define ZFCP_DEVICE_MODEL_PRIV	0x04
- 
+
 /* allow as many chained SBALs as are supported by hardware */
 /* 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_REQ		FSF_MAX_SBALS_PER_REQ
 #define ZFCP_MAX_SBALS_PER_CT_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
  * 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)
  * higher log levels are removed)
  */
  */
 #define ZFCP_LOG_LEVEL_LIMIT	ZFCP_LOG_LEVEL_TRACE
 #define ZFCP_LOG_LEVEL_LIMIT	ZFCP_LOG_LEVEL_TRACE
@@ -546,7 +546,7 @@ do { \
 	if (ZFCP_LOG_CHECK(level)) \
 	if (ZFCP_LOG_CHECK(level)) \
 		_ZFCP_LOG(fmt, ##args); \
 		_ZFCP_LOG(fmt, ##args); \
 } while (0)
 } while (0)
-	
+
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
 # define ZFCP_LOG_NORMAL(fmt, args...)	do { } while (0)
 # define ZFCP_LOG_NORMAL(fmt, args...)	do { } while (0)
 #else
 #else
@@ -583,8 +583,8 @@ do { \
 
 
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
 /*************** 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
  * and unit
  */
  */
 #define ZFCP_COMMON_FLAGS			0xfff00000
 #define ZFCP_COMMON_FLAGS			0xfff00000
@@ -1007,8 +1007,8 @@ struct zfcp_fsf_req {
 	u32		       fsf_command;    /* FSF Command copy */
 	u32		       fsf_command;    /* FSF Command copy */
 	struct fsf_qtcb	       *qtcb;	       /* address of associated QTCB */
 	struct fsf_qtcb	       *qtcb;	       /* address of associated QTCB */
 	u32		       seq_no;         /* Sequence number of request */
 	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
 	struct zfcp_erp_action *erp_action;    /* used if this request is
 						  issued on behalf of erp */
 						  issued on behalf of erp */
 	mempool_t	       *pool;	       /* used if request was alloacted
 	mempool_t	       *pool;	       /* used if request was alloacted

+ 70 - 70
drivers/s390/scsi/zfcp_erp.c

@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  * FCP adapters for IBM System z9 and zSeries.
  *
  *
  * (C) Copyright IBM Corp. 2002, 2006
  * (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
 #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,
  * purpose:	called if an adapter failed,
  *		initiates adapter recovery which is done
  *		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
  * purpose:	Wrappper for zfcp_erp_adapter_reopen_internal
  *              used to ensure the correct locking
  *              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
  * purpose:	called if a port failed to be opened normally
  *		initiates Forced Reopen recovery which is done
  *		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
  * purpose:	Wrappper for zfcp_erp_port_forced_reopen_internal
  *              used to ensure the correct locking
  *              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
  * purpose:	called if a port is to be opened
  *		initiates Reopen recovery which is done
  *		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
  * purpose:	called if a unit is to be opened
  *		initiates Reopen recovery which is done
  *		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,
  * purpose:	disable I/O,
  *		return any open requests and clean them up,
  *		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
  * purpose:	enable I/O
  *
  *
@@ -742,7 +742,7 @@ zfcp_erp_port_unblock(struct zfcp_port *port)
 }
 }
 
 
 /*
 /*
- * function:	
+ * function:
  *
  *
  * purpose:	disable I/O,
  * purpose:	disable I/O,
  *		return any open requests and clean them up,
  *		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
  * purpose:	enable I/O
  *
  *
@@ -792,7 +792,7 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
 }
 }
 
 
 /*
 /*
- * function:	
+ * function:
  *
  *
  * purpose:
  * purpose:
  *
  *
@@ -967,7 +967,7 @@ static void zfcp_erp_timeout_handler(unsigned long data)
  * zfcp_erp_action_dismiss - dismiss an erp_action
  * zfcp_erp_action_dismiss - dismiss an erp_action
  *
  *
  * adapter->erp_lock must be held
  * adapter->erp_lock must be held
- * 
+ *
  * Dismissal of an erp_action is usually required if an erp_action of
  * Dismissal of an erp_action is usually required if an erp_action of
  * higher priority is generated.
  * higher priority is generated.
  */
  */
@@ -1005,9 +1005,9 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
 }
 }
 
 
 /*
 /*
- * function:	
+ * function:
  *
  *
- * purpose:	
+ * purpose:
  *
  *
  * returns:
  * returns:
  *
  *
@@ -1094,7 +1094,7 @@ zfcp_erp_thread(void *data)
 }
 }
 
 
 /*
 /*
- * function:	
+ * function:
  *
  *
  * purpose:	drives single error recovery action and schedules higher and
  * purpose:	drives single error recovery action and schedules higher and
  *		subordinate actions, if necessary
  *		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
 	 * 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
 	 * to offline or the other way around
 	 * (old retval is preserved if nothing has to be done here)
 	 * (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:
  unlock:
 	write_unlock(&adapter->erp_lock);
 	write_unlock(&adapter->erp_lock);
 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
-	
+
 	if (retval != ZFCP_ERP_CONTINUES)
 	if (retval != ZFCP_ERP_CONTINUES)
 		zfcp_erp_action_cleanup(action, adapter, port, unit, retval);
 		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
  * returns:	ZFCP_ERP_DISMISSED	- if action has been dismissed
  *		retval			- otherwise
  *		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
  * purpose:	triggers retry of this action after a certain amount of time
  *		by means of timer provided by erp_action
  *		by means of timer provided by erp_action
@@ -1346,7 +1346,7 @@ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
 	return retval;
 	return retval;
 }
 }
 
 
-/* 
+/*
  * function:    zfcp_erp_adapter_failed
  * function:    zfcp_erp_adapter_failed
  *
  *
  * purpose:     sets the adapter and all underlying devices to ERP_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");
 	debug_text_event(adapter->erp_dbf, 2, "a_afail");
 }
 }
 
 
-/* 
+/*
  * function:    zfcp_erp_port_failed
  * function:    zfcp_erp_port_failed
  *
  *
  * purpose:     sets the port and all underlying devices to ERP_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));
 	debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t));
 }
 }
 
 
-/* 
+/*
  * function:    zfcp_erp_unit_failed
  * function:    zfcp_erp_unit_failed
  *
  *
  * purpose:     sets the unit to ERP_FAILED
  * purpose:     sets the unit to ERP_FAILED
@@ -1417,7 +1417,7 @@ zfcp_erp_unit_failed(struct zfcp_unit *unit)
  *              successfully is reset.
  *              successfully is reset.
  *
  *
  * returns:	ZFCP_ERP_CONTINUES	- action continues (not considered)
  * 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
  *		ZFCP_ERP_EXIT		- action failed and will not continue
  */
  */
 static int
 static int
@@ -1646,7 +1646,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit)
 }
 }
 
 
 /*
 /*
- * function:	
+ * function:
  *
  *
  * purpose:	remaining things in good cases,
  * purpose:	remaining things in good cases,
  *		escalation in bad cases
  *		escalation in bad cases
@@ -1687,8 +1687,8 @@ zfcp_erp_strategy_followup_actions(int action,
 		break;
 		break;
 
 
 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
 	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);
 			zfcp_erp_port_reopen_internal(unit->port, 0);
 		break;
 		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
  * purpose:	Wrappper for zfcp_erp_port_reopen_all_internal
  *              used to ensure the correct locking
  *              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
  * 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
  * purpose:	this routine executes the 'Reopen Adapter' action
  *		(the entire action is processed synchronously, since
  *		(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
  * returns:	ZFCP_ERP_SUCCEEDED      - action finished successfully
  *              ZFCP_ERP_FAILED         - action finished unsuccessfully
  *              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
  * returns:	ZFCP_ERP_SUCCEEDED      - action finished successfully
  *              ZFCP_ERP_FAILED         - action finished unsuccessfully
  *              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
  * purpose:	allocate the irq associated with this devno and register
  *		the FSF adapter with the SCSI stack
  *		the FSF adapter with the SCSI stack
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
 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);
 	zfcp_erp_action_to_running(erp_action);
 	write_unlock_irq(&adapter->erp_lock);
 	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) {
 	if (ret == -EOPNOTSUPP) {
 		debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
 		debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
 		return ZFCP_ERP_SUCCEEDED;
 		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
  * 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
  * 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
  * purpose:	makes the erp thread continue with reopen (physical) port
  *		actions which have been paused until the name server 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)
  * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously)
  *		ZFCP_ERP_FAILED		- action finished unsuccessfully
  *		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)
  * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously)
  *		ZFCP_ERP_FAILED		- action finished unsuccessfully
  *		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)
  * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously)
  *		ZFCP_ERP_FAILED		- action finished unsuccessfully
  *		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)
  * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously)
  *		ZFCP_ERP_FAILED		- action finished unsuccessfully
  *		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
  * purpose:	this routine executes the 'Reopen Unit' action
  *		currently no retries
  *		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)
  * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously)
  *		ZFCP_ERP_FAILED		- action finished unsuccessfully
  *		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)
  * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously)
  *		ZFCP_ERP_FAILED		- action finished unsuccessfully
  *		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
  * purpose:	enqueue the specified error recovery action, if needed
  *
  *
@@ -2992,7 +2992,7 @@ zfcp_erp_action_enqueue(int action,
 					      port->erp_action.action);
 					      port->erp_action.action);
 				debug_text_event(adapter->erp_dbf, 4,
 				debug_text_event(adapter->erp_dbf, 4,
 						 "pf_actenq_drp");
 						 "pf_actenq_drp");
-			} else 
+			} else
 				debug_text_event(adapter->erp_dbf, 4,
 				debug_text_event(adapter->erp_dbf, 4,
 						 "pf_actenq_drpcp");
 						 "pf_actenq_drpcp");
 			debug_event(adapter->erp_dbf, 4, &port->wwpn,
 			debug_event(adapter->erp_dbf, 4, &port->wwpn,

+ 20 - 18
drivers/s390/scsi/zfcp_ext.h

@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  * FCP adapters for IBM System z9 and zSeries.
  *
  *
  * (C) Copyright IBM Corp. 2002, 2006
  * (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
 #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_close_unit(struct zfcp_erp_action *);
 
 
 extern int  zfcp_fsf_exchange_config_data(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 **,
 extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
 				  u32, u32, struct zfcp_sg_list *);
 				  u32, u32, struct zfcp_sg_list *);
 extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
 extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);

+ 197 - 96
drivers/s390/scsi/zfcp_fsf.c

@@ -80,10 +80,10 @@ static const char zfcp_act_subtable_type[5][8] = {
 /*
 /*
  * function:	zfcp_fsf_req_alloc
  * 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
  *              unsolicited requests) via helper functions
  *              Does some initial fsf request set-up.
  *              Does some initial fsf request set-up.
- *              
+ *
  * returns:	pointer to allocated fsf_req if successfull
  * returns:	pointer to allocated fsf_req if successfull
  *              NULL otherwise
  *              NULL otherwise
  *
  *
@@ -192,7 +192,7 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
  * returns:	0 - success
  * returns:	0 - success
  *		!0 - failure
  *		!0 - failure
  *
  *
- * context:	
+ * context:
  */
  */
 int
 int
 zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
 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))
 	if (likely(fsf_req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
 		cleanup = 1;
 		cleanup = 1;
@@ -259,9 +259,9 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
  *		and initiates appropriate actions
  *		and initiates appropriate actions
  *		(usually calling FSF command specific handlers)
  *		(usually calling FSF command specific handlers)
  *
  *
- * returns:	
+ * returns:
  *
  *
- * context:	
+ * context:
  *
  *
  * locks:
  * locks:
  */
  */
@@ -638,7 +638,7 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
  *
  *
  * purpose:	calls the appropriate command specific handler
  * purpose:	calls the appropriate command specific handler
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
 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
  * purpose:	is called for finished Open Port command
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
 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
  * returns:	address of initiated FSF request
  *		NULL - request could not be initiated
  *		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
  * FIXME(design) shouldn't this be modified to return an int
  *               also...don't know how though
  *               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
  * purpose:	is called for finished Abort FCP Command request
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
 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;
 	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;
 	unsigned long lock_flags;
-	int retval = 0;
+	int retval;
 
 
 	/* setup new FSF request */
 	/* setup new FSF request */
-	retval = zfcp_fsf_req_create(erp_action->adapter,
+	retval = zfcp_fsf_req_create(adapter,
 				     FSF_QTCB_EXCHANGE_CONFIG_DATA,
 				     FSF_QTCB_EXCHANGE_CONFIG_DATA,
 				     ZFCP_REQ_AUTO_CLEANUP,
 				     ZFCP_REQ_AUTO_CLEANUP,
-				     erp_action->adapter->pool.fsf_req_erp,
+				     adapter->pool.fsf_req_erp,
 				     &lock_flags, &fsf_req);
 				     &lock_flags, &fsf_req);
-	if (retval < 0) {
+	if (retval) {
 		ZFCP_LOG_INFO("error: Could not create exchange configuration "
 		ZFCP_LOG_INFO("error: Could not create exchange configuration "
 			      "data request for adapter %s.\n",
 			      "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 = 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_req->qtcb->bottom.config.feature_selection =
 			FSF_FEATURE_CFDC |
 			FSF_FEATURE_CFDC |
@@ -1971,23 +1974,71 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 
 
 	zfcp_erp_start_timer(fsf_req);
 	zfcp_erp_start_timer(fsf_req);
 	retval = zfcp_fsf_req_send(fsf_req);
 	retval = zfcp_fsf_req_send(fsf_req);
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+				lock_flags);
 	if (retval) {
 	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);
 		zfcp_fsf_req_free(fsf_req);
 		erp_action->fsf_req = NULL;
 		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);
 				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;
 	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;
 	adapter->peer_d_id = 0;
 
 
 	if (xchg_ok) {
 	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_node_name(shost) = bottom->nport_serv_param.wwnn;
 		fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
 		fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
 		fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
 		fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
 		fc_host_speed(shost) = bottom->fc_link_speed;
 		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;
 		adapter->hydra_version = bottom->adapter_type;
 		if (fc_host_permanent_port_name(shost) == -1)
 		if (fc_host_permanent_port_name(shost) == -1)
 			fc_host_permanent_port_name(shost) =
 			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));
 		       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, "
 			"WWNN 0x%016Lx, "
 			"WWPN 0x%016Lx, "
 			"WWPN 0x%016Lx, "
 			"S_ID 0x%06x,\n"
 			"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;
 	return 0;
 }
 }
 
 
-/*
+/**
  * function:    zfcp_fsf_exchange_config_data_handler
  * function:    zfcp_fsf_exchange_config_data_handler
  *
  *
  * purpose:     is called for finished Exchange Configuration Data command
  * 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_wwpn,
 					adapter->peer_d_id);
 					adapter->peer_d_id);
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
-					 "top-p-to-p");
+					"top-p-to-p");
 			break;
 			break;
 		case FC_PORTTYPE_NLPORT:
 		case FC_PORTTYPE_NLPORT:
 			ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
 			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;
 			return -EIO;
 		case FC_PORTTYPE_NPORT:
 		case FC_PORTTYPE_NPORT:
 			ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
 			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;
 			break;
 		default:
 		default:
 			ZFCP_LOG_NORMAL("bug: The fibrechannel topology "
 			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))
 		if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
 			return -EIO;
 			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,
 		zfcp_fsf_link_down_info_eval(adapter,
 			&qtcb->header.fsf_status_qual.link_down_info);
 			&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:
 	default:
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
 		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
 		debug_event(fsf_req->adapter->erp_dbf, 0,
 		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);
 		zfcp_erp_adapter_shutdown(adapter, 0);
 		return -EIO;
 		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
  * zfcp_fsf_exchange_port_data - request information about local port
  * @erp_action: ERP action for the adapter for which port data is requested
  * @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
 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;
 	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;
 	unsigned long lock_flags;
-	int retval = 0;
+	int retval;
 
 
 	if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
 	if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
 		ZFCP_LOG_INFO("error: exchange port data "
 		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));
 			      zfcp_get_busid_by_adapter(adapter));
-                return -EOPNOTSUPP;
-        }
+		return -EOPNOTSUPP;
+	}
 
 
 	/* setup new FSF request */
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
 	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 "
 		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));
 			      zfcp_get_busid_by_adapter(adapter));
 		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
 		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
 					lock_flags);
 					lock_flags);
 		return retval;
 		return retval;
 	}
 	}
 
 
-	if (data)
-		fsf_req->data = (unsigned long) data;
-
 	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 	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);
 	retval = zfcp_fsf_req_send(fsf_req);
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
+
 	if (retval) {
 	if (retval) {
 		ZFCP_LOG_INFO("error: Could not send an exchange port data "
 		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_get_busid_by_adapter(adapter));
 		zfcp_fsf_req_free(fsf_req);
 		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,
 		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
 					lock_flags);
 					lock_flags);
 		return retval;
 		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);
 	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,
 		wait_event(fsf_req->completion_wq,
 			   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
 			   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
-		zfcp_fsf_req_free(fsf_req);
-	}
+
+	zfcp_fsf_req_free(fsf_req);
+
 	return retval;
 	return retval;
 }
 }
 
 
@@ -2277,18 +2380,16 @@ static void
 zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
 zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
 {
 {
 	struct zfcp_adapter *adapter;
 	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;
 	struct Scsi_Host *shost;
 
 
 	adapter = fsf_req->adapter;
 	adapter = fsf_req->adapter;
-	qtcb = fsf_req->qtcb;
-	bottom = &qtcb->bottom.port;
+	bottom = &fsf_req->qtcb->bottom.port;
 	shost = adapter->scsi_host;
 	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)
 	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
 		fc_host_permanent_port_name(shost) = bottom->wwpn;
 		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
  * function:    zfcp_fsf_open_port
  *
  *
- * purpose:	
+ * purpose:
  *
  *
  * returns:	address of initiated FSF request
  * returns:	address of initiated FSF request
- *		NULL - request could not be initiated 
+ *		NULL - request could not be initiated
  */
  */
 int
 int
 zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
 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
  * purpose:	is called for finished Open Port command
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
 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
  * purpose:	is called for finished Open LUN command
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
 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:
  * purpose:
  *
  *
  * returns:	address of fsf_req - request successfully initiated
  * returns:	address of fsf_req - request successfully initiated
- *		NULL - 
+ *		NULL -
  *
  *
  * assumptions: This routine does not check whether the associated
  * assumptions: This routine does not check whether the associated
  *              remote port/lun has already been opened. This should be
  *              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(
 			ZFCP_LOG_DEBUG(
 				"Data did not fit into available buffer(s), "
 				"Data did not fit into available buffer(s), "
 			       "waiting for more...\n");
 			       "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;
 		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
  * purpose:	is called for finished Send FCP Command
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
 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
  * purpose:	evaluates FCP_RSP IU
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 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
  * purpose:	evaluates FCP_RSP IU
  *
  *
- * returns:	
+ * returns:
  */
  */
 static int
 static int
 zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
 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_LIST_HEAD(&fsf_req->list);
 	init_timer(&fsf_req->timer);
 	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 */
 	   this request completion */
 	init_waitqueue_head(&fsf_req->completion_wq);
 	init_waitqueue_head(&fsf_req->completion_wq);
 
 

+ 15 - 15
drivers/s390/scsi/zfcp_fsf.h

@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  * FCP adapters for IBM System z9 and zSeries.
  *
  *
  * (C) Copyright IBM Corp. 2002, 2006
  * (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
 #ifndef FSF_H

+ 3 - 4
drivers/s390/scsi/zfcp_qdio.c

@@ -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
                 * That is why we need to clear the link-down flag
                 * which is set again in case we have missed by a mile.
                 * 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;
 	return retval;
 }
 }

+ 23 - 24
drivers/s390/scsi/zfcp_scsi.c

@@ -1,22 +1,22 @@
-/* 
+/*
  * This file is part of the zfcp device driver for
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  * FCP adapters for IBM System z9 and zSeries.
  *
  *
  * (C) Copyright IBM Corp. 2002, 2006
  * (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
 #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 +
 		((unsigned char *) fcp_cmd +
 		 sizeof (struct fcp_cmnd_iu) + additional_length);
 		 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
 	 * size of fixed part + size of dynamically sized add_dcp_cdb field
 	 * SEE FCP-2 documentation
 	 * SEE FCP-2 documentation
 	 */
 	 */
@@ -189,13 +189,12 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
 		unit->device = NULL;
 		unit->device = NULL;
 		zfcp_erp_unit_failed(unit);
 		zfcp_erp_unit_failed(unit);
 		zfcp_unit_put(unit);
 		zfcp_unit_put(unit);
-	} else {
+	} else
 		ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
 		ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
 				"address %p\n", sdpnt);
 				"address %p\n", sdpnt);
-	}
 }
 }
 
 
-/* 
+/*
  * called from scsi midlayer to allow finetuning of a device.
  * called from scsi midlayer to allow finetuning of a device.
  */
  */
 static int
 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) {
 	list_for_each_entry(port, &adapter->port_list_head, list) {
 		if (!port->rport || (id != port->rport->scsi_target_id))
 		if (!port->rport || (id != port->rport->scsi_target_id))
 			continue;
 			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) {
 			if (lun == unit->scsi_lun) {
 				retval = unit;
 				retval = unit;
 				goto out;
 				goto out;
 			}
 			}
-		}
 	}
 	}
  out:
  out:
 	return retval;
 	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
  * 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
  * Return: SUCCESS - command has been aborted and cleaned up in internal
  *          bookkeeping, SCSI stack won't be called for aborted command
  *          bookkeeping, SCSI stack won't be called for aborted command
  *         FAILED - otherwise
  *         FAILED - otherwise
@@ -733,7 +731,7 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost)
 	if (!data)
 	if (!data)
 		return NULL;
 		return NULL;
 
 
-	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+	ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
 	if (ret) {
 	if (ret) {
 		kfree(data);
 		kfree(data);
 		return NULL; /* XXX return zeroed fc_stats? */
 		return NULL; /* XXX return zeroed fc_stats? */
@@ -763,7 +761,7 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
 	if (!data)
 	if (!data)
 		return;
 		return;
 
 
-	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+	ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
 	if (ret) {
 	if (ret) {
 		kfree(data);
 		kfree(data);
 	} else {
 	} else {
@@ -802,6 +800,7 @@ struct fc_function_template zfcp_transport_functions = {
 	.show_host_port_type = 1,
 	.show_host_port_type = 1,
 	.show_host_speed = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
 	.show_host_port_id = 1,
+	.disable_target_scan = 1,
 };
 };
 
 
 /**
 /**

+ 2 - 2
drivers/s390/scsi/zfcp_sysfs_unit.c

@@ -139,7 +139,7 @@ static struct attribute_group zfcp_unit_attr_group = {
 	.attrs = zfcp_unit_attrs,
 	.attrs = zfcp_unit_attrs,
 };
 };
 
 
-/** 
+/**
  * zfcp_sysfs_create_unit_files - create sysfs unit files
  * zfcp_sysfs_create_unit_files - create sysfs unit files
  * @dev: pointer to belonging device
  * @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);
 	return sysfs_create_group(&dev->kobj, &zfcp_unit_attr_group);
 }
 }
 
 
-/** 
+/**
  * zfcp_sysfs_remove_unit_files - remove sysfs unit files
  * zfcp_sysfs_remove_unit_files - remove sysfs unit files
  * @dev: pointer to belonging device
  * @dev: pointer to belonging device
  *
  *

+ 41 - 7
drivers/scsi/Kconfig

@@ -272,6 +272,13 @@ config SCSI_FC_ATTRS
 	  each attached FiberChannel device to sysfs, say Y.
 	  each attached FiberChannel device to sysfs, say Y.
 	  Otherwise, say N.
 	  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
 config SCSI_ISCSI_ATTRS
 	tristate "iSCSI Transport Attributes"
 	tristate "iSCSI Transport Attributes"
 	depends on SCSI && NET
 	depends on SCSI && NET
@@ -289,6 +296,20 @@ config SCSI_SAS_ATTRS
 
 
 source "drivers/scsi/libsas/Kconfig"
 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
 endmenu
 
 
 menuconfig SCSI_LOWLEVEL
 menuconfig SCSI_LOWLEVEL
@@ -502,7 +523,6 @@ config SCSI_ADVANSYS
 	tristate "AdvanSys SCSI support"
 	tristate "AdvanSys SCSI support"
 	depends on SCSI
 	depends on SCSI
 	depends on ISA || EISA || PCI
 	depends on ISA || EISA || PCI
-	depends on BROKEN || X86_32
 	help
 	help
 	  This is a driver for all SCSI host adapters manufactured by
 	  This is a driver for all SCSI host adapters manufactured by
 	  AdvanSys. It is documented in the kernel source in
 	  AdvanSys. It is documented in the kernel source in
@@ -524,19 +544,32 @@ config SCSI_IN2000
 	  module will be called in2000.
 	  module will be called in2000.
 
 
 config SCSI_ARCMSR
 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
 	depends on PCI && SCSI
 	help
 	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.
 	  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.
 	  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
 	  To compile this driver as a module, choose M here: the
 	  module will be called arcmsr (modprobe arcmsr).
 	  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"
 source "drivers/scsi/megaraid/Kconfig.megaraid"
 
 
 config SCSI_HPTIOP
 config SCSI_HPTIOP
@@ -836,6 +869,7 @@ config SCSI_IPS
 config SCSI_IBMVSCSI
 config SCSI_IBMVSCSI
 	tristate "IBM Virtual SCSI support"
 	tristate "IBM Virtual SCSI support"
 	depends on PPC_PSERIES || PPC_ISERIES
 	depends on PPC_PSERIES || PPC_ISERIES
+	select SCSI_SRP_ATTRS
 	help
 	help
 	  This is the IBM POWER Virtual SCSI Client
 	  This is the IBM POWER Virtual SCSI Client
 
 
@@ -844,7 +878,7 @@ config SCSI_IBMVSCSI
 
 
 config SCSI_IBMVSCSIS
 config SCSI_IBMVSCSIS
 	tristate "IBM Virtual SCSI Server support"
 	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
 	help
 	  This is the SRP target driver for IBM pSeries virtual environments.
 	  This is the SRP target driver for IBM pSeries virtual environments.
 
 

+ 1 - 0
drivers/scsi/Makefile

@@ -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_ISCSI_ATTRS)	+= scsi_transport_iscsi.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)	+= scsi_transport_sas.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)	+= scsi_transport_sas.o
 obj-$(CONFIG_SCSI_SAS_LIBSAS)	+= libsas/
 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_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
 obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
 obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o

+ 13 - 18
drivers/scsi/NCR5380.c

@@ -1542,9 +1542,7 @@ part2:
 	hostdata->connected = cmd;
 	hostdata->connected = cmd;
 	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 	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;
 	return 0;
 
 
@@ -2133,7 +2131,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 				sink = 1;
 				sink = 1;
 				do_abort(instance);
 				do_abort(instance);
 				cmd->result = DID_ERROR << 16;
 				cmd->result = DID_ERROR << 16;
-				cmd->done(cmd);
+				cmd->scsi_done(cmd);
 				return;
 				return;
 #endif
 #endif
 				/* 
 				/* 
@@ -2196,7 +2194,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 						sink = 1;
 						sink = 1;
 						do_abort(instance);
 						do_abort(instance);
 						cmd->result = DID_ERROR << 16;
 						cmd->result = DID_ERROR << 16;
-						cmd->done(cmd);
+						cmd->scsi_done(cmd);
 						/* XXX - need to source or sink data here, as appropriate */
 						/* XXX - need to source or sink data here, as appropriate */
 					} else
 					} else
 						cmd->SCp.this_residual -= transfersize - len;
 						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);
 						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
 
 #ifdef AUTOSENSE
 #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)) {
 					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));
 						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);
 						LIST(cmd, hostdata->issue_queue);
 						cmd->host_scribble = (unsigned char *)
 						cmd->host_scribble = (unsigned char *)
@@ -2740,7 +2735,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
 			tmp->host_scribble = NULL;
 			tmp->host_scribble = NULL;
 			tmp->result = DID_ABORT << 16;
 			tmp->result = DID_ABORT << 16;
 			dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
 			dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
-			tmp->done(tmp);
+			tmp->scsi_done(tmp);
 			return SUCCESS;
 			return SUCCESS;
 		}
 		}
 #if (NDEBUG  & NDEBUG_ABORT)
 #if (NDEBUG  & NDEBUG_ABORT)
@@ -2805,7 +2800,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
 					*prev = (Scsi_Cmnd *) tmp->host_scribble;
 					*prev = (Scsi_Cmnd *) tmp->host_scribble;
 					tmp->host_scribble = NULL;
 					tmp->host_scribble = NULL;
 					tmp->result = DID_ABORT << 16;
 					tmp->result = DID_ABORT << 16;
-					tmp->done(tmp);
+					tmp->scsi_done(tmp);
 					return SUCCESS;
 					return SUCCESS;
 				}
 				}
 		}
 		}

+ 7 - 0
drivers/scsi/NCR5380.h

@@ -30,6 +30,10 @@
 
 
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 
 
+#ifdef AUTOSENSE
+#include <scsi/scsi_eh.h>
+#endif
+
 #define NCR5380_PUBLIC_RELEASE 7
 #define NCR5380_PUBLIC_RELEASE 7
 #define NCR53C400_PUBLIC_RELEASE 2
 #define NCR53C400_PUBLIC_RELEASE 2
 
 
@@ -281,6 +285,9 @@ struct NCR5380_hostdata {
 	unsigned pendingr;
 	unsigned pendingr;
 	unsigned pendingw;
 	unsigned pendingw;
 #endif
 #endif
+#ifdef AUTOSENSE
+	struct scsi_eh_save ses;
+#endif
 };
 };
 
 
 #ifdef __KERNEL__
 #ifdef __KERNEL__

+ 1 - 1
drivers/scsi/NCR53C9x.c

@@ -1385,7 +1385,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
 				this->host_scribble = NULL;
 				this->host_scribble = NULL;
 				esp_release_dmabufs(esp, this);
 				esp_release_dmabufs(esp, this);
 				this->result = DID_ABORT << 16;
 				this->result = DID_ABORT << 16;
-				this->done(this);
+				this->scsi_done(this);
 				if(don)
 				if(don)
 					esp->dma_ints_on(esp);
 					esp->dma_ints_on(esp);
 				return SUCCESS;
 				return SUCCESS;

+ 2 - 3
drivers/scsi/NCR_D700.c

@@ -97,7 +97,6 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/mca.h>
 #include <linux/mca.h>
-#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_device.h>
@@ -314,10 +313,10 @@ NCR_D700_probe(struct device *dev)
 		break;
 		break;
 	}
 	}
 
 
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (!p)
 	if (!p)
 		return -ENOMEM;
 		return -ENOMEM;
-	memset(p, '\0', sizeof(*p));
+
 	p->dev = dev;
 	p->dev = dev;
 	snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
 	snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
 	if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {
 	if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {

+ 3 - 4
drivers/scsi/a4000t.c

@@ -37,7 +37,7 @@ static struct platform_device *a4000t_scsi_device;
 
 
 static int __devinit a4000t_probe(struct device *dev)
 static int __devinit a4000t_probe(struct device *dev)
 {
 {
-	struct Scsi_Host * host = NULL;
+	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata;
 	struct NCR_700_Host_Parameters *hostdata;
 
 
 	if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
 	if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
@@ -47,12 +47,11 @@ static int __devinit a4000t_probe(struct device *dev)
 				"A4000T builtin SCSI"))
 				"A4000T builtin SCSI"))
 		goto out;
 		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");
 		printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
 		goto out_release;
 		goto out_release;
 	}
 	}
-	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 
 
 	/* Fill in the required pieces of hostdata */
 	/* Fill in the required pieces of hostdata */
 	hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
 	hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);

+ 4 - 4
drivers/scsi/aacraid/aachba.c

@@ -177,9 +177,9 @@ int check_interval = 24 * 60 * 60;
 module_param(check_interval, int, S_IRUGO|S_IWUSR);
 module_param(check_interval, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks.");
 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;
 int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
 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),
 			  (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
 			  dev->supplement_adapter_info.VpdInfo.Tsid);
 			  dev->supplement_adapter_info.VpdInfo.Tsid);
 		}
 		}
-		if (!check_reset ||
+		if (!aac_check_reset ||
 		  (dev->supplement_adapter_info.SupportedOptions2 &
 		  (dev->supplement_adapter_info.SupportedOptions2 &
 		  le32_to_cpu(AAC_OPTION_IGNORE_RESET))) {
 		  le32_to_cpu(AAC_OPTION_IGNORE_RESET))) {
 			printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
 			printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",

+ 1 - 1
drivers/scsi/aacraid/aacraid.h

@@ -1871,4 +1871,4 @@ extern int aac_reset_devices;
 extern int aac_commit;
 extern int aac_commit;
 extern int update_interval;
 extern int update_interval;
 extern int check_interval;
 extern int check_interval;
-extern int check_reset;
+extern int aac_check_reset;

+ 3 - 2
drivers/scsi/aacraid/commsup.c

@@ -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);
 	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;
 		goto out;
 	host = aac->scsi_host_ptr;
 	host = aac->scsi_host_ptr;
 	if (aac->thread->pid != current->pid)
 	if (aac->thread->pid != current->pid)

+ 10263 - 14951
drivers/scsi/advansys.c

@@ -1,765 +1,27 @@
-#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
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  *
  *
  * Copyright (c) 1995-2000 Advanced System Products, Inc.
  * Copyright (c) 1995-2000 Advanced System Products, Inc.
  * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
  * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
+ * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx>
  * All Rights Reserved.
  * 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>
 #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/string.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/types.h>
@@ -771,7 +33,9 @@
 #include <linux/proc_fs.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/blkdev.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/spinlock.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 
 
@@ -779,49 +43,38 @@
 #include <asm/system.h>
 #include <asm/system.h>
 #include <asm/dma.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_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.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. */
 /* Enable driver /proc statistics. */
 #define ADVANSYS_STATS
 #define ADVANSYS_STATS
 
 
 /* Enable driver tracing. */
 /* 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
  * Portable Data Types
@@ -837,17 +90,6 @@
 #define ASC_DCNT  __u32		/* Unsigned Data count type. */
 #define ASC_DCNT  __u32		/* Unsigned Data count type. */
 #define ASC_SDCNT __s32		/* Signed 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;
 typedef unsigned char uchar;
 
 
 #ifndef TRUE
 #ifndef TRUE
@@ -857,29 +99,9 @@ typedef unsigned char uchar;
 #define FALSE    (0)
 #define FALSE    (0)
 #endif
 #endif
 
 
-#define EOF      (-1)
 #define ERR      (-1)
 #define ERR      (-1)
 #define UW_ERR   (uint)(0xFFFF)
 #define UW_ERR   (uint)(0xFFFF)
 #define isodd_word(val)   ((((uint)val) & (uint)0x0001) != 0)
 #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_VENDOR_ID_ASP		0x10cd
 #define PCI_DEVICE_ID_ASP_1200A		0x1100
 #define PCI_DEVICE_ID_ASP_1200A		0x1100
@@ -898,7 +120,7 @@ typedef unsigned char uchar;
 #define CC_VERY_LONG_SG_LIST 0
 #define CC_VERY_LONG_SG_LIST 0
 #define ASC_SRB2SCSIQ(srb_ptr)  (srb_ptr)
 #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 inp(port)                inb(port)
 #define outp(port, byte)         outb((byte), (port))
 #define outp(port, byte)         outb((byte), (port))
 
 
@@ -918,11 +140,10 @@ typedef unsigned char uchar;
 #define ASC_IS_PCMCIA       (0x0008)
 #define ASC_IS_PCMCIA       (0x0008)
 #define ASC_IS_MCA          (0x0020)
 #define ASC_IS_MCA          (0x0020)
 #define ASC_IS_VL           (0x0040)
 #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_16  (0x0100)
 #define ASC_IS_WIDESCSI_32  (0x0200)
 #define ASC_IS_WIDESCSI_32  (0x0200)
 #define ASC_IS_BIG_ENDIAN   (0x8000)
 #define ASC_IS_BIG_ENDIAN   (0x8000)
+
 #define ASC_CHIP_MIN_VER_VL      (0x01)
 #define ASC_CHIP_MIN_VER_VL      (0x01)
 #define ASC_CHIP_MAX_VER_VL      (0x07)
 #define ASC_CHIP_MAX_VER_VL      (0x07)
 #define ASC_CHIP_MIN_VER_PCI     (0x09)
 #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_MAX_VER_EISA (0x47)
 #define ASC_CHIP_VER_EISA_BIT (0x40)
 #define ASC_CHIP_VER_EISA_BIT (0x40)
 #define ASC_CHIP_LATEST_VER_EISA   ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
 #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_VL_DMA_COUNT    (0x07FFFFFFL)
-#define ASC_MAX_PCI_DMA_ADDR    (0xFFFFFFFFL)
 #define ASC_MAX_PCI_DMA_COUNT   (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_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_ID_BITS  3
 #define ASC_SCSI_TIX_TYPE     uchar
 #define ASC_SCSI_TIX_TYPE     uchar
@@ -961,82 +175,17 @@ typedef unsigned char uchar;
 #define ASC_SCSI_WIDTH_BIT_SET  0xFF
 #define ASC_SCSI_WIDTH_BIT_SET  0xFF
 #define ASC_MAX_SENSE_LEN   32
 #define ASC_MAX_SENSE_LEN   32
 #define ASC_MIN_SENSE_LEN   14
 #define ASC_MIN_SENSE_LEN   14
-#define ASC_MAX_CDB_LEN     12
 #define ASC_SCSI_RESET_HOLD_TIME_US  60
 #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_LEN    0x03
-#define MS_SDTR_CODE   0x01
 #define MS_WDTR_LEN    0x02
 #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 ASC_SG_LIST_PER_Q   7
 #define QS_FREE        0x00
 #define QS_FREE        0x00
@@ -1215,22 +364,9 @@ typedef struct asc_sg_head {
 	ushort queue_cnt;
 	ushort queue_cnt;
 	ushort entry_to_copy;
 	ushort entry_to_copy;
 	ushort res;
 	ushort res;
-	ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
+	ASC_SG_LIST sg_list[0];
 } ASC_SG_HEAD;
 } 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 {
 typedef struct asc_scsi_q {
 	ASC_SCSIQ_1 q1;
 	ASC_SCSIQ_1 q1;
 	ASC_SCSIQ_2 q2;
 	ASC_SCSIQ_2 q2;
@@ -1287,45 +423,12 @@ typedef struct asc_risc_sg_list_q {
 	ASC_SG_LIST sg_list[7];
 	ASC_SG_LIST sg_list[7];
 } ASC_RISC_SG_LIST_Q;
 } 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_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_CUR_QNG              0x17
 #define ASCQ_ERR_SG_Q_LINKS           0x18
 #define ASCQ_ERR_SG_Q_LINKS           0x18
-#define ASCQ_ERR_SCSIQ_PTR            0x19
 #define ASCQ_ERR_ISR_RE_ENTRY         0x1A
 #define ASCQ_ERR_ISR_RE_ENTRY         0x1A
 #define ASCQ_ERR_CRITICAL_RE_ENTRY    0x1B
 #define ASCQ_ERR_CRITICAL_RE_ENTRY    0x1B
 #define ASCQ_ERR_ISR_ON_CRITICAL      0x1C
 #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'.
  * 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_CMD_QNG_CONFLICT     0x0010
 #define ASC_WARN_EEPROM_RECOVER       0x0020
 #define ASC_WARN_EEPROM_RECOVER       0x0020
 #define ASC_WARN_CFG_MSW_RECOVER      0x0040
 #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_DEF_MAX_TOTAL_QNG   (0xF0)
 #define ASC_MIN_TAG_Q_PER_DVC   (0x04)
 #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_MIN_TOTAL_QNG     ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
 #define ASC_MAX_TOTAL_QNG 240
 #define ASC_MAX_TOTAL_QNG 240
 #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
 #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
 #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG   8
 #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG   8
 #define ASC_MAX_PCI_INRAM_TOTAL_QNG  20
 #define ASC_MAX_PCI_INRAM_TOTAL_QNG  20
 #define ASC_MAX_INRAM_TAG_QNG   16
 #define ASC_MAX_INRAM_TAG_QNG   16
-#define ASC_IOADR_TABLE_MAX_IX  11
 #define ASC_IOADR_GAP   0x10
 #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_SYN_MAX_OFFSET         0x0F
 #define ASC_DEF_SDTR_OFFSET        0x0F
 #define ASC_DEF_SDTR_OFFSET        0x0F
-#define ASC_DEF_SDTR_INDEX         0x00
 #define ASC_SDTR_ULTRA_PCI_10MB_INDEX  0x02
 #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 {
 typedef struct ext_msg {
 	uchar msg_type;
 	uchar msg_type;
@@ -1456,22 +526,16 @@ typedef struct asc_dvc_cfg {
 	uchar isa_dma_speed;
 	uchar isa_dma_speed;
 	uchar isa_dma_channel;
 	uchar isa_dma_channel;
 	uchar chip_version;
 	uchar chip_version;
-	ushort lib_serial_no;
-	ushort lib_version;
 	ushort mcode_date;
 	ushort mcode_date;
 	ushort mcode_version;
 	ushort mcode_version;
 	uchar max_tag_qng[ASC_MAX_TID + 1];
 	uchar max_tag_qng[ASC_MAX_TID + 1];
-	uchar *overrun_buf;
 	uchar sdtr_period_offset[ASC_MAX_TID + 1];
 	uchar sdtr_period_offset[ASC_MAX_TID + 1];
-	ushort pci_slot_info;
 	uchar adapter_info[6];
 	uchar adapter_info[6];
-	struct device *dev;
 } ASC_DVC_CFG;
 } ASC_DVC_CFG;
 
 
 #define ASC_DEF_DVC_CNTL       0xFFFF
 #define ASC_DEF_DVC_CNTL       0xFFFF
 #define ASC_DEF_CHIP_SCSI_ID   7
 #define ASC_DEF_CHIP_SCSI_ID   7
 #define ASC_DEF_ISA_DMA_SPEED  4
 #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_BEG_GET_CFG   0x0001
 #define ASC_INIT_STATE_END_GET_CFG   0x0002
 #define ASC_INIT_STATE_END_GET_CFG   0x0002
 #define ASC_INIT_STATE_BEG_SET_CFG   0x0004
 #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_INIT_STATE_WITHOUT_EEP   0x8000
 #define ASC_BUG_FIX_IF_NOT_DWB       0x0001
 #define ASC_BUG_FIX_IF_NOT_DWB       0x0001
 #define ASC_BUG_FIX_ASYN_USE_SYN     0x0002
 #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_MIN_TAGGED_CMD  7
 #define ASC_MAX_SCSI_RESET_WAIT      30
 #define ASC_MAX_SCSI_RESET_WAIT      30
+#define ASC_OVERRUN_BSIZE		64
 
 
 struct asc_dvc_var;		/* Forward Declaration. */
 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 {
 typedef struct asc_dvc_var {
 	PortAddr iop_base;
 	PortAddr iop_base;
 	ushort err_code;
 	ushort err_code;
 	ushort dvc_cntl;
 	ushort dvc_cntl;
 	ushort bug_fix_cntl;
 	ushort bug_fix_cntl;
 	ushort bus_type;
 	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 init_sdtr;
 	ASC_SCSI_BIT_ID_TYPE sdtr_done;
 	ASC_SCSI_BIT_ID_TYPE sdtr_done;
 	ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
 	ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
 	ASC_SCSI_BIT_ID_TYPE unit_not_ready;
 	ASC_SCSI_BIT_ID_TYPE unit_not_ready;
 	ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
 	ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
 	ASC_SCSI_BIT_ID_TYPE start_motor;
 	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 scsi_reset_wait;
 	uchar chip_no;
 	uchar chip_no;
 	char is_in_int;
 	char is_in_int;
 	uchar max_total_qng;
 	uchar max_total_qng;
 	uchar cur_total_qng;
 	uchar cur_total_qng;
 	uchar in_critical_cnt;
 	uchar in_critical_cnt;
-	uchar irq_no;
 	uchar last_q_shortage;
 	uchar last_q_shortage;
 	ushort init_state;
 	ushort init_state;
 	uchar cur_dvc_qng[ASC_MAX_TID + 1];
 	uchar cur_dvc_qng[ASC_MAX_TID + 1];
 	uchar max_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_head[ASC_MAX_TID + 1];
 	ASC_SCSI_Q *scsiq_busy_tail[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_DVC_CFG *cfg;
 	ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
 	ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
 	char redo_scam;
 	char redo_scam;
@@ -1529,9 +589,11 @@ typedef struct asc_dvc_var {
 	ASC_DCNT max_dma_count;
 	ASC_DCNT max_dma_count;
 	ASC_SCSI_BIT_ID_TYPE no_scam;
 	ASC_SCSI_BIT_ID_TYPE no_scam;
 	ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
 	ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
+	uchar min_sdtr_index;
 	uchar max_sdtr_index;
 	uchar max_sdtr_index;
-	uchar host_init_sdtr_index;
 	struct asc_board *drv_ptr;
 	struct asc_board *drv_ptr;
+	int ptr_map_count;
+	void **ptr_map;
 	ASC_DCNT uc_break;
 	ASC_DCNT uc_break;
 } ASC_DVC_VAR;
 } ASC_DVC_VAR;
 
 
@@ -1568,12 +630,7 @@ typedef struct asc_cap_info_array {
 #define ASC_EEP_MAX_DVC_ADDR_VL   15
 #define ASC_EEP_MAX_DVC_ADDR_VL   15
 #define ASC_EEP_DVC_CFG_BEG      32
 #define ASC_EEP_DVC_CFG_BEG      32
 #define ASC_EEP_MAX_DVC_ADDR     45
 #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_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
  * These macros keep the chip SCSI id and ISA DMA speed
@@ -1609,17 +666,10 @@ typedef struct asceep_config {
 	ushort chksum;
 	ushort chksum;
 } ASCEEP_CONFIG;
 } 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_READ          0x80
 #define ASC_EEP_CMD_WRITE         0x40
 #define ASC_EEP_CMD_WRITE         0x40
 #define ASC_EEP_CMD_WRITE_ABLE    0x30
 #define ASC_EEP_CMD_WRITE_ABLE    0x30
 #define ASC_EEP_CMD_WRITE_DISABLE 0x00
 #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_BEG         0x0000
 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
 #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
 #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      0x04C1
 #define ASC_1000_ID0W_FIX  0x00C1
 #define ASC_1000_ID0W_FIX  0x00C1
 #define ASC_1000_ID1B      0x25
 #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_REV_IOP_MASK  (0x0C83)
-#define ASC_EISA_PID_IOP_MASK  (0x0C80)
 #define ASC_EISA_CFG_IOP_MASK  (0x0C86)
 #define ASC_EISA_CFG_IOP_MASK  (0x0C86)
 #define ASC_GET_EISA_SLOT(iop)  (PortAddr)((iop) & 0xF000)
 #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_HALTINT        (ushort)0x6281
 #define INS_HALT           (ushort)0x6280
 #define INS_HALT           (ushort)0x6280
 #define INS_SINT           (ushort)0x6200
 #define INS_SINT           (ushort)0x6200
@@ -1828,11 +871,10 @@ typedef struct asc_mc_saved {
 #define AscGetRiscVarDoneQTail(port)        AscReadLramByte((port), ASCV_DONENEXT_B)
 #define AscGetRiscVarDoneQTail(port)        AscReadLramByte((port), ASCV_DONENEXT_B)
 #define AscPutRiscVarFreeQHead(port, val)   AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
 #define AscPutRiscVarFreeQHead(port, val)   AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
 #define AscPutRiscVarDoneQTail(port, val)   AscWriteLramByte((port), ASCV_DONENEXT_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 AscGetChipSignatureByte(port)     (uchar)inp((port)+IOP_SIG_BYTE)
 #define AscGetChipSignatureWord(port)     (ushort)inpw((port)+IOP_SIG_WORD)
 #define AscGetChipSignatureWord(port)     (ushort)inpw((port)+IOP_SIG_WORD)
 #define AscGetChipVerNo(port)             (uchar)inp((port)+IOP_VERSION)
 #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 AscReadChipDvcID(port)            (uchar)inp((port)+IOP_REG_ID)
 #define AscWriteChipDvcID(port, data)     outp((port)+IOP_REG_ID, data)
 #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
  * 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)
 #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
  * Define total number of simultaneous maximum element scatter-gather
  * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
  * 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.
  * 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
  * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
  * structures or 255 scatter-gather elements.
  * structures or 255 scatter-gather elements.
- *
  */
  */
 #define ADV_TOT_SG_BLOCK        ASC_DEF_MAX_HOST_QNG
 #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
 #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_BEGIN           (0x00)
 #define ADV_EEP_DVC_CFG_END             (0x15)
 #define ADV_EEP_DVC_CFG_END             (0x15)
@@ -2385,10 +1288,6 @@ typedef struct adveep_38C1600_config {
  * EEPROM Commands
  * EEPROM Commands
  */
  */
 #define ASC_EEP_CMD_DONE             0x0200
 #define ASC_EEP_CMD_DONE             0x0200
-#define ASC_EEP_CMD_DONE_ERR         0x0001
-
-/* cfg_word */
-#define EEP_CFG_WORD_BIG_ENDIAN      0x8000
 
 
 /* bios_ctrl */
 /* bios_ctrl */
 #define BIOS_CTRL_BIOS               0x0001
 #define BIOS_CTRL_BIOS               0x0001
@@ -2405,10 +1304,8 @@ typedef struct adveep_38C1600_config {
 #define BIOS_CTRL_AIPP_DIS           0x2000
 #define BIOS_CTRL_AIPP_DIS           0x2000
 
 
 #define ADV_3550_MEMSIZE   0x2000	/* 8 KB Internal Memory */
 #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_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
  * 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  0x8000L   * 32 KB Internal Memory *
  */
  */
 #define ADV_38C1600_MEMSIZE  0x4000	/* 16 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'.
  * 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_BYTE         0x25
 #define ADV_CHIP_ID_WORD         0x04C1
 #define ADV_CHIP_ID_WORD         0x04C1
 
 
-#define ADV_SC_SCSI_BUS_RESET    0x2000
-
 #define ADV_INTR_ENABLE_HOST_INTR                   0x01
 #define ADV_INTR_ENABLE_HOST_INTR                   0x01
 #define ADV_INTR_ENABLE_SEL_INTR                    0x02
 #define ADV_INTR_ENABLE_SEL_INTR                    0x02
 #define ADV_INTR_ENABLE_DPR_INTR                    0x04
 #define ADV_INTR_ENABLE_DPR_INTR                    0x04
@@ -2590,8 +1483,6 @@ typedef struct adveep_38C1600_config {
 #define ADV_TICKLE_B                        0x02
 #define ADV_TICKLE_B                        0x02
 #define ADV_TICKLE_C                        0x03
 #define ADV_TICKLE_C                        0x03
 
 
-#define ADV_SCSI_CTRL_RSTOUT        0x2000
-
 #define AdvIsIntPending(port) \
 #define AdvIsIntPending(port) \
     (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
     (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
 
 
@@ -2744,14 +1635,11 @@ typedef struct adveep_38C1600_config {
  */
  */
 #define INTAB           0x01
 #define INTAB           0x01
 
 
-/* a_advlib.h */
-
 /*
 /*
  * Adv Library Status Definitions
  * Adv Library Status Definitions
  */
  */
 #define ADV_TRUE        1
 #define ADV_TRUE        1
 #define ADV_FALSE       0
 #define ADV_FALSE       0
-#define ADV_NOERROR     1
 #define ADV_SUCCESS     1
 #define ADV_SUCCESS     1
 #define ADV_BUSY        0
 #define ADV_BUSY        0
 #define ADV_ERROR       (-1)
 #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_BUSRESET_ERROR         0x0001	/* SCSI Bus Reset error */
 #define ASC_WARN_EEPROM_CHKSUM          0x0002	/* EEP check sum error */
 #define ASC_WARN_EEPROM_CHKSUM          0x0002	/* EEP check sum error */
 #define ASC_WARN_EEPROM_TERMINATION     0x0004	/* EEP termination bad field */
 #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 ASC_WARN_ERROR                  0xFFFF	/* ADV_ERROR return */
 
 
 #define ADV_MAX_TID                     15	/* max. target identifier */
 #define ADV_MAX_TID                     15	/* max. target identifier */
 #define ADV_MAX_LUN                     7	/* max. logical unit number */
 #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.
  * 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 ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
 
 
 #define ADV_CARRIER_NUM_PAGE_CROSSING \
 #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 \
 #define ADV_CARRIER_BUFSIZE \
     ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
     ((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 */
 	ushort disc_enable;	/* enable disconnection */
 	uchar chip_version;	/* chip version */
 	uchar chip_version;	/* chip version */
 	uchar termination;	/* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
 	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 control_flag;	/* Microcode Control Flag */
 	ushort mcode_date;	/* Microcode date */
 	ushort mcode_date;	/* Microcode date */
 	ushort mcode_version;	/* Microcode version */
 	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 serial1;		/* EEPROM serial number word 1 */
 	ushort serial2;		/* EEPROM serial number word 2 */
 	ushort serial2;		/* EEPROM serial number word 2 */
 	ushort serial3;		/* EEPROM serial number word 3 */
 	ushort serial3;		/* EEPROM serial number word 3 */
-	struct device *dev;	/* pointer to the pci dev structure for this board */
 } ADV_DVC_CFG;
 } ADV_DVC_CFG;
 
 
 struct adv_dvc_var;
 struct adv_dvc_var;
 struct adv_scsi_req_q;
 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 {
 typedef struct asc_sg_block {
 	uchar reserved1;
 	uchar reserved1;
 	uchar reserved2;
 	uchar reserved2;
@@ -3068,6 +1873,83 @@ typedef struct adv_scsi_req_q {
 	uchar pad[2];		/* Pad out to a word boundary. */
 	uchar pad[2];		/* Pad out to a word boundary. */
 } ADV_SCSI_REQ_Q;
 } 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
  * Microcode idle loop commands
  */
  */
@@ -3092,10 +1974,8 @@ typedef struct adv_scsi_req_q {
 /*
 /*
  * Wait loop time out values.
  * Wait loop time out values.
  */
  */
-#define SCSI_WAIT_10_SEC             10UL	/* 10 seconds */
 #define SCSI_WAIT_100_MSEC           100UL	/* 100 milliseconds */
 #define SCSI_WAIT_100_MSEC           100UL	/* 100 milliseconds */
 #define SCSI_US_PER_MSEC             1000	/* microseconds per millisecond */
 #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 SCSI_MAX_RETRY               10	/* retry count */
 
 
 #define ADV_ASYNC_RDMA_FAILURE          0x01	/* Fatal RDMA failure. */
 #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. */
 #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. */
 /* Read byte from a register. */
 #define AdvReadByteRegister(iop_base, reg_off) \
 #define AdvReadByteRegister(iop_base, reg_off) \
      (ADV_MEM_READB((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_FROZEN_TIDQ         0x46	/* TID Queue frozen. */
 #define QHSTA_M_SGBACKUP_ERROR      0x47	/* Scatter-Gather backup error */
 #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'. */
 /* Return the address that is aligned at the next doubleword >= to 'addr'. */
 #define ADV_8BALIGN(addr)      (((ulong) (addr) + 0x7) & ~0x7)
 #define ADV_8BALIGN(addr)      (((ulong) (addr) + 0x7) & ~0x7)
 #define ADV_16BALIGN(addr)     (((ulong) (addr) + 0xF) & ~0xF)
 #define ADV_16BALIGN(addr)     (((ulong) (addr) + 0xF) & ~0xF)
@@ -3353,92 +2169,10 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
          (sizeof(ADV_SG_BLOCK) * \
          (sizeof(ADV_SG_BLOCK) * \
           ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_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_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_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 */
 #define NO_ISA_DMA              0xff	/* No ISA DMA Channel Used */
 
 
@@ -3473,82 +2207,14 @@ typedef struct {
 #define HOST_BYTE(byte)     ((byte) << 16)
 #define HOST_BYTE(byte)     ((byte) << 16)
 #define DRIVER_BYTE(byte)   ((byte) << 24)
 #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
 #ifndef ADVANSYS_STATS
-#define ASC_STATS(shost, counter)
 #define ASC_STATS_ADD(shost, counter, count)
 #define ASC_STATS_ADD(shost, counter, count)
 #else /* ADVANSYS_STATS */
 #else /* ADVANSYS_STATS */
-#define ASC_STATS(shost, counter) \
-    (ASC_BOARDP(shost)->asc_stats.counter++)
-
 #define ASC_STATS_ADD(shost, counter, count) \
 #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 */
 #endif /* ADVANSYS_STATS */
 
 
-#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
-
 /* If the result wraps when calculating tenths, return 0. */
 /* If the result wraps when calculating tenths, return 0. */
 #define ASC_TENTHS(num, den) \
 #define ASC_TENTHS(num, den) \
     (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
     (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
@@ -3589,13 +2255,8 @@ typedef struct scsi_cmnd REQ, *REQP;
 
 
 #ifndef ADVANSYS_DEBUG
 #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_HOST(lvl, s)
-#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
 #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
 #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
@@ -3614,40 +2275,11 @@ typedef struct scsi_cmnd REQ, *REQP;
  * 2-N: Verbose Tracing
  * 2-N: Verbose Tracing
  */
  */
 
 
-#define ASC_DBG(lvl, s) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk(s); \
-        } \
-    }
-
-#define ASC_DBG1(lvl, s, a1) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1)); \
-        } \
-    }
-
-#define ASC_DBG2(lvl, s, a1, a2) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1), (a2)); \
-        } \
-    }
-
-#define ASC_DBG3(lvl, s, a1, a2, a3) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1), (a2), (a3)); \
-        } \
-    }
-
-#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1), (a2), (a3), (a4)); \
-        } \
-    }
+#define ASC_DBG(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) \
 #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) \
 #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
     { \
     { \
         if (asc_dbglvl >= (lvl)) { \
         if (asc_dbglvl >= (lvl)) { \
@@ -3701,24 +2326,6 @@ typedef struct scsi_cmnd REQ, *REQP;
         ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
         ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
 #endif /* ADVANSYS_DEBUG */
 #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
 #ifdef ADVANSYS_STATS
 
 
 /* Per board statistics structure */
 /* Per board statistics structure */
@@ -3739,72 +2346,23 @@ struct asc_stats {
 	ADV_DCNT exe_error;	/* # ASC_ERROR returns. */
 	ADV_DCNT exe_error;	/* # ASC_ERROR returns. */
 	ADV_DCNT exe_unknown;	/* # unknown returns. */
 	ADV_DCNT exe_unknown;	/* # unknown returns. */
 	/* Data Transfer Statistics */
 	/* 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 */
 #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.
  * 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'
  * of the 'Scsi_Host' structure starting at the 'hostdata'
  * field. It is guaranteed to be allocated from DMA-able memory.
  * 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 */
 	uint flags;		/* Board flags */
+	unsigned int irq;
 	union {
 	union {
 		ASC_DVC_VAR asc_dvc_var;	/* Narrow board */
 		ASC_DVC_VAR asc_dvc_var;	/* Narrow board */
 		ADV_DVC_VAR adv_dvc_var;	/* Wide 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 */
 		ADV_DVC_CFG adv_dvc_cfg;	/* Wide board */
 	} dvc_cfg;
 	} dvc_cfg;
 	ushort asc_n_io_port;	/* Number I/O ports. */
 	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 */
 	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 */
 	ushort reqcnt[ADV_MAX_TID + 1];	/* Starvation request count */
 	ADV_SCSI_BIT_ID_TYPE queue_full;	/* Queue full mask */
 	ADV_SCSI_BIT_ID_TYPE queue_full;	/* Queue full mask */
 	ushort queue_full_cnt[ADV_MAX_TID + 1];	/* Queue full count */
 	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. */
 		ADVEEP_38C1600_CONFIG adv_38C1600_eep;	/* 38C1600 EEPROM config. */
 	} eep_config;
 	} eep_config;
 	ulong last_reset;	/* Saved last reset time */
 	ulong last_reset;	/* Saved last reset time */
-	spinlock_t lock;	/* Board spinlock */
-#ifdef CONFIG_PROC_FS
 	/* /proc/scsi/advansys/[0...] */
 	/* /proc/scsi/advansys/[0...] */
 	char *prtbuf;		/* /proc print buffer */
 	char *prtbuf;		/* /proc print buffer */
-#endif				/* CONFIG_PROC_FS */
 #ifdef ADVANSYS_STATS
 #ifdef ADVANSYS_STATS
 	struct asc_stats asc_stats;	/* Board statistics */
 	struct asc_stats asc_stats;	/* Board statistics */
 #endif				/* ADVANSYS_STATS */
 #endif				/* ADVANSYS_STATS */
 	/*
 	/*
 	 * The following fields are used only for Narrow Boards.
 	 * 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 */
 	uchar sdtr_data[ASC_MAX_TID + 1];	/* SDTR information */
 	/*
 	/*
 	 * The following fields are used only for Wide Boards.
 	 * The following fields are used only for Wide Boards.
 	 */
 	 */
 	void __iomem *ioremap_addr;	/* I/O Memory remap address. */
 	void __iomem *ioremap_addr;	/* I/O Memory remap address. */
 	ushort ioport;		/* I/O Port 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_req_t *adv_reqp;	/* Request structures. */
 	adv_sgblk_t *adv_sgblkp;	/* Scatter-gather structures. */
 	adv_sgblk_t *adv_sgblkp;	/* Scatter-gather structures. */
 	ushort bios_signature;	/* BIOS Signature. */
 	ushort bios_signature;	/* BIOS Signature. */
 	ushort bios_version;	/* BIOS Version. */
 	ushort bios_version;	/* BIOS Version. */
 	ushort bios_codeseg;	/* BIOS Code Segment. */
 	ushort bios_codeseg;	/* BIOS Code Segment. */
 	ushort bios_codelen;	/* BIOS Code Segment Length. */
 	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 {
 		} 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 (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 {
 		} 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 {
 	} 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 {
 		} 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
 #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;
 	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 {
 	} 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 {
 	} 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 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 {
 	} 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 {
 	} 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 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;
 	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
 #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,
  * Note: no single line should be greater than ASC_PRTLINE_SIZE,
  * cf. asc_prt_line().
  * 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
  * Return the number of characters copied into 'cp'. No more than
  * 'cplen' characters will be copied to 'cp'.
  * '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,
 	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);
 			   shost->host_no);
 	ASC_PRT_NEXT();
 	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();
 	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();
 	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();
 		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();
 		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();
 		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();
 		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;
 	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 {
 	} 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 {
 	} 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 {
 	} 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 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. */
 /* 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;
 	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;
 	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;
 	PortAddr iop_base;
-	uchar free_q_head;
-	uchar next_qp;
-	uchar tid_no;
-	uchar target_ix;
-	int sta;
 
 
 	iop_base = asc_dvc->iop_base;
 	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 {
 	} 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;
 	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 warn_code;
-	ushort cfg_msw, cfg_lsw;
+	int begin_addr;
+	int end_addr;
+	ushort code_sum;
+	long word;
 	int i;
 	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 {
 		} 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;
 	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;
 			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;
 			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 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 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 {
 	} 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 {
 		} 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 {
 		} 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 {
 		} 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;
 	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 {
 	} 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;
 	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 {
 		} 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 {
 	} 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;
 	ushort warn_code;
-	ADVEEP_38C1600_CONFIG eep_config;
+	ushort cfg_msw, cfg_lsw;
 	int i;
 	int i;
-	uchar tid, termination;
-	ushort sdtr_speed = 0;
+	int write_eep = 0;
 
 
 	iop_base = asc_dvc->iop_base;
 	iop_base = asc_dvc->iop_base;
-
 	warn_code = 0;
 	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 {
 		} 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 {
 	} 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 {
 		} 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
  * 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,
 	AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 			     ASC_EEP_CMD_READ | eep_word_addr);
 			     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);
 	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'.
  * Write the EEPROM from 'cfg_buf'.
  */
  */
-void __init
+void __devinit
 AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 {
 {
 	ushort *wbuf;
 	ushort *wbuf;
@@ -16923,7 +12292,7 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 		AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 		AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 				     ASC_EEP_CMD_WRITE | addr);
 				     ASC_EEP_CMD_WRITE | addr);
 		AdvWaitEEPCmd(iop_base);
 		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);
 	AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
 	AdvWaitEEPCmd(iop_base);
 	AdvWaitEEPCmd(iop_base);
-	return;
 }
 }
 
 
 /*
 /*
  * Write the EEPROM from 'cfg_buf'.
  * Write the EEPROM from 'cfg_buf'.
  */
  */
-void __init
+void __devinit
 AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
 AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
 {
 {
 	ushort *wbuf;
 	ushort *wbuf;
@@ -16991,7 +12359,7 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
 		AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 		AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 				     ASC_EEP_CMD_WRITE | addr);
 				     ASC_EEP_CMD_WRITE | addr);
 		AdvWaitEEPCmd(iop_base);
 		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);
 	AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
 	AdvWaitEEPCmd(iop_base);
 	AdvWaitEEPCmd(iop_base);
-	return;
 }
 }
 
 
 /*
 /*
  * Write the EEPROM from 'cfg_buf'.
  * Write the EEPROM from 'cfg_buf'.
  */
  */
-void __init
+void __devinit
 AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
 AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
 {
 {
 	ushort *wbuf;
 	ushort *wbuf;
@@ -17059,7 +12426,7 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
 		AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 		AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
 				     ASC_EEP_CMD_WRITE | addr);
 				     ASC_EEP_CMD_WRITE | addr);
 		AdvWaitEEPCmd(iop_base);
 		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++;
 	wbuf++;
 	charfields++;
 	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++) {
 		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;
 	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;
 	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;
 	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;
 	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;
 	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;
 	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 {
 	} 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 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)) {
 	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 = &boardp->dvc_var.asc_dvc_var;
 		asc_dvc_varp->bus_type = bus_type;
 		asc_dvc_varp->bus_type = bus_type;
 		asc_dvc_varp->drv_ptr = boardp;
 		asc_dvc_varp->drv_ptr = boardp;
 		asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
 		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->iop_base = iop;
-		asc_dvc_varp->isr_callback = asc_isr_callback;
 	} else {
 	} 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 = &boardp->dvc_var.adv_dvc_var;
 		adv_dvc_varp->drv_ptr = boardp;
 		adv_dvc_varp->drv_ptr = boardp;
 		adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
 		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) {
 		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;
 			adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
 		} else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
 		} 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;
 			adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
 		} else {
 		} 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;
 			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
 		 * 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;
 		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
 #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
 	 * Allocate buffer for printing information from
 	 * /proc/scsi/advansys/[0...].
 	 * /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 */
 #endif /* CONFIG_PROC_FS */
 
 
 	if (ASC_NARROW_BOARD(boardp)) {
 	if (ASC_NARROW_BOARD(boardp)) {
-		asc_dvc_varp->cfg->dev = dev;
 		/*
 		/*
 		 * Set the board bus type and PCI IRQ before
 		 * Set the board bus type and PCI IRQ before
 		 * calling AscInitGetConfig().
 		 * calling AscInitGetConfig().
@@ -17937,127 +13473,56 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 #ifdef CONFIG_ISA
 #ifdef CONFIG_ISA
 		case ASC_IS_ISA:
 		case ASC_IS_ISA:
 			shost->unchecked_isa_dma = TRUE;
 			shost->unchecked_isa_dma = TRUE;
-			share_irq = FALSE;
+			share_irq = 0;
 			break;
 			break;
 		case ASC_IS_VL:
 		case ASC_IS_VL:
 			shost->unchecked_isa_dma = FALSE;
 			shost->unchecked_isa_dma = FALSE;
-			share_irq = FALSE;
+			share_irq = 0;
 			break;
 			break;
 		case ASC_IS_EISA:
 		case ASC_IS_EISA:
 			shost->unchecked_isa_dma = FALSE;
 			shost->unchecked_isa_dma = FALSE;
-			share_irq = TRUE;
+			share_irq = IRQF_SHARED;
 			break;
 			break;
 #endif /* CONFIG_ISA */
 #endif /* CONFIG_ISA */
 #ifdef CONFIG_PCI
 #ifdef CONFIG_PCI
 		case ASC_IS_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;
 			shost->unchecked_isa_dma = FALSE;
-			share_irq = TRUE;
+			share_irq = IRQF_SHARED;
 			break;
 			break;
 #endif /* CONFIG_PCI */
 #endif /* CONFIG_PCI */
 		default:
 		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;
 			shost->unchecked_isa_dma = TRUE;
-			share_irq = FALSE;
+			share_irq = 0;
 			break;
 			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
 		 * NOTE: AscInitGetConfig() may change the board's
 		 * bus_type value. The bus_type value should no
 		 * bus_type value. The bus_type value should no
 		 * longer be used. If the bus_type field must be
 		 * longer be used. If the bus_type field must be
 		 * referenced only use the bit-wise AND operator "&".
 		 * 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 {
 	} 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
 	 * Save the EEPROM configuration so that it can be displayed
 	 * from /proc/scsi/advansys/[0...].
 	 * from /proc/scsi/advansys/[0...].
@@ -18098,61 +13563,10 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 		/*
 		/*
 		 * Modify board configuration.
 		 * 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 {
 	} else {
 		ADVEEP_3550_CONFIG *ep_3550;
 		ADVEEP_3550_CONFIG *ep_3550;
 		ADVEEP_38C0800_CONFIG *ep_38C0800;
 		ADVEEP_38C0800_CONFIG *ep_38C0800;
@@ -18246,11 +13660,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 		 */
 		 */
 		boardp->init_tidmask |=
 		boardp->init_tidmask |=
 		    ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
 		    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)) {
 	if (ASC_NARROW_BOARD(boardp)) {
 		shost->max_id = ASC_MAX_TID + 1;
 		shost->max_id = ASC_MAX_TID + 1;
 		shost->max_lun = ASC_MAX_LUN + 1;
 		shost->max_lun = ASC_MAX_LUN + 1;
+		shost->max_cmd_len = ASC_MAX_CDB_LEN;
 
 
 		shost->io_port = asc_dvc_varp->iop_base;
 		shost->io_port = asc_dvc_varp->iop_base;
 		boardp->asc_n_io_port = ASC_IOADR_GAP;
 		boardp->asc_n_io_port = ASC_IOADR_GAP;
@@ -18272,6 +13682,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 	} else {
 	} else {
 		shost->max_id = ADV_MAX_TID + 1;
 		shost->max_id = ADV_MAX_TID + 1;
 		shost->max_lun = ADV_MAX_LUN + 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
 		 * 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.
 		 * PCI Memory Mapped I/O.
 		 */
 		 */
 		shost->io_port = iop;
 		shost->io_port = iop;
-		boardp->asc_n_io_port = iolen;
 
 
 		shost->this_id = adv_dvc_varp->chip_scsi_id;
 		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;
 		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
 	 * Following v1.3.89, 'cmd_per_lun' is no longer needed
 	 * and should be set to zero.
 	 * 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;
 		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. */
 	/* BIOS start address. */
 	if (ASC_NARROW_BOARD(boardp)) {
 	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 {
 	} else {
 		/*
 		/*
 		 * Fill-in BIOS board variables. The Wide BIOS saves
 		 * 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,
 		AdvReadWordLram(adv_dvc_varp->iop_base,
 				BIOS_CODELEN, boardp->bios_codelen);
 				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);
 			 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);
 			 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 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. */
 	/* Register DMA Channel for Narrow boards. */
 	shost->dma_channel = NO_ISA_DMA;	/* Default to no ISA DMA. */
 	shost->dma_channel = NO_ISA_DMA;	/* Default to no ISA DMA. */
 #ifdef CONFIG_ISA
 #ifdef CONFIG_ISA
@@ -18423,19 +13796,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 		/* Register DMA channel for ISA bus. */
 		/* Register DMA channel for ISA bus. */
 		if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
 		if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
 			shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
 			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);
 			AscEnableIsaDma(shost->dma_channel);
 		}
 		}
@@ -18443,573 +13809,392 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
 #endif /* CONFIG_ISA */
 #endif /* CONFIG_ISA */
 
 
 	/* Register IRQ Number. */
 	/* 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) {
 		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) {
 		} 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 {
 		} 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.
 	 * Initialize board RISC chip and enable interrupts.
 	 */
 	 */
 	if (ASC_NARROW_BOARD(boardp)) {
 	if (ASC_NARROW_BOARD(boardp)) {
-		ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
+		ASC_DBG(2, "AscInitAsc1000Driver()\n");
 		warn_code = AscInitAsc1000Driver(asc_dvc_varp);
 		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 {
 	} 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;
 		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;
 	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 */
 /* PCI Devices supported by this driver */
 static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
 static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
 	{PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
 	{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);
 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");

+ 2 - 2
drivers/scsi/aha152x.c

@@ -907,9 +907,10 @@ out_host_put:
 
 
 void aha152x_release(struct Scsi_Host *shpnt)
 void aha152x_release(struct Scsi_Host *shpnt)
 {
 {
-	if(!shpnt)
+	if (!shpnt)
 		return;
 		return;
 
 
+	scsi_remove_host(shpnt);
 	if (shpnt->irq)
 	if (shpnt->irq)
 		free_irq(shpnt->irq, shpnt);
 		free_irq(shpnt->irq, shpnt);
 
 
@@ -923,7 +924,6 @@ void aha152x_release(struct Scsi_Host *shpnt)
 		pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
 		pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
 #endif
 #endif
 
 
-	scsi_remove_host(shpnt);
 	list_del(&HOSTDATA(shpnt)->host_list);
 	list_del(&HOSTDATA(shpnt)->host_list);
 	scsi_host_put(shpnt);
 	scsi_host_put(shpnt);
 }
 }

+ 3 - 5
drivers/scsi/aic7xxx_old.c

@@ -8416,10 +8416,9 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp)
     *p = *temp;
     *p = *temp;
     p->host = host;
     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);
       scbq_init (&p->scb_data->free_scbs);
     }
     }
     else
     else
@@ -9196,10 +9195,9 @@ aic7xxx_detect(struct scsi_host_template *template)
             printk(KERN_INFO "         this driver, we are ignoring it.\n");
             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 )
                                     GFP_ATOMIC)) != NULL )
         {
         {
-          memset(temp_p, 0, sizeof(struct aic7xxx_host));
           temp_p->chip = aic_pdevs[i].chip | AHC_PCI;
           temp_p->chip = aic_pdevs[i].chip | AHC_PCI;
           temp_p->flags = aic_pdevs[i].flags;
           temp_p->flags = aic_pdevs[i].flags;
           temp_p->features = aic_pdevs[i].features;
           temp_p->features = aic_pdevs[i].features;

+ 0 - 12
drivers/scsi/aic94xx/aic94xx_hwi.h

@@ -40,18 +40,6 @@
 #define ASD_MAX_PHYS       8
 #define ASD_MAX_PHYS       8
 #define ASD_PCBA_SN_SIZE   12
 #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 {
 struct asd_ha_addrspace {
 	void __iomem  *addr;
 	void __iomem  *addr;
 	unsigned long  start;       /* pci resource start */
 	unsigned long  start;       /* pci resource start */

+ 18 - 24
drivers/scsi/aic94xx/aic94xx_init.c

@@ -583,7 +583,7 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
 	asd_ha = kzalloc(sizeof(*asd_ha), GFP_KERNEL);
 	asd_ha = kzalloc(sizeof(*asd_ha), GFP_KERNEL);
 	if (!asd_ha) {
 	if (!asd_ha) {
 		asd_printk("out of memory\n");
 		asd_printk("out of memory\n");
-		goto Err;
+		goto Err_put;
 	}
 	}
 	asd_ha->pcidev = dev;
 	asd_ha->pcidev = dev;
 	asd_ha->sas_ha.dev = &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;
 	shost->max_cmd_len = 16;
 
 
 	err = scsi_add_host(shost, &dev->dev);
 	err = scsi_add_host(shost, &dev->dev);
-	if (err) {
-		scsi_host_put(shost);
+	if (err)
 		goto Err_free;
 		goto Err_free;
-	}
 
 
 	err = asd_dev->setup(asd_ha);
 	err = asd_dev->setup(asd_ha);
 	if (err)
 	if (err)
-		goto Err_free;
+		goto Err_remove;
 
 
 	err = -ENODEV;
 	err = -ENODEV;
 	if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)
 	if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)
@@ -618,14 +616,14 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
 		;
 		;
 	else {
 	else {
 		asd_printk("no suitable DMA mask for %s\n", pci_name(dev));
 		asd_printk("no suitable DMA mask for %s\n", pci_name(dev));
-		goto Err_free;
+		goto Err_remove;
 	}
 	}
 
 
 	pci_set_drvdata(dev, asd_ha);
 	pci_set_drvdata(dev, asd_ha);
 
 
 	err = asd_map_ha(asd_ha);
 	err = asd_map_ha(asd_ha);
 	if (err)
 	if (err)
-		goto Err_free;
+		goto Err_remove;
 
 
 	err = asd_create_ha_caches(asd_ha);
 	err = asd_create_ha_caches(asd_ha);
         if (err)
         if (err)
@@ -692,9 +690,12 @@ Err_free_cache:
 	asd_destroy_ha_caches(asd_ha);
 	asd_destroy_ha_caches(asd_ha);
 Err_unmap:
 Err_unmap:
 	asd_unmap_ha(asd_ha);
 	asd_unmap_ha(asd_ha);
+Err_remove:
+	scsi_remove_host(shost);
 Err_free:
 Err_free:
 	kfree(asd_ha);
 	kfree(asd_ha);
-	scsi_remove_host(shost);
+Err_put:
+	scsi_host_put(shost);
 Err:
 Err:
 	pci_disable_device(dev);
 	pci_disable_device(dev);
 	return err;
 	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 = {
 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},
 	{}
 	{}
 };
 };
 
 

+ 1 - 1
drivers/scsi/aic94xx/aic94xx_task.c

@@ -207,7 +207,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
 					    "stat(0x%x) is not CHECK_CONDITION"
 					    "stat(0x%x) is not CHECK_CONDITION"
 					    "\n",
 					    "\n",
 					    SAS_ADDR(task->dev->sas_addr),
 					    SAS_ADDR(task->dev->sas_addr),
-					    ts->stat);
+					    iu->status);
 			}
 			}
 		}
 		}
 	}  else {
 	}  else {

+ 142 - 50
drivers/scsi/arcmsr/arcmsr.h

@@ -9,7 +9,7 @@
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved.
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved.
 **
 **
 **     Web site: www.areca.com.tw
 **     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
 ** 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
 ** it under the terms of the GNU General Public License version 2 as
@@ -45,19 +45,26 @@
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 
 
 struct class_device_attribute;
 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_SCSI_INITIATOR_ID						255
 #define ARCMSR_MAX_XFER_SECTORS							512
 #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
 **        split 64bits dma addressing
@@ -90,7 +97,7 @@ struct CMD_MESSAGE_FIELD
     uint8_t				messagedatabuffer[1032];
     uint8_t				messagedatabuffer[1032];
 };
 };
 /* IOP message transfer */
 /* IOP message transfer */
-#define ARCMSR_MESSAGE_FAIL             0x0001
+#define ARCMSR_MESSAGE_FAIL			0x0001
 /* DeviceType */
 /* DeviceType */
 #define ARECA_SATA_RAID				0x90000000
 #define ARECA_SATA_RAID				0x90000000
 /* FunctionCode */
 /* FunctionCode */
@@ -163,27 +170,27 @@ struct QBUFFER
 };
 };
 /*
 /*
 *******************************************************************************
 *******************************************************************************
-**      FIRMWARE INFO
+**      FIRMWARE INFO for Intel IOP R 80331 processor (Type A)
 *******************************************************************************
 *******************************************************************************
 */
 */
 struct FIRMWARE_INFO
 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      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 */
 /* 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 */
 /* 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_SET_CONFIG               0x00000002
 #define ARCMSR_INBOUND_MESG0_ABORT_CMD                0x00000003
 #define ARCMSR_INBOUND_MESG0_ABORT_CMD                0x00000003
 #define ARCMSR_INBOUND_MESG0_STOP_BGRB                0x00000004
 #define ARCMSR_INBOUND_MESG0_STOP_BGRB                0x00000004
@@ -203,6 +210,60 @@ struct FIRMWARE_INFO
 #define ARCMSR_CCBREPLY_FLAG_ERROR                    0x10000000
 #define ARCMSR_CCBREPLY_FLAG_ERROR                    0x10000000
 /* outbound firmware ok */
 /* outbound firmware ok */
 #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK             0x80000000
 #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)
 **    ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
@@ -214,7 +275,6 @@ struct ARCMSR_CDB
 	uint8_t							TargetID;
 	uint8_t							TargetID;
 	uint8_t							LUN;
 	uint8_t							LUN;
 	uint8_t							Function;
 	uint8_t							Function;
-
 	uint8_t							CdbLength;
 	uint8_t							CdbLength;
 	uint8_t							sgcount;
 	uint8_t							sgcount;
 	uint8_t							Flags;
 	uint8_t							Flags;
@@ -224,20 +284,18 @@ struct ARCMSR_CDB
 #define ARCMSR_CDB_FLAG_SIMPLEQ            0x00
 #define ARCMSR_CDB_FLAG_SIMPLEQ            0x00
 #define ARCMSR_CDB_FLAG_HEADQ              0x08
 #define ARCMSR_CDB_FLAG_HEADQ              0x08
 #define ARCMSR_CDB_FLAG_ORDEREDQ           0x10
 #define ARCMSR_CDB_FLAG_ORDEREDQ           0x10
-	uint8_t							Reserved1;
 
 
+	uint8_t							Reserved1;
 	uint32_t						Context;
 	uint32_t						Context;
 	uint32_t						DataLength;
 	uint32_t						DataLength;
-
 	uint8_t							Cdb[16];
 	uint8_t							Cdb[16];
-
 	uint8_t							DeviceStatus;
 	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
 	union
 	{
 	{
 		struct SG32ENTRY                sg32entry[ARCMSR_MAX_SG_ENTRIES];
 		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	resrved0[4];			/*0000 000F*/
 	uint32_t	inbound_msgaddr0;		/*0010 0013*/
 	uint32_t	inbound_msgaddr0;		/*0010 0013*/
@@ -274,6 +332,30 @@ struct MessageUnit
 	uint32_t	message_rbuffer[32];		/*0F00 0F7F  32*/
 	uint32_t	message_rbuffer[32];		/*0F00 0F7F  32*/
 	uint32_t	reserved6[32];			/*0F80 0FFF  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
 **                 Adapter Control Block
@@ -281,37 +363,45 @@ struct MessageUnit
 */
 */
 struct AdapterControlBlock
 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 pci_dev *		pdev;
 	struct Scsi_Host *		host;
 	struct Scsi_Host *		host;
 	unsigned long			vir2phy_offset;
 	unsigned long			vir2phy_offset;
 	/* Offset is used in making arc cdb physical to virtual calculations */
 	/* Offset is used in making arc cdb physical to virtual calculations */
 	uint32_t			outbound_int_enable;
 	uint32_t			outbound_int_enable;
 
 
-	struct MessageUnit __iomem *		pmu;
+	struct MessageUnit *			pmu;
 	/* message unit ATU inbound base address0 */
 	/* message unit ATU inbound base address0 */
 
 
 	uint32_t			acb_flags;
 	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 */
 	/* stop RAID background rebuild */
-#define ACB_F_MSG_START_BGRB          0x0004
+	#define ACB_F_MSG_START_BGRB          	0x0004
 	/* stop RAID background rebuild */
 	/* stop RAID background rebuild */
-#define ACB_F_IOPDATA_OVERFLOW        0x0008
+	#define ACB_F_IOPDATA_OVERFLOW        	0x0008
 	/* iop message data rqbuffer overflow */
 	/* iop message data rqbuffer overflow */
-#define ACB_F_MESSAGE_WQBUFFER_CLEARED  0x0010
+	#define ACB_F_MESSAGE_WQBUFFER_CLEARED	0x0010
 	/* message clear wqbuffer */
 	/* message clear wqbuffer */
-#define ACB_F_MESSAGE_RQBUFFER_CLEARED  0x0020
+	#define ACB_F_MESSAGE_RQBUFFER_CLEARED  0x0020
 	/* message clear rqbuffer */
 	/* 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 */
 	/* iop init */
 
 
 	struct CommandControlBlock *			pccb_pool[ARCMSR_MAX_FREECCB_NUM];
 	struct CommandControlBlock *			pccb_pool[ARCMSR_MAX_FREECCB_NUM];
 	/* used for memory free */
 	/* used for memory free */
 	struct list_head		ccb_free_list;
 	struct list_head		ccb_free_list;
 	/* head of free ccb list */
 	/* head of free ccb list */
+
 	atomic_t			ccboutstandingcount;
 	atomic_t			ccboutstandingcount;
+	/*The present outstanding command number that in the IOP that
+					waiting for being handled by FW*/
 
 
 	void *				dma_coherent;
 	void *				dma_coherent;
 	/* dma_coherent used for memory free */
 	/* dma_coherent used for memory free */
@@ -353,7 +443,7 @@ struct CommandControlBlock
 {
 {
 	struct ARCMSR_CDB		arcmsr_cdb;
 	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
 	** arcmsr messenger scsi command descriptor size 504 bytes
 	*/
 	*/
 	uint32_t			cdb_shifted_phyaddr;
 	uint32_t			cdb_shifted_phyaddr;
@@ -466,7 +556,9 @@ struct SENSE_DATA
 #define     ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE               0x01
 #define     ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE               0x01
 #define     ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE                    0x1F
 #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 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);
 void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);

+ 33 - 40
drivers/scsi/arcmsr/arcmsr_attr.c

@@ -8,7 +8,7 @@
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
 **
 **
 **     Web site: www.areca.com.tw
 **     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
 ** 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
 ** it under the terms of the GNU General Public License version 2 as
@@ -49,6 +49,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_device.h>
@@ -58,15 +59,14 @@
 
 
 struct class_device_attribute *arcmsr_host_attrs[];
 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 class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *host = class_to_shost(cdev);
 	struct Scsi_Host *host = class_to_shost(cdev);
 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-	struct MessageUnit __iomem *reg = acb->pmu;
 	uint8_t *pQbuffer,*ptmpQbuffer;
 	uint8_t *pQbuffer,*ptmpQbuffer;
 	int32_t allxfer_len = 0;
 	int32_t allxfer_len = 0;
 
 
@@ -85,12 +85,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
 		allxfer_len++;
 		allxfer_len++;
 	}
 	}
 	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
 	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;
 		int32_t iop_len;
 
 
 		acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
 		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);
 		iop_len = readl(&prbuffer->data_len);
 		while (iop_len > 0) {
 		while (iop_len > 0) {
 			acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
 			acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
@@ -99,16 +100,15 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
 			iop_data++;
 			iop_data++;
 			iop_len--;
 			iop_len--;
 		}
 		}
-		writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
-				&reg->inbound_doorbell);
+		arcmsr_iop_message_read(acb);
 	}
 	}
 	return (allxfer_len);
 	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 class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *host = class_to_shost(cdev);
 	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_lastindex = acb->wqbuf_lastindex;
 	wqbuf_firstindex = acb->wqbuf_firstindex;
 	wqbuf_firstindex = acb->wqbuf_firstindex;
 	if (wqbuf_lastindex != wqbuf_firstindex) {
 	if (wqbuf_lastindex != wqbuf_firstindex) {
-		arcmsr_post_Qbuffer(acb);
+		arcmsr_post_ioctldata2iop(acb);
 		return 0;	/*need retry*/
 		return 0;	/*need retry*/
 	} else {
 	} else {
 		my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
 		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) {
 			if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
 				acb->acb_flags &=
 				acb->acb_flags &=
 					~ACB_F_MESSAGE_WQBUFFER_CLEARED;
 					~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-				arcmsr_post_Qbuffer(acb);
+				arcmsr_post_ioctldata2iop(acb);
 			}
 			}
 			return count;
 			return count;
 		} else {
 		} 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 class_device *cdev = container_of(kobj,struct class_device,kobj);
 	struct Scsi_Host *host = class_to_shost(cdev);
 	struct Scsi_Host *host = class_to_shost(cdev);
 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-	struct MessageUnit __iomem *reg = acb->pmu;
 	uint8_t *pQbuffer;
 	uint8_t *pQbuffer;
 
 
 	if (!capable(CAP_SYS_ADMIN))
 	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) {
 	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
 		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->acb_flags |=
 		(ACB_F_MESSAGE_WQBUFFER_CLEARED
 		(ACB_F_MESSAGE_WQBUFFER_CLEARED
@@ -191,6 +189,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
 	.attr = {
 	.attr = {
 		.name = "mu_read",
 		.name = "mu_read",
 		.mode = S_IRUSR ,
 		.mode = S_IRUSR ,
+		.owner = THIS_MODULE,
 	},
 	},
 	.size = 1032,
 	.size = 1032,
 	.read = arcmsr_sysfs_iop_message_read,
 	.read = arcmsr_sysfs_iop_message_read,
@@ -200,6 +199,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
 	.attr = {
 	.attr = {
 		.name = "mu_write",
 		.name = "mu_write",
 		.mode = S_IWUSR,
 		.mode = S_IWUSR,
+		.owner = THIS_MODULE,
 	},
 	},
 	.size = 1032,
 	.size = 1032,
 	.write = arcmsr_sysfs_iop_message_write,
 	.write = arcmsr_sysfs_iop_message_write,
@@ -209,6 +209,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
 	.attr = {
 	.attr = {
 		.name = "mu_clear",
 		.name = "mu_clear",
 		.mode = S_IWUSR,
 		.mode = S_IWUSR,
+		.owner = THIS_MODULE,
 	},
 	},
 	.size = 1,
 	.size = 1,
 	.write = arcmsr_sysfs_iop_message_clear,
 	.write = arcmsr_sysfs_iop_message_clear,
@@ -219,31 +220,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
 	struct Scsi_Host *host = acb->host;
 	struct Scsi_Host *host = acb->host;
 	int error;
 	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) {
 	if (error) {
 		printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
 		printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
 		goto error_bin_file_message_read;
 		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) {
 	if (error) {
 		printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
 		printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
 		goto error_bin_file_message_write;
 		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) {
 	if (error) {
 		printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
 		printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
 		goto error_bin_file_message_clear;
 		goto error_bin_file_message_clear;
 	}
 	}
 	return 0;
 	return 0;
 error_bin_file_message_clear:
 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:
 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:
 error_bin_file_message_read:
 	return error;
 	return error;
 }
 }
@@ -252,12 +248,9 @@ void
 arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
 arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
 	struct Scsi_Host *host = acb->host;
 	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);
 }
 }
 
 
 
 

+ 1369 - 893
drivers/scsi/arcmsr/arcmsr_hba.c

@@ -9,7 +9,7 @@
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
 **
 **
 **     Web site: www.areca.com.tw
 **     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
 ** 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
 ** it under the terms of the GNU General Public License version 2 as
@@ -71,33 +71,34 @@
 #include <scsi/scsicam.h>
 #include <scsi/scsicam.h>
 #include "arcmsr.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_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(ARCMSR_DRIVER_VERSION);
 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_abort(struct scsi_cmnd *);
 static int arcmsr_bus_reset(struct scsi_cmnd *);
 static int arcmsr_bus_reset(struct scsi_cmnd *);
 static int arcmsr_bios_param(struct scsi_device *sdev,
 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,
 static int arcmsr_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id);
 				const struct pci_device_id *id);
 static void arcmsr_remove(struct pci_dev *pdev);
 static void arcmsr_remove(struct pci_dev *pdev);
 static void arcmsr_shutdown(struct pci_dev *pdev);
 static void arcmsr_shutdown(struct pci_dev *pdev);
 static void arcmsr_iop_init(struct AdapterControlBlock *acb);
 static void arcmsr_iop_init(struct AdapterControlBlock *acb);
 static void arcmsr_free_ccb_pool(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_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 const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
 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)
 	if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
 		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,
 	.use_clustering		= ENABLE_CLUSTERING,
 	.shost_attrs		= arcmsr_host_attrs,
 	.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 = {
 static struct pci_error_handlers arcmsr_pci_error_handlers = {
 	.error_detected		= arcmsr_pci_error_detected,
 	.error_detected		= arcmsr_pci_error_detected,
 	.slot_reset		= arcmsr_pci_slot_reset,
 	.slot_reset		= arcmsr_pci_slot_reset,
 };
 };
-
+#endif
 static struct pci_device_id arcmsr_device_id_table[] = {
 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_1110)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)},
 	{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_1130)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)},
 	{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_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_1210)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)},
 	{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,
 	.probe			= arcmsr_probe,
 	.remove			= arcmsr_remove,
 	.remove			= arcmsr_remove,
 	.shutdown		= arcmsr_shutdown,
 	.shutdown		= arcmsr_shutdown,
+	#ifdef CONFIG_SCSI_ARCMSR_AER
 	.err_handler		= &arcmsr_pci_error_handlers,
 	.err_handler		= &arcmsr_pci_error_handlers,
+	#endif
 };
 };
 
 
 static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
 static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
 {
 {
 	irqreturn_t handle_state;
 	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);
 	handle_state = arcmsr_interrupt(acb);
-	spin_unlock_irqrestore(acb->host->host_lock, flags);
+	spin_unlock(acb->host->host_lock);
+
 	return handle_state;
 	return handle_state;
 }
 }
 
 
@@ -198,68 +207,159 @@ static int arcmsr_bios_param(struct scsi_device *sdev,
 	return 0;
 	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 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 *
 			ARCMSR_MAX_FREECCB_NUM *
 			sizeof (struct CommandControlBlock) + 0x20,
 			sizeof (struct CommandControlBlock) + 0x20,
 			&dma_coherent_handle, GFP_KERNEL);
 			&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;
 	return 0;
 }
 }
 
 
@@ -310,16 +410,11 @@ static int arcmsr_probe(struct pci_dev *pdev,
 	host->unique_id = (bus << 8) | dev_fun;
 	host->unique_id = (bus << 8) | dev_fun;
 	host->irq = pdev->irq;
 	host->irq = pdev->irq;
 	error = pci_request_regions(pdev, "arcmsr");
 	error = pci_request_regions(pdev, "arcmsr");
-	if (error)
+	if (error) {
 		goto out_host_put;
 		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->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
 			   ACB_F_MESSAGE_RQBUFFER_CLEARED |
 			   ACB_F_MESSAGE_RQBUFFER_CLEARED |
 			   ACB_F_MESSAGE_WQBUFFER_READED);
 			   ACB_F_MESSAGE_WQBUFFER_READED);
@@ -328,10 +423,10 @@ static int arcmsr_probe(struct pci_dev *pdev,
 
 
 	error = arcmsr_alloc_ccb_pool(acb);
 	error = arcmsr_alloc_ccb_pool(acb);
 	if (error)
 	if (error)
-		goto out_iounmap;
+		goto out_release_regions;
 
 
 	error = request_irq(pdev->irq, arcmsr_do_interrupt,
 	error = request_irq(pdev->irq, arcmsr_do_interrupt,
-			IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
+			    IRQF_SHARED, "arcmsr", acb);
 	if (error)
 	if (error)
 		goto out_free_ccb_pool;
 		goto out_free_ccb_pool;
 
 
@@ -349,14 +444,15 @@ static int arcmsr_probe(struct pci_dev *pdev,
 		goto out_free_sysfs;
 		goto out_free_sysfs;
 
 
 	scsi_scan_host(host);
 	scsi_scan_host(host);
+	#ifdef CONFIG_SCSI_ARCMSR_AER
 	pci_enable_pcie_error_reporting(pdev);
 	pci_enable_pcie_error_reporting(pdev);
+	#endif
 	return 0;
 	return 0;
  out_free_sysfs:
  out_free_sysfs:
  out_free_irq:
  out_free_irq:
 	free_irq(pdev->irq, acb);
 	free_irq(pdev->irq, acb);
  out_free_ccb_pool:
  out_free_ccb_pool:
 	arcmsr_free_ccb_pool(acb);
 	arcmsr_free_ccb_pool(acb);
- out_iounmap:
 	iounmap(acb->pmu);
 	iounmap(acb->pmu);
  out_release_regions:
  out_release_regions:
 	pci_release_regions(pdev);
 	pci_release_regions(pdev);
@@ -368,17 +464,84 @@ static int arcmsr_probe(struct pci_dev *pdev,
 	return error;
 	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);
 	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
 		printk(KERN_NOTICE
 			"arcmsr%d: wait 'abort all outstanding command' timeout \n"
 			"arcmsr%d: wait 'abort all outstanding command' timeout \n"
 			, acb->host->host_no);
 			, 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)
 static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
 {
 {
 	struct scsi_cmnd *pcmd = ccb->pcmd;
 	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);
 	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)
 static void arcmsr_remove(struct pci_dev *pdev)
 {
 {
 	struct Scsi_Host *host = pci_get_drvdata(pdev);
 	struct Scsi_Host *host = pci_get_drvdata(pdev);
 	struct AdapterControlBlock *acb =
 	struct AdapterControlBlock *acb =
 		(struct AdapterControlBlock *) host->hostdata;
 		(struct AdapterControlBlock *) host->hostdata;
-	struct MessageUnit __iomem *reg = acb->pmu;
 	int poll_count = 0;
 	int poll_count = 0;
 
 
 	arcmsr_free_sysfs_attr(acb);
 	arcmsr_free_sysfs_attr(acb);
 	scsi_remove_host(host);
 	scsi_remove_host(host);
 	arcmsr_stop_adapter_bgrb(acb);
 	arcmsr_stop_adapter_bgrb(acb);
 	arcmsr_flush_adapter_cache(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_SCSISTOPADAPTER;
 	acb->acb_flags &= ~ACB_F_IOP_INITED;
 	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))
 		if (!atomic_read(&acb->ccboutstandingcount))
 			break;
 			break;
-		arcmsr_interrupt(acb);
+		arcmsr_interrupt(acb);/* FIXME: need spinlock */
 		msleep(25);
 		msleep(25);
 	}
 	}
 
 
@@ -429,8 +803,7 @@ static void arcmsr_remove(struct pci_dev *pdev)
 		int i;
 		int i;
 
 
 		arcmsr_abort_allcmd(acb);
 		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++) {
 		for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
 			struct CommandControlBlock *ccb = acb->pccb_pool[i];
 			struct CommandControlBlock *ccb = acb->pccb_pool[i];
 			if (ccb->startdone == ARCMSR_CCB_START) {
 			if (ccb->startdone == ARCMSR_CCB_START) {
@@ -477,77 +850,34 @@ static void arcmsr_module_exit(void)
 module_init(arcmsr_module_init);
 module_init(arcmsr_module_init);
 module_exit(arcmsr_module_exit);
 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;
 	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;
 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
 	int8_t *psge = (int8_t *)&arcmsr_cdb->u;
 	int8_t *psge = (int8_t *)&arcmsr_cdb->u;
@@ -556,7 +886,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
 	int nseg;
 	int nseg;
 
 
 	ccb->pcmd = pcmd;
 	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->Bus = 0;
 	arcmsr_cdb->TargetID = pcmd->device->id;
 	arcmsr_cdb->TargetID = pcmd->device->id;
 	arcmsr_cdb->LUN = pcmd->device->lun;
 	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)
 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;
 	uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr;
 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
-
 	atomic_inc(&acb->ccboutstandingcount);
 	atomic_inc(&acb->ccboutstandingcount);
 	ccb->startdone = ARCMSR_CCB_START;
 	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);
 			&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;
 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
 	writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, &reg->inbound_msgaddr0);
 	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
 		printk(KERN_NOTICE
 			"arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
 			"arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
 			, acb->host->host_no);
 			, 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)
 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);
 		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;
 	return IRQ_HANDLED;
 }
 }
 
 
@@ -818,16 +1290,47 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
 	if (acb) {
 	if (acb) {
 		/* stop adapter background rebuild */
 		/* stop adapter background rebuild */
 		if (acb->acb_flags & ACB_F_MSG_START_BGRB) {
 		if (acb->acb_flags & ACB_F_MSG_START_BGRB) {
+			uint32_t intmask_org;
 			acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
 			acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+			intmask_org = arcmsr_disable_outbound_ints(acb);
 			arcmsr_stop_adapter_bgrb(acb);
 			arcmsr_stop_adapter_bgrb(acb);
 			arcmsr_flush_adapter_cache(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;
 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
 	int retvalue = 0, transfer_len = 0;
 	int retvalue = 0, transfer_len = 0;
 	char *buffer;
 	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[6] << 16 |
 						(uint32_t ) cmd->cmnd[7] << 8  |
 						(uint32_t ) cmd->cmnd[7] << 8  |
 						(uint32_t ) cmd->cmnd[8];
 						(uint32_t ) cmd->cmnd[8];
-					/* 4 bytes: Areca io control code */
+						/* 4 bytes: Areca io control code */
 
 
 	sg = scsi_sglist(cmd);
 	sg = scsi_sglist(cmd);
 	buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 	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;
 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
 	switch(controlcode) {
 	switch(controlcode) {
+
 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
 	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;
 		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 *sensebuffer =
 					(struct SENSE_DATA *)cmd->sense_buffer;
 					(struct SENSE_DATA *)cmd->sense_buffer;
-				arcmsr_post_Qbuffer(acb);
-				/* has error report sensedata */
 				sensebuffer->ErrorCode = 0x70;
 				sensebuffer->ErrorCode = 0x70;
 				sensebuffer->SenseKey = ILLEGAL_REQUEST;
 				sensebuffer->SenseKey = ILLEGAL_REQUEST;
 				sensebuffer->AdditionalSenseLength = 0x0A;
 				sensebuffer->AdditionalSenseLength = 0x0A;
 				sensebuffer->AdditionalSenseCode = 0x20;
 				sensebuffer->AdditionalSenseCode = 0x20;
 				sensebuffer->Valid = 1;
 				sensebuffer->Valid = 1;
 				retvalue = ARCMSR_MESSAGE_FAIL;
 				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);
 			pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
 		}
 		}
 		break;
 		break;
+
 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
 	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;
 		break;
+
 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
 	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;
 		break;
+
 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
 	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;
 		break;
+
 	case ARCMSR_MESSAGE_RETURN_CODE_3F: {
 	case ARCMSR_MESSAGE_RETURN_CODE_3F: {
-			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
+		pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
 		}
 		}
 		break;
 		break;
+
 	case ARCMSR_MESSAGE_SAY_HELLO: {
 	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;
 		break;
+
 	case ARCMSR_MESSAGE_SAY_GOODBYE:
 	case ARCMSR_MESSAGE_SAY_GOODBYE:
 		arcmsr_iop_parking(acb);
 		arcmsr_iop_parking(acb);
 		break;
 		break;
+
 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
 		arcmsr_flush_adapter_cache(acb);
 		arcmsr_flush_adapter_cache(acb);
 		break;
 		break;
+
 	default:
 	default:
 		retvalue = ARCMSR_MESSAGE_FAIL;
 		retvalue = ARCMSR_MESSAGE_FAIL;
 	}
 	}
- message_out:
+	message_out:
 	sg = scsi_sglist(cmd);
 	sg = scsi_sglist(cmd);
 	kunmap_atomic(buffer - sg->offset, KM_IRQ0);
 	kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-
 	return retvalue;
 	return retvalue;
 }
 }
 
 
@@ -1109,8 +1617,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
 	void (* done)(struct scsi_cmnd *))
 	void (* done)(struct scsi_cmnd *))
 {
 {
 	struct Scsi_Host *host = cmd->device->host;
 	struct Scsi_Host *host = cmd->device->host;
-	struct AdapterControlBlock *acb =
-		(struct AdapterControlBlock *) host->hostdata;
+	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
 	struct CommandControlBlock *ccb;
 	struct CommandControlBlock *ccb;
 	int target = cmd->device->id;
 	int target = cmd->device->id;
 	int lun = cmd->device->lun;
 	int lun = cmd->device->lun;
@@ -1153,26 +1660,27 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
 	ccb = arcmsr_get_freeccb(acb);
 	ccb = arcmsr_get_freeccb(acb);
 	if (!ccb)
 	if (!ccb)
 		return SCSI_MLQUEUE_HOST_BUSY;
 		return SCSI_MLQUEUE_HOST_BUSY;
+
 	arcmsr_build_ccb(acb, ccb, cmd);
 	arcmsr_build_ccb(acb, ccb, cmd);
 	arcmsr_post_ccb(acb, ccb);
 	arcmsr_post_ccb(acb, ccb);
 	return 0;
 	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_model = acb->firm_model;
 	char *acb_firm_version = acb->firm_version;
 	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;
 	int count;
 
 
 	writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
 	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;
 	count = 8;
 	while (count) {
 	while (count) {
 		*acb_firm_model = readb(iop_firm_model);
 		*acb_firm_model = readb(iop_firm_model);
@@ -1180,6 +1688,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
 		iop_firm_model++;
 		iop_firm_model++;
 		count--;
 		count--;
 	}
 	}
+
 	count = 16;
 	count = 16;
 	while (count) {
 	while (count) {
 		*acb_firm_version = readb(iop_firm_version);
 		*acb_firm_version = readb(iop_firm_version);
@@ -1187,28 +1696,93 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
 		iop_firm_version++;
 		iop_firm_version++;
 		count--;
 		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->host->host_no
 		, acb->firm_version);
 		, acb->firm_version);
+
 	acb->firm_request_len = readl(&reg->message_rwbuffer[1]);
 	acb->firm_request_len = readl(&reg->message_rwbuffer[1]);
 	acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]);
 	acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]);
 	acb->firm_sdram_size = readl(&reg->message_rwbuffer[3]);
 	acb->firm_sdram_size = readl(&reg->message_rwbuffer[3]);
 	acb->firm_hd_channels = readl(&reg->message_rwbuffer[4]);
 	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 CommandControlBlock *poll_ccb)
 {
 {
-	struct MessageUnit __iomem *reg = acb->pmu;
+	struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
 	struct CommandControlBlock *ccb;
 	struct CommandControlBlock *ccb;
 	uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0;
 	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++;
 	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*/
 	writel(outbound_intstatus, &reg->outbound_intstatus);/*clear interrupt*/
 	while (1) {
 	while (1) {
 		if ((flag_ccb = readl(&reg->outbound_queueport)) == 0xFFFFFFFF) {
 		if ((flag_ccb = readl(&reg->outbound_queueport)) == 0xFFFFFFFF) {
@@ -1218,17 +1792,14 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
 				msleep(25);
 				msleep(25);
 				if (poll_count > 100)
 				if (poll_count > 100)
 					break;
 					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"
 					" poll command abort successfully \n"
 					, acb->host->host_no
 					, acb->host->host_no
 					, ccb->pcmd->device->id
 					, ccb->pcmd->device->id
@@ -1239,176 +1810,280 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
 				poll_ccb_done = 1;
 				poll_ccb_done = 1;
 				continue;
 				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"
 				"ccboutstandingcount = %d \n"
 				, acb->host->host_no
 				, acb->host->host_no
 				, ccb
 				, ccb
 				, atomic_read(&acb->ccboutstandingcount));
 				, atomic_read(&acb->ccboutstandingcount));
 			continue;
 			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);
 					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
 					, 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;
 	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) {
 	if (atomic_read(&acb->ccboutstandingcount) != 0) {
 		/* talk to iop 331 outstanding command aborted */
 		/* talk to iop 331 outstanding command aborted */
 		arcmsr_abort_allcmd(acb);
 		arcmsr_abort_allcmd(acb);
+
 		/* wait for 3 sec for all command aborted*/
 		/* wait for 3 sec for all command aborted*/
-		msleep_interruptible(3000);
+		ssleep(3);
+
 		/* disable all outbound interrupt */
 		/* disable all outbound interrupt */
 		intmask_org = arcmsr_disable_outbound_ints(acb);
 		intmask_org = arcmsr_disable_outbound_ints(acb);
 		/* clear all outbound posted Q */
 		/* clear all outbound posted Q */
-		arcmsr_done4_abort_postqueue(acb);
+		arcmsr_done4abort_postqueue(acb);
 		for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
 		for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
 			ccb = acb->pccb_pool[i];
 			ccb = acb->pccb_pool[i];
 			if (ccb->startdone == ARCMSR_CCB_START) {
 			if (ccb->startdone == ARCMSR_CCB_START) {
 				ccb->startdone = ARCMSR_CCB_ABORTED;
 				ccb->startdone = ARCMSR_CCB_ABORTED;
+				arcmsr_ccb_complete(ccb, 1);
 			}
 			}
 		}
 		}
 		/* enable all outbound interrupt */
 		/* enable all outbound interrupt */
 		arcmsr_enable_outbound_ints(acb, intmask_org);
 		arcmsr_enable_outbound_ints(acb, intmask_org);
 	}
 	}
-
 }
 }
 
 
 static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
 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++) {
 	for (i = 0; i < 400; i++) {
 		if (!atomic_read(&acb->ccboutstandingcount))
 		if (!atomic_read(&acb->ccboutstandingcount))
 			break;
 			break;
-		arcmsr_interrupt(acb);
+		arcmsr_interrupt(acb);/* FIXME: need spinlock */
 		msleep(25);
 		msleep(25);
 	}
 	}
 	arcmsr_iop_reset(acb);
 	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.
 	** Wait for 3 sec for all command done.
 	*/
 	*/
-	msleep_interruptible(3000);
+	ssleep(3);
 
 
 	intmask = arcmsr_disable_outbound_ints(acb);
 	intmask = arcmsr_disable_outbound_ints(acb);
 	arcmsr_polling_ccbdone(acb, ccb);
 	arcmsr_polling_ccbdone(acb, ccb);
@@ -1515,6 +2192,8 @@ static const char *arcmsr_info(struct Scsi_Host *host)
 
 
 	switch (acb->pdev->device) {
 	switch (acb->pdev->device) {
 	case PCI_DEVICE_ID_ARECA_1110:
 	case PCI_DEVICE_ID_ARECA_1110:
+	case PCI_DEVICE_ID_ARECA_1200:
+	case PCI_DEVICE_ID_ARECA_1202:
 	case PCI_DEVICE_ID_ARECA_1210:
 	case PCI_DEVICE_ID_ARECA_1210:
 		raid6 = 0;
 		raid6 = 0;
 		/*FALLTHRU*/
 		/*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_1130:
 	case PCI_DEVICE_ID_ARECA_1160:
 	case PCI_DEVICE_ID_ARECA_1160:
 	case PCI_DEVICE_ID_ARECA_1170:
 	case PCI_DEVICE_ID_ARECA_1170:
+	case PCI_DEVICE_ID_ARECA_1201:
 	case PCI_DEVICE_ID_ARECA_1220:
 	case PCI_DEVICE_ID_ARECA_1220:
 	case PCI_DEVICE_ID_ARECA_1230:
 	case PCI_DEVICE_ID_ARECA_1230:
 	case PCI_DEVICE_ID_ARECA_1260:
 	case PCI_DEVICE_ID_ARECA_1260:
@@ -1544,287 +2224,82 @@ static const char *arcmsr_info(struct Scsi_Host *host)
 			ARCMSR_DRIVER_VERSION);
 			ARCMSR_DRIVER_VERSION);
 	return buf;
 	return buf;
 }
 }
-
+#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_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;
 		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->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
 			   ACB_F_MESSAGE_RQBUFFER_CLEARED |
 			   ACB_F_MESSAGE_RQBUFFER_CLEARED |
 			   ACB_F_MESSAGE_WQBUFFER_READED);
 			   ACB_F_MESSAGE_WQBUFFER_READED);
 	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
 	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;
 	return PCI_ERS_RESULT_RECOVERED;
 }
 }
 
 
 static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
 static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
 {
 {
 	struct Scsi_Host *host = pci_get_drvdata(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;
 	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)
 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,
 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;
 			break;
 	default:
 	default:
 			return PCI_ERS_RESULT_NEED_RESET;
 			return PCI_ERS_RESULT_NEED_RESET;
-	}
+	  }
 }
 }
+#endif

+ 10 - 17
drivers/scsi/atari_NCR5380.c

@@ -2041,7 +2041,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 				sink = 1;
 				sink = 1;
 				do_abort(instance);
 				do_abort(instance);
 				cmd->result = DID_ERROR << 16;
 				cmd->result = DID_ERROR << 16;
-				cmd->done(cmd);
+				cmd->scsi_done(cmd);
 				return;
 				return;
 #endif
 #endif
 			case PHASE_DATAIN:
 			case PHASE_DATAIN:
@@ -2100,7 +2100,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 						sink = 1;
 						sink = 1;
 						do_abort(instance);
 						do_abort(instance);
 						cmd->result = DID_ERROR << 16;
 						cmd->result = DID_ERROR << 16;
-						cmd->done(cmd);
+						cmd->scsi_done(cmd);
 						/* XXX - need to source or sink data here, as appropriate */
 						/* XXX - need to source or sink data here, as appropriate */
 					} else {
 					} else {
 #ifdef REAL_DMA
 #ifdef REAL_DMA
@@ -2235,24 +2235,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
 
 #ifdef AUTOSENSE
 #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) &&
 					if ((cmd->cmnd[0] != REQUEST_SENSE) &&
 					    (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
 					    (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);
 						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);
 						local_irq_save(flags);
 						LIST(cmd,hostdata->issue_queue);
 						LIST(cmd,hostdata->issue_queue);

+ 3 - 4
drivers/scsi/bvme6000_scsi.c

@@ -36,19 +36,18 @@ static struct platform_device *bvme6000_scsi_device;
 static __devinit int
 static __devinit int
 bvme6000_probe(struct device *dev)
 bvme6000_probe(struct device *dev)
 {
 {
-	struct Scsi_Host * host = NULL;
+	struct Scsi_Host *host;
 	struct NCR_700_Host_Parameters *hostdata;
 	struct NCR_700_Host_Parameters *hostdata;
 
 
 	if (!MACH_IS_BVME6000)
 	if (!MACH_IS_BVME6000)
 		goto out;
 		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: "
 		printk(KERN_ERR "bvme6000-scsi: "
 				"Failed to allocate host data\n");
 				"Failed to allocate host data\n");
 		goto out;
 		goto out;
 	}
 	}
-	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 
 
 	/* Fill in the required pieces of hostdata */
 	/* Fill in the required pieces of hostdata */
 	hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
 	hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;

+ 15 - 1
drivers/scsi/constants.c

@@ -1235,7 +1235,21 @@ scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
 }
 }
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 
 
+/*
+ * Print normalized SCSI sense header with device information and a prefix.
+ */
 void
 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,
 scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
 		       struct scsi_sense_hdr *sshdr)
 		       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,
 scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len,
 			 struct scsi_sense_hdr *sshdr)
 			 struct scsi_sense_hdr *sshdr)
 {
 {

+ 55 - 55
drivers/scsi/dc395x.c

@@ -778,7 +778,7 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb)
 		struct ScsiReqBlk *srb)
 {
 {
 	dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n",
 	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);
 	list_add(&srb->list, &dcb->srb_waiting_list);
 }
 }
 
 
@@ -787,7 +787,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb)
 		struct ScsiReqBlk *srb)
 {
 {
 	dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n",
 	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);
 	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)
 static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
 {
 {
 	dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n",
 	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);
 	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 *i;
 	struct ScsiReqBlk *tmp;
 	struct ScsiReqBlk *tmp;
 	dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n",
 	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)
 	list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list)
 		if (i == srb) {
 		if (i == srb) {
@@ -821,7 +821,7 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb,
 	struct ScsiReqBlk *i;
 	struct ScsiReqBlk *i;
 	struct ScsiReqBlk *tmp;
 	struct ScsiReqBlk *tmp;
 	dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n",
 	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)
 	list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list)
 		if (i == srb) {
 		if (i == srb) {
@@ -836,7 +836,7 @@ static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb,
 {
 {
 	dprintkdbg(DBG_0,
 	dprintkdbg(DBG_0,
 		"srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n",
 		"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);
 	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,
 	dprintkdbg(DBG_0,
 		"srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n",
 		"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);
 	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;
 	int nseg;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n",
 	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->dcb = dcb;
 	srb->cmd = cmd;
 	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 *acb =
 	    (struct AdapterCtlBlk *)cmd->device->host->hostdata;
 	    (struct AdapterCtlBlk *)cmd->device->host->hostdata;
 	dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n",
 	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 */
 	/* Assume BAD_TARGET; will be cleared later */
 	cmd->result = DID_BAD_TARGET << 16;
 	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 */
 		/* process immediately */
 		send_srb(acb, srb);
 		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;
 	return 0;
 
 
 complete:
 complete:
@@ -1203,7 +1203,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb,
 		else
 		else
 			dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) "
 			dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) "
 				 "cmnd=0x%02x <%02i-%i>\n",
 				 "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->cmnd[0], srb->cmd->device->id,
 			       	srb->cmd->device->lun);
 			       	srb->cmd->device->lun);
 		printk("  sglist=%p cnt=%i idx=%i len=%zu\n",
 		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;
 		(struct AdapterCtlBlk *)cmd->device->host->hostdata;
 	dprintkl(KERN_INFO,
 	dprintkl(KERN_INFO,
 		"eh_bus_reset: (pid#%li) target=<%02i-%i> cmd=%p\n",
 		"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))
 	if (timer_pending(&acb->waiting_timer))
 		del_timer(&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 DeviceCtlBlk *dcb;
 	struct ScsiReqBlk *srb;
 	struct ScsiReqBlk *srb;
 	dprintkl(KERN_INFO, "eh_abort: (pid#%li) target=<%02i-%i> cmd=%p\n",
 	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);
 	dcb = find_dcb(acb, cmd->device->id, cmd->device->lun);
 	if (!dcb) {
 	if (!dcb) {
@@ -1494,7 +1494,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
 	u8 s_stat, scsicommand, i, identify_message;
 	u8 s_stat, scsicommand, i, identify_message;
 	u8 *ptr;
 	u8 *ptr;
 	dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> srb=%p\n",
 	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 */
 	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 1
 	if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) {
 	if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) {
 		dprintkdbg(DBG_KG, "start_scsi: (pid#%li) BUSY %02x %04x\n",
 		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?
 		 * Try anyway?
 		 *
 		 *
@@ -1522,14 +1522,14 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
 	if (acb->active_dcb) {
 	if (acb->active_dcb) {
 		dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a"
 		dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a"
 			"command while another command (pid#%li) is active.",
 			"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 ?
-			    acb->active_dcb->active_srb->cmd->pid : 0);
+			    acb->active_dcb->active_srb->cmd->serial_number : 0);
 		return 1;
 		return 1;
 	}
 	}
 	if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) {
 	if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) {
 		dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n",
 		dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n",
-			srb->cmd->pid);
+			srb->cmd->serial_number);
 		return 1;
 		return 1;
 	}
 	}
 	/* Allow starting of SCSI commands half a second before we allow the mid-level
 	/* 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) {
 		if (tag_number >= dcb->max_command) {
 			dprintkl(KERN_WARNING, "start_scsi: (pid#%li) "
 			dprintkl(KERN_WARNING, "start_scsi: (pid#%li) "
 				"Out of tags target=<%02i-%i>)\n",
 				"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->cmd->device->lun);
 			srb->state = SRB_READY;
 			srb->state = SRB_READY;
 			DC395x_write16(acb, TRM_S1040_SCSI_CONTROL,
 			DC395x_write16(acb, TRM_S1040_SCSI_CONTROL,
@@ -1622,7 +1622,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
 /*polling:*/
 /*polling:*/
 	/* Send CDB ..command block ......... */
 	/* Send CDB ..command block ......... */
 	dprintkdbg(DBG_KG, "start_scsi: (pid#%li) <%02i-%i> cmnd=0x%02x tag=%i\n",
 	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);
 		srb->cmd->cmnd[0], srb->tag_number);
 	if (srb->flag & AUTO_REQSENSE) {
 	if (srb->flag & AUTO_REQSENSE) {
 		DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE);
 		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!
 		 * : Let's process it first!
 		 */
 		 */
 		dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> Failed - busy\n",
 		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;
 		srb->state = SRB_READY;
 		free_tag(dcb, srb);
 		free_tag(dcb, srb);
 		srb->msg_count = 0;
 		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,
 static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		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))
 	if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT))
 		*pscsi_status = PH_BUS_FREE;	/*.. initial phase */
 		*pscsi_status = PH_BUS_FREE;	/*.. initial phase */
 
 
@@ -1856,18 +1856,18 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 {
 {
 	u16 i;
 	u16 i;
 	u8 *ptr;
 	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");
 	clear_fifo(acb, "msgout_phase1");
 	if (!(srb->state & SRB_MSGOUT)) {
 	if (!(srb->state & SRB_MSGOUT)) {
 		srb->state |= SRB_MSGOUT;
 		srb->state |= SRB_MSGOUT;
 		dprintkl(KERN_DEBUG,
 		dprintkl(KERN_DEBUG,
 			"msgout_phase1: (pid#%li) Phase unexpected\n",
 			"msgout_phase1: (pid#%li) Phase unexpected\n",
-			srb->cmd->pid);	/* So what ? */
+			srb->cmd->serial_number);	/* So what ? */
 	}
 	}
 	if (!srb->msg_count) {
 	if (!srb->msg_count) {
 		dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n",
 		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_write8(acb, TRM_S1040_SCSI_FIFO, MSG_NOP);
 		DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);	/* it's important for atn stop */
 		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);
 		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,
 static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		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);
 	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;
 	struct DeviceCtlBlk *dcb;
 	u8 *ptr;
 	u8 *ptr;
 	u16 i;
 	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");
 	clear_fifo(acb, "command_phase1");
 	DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN);
 	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;
 	u16 scsi_status = *pscsi_status;
 	u32 d_left_counter = 0;
 	u32 d_left_counter = 0;
 	dprintkdbg(DBG_0, "data_out_phase0: (pid#%li) <%02i-%i>\n",
 	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!
 	 * 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)
 		u16 *pscsi_status)
 {
 {
 	dprintkdbg(DBG_0, "data_out_phase1: (pid#%li) <%02i-%i>\n",
 	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");
 	clear_fifo(acb, "data_out_phase1");
 	/* do prepare before transfer when data out phase */
 	/* do prepare before transfer when data out phase */
 	data_io_transfer(acb, srb, XFERDATAOUT);
 	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;
 	u16 scsi_status = *pscsi_status;
 
 
 	dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n",
 	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
 	 * 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) {
 		if (scsi_status & PARITYERROR) {
 			dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) "
 			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;
 			srb->status |= PARITY_ERROR;
 		}
 		}
 		/*
 		/*
@@ -2395,7 +2395,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		u16 *pscsi_status)
 {
 {
 	dprintkdbg(DBG_0, "data_in_phase1: (pid#%li) <%02i-%i>\n",
 	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);
 	data_io_transfer(acb, srb, XFERDATAIN);
 }
 }
 
 
@@ -2407,7 +2407,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
 	u8 bval;
 	u8 bval;
 	dprintkdbg(DBG_0,
 	dprintkdbg(DBG_0,
 		"data_io_transfer: (pid#%li) <%02i-%i> %c len=%i, sg=(%i/%i)\n",
 		"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'),
 		((io_dir & DMACMD_DIR) ? 'r' : 'w'),
 		srb->total_xfer_length, srb->sg_index, srb->sg_count);
 		srb->total_xfer_length, srb->sg_index, srb->sg_count);
 	if (srb == acb->tmp_srb)
 	if (srb == acb->tmp_srb)
@@ -2580,7 +2580,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		u16 *pscsi_status)
 {
 {
 	dprintkdbg(DBG_0, "status_phase0: (pid#%li) <%02i-%i>\n",
 	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->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
 	srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);	/* get message */
 	srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);	/* get message */
 	srb->state = SRB_COMPLETED;
 	srb->state = SRB_COMPLETED;
@@ -2594,7 +2594,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		u16 *pscsi_status)
 {
 {
 	dprintkdbg(DBG_0, "status_phase1: (pid#%li) <%02i-%i>\n",
 	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;
 	srb->state = SRB_STATUS;
 	DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);	/* it's important for atn stop */
 	DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);	/* it's important for atn stop */
 	DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP);
 	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 *srb = NULL;
 	struct ScsiReqBlk *i;
 	struct ScsiReqBlk *i;
 	dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) tag=%i srb=%p\n",
 	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)))
 	if (!(dcb->tag_mask & (1 << tag)))
 		dprintkl(KERN_DEBUG,
 		dprintkl(KERN_DEBUG,
@@ -2655,7 +2655,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
 		goto mingx0;
 		goto mingx0;
 
 
 	dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) <%02i-%i>\n",
 	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_) {
 	if (dcb->flag & ABORT_DEV_) {
 		/*srb->state = SRB_ABORT_SENT; */
 		/*srb->state = SRB_ABORT_SENT; */
 		enable_msgout_abort(acb, srb);
 		enable_msgout_abort(acb, srb);
@@ -2865,7 +2865,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		u16 *pscsi_status)
 {
 {
 	struct DeviceCtlBlk *dcb = acb->active_dcb;
 	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);
 	srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
 	if (msgin_completed(srb->msgin_buf, acb->msg_len)) {
 	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) "
 			dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
 				"SAVE POINTER rem=%i Ignore\n",
 				"SAVE POINTER rem=%i Ignore\n",
-				srb->cmd->pid, srb->total_xfer_length);
+				srb->cmd->serial_number, srb->total_xfer_length);
 			break;
 			break;
 
 
 		case RESTORE_POINTERS:
 		case RESTORE_POINTERS:
@@ -2943,7 +2943,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		case ABORT:
 		case ABORT:
 			dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
 			dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
 				"<%02i-%i> ABORT msg\n",
 				"<%02i-%i> ABORT msg\n",
-				srb->cmd->pid, dcb->target_id,
+				srb->cmd->serial_number, dcb->target_id,
 				dcb->target_lun);
 				dcb->target_lun);
 			dcb->flag |= ABORT_DEV_;
 			dcb->flag |= ABORT_DEV_;
 			enable_msgout_abort(acb, srb);
 			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,
 static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 		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");
 	clear_fifo(acb, "msgin_phase1");
 	DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1);
 	DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1);
 	if (!(srb->state & SRB_MSGIN)) {
 	if (!(srb->state & SRB_MSGIN)) {
@@ -3041,7 +3041,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
 	}
 	}
 	srb = dcb->active_srb;
 	srb = dcb->active_srb;
 	acb->active_dcb = NULL;
 	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 */
 	srb->scsi_phase = PH_BUS_FREE;	/* initial phase */
 	clear_fifo(acb, "disconnect");
 	clear_fifo(acb, "disconnect");
@@ -3072,13 +3072,13 @@ static void disconnect(struct AdapterCtlBlk *acb)
 				srb->state = SRB_READY;
 				srb->state = SRB_READY;
 				dprintkl(KERN_DEBUG,
 				dprintkl(KERN_DEBUG,
 					"disconnect: (pid#%li) Unexpected\n",
 					"disconnect: (pid#%li) Unexpected\n",
-					srb->cmd->pid);
+					srb->cmd->serial_number);
 				srb->target_status = SCSI_STAT_SEL_TIMEOUT;
 				srb->target_status = SCSI_STAT_SEL_TIMEOUT;
 				goto disc1;
 				goto disc1;
 			} else {
 			} else {
 				/* Normal selection timeout */
 				/* Normal selection timeout */
 				dprintkdbg(DBG_KG, "disconnect: (pid#%li) "
 				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);
 					dcb->target_id, dcb->target_lun);
 				if (srb->retry_count++ > DC395x_MAX_RETRIES
 				if (srb->retry_count++ > DC395x_MAX_RETRIES
 				    || acb->scan_devices) {
 				    || acb->scan_devices) {
@@ -3090,7 +3090,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
 				srb_going_to_waiting_move(dcb, srb);
 				srb_going_to_waiting_move(dcb, srb);
 				dprintkdbg(DBG_KG,
 				dprintkdbg(DBG_KG,
 					"disconnect: (pid#%li) Retry\n",
 					"disconnect: (pid#%li) Retry\n",
-					srb->cmd->pid);
+					srb->cmd->serial_number);
 				waiting_set_timer(acb, HZ / 20);
 				waiting_set_timer(acb, HZ / 20);
 			}
 			}
 		} else if (srb->state & SRB_DISCONNECT) {
 		} else if (srb->state & SRB_DISCONNECT) {
@@ -3144,7 +3144,7 @@ static void reselect(struct AdapterCtlBlk *acb)
 		if (!acb->scan_devices) {
 		if (!acb->scan_devices) {
 			dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> "
 			dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> "
 				"Arb lost but Resel win rsel=%i stat=0x%04x\n",
 				"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,
 				dcb->target_lun, rsel_tar_lun_id,
 				DC395x_read16(acb, TRM_S1040_SCSI_STATUS));
 				DC395x_read16(acb, TRM_S1040_SCSI_STATUS));
 			arblostflag = 1;
 			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;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	int ckc_only = 1;
 	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);
 		srb->cmd->device->id, srb->cmd->device->lun);
 	dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
 	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,
 		   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)
 		if (srb->total_xfer_length)
 			dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> "
 			dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> "
 				"cmnd=0x%02x Missed %i bytes\n",
 				"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);
 				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");
 		dprintkl(KERN_ERR, "srb_done: ERROR! Completed cmd with tmp_srb\n");
 	else {
 	else {
 		dprintkdbg(DBG_0, "srb_done: (pid#%li) done result=0x%08x\n",
 		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);
 		srb_free_insert(acb, srb);
 	}
 	}
 	pci_unmap_srb(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;
 			p = srb->cmd;
 			dir = p->sc_data_direction;
 			dir = p->sc_data_direction;
 			result = MK_RES(0, did_flag, 0, 0);
 			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);
 			       p->device->id, p->device->lun);
 			srb_going_remove(dcb, srb);
 			srb_going_remove(dcb, srb);
 			free_tag(dcb, srb);
 			free_tag(dcb, srb);
@@ -3568,7 +3568,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
 			p = srb->cmd;
 			p = srb->cmd;
 
 
 			result = MK_RES(0, did_flag, 0, 0);
 			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);
 			       p->device->lun);
 			srb_waiting_remove(dcb, srb);
 			srb_waiting_remove(dcb, srb);
 			srb_free_insert(acb, 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;
 	struct scsi_cmnd *cmd = srb->cmd;
 	dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n",
 	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->flag |= AUTO_REQSENSE;
 	srb->adapter_status = 0;
 	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 */
 	if (start_scsi(acb, dcb, srb)) {	/* Should only happen, if sb. else grabs the bus */
 		dprintkl(KERN_DEBUG,
 		dprintkl(KERN_DEBUG,
 			"request_sense: (pid#%li) failed <%02i-%i>\n",
 			"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);
 		srb_going_to_waiting_move(dcb, srb);
 		waiting_set_timer(acb, HZ / 100);
 		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,
 				dcb->target_id, dcb->target_lun,
 				list_size(&dcb->srb_waiting_list));
 				list_size(&dcb->srb_waiting_list));
                 list_for_each_entry(srb, &dcb->srb_waiting_list, 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))
 		if (!list_empty(&dcb->srb_going_list))
 			SPRINTF("\nDCB (%02i-%i): Going  : %i:",
 			SPRINTF("\nDCB (%02i-%i): Going  : %i:",
 				dcb->target_id, dcb->target_lun,
 				dcb->target_id, dcb->target_lun,
 				list_size(&dcb->srb_going_list));
 				list_size(&dcb->srb_going_list));
 		list_for_each_entry(srb, &dcb->srb_going_list, 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))
 		if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list))
 			SPRINTF("\n");
 			SPRINTF("\n");
 	}
 	}

+ 12 - 17
drivers/scsi/dpt_i2o.c

@@ -949,16 +949,14 @@ static int adpt_install_hba(struct pci_dev* pDev)
 	}
 	}
 	
 	
 	// Allocate and zero the data structure
 	// 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(msg_addr_virt);
-		}
 		iounmap(base_addr_virt);
 		iounmap(base_addr_virt);
 		pci_release_regions(pDev);
 		pci_release_regions(pDev);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	memset(pHba, 0, sizeof(adpt_hba));
 
 
 	mutex_lock(&adpt_configuration_lock);
 	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);
 	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);
 		adpt_send_nop(pHba, m);
 		printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
 		printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
 			pHba->name);
 			pHba->name);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	memset(status, 0, 4);
 
 
 	writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
 	writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
 	writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
 	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);
 	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;
 	ptr = pHba->reply_pool;
 	for(i = 0; i < pHba->reply_fifo_size; i++) {
 	for(i = 0; i < pHba->reply_fifo_size; i++) {
@@ -2884,12 +2880,11 @@ static int adpt_i2o_build_sys_table(void)
 
 
 	kfree(sys_tbl);
 	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");	
 		printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");	
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	memset(sys_tbl, 0, sys_tbl_len);
 
 
 	sys_tbl->num_entries = hba_count;
 	sys_tbl->num_entries = hba_count;
 	sys_tbl->version = I2OVERSION;
 	sys_tbl->version = I2OVERSION;
@@ -3351,7 +3346,7 @@ static int __init adpt_init(void)
 	return count > 0 ? 0 : -ENODEV;
 	return count > 0 ? 0 : -ENODEV;
 }
 }
 
 
-static void __exit adpt_exit(void)
+static void adpt_exit(void)
 {
 {
 	while (hba_chain)
 	while (hba_chain)
 		adpt_release(hba_chain);
 		adpt_release(hba_chain);

+ 7 - 9
drivers/scsi/dtc.c

@@ -137,11 +137,9 @@ static struct override {
 #ifdef OVERRIDE
 #ifdef OVERRIDE
 [] __initdata = OVERRIDE;
 [] __initdata = OVERRIDE;
 #else
 #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
 #endif
 
 
 #define NO_OVERRIDES ARRAY_SIZE(overrides)
 #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]
  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  *	equal to the number of ints.
  *	equal to the number of ints.
  *
  *
-*/
+ */
 
 
 static void __init dtc_setup(char *str, int *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
 		} else
 			for (; !addr && (current_base < NO_BASES); ++current_base) {
 			for (; !addr && (current_base < NO_BASES); ++current_base) {
 #if (DTCDEBUG & DTCDEBUG_INIT)
 #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
 #endif
 				if (bases[current_base].noauto)
 				if (bases[current_base].noauto)
 					continue;
 					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))) {
 					if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
 						addr = bases[current_base].address;
 						addr = bases[current_base].address;
 #if (DTCDEBUG & DTCDEBUG_INIT)
 #if (DTCDEBUG & DTCDEBUG_INIT)
-						printk("scsi-dtc : detected board.\n");
+						printk(KERN_DEBUG "scsi-dtc : detected board.\n");
 #endif
 #endif
 						goto found;
 						goto found;
 					}
 					}
@@ -253,7 +251,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
 			}
 			}
 
 
 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
-		printk("scsi-dtc : base = %08x\n", addr);
+		printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr);
 #endif
 #endif
 
 
 		if (!addr)
 		if (!addr)

+ 22 - 22
drivers/scsi/eata.c

@@ -1758,7 +1758,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
 
 	if (SCpnt->host_scribble)
 	if (SCpnt->host_scribble)
 		panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
 		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
 	/* i is the mailbox number, look for the first free mailbox
 	   starting from last_cp_used */
 	   starting from last_cp_used */
@@ -1792,7 +1792,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 
 
 	if (do_trace)
 	if (do_trace)
 		scmd_printk(KERN_INFO, SCpnt,
 		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->reqsen = 1;
 	cpp->dispri = 1;
 	cpp->dispri = 1;
@@ -1825,7 +1825,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
 		unmap_dma(i, ha);
 		unmap_dma(i, ha);
 		SCpnt->host_scribble = NULL;
 		SCpnt->host_scribble = NULL;
 		scmd_printk(KERN_INFO, SCpnt,
 		scmd_printk(KERN_INFO, SCpnt,
-			"qcomm, pid %ld, adapter busy.\n", SCpnt->pid);
+			"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
 		return 1;
 		return 1;
 	}
 	}
 
 
@@ -1841,13 +1841,13 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
 
 
 	if (SCarg->host_scribble == NULL) {
 	if (SCarg->host_scribble == NULL) {
 		scmd_printk(KERN_INFO, SCarg,
 		scmd_printk(KERN_INFO, SCarg,
-			"abort, pid %ld inactive.\n", SCarg->pid);
+			"abort, pid %ld inactive.\n", SCarg->serial_number);
 		return SUCCESS;
 		return SUCCESS;
 	}
 	}
 
 
 	i = *(unsigned int *)SCarg->host_scribble;
 	i = *(unsigned int *)SCarg->host_scribble;
 	scmd_printk(KERN_WARNING, SCarg,
 	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)
 	if (i >= shost->can_queue)
 		panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name);
 		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;
 		SCarg->host_scribble = NULL;
 		ha->cp_stat[i] = FREE;
 		ha->cp_stat[i] = FREE;
 		printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
 		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);
 		SCarg->scsi_done(SCarg);
 		return SUCCESS;
 		return SUCCESS;
 	}
 	}
@@ -1909,12 +1909,12 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
 	struct hostdata *ha = (struct hostdata *)shost->hostdata;
 	struct hostdata *ha = (struct hostdata *)shost->hostdata;
 
 
 	scmd_printk(KERN_INFO, SCarg,
 	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);
 	spin_lock_irq(shost->host_lock);
 
 
 	if (SCarg->host_scribble == NULL)
 	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) {
 	if (ha->in_reset) {
 		printk("%s: reset, exit, already in reset.\n", ha->board_name);
 		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) {
 		if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) {
 			ha->cp_stat[i] = ABORTING;
 			ha->cp_stat[i] = ABORTING;
 			printk("%s: reset, mbox %d aborting, pid %ld.\n",
 			printk("%s: reset, mbox %d aborting, pid %ld.\n",
-			       ha->board_name, i, SCpnt->pid);
+			       ha->board_name, i, SCpnt->serial_number);
 		}
 		}
 
 
 		else {
 		else {
 			ha->cp_stat[i] = IN_RESET;
 			ha->cp_stat[i] = IN_RESET;
 			printk("%s: reset, mbox %d in reset, pid %ld.\n",
 			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)
 		if (SCpnt->host_scribble == NULL)
@@ -2015,7 +2015,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
 
 
 			printk
 			printk
 			    ("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
 			    ("%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) {
 		else if (ha->cp_stat[i] == ABORTING) {
@@ -2029,7 +2029,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
 
 
 			printk
 			printk
 			    ("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
 			    ("%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
 		else
@@ -2043,7 +2043,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
 	do_trace = 0;
 	do_trace = 0;
 
 
 	if (arg_done)
 	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
 	else
 		printk("%s: reset, exit.\n", ha->board_name);
 		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];
 			cpp = &ha->cp[k];
 			SCpnt = cpp->SCpnt;
 			SCpnt = cpp->SCpnt;
 			ll[n] = SCpnt->request->nr_sectors;
 			ll[n] = SCpnt->request->nr_sectors;
-			pl[n] = SCpnt->pid;
+			pl[n] = SCpnt->serial_number;
 
 
 			if (!n)
 			if (!n)
 				continue;
 				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"
 			    "%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",
 			     " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n",
 			     (ihdlr ? "ihdlr" : "qcomm"),
 			     (ihdlr ? "ihdlr" : "qcomm"),
-			     SCpnt->pid, k, flushcount,
+			     SCpnt->serial_number, k, flushcount,
 			     n_ready, SCpnt->request->sector,
 			     n_ready, SCpnt->request->sector,
 			     SCpnt->request->nr_sectors, cursec, YESNO(s),
 			     SCpnt->request->nr_sectors, cursec, YESNO(s),
 			     YESNO(r), YESNO(rev), YESNO(input_only),
 			     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"
 			    "%s, pid %ld, mbox %d, adapter"
 			     " busy, will abort.\n",
 			     " busy, will abort.\n",
 			     (ihdlr ? "ihdlr" : "qcomm"),
 			     (ihdlr ? "ihdlr" : "qcomm"),
-			     SCpnt->pid, k);
+			     SCpnt->serial_number, k);
 			ha->cp_stat[k] = ABORTING;
 			ha->cp_stat[k] = ABORTING;
 			continue;
 			continue;
 		}
 		}
@@ -2391,11 +2391,11 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
 
 
 	if (SCpnt->host_scribble == NULL)
 	if (SCpnt->host_scribble == NULL)
 		panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", ha->board_name,
 		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)
 	if (*(unsigned int *)SCpnt->host_scribble != i)
 		panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
 		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);
 		      *(unsigned int *)SCpnt->host_scribble);
 
 
 	sync_dma(i, ha);
 	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",
 			       "target_status 0x%x, sense key 0x%x.\n",
 			       ha->board_name,
 			       ha->board_name,
 			       SCpnt->device->channel, SCpnt->device->id,
 			       SCpnt->device->channel, SCpnt->device->id,
-			       SCpnt->device->lun, SCpnt->pid,
+			       SCpnt->device->lun, SCpnt->serial_number,
 			       spp->target_status, SCpnt->sense_buffer[2]);
 			       spp->target_status, SCpnt->sense_buffer[2]);
 
 
 		ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0;
 		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;
 			ha->retries = 0;
 
 
 		break;
 		break;
@@ -2485,7 +2485,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
 #endif
 #endif
 
 
 			ha->retries++;
 			ha->retries++;
-			ha->last_retried_pid = SCpnt->pid;
+			ha->last_retried_pid = SCpnt->serial_number;
 		} else
 		} else
 			status = DID_ERROR << 16;
 			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,"
 		scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"
 		       " pid %ld, reg 0x%x, count %d.\n",
 		       " pid %ld, reg 0x%x, count %d.\n",
 		       i, spp->adapter_status, spp->target_status,
 		       i, spp->adapter_status, spp->target_status,
-		       SCpnt->pid, reg, ha->iocount);
+		       SCpnt->serial_number, reg, ha->iocount);
 
 
 	unmap_dma(i, ha);
 	unmap_dma(i, ha);
 
 

+ 45 - 55
drivers/scsi/eata_pio.c

@@ -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,
 static int eata_pio_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
 			      int length, int rw)
 			      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);
 		   "%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);
 		   "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);
 		   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);
 		   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 == 'P')?"PCI ":
 		   (SD(shost)->bustype == 'E')?"EISA":"ISA ");
 		   (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)
 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,
 	DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
 		"eata_pio_queue pid %ld, y %d\n",
 		"eata_pio_queue pid %ld, y %d\n",
-		cmd->pid, y));
+		cmd->serial_number, y));
 
 
 	cmd->scsi_done = (void *) done;
 	cmd->scsi_done = (void *) done;
 
 
@@ -435,10 +420,10 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
 		cmd->result = DID_BUS_BUSY << 16;
 		cmd->result = DID_BUS_BUSY << 16;
 		scmd_printk(KERN_NOTICE, cmd,
 		scmd_printk(KERN_NOTICE, cmd,
 			"eata_pio_queue pid %ld, HBA busy, "
 			"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);
 		done(cmd);
 		cp->status = FREE;
 		cp->status = FREE;
-		return (0);
+		return 0;
 	}
 	}
 	/* FIXME: timeout */
 	/* FIXME: timeout */
 	while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
 	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,
 	DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
 		"Queued base %#.4lx pid: %ld "
 		"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)
 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,
 	DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
 		"eata_pio_abort called pid: %ld\n",
 		"eata_pio_abort called pid: %ld\n",
-		cmd->pid));
+		cmd->serial_number));
 
 
 	while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
 	while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
 		if (--loop == 0) {
 		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,
 	DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
 		"eata_pio_reset called pid:%ld\n",
 		"eata_pio_reset called pid:%ld\n",
-		cmd->pid));
+		cmd->serial_number));
 
 
 	spin_lock_irq(host->host_lock);
 	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;
 		sp = HD(cmd)->ccb[x].cmd;
 		HD(cmd)->ccb[x].status = RESET;
 		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)
 		if (sp == NULL)
 			panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
 			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;
 	cp.cp_cdb[5] = 0;
 
 
 	if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP))
 	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);
 	outsw(base + HA_RDATA, &cp, cplen);
 	outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
 	outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
 	for (z = 0; z < cppadlen; z++)
 	for (z = 0; z < cppadlen; z++)
 		outw(0, base + HA_RDATA);
 		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)
 	if (inb(base + HA_RSTATUS) & HA_SERROR)
-		return (NULL);
+		return NULL;
 	else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
 	else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
-		return (NULL);
+		return NULL;
 	else {
 	else {
 		insw(base + HA_RDATA, &buff, 127);
 		insw(base + HA_RDATA, &buff, 127);
 		while (inb(base + HA_RSTATUS) & HA_SDRQ)
 		while (inb(base + HA_RSTATUS) & HA_SDRQ)
 			inw(base + HA_RDATA);
 			inw(base + HA_RDATA);
-		return (buff);
+		return buff;
 	}
 	}
 }
 }
 
 

+ 5 - 5
drivers/scsi/esp_scsi.c

@@ -2138,7 +2138,7 @@ irqreturn_t scsi_esp_intr(int irq, void *dev_id)
 }
 }
 EXPORT_SYMBOL(scsi_esp_intr);
 EXPORT_SYMBOL(scsi_esp_intr);
 
 
-static void __devinit esp_get_revision(struct esp *esp)
+static void esp_get_revision(struct esp *esp)
 {
 {
 	u8 val;
 	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;
 	int i;
 
 
@@ -2233,7 +2233,7 @@ static void esp_bootup_reset(struct esp *esp)
 	esp_read8(ESP_INTRPT);
 	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;
 	int fmhz;
 	u8 ccf;
 	u8 ccf;
@@ -2306,7 +2306,7 @@ static const char *esp_chip_names[] = {
 
 
 static struct scsi_transport_template *esp_transport_template;
 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;
 	static int instance;
 	int err;
 	int err;
@@ -2346,7 +2346,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev)
 }
 }
 EXPORT_SYMBOL(scsi_esp_register);
 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);
 	scsi_remove_host(esp->host);
 }
 }

+ 4 - 1
drivers/scsi/fdomain.c

@@ -387,7 +387,9 @@ static void __iomem *    bios_mem;
 static int               bios_major;
 static int               bios_major;
 static int               bios_minor;
 static int               bios_minor;
 static int               PCI_bus;
 static int               PCI_bus;
+#ifdef CONFIG_PCI
 static struct pci_dev	*PCI_dev;
 static struct pci_dev	*PCI_dev;
+#endif
 static int               Quantum;	/* Quantum board variant */
 static int               Quantum;	/* Quantum board variant */
 static int               interrupt_level;
 static int               interrupt_level;
 static volatile int      in_command;
 static volatile int      in_command;
@@ -1764,6 +1766,7 @@ struct scsi_host_template fdomain_driver_template = {
 };
 };
 
 
 #ifndef PCMCIA
 #ifndef PCMCIA
+#ifdef CONFIG_PCI
 
 
 static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
 static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
 	{ 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);
 MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl);
-
+#endif
 #define driver_template fdomain_driver_template
 #define driver_template fdomain_driver_template
 #include "scsi_module.c"
 #include "scsi_module.c"
 
 

+ 1 - 1
drivers/scsi/g_NCR5380.c

@@ -556,7 +556,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 }
 }
 #endif
 #endif
 
 
-#if NCR53C400_PSEUDO_DMA
+#ifdef NCR53C400_PSEUDO_DMA
 
 
 /**
 /**
  *	NCR5380_pread		-	pseudo DMA read
  *	NCR5380_pread		-	pseudo DMA read

+ 1254 - 1679
drivers/scsi/gdth.c

@@ -27,280 +27,8 @@
  * along with this kernel; if not, write to the Free Software           *
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  * 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.
 /* All GDT Disk Array Controllers are fully supported by this driver.
@@ -328,8 +56,6 @@
  * max_ids:x                    x - target ID count per channel (1..MAXID)
  * max_ids:x                    x - target ID count per channel (1..MAXID)
  * rescan:Y                     rescan all channels/IDs 
  * rescan:Y                     rescan all channels/IDs 
  * rescan:N                     use all devices found until now
  * 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
  * hdr_channel:x                x - number of virtual bus for host drives
  * shared_access:Y              disable driver reserve/release protocol to 
  * shared_access:Y              disable driver reserve/release protocol to 
  *                              access a shared resource from several nodes, 
  *                              access a shared resource from several nodes, 
@@ -341,7 +67,7 @@
  * force_dma32:N                use 64 bit DMA mode, if supported
  * force_dma32:N                use 64 bit DMA mode, if supported
  *
  *
  * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
  * 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".
  *                          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".
  * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
  * 
  * 
@@ -352,22 +78,22 @@
  * '1' in place of 'Y' and '0' in place of 'N'.
  * '1' in place of 'Y' and '0' in place of 'N'.
  * 
  * 
  * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
  * 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"
  *           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 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:
 /* The meaning of the Scsi_Pointer members in this driver is as follows:
  * ptr:                     Chaining
  * 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
  */
  */
 
 
 
 
@@ -392,12 +118,8 @@
 #include <linux/proc_fs.h>
 #include <linux/proc_fs.h>
 #include <linux/time.h>
 #include <linux/time.h>
 #include <linux/timer.h>
 #include <linux/timer.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
-#else
-#define DMA_32BIT_MASK	0x00000000ffffffffULL
-#define DMA_64BIT_MASK	0xffffffffffffffffULL
-#endif
+#include <linux/list.h>
 
 
 #ifdef GDTH_RTC
 #ifdef GDTH_RTC
 #include <linux/mc146818rtc.h>
 #include <linux/mc146818rtc.h>
@@ -409,29 +131,27 @@
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <linux/blkdev.h>
 #include <linux/blkdev.h>
-#else
-#include <linux/blk.h>
-#include "sd.h"
-#endif
+#include <linux/scatterlist.h>
 
 
 #include "scsi.h"
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_host.h>
-#include "gdth_kcompat.h"
 #include "gdth.h"
 #include "gdth.h"
 
 
 static void gdth_delay(int milliseconds);
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
 static irqreturn_t gdth_interrupt(int irq, void *dev_id);
 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_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,
 static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
                                       ushort idx, gdth_evt_data *evt);
                                       ushort idx, gdth_evt_data *evt);
 static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
 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);
                                gdth_evt_str *estr);
 static void gdth_clear_events(void);
 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_open(struct inode *inode, struct file *filep);
 static int gdth_close(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,
 static int gdth_ioctl(struct inode *inode, struct file *filep,
                       unsigned int cmd, unsigned long arg);
                       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_halt(struct notifier_block *nb, ulong event, void *buf);
 static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
 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);
 static void gdth_scsi_done(struct scsi_cmnd *scp);
 
 
 #ifdef DEBUG_GDTH
 #ifdef DEBUG_GDTH
@@ -571,29 +283,17 @@ static struct timer_list gdth_timer;
 #define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)
 #define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)
 #define INDEX_OK(i,t)   ((i)<ARRAY_SIZE(t))
 #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 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 */
 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 */
 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_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_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 unchar   gdth_write_through = FALSE;             /* write through */
 static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
 static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
 static int elastidx;
 static int elastidx;
@@ -645,8 +345,6 @@ static int hdr_channel = 0;
 static int max_ids = MAXID;
 static int max_ids = MAXID;
 /* rescan all IDs */
 /* rescan all IDs */
 static int rescan = 0;
 static int rescan = 0;
-/* map channels to virtual controllers */
-static int virt_ctr = 0;
 /* shared access */
 /* shared access */
 static int shared_access = 1;
 static int shared_access = 1;
 /* enable support for EISA and ISA controllers */
 /* enable support for EISA and ISA controllers */
@@ -655,7 +353,6 @@ static int probe_eisa_isa = 0;
 static int force_dma32 = 0;
 static int force_dma32 = 0;
 
 
 /* parameters for modprobe/insmod */
 /* parameters for modprobe/insmod */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
 module_param_array(irq, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param(disable, int, 0);
 module_param(disable, int, 0);
 module_param(reserve_mode, 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(hdr_channel, int, 0);
 module_param(max_ids, int, 0);
 module_param(max_ids, int, 0);
 module_param(rescan, int, 0);
 module_param(rescan, int, 0);
-module_param(virt_ctr, int, 0);
 module_param(shared_access, int, 0);
 module_param(shared_access, int, 0);
 module_param(probe_eisa_isa, int, 0);
 module_param(probe_eisa_isa, int, 0);
 module_param(force_dma32, 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_AUTHOR("Achim Leubner");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
@@ -692,6 +374,47 @@ static const struct file_operations gdth_fops = {
     .release = gdth_close,
     .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.h"
 #include "gdth_proc.c"
 #include "gdth_proc.c"
 
 
@@ -701,6 +424,45 @@ static struct notifier_block gdth_notifier = {
 };
 };
 static int notifier_disabled = 0;
 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)
 static void gdth_delay(int milliseconds)
 {
 {
     if (milliseconds == 0) {
     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)
 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 __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
                    int timeout, u32 *info)
                    int timeout, u32 *info)
 {
 {
+    gdth_ha_str *ha = shost_priv(sdev->host);
     Scsi_Cmnd *scp;
     Scsi_Cmnd *scp;
+    struct gdth_cmndinfo cmndinfo;
+    struct scatterlist one_sg;
     DECLARE_COMPLETION_ONSTACK(wait);
     DECLARE_COMPLETION_ONSTACK(wait);
     int rval;
     int rval;
 
 
-    scp = kmalloc(sizeof(*scp), GFP_KERNEL);
+    scp = kzalloc(sizeof(*scp), GFP_KERNEL);
     if (!scp)
     if (!scp)
         return -ENOMEM;
         return -ENOMEM;
-    memset(scp, 0, sizeof(*scp));
+
     scp->device = sdev;
     scp->device = sdev;
+    memset(&cmndinfo, 0, sizeof(cmndinfo));
+
     /* use request field to save the ptr. to completion struct. */
     /* use request field to save the ptr. to completion struct. */
     scp->request = (struct request *)&wait;
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
     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;
     scp->cmd_len = 12;
     memcpy(scp->cmnd, cmnd, 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);
     wait_for_completion(&wait);
 
 
-    rval = scp->SCp.Status;
+    rval = cmndinfo.status;
     if (info)
     if (info)
-        *info = scp->SCp.Message;
-
-    scsi_release_command(scp);
+        *info = cmndinfo.info;
+    kfree(scp);
     return rval;
     return rval;
 }
 }
-#endif
 
 
 int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
 int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
                  int timeout, u32 *info)
                  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 */
 /* controller search and initialization functions */
-
+#ifdef CONFIG_EISA
 static int __init gdth_search_eisa(ushort eisa_adr)
 static int __init gdth_search_eisa(ushort eisa_adr)
 {
 {
     ulong32 id;
     ulong32 id;
@@ -832,8 +576,9 @@ static int __init gdth_search_eisa(ushort eisa_adr)
 
 
     return 0;                                   
     return 0;                                   
 }
 }
+#endif /* CONFIG_EISA */
 
 
-
+#ifdef CONFIG_ISA
 static int __init gdth_search_isa(ulong32 bios_adr)
 static int __init gdth_search_isa(ulong32 bios_adr)
 {
 {
     void __iomem *addr;
     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));
     TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
     if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
     if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
-        id = gdth_readl(addr);
+        id = readl(addr);
         iounmap(addr);
         iounmap(addr);
         if (id == GDT2_ID)                          /* GDT2000 */
         if (id == GDT2_ID)                          /* GDT2000 */
             return 1;
             return 1;
     }
     }
     return 0;
     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)
 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)
 static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
 {    
 {    
     gdth_pci_str temp;
     gdth_pci_str temp;
@@ -965,8 +713,9 @@ static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
         }
         }
     } while (changed);
     } while (changed);
 }
 }
+#endif /* CONFIG_PCI */
 
 
-
+#ifdef CONFIG_EISA
 static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
 static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
 {
 {
     ulong32 retries,id;
     ulong32 retries,id;
@@ -1058,8 +807,9 @@ static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
     ha->dma64_support = 0;
     ha->dma64_support = 0;
     return 1;
     return 1;
 }
 }
+#endif /* CONFIG_EISA */
 
 
-       
+#ifdef CONFIG_ISA
 static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
 static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
 {
 {
     register gdt2_dpram_str __iomem *dp2_ptr;
     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;
         return 0;
     }
     }
     dp2_ptr = ha->brd;
     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 */
     /* reset interface area */
     memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u));
     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");
         printk("GDT-ISA: Initialization error (DPMEM write error)\n");
         iounmap(ha->brd);
         iounmap(ha->brd);
         return 0;
         return 0;
     }
     }
 
 
     /* disable board interrupts, read DRQ and IRQ */
     /* 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) {
     for (i=0; i<3; ++i) {
         if ((irq_drq & 1)==0)
         if ((irq_drq & 1)==0)
             break;
             break;
@@ -1098,7 +848,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
     }
     }
     ha->drq = gdth_drq_tab[i];
     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) {
     for (i=1; i<5; ++i) {
         if ((irq_drq & 1)==0)
         if ((irq_drq & 1)==0)
             break;
             break;
@@ -1107,12 +857,12 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
     ha->irq = gdth_irq_tab[i];
     ha->irq = gdth_irq_tab[i];
 
 
     /* deinitialize services */
     /* 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;
     retries = INIT_RETRIES;
     gdth_delay(20);
     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) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error (DEINIT failed)\n");
             printk("GDT-ISA: Initialization error (DEINIT failed)\n");
             iounmap(ha->brd);
             iounmap(ha->brd);
@@ -1120,9 +870,9 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
         }
         }
         gdth_delay(1);
         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) {
     if (prot_ver != PROTOCOL_VERSION) {
         printk("GDT-ISA: Illegal protocol version\n");
         printk("GDT-ISA: Illegal protocol version\n");
         iounmap(ha->brd);
         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;
     ha->brd_phys = bios_adr >> 4;
 
 
     /* special request to controller BIOS */
     /* 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;
     retries = INIT_RETRIES;
     gdth_delay(20);
     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) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error\n");
             printk("GDT-ISA: Initialization error\n");
             iounmap(ha->brd);
             iounmap(ha->brd);
@@ -1152,14 +902,15 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
         }
         }
         gdth_delay(1);
         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;
     ha->dma64_support = 0;
     return 1;
     return 1;
 }
 }
+#endif /* CONFIG_ISA */
 
 
-
+#ifdef CONFIG_PCI
 static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 {
 {
     register gdt6_dpram_str __iomem *dp6_ptr;
     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 */
         /* check and reset interface area */
         dp6_ptr = ha->brd;
         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", 
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
                    pcistr->dpmem);
                    pcistr->dpmem);
             found = FALSE;
             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");
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                     return 0;
                 }
                 }
-                if (gdth_readw(ha->brd) != 0xffff) {
+                if (readw(ha->brd) != 0xffff) {
                     TRACE2(("init_pci_old() address 0x%x busy\n", i));
                     TRACE2(("init_pci_old() address 0x%x busy\n", i));
                     continue;
                     continue;
                 }
                 }
@@ -1215,8 +966,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     return 0;
                     return 0;
                 }
                 }
                 dp6_ptr = ha->brd;
                 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);
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
                     found = TRUE;
                     found = TRUE;
                     break;
                     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));
         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");
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
             iounmap(ha->brd);
             return 0;
             return 0;
         }
         }
         
         
         /* disable board interrupts, deinit services */
         /* 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;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
                 iounmap(ha->brd);
@@ -1254,9 +1005,9 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             }
             gdth_delay(1);
             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) {
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
             printk("GDT-PCI: Illegal protocol version\n");
             iounmap(ha->brd);
             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);
         ha->ic_all_size = sizeof(dp6_ptr->u);
         
         
         /* special command to controller BIOS */
         /* 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;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
                 printk("GDT-PCI: Initialization error\n");
                 iounmap(ha->brd);
                 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_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;
         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 */
         /* check and reset interface area */
         dp6c_ptr = ha->brd;
         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", 
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
                    pcistr->dpmem);
                    pcistr->dpmem);
             found = FALSE;
             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");
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                     return 0;
                 }
                 }
-                if (gdth_readw(ha->brd) != 0xffff) {
+                if (readw(ha->brd) != 0xffff) {
                     TRACE2(("init_pci_plx() address 0x%x busy\n", i));
                     TRACE2(("init_pci_plx() address 0x%x busy\n", i));
                     continue;
                     continue;
                 }
                 }
@@ -1325,8 +1076,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     return 0;
                     return 0;
                 }
                 }
                 dp6c_ptr = ha->brd;
                 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);
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
                     found = TRUE;
                     found = TRUE;
                     break;
                     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));
         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");
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
             iounmap(ha->brd);
             return 0;
             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(0x00,PTR2USHORT(&ha->plx->control1));
         outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
         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));
         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
 
 
         retries = INIT_RETRIES;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
                 iounmap(ha->brd);
@@ -1367,8 +1118,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             }
             gdth_delay(1);
             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) {
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
             printk("GDT-PCI: Illegal protocol version\n");
             iounmap(ha->brd);
             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);
         ha->ic_all_size = sizeof(dp6c_ptr->u);
 
 
         /* special command to controller BIOS */
         /* 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));
         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
 
 
         retries = INIT_RETRIES;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
                 printk("GDT-PCI: Initialization error\n");
                 iounmap(ha->brd);
                 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_delay(1);
         }
         }
-        gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
+        writeb(0, &dp6c_ptr->u.ic.S_Status);
 
 
         ha->dma64_support = 0;
         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.
         /* Ensure that it is safe to access the non HW portions of DPMEM.
          * Aditional check needed for Xscale based RAID controllers */
          * 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);
             gdth_delay(1);
         
         
         /* check and reset interface area */
         /* 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", 
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
                    pcistr->dpmem);
                    pcistr->dpmem);
             found = FALSE;
             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");
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                     return 0;
                 }
                 }
-                if (gdth_readw(ha->brd) != 0xffff) {
+                if (readw(ha->brd) != 0xffff) {
                     TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
                     TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
                     continue;
                     continue;
                 }
                 }
@@ -1454,8 +1205,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     return 0;
                     return 0;
                 }
                 }
                 dp6m_ptr = ha->brd;
                 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);
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
                     found = TRUE;
                     found = TRUE;
                     break;
                     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));
         memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u));
         
         
         /* disable board interrupts, deinit services */
         /* 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);
                     &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;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
                 iounmap(ha->brd);
@@ -1489,8 +1240,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             }
             gdth_delay(1);
             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) {
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
             printk("GDT-PCI: Illegal protocol version\n");
             iounmap(ha->brd);
             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);
         ha->ic_all_size = sizeof(dp6m_ptr->u);
         
         
         /* special command to controller BIOS */
         /* 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;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
                 printk("GDT-PCI: Initialization error\n");
                 iounmap(ha->brd);
                 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_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 */
         /* 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;
         retries = INIT_RETRIES;
         gdth_delay(20);
         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) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                 iounmap(ha->brd);
                 iounmap(ha->brd);
@@ -1532,8 +1283,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
             }
             }
             gdth_delay(1);
             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 */
         if (prot_ver < 0x2b)      /* FW < x.43: no 64-bit DMA support */
             ha->dma64_support = 0;
             ha->dma64_support = 0;
         else 
         else 
@@ -1542,20 +1293,18 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 
 
     return 1;
     return 1;
 }
 }
-
+#endif /* CONFIG_PCI */
 
 
 /* controller protocol functions */
 /* 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;
     ulong flags;
     gdt2_dpram_str __iomem *dp2_ptr;
     gdt2_dpram_str __iomem *dp2_ptr;
     gdt6_dpram_str __iomem *dp6_ptr;
     gdt6_dpram_str __iomem *dp6_ptr;
     gdt6m_dpram_str __iomem *dp6m_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);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     if (ha->type == GDT_EISA) {
     if (ha->type == GDT_EISA) {
@@ -1564,93 +1313,80 @@ static void __init gdth_enable_int(int hanum)
         outb(0x01, ha->bmic + EINTENABREG);
         outb(0x01, ha->bmic + EINTENABREG);
     } else if (ha->type == GDT_ISA) {
     } else if (ha->type == GDT_ISA) {
         dp2_ptr = ha->brd;
         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) {
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = ha->brd;
         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) {
     } else if (ha->type == GDT_PCINEW) {
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
         outb(0x03, PTR2USHORT(&ha->plx->control1));
         outb(0x03, PTR2USHORT(&ha->plx->control1));
     } else if (ha->type == GDT_PCIMPR) {
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = ha->brd;
         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);
                     &dp6m_ptr->i960r.edoor_en_reg);
     }
     }
     spin_unlock_irqrestore(&ha->smp_lock, flags);
     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 */
         if (ha->irq != (unchar)irq)             /* check IRQ */
-            continue;
+            return false;
         if (ha->type == GDT_EISA)
         if (ha->type == GDT_EISA)
-            *pIStatus = inb((ushort)ha->bmic + EDOORREG);
+            IStatus = inb((ushort)ha->bmic + EDOORREG);
         else if (ha->type == GDT_ISA)
         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)
         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) 
         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)
         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;
     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)
     if (ha->type == GDT_EISA)
         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
     else if (ha->type == GDT_ISA)
     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)
     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) 
     else if (ha->type == GDT_PCINEW) 
         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
     else if (ha->type == GDT_PCIMPR)
     else if (ha->type == GDT_PCIMPR)
         gdtsema0 = 
         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);
     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;
     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) {
     for (i=0; i<GDTH_MAXCMDS; ++i) {
         if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
         if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
             ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
             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) {
     if (ha->type == GDT_EISA) {
         outb(1, ha->bmic + SEMA0REG);
         outb(1, ha->bmic + SEMA0REG);
     } else if (ha->type == GDT_ISA) {
     } 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) {
     } 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) { 
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
     } else if (ha->type == GDT_PCIMPR) {
     } 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 gdth_cmd_str *cmd_ptr;
     register gdt6m_dpram_str __iomem *dp6m_ptr;
     register gdt6m_dpram_str __iomem *dp6m_ptr;
     register gdt6c_dpram_str __iomem *dp6c_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;
     gdt2_dpram_str __iomem *dp2_ptr;
     ushort cp_count,dp_offset,cmd_no;
     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;
     cp_count = ha->cmd_len;
     dp_offset= ha->cmd_offs_dpmem;
     dp_offset= ha->cmd_offs_dpmem;
     cmd_no   = ha->cmd_cnt;
     cmd_no   = ha->cmd_cnt;
@@ -1715,42 +1446,39 @@ static void gdth_copy_command(int hanum)
     /* set offset and service, copy command to DPMEM */
     /* set offset and service, copy command to DPMEM */
     if (ha->type == GDT_ISA) {
     if (ha->type == GDT_ISA) {
         dp2_ptr = ha->brd;
         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);
                     &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);
                     &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);
         memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCI) {
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = ha->brd;
         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);
                     &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);
                     &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);
         memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCINEW) {
     } else if (ha->type == GDT_PCINEW) {
         dp6c_ptr = ha->brd;
         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);
                     &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);
                     &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);
         memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCIMPR) {
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = ha->brd;
         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);
                     &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);
                     &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);
         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
 #ifdef GDTH_STATISTICS
     {
     {
@@ -1774,56 +1502,50 @@ static void gdth_release_event(int hanum)
             outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
             outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
     } else if (ha->type == GDT_ISA) {
     } 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) {
     } 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) { 
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
     } else if (ha->type == GDT_PCIMPR) {
     } 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 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)
     if (index == 0)
         return 1;                               /* no wait required */
         return 1;                               /* no wait required */
 
 
-    gdth_from_wait = TRUE;
     do {
     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;
             answer_found = TRUE;
             break;
             break;
         }
         }
         gdth_delay(1);
         gdth_delay(1);
     } while (--time);
     } while (--time);
-    gdth_from_wait = FALSE;
-    
-    while (gdth_test_busy(hanum))
+
+    while (gdth_test_busy(ha))
         gdth_delay(0);
         gdth_delay(0);
 
 
     return (answer_found);
     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;
     register gdth_cmd_str *cmd_ptr;
     int retries,index;
     int retries,index;
 
 
     TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
     TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     cmd_ptr = ha->pccb;
     cmd_ptr = ha->pccb;
     memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
     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;;) {
     for (retries = INIT_RETRIES;;) {
         cmd_ptr->Service          = service;
         cmd_ptr->Service          = service;
         cmd_ptr->RequestBuffer    = INTERNAL_CMND;
         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"));
             TRACE(("GDT: No free command index found\n"));
             return 0;
             return 0;
         }
         }
-        gdth_set_sema0(hanum);
+        gdth_set_sema0(ha);
         cmd_ptr->OpCode           = opcode;
         cmd_ptr->OpCode           = opcode;
         cmd_ptr->BoardNode        = LOCALBOARD;
         cmd_ptr->BoardNode        = LOCALBOARD;
         if (service == CACHESERVICE) {
         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_len          = sizeof(gdth_cmd_str);
         ha->cmd_offs_dpmem   = 0;
         ha->cmd_offs_dpmem   = 0;
         ha->cmd_cnt          = 0;
         ha->cmd_cnt          = 0;
-        gdth_copy_command(hanum);
-        gdth_release_event(hanum);
+        gdth_copy_command(ha);
+        gdth_release_event(ha);
         gdth_delay(20);
         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);
             printk("GDT: Initialization error (timeout service %d)\n",service);
             return 0;
             return 0;
         }
         }
@@ -1893,9 +1615,8 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
 
 
 /* search for devices */
 /* 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;
     ushort cdev_cnt, i;
     int ok;
     int ok;
     ulong32 bus_no, drv_cnt, drv_no, j;
     ulong32 bus_no, drv_cnt, drv_no, j;
@@ -1915,22 +1636,21 @@ static int __init gdth_search_drives(int hanum)
     ulong flags;
     ulong flags;
 #endif     
 #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;
     ok = 0;
 
 
     /* initialize controller services, at first: screen service */
     /* initialize controller services, at first: screen service */
     ha->screen_feat = 0;
     ha->screen_feat = 0;
     if (!force_dma32) {
     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)
         if (ok)
             ha->screen_feat = GDT_64BIT;
             ha->screen_feat = GDT_64BIT;
     }
     }
     if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
     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) {
     if (!ok) {
         printk("GDT-HA %d: Initialization error screen service (code %d)\n",
         printk("GDT-HA %d: Initialization error screen service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
         return 0;
     }
     }
     TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
     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],
     TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
     /* 3. send to controller firmware */
     /* 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]);
                       *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]);
 #endif  
 #endif  
  
  
     /* unfreeze all IOs */
     /* 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 */
     /* initialize cache service */
     ha->cache_feat = 0;
     ha->cache_feat = 0;
     if (!force_dma32) {
     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)
         if (ok)
             ha->cache_feat = GDT_64BIT;
             ha->cache_feat = GDT_64BIT;
     }
     }
     if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
     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) {
     if (!ok) {
         printk("GDT-HA %d: Initialization error cache service (code %d)\n",
         printk("GDT-HA %d: Initialization error cache service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
         return 0;
     }
     }
     TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
     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->cmd_buff_size    = 0;
         pmod->reserved1        = 0;            
         pmod->reserved1        = 0;            
         pmod->reserved2        = 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))) {
                               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
 #endif
@@ -2015,7 +1736,7 @@ static int __init gdth_search_drives(int hanum)
     iocr->hdr.first_chan     = 0;
     iocr->hdr.first_chan     = 0;
     iocr->hdr.last_chan      = MAXBUS-1;
     iocr->hdr.last_chan      = MAXBUS-1;
     iocr->hdr.list_offset    = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
     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))) {
                           INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
         TRACE2(("IOCHAN_RAW_DESC supported!\n"));
         TRACE2(("IOCHAN_RAW_DESC supported!\n"));
         ha->bus_cnt = iocr->hdr.chan_count;
         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;
         chn = (gdth_getch_str *)ha->pscratch;
         for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
         for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
             chn->channel_no = 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,
                                    SCSI_CHAN_CNT | L_CTRL_PATTERN,
                                    IO_CHANNEL | INVALID_CHANNEL,
                                    IO_CHANNEL | INVALID_CHANNEL,
                                    sizeof(gdth_getch_str))) {
                                    sizeof(gdth_getch_str))) {
                 if (bus_no == 0) {
                 if (bus_no == 0) {
                     printk("GDT-HA %d: Error detecting channel count (0x%x)\n",
                     printk("GDT-HA %d: Error detecting channel count (0x%x)\n",
-                           hanum, ha->status);
+                           ha->hanum, ha->status);
                     return 0;
                     return 0;
                 }
                 }
                 break;
                 break;
@@ -2051,10 +1772,10 @@ static int __init gdth_search_drives(int hanum)
     TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
     TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
 
 
     /* read cache configuration */
     /* 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))) {
                            INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
         printk("GDT-HA %d: Initialization error cache service (code %d)\n",
         printk("GDT-HA %d: Initialization error cache service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
         return 0;
     }
     }
     ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
     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 */
     /* read board info and features */
     ha->more_proc = FALSE;
     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))) {
                           INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
         memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
         memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
                sizeof(gdth_binfo_str));
                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))) {
                               INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
             TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
             TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
             ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
             ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
@@ -2076,7 +1797,7 @@ static int __init gdth_search_drives(int hanum)
         }
         }
     } else {
     } else {
         TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
         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));
     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.first_chan     = 0;
         ioc->hdr.last_chan      = MAXBUS-1;
         ioc->hdr.last_chan      = MAXBUS-1;
         ioc->hdr.list_offset    = GDTOFFSOF(gdth_iochan_str, list[0]);
         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))) {
                               INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
             for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
             for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
                 ha->raw[bus_no].address = ioc->list[bus_no].address;
                 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) {
         for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
             chn = (gdth_getch_str *)ha->pscratch;
             chn = (gdth_getch_str *)ha->pscratch;
             chn->channel_no = ha->raw[bus_no].local_no;
             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,
                                   SCSI_CHAN_CNT | L_CTRL_PATTERN,
                                   ha->raw[bus_no].address | INVALID_CHANNEL,
                                   ha->raw[bus_no].address | INVALID_CHANNEL,
                                   sizeof(gdth_getch_str))) {
                                   sizeof(gdth_getch_str))) {
@@ -2116,7 +1837,7 @@ static int __init gdth_search_drives(int hanum)
                 drl = (gdth_drlist_str *)ha->pscratch;
                 drl = (gdth_drlist_str *)ha->pscratch;
                 drl->sc_no = ha->raw[bus_no].local_no;
                 drl->sc_no = ha->raw[bus_no].local_no;
                 drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
                 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,
                                       SCSI_DR_LIST | L_CTRL_PATTERN,
                                       ha->raw[bus_no].address | INVALID_CHANNEL,
                                       ha->raw[bus_no].address | INVALID_CHANNEL,
                                       sizeof(gdth_drlist_str))) {
                                       sizeof(gdth_drlist_str))) {
@@ -2129,10 +1850,10 @@ static int __init gdth_search_drives(int hanum)
         }
         }
 
 
         /* logical drives */
         /* 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))) {
                               INVALID_CHANNEL,sizeof(ulong32))) {
             drv_cnt = *(ulong32 *)ha->pscratch;
             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))) {
                                   INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
                 for (j = 0; j < drv_cnt; ++j) {
                 for (j = 0; j < drv_cnt; ++j) {
                     drv_no = ((ulong32 *)ha->pscratch)[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->entries_avail = MAX_LDRIVES;
             alst->first_entry = 0;
             alst->first_entry = 0;
             alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[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, 
                                   ARRAY_DRV_LIST2 | LA_CTRL_PATTERN, 
                                   INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
                                   INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
                                   (alst->entries_avail-1) * sizeof(gdth_alist_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].is_hotfix = alst->list[j].is_hotfix;
                     ha->hdr[j].master_no = alst->list[j].cd_handle;
                     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,
                                          ARRAY_DRV_LIST | LA_CTRL_PATTERN,
                                          0, 35 * sizeof(gdth_alist_str))) {
                                          0, 35 * sizeof(gdth_alist_str))) {
                 for (j = 0; j < 35; ++j) {
                 for (j = 0; j < 35; ++j) {
@@ -2175,24 +1896,24 @@ static int __init gdth_search_drives(int hanum)
     /* initialize raw service */
     /* initialize raw service */
     ha->raw_feat = 0;
     ha->raw_feat = 0;
     if (!force_dma32) {
     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)
         if (ok)
             ha->raw_feat = GDT_64BIT;
             ha->raw_feat = GDT_64BIT;
     }
     }
     if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
     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) {
     if (!ok) {
         printk("GDT-HA %d: Initialization error raw service (code %d)\n",
         printk("GDT-HA %d: Initialization error raw service (code %d)\n",
-               hanum, ha->status);
+               ha->hanum, ha->status);
         return 0;
         return 0;
     }
     }
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
 
 
     /* set/get features raw service (scatter/gather) */
     /* 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"));
         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",
             TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
                     ha->info));
                     ha->info));
             ha->raw_feat |= (ushort)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) */
     /* 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)) {
                           SCATTER_GATHER,0)) {
         TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
         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",
             TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
                     ha->info));
                     ha->info));
             ha->cache_feat |= (ushort)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 */
     /* reserve drives for raw service */
     if (reserve_mode != 0) {
     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);
                           reserve_mode == 1 ? 1 : 3, 0, 0);
         TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", 
         TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", 
                 ha->status));
                 ha->status));
     }
     }
     for (i = 0; i < MAX_RES_ARGS; i += 4) {
     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) {
             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",
             TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
                     reserve_list[i], reserve_list[i+1],
                     reserve_list[i], reserve_list[i+1],
                     reserve_list[i+2], reserve_list[i+3]));
                     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+1], reserve_list[i+2] | 
                                    (reserve_list[i+3] << 8))) {
                                    (reserve_list[i+3] << 8))) {
                 printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n",
                 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 = (gdth_oem_str_ioctl *)ha->pscratch;
     oemstr->params.ctl_version = 0x01;
     oemstr->params.ctl_version = 0x01;
     oemstr->params.buffer_size = sizeof(oemstr->text);
     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,
                           CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
                           sizeof(gdth_oem_str_ioctl))) {
                           sizeof(gdth_oem_str_ioctl))) {
         TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
         TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
         printk("GDT-HA %d: Vendor: %s Name: %s\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 */
         /* 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,
         strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,
                 sizeof(ha->oem_name));
                 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 {
     } else {
         /* Old method, based on PCI ID */
         /* Old method, based on PCI ID */
         TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
         TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
         printk("GDT-HA %d: Name: %s\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)
         if (ha->oem_id == OEM_ID_INTEL)
             strlcpy(ha->oem_name,"Intel  ", sizeof(ha->oem_name));
             strlcpy(ha->oem_name,"Intel  ", sizeof(ha->oem_name));
         else
         else
             strlcpy(ha->oem_name,"ICP    ", sizeof(ha->oem_name));
             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 */
     /* scanning for host drives */
     for (i = 0; i < cdev_cnt; ++i) 
     for (i = 0; i < cdev_cnt; ++i) 
-        gdth_analyse_hdrive(hanum,i);
+        gdth_analyse_hdrive(ha, i);
     
     
     TRACE(("gdth_search_drives() OK\n"));
     TRACE(("gdth_search_drives() OK\n"));
     return 1;
     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;
     ulong32 drv_cyls;
     int drv_hds, drv_secs;
     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)
     if (hdrive >= MAX_HDRIVES)
         return 0;
         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;
         return 0;
     ha->hdr[hdrive].present = TRUE;
     ha->hdr[hdrive].present = TRUE;
     ha->hdr[hdrive].size = ha->info;
     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;
     ha->hdr[hdrive].size  = drv_cyls * drv_hds * drv_secs;
     
     
     if (ha->cache_feat & GDT_64BIT) {
     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->info2 != 0) {
             ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info;
             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));
             hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
 
 
     /* get informations about device */
     /* 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",
         TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
                 hdrive,ha->info));
                 hdrive,ha->info));
         ha->hdr[hdrive].devtype = (ushort)ha->info;
         ha->hdr[hdrive].devtype = (ushort)ha->info;
     }
     }
 
 
     /* cluster 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",
         TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
                 hdrive,ha->info));
                 hdrive,ha->info));
         if (!shared_access)
         if (!shared_access)
@@ -2331,7 +2038,7 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive)
     }
     }
 
 
     /* R/W attributes */
     /* 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",
         TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
                 hdrive,ha->info));
                 hdrive,ha->info));
         ha->hdr[hdrive].rw_attribs = (unchar)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 */
 /* 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 *pscp;
     register Scsi_Cmnd *nscp;
     register Scsi_Cmnd *nscp;
     ulong flags;
     ulong flags;
     unchar b, t;
     unchar b, t;
 
 
     TRACE(("gdth_putq() priority %d\n",priority));
     TRACE(("gdth_putq() priority %d\n",priority));
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     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;
         t = scp->device->id;
         if (priority >= DEFAULT_PRI) {
         if (priority >= DEFAULT_PRI) {
             if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
             if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
                 (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
                 (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
                 TRACE2(("gdth_putq(): locked IO ->update_timeout()\n"));
                 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;
         pscp = ha->req_first;
         nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
         nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
         /* priority: 0-highest,..,0xff-lowest */
         /* priority: 0-highest,..,0xff-lowest */
-        while (nscp && (unchar)nscp->SCp.this_residual <= priority) {
+        while (nscp && gdth_cmnd_priv(nscp)->priority <= priority) {
             pscp = nscp;
             pscp = nscp;
             nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
             nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
         }
         }
@@ -2395,9 +2101,8 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
 #endif
 #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 *pscp;
     register Scsi_Cmnd *nscp;
     register Scsi_Cmnd *nscp;
     unchar b, t, l, firsttime;
     unchar b, t, l, firsttime;
@@ -2405,8 +2110,7 @@ static void gdth_next(int hanum)
     ulong flags = 0;
     ulong flags = 0;
     int cmd_index;
     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) 
     if (!gdth_polling) 
         spin_lock_irqsave(&ha->smp_lock, flags);
         spin_lock_irqsave(&ha->smp_lock, flags);
 
 
@@ -2416,14 +2120,14 @@ static void gdth_next(int hanum)
     cmd_index = 0;
     cmd_index = 0;
 
 
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
     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)
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (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;
             t = nscp->device->id;
             l = nscp->device->lun;
             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) ||
                 if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
                     (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
                     (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
                     continue;
                     continue;
@@ -2432,21 +2136,21 @@ static void gdth_next(int hanum)
             b = t = l = 0;
             b = t = l = 0;
 
 
         if (firsttime) {
         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) {
                 if (!gdth_polling) {
                     spin_unlock_irqrestore(&ha->smp_lock, flags);
                     spin_unlock_irqrestore(&ha->smp_lock, flags);
                     return;
                     return;
                 }
                 }
-                while (gdth_test_busy(hanum))
+                while (gdth_test_busy(ha))
                     gdth_delay(1);
                     gdth_delay(1);
             }   
             }   
             firsttime = FALSE;
             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) {
             if (nscp->cmnd[0] == TEST_UNIT_READY) {
                 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", 
                 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", 
                         b, t, l));
                         b, t, l));
@@ -2459,8 +2163,8 @@ static void gdth_next(int hanum)
                 } else if ((ha->scan_mode & 0x0f) == 1) {
                 } else if ((ha->scan_mode & 0x0f) == 1) {
                     if (b == 0 && ((t == 0 && l == 1) ||
                     if (b == 0 && ((t == 0 && l == 1) ||
                          (t == 1 && l == 0))) {
                          (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;
                             | SCSIRAWSERVICE;
                         ha->scan_mode = 0x12;
                         ha->scan_mode = 0x12;
                         TRACE2(("Scan mode: 0x%x (SCAN_START)\n", 
                         TRACE2(("Scan mode: 0x%x (SCAN_START)\n", 
@@ -2471,8 +2175,8 @@ static void gdth_next(int hanum)
                     }                   
                     }                   
                 } else if (ha->scan_mode == 0x12) {
                 } else if (ha->scan_mode == 0x12) {
                     if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
                     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;
                         ha->scan_mode &= 0x10;
                         TRACE2(("Scan mode: 0x%x (SCAN_END)\n", 
                         TRACE2(("Scan mode: 0x%x (SCAN_END)\n", 
                                 ha->scan_mode));
                                 ha->scan_mode));
@@ -2483,18 +2187,18 @@ static void gdth_next(int hanum)
                 nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
                 nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
                 (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
                 (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
                 /* always GDT_CLUST_INFO! */
                 /* 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;
                     this_cmd = FALSE;
                 next_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;
                     this_cmd = FALSE;
                 next_cmd = FALSE;
                 next_cmd = FALSE;
             } else {
             } else {
@@ -2502,18 +2206,18 @@ static void gdth_next(int hanum)
                 nscp->sense_buffer[0] = 0x70;
                 nscp->sense_buffer[0] = 0x70;
                 nscp->sense_buffer[2] = NOT_READY;
                 nscp->sense_buffer[2] = NOT_READY;
                 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                 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
                 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(ha, nscp)))
                 this_cmd = FALSE;
                 this_cmd = FALSE;
             next_cmd = FALSE;
             next_cmd = FALSE;
         } else if (b != ha->virt_bus) {
         } else if (b != ha->virt_bus) {
             if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
             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;
                 this_cmd = FALSE;
             else 
             else 
                 ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
                 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",
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
                     nscp->cmnd[0], b, t, l));
                     nscp->cmnd[0], b, t, l));
             nscp->result = DID_BAD_TARGET << 16;
             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
             else
-                nscp->scsi_done(nscp);
+                gdth_scsi_done(nscp);
         } else {
         } else {
             switch (nscp->cmnd[0]) {
             switch (nscp->cmnd[0]) {
               case TEST_UNIT_READY:
               case TEST_UNIT_READY:
@@ -2547,12 +2251,12 @@ static void gdth_next(int hanum)
                     nscp->sense_buffer[0] = 0x70;
                     nscp->sense_buffer[0] = 0x70;
                     nscp->sense_buffer[2] = UNIT_ATTENTION;
                     nscp->sense_buffer[2] = UNIT_ATTENTION;
                     nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                     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
                     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(ha, nscp))
+                    gdth_scsi_done(nscp);
                 break;
                 break;
 
 
               case ALLOW_MEDIUM_REMOVAL:
               case ALLOW_MEDIUM_REMOVAL:
@@ -2563,15 +2267,15 @@ static void gdth_next(int hanum)
                     TRACE(("Prevent r. nonremov. drive->do nothing\n"));
                     TRACE(("Prevent r. nonremov. drive->do nothing\n"));
                     nscp->result = DID_OK << 16;
                     nscp->result = DID_OK << 16;
                     nscp->sense_buffer[0] = 0;
                     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
                     else
-                        nscp->scsi_done(nscp);
+                        gdth_scsi_done(nscp);
                 } else {
                 } else {
                     nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
                     nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
                     TRACE(("Prevent/allow r. %d rem. drive %d\n",
                     TRACE(("Prevent/allow r. %d rem. drive %d\n",
                            nscp->cmnd[4],nscp->cmnd[3]));
                            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;
                         this_cmd = FALSE;
                 }
                 }
                 break;
                 break;
@@ -2580,7 +2284,7 @@ static void gdth_next(int hanum)
               case RELEASE:
               case RELEASE:
                 TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
                 TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
                         "RESERVE" : "RELEASE"));
                         "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;
                     this_cmd = FALSE;
                 break;
                 break;
                 
                 
@@ -2599,11 +2303,11 @@ static void gdth_next(int hanum)
                     nscp->sense_buffer[0] = 0x70;
                     nscp->sense_buffer[0] = 0x70;
                     nscp->sense_buffer[2] = UNIT_ATTENTION;
                     nscp->sense_buffer[2] = UNIT_ATTENTION;
                     nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                     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
                     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;
                     this_cmd = FALSE;
                 break;
                 break;
 
 
@@ -2612,12 +2316,12 @@ static void gdth_next(int hanum)
                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                         nscp->cmnd[4],nscp->cmnd[5]));
                         nscp->cmnd[4],nscp->cmnd[5]));
                 printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n",
                 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;
                 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
                 else
-                    nscp->scsi_done(nscp);
+                    gdth_scsi_done(nscp);
                 break;
                 break;
             }
             }
         }
         }
@@ -2633,79 +2337,77 @@ static void gdth_next(int hanum)
     }
     }
 
 
     if (ha->cmd_cnt > 0) {
     if (ha->cmd_cnt > 0) {
-        gdth_release_event(hanum);
+        gdth_release_event(ha);
     }
     }
 
 
     if (!gdth_polling) 
     if (!gdth_polling) 
         spin_unlock_irqrestore(&ha->smp_lock, flags);
         spin_unlock_irqrestore(&ha->smp_lock, flags);
 
 
     if (gdth_polling && ha->cmd_cnt > 0) {
     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",
             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;
     ushort cpsum,cpnow;
     struct scatterlist *sl;
     struct scatterlist *sl;
-    gdth_ha_str *ha;
     char *address;
     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;
             unsigned long flags;
             cpnow = (ushort)sl->length;
             cpnow = (ushort)sl->length;
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
             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) 
             if (cpsum+cpnow > cpcount) 
                 cpnow = cpcount - cpsum;
                 cpnow = cpcount - cpsum;
             cpsum += cpnow;
             cpsum += cpnow;
             if (!sl->page) {
             if (!sl->page) {
                 printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
                 printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
-                       hanum);
+                       ha->hanum);
                 return;
                 return;
             }
             }
             local_irq_save(flags);
             local_irq_save(flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
             address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
             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);
             flush_dcache_page(sl->page);
             kunmap_atomic(address, KM_BIO_SRC_IRQ);
             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);
             local_irq_restore(flags);
             if (cpsum == cpcount)
             if (cpsum == cpcount)
                 break;
                 break;
             buffer += cpnow;
             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;
     unchar t;
     gdth_inq_data inq;
     gdth_inq_data inq;
     gdth_rdcap_data rdc;
     gdth_rdcap_data rdc;
     gdth_sense_data sd;
     gdth_sense_data sd;
     gdth_modep_data mpd;
     gdth_modep_data mpd;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     t  = scp->device->id;
     t  = scp->device->id;
     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
            scp->cmnd[0],t));
            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);
         strcpy(inq.vendor,ha->oem_name);
         sprintf(inq.product,"Host Drive  #%02d",t);
         sprintf(inq.product,"Host Drive  #%02d",t);
         strcpy(inq.revision,"   ");
         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;
         break;
 
 
       case REQUEST_SENSE:
       case REQUEST_SENSE:
@@ -2746,7 +2448,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         sd.key       = NO_SENSE;
         sd.key       = NO_SENSE;
         sd.info      = 0;
         sd.info      = 0;
         sd.add_length= 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;
         break;
 
 
       case MODE_SENSE:
       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[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
         mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
         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;
         break;
 
 
       case READ_CAPACITY:
       case READ_CAPACITY:
@@ -2768,7 +2470,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         else
         else
             rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
             rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
         rdc.block_length  = cpu_to_be32(SECTOR_SIZE);
         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;
         break;
 
 
       case SERVICE_ACTION_IN:
       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));
             TRACE2(("Read capacity (16) hdrive %d\n",t));
             rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
             rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
             rdc16.block_length  = cpu_to_be32(SECTOR_SIZE);
             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 { 
         } else { 
             scp->result = DID_ABORT << 16;
             scp->result = DID_ABORT << 16;
         }
         }
@@ -2790,27 +2493,22 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         break;
         break;
     }
     }
 
 
-    if (!scp->SCp.have_data_in)
-        scp->SCp.have_data_in++;
+    if (!cmndinfo->wait_for_completion)
+        cmndinfo->wait_for_completion++;
     else 
     else 
         return 1;
         return 1;
 
 
     return 0;
     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;
     register gdth_cmd_str *cmdp;
-    struct scatterlist *sl;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
     ulong32 cnt, blockcnt;
     ulong32 cnt, blockcnt;
     ulong64 no, blockno;
     ulong64 no, blockno;
-    dma_addr_t phys_addr;
     int i, cmd_index, read_write, sgcnt, mode64;
     int i, cmd_index, read_write, sgcnt, mode64;
-    struct page *page;
-    ulong offset;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
     cmdp = ha->pccb;
     TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
     TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
                  scp->cmnd[0],scp->cmd_len,hdrive));
                  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->Service = CACHESERVICE;
     cmdp->RequestBuffer = scp;
     cmdp->RequestBuffer = scp;
     /* search free command index */
     /* 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"));
         TRACE(("GDT: No free command index found\n"));
         return 0;
         return 0;
     }
     }
     /* if it's the first command, set command semaphore */
     /* if it's the first command, set command semaphore */
     if (ha->cmd_cnt == 0)
     if (ha->cmd_cnt == 0)
-        gdth_set_sema0(hanum);
+        gdth_set_sema0(ha);
 
 
     /* fill command */
     /* fill command */
     read_write = 0;
     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) 
     else if (scp->cmnd[0] == RESERVE) 
         cmdp->OpCode = GDT_RESERVE_DRV;
         cmdp->OpCode = GDT_RESERVE_DRV;
     else if (scp->cmnd[0] == RELEASE)
     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;
             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);   
                 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) {
             if (mode64) {
+                struct scatterlist *sl;
+
                 cmdp->u.cache64.DestAddr= (ulong64)-1;
                 cmdp->u.cache64.DestAddr= (ulong64)-1;
                 cmdp->u.cache64.sg_canz = sgcnt;
                 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);
                     cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
 #ifdef GDTH_DMA_STATISTICS
                     if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
                     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);
                     cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl);
                 }
                 }
             } else {
             } else {
+                struct scatterlist *sl;
+
                 cmdp->u.cache.DestAddr= 0xffffffff;
                 cmdp->u.cache.DestAddr= 0xffffffff;
                 cmdp->u.cache.sg_canz = sgcnt;
                 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);
                     cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
 #ifdef GDTH_DMA_STATISTICS
                     ha->dma32_cnt++;
                     ha->dma32_cnt++;
@@ -2937,38 +2637,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
             }
             }
 #endif
 #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 */
     /* evaluate command size, check space */
@@ -3004,23 +2672,21 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
     }
     }
 
 
     /* copy command */
     /* copy command */
-    gdth_copy_command(hanum);
+    gdth_copy_command(ha);
     return cmd_index;
     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;
     register gdth_cmd_str *cmdp;
-    struct scatterlist *sl;
     ushort i;
     ushort i;
-    dma_addr_t phys_addr, sense_paddr;
+    dma_addr_t sense_paddr;
     int cmd_index, sgcnt, mode64;
     int cmd_index, sgcnt, mode64;
     unchar t,l;
     unchar t,l;
     struct page *page;
     struct page *page;
     ulong offset;
     ulong offset;
+    struct gdth_cmndinfo *cmndinfo;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     t = scp->device->id;
     t = scp->device->id;
     l = scp->device->lun;
     l = scp->device->lun;
     cmdp = ha->pccb;
     cmdp = ha->pccb;
@@ -3035,26 +2701,27 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
     cmdp->Service = SCSIRAWSERVICE;
     cmdp->Service = SCSIRAWSERVICE;
     cmdp->RequestBuffer = scp;
     cmdp->RequestBuffer = scp;
     /* search free command index */
     /* 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"));
         TRACE(("GDT: No free command index found\n"));
         return 0;
         return 0;
     }
     }
     /* if it's the first command, set command semaphore */
     /* if it's the first command, set command semaphore */
     if (ha->cmd_cnt == 0)
     if (ha->cmd_cnt == 0)
-        gdth_set_sema0(hanum);
+        gdth_set_sema0(ha);
 
 
+    cmndinfo = gdth_cmnd_priv(scp);
     /* fill command */  
     /* 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;
         cmdp->BoardNode        = LOCALBOARD;
         if (mode64) {
         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", 
             TRACE2(("special raw cmd 0x%x param 0x%x\n", 
                     cmdp->OpCode, cmdp->u.raw64.direction));
                     cmdp->OpCode, cmdp->u.raw64.direction));
             /* evaluate command size */
             /* evaluate command size */
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst);
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst);
         } else {
         } 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", 
             TRACE2(("special raw cmd 0x%x param 0x%x\n", 
                     cmdp->OpCode, cmdp->u.raw.direction));
                     cmdp->OpCode, cmdp->u.raw.direction));
             /* evaluate command size */
             /* 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;
         offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
         sense_paddr = pci_map_page(ha->pdev,page,offset,
         sense_paddr = pci_map_page(ha->pdev,page,offset,
                                    16,PCI_DMA_FROMDEVICE);
                                    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->OpCode           = GDT_WRITE;             /* always */
         cmdp->BoardNode        = LOCALBOARD;
         cmdp->BoardNode        = LOCALBOARD;
         if (mode64) { 
         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.lun        = l;
             cmdp->u.raw64.bus        = b;
             cmdp->u.raw64.bus        = b;
             cmdp->u.raw64.priority   = 0;
             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_len  = 16;
             cmdp->u.raw64.sense_data = sense_paddr;
             cmdp->u.raw64.sense_data = sense_paddr;
             cmdp->u.raw64.direction  = 
             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.bus        = b;
             cmdp->u.raw.priority   = 0;
             cmdp->u.raw.priority   = 0;
             cmdp->u.raw.link_p     = 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_len  = 16;
             cmdp->u.raw.sense_data = sense_paddr;
             cmdp->u.raw.sense_data = sense_paddr;
             cmdp->u.raw.direction  = 
             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;
             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) {
             if (mode64) {
+                struct scatterlist *sl;
+
                 cmdp->u.raw64.sdata = (ulong64)-1;
                 cmdp->u.raw64.sdata = (ulong64)-1;
                 cmdp->u.raw64.sg_ranz = sgcnt;
                 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);
                     cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
 #ifdef GDTH_DMA_STATISTICS
                     if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
                     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);
                     cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl);
                 }
                 }
             } else {
             } else {
+                struct scatterlist *sl;
+
                 cmdp->u.raw.sdata = 0xffffffff;
                 cmdp->u.raw.sdata = 0xffffffff;
                 cmdp->u.raw.sg_ranz = sgcnt;
                 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);
                     cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
 #ifdef GDTH_DMA_STATISTICS
 #ifdef GDTH_DMA_STATISTICS
                     ha->dma32_cnt++;
                     ha->dma32_cnt++;
@@ -3144,38 +2812,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
             }
             }
 #endif
 #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) {
         if (mode64) {
             TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
             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 */
     /* copy command */
-    gdth_copy_command(hanum);
+    gdth_copy_command(ha);
     return cmd_index;
     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;
     register gdth_cmd_str *cmdp;
     int cmd_index;
     int cmd_index;
 
 
-    ha  = HADATA(gdth_ctr_tab[hanum]);
     cmdp= ha->pccb;
     cmdp= ha->pccb;
     TRACE2(("gdth_special_cmd(): "));
     TRACE2(("gdth_special_cmd(): "));
 
 
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
         return 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;
     cmdp->RequestBuffer = scp;
 
 
     /* search free command index */
     /* 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"));
         TRACE(("GDT: No free command index found\n"));
         return 0;
         return 0;
     }
     }
 
 
     /* if it's the first command, set command semaphore */
     /* if it's the first command, set command semaphore */
     if (ha->cmd_cnt == 0)
     if (ha->cmd_cnt == 0)
-       gdth_set_sema0(hanum);
+       gdth_set_sema0(ha);
 
 
     /* evaluate command size, check space */
     /* evaluate command size, check space */
     if (cmdp->OpCode == GDT_IOCTL) {
     if (cmdp->OpCode == GDT_IOCTL) {
@@ -3275,7 +2909,7 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
     }
     }
 
 
     /* copy command */
     /* copy command */
-    gdth_copy_command(hanum);
+    gdth_copy_command(ha);
     return cmd_index;
     return cmd_index;
 }    
 }    
 
 
@@ -3402,15 +3036,14 @@ static void gdth_clear_events(void)
 
 
 /* SCSI interface functions */
 /* 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;
     gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
     gdt6_dpram_str __iomem *dp6_ptr;
     gdt6_dpram_str __iomem *dp6_ptr;
     gdt2_dpram_str __iomem *dp2_ptr;
     gdt2_dpram_str __iomem *dp2_ptr;
     Scsi_Cmnd *scp;
     Scsi_Cmnd *scp;
-    int hanum, rval, i;
+    int rval, i;
     unchar IStatus;
     unchar IStatus;
     ushort Service;
     ushort Service;
     ulong flags = 0;
     ulong flags = 0;
@@ -3431,17 +3064,15 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
     }
     }
 
 
     if (!gdth_polling)
     if (!gdth_polling)
-        spin_lock_irqsave(&ha2->smp_lock, flags);
-    wait_index = 0;
+        spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     /* search controller */
     /* search controller */
-    if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
+    if (0 == (IStatus = gdth_get_status(ha, irq))) {
         /* spurious interrupt */
         /* spurious interrupt */
         if (!gdth_polling)
         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
 #ifdef GDTH_STATISTICS
     ++act_ints;
     ++act_ints;
@@ -3482,32 +3113,32 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
             dp2_ptr = ha->brd;
             dp2_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 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));
                 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
             } else                                      /* no error */
             } else                                      /* no error */
                 ha->status = S_OK;
                 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) {
         } else if (ha->type == GDT_PCI) {
             dp6_ptr = ha->brd;
             dp6_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 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));
                 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
             } else                                      /* no error */
             } else                                      /* no error */
                 ha->status = S_OK;
                 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) {
         } else if (ha->type == GDT_PCINEW) {
             if (IStatus & 0x80) {                       /* error flag */
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 IStatus &= ~0x80;
@@ -3530,7 +3161,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
                     ha->status = pcs->ext_status & 0xffff;
                     ha->status = pcs->ext_status & 0xffff;
                 else 
                 else 
 #endif
 #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));
                 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
             } else                                      /* no error */
             } else                                      /* no error */
                 ha->status = S_OK;
                 ha->status = S_OK;
@@ -3543,18 +3174,18 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
             } else
             } else
 #endif
 #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 */
             /* event string */
             if (IStatus == ASYNCINDEX) {
             if (IStatus == ASYNCINDEX) {
                 if (ha->service != SCREENSERVICE &&
                 if (ha->service != SCREENSERVICE &&
                     (ha->fw_vers & 0xff) >= 0x1a) {
                     (ha->fw_vers & 0xff) >= 0x1a) {
-                    ha->dvr.severity = gdth_readb
+                    ha->dvr.severity = readb
                         (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity);
                         (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity);
                     for (i = 0; i < 256; ++i) {
                     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]);
                             (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]);
                         if (ha->dvr.event_string[i] == 0)
                         if (ha->dvr.event_string[i] == 0)
                             break;
                             break;
@@ -3567,13 +3198,13 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
             if (!coalesced)
             if (!coalesced)
 #endif                          
 #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 {
         } else {
             TRACE2(("gdth_interrupt() unknown controller type\n"));
             TRACE2(("gdth_interrupt() unknown controller type\n"));
             if (!gdth_polling)
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
             return IRQ_HANDLED;
         }
         }
 
 
@@ -3581,26 +3212,25 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
                IStatus,ha->status,ha->info));
                IStatus,ha->status,ha->info));
 
 
         if (gdth_from_wait) {
         if (gdth_from_wait) {
-            wait_hanum = hanum;
-            wait_index = (int)IStatus;
+            *pIndex = (int)IStatus;
         }
         }
 
 
         if (IStatus == ASYNCINDEX) {
         if (IStatus == ASYNCINDEX) {
             TRACE2(("gdth_interrupt() async. event\n"));
             TRACE2(("gdth_interrupt() async. event\n"));
-            gdth_async_event(hanum);
+            gdth_async_event(ha);
             if (!gdth_polling)
             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;
             return IRQ_HANDLED;
         } 
         } 
 
 
         if (IStatus == SPEZINDEX) {
         if (IStatus == SPEZINDEX) {
             TRACE2(("Service unknown or not initialized !\n"));
             TRACE2(("Service unknown or not initialized !\n"));
             ha->dvr.size = sizeof(ha->dvr.eu.driver);
             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);
             gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
             if (!gdth_polling)
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
             return IRQ_HANDLED;
         }
         }
         scp     = ha->cmd_tab[IStatus-2].cmnd;
         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) {
         if (scp == UNUSED_CMND) {
             TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
             TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
             ha->dvr.size = sizeof(ha->dvr.eu.driver);
             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;
             ha->dvr.eu.driver.index = IStatus;
             gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
             gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
             if (!gdth_polling)
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
             return IRQ_HANDLED;
         }
         }
         if (scp == INTERNAL_CMND) {
         if (scp == INTERNAL_CMND) {
             TRACE(("gdth_interrupt() answer to internal command\n"));
             TRACE(("gdth_interrupt() answer to internal command\n"));
             if (!gdth_polling)
             if (!gdth_polling)
-                spin_unlock_irqrestore(&ha2->smp_lock, flags);
+                spin_unlock_irqrestore(&ha->smp_lock, flags);
             return IRQ_HANDLED;
             return IRQ_HANDLED;
         }
         }
 
 
         TRACE(("gdth_interrupt() sync. status\n"));
         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)
         if (!gdth_polling)
-            spin_unlock_irqrestore(&ha2->smp_lock, flags);
+            spin_unlock_irqrestore(&ha->smp_lock, flags);
         if (rval == 2) {
         if (rval == 2) {
-            gdth_putq(hanum,scp,scp->SCp.this_residual);
+            gdth_putq(ha, scp, gdth_cmnd_priv(scp)->priority);
         } else if (rval == 1) {
         } else if (rval == 1) {
-            scp->scsi_done(scp);
+            gdth_scsi_done(scp);
         }
         }
 
 
 #ifdef INT_COAL
 #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 */      
     /* coalescing only for new GDT_PCIMPR controllers available */      
     if (ha->type == GDT_PCIMPR && coalesced) {
     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
 #endif
 
 
-    gdth_next(hanum);
+    gdth_next(ha);
     return IRQ_HANDLED;
     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_msg_str *msg;
     gdth_cmd_str *cmdp;
     gdth_cmd_str *cmdp;
     unchar b, t;
     unchar b, t;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
 
 
-    ha   = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
     cmdp = ha->pccb;
     TRACE(("gdth_sync_event() serv %d status %d\n",
     TRACE(("gdth_sync_event() serv %d status %d\n",
            service,ha->status));
            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) {
         if (msg->msg_ext && !msg->msg_answer) {
-            while (gdth_test_busy(hanum))
+            while (gdth_test_busy(ha))
                 gdth_delay(0);
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
             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->OpCode        = GDT_READ;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             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) 
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong64);
                 + sizeof(ulong64);
             ha->cmd_cnt = 0;
             ha->cmd_cnt = 0;
-            gdth_copy_command(hanum);
-            gdth_release_event(hanum);
+            gdth_copy_command(ha);
+            gdth_release_event(ha);
             return 0;
             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_ext    = 0;
             msg->msg_answer = 0;
             msg->msg_answer = 0;
-            while (gdth_test_busy(hanum))
+            while (gdth_test_busy(ha))
                 gdth_delay(0);
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
             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->OpCode        = GDT_WRITE;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             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) 
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong64);
                 + sizeof(ulong64);
             ha->cmd_cnt = 0;
             ha->cmd_cnt = 0;
-            gdth_copy_command(hanum);
-            gdth_release_event(hanum);
+            gdth_copy_command(ha);
+            gdth_release_event(ha);
             return 0;
             return 0;
         }
         }
         printk("\n");
         printk("\n");
 
 
     } else {
     } else {
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        b = scp->device->channel;
         t = scp->device->id;
         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]--;
             ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
         }
         }
         /* cache or raw service */
         /* cache or raw service */
         if (ha->status == S_BSY) {
         if (ha->status == S_BSY) {
             TRACE2(("Controller busy -> retry !\n"));
             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 */
             /* retry */
             return 2;
             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) {
         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",
                 TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
-                        scp->SCp.sent_command));
+                        cmndinfo->OpCode));
                 /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
                 /* 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;
                     ha->hdr[t].cluster_type = (unchar)ha->info;
                     if (!(ha->hdr[t].cluster_type & 
                     if (!(ha->hdr[t].cluster_type & 
                         CLUSTER_MOUNTED)) {
                         CLUSTER_MOUNTED)) {
                         /* NOT MOUNTED -> MOUNT */
                         /* NOT MOUNTED -> MOUNT */
-                        scp->SCp.sent_command = GDT_MOUNT;
+                        cmndinfo->OpCode = GDT_MOUNT;
                         if (ha->hdr[t].cluster_type & 
                         if (ha->hdr[t].cluster_type & 
                             CLUSTER_RESERVED) {
                             CLUSTER_RESERVED) {
                             /* cluster drive RESERVED (on the other node) */
                             /* cluster drive RESERVED (on the other node) */
-                            scp->SCp.phase = -2;      /* reservation conflict */
+                            cmndinfo->phase = -2;      /* reservation conflict */
                         }
                         }
                     } else {
                     } else {
-                        scp->SCp.sent_command = -1;
+                        cmndinfo->OpCode = -1;
                     }
                     }
                 } else {
                 } else {
-                    if (scp->SCp.sent_command == GDT_MOUNT) {
+                    if (cmndinfo->OpCode == GDT_MOUNT) {
                         ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
                         ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
                         ha->hdr[t].media_changed = TRUE;
                         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].cluster_type &= ~CLUSTER_MOUNTED;
                         ha->hdr[t].media_changed = TRUE;
                         ha->hdr[t].media_changed = TRUE;
                     } 
                     } 
-                    scp->SCp.sent_command = -1;
+                    cmndinfo->OpCode = -1;
                 }
                 }
                 /* retry */
                 /* retry */
-                scp->SCp.this_residual = HIGH_PRI;
+                cmndinfo->priority = HIGH_PRI;
                 return 2;
                 return 2;
             } else {
             } else {
                 /* RESERVE/RELEASE ? */
                 /* 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;
                 scp->sense_buffer[0] = 0;
             }
             }
         } else {
         } 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",
                 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 */
                     /* retry */
-                    scp->SCp.this_residual = HIGH_PRI;
+                    cmndinfo->priority = HIGH_PRI;
                     return 2;
                     return 2;
                 }
                 }
                 memset((char*)scp->sense_buffer,0,16);
                 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->sense_buffer[2] = NOT_READY;
                     scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                     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.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.service = service;
                     ha->dvr.eu.sync.status  = ha->status;
                     ha->dvr.eu.sync.status  = ha->status;
                     ha->dvr.eu.sync.info    = ha->info;
                     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 
         else 
             return 1;
             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;
     gdth_cmd_str *cmdp;
     int cmd_index;
     int cmd_index;
 
 
-    ha  = HADATA(gdth_ctr_tab[hanum]);
     cmdp= ha->pccb;
     cmdp= ha->pccb;
     TRACE2(("gdth_async_event() ha %d serv %d\n",
     TRACE2(("gdth_async_event() ha %d serv %d\n",
-            hanum,ha->service));
+            ha->hanum, ha->service));
 
 
     if (ha->service == SCREENSERVICE) {
     if (ha->service == SCREENSERVICE) {
         if (ha->status == MSG_REQUEST) {
         if (ha->status == MSG_REQUEST) {
-            while (gdth_test_busy(hanum))
+            while (gdth_test_busy(ha))
                 gdth_delay(0);
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
             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->OpCode        = GDT_READ;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             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) 
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong64);
                 + sizeof(ulong64);
             ha->cmd_cnt = 0;
             ha->cmd_cnt = 0;
-            gdth_copy_command(hanum);
+            gdth_copy_command(ha);
             if (ha->type == GDT_EISA)
             if (ha->type == GDT_EISA)
                 printk("[EISA slot %d] ",(ushort)ha->brd_phys);
                 printk("[EISA slot %d] ",(ushort)ha->brd_phys);
             else if (ha->type == GDT_ISA)
             else if (ha->type == GDT_ISA)
@@ -4070,19 +3698,19 @@ static int gdth_async_event(int hanum)
             else 
             else 
                 printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
                 printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
                        (ushort)((ha->brd_phys>>3)&0x1f));
                        (ushort)((ha->brd_phys>>3)&0x1f));
-            gdth_release_event(hanum);
+            gdth_release_event(ha);
         }
         }
 
 
     } else {
     } else {
         if (ha->type == GDT_PCIMPR && 
         if (ha->type == GDT_PCIMPR && 
             (ha->fw_vers & 0xff) >= 0x1a) {
             (ha->fw_vers & 0xff) >= 0x1a) {
             ha->dvr.size = 0;
             ha->dvr.size = 0;
-            ha->dvr.eu.async.ionode = hanum;
+            ha->dvr.eu.async.ionode = ha->hanum;
             ha->dvr.eu.async.status  = ha->status;
             ha->dvr.eu.async.status  = ha->status;
             /* severity and event_string already set! */
             /* severity and event_string already set! */
         } else {        
         } else {        
             ha->dvr.size = sizeof(ha->dvr.eu.async);
             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.service = ha->service;
             ha->dvr.eu.async.status  = ha->status;
             ha->dvr.eu.async.status  = ha->status;
             ha->dvr.eu.async.info    = ha->info;
             ha->dvr.eu.async.info    = ha->info;
@@ -4164,9 +3792,8 @@ static void gdth_timeout(ulong data)
     Scsi_Cmnd *nscp;
     Scsi_Cmnd *nscp;
     gdth_ha_str *ha;
     gdth_ha_str *ha;
     ulong flags;
     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);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i) 
     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;
             max_ids = val;
         else if (!strncmp(argv, "rescan:", 7))
         else if (!strncmp(argv, "rescan:", 7))
             rescan = val;
             rescan = val;
-        else if (!strncmp(argv, "virt_ctr:", 9))
-            virt_ctr = val;
         else if (!strncmp(argv, "shared_access:", 14))
         else if (!strncmp(argv, "shared_access:", 14))
             shared_access = val;
             shared_access = val;
         else if (!strncmp(argv, "probe_eisa_isa:", 15))
         else if (!strncmp(argv, "probe_eisa_isa:", 15))
@@ -4277,523 +3902,10 @@ int __init option_setup(char *str)
     return 1;
     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"));
     TRACE2(("gdth_ctr_name()\n"));
 
 
-    ha    = HADATA(gdth_ctr_tab[hanum]);
-
     if (ha->type == GDT_EISA) {
     if (ha->type == GDT_EISA) {
         switch (ha->stype) {
         switch (ha->stype) {
           case GDT3_ID:
           case GDT3_ID:
@@ -4820,29 +3932,23 @@ static const char *gdth_ctr_name(int hanum)
 
 
 static const char *gdth_info(struct Scsi_Host *shp)
 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"));
     TRACE2(("gdth_info()\n"));
-    hanum = NUMDATA(shp)->hanum;
-    ha    = HADATA(gdth_ctr_tab[hanum]);
-
     return ((const char *)ha->binfo.type_string);
     return ((const char *)ha->binfo.type_string);
 }
 }
 
 
 static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
 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;
     ulong flags;
     Scsi_Cmnd *cmnd;
     Scsi_Cmnd *cmnd;
     unchar b;
     unchar b;
 
 
     TRACE2(("gdth_eh_bus_reset()\n"));
     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 */
     /* clear command tab */
     spin_lock_irqsave(&ha->smp_lock, flags);
     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) {
             if (ha->hdr[i].present) {
                 spin_lock_irqsave(&ha->smp_lock, flags);
                 spin_lock_irqsave(&ha->smp_lock, flags);
                 gdth_polling = TRUE;
                 gdth_polling = TRUE;
-                while (gdth_test_busy(hanum))
+                while (gdth_test_busy(ha))
                     gdth_delay(0);
                     gdth_delay(0);
-                if (gdth_internal_cmd(hanum, CACHESERVICE, 
+                if (gdth_internal_cmd(ha, CACHESERVICE,
                                       GDT_CLUST_RESET, i, 0, 0))
                                       GDT_CLUST_RESET, i, 0, 0))
                     ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
                     ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
                 gdth_polling = FALSE;
                 gdth_polling = FALSE;
@@ -4874,9 +3980,9 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
         for (i = 0; i < MAXID; ++i)
         for (i = 0; i < MAXID; ++i)
             ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
             ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
         gdth_polling = TRUE;
         gdth_polling = TRUE;
-        while (gdth_test_busy(hanum))
+        while (gdth_test_busy(ha))
             gdth_delay(0);
             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);
                           BUS_L2P(ha,b), 0, 0);
         gdth_polling = FALSE;
         gdth_polling = FALSE;
         spin_unlock_irqrestore(&ha->smp_lock, flags);
         spin_unlock_irqrestore(&ha->smp_lock, flags);
@@ -4884,30 +3990,18 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
     return SUCCESS;
     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)
 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;
     unchar b, t;
-    int hanum;
-    gdth_ha_str *ha;
+    gdth_ha_str *ha = shost_priv(sdev->host);
     struct scsi_device *sd;
     struct scsi_device *sd;
     unsigned capacity;
     unsigned capacity;
 
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     sd = sdev;
     sd = sdev;
     capacity = cap;
     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;
     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) {
     if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
         /* raw device or host drive without mapping information */
         /* 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]));
     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
 #ifdef GDTH_STATISTICS
     ++act_ios;
     ++act_ios;
 #endif
 #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;
     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)
 static int gdth_open(struct inode *inode, struct file *filep)
 {
 {
     gdth_ha_str *ha;
     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)
         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"));
     TRACE(("gdth_open()\n"));
@@ -4983,10 +4084,11 @@ static int ioc_event(void __user *arg)
     gdth_ha_str *ha;
     gdth_ha_str *ha;
     ulong flags;
     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;
         return -EFAULT;
-    ha = HADATA(gdth_ctr_tab[evt.ionode]);
 
 
     if (evt.erase == 0xff) {
     if (evt.erase == 0xff) {
         if (evt.event.event_source == ES_TEST)
         if (evt.event.event_source == ES_TEST)
@@ -5020,11 +4122,12 @@ static int ioc_lockdrv(void __user *arg)
     ulong flags;
     ulong flags;
     gdth_ha_str *ha;
     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;
         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) {
     for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
         j = ldrv.drives[i];
         j = ldrv.drives[i];
         if (j >= MAX_HDRIVES || !ha->hdr[j].present)
         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);
             spin_lock_irqsave(&ha->smp_lock, flags);
             ha->hdr[j].lock = 1;
             ha->hdr[j].lock = 1;
             spin_unlock_irqrestore(&ha->smp_lock, flags);
             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 {
         } else {
             spin_lock_irqsave(&ha->smp_lock, flags);
             spin_lock_irqsave(&ha->smp_lock, flags);
             ha->hdr[j].lock = 0;
             ha->hdr[j].lock = 0;
             spin_unlock_irqrestore(&ha->smp_lock, flags);
             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;
     return 0;
@@ -5050,16 +4153,16 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
 {
 {
     gdth_ioctl_reset res;
     gdth_ioctl_reset res;
     gdth_cmd_str cmd;
     gdth_cmd_str cmd;
-    int hanum;
     gdth_ha_str *ha;
     gdth_ha_str *ha;
     int rval;
     int rval;
 
 
     if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
     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;
         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)
     if (!ha->hdr[res.number].present)
         return 0;
         return 0;
     memset(&cmd, 0, sizeof(gdth_cmd_str));
     memset(&cmd, 0, sizeof(gdth_cmd_str));
@@ -5085,22 +4188,21 @@ static int ioc_general(void __user *arg, char *cmnd)
     gdth_ioctl_general gen;
     gdth_ioctl_general gen;
     char *buf = NULL;
     char *buf = NULL;
     ulong64 paddr; 
     ulong64 paddr; 
-    int hanum;
     gdth_ha_str *ha;
     gdth_ha_str *ha;
     int rval;
     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;
         return -EFAULT;
-    hanum = gen.ionode; 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     if (gen.data_len + gen.sense_len != 0) {
     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)))
                                      FALSE, &paddr)))
             return -EFAULT;
             return -EFAULT;
         if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general),  
         if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general),  
                            gen.data_len + gen.sense_len)) {
                            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;
             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;
                 gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len;
             }
             }
         } else {
         } 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;
             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, 
     if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, 
                      gen.data_len + gen.sense_len)) {
                      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; 
         return -EFAULT; 
     } 
     } 
     if (copy_to_user(arg, &gen, 
     if (copy_to_user(arg, &gen, 
         sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
         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;
         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;
     return 0;
 }
 }
  
  
@@ -5204,7 +4306,7 @@ static int ioc_hdrlist(void __user *arg, char *cmnd)
     gdth_cmd_str *cmd;
     gdth_cmd_str *cmd;
     gdth_ha_str *ha;
     gdth_ha_str *ha;
     unchar i;
     unchar i;
-    int hanum, rc = -ENOMEM;
+    int rc = -ENOMEM;
     u32 cluster_type = 0;
     u32 cluster_type = 0;
 
 
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
@@ -5213,12 +4315,10 @@ static int ioc_hdrlist(void __user *arg, char *cmnd)
         goto free_fail;
         goto free_fail;
 
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
-        rsc->ionode >= gdth_ctr_count) {
+        (NULL == (ha = gdth_find_ha(rsc->ionode)))) {
         rc = -EFAULT;
         rc = -EFAULT;
         goto free_fail;
         goto free_fail;
     }
     }
-    hanum = rsc->ionode;
-    ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
     memset(cmd, 0, sizeof(gdth_cmd_str));
    
    
     for (i = 0; i < MAX_HDRIVES; ++i) { 
     for (i = 0; i < MAX_HDRIVES; ++i) { 
@@ -5259,7 +4359,7 @@ static int ioc_rescan(void __user *arg, char *cmnd)
     gdth_cmd_str *cmd;
     gdth_cmd_str *cmd;
     ushort i, status, hdr_cnt;
     ushort i, status, hdr_cnt;
     ulong32 info;
     ulong32 info;
-    int hanum, cyls, hds, secs;
+    int cyls, hds, secs;
     int rc = -ENOMEM;
     int rc = -ENOMEM;
     ulong flags;
     ulong flags;
     gdth_ha_str *ha; 
     gdth_ha_str *ha; 
@@ -5270,12 +4370,10 @@ static int ioc_rescan(void __user *arg, char *cmnd)
         goto free_fail;
         goto free_fail;
 
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
-        rsc->ionode >= gdth_ctr_count) {
+        (NULL == (ha = gdth_find_ha(rsc->ionode)))) {
         rc = -EFAULT;
         rc = -EFAULT;
         goto free_fail;
         goto free_fail;
     }
     }
-    hanum = rsc->ionode;
-    ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
     memset(cmd, 0, sizeof(gdth_cmd_str));
 
 
     if (rsc->flag == 0) {
     if (rsc->flag == 0) {
@@ -5432,9 +4530,9 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
         gdth_ioctl_ctrtype ctrt;
         gdth_ioctl_ctrtype ctrt;
         
         
         if (copy_from_user(&ctrt, argp, sizeof(gdth_ioctl_ctrtype)) ||
         if (copy_from_user(&ctrt, argp, sizeof(gdth_ioctl_ctrtype)) ||
-            ctrt.ionode >= gdth_ctr_count)
+            (NULL == (ha = gdth_find_ha(ctrt.ionode))))
             return -EFAULT;
             return -EFAULT;
-        ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
+
         if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
         if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
             ctrt.type = (unchar)((ha->stype>>20) - 0x10);
             ctrt.type = (unchar)((ha->stype>>20) - 0x10);
         } else {
         } else {
@@ -5473,10 +4571,9 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
         unchar i, j;
         unchar i, j;
 
 
         if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) ||
         if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) ||
-            lchn.ionode >= gdth_ctr_count)
+            (NULL == (ha = gdth_find_ha(lchn.ionode))))
             return -EFAULT;
             return -EFAULT;
-        ha = HADATA(gdth_ctr_tab[lchn.ionode]);
-        
+
         i = lchn.channel;
         i = lchn.channel;
         if (i < ha->bus_cnt) {
         if (i < ha->bus_cnt) {
             if (lchn.lock) {
             if (lchn.lock) {
@@ -5484,16 +4581,16 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
                 ha->raw[i].lock = 1;
                 ha->raw[i].lock = 1;
                 spin_unlock_irqrestore(&ha->smp_lock, flags);
                 spin_unlock_irqrestore(&ha->smp_lock, flags);
                 for (j = 0; j < ha->tid_cnt; ++j) {
                 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 {
             } else {
                 spin_lock_irqsave(&ha->smp_lock, flags);
                 spin_lock_irqsave(&ha->smp_lock, flags);
                 ha->raw[i].lock = 0;
                 ha->raw[i].lock = 0;
                 spin_unlock_irqrestore(&ha->smp_lock, flags);
                 spin_unlock_irqrestore(&ha->smp_lock, flags);
                 for (j = 0; j < ha->tid_cnt; ++j) {
                 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:
       case GDTIOCTL_RESET_BUS:
       {
       {
         gdth_ioctl_reset res;
         gdth_ioctl_reset res;
-        int hanum, rval;
+        int rval;
 
 
         if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) ||
         if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) ||
-            res.ionode >= gdth_ctr_count)
+            (NULL == (ha = gdth_find_ha(res.ionode))))
             return -EFAULT;
             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)
         if (!scp)
             return -ENOMEM;
             return -ENOMEM;
-        memset(scp, 0, sizeof(*scp));
         scp->device = ha->sdev;
         scp->device = ha->sdev;
         scp->cmd_len = 12;
         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);
         rval = gdth_eh_bus_reset(scp);
         res.status = (rval == SUCCESS ? S_OK : S_GENERR);
         res.status = (rval == SUCCESS ? S_OK : S_GENERR);
         kfree(scp);
         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)))
         if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset)))
             return -EFAULT;
             return -EFAULT;
         break;
         break;
@@ -5556,16 +4638,14 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
 
 
 
 
 /* flush routine */
 /* flush routine */
-static void gdth_flush(int hanum)
+static void gdth_flush(gdth_ha_str *ha)
 {
 {
     int             i;
     int             i;
-    gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cmd_str    gdtcmd;
     char            cmnd[MAX_COMMAND_SIZE];   
     char            cmnd[MAX_COMMAND_SIZE];   
     memset(cmnd, 0xff, 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) {
     for (i = 0; i < MAX_HDRIVES; ++i) {
         if (ha->hdr[i].present) {
         if (ha->hdr[i].present) {
@@ -5581,9 +4661,9 @@ static void gdth_flush(int hanum)
                 gdtcmd.u.cache.BlockNo = 1;
                 gdtcmd.u.cache.BlockNo = 1;
                 gdtcmd.u.cache.sg_canz = 0;
                 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 */
 /* shutdown routine */
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
 {
 {
-    int             hanum;
+    gdth_ha_str *ha;
 #ifndef __alpha__
 #ifndef __alpha__
     gdth_cmd_str    gdtcmd;
     gdth_cmd_str    gdtcmd;
     char            cmnd[MAX_COMMAND_SIZE];   
     char            cmnd[MAX_COMMAND_SIZE];   
@@ -5606,8 +4686,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
 
 
     notifier_disabled = 1;
     notifier_disabled = 1;
     printk("GDT-HA: Flushing all host drives .. ");
     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__
 #ifndef __alpha__
         /* controller reset */
         /* controller reset */
@@ -5615,8 +4695,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
         gdtcmd.BoardNode = LOCALBOARD;
         gdtcmd.BoardNode = LOCALBOARD;
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_RESET;
         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
 #endif
     }
     }
     printk("Done.\n");
     printk("Done.\n");
@@ -5627,7 +4707,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
     return NOTIFY_OK;
     return NOTIFY_OK;
 }
 }
 
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 /* configure lun */
 /* configure lun */
 static int gdth_slave_configure(struct scsi_device *sdev)
 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;
     sdev->skip_ms_page_8 = 1;
     return 0;
     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",
         .name                   = "GDT SCSI Disk Array Controller",
-        .detect                 = gdth_detect, 
-        .release                = gdth_release,
         .info                   = gdth_info, 
         .info                   = gdth_info, 
         .queuecommand           = gdth_queuecommand,
         .queuecommand           = gdth_queuecommand,
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
+        .slave_configure        = gdth_slave_configure,
         .bios_param             = gdth_bios_param,
         .bios_param             = gdth_bios_param,
+        .proc_info              = gdth_proc_info,
+        .proc_name              = "gdth",
         .can_queue              = GDTH_MAXCMDS,
         .can_queue              = GDTH_MAXCMDS,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        .slave_configure        = gdth_slave_configure,
-#endif
         .this_id                = -1,
         .this_id                = -1,
         .sg_tablesize           = GDTH_MAXSG,
         .sg_tablesize           = GDTH_MAXSG,
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .unchecked_isa_dma      = 1,
         .unchecked_isa_dma      = 1,
         .use_clustering         = ENABLE_CLUSTERING,
         .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
 #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
 #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
 #ifndef MODULE
 __setup("gdth=", option_setup);
 __setup("gdth=", option_setup);
 #endif
 #endif

+ 21 - 21
drivers/scsi/gdth.h

@@ -13,7 +13,6 @@
  * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $
  * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $
  */
  */
 
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/types.h>
 
 
 #ifndef TRUE
 #ifndef TRUE
@@ -304,15 +303,8 @@
 #define MAILBOXREG      0x0c90                  /* mailbox reg. (16 bytes) */
 #define MAILBOXREG      0x0c90                  /* mailbox reg. (16 bytes) */
 #define EISAREG         0x0cc0                  /* EISA configuration */
 #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 */
 /* other defines */
 #define LINUX_OS        8                       /* used for cache optim. */
 #define LINUX_OS        8                       /* used for cache optim. */
-#define SCATTER_GATHER  1                       /* s/g feature */
 #define SECS32          0x1f                    /* round capacity */
 #define SECS32          0x1f                    /* round capacity */
 #define BIOS_ID_OFFS    0x10                    /* offset contr-ID in ISABIOS */
 #define BIOS_ID_OFFS    0x10                    /* offset contr-ID in ISABIOS */
 #define LOCALBOARD      0                       /* board node always 0 */
 #define LOCALBOARD      0                       /* board node always 0 */
@@ -854,6 +846,9 @@ typedef struct {
 
 
 /* controller information structure */
 /* controller information structure */
 typedef struct {
 typedef struct {
+    struct Scsi_Host    *shost;
+    struct list_head    list;
+    ushort      	hanum;
     ushort              oem_id;                 /* OEM */
     ushort              oem_id;                 /* OEM */
     ushort              type;                   /* controller class */
     ushort              type;                   /* controller class */
     ulong32             stype;                  /* subtype (PCI: device ID) */
     ulong32             stype;                  /* subtype (PCI: device ID) */
@@ -865,6 +860,7 @@ typedef struct {
     void __iomem        *brd;                   /* DPRAM address */
     void __iomem        *brd;                   /* DPRAM address */
     ulong32             brd_phys;               /* slot number/BIOS address */
     ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
+    gdth_cmd_str        cmdext;
     gdth_cmd_str        *pccb;                  /* address command structure */
     gdth_cmd_str        *pccb;                  /* address command structure */
     ulong32             ccb_phys;               /* phys. address */
     ulong32             ccb_phys;               /* phys. address */
 #ifdef INT_COAL
 #ifdef INT_COAL
@@ -916,6 +912,19 @@ typedef struct {
         Scsi_Cmnd       *cmnd;                  /* pending request */
         Scsi_Cmnd       *cmnd;                  /* pending request */
         ushort          service;                /* service */
         ushort          service;                /* service */
     } cmd_tab[GDTH_MAXCMDS];                    /* table of pend. requests */
     } 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              bus_cnt;                /* SCSI bus count */
     unchar              tid_cnt;                /* Target ID count */
     unchar              tid_cnt;                /* Target ID count */
     unchar              bus_id[MAXBUS];         /* IOP IDs */
     unchar              bus_id[MAXBUS];         /* IOP IDs */
@@ -938,19 +947,10 @@ typedef struct {
     struct scsi_device         *sdev;
     struct scsi_device         *sdev;
 } gdth_ha_str;
 } 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 */
 /* INQUIRY data format */
 typedef struct {
 typedef struct {

+ 0 - 31
drivers/scsi/gdth_kcompat.h

@@ -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

+ 43 - 90
drivers/scsi/gdth_proc.c

@@ -4,62 +4,32 @@
 
 
 #include <linux/completion.h>
 #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 gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,   
                    int inout)
                    int inout)
 {
 {
-    int hanum,busnum;
+    gdth_ha_str *ha = shost_priv(host);
 
 
     TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
     TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
             length,(int)offset,inout));
             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)
     if (inout)
-        return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum));
+        return(gdth_set_info(buffer,length,host,ha));
     else
     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,
 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;
     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 (length >= 4) {
         if (strncmp(buffer,"gdth",4) == 0) {
         if (strncmp(buffer,"gdth",4) == 0) {
             buffer += 5;
             buffer += 5;
             length -= 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,
 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 orig_length, drive, wb_mode;
     int i, found;
     int i, found;
-    gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
     gdth_cpar_str   *pcpar;
     ulong64         paddr;
     ulong64         paddr;
@@ -80,8 +49,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
     memset(cmnd, 0xff, 12);
     memset(cmnd, 0xff, 12);
     memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
     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;
     orig_length = length + 5;
     drive = -1;
     drive = -1;
     wb_mode = 0;
     wb_mode = 0;
@@ -157,7 +125,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
     }
     }
 
 
     if (wb_mode) {
     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);
             return(-EBUSY);
         pcpar = (gdth_cpar_str *)ha->pscratch;
         pcpar = (gdth_cpar_str *)ha->pscratch;
         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
         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_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");
         printk("Done.\n");
         return(orig_length);
         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,
 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;
     int size = 0,len = 0;
     off_t begin = 0,pos = 0;
     off_t begin = 0,pos = 0;
-    gdth_ha_str *ha;
     int id, i, j, k, sec, flag;
     int id, i, j, k, sec, flag;
     int no_mdrv = 0, drv_no, is_mirr;
     int no_mdrv = 0, drv_no, is_mirr;
     ulong32 cnt;
     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(cmnd, 0xff, 12);
     memset(gdtcmd, 0, sizeof(gdth_cmd_str));
     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" */ 
     /* 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 */
     /* controller information */
     size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
     size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
     len += size;  pos = begin + len;
     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,
     size = sprintf(buffer+len,
                    " Number:       \t%d         \tName:          \t%s\n",
                    " Number:       \t%d         \tName:          \t%s\n",
-                   hanum, hrec);
+                   ha->hanum, hrec);
     len += size;  pos = begin + len;
     len += size;  pos = begin + len;
 
 
     if (ha->more_proc)
     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;
         len += size;  pos = begin + len;
         flag = FALSE;
         flag = FALSE;
             
             
-        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
         if (!buf) 
         if (!buf) 
             goto stop_output;
             goto stop_output;
         for (i = 0; i < ha->bus_cnt; ++i) {
         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;
                     goto stop_output;
             }
             }
         }
         }
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
 
 
         if (!flag) {
         if (!flag) {
             size = sprintf(buffer+len, "\n --\n");
             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;
         len += size;  pos = begin + len;
         flag = FALSE;
         flag = FALSE;
 
 
-        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
         if (!buf) 
         if (!buf) 
             goto stop_output;
             goto stop_output;
         for (i = 0; i < MAX_LDRIVES; ++i) {
         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)
             if (pos > offset + length)
                 goto stop_output;
                 goto stop_output;
         }       
         }       
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
         
         if (!flag) {
         if (!flag) {
             size = sprintf(buffer+len, "\n --\n");
             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;
         len += size;  pos = begin + len;
         flag = FALSE;
         flag = FALSE;
 
 
-        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
         if (!buf) 
         if (!buf) 
             goto stop_output;
             goto stop_output;
         for (i = 0; i < MAX_LDRIVES; ++i) {
         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;
                     goto stop_output;
             }
             }
         }
         }
-        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
         
         if (!flag) {
         if (!flag) {
             size = sprintf(buffer+len, "\n --\n");
             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;
         len += size;  pos = begin + len;
         flag = FALSE;
         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) 
         if (!buf) 
             goto stop_output;
             goto stop_output;
         for (i = 0; i < MAX_LDRIVES; ++i) {
         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) {
         for (i = 0; i < MAX_HDRIVES; ++i) {
             if (!(ha->hdr[i].present))
             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);
         id = gdth_read_event(ha, id, estr);
         if (estr->event_source == 0)
         if (estr->event_source == 0)
             break;
             break;
-        if (estr->event_data.eu.driver.ionode == hanum &&
+        if (estr->event_data.eu.driver.ionode == ha->hanum &&
             estr->event_source == ES_ASYNC) { 
             estr->event_source == ES_ASYNC) { 
             gdth_log_event(&estr->event_data, hrec);
             gdth_log_event(&estr->event_data, hrec);
             do_gettimeofday(&tv);
             do_gettimeofday(&tv);
@@ -699,17 +662,15 @@ free_fail:
     return rc;
     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)
                               ulong64 *paddr)
 {
 {
-    gdth_ha_str *ha;
     ulong flags;
     ulong flags;
     char *ret_val;
     char *ret_val;
 
 
     if (size == 0)
     if (size == 0)
         return NULL;
         return NULL;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
     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;
     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;
     ulong flags;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     if (buf == ha->pscratch) {
     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
 #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;
     ulong flags;
     int ret_val;
     int ret_val;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     ret_val = FALSE;
     ret_val = FALSE;
@@ -766,27 +723,27 @@ static int gdth_ioctl_check_bin(int hanum, ushort size)
 }
 }
 #endif
 #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;
     ulong flags;
     int i;
     int i;
     Scsi_Cmnd *scp;
     Scsi_Cmnd *scp;
+    struct gdth_cmndinfo *cmndinfo;
     unchar b, t;
     unchar b, t;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         scp = ha->cmd_tab[i].cmnd;
         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;
         t = scp->device->id;
         if (!SPECIAL_SCP(scp) && t == (unchar)id && 
         if (!SPECIAL_SCP(scp) && t == (unchar)id && 
             b == (unchar)busnum) {
             b == (unchar)busnum) {
-            scp->SCp.have_data_in = 0;
+            cmndinfo->wait_for_completion = 0;
             spin_unlock_irqrestore(&ha->smp_lock, flags);
             spin_unlock_irqrestore(&ha->smp_lock, flags);
-            while (!scp->SCp.have_data_in)
+            while (!cmndinfo->wait_for_completion)
                 barrier();
                 barrier();
             spin_lock_irqsave(&ha->smp_lock, flags);
             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);
     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;
     ulong flags;
     Scsi_Cmnd *scp;
     Scsi_Cmnd *scp;
     unchar b, t;
     unchar b, t;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
     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;
             t = scp->device->id;
             if (t == (unchar)id && b == (unchar)busnum) {
             if (t == (unchar)id && b == (unchar)busnum) {
                 TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
                 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);
     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;
     ulong flags;
     Scsi_Cmnd *scp;
     Scsi_Cmnd *scp;
     unchar b, t;
     unchar b, t;
 
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
     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;
             t = scp->device->id;
             if (t == (unchar)id && b == (unchar)busnum) {
             if (t == (unchar)id && b == (unchar)busnum) {
                 TRACE2(("gdth_start_timeout(): update_timeout()\n"));
                 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);
     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;
     int oldto;
 
 

+ 10 - 10
drivers/scsi/gdth_proc.h

@@ -9,20 +9,20 @@ int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
                  int timeout, u32 *info);
                  int timeout, u32 *info);
 
 
 static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
 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,
 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,
 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
 #endif
 
 

+ 1 - 0
drivers/scsi/hosts.c

@@ -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->unchecked_isa_dma = sht->unchecked_isa_dma;
 	shost->use_clustering = sht->use_clustering;
 	shost->use_clustering = sht->use_clustering;
 	shost->ordered_tag = sht->ordered_tag;
 	shost->ordered_tag = sht->ordered_tag;
+	shost->active_mode = sht->supported_mode;
 
 
 	if (sht->max_host_blocked)
 	if (sht->max_host_blocked)
 		shost->max_host_blocked = sht->max_host_blocked;
 		shost->max_host_blocked = sht->max_host_blocked;

+ 48 - 15
drivers/scsi/hptiop.c

@@ -1,6 +1,6 @@
 /*
 /*
  * HighPoint RR3xxx controller driver for Linux
  * 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
  * 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
  * 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 char driver_name[] = "hptiop";
 static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver";
 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_host_request_callback(struct hptiop_hba *hba, u32 tag);
 static void hptiop_iop_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)
 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,
 		return hptiop_host_request_callback(hba,
 				tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
 				tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
 	else
 	else
@@ -323,12 +323,22 @@ static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req)
 	hba->req_list = 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 hpt_iop_request_scsi_command *req;
 	struct scsi_cmnd *scp;
 	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, "
 	dprintk("hptiop_host_request_callback: req=%p, type=%d, "
 			"result=%d, context=0x%x tag=%d\n",
 			"result=%d, context=0x%x tag=%d\n",
 			req, req->header.type, req->header.result,
 			req, req->header.type, req->header.result,
@@ -497,7 +507,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 		goto cmd_done;
 		goto cmd_done;
 	}
 	}
 
 
-	req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
+	req = _req->req_virt;
 
 
 	/* build S/G table */
 	/* build S/G table */
 	sg_count = hptiop_buildsgl(scp, req->sg_list);
 	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));
 	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;
 	return 0;
 
 
@@ -688,6 +709,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
 	hba->pcidev = pcidev;
 	hba->pcidev = pcidev;
 	hba->host = host;
 	hba->host = host;
 	hba->initialized = 0;
 	hba->initialized = 0;
+	hba->iopintf_v2 = 0;
 
 
 	atomic_set(&hba->resetting, 0);
 	atomic_set(&hba->resetting, 0);
 	atomic_set(&hba->reset_count, 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_request_size = le32_to_cpu(iop_config.request_size);
 	hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);
 	hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);
 	hba->firmware_version = le32_to_cpu(iop_config.firmware_version);
 	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);
 	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_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9;
 	host->max_id = le32_to_cpu(iop_config.max_devices);
 	host->max_id = le32_to_cpu(iop_config.max_devices);
 	host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count);
 	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->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
 	host->max_cmd_len = 16;
 	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.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)) {
 	if (iop_set_config(hba, &set_config)) {
 		printk(KERN_ERR "scsi%d: set config failed\n",
 		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 */
 	/* 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);
 	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[] = {
 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_exit(hptiop_module_exit);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
+

+ 10 - 219
drivers/scsi/hptiop.h

@@ -1,6 +1,6 @@
 /*
 /*
  * HighPoint RR3xxx controller driver for Linux
  * 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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -18,219 +18,6 @@
 #ifndef _HPTIOP_H_
 #ifndef _HPTIOP_H_
 #define _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
 struct hpt_iopmu
 {
 {
 	__le32 resrved0[4];
 	__le32 resrved0[4];
@@ -252,6 +39,8 @@ struct hpt_iopmu
 #define IOPMU_QUEUE_EMPTY            0xffffffff
 #define IOPMU_QUEUE_EMPTY            0xffffffff
 #define IOPMU_QUEUE_MASK_HOST_BITS   0xf0000000
 #define IOPMU_QUEUE_MASK_HOST_BITS   0xf0000000
 #define IOPMU_QUEUE_ADDR_HOST_BIT    0x80000000
 #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_MSG0      1
 #define IOPMU_OUTBOUND_INT_MSG1      2
 #define IOPMU_OUTBOUND_INT_MSG1      2
@@ -336,7 +125,8 @@ struct hpt_iop_request_set_config
 {
 {
 	struct hpt_iop_request_header header;
 	struct hpt_iop_request_header header;
 	__le32 iop_id;
 	__le32 iop_id;
-	__le32 vbus_id;
+	__le16 vbus_id;
+	__le16 max_host_request_size;
 	__le32 reserve[6];
 	__le32 reserve[6];
 };
 };
 
 
@@ -412,9 +202,8 @@ struct hptiop_hba {
 	struct Scsi_Host * host;
 	struct Scsi_Host * host;
 	struct pci_dev * pcidev;
 	struct pci_dev * pcidev;
 
 
-	struct list_head link;
-
 	/* IOP config info */
 	/* IOP config info */
+	u32     interface_version;
 	u32     firmware_version;
 	u32     firmware_version;
 	u32     sdram_size;
 	u32     sdram_size;
 	u32     max_devices;
 	u32     max_devices;
@@ -423,8 +212,10 @@ struct hptiop_hba {
 	u32     max_sg_descriptors;
 	u32     max_sg_descriptors;
 
 
 	u32     req_size; /* host-allocated request buffer size */
 	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 * req_list;
 	struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];
 	struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];

+ 1 - 7
drivers/scsi/ibmmca.c

@@ -460,13 +460,6 @@ module_param(boot_options, charp, 0);
 module_param_array(io_port, int, NULL, 0);
 module_param_array(io_port, int, NULL, 0);
 module_param_array(scsi_id, 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");
 MODULE_LICENSE("GPL");
 #endif
 #endif
 /*counter of concurrent disk read/writes, to turn on/off disk led */
 /*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);
 	scsi_remove_host(shpnt);
 	release_region(shpnt->io_port, shpnt->n_io_port);
 	release_region(shpnt->io_port, shpnt->n_io_port);
 	free_irq(shpnt->irq, dev);
 	free_irq(shpnt->irq, dev);
+	scsi_host_put(shpnt);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 2
drivers/scsi/ibmvscsi/Makefile

@@ -1,9 +1,7 @@
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
 
 
 ibmvscsic-y			+= ibmvscsi.o
 ibmvscsic-y			+= ibmvscsi.o
-ifndef CONFIG_PPC_PSERIES
 ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
 ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
-endif
 ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
 ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
 
 
 obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o
 obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o

+ 61 - 20
drivers/scsi/ibmvscsi/ibmvscsi.c

@@ -70,11 +70,13 @@
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
+#include <asm/firmware.h>
 #include <asm/vio.h>
 #include <asm/vio.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_srp.h>
 #include "ibmvscsi.h"
 #include "ibmvscsi.h"
 
 
 /* The values below are somewhat arbitrary default values, but 
 /* 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 init_timeout = 5;
 static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
 static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
 
 
+static struct scsi_transport_template *ibmvscsi_transport_template;
+
 #define IBMVSCSI_VERSION "1.5.8"
 #define IBMVSCSI_VERSION "1.5.8"
 
 
+static struct ibmvscsi_ops *ibmvscsi_ops;
+
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
 MODULE_AUTHOR("Dave Boutcher");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
@@ -506,8 +512,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
 	atomic_set(&hostdata->request_limit, 0);
 	atomic_set(&hostdata->request_limit, 0);
 
 
 	purge_requests(hostdata, DID_ERROR);
 	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)))) {
 	    (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
 		atomic_set(&hostdata->request_limit, -1);
 		atomic_set(&hostdata->request_limit, -1);
 		dev_err(hostdata->dev, "error after reset\n");
 		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 =
 	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);
 		list_del(&evt_struct->list);
 		del_timer(&evt_struct->timer);
 		del_timer(&evt_struct->timer);
 
 
@@ -1211,8 +1217,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 		case 0x01:	/* Initialization message */
 		case 0x01:	/* Initialization message */
 			dev_info(hostdata->dev, "partner initialized\n");
 			dev_info(hostdata->dev, "partner initialized\n");
 			/* Send back a response */
 			/* 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 */
 				/* Now login */
 				send_srp_login(hostdata);
 				send_srp_login(hostdata);
 			} else {
 			} else {
@@ -1237,10 +1243,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			/* We need to re-setup the interpartition connection */
 			/* We need to re-setup the interpartition connection */
 			dev_info(hostdata->dev, "Re-enabling adapter!\n");
 			dev_info(hostdata->dev, "Re-enabling adapter!\n");
 			purge_requests(hostdata, DID_REQUEUE);
 			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,
 					atomic_set(&hostdata->request_limit,
 						   -1);
 						   -1);
 					dev_err(hostdata->dev, "error after enable\n");
 					dev_err(hostdata->dev, "error after enable\n");
@@ -1250,10 +1256,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 				crq->format);
 				crq->format);
 
 
 			purge_requests(hostdata, DID_ERROR);
 			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,
 					atomic_set(&hostdata->request_limit,
 						   -1);
 						   -1);
 					dev_err(hostdata->dev, "error after reset\n");
 					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 ibmvscsi_host_data *hostdata;
 	struct Scsi_Host *host;
 	struct Scsi_Host *host;
 	struct device *dev = &vdev->dev;
 	struct device *dev = &vdev->dev;
+	struct srp_rport_identifiers ids;
+	struct srp_rport *rport;
 	unsigned long wait_switch = 0;
 	unsigned long wait_switch = 0;
 	int rc;
 	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;
 		goto scsi_host_alloc_failed;
 	}
 	}
 
 
+	host->transportt = ibmvscsi_transport_template;
 	hostdata = shost_priv(host);
 	hostdata = shost_priv(host);
 	memset(hostdata, 0x00, sizeof(*hostdata));
 	memset(hostdata, 0x00, sizeof(*hostdata));
 	INIT_LIST_HEAD(&hostdata->sent);
 	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);
 	atomic_set(&hostdata->request_limit, -1);
 	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 	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) {
 	if (rc != 0 && rc != H_RESOURCE) {
 		dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
 		dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
 		goto init_crq_failed;
 		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))
 	if (scsi_add_host(hostdata->host, hostdata->dev))
 		goto add_host_failed;
 		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
 	/* 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
 	 * to fail if the other end is not acive.  In that case we don't
 	 * want to scan
 	 * want to scan
 	 */
 	 */
-	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+	if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
 	    || rc == H_RESOURCE) {
 	    || rc == H_RESOURCE) {
 		/*
 		/*
 		 * Wait around max init_timeout secs for the adapter to finish
 		 * 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;
 	vdev->dev.driver_data = hostdata;
 	return 0;
 	return 0;
 
 
+      add_srp_port_failed:
+	scsi_remove_host(hostdata->host);
       add_host_failed:
       add_host_failed:
 	release_event_pool(&hostdata->pool, hostdata);
 	release_event_pool(&hostdata->pool, hostdata);
       init_pool_failed:
       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:
       init_crq_failed:
 	scsi_host_put(host);
 	scsi_host_put(host);
       scsi_host_alloc_failed:
       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;
 	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
 	release_event_pool(&hostdata->pool, hostdata);
 	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_remove_host(hostdata->host);
 	scsi_host_put(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)
 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)
 void __exit ibmvscsi_module_exit(void)
 {
 {
 	vio_unregister_driver(&ibmvscsi_driver);
 	vio_unregister_driver(&ibmvscsi_driver);
+	srp_release_transport(ibmvscsi_transport_template);
 }
 }
 
 
 module_init(ibmvscsi_module_init);
 module_init(ibmvscsi_module_init);

+ 18 - 14
drivers/scsi/ibmvscsi/ibmvscsi.h

@@ -98,21 +98,25 @@ struct ibmvscsi_host_data {
 };
 };
 
 
 /* routines for managing a command/response queue */
 /* 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,
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			 struct ibmvscsi_host_data *hostdata);
 			 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 */
 #endif				/* IBMVSCSI_H */

+ 54 - 7
drivers/scsi/ibmvscsi/ibmvstgt.c

@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_srp.h>
 #include <scsi/scsi_tgt.h>
 #include <scsi/scsi_tgt.h>
 #include <scsi/libsrp.h>
 #include <scsi/libsrp.h>
 #include <asm/hvcall.h>
 #include <asm/hvcall.h>
@@ -68,9 +69,12 @@ struct vio_port {
 	unsigned long liobn;
 	unsigned long liobn;
 	unsigned long riobn;
 	unsigned long riobn;
 	struct srp_target *target;
 	struct srp_target *target;
+
+	struct srp_rport *rport;
 };
 };
 
 
 static struct workqueue_struct *vtgtd;
 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.
  * 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)
 static void handle_cmd_queue(struct srp_target *target)
 {
 {
 	struct Scsi_Host *shost = target->shost;
 	struct Scsi_Host *shost = target->shost;
+	struct srp_rport *rport = target_to_port(target)->rport;
 	struct iu_entry *iue;
 	struct iu_entry *iue;
 	struct srp_cmd *cmd;
 	struct srp_cmd *cmd;
 	unsigned long flags;
 	unsigned long flags;
@@ -200,7 +205,8 @@ retry:
 		if (!test_and_set_bit(V_FLYING, &iue->flags)) {
 		if (!test_and_set_bit(V_FLYING, &iue->flags)) {
 			spin_unlock_irqrestore(&target->lock, flags);
 			spin_unlock_irqrestore(&target->lock, flags);
 			cmd = iue->sbuf->buf;
 			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) {
 			if (err) {
 				eprintk("cannot queue cmd %p %d\n", cmd, err);
 				eprintk("cannot queue cmd %p %d\n", cmd, err);
 				srp_iu_put(iue);
 				srp_iu_put(iue);
@@ -359,6 +365,16 @@ static void process_login(struct iu_entry *iue)
 	union viosrp_iu *iu = vio_iu(iue);
 	union viosrp_iu *iu = vio_iu(iue);
 	struct srp_login_rsp *rsp = &iu->srp.login_rsp;
 	struct srp_login_rsp *rsp = &iu->srp.login_rsp;
 	uint64_t tag = iu->srp.rsp.tag;
 	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
 	/* TODO handle case that requested size is wrong and
 	 * buffer format is wrong
 	 * buffer format is wrong
@@ -412,7 +428,9 @@ static int process_tsk_mgmt(struct iu_entry *iue)
 		fn = 0;
 		fn = 0;
 	}
 	}
 	if (fn)
 	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,
 					  iu->srp.tsk_mgmt.task_tag,
 					  (struct scsi_lun *) &iu->srp.tsk_mgmt.lun,
 					  (struct scsi_lun *) &iu->srp.tsk_mgmt.lun,
 					  iue);
 					  iue);
@@ -721,7 +739,8 @@ static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc)
 	return 0;
 	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);
 	struct iu_entry *iue = (struct iu_entry *) ((void *) mid);
 	union viosrp_iu *iu = vio_iu(iue);
 	union viosrp_iu *iu = vio_iu(iue);
@@ -747,6 +766,20 @@ static int ibmvstgt_tsk_mgmt_response(u64 mid, int result)
 	return 0;
 	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)
 static ssize_t system_id_show(struct class_device *cdev, char *buf)
 {
 {
 	return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
 	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,
 	.max_sectors		= DEFAULT_MAX_SECTORS,
 	.transfer_response	= ibmvstgt_cmd_done,
 	.transfer_response	= ibmvstgt_cmd_done,
 	.eh_abort_handler	= ibmvstgt_eh_abort_handler,
 	.eh_abort_handler	= ibmvstgt_eh_abort_handler,
-	.tsk_mgmt_response	= ibmvstgt_tsk_mgmt_response,
 	.shost_attrs		= ibmvstgt_attrs,
 	.shost_attrs		= ibmvstgt_attrs,
 	.proc_name		= TGT_NAME,
 	.proc_name		= TGT_NAME,
+	.supported_mode		= MODE_TARGET,
 };
 };
 
 
 static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
 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));
 	shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target));
 	if (!shost)
 	if (!shost)
 		goto free_vport;
 		goto free_vport;
+	shost->transportt = ibmvstgt_transport_template;
 	err = scsi_tgt_alloc_queue(shost);
 	err = scsi_tgt_alloc_queue(shost);
 	if (err)
 	if (err)
 		goto put_host;
 		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);
 	err = scsi_add_host(shost, target->dev);
 	if (err)
 	if (err)
 		goto destroy_queue;
 		goto destroy_queue;
-	return 0;
 
 
+	return 0;
 destroy_queue:
 destroy_queue:
 	crq_queue_destroy(target);
 	crq_queue_destroy(target);
 free_srp_target:
 free_srp_target:
@@ -857,6 +891,7 @@ static int ibmvstgt_remove(struct vio_dev *dev)
 	struct vio_port *vport = target->ldata;
 	struct vio_port *vport = target->ldata;
 
 
 	crq_queue_destroy(target);
 	crq_queue_destroy(target);
+	srp_remove_host(shost);
 	scsi_remove_host(shost);
 	scsi_remove_host(shost);
 	scsi_tgt_free_queue(shost);
 	scsi_tgt_free_queue(shost);
 	srp_target_free(target);
 	srp_target_free(target);
@@ -909,15 +944,25 @@ static int get_system_info(void)
 	return 0;
 	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)
 static int ibmvstgt_init(void)
 {
 {
 	int err = -ENOMEM;
 	int err = -ENOMEM;
 
 
 	printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n");
 	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");
 	vtgtd = create_workqueue("ibmvtgtd");
 	if (!vtgtd)
 	if (!vtgtd)
-		return err;
+		goto release_transport;
 
 
 	err = get_system_info();
 	err = get_system_info();
 	if (err)
 	if (err)
@@ -928,9 +973,10 @@ static int ibmvstgt_init(void)
 		goto destroy_wq;
 		goto destroy_wq;
 
 
 	return 0;
 	return 0;
-
 destroy_wq:
 destroy_wq:
 	destroy_workqueue(vtgtd);
 	destroy_workqueue(vtgtd);
+release_transport:
+	srp_release_transport(ibmvstgt_transport_template);
 	return err;
 	return err;
 }
 }
 
 
@@ -940,6 +986,7 @@ static void ibmvstgt_exit(void)
 
 
 	destroy_workqueue(vtgtd);
 	destroy_workqueue(vtgtd);
 	vio_unregister_driver(&ibmvstgt_driver);
 	vio_unregister_driver(&ibmvstgt_driver);
+	srp_release_transport(ibmvstgt_transport_template);
 }
 }
 
 
 MODULE_DESCRIPTION("IBM Virtual SCSI Target");
 MODULE_DESCRIPTION("IBM Virtual SCSI Target");

+ 23 - 14
drivers/scsi/ibmvscsi/iseries_vscsi.c

@@ -53,7 +53,7 @@ struct srp_lp_event {
 /** 
 /** 
  * standard interface for handling logical partition events.
  * 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;
 	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
  * 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;
 	int rc;
 
 
@@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 		goto viopath_open_failed;
 		goto viopath_open_failed;
 	}
 	}
 
 
-	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+	rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
 	if (rc < 0) {
 	if (rc < 0) {
 		printk("vio_setHandler failed with rc %d in open_event_path\n",
 		printk("vio_setHandler failed with rc %d in open_event_path\n",
 		       rc);
 		       rc);
@@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 	return -1;
 	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);
 	vio_clearHandler(viomajorsubtype_scsi);
 	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
 	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
  * 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;
 	return 0;
 }
 }
@@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
  *
  *
  * no-op for iSeries
  * 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;
 	return 0;
 }
 }
 
 
 /**
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * iseriesvscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word1:	the first 64 bits of the data
  * @word2:	the second 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;
 	single_host_data = hostdata;
 	return HvCallEvent_signalLpEventFast(viopath_hostLp,
 	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,
 					     VIOVERSION << 16, word1, word2, 0,
 					     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,
+};

+ 61 - 52
drivers/scsi/ibmvscsi/rpa_vscsi.c

@@ -42,14 +42,14 @@ static unsigned int partition_number = -1;
  * Routines for managing the command/response queue
  * 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
  * @irq:	number of irq to handle, not used
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
  *
  *
  * Disables interrupts and schedules srp_task
  * Disables interrupts and schedules srp_task
  * Always returns IRQ_HANDLED
  * 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 *hostdata =
 	    (struct ibmvscsi_host_data *)dev_instance;
 	    (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
  * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
  * the crq with the hypervisor.
  * 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;
 	long rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 	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
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word1:	the first 64 bits of the data
  * @word2:	the second 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);
 	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
  * @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 ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 	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;
 	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
  * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
  * @queue:	crq_queue to initialize and register
  * @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.
  * the crq with the hypervisor.
  * Returns zero on success.
  * 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 rc;
 	int retrc;
 	int retrc;
@@ -227,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 				queue->msg_token, PAGE_SIZE);
 				queue->msg_token, PAGE_SIZE);
 	if (rc == H_RESOURCE)
 	if (rc == H_RESOURCE)
 		/* maybe kexecing and resource is busy. try a reset */
 		/* maybe kexecing and resource is busy. try a reset */
-		rc = ibmvscsi_reset_crq_queue(queue,
+		rc = rpavscsi_reset_crq_queue(queue,
 					      hostdata);
 					      hostdata);
 
 
 	if (rc == 2) {
 	if (rc == 2) {
@@ -240,7 +277,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 	}
 	}
 
 
 	if (request_irq(vdev->irq,
 	if (request_irq(vdev->irq,
-			ibmvscsi_handle_event,
+			rpavscsi_handle_event,
 			0, "ibmvscsi", (void *)hostdata) != 0) {
 			0, "ibmvscsi", (void *)hostdata) != 0) {
 		dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
 		dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
 			vdev->irq);
 			vdev->irq);
@@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 	queue->cur = 0;
 	queue->cur = 0;
 	spin_lock_init(&queue->lock);
 	spin_lock_init(&queue->lock);
 
 
-	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
 		     (unsigned long)hostdata);
 		     (unsigned long)hostdata);
 
 
 	return retrc;
 	return retrc;
@@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
  * @hostdata:	ibmvscsi_host_data of host
  * @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;
 	int rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -297,38 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
 	return rc;
 	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,
+};

+ 14 - 126
drivers/scsi/ide-scsi.c

@@ -82,14 +82,12 @@ typedef struct idescsi_pc_s {
  */
  */
 #define PC_DMA_IN_PROGRESS		0	/* 1 while DMA in progress */
 #define PC_DMA_IN_PROGRESS		0	/* 1 while DMA in progress */
 #define PC_WRITING			1	/* Data direction */
 #define PC_WRITING			1	/* Data direction */
-#define PC_TRANSFORM			2	/* transform SCSI commands */
 #define PC_TIMEDOUT			3	/* command timed out */
 #define PC_TIMEDOUT			3	/* command timed out */
 #define PC_DMA_OK			4	/* Use DMA */
 #define PC_DMA_OK			4	/* Use DMA */
 
 
 /*
 /*
  *	SCSI command transformation layer
  *	SCSI command transformation layer
  */
  */
-#define IDESCSI_TRANSFORM		0	/* Enable/Disable transformation */
 #define IDESCSI_SG_TRANSFORM		1	/* /dev/sg 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;
 	char *buf;
 
 
 	while (bcount) {
 	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");
 			printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
 			idescsi_discard_data (drive, bcount);
 			idescsi_discard_data (drive, bcount);
 			return;
 			return;
@@ -210,7 +209,8 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
 	char *buf;
 	char *buf;
 
 
 	while (bcount) {
 	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");
 			printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
 			idescsi_output_zeros (drive, bcount);
 			idescsi_output_zeros (drive, bcount);
 			return;
 			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)
 static void hexdump(u8 *x, int len)
 {
 {
 	int i;
 	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;
 	idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
 	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
 	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
 	struct Scsi_Host *host;
 	struct Scsi_Host *host;
-	u8 *scsi_buf;
 	int errors = rq->errors;
 	int errors = rq->errors;
 	unsigned long flags;
 	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);
 		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
 	} else {
 	} else {
 		pc->scsi_cmd->result = DID_OK << 16;
 		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;
 	host = pc->scsi_cmd->device->host;
 	spin_lock_irqsave(host->host_lock, flags);
 	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;
 		return 1;
 
 
 	sg = hwif->sg_table;
 	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)
 	if (segments > hwif->sg_max_nents)
 		return 1;
 		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;
 	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)
 	if (drive->id && (drive->id->config & 0x0060) == 0x20)
 		set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
 		set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
-	set_bit(IDESCSI_TRANSFORM, &scsi->transform);
 	clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 	clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 #if IDESCSI_DEBUG_LOG
 #if IDESCSI_DEBUG_LOG
 	set_bit(IDESCSI_LOG_CMD, &scsi->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 ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
 	struct gendisk *g = scsi->disk;
 	struct gendisk *g = scsi->disk;
 
 
+	scsi_remove_host(scsihost);
 	ide_proc_unregister_driver(drive, scsi->driver);
 	ide_proc_unregister_driver(drive, scsi->driver);
 
 
 	ide_unregister_region(g);
 	ide_unregister_region(g);
@@ -766,7 +680,6 @@ static void ide_scsi_remove(ide_drive_t *drive)
 	g->private_data = NULL;
 	g->private_data = NULL;
 	put_disk(g);
 	put_disk(g);
 
 
-	scsi_remove_host(scsihost);
 	ide_scsi_put(scsi);
 	ide_scsi_put(scsi);
 }
 }
 
 
@@ -838,6 +751,8 @@ static struct block_device_operations idescsi_ops = {
 static int idescsi_slave_configure(struct scsi_device * sdp)
 static int idescsi_slave_configure(struct scsi_device * sdp)
 {
 {
 	/* Configure detected device */
 	/* 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);
 	scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);
 	return 0;
 	return 0;
 }
 }
@@ -862,24 +777,6 @@ static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg)
 	return -EINVAL;
 	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,
 static int idescsi_queue (struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
 		void (*done)(struct scsi_cmnd *))
 {
 {
@@ -905,23 +802,14 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
 	pc->flags = 0;
 	pc->flags = 0;
 	pc->rq = rq;
 	pc->rq = rq;
 	memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
 	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->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->scsi_cmd = cmd;
 	pc->done = done;
 	pc->done = done;
 	pc->timeout = jiffies + cmd->timeout_per_command;
 	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)) {
 	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
 		printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
 		printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
 		hexdump(cmd->cmnd, cmd->cmd_len);
 		hexdump(cmd->cmnd, cmd->cmd_len);

+ 0 - 4
drivers/scsi/imm.c

@@ -740,10 +740,6 @@ static void imm_interrupt(struct work_struct *work)
 	struct Scsi_Host *host = cmd->device->host;
 	struct Scsi_Host *host = cmd->device->host;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (!cmd) {
-		printk("IMM: bug in imm_interrupt\n");
-		return;
-	}
 	if (imm_engine(dev, cmd)) {
 	if (imm_engine(dev, cmd)) {
 		schedule_delayed_work(&dev->imm_tq, 1);
 		schedule_delayed_work(&dev->imm_tq, 1);
 		return;
 		return;

+ 15 - 15
drivers/scsi/in2000.c

@@ -343,7 +343,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	instance = cmd->device->host;
 	instance = cmd->device->host;
 	hostdata = (struct IN2000_hostdata *) instance->hostdata;
 	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:
 /* 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
  *  - 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);
 	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;
 	    return 0;
 }
 }
 
 
@@ -703,7 +703,7 @@ static void in2000_execute(struct Scsi_Host *instance)
 	 * to search the input_Q again...
 	 * 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_XFER_DONE | PHS_COMMAND:
 	case CSR_UNEXP | PHS_COMMAND:
 	case CSR_UNEXP | PHS_COMMAND:
 	case CSR_SRV_REQ | 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);
 		    transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
 		hostdata->state = S_CONNECTED;
 		hostdata->state = S_CONNECTED;
 		break;
 		break;
@@ -1189,7 +1189,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 		switch (msg) {
 		switch (msg) {
 
 
 		case COMMAND_COMPLETE:
 		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);
 			    write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
 			hostdata->state = S_PRE_CMP_DISC;
 			hostdata->state = S_PRE_CMP_DISC;
 			break;
 			break;
@@ -1327,7 +1327,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 
 
 		write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
 		write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
 		if (phs == 0x60) {
 		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;
 			    cmd->SCp.Message = COMMAND_COMPLETE;
 			lun = read_3393(hostdata, WD_TARGET_LUN);
 			lun = read_3393(hostdata, WD_TARGET_LUN);
 			DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, 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);
 			in2000_execute(instance);
 		} else {
 		} 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;
 		break;
 
 
@@ -1415,7 +1415,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 			spin_unlock_irqrestore(instance->host_lock, flags);
 			spin_unlock_irqrestore(instance->host_lock, flags);
 			return IRQ_HANDLED;
 			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->connected = NULL;
 		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 		hostdata->state = S_UNCONNECTED;
 		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);
 		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) {
 		    if (cmd == NULL) {
 			printk(" - Already disconnected! ");
 			printk(" - Already disconnected! ");
 			hostdata->state = S_UNCONNECTED;
 			hostdata->state = S_UNCONNECTED;
@@ -1573,7 +1573,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 		} else
 		} else
 			hostdata->state = S_CONNECTED;
 			hostdata->state = S_CONNECTED;
 
 
-		DB(DB_INTR, printk("-%ld", cmd->pid))
+		DB(DB_INTR, printk("-%ld", cmd->serial_number))
 		    break;
 		    break;
 
 
 	default:
 	default:
@@ -1702,7 +1702,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd)
 				prev->host_scribble = cmd->host_scribble;
 				prev->host_scribble = cmd->host_scribble;
 			cmd->host_scribble = NULL;
 			cmd->host_scribble = NULL;
 			cmd->result = DID_ABORT << 16;
 			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);
 			cmd->scsi_done(cmd);
 			return SUCCESS;
 			return SUCCESS;
 		}
 		}
@@ -1723,7 +1723,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd)
 
 
 	if (hostdata->connected == 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 - ");
 		printk("sending wd33c93 ABORT command - ");
 		write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 		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:     ");
 		strcat(bp, "\nconnected:     ");
 		if (hd->connected) {
 		if (hd->connected) {
 			cmd = (Scsi_Cmnd *) 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);
 			strcat(bp, tbuf);
 		}
 		}
 	}
 	}
@@ -2276,7 +2276,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
 		strcat(bp, "\ninput_Q:       ");
 		strcat(bp, "\ninput_Q:       ");
 		cmd = (Scsi_Cmnd *) hd->input_Q;
 		cmd = (Scsi_Cmnd *) hd->input_Q;
 		while (cmd) {
 		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);
 			strcat(bp, tbuf);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 			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:");
 		strcat(bp, "\ndisconnected_Q:");
 		cmd = (Scsi_Cmnd *) hd->disconnected_Q;
 		cmd = (Scsi_Cmnd *) hd->disconnected_Q;
 		while (cmd) {
 		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);
 			strcat(bp, tbuf);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 		}

+ 5 - 4
drivers/scsi/ips.c

@@ -204,8 +204,8 @@ module_param(ips, charp, 0);
 /*
 /*
  * DRIVER_VER
  * 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__)
 #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
 #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);
 	METHOD_TRACE("ips_release", 1);
 
 
+	scsi_remove_host(sh);
+
 	for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ;
 	for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ;
 
 
 	if (i == IPS_MAX_ADAPTERS) {
 	if (i == IPS_MAX_ADAPTERS) {
@@ -707,7 +709,6 @@ ips_release(struct Scsi_Host *sh)
 	/* free IRQ */
 	/* free IRQ */
 	free_irq(ha->irq, ha);
 	free_irq(ha->irq, ha);
 
 
-	scsi_remove_host(sh);
 	scsi_host_put(sh);
 	scsi_host_put(sh);
 
 
 	ips_released_controllers++;
 	ips_released_controllers++;
@@ -6946,7 +6947,7 @@ module_exit(ips_module_exit);
 static int __devinit
 static int __devinit
 ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
 ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
 {
 {
-	int index;
+	int uninitialized_var(index);
 	int rc;
 	int rc;
 
 
 	METHOD_TRACE("ips_insert_device", 1);
 	METHOD_TRACE("ips_insert_device", 1);

+ 6 - 5
drivers/scsi/ips.h

@@ -1172,12 +1172,13 @@ typedef struct {
 *************************************************************************/
 *************************************************************************/
 
 
 #define IPS_VER_MAJOR 7
 #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 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_RELEASE_ID 0x00020000
 #define IPS_BUILD_IDENT 761
 #define IPS_BUILD_IDENT 761
 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."

+ 3 - 2
drivers/scsi/libsrp.c

@@ -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,
 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;
 	enum dma_data_direction dir;
 	struct scsi_cmnd *sc;
 	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_bufflen = len;
 	sc->request_buffer = (void *) (unsigned long) addr;
 	sc->request_buffer = (void *) (unsigned long) addr;
 	sc->tag = tag;
 	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)
 	if (err)
 		scsi_host_put_command(shost, sc);
 		scsi_host_put_command(shost, sc);
 
 

+ 1 - 4
drivers/scsi/lpfc/lpfc_debugfs.c

@@ -43,7 +43,6 @@
 #include "lpfc_crtn.h"
 #include "lpfc_crtn.h"
 #include "lpfc_vport.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
 #include "lpfc_version.h"
-#include "lpfc_vport.h"
 #include "lpfc_debugfs.h"
 #include "lpfc_debugfs.h"
 
 
 #ifdef CONFIG_LPFC_DEBUG_FS
 #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),
 		(sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
 		GFP_KERNEL);
 		GFP_KERNEL);
 
 
@@ -913,8 +912,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
 		goto debug_failed;
 		goto debug_failed;
 	}
 	}
 	atomic_set(&vport->disc_trc_cnt, 0);
 	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");
 	snprintf(name, sizeof(name), "discovery_trace");
 	vport->debug_disc_trc =
 	vport->debug_disc_trc =

+ 1 - 3
drivers/scsi/lpfc/lpfc_init.c

@@ -43,7 +43,6 @@
 #include "lpfc_crtn.h"
 #include "lpfc_crtn.h"
 #include "lpfc_vport.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
 #include "lpfc_version.h"
-#include "lpfc_vport.h"
 
 
 static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
 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 *);
 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 *HashWorking;
 	uint32_t *pwwnn = (uint32_t *) phba->wwnn;
 	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)
 	if (!HashWorking)
 		return;
 		return;
 
 
-	memset(HashWorking, 0, (80 * sizeof(uint32_t)));
 	HashWorking[0] = HashWorking[78] = *pwwnn++;
 	HashWorking[0] = HashWorking[78] = *pwwnn++;
 	HashWorking[1] = HashWorking[79] = *pwwnn;
 	HashWorking[1] = HashWorking[79] = *pwwnn;
 
 

+ 1 - 2
drivers/scsi/lpfc/lpfc_scsi.c

@@ -202,10 +202,9 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport)
 	dma_addr_t pdma_phys;
 	dma_addr_t pdma_phys;
 	uint16_t iotag;
 	uint16_t iotag;
 
 
-	psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
+	psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
 	if (!psb)
 	if (!psb)
 		return NULL;
 		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
 	 * Get memory from the pci pool to map the virt space to pci bus space

部分文件因为文件数量过多而无法显示