Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
new file mode 100644
index 0000000..820fd07
--- /dev/null
+++ b/Documentation/scsi/aacraid.txt
@@ -0,0 +1,108 @@
+AACRAID Driver for Linux (take two)
+
+Introduction
+-------------------------
+The aacraid driver adds support for Adaptec (http://www.adaptec.com)
+RAID controllers. This is a major rewrite from the original
+Adaptec supplied driver. It has signficantly cleaned up both the code
+and the running binary size (the module is less than half the size of
+the original).
+
+Supported Cards/Chipsets
+-------------------------
+	PCI ID (pci.ids)	OEM	Product
+	9005:0285:9005:028a	Adaptec	2020ZCR (Skyhawk)
+	9005:0285:9005:028e	Adaptec	2020SA (Skyhawk)
+	9005:0285:9005:028b	Adaptec 2025ZCR (Terminator)
+	9005:0285:9005:028f	Adaptec 2025SA (Terminator)
+	9005:0285:9005:0286	Adaptec	2120S (Crusader)
+	9005:0286:9005:028d	Adaptec	2130S (Lancer)
+	9005:0285:9005:0285	Adaptec	2200S (Vulcan)
+	9005:0285:9005:0287	Adaptec	2200S (Vulcan-2m)
+	9005:0286:9005:028c	Adaptec	2230S (Lancer)
+	9005:0286:9005:028c	Adaptec	2230SLP (Lancer)
+	9005:0285:9005:0296	Adaptec	2240S (SabreExpress)
+	9005:0285:9005:0290	Adaptec	2410SA (Jaguar)
+	9005:0285:9005:0293	Adaptec 21610SA (Corsair-16)
+	9005:0285:103c:3227	Adaptec 2610SA (Bearcat)
+	9005:0285:9005:0292	Adaptec	2810SA (Corsair-8)
+	9005:0285:9005:0294	Adaptec	Prowler
+	9005:0286:9005:029d	Adaptec	2420SA (Intruder)
+	9005:0286:9005:029c	Adaptec	2620SA (Intruder)
+	9005:0286:9005:029b	Adaptec	2820SA (Intruder)
+	9005:0286:9005:02a7	Adaptec	2830SA (Skyray)
+	9005:0286:9005:02a8	Adaptec	2430SA (Skyray)
+	9005:0285:9005:0288	Adaptec	3230S (Harrier)
+	9005:0285:9005:0289	Adaptec	3240S (Tornado)
+	9005:0285:9005:0298	Adaptec	4000SAS (BlackBird)
+	9005:0285:9005:0297	Adaptec	4005SAS (AvonPark)
+	9005:0285:9005:0299	Adaptec	4800SAS (Marauder-X)
+	9005:0285:9005:029a	Adaptec	4805SAS (Marauder-E)
+	9005:0286:9005:02a2	Adaptec	4810SAS (Hurricane)
+	1011:0046:9005:0364	Adaptec	5400S (Mustang)
+	1011:0046:9005:0365	Adaptec	5400S (Mustang)
+	9005:0283:9005:0283	Adaptec	Catapult (3210S with arc firmware)
+	9005:0284:9005:0284	Adaptec	Tomcat (3410S with arc firmware)
+	9005:0287:9005:0800	Adaptec	Themisto (Jupiter)
+	9005:0200:9005:0200	Adaptec	Themisto (Jupiter)
+	9005:0286:9005:0800	Adaptec	Callisto (Jupiter)
+	1011:0046:9005:1364	Dell	PERC 2/QC (Quad Channel, Mustang)
+	1028:0001:1028:0001	Dell	PERC 2/Si (Iguana)
+	1028:0003:1028:0003	Dell	PERC 3/Si (SlimFast)
+	1028:0002:1028:0002	Dell	PERC 3/Di (Opal)
+	1028:0004:1028:0004	Dell	PERC 3/DiF (Iguana)
+	1028:0002:1028:00d1	Dell	PERC 3/DiV (Viper)
+	1028:0002:1028:00d9	Dell	PERC 3/DiL (Lexus)
+	1028:000a:1028:0106	Dell	PERC 3/DiJ (Jaguar)
+	1028:000a:1028:011b	Dell	PERC 3/DiD (Dagger)
+	1028:000a:1028:0121	Dell	PERC 3/DiB (Boxster)
+	9005:0285:1028:0287	Dell	PERC 320/DC (Vulcan)
+	9005:0285:1028:0291	Dell	CERC 2 (DellCorsair)
+	1011:0046:103c:10c2	HP	NetRAID-4M (Mustang)
+	9005:0285:17aa:0286	Legend	S220 (Crusader)
+	9005:0285:17aa:0287	Legend	S230 (Vulcan)
+	9005:0285:9005:0290	IBM	ServeRAID 7t (Jaguar)
+	9005:0285:1014:02F2	IBM	ServeRAID 8i (AvonPark)
+	9005:0285:1014:0312	IBM	ServeRAID 8i (AvonParkLite)
+	9005:0286:1014:9580	IBM	ServeRAID 8k/8k-l8 (Aurora)
+	9005:0286:1014:9540	IBM	ServeRAID 8k/8k-l4 (AuroraLite)
+	9005:0286:9005:029f	ICP	ICP9014R0 (Lancer)
+	9005:0286:9005:029e	ICP	ICP9024R0 (Lancer)
+	9005:0286:9005:02a0	ICP	ICP9047MA (Lancer)
+	9005:0286:9005:02a1	ICP	ICP9087MA (Lancer)
+	9005:0286:9005:02a4	ICP	ICP9085LI (Marauder-X)
+	9005:0286:9005:02a5	ICP	ICP5085BR (Marauder-E)
+	9005:0286:9005:02a3	ICP	ICP5085AU (Hurricane)
+	9005:0286:9005:02a6	ICP	ICP9067MA (Intruder-6)
+	9005:0286:9005:02a9	ICP	ICP5087AU (Skyray)
+	9005:0286:9005:02aa	ICP	ICP5047AU (Skyray)
+
+People
+-------------------------
+Alan Cox <alan@redhat.com>
+Christoph Hellwig <hch@infradead.org>	(updates for new-style PCI probing and SCSI host registration,
+					 small cleanups/fixes)
+Matt Domsch <matt_domsch@dell.com>	(revision ioctl, adapter messages)
+Deanna Bonds                            (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
+					 added new ioctls, changed scsi interface to use new error handler,
+					 increased the number of fibs and outstanding commands to a container)
+
+					(fixed 64bit and 64G memory model, changed confusing naming convention
+					 where fibs that go to the hardware are consistently called hw_fibs and
+					 not just fibs like the name of the driver tracking structure)
+Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
+
+Original Driver
+-------------------------
+Adaptec Unix OEM Product Group
+
+Mailing List
+-------------------------
+linux-scsi@vger.kernel.org (Interested parties troll here)
+Also note this is very different to Brian's original driver
+so don't expect him to support it.
+Adaptec does support this driver.  Contact Adaptec tech support or
+aacraid@adaptec.com
+
+Original by Brian Boerner February 2001
+Rewritten by Alan Cox, November 2001
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 1883d22..e67cf15 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -23,6 +23,7 @@
 	tristate "Fusion MPT ScsiHost drivers for FC"
 	depends on PCI && SCSI
 	select FUSION
+	select SCSI_FC_ATTRS
 	---help---
 	  SCSI HOST support for a Fiber Channel host adapters.
 
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index b61e3d1..02cdc84 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.08
+ *    mpi.h Version:  01.05.10
  *
  *  Version History
  *  ---------------
@@ -74,6 +74,8 @@
  *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
  *                      TargetAssistExtended requests.
  *                      Added EEDP IOCStatus codes.
+ *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
+ *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  --------------------------------------------------------------------------
  */
 
@@ -104,7 +106,7 @@
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0A)
+#define MPI_HEADER_VERSION_UNIT             (0x0C)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
@@ -711,6 +713,8 @@
 #define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR   (0x006D)
 #define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
 #define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT        (0x006F)
+#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT     (0x0070)
+#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED        (0x0071)
 
 /****************************************************************************/
 /*  Additional FCP target values (obsolete)                                 */
@@ -745,7 +749,7 @@
 #define MPI_IOCSTATUS_LAN_CANCELED              (0x0087)
 
 /****************************************************************************/
-/*  Serial Attached SCSI values                                                              */
+/*  Serial Attached SCSI values                                             */
 /****************************************************************************/
 
 #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED    (0x0090)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index d833989..b1becec 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.09
+ *    mpi_cnfg.h Version:  01.05.11
  *
  *  Version History
  *  ---------------
@@ -249,6 +249,23 @@
  *                      Added OwnerDevHandle and Flags field to SAS PHY Page 0.
  *                      Added IOC GPIO Flags define to SAS Enclosure Page 0.
  *                      Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
+ *  08-03-05  01.05.10  Removed ISDataScrubRate and ISResyncRate from
+ *                      Manufacturing Page 4.
+ *                      Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ *                      Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ *                      Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ *                      define.
+ *                      Added EnclosureHandle field to SAS Expander page 0.
+ *                      Removed redundant NumTableEntriesProg field from SAS
+ *                      Expander Page 1.
+ *  08-30-05  01.05.11  Added DeviceID for FC949E and changed the DeviceID for
+ *                      SAS1078.
+ *                      Added more defines for Manufacturing Page 4 Flags field.
+ *                      Added more defines for IOCSettings and added
+ *                      ExpanderSpinup field to Bios Page 1.
+ *                      Added postpone SATA Init bit to SAS IO Unit Page 1
+ *                      ControlFlags.
+ *                      Changed LogEntry format for Log Page 0.
  *  --------------------------------------------------------------------------
  */
 
@@ -494,7 +511,7 @@
 #define MPI_MANUFACTPAGE_DEVICEID_FC929X            (0x0626)
 #define MPI_MANUFACTPAGE_DEVICEID_FC939X            (0x0642)
 #define MPI_MANUFACTPAGE_DEVICEID_FC949X            (0x0640)
-#define MPI_MANUFACTPAGE_DEVICEID_FC949ES           (0x0646)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949E            (0x0646)
 /* SCSI */
 #define MPI_MANUFACTPAGE_DEVID_53C1030              (0x0030)
 #define MPI_MANUFACTPAGE_DEVID_53C1030ZC            (0x0031)
@@ -510,7 +527,7 @@
 #define MPI_MANUFACTPAGE_DEVID_SAS1066E             (0x005A)
 #define MPI_MANUFACTPAGE_DEVID_SAS1068              (0x0054)
 #define MPI_MANUFACTPAGE_DEVID_SAS1068E             (0x0058)
-#define MPI_MANUFACTPAGE_DEVID_SAS1078              (0x0060)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078              (0x0062)
 
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -602,9 +619,7 @@
     U32                             IMVolumeSettings;   /* 50h */
     U32                             Reserved3;          /* 54h */
     U32                             Reserved4;          /* 58h */
-    U8                              ISDataScrubRate;    /* 5Ch */
-    U8                              ISResyncRate;       /* 5Dh */
-    U16                             Reserved5;          /* 5Eh */
+    U32                             Reserved5;          /* 5Ch */
     U8                              IMEDataScrubRate;   /* 60h */
     U8                              IMEResyncRate;      /* 61h */
     U16                             Reserved6;          /* 62h */
@@ -616,9 +631,14 @@
 } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
 
-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x02)
+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x03)
 
 /* defines for the Flags field */
+#define MPI_MANPAGE4_IME_DISABLE                        (0x20)
+#define MPI_MANPAGE4_IM_DISABLE                         (0x10)
+#define MPI_MANPAGE4_IS_DISABLE                         (0x08)
+#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE               (0x04)
+#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE             (0x02)
 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
 
 
@@ -669,7 +689,7 @@
 } CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
   IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
 
-#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x01)
+#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x02)
 
 /* IO Unit Page 1 Flags defines */
 #define MPI_IOUNITPAGE1_MULTI_FUNCTION                  (0x00000000)
@@ -681,7 +701,7 @@
 #define MPI_IOUNITPAGE1_DISABLE_IR                      (0x00000040)
 #define MPI_IOUNITPAGE1_FORCE_32                        (0x00000080)
 #define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE        (0x00000100)
-
+#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE        (0x00000200)
 
 typedef struct _MPI_ADAPTER_INFO
 {
@@ -968,7 +988,8 @@
     U32                     Reserved1;                  /* 0Ch */
     U32                     DeviceSettings;             /* 10h */
     U16                     NumberOfDevices;            /* 14h */
-    U16                     Reserved2;                  /* 16h */
+    U8                      ExpanderSpinup;             /* 16h */
+    U8                      Reserved2;                  /* 17h */
     U16                     IOTimeoutBlockDevicesNonRM; /* 18h */
     U16                     IOTimeoutSequential;        /* 1Ah */
     U16                     IOTimeoutOther;             /* 1Ch */
@@ -976,7 +997,7 @@
 } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
   BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
 
-#define MPI_BIOSPAGE1_PAGEVERSION                       (0x02)
+#define MPI_BIOSPAGE1_PAGEVERSION                       (0x03)
 
 /* values for the BiosOptions field */
 #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE                (0x00000400)
@@ -985,8 +1006,15 @@
 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS              (0x00000001)
 
 /* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY  (0x0F000000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24)
+
 #define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY     (0x00F00000)
 #define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY    (20)
+
+#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE           (0x00080000)
+#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE  (0x00040000)
+
 #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE       (0x00030000)
 #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT        (0x00000000)
 #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT           (0x00010000)
@@ -1016,6 +1044,11 @@
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN          (0x00000001)
 
+/* defines for the ExpanderSpinup field */
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET         (0xF0)
+#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET        (4)
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY              (0x0F)
+
 typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
 {
     U32         Reserved1;                              /* 00h */
@@ -1233,13 +1266,13 @@
 
 #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD     (8)
 #define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap)      \
-    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \
+    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \
     >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD          \
     )
 #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK      (0x00FF0000)
 #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET     (16)
 #define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap)      \
-    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
+    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \
     >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET          \
     )
 #define MPI_SCSIPORTPAGE0_CAP_IDP                       (0x08000000)
@@ -2370,47 +2403,48 @@
 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
   SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
 
-#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x04)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x05)
 
 /* values for SAS IO Unit Page 1 ControlFlags */
-#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST        (0x8000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX            (0x4000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX            (0x2000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE        (0x1000)
-#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH        (0x0800)
+#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST            (0x8000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX                (0x4000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX                (0x2000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE            (0x1000)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH            (0x0800)
 
-#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT        (0x0600)
-#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT       (9)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH        (0x00)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT         (0x01)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT        (0x02)
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT            (0x0600)
+#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT           (9)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH            (0x00)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT             (0x01)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT            (0x02)
 
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED     (0x0040)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED       (0x0020)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED       (0x0010)
-#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH   (0x0008)
-#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL     (0x0004)
-#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY     (0x0002)
-#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION       (0x0001)
+#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT          (0x0100)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED     (0x0080)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED         (0x0040)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED           (0x0020)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED           (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH       (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL         (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY         (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
 
 /* values for SAS IO Unit Page 1 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM     (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM     (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG     (0x01)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG         (0x01)
 
 /* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE           (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT             (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT             (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE               (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT                 (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT                 (0x01)
 
 /* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                   (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                    (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                    (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                   (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                    (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                    (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                       (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                        (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                        (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                       (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                        (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                        (0x09)
 
 /* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
 
@@ -2418,16 +2452,18 @@
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
 {
     CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
-    U32                                 Reserved1;              /* 08h */
+    U8                                  NumDevsPerEnclosure;    /* 08h */
+    U8                                  Reserved1;              /* 09h */
+    U16                                 Reserved2;              /* 0Ah */
     U16                                 MaxPersistentIDs;       /* 0Ch */
     U16                                 NumPersistentIDsUsed;   /* 0Eh */
     U8                                  Status;                 /* 10h */
     U8                                  Flags;                  /* 11h */
-    U16                                 MaxNumPhysicalMappedIDs;/* 12h */              /* 12h */
+    U16                                 MaxNumPhysicalMappedIDs;/* 12h */
 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
   SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
 
-#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x04)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x05)
 
 /* values for SAS IO Unit Page 2 Status field */
 #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2441,6 +2477,7 @@
 #define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP                   (0x00)
 #define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP        (0x01)
 #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP       (0x02)
+#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP        (0x07)
 
 #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT         (0x10)
 #define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT              (0x20)
@@ -2473,7 +2510,7 @@
     CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
     U8                                  PhysicalPort;           /* 08h */
     U8                                  Reserved1;              /* 09h */
-    U16                                 Reserved2;              /* 0Ah */
+    U16                                 EnclosureHandle;        /* 0Ah */
     U64                                 SASAddress;             /* 0Ch */
     U32                                 DiscoveryStatus;        /* 14h */
     U16                                 DevHandle;              /* 18h */
@@ -2487,7 +2524,7 @@
 } CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
   SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
 
-#define MPI_SASEXPANDER0_PAGEVERSION        (0x02)
+#define MPI_SASEXPANDER0_PAGEVERSION        (0x03)
 
 /* values for SAS Expander Page 0 DiscoveryStatus field */
 #define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED              (0x00000001)
@@ -2527,9 +2564,9 @@
     U8                          NegotiatedLinkRate;     /* 1Fh */
     U8                          PhyIdentifier;          /* 20h */
     U8                          AttachedPhyIdentifier;  /* 21h */
-    U8                          NumTableEntriesProg;    /* 22h */
+    U8                          Reserved3;              /* 22h */
     U8                          DiscoveryInfo;          /* 23h */
-    U32                         Reserved3;              /* 24h */
+    U32                         Reserved4;              /* 24h */
 } CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
   SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
 
@@ -2766,16 +2803,15 @@
 #define MPI_LOG_0_NUM_LOG_ENTRIES        (1)
 #endif
 
-#define MPI_LOG_0_LOG_DATA_LENGTH        (20)
+#define MPI_LOG_0_LOG_DATA_LENGTH        (0x1C)
 
 typedef struct _MPI_LOG_0_ENTRY
 {
-    U64         WWID;                               /* 00h */
-    U32         TimeStamp;                          /* 08h */
-    U32         Reserved1;                          /* 0Ch */
-    U16         LogSequence;                        /* 10h */
-    U16         LogEntryQualifier;                  /* 12h */
-    U8          LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+    U32         TimeStamp;                          /* 00h */
+    U32         Reserved1;                          /* 04h */
+    U16         LogSequence;                        /* 08h */
+    U16         LogEntryQualifier;                  /* 0Ah */
+    U8          LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */
 } MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
   MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
 
@@ -2794,7 +2830,7 @@
 } CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
   LogPage0_t, MPI_POINTER pLogPage0_t;
 
-#define MPI_LOG_0_PAGEVERSION               (0x00)
+#define MPI_LOG_0_PAGEVERSION               (0x01)
 
 
 #endif
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 1a30ef1..4a5f8dd 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,25 +6,25 @@
  Copyright (c) 2000-2005 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.10
- Header Set Release Date:       03-11-05
+ Header Set Release Version:    01.05.12
+ Header Set Release Date:       08-30-05
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.08            01.05.07
- mpi_ioc.h              01.05.09            01.05.08
- mpi_cnfg.h             01.05.09            01.05.08
- mpi_init.h             01.05.05            01.05.04
- mpi_targ.h             01.05.05            01.05.04
+ mpi.h                  01.05.10            01.05.09
+ mpi_ioc.h              01.05.10            01.05.09
+ mpi_cnfg.h             01.05.11            01.05.10
+ mpi_init.h             01.05.06            01.05.06
+ mpi_targ.h             01.05.05            01.05.05
  mpi_fc.h               01.05.01            01.05.01
  mpi_lan.h              01.05.01            01.05.01
  mpi_raid.h             01.05.02            01.05.02
  mpi_tool.h             01.05.03            01.05.03
  mpi_inb.h              01.05.01            01.05.01
- mpi_sas.h              01.05.01            01.05.01
- mpi_type.h             01.05.01            01.05.01
- mpi_history.txt        01.05.09            01.05.09
+ mpi_sas.h              01.05.02            01.05.01
+ mpi_type.h             01.05.02            01.05.01
+ mpi_history.txt        01.05.12            01.05.11
 
 
  *  Date      Version   Description
@@ -91,6 +91,8 @@
  *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
  *                      TargetAssistExtended requests.
  *                      Added EEDP IOCStatus codes.
+ *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
+ *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -164,6 +166,10 @@
  *                      Removed IOCFacts Reply EEDP Capability bit.
  *  06-24-05  01.05.09  Added 5 new IOCFacts Reply IOCCapabilities bits.
  *                      Added Max SATA Targets to SAS Discovery Error event.
+ *  08-30-05  01.05.10  Added 4 new events and their event data structures.
+ *                      Added new ReasonCode value for SAS Device Status Change
+ *                      event.
+ *                      Added new family code for FC949E.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -402,6 +408,23 @@
  *                      Added OwnerDevHandle and Flags field to SAS PHY Page 0.
  *                      Added IOC GPIO Flags define to SAS Enclosure Page 0.
  *                      Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
+ *  08-03-05  01.05.10  Removed ISDataScrubRate and ISResyncRate from
+ *                      Manufacturing Page 4.
+ *                      Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ *                      Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ *                      Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ *                      define.
+ *                      Added EnclosureHandle field to SAS Expander page 0.
+ *                      Removed redundant NumTableEntriesProg field from SAS
+ *                      Expander Page 1.
+ *  08-30-05  01.05.11  Added DeviceID for FC949E and changed the DeviceID for
+ *                      SAS1078.
+ *                      Added more defines for Manufacturing Page 4 Flags field.
+ *                      Added more defines for IOCSettings and added
+ *                      ExpanderSpinup field to Bios Page 1.
+ *                      Added postpone SATA Init bit to SAS IO Unit Page 1
+ *                      ControlFlags.
+ *                      Changed LogEntry format for Log Page 0.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -442,6 +465,8 @@
  *                      addressing.
  *  06-24-05  01.05.05  Added SCSI IO 32 structures and defines.
  *                      Added four new defines for SEP SlotStatus.
+ *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ *                      unique in the first 32 characters.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -582,6 +607,9 @@
 
 mpi_sas.h
  *  08-19-04  01.05.01  Original release.
+ *  08-30-05  01.05.02  Added DeviceInfo bit for SEP.
+ *                      Added PrimFlags and Primitive field to SAS IO Unit
+ *                      Control request, and added a new operation code.
  *  --------------------------------------------------------------------------
 
 mpi_type.h
@@ -592,24 +620,25 @@
  *  08-08-01  01.02.01  Original release for v1.2 work.
  *  05-11-04  01.03.01  Original release for MPI v1.3.
  *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  08-30-05  01.05.02  Added PowerPC option to #ifdef's.
  *  --------------------------------------------------------------------------
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.10  01.05.09
-----------  --------  --------
-mpi.h       01.05.08  01.05.07
-mpi_ioc.h   01.05.09  01.05.08
-mpi_cnfg.h  01.05.09  01.05.08
-mpi_init.h  01.05.05  01.05.04
-mpi_targ.h  01.05.05  01.05.04
-mpi_fc.h    01.05.01  01.05.01
-mpi_lan.h   01.05.01  01.05.01
-mpi_raid.h  01.05.02  01.05.02
-mpi_tool.h  01.05.03  01.05.03
-mpi_inb.h   01.05.01  01.05.01
-mpi_sas.h   01.05.01  01.05.01
-mpi_type.h  01.05.01  01.05.01
+Filename    01.05.12  01.05.11  01.05.10  01.05.09
+----------  --------  --------  --------  --------
+mpi.h       01.05.10  01.05.09  01.05.08  01.05.07
+mpi_ioc.h   01.05.10  01.05.09  01.05.09  01.05.08
+mpi_cnfg.h  01.05.11  01.05.10  01.05.09  01.05.08
+mpi_init.h  01.05.06  01.05.06  01.05.05  01.05.04
+mpi_targ.h  01.05.05  01.05.05  01.05.05  01.05.04
+mpi_fc.h    01.05.01  01.05.01  01.05.01  01.05.01
+mpi_lan.h   01.05.01  01.05.01  01.05.01  01.05.01
+mpi_raid.h  01.05.02  01.05.02  01.05.02  01.05.02
+mpi_tool.h  01.05.03  01.05.03  01.05.03  01.05.03
+mpi_inb.h   01.05.01  01.05.01  01.05.01  01.05.01
+mpi_sas.h   01.05.02  01.05.01  01.05.01  01.05.01
+mpi_type.h  01.05.02  01.05.01  01.05.01  01.05.01
 
 Filename    01.05.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
 ----------  --------   --------   --------   --------   --------   --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index d5af75a..68941f4 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -6,7 +6,7 @@
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.05
+ *    mpi_init.h Version:  01.05.06
  *
  *  Version History
  *  ---------------
@@ -50,6 +50,8 @@
  *                      addressing.
  *  06-24-05  01.05.05  Added SCSI IO 32 structures and defines.
  *                      Added four new defines for SEP SlotStatus.
+ *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ *                      unique in the first 32 characters.
  *  --------------------------------------------------------------------------
  */
 
@@ -290,8 +292,8 @@
 
 /* SCSI IO 32 MsgFlags bits */
 #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH                (0x01)
-#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32             (0x00)
-#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64             (0x01)
+#define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH             (0x00)
+#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH             (0x01)
 
 #define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION             (0x02)
 #define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST             (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 93b70e2..2c5f43f 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.09
+ *    mpi_ioc.h Version:  01.05.10
  *
  *  Version History
  *  ---------------
@@ -83,6 +83,10 @@
  *                      Removed IOCFacts Reply EEDP Capability bit.
  *  06-24-05  01.05.09  Added 5 new IOCFacts Reply IOCCapabilities bits.
  *                      Added Max SATA Targets to SAS Discovery Error event.
+ *  08-30-05  01.05.10  Added 4 new events and their event data structures.
+ *                      Added new ReasonCode value for SAS Device Status Change
+ *                      event.
+ *                      Added new family code for FC949E.
  *  --------------------------------------------------------------------------
  */
 
@@ -464,6 +468,10 @@
 #define MPI_EVENT_PERSISTENT_TABLE_FULL     (0x00000011)
 #define MPI_EVENT_SAS_PHY_LINK_STATUS       (0x00000012)
 #define MPI_EVENT_SAS_DISCOVERY_ERROR       (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE          (0x00000014)
+#define MPI_EVENT_IR2                       (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY             (0x00000016)
+#define MPI_EVENT_LOG_ENTRY_ADDED           (0x00000021)
 
 /* AckRequired field values */
 
@@ -480,6 +488,29 @@
 } EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE,
   EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t;
 
+/* LogEntryAdded Event data */
+
+/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */
+#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH    (0x1C)
+typedef struct _EVENT_DATA_LOG_ENTRY
+{
+    U32         TimeStamp;                          /* 00h */
+    U32         Reserved1;                          /* 04h */
+    U16         LogSequence;                        /* 08h */
+    U16         LogEntryQualifier;                  /* 0Ah */
+    U8          LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */
+} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY,
+  MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t;
+
+typedef struct _EVENT_DATA_LOG_ENTRY_ADDED
+{
+    U16                     LogSequence;            /* 00h */
+    U16                     Reserved1;              /* 02h */
+    U32                     Reserved2;              /* 04h */
+    EVENT_DATA_LOG_ENTRY    LogEntry;               /* 08h */
+} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED,
+  MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t;
+
 /* SCSI Event data for Port, Bus and Device forms */
 
 typedef struct _EVENT_DATA_SCSI
@@ -538,6 +569,7 @@
 #define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA            (0x05)
 #define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED      (0x06)
 #define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED           (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
 
 
 /* SCSI Event data for Queue Full event */
@@ -579,6 +611,79 @@
 #define MPI_EVENT_RAID_RC_SMART_DATA                    (0x0A)
 #define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED        (0x0B)
 
+
+/* MPI Integrated RAID Resync Update Event data */
+
+typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE
+{
+    U8                      VolumeID;                   /* 00h */
+    U8                      VolumeBus;                  /* 01h */
+    U8                      ResyncComplete;             /* 02h */
+    U8                      Reserved1;                  /* 03h */
+    U32                     Reserved2;                  /* 04h */
+} MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+  MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+  MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t;
+
+/* MPI IR2 Event data */
+
+/* MPI_LD_STATE or MPI_PD_STATE */
+typedef struct _IR2_STATE_CHANGED
+{
+    U16                 PreviousState;  /* 00h */
+    U16                 NewState;       /* 02h */
+} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED;
+
+typedef struct _IR2_PD_INFO
+{
+    U16                 DeviceHandle;           /* 00h */
+    U8                  TruncEnclosureHandle;   /* 02h */
+    U8                  TruncatedSlot;          /* 03h */
+} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO;
+
+typedef union _MPI_IR2_RC_EVENT_DATA
+{
+    IR2_STATE_CHANGED   StateChanged;
+    U32                 Lba;
+    IR2_PD_INFO         PdInfo;
+} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA;
+
+typedef struct _MPI_EVENT_DATA_IR2
+{
+    U8                      TargetID;             /* 00h */
+    U8                      Bus;                  /* 01h */
+    U8                      ReasonCode;           /* 02h */
+    U8                      PhysDiskNum;          /* 03h */
+    MPI_IR2_RC_EVENT_DATA   IR2EventData;         /* 04h */
+} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2,
+  MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t;
+
+/* MPI IR2 Event data ReasonCode values */
+#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED           (0x01)
+#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED           (0x02)
+#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL       (0x03)
+#define MPI_EVENT_IR2_RC_PD_INSERTED                (0x04)
+#define MPI_EVENT_IR2_RC_PD_REMOVED                 (0x05)
+#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED       (0x06)
+#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR       (0x07)
+
+/* defines for logical disk states */
+#define MPI_LD_STATE_OPTIMAL                        (0x00)
+#define MPI_LD_STATE_DEGRADED                       (0x01)
+#define MPI_LD_STATE_FAILED                         (0x02)
+#define MPI_LD_STATE_MISSING                        (0x03)
+#define MPI_LD_STATE_OFFLINE                        (0x04)
+
+/* defines for physical disk states */
+#define MPI_PD_STATE_ONLINE                         (0x00)
+#define MPI_PD_STATE_MISSING                        (0x01)
+#define MPI_PD_STATE_NOT_COMPATIBLE                 (0x02)
+#define MPI_PD_STATE_FAILED                         (0x03)
+#define MPI_PD_STATE_INITIALIZING                   (0x04)
+#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST        (0x05)
+#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST         (0x06)
+#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON     (0xFF)
+
 /* MPI Link Status Change Event data */
 
 typedef struct _EVENT_DATA_LINK_STATUS
@@ -660,6 +765,20 @@
 #define MPI_EVENT_SAS_PLS_LR_RATE_1_5                       (0x08)
 #define MPI_EVENT_SAS_PLS_LR_RATE_3_0                       (0x09)
 
+/* SAS Discovery Event data */
+
+typedef struct _EVENT_DATA_SAS_DISCOVERY
+{
+    U32                     DiscoveryStatus;            /* 00h */
+    U32                     Reserved1;                  /* 04h */
+} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY,
+  EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t;
+
+#define MPI_EVENT_SAS_DSCVRY_COMPLETE                       (0x00000000)
+#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS                    (0x00000001)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK                  (0xFFFF0000)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT                 (16)
+
 /* SAS Discovery Errror Event data */
 
 typedef struct _EVENT_DATA_DISCOVERY_ERROR
@@ -869,6 +988,7 @@
 #define MPI_FW_HEADER_PID_FAMILY_919XL_FC       (0x0003) /* 919XL and 929XL */
 #define MPI_FW_HEADER_PID_FAMILY_939X_FC        (0x0004) /* 939X and 949X   */
 #define MPI_FW_HEADER_PID_FAMILY_959_FC         (0x0005)
+#define MPI_FW_HEADER_PID_FAMILY_949E_FC        (0x0006)
 /* SAS */
 #define MPI_FW_HEADER_PID_FAMILY_1064_SAS       (0x0001)
 #define MPI_FW_HEADER_PID_FAMILY_1068_SAS       (0x0002)
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
new file mode 100644
index 0000000..dc98d46
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_fc.h
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *
+ *  NAME:           fc_log.h
+ *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
+ *  DESCRIPTION:    Contains the enumerated list of values that may be returned
+ *                  in the IOCLogInfo field of a MPI Default Reply Message.
+ *
+ *  CREATION DATE:  6/02/2000
+ *  ID:             $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
+ */
+
+
+/*
+ * MpiIocLogInfo_t enum
+ *
+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply
+ * messages.
+ * The value is 0xabcccccc where
+ *          a = The type of log info as per the MPI spec. Since these codes are
+ *              all for Fibre Channel this value will always be 2.
+ *          b = Specifies a subclass of the firmware where
+ *                  0 = FCP Initiator
+ *                  1 = FCP Target
+ *                  2 = LAN
+ *                  3 = MPI Message Layer
+ *                  4 = FC Link
+ *                  5 = Context Manager
+ *                  6 = Invalid Field Offset
+ *                  7 = State Change Info
+ *                  all others are reserved for future use
+ *          c = A specific value within the subclass.
+ *
+ * NOTE: Any new values should be added to the end of each subclass so that the
+ *       codes remain consistent across firmware releases.
+ */
+typedef enum _MpiIocLogInfoFc
+{
+    MPI_IOCLOGINFO_FC_INIT_BASE                     = 0x20000000,
+    MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN           = 0x20000004, /* Bad Rx Frame, overrun */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER           = 0x20000005, /* Other errors caught by IOC which require retries */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD       = 0x20000006, /* Main processor could not initialize sub-processor */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN         = 0x20000007, /* Scatter Gather overrun  */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS      = 0x20000008, /* Receiver detected context mismatch via invalid header */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type  */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE       = 0x2000000A, /* Link failure occurred  */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT         = 0x2000000B, /* Transmitter timeout error */
+
+    MPI_IOCLOGINFO_FC_TARGET_BASE                   = 0x21000000,
+    MPI_IOCLOGINFO_FC_TARGET_NO_PDISC               = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
+    MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN               = 0x21000002, /* not sent because we are not logged in to the remote node */
+    MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP     = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP     = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA      = 0x21000005, /* Data In, Auto Response, missing data frames */
+    MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP     = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP     = 0x21000007, /* Auto-response after a write not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP     = 0x21000008, /* Data In, No Response, not completed due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA      = 0x21000009, /* Data In, No Response, missing data frames */
+    MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP     = 0x2100000a, /* Manual Response not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3             = 0x2100000b, /* not sent because remote node does not support Class 3 */
+    MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID        = 0x2100000c, /* not sent because login to remote node not validated */
+    MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND          = 0x2100000e, /* cleared from the outbound queue after a logout */
+    MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN    = 0x2100000f, /* cleared waiting for data after a logout */
+
+    MPI_IOCLOGINFO_FC_LAN_BASE                      = 0x22000000,
+    MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING         = 0x22000001, /* Transaction Context Sgl Missing */
+    MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE         = 0x22000002, /* Transaction Context found before an EOB */
+    MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET        = 0x22000003, /* Transaction Context value has reserved bits set */
+    MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG            = 0x22000004, /* Invalid SGL Flags */
+
+    MPI_IOCLOGINFO_FC_MSG_BASE                      = 0x23000000,
+
+    MPI_IOCLOGINFO_FC_LINK_BASE                     = 0x24000000,
+    MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT        = 0x24000001, /* Loop initialization timed out */
+    MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED      = 0x24000002, /* Another system controller already initialized the loop */
+    MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED     = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
+    MPI_IOCLOGINFO_FC_LINK_CRC_ERROR                = 0x24000004, /* CRC check detected error on received frame */
+
+    MPI_IOCLOGINFO_FC_CTX_BASE                      = 0x25000000,
+
+    MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET     = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
+    MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET      = 0x26ffffff,
+
+    MPI_IOCLOGINFO_FC_STATE_CHANGE                  = 0x27000000  /* The lower 24 bits give additional information concerning state change */
+
+} MpiIocLogInfoFc_t;
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
new file mode 100644
index 0000000..9259d1a
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -0,0 +1,162 @@
+
+/***************************************************************************
+ *                                                                         *
+ *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
+ *                                                                         *
+ *  This file is confidential and a trade secret of LSI Logic.  The        *
+ *  receipt of or possession of this file does not convey any rights to    *
+ *  reproduce or disclose its contents or to manufacture, use, or sell     *
+ *  anything it may describe, in whole, or in part, without the specific   *
+ *  written consent of LSI Logic Corporation.                              *
+ *                                                                         *
+ ***************************************************************************
+ *
+ *           Name:  iopiIocLogInfo.h
+ *          Title:  SAS Firmware IOP Interface IOC Log Info Definitions
+ *     Programmer:  Guy Kendall
+ *  Creation Date:  September 24, 2003
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Last Updated
+ *  -------------
+ *  Version         %version: 22 %
+ *  Date Updated    %date_modified: %
+ *  Programmer      %created_by: nperucca %
+ *
+ *  Date      Who   Description
+ *  --------  ---   -------------------------------------------------------
+ *  09/24/03  GWK   Initial version
+ *
+ *
+ * Description
+ * ------------
+ * This include file contains SAS firmware interface IOC Log Info codes
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef IOPI_IOCLOGINFO_H_INCLUDED
+#define IOPI_IOCLOGINFO_H_INCLUDED
+
+
+/****************************************************************************/
+/*  IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF                            */
+/*  Format:                                                                 */
+/*      Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3)                             */
+/*      Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR               */
+/*      Bits 23-16: LOGINFO_CODE                                            */
+/*      Bits 15-0:  LOGINFO_CODE Specific                                   */
+/****************************************************************************/
+
+/****************************************************************************/
+/* IOC_LOGINFO_ORIGINATOR defines                                           */
+/****************************************************************************/
+#define IOC_LOGINFO_ORIGINATOR_IOP                      (0x00000000)
+#define IOC_LOGINFO_ORIGINATOR_PL                       (0x01000000)
+#define IOC_LOGINFO_ORIGINATOR_IR                       (0x02000000)
+
+/****************************************************************************/
+/* LOGINFO_CODE defines                                                     */
+/****************************************************************************/
+#define IOC_LOGINFO_CODE_MASK                           (0x00FF0000)
+#define IOC_LOGINFO_CODE_SHIFT                          (16)
+
+/****************************************************************************/
+/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP          */
+/****************************************************************************/
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS            (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2                        (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE            (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT         (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN         (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM       (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT         (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM        (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST    (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT    (0x00030700) /* Default Page not found */
+#define IOP_LOGINFO_CODE_TASK_TERMINATED                (0x00050000)
+
+
+/****************************************************************************/
+/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL            */
+/****************************************************************************/
+#define PL_LOGINFO_CODE_OPEN_FAILURE                        (0x00010000)
+#define PL_LOGINFO_CODE_INVALID_SGL                         (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH       (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR                    (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW                 (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET         (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR      (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR     (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS     (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE               (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR          (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR           (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN                      (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS           (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS        (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP         (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV          (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM            (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY             (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER        (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT            (0x00100000)
+#define PL_LOGINFO_CODE_RESET                               (0x00110000)
+#define PL_LOGINFO_CODE_ABORT                               (0x00120000)
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                 (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED                         (0x00140000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                    (0x00000100)
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL                     (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH   (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                (0x00000400)
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW             (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET     (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR  (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE           (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR      (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR       (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                  (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS       (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT        (0x00001000)
+
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE         (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR            (0x00200001) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR           (0x00200002) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL     (0x00200004) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED   (0x00200005) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM              (0x00200006) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT         (0x00200007) /* SGPIO not present/enabled */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT                       (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR               (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE          (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE          (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM             (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1         (0x00200105) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2         (0x00200106) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP           (0x00200107) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA   (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
+
+
+/****************************************************************************/
+/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR            */
+/****************************************************************************/
+#define IR_LOGINFO_CODE_UNUSED1                         (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2                         (0x00020000)
+
+/****************************************************************************/
+/* Defines for convienence                                                  */
+/****************************************************************************/
+#define IOC_LOGINFO_PREFIX_IOP                          ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
+#define IOC_LOGINFO_PREFIX_PL                           ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
+#define IOC_LOGINFO_PREFIX_IR                           ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)
+
+#endif /* end of file */
+
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 230fa69..7051486 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  August 19, 2004
  *
- *    mpi_sas.h Version:  01.05.01
+ *    mpi_sas.h Version:  01.05.02
  *
  *  Version History
  *  ---------------
@@ -14,6 +14,9 @@
  *  Date      Version   Description
  *  --------  --------  ------------------------------------------------------
  *  08-19-04  01.05.01  Original release.
+ *  08-30-05  01.05.02  Added DeviceInfo bit for SEP.
+ *                      Added PrimFlags and Primitive field to SAS IO Unit
+ *                      Control request, and added a new operation code.
  *  --------------------------------------------------------------------------
  */
 
@@ -51,6 +54,7 @@
  * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
  * data and SAS IO Unit Configuration pages.
  */
+#define MPI_SAS_DEVICE_INFO_SEP                 (0x00004000)
 #define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE        (0x00002000)
 #define MPI_SAS_DEVICE_INFO_LSI_DEVICE          (0x00001000)
 #define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH       (0x00000800)
@@ -212,20 +216,26 @@
     U8                      TargetID;           /* 0Ch */
     U8                      Bus;                /* 0Dh */
     U8                      PhyNum;             /* 0Eh */
-    U8                      Reserved4;          /* 0Fh */
-    U32                     Reserved5;          /* 10h */
+    U8                      PrimFlags;          /* 0Fh */
+    U32                     Primitive;          /* 10h */
     U64                     SASAddress;         /* 14h */
-    U32                     Reserved6;          /* 1Ch */
+    U32                     Reserved4;          /* 1Ch */
 } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
   SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
 
 /* values for the Operation field */
-#define MPI_SAS_OP_CLEAR_NOT_PRESENT             (0x01)
-#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT          (0x02)
-#define MPI_SAS_OP_PHY_LINK_RESET                (0x06)
-#define MPI_SAS_OP_PHY_HARD_RESET                (0x07)
-#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG           (0x08)
-#define MPI_SAS_OP_MAP_CURRENT                   (0x09)
+#define MPI_SAS_OP_CLEAR_NOT_PRESENT            (0x01)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT         (0x02)
+#define MPI_SAS_OP_PHY_LINK_RESET               (0x06)
+#define MPI_SAS_OP_PHY_HARD_RESET               (0x07)
+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG          (0x08)
+#define MPI_SAS_OP_MAP_CURRENT                  (0x09)
+#define MPI_SAS_OP_SEND_PRIMITIVE               (0x0A)
+
+/* values for the PrimFlags field */
+#define MPI_SAS_PRIMFLAGS_SINGLE                (0x08)
+#define MPI_SAS_PRIMFLAGS_TRIPLE                (0x02)
+#define MPI_SAS_PRIMFLAGS_REDUNDANT             (0x01)
 
 
 /* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 5378360..d890b2b 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -148,7 +148,6 @@
 static int	WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int	WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int	GetLanConfigPages(MPT_ADAPTER *ioc);
-static int	GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 static int	GetIoUnitPage2(MPT_ADAPTER *ioc);
 int		mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 static int	mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
@@ -1232,12 +1231,11 @@
 		dprintk((KERN_INFO MYNAM
 			": Not using 64 bit consistent mask\n"));
 
-	ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+	ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
 	if (ioc == NULL) {
 		printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
 		return -ENOMEM;
 	}
-	memset(ioc, 0, sizeof(MPT_ADAPTER));
 	ioc->alloc_total = sizeof(MPT_ADAPTER);
 	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */
 	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@@ -1245,6 +1243,8 @@
 	ioc->pcidev = pdev;
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
+	spin_lock_init(&ioc->fc_rescan_work_lock);
+	spin_lock_init(&ioc->fc_rport_lock);
 	spin_lock_init(&ioc->initializing_hba_lock);
 
 	/* Initialize the event logging.
@@ -1268,6 +1268,10 @@
 	 */
 	INIT_LIST_HEAD(&ioc->configQ);
 
+	/* Initialize the fc rport list head.
+	 */
+	INIT_LIST_HEAD(&ioc->fc_rports);
+
 	/* Find lookup slot. */
 	INIT_LIST_HEAD(&ioc->list);
 	ioc->id = mpt_ids++;
@@ -1374,6 +1378,10 @@
 		ioc->bus_type = FC;
 		ioc->errata_flag_1064 = 1;
 	}
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+		ioc->prod_name = "LSIFC949E";
+		ioc->bus_type = FC;
+	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
 		ioc->prod_name = "LSI53C1030";
 		ioc->bus_type = SPI;
@@ -1622,7 +1630,7 @@
 	pci_enable_device(pdev);
 
 	/* enable interrupts */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+	CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
 	ioc->active = 1;
 
 	/* F/W not running */
@@ -1715,7 +1723,7 @@
 				/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
 				dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
 						ioc->alt_ioc->name));
-				CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+				CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
 				ioc->alt_ioc->active = 1;
 			}
 
@@ -1831,7 +1839,7 @@
 
 	if (ret == 0) {
 		/* Enable! (reply interrupt) */
-		CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+		CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
 		ioc->active = 1;
 	}
 
@@ -1839,7 +1847,7 @@
 		/* (re)Enable alt-IOC! (reply interrupt) */
 		dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
 				ioc->alt_ioc->name));
-		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
 		ioc->alt_ioc->active = 1;
 	}
 
@@ -1880,7 +1888,7 @@
 			 *  (FCPortPage0_t stuff)
 			 */
 			for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-				(void) GetFcPortPage0(ioc, ii);
+				(void) mptbase_GetFcPortPage0(ioc, ii);
 			}
 
 			if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -4199,7 +4207,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	GetFcPortPage0 - Fetch FCPort config Page0.
+ *	mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@portnum: IOC Port number
  *
@@ -4209,8 +4217,8 @@
  *		-EAGAIN if no msg frames currently available
  *		-EFAULT for non-successful reply or no reply (timeout)
  */
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
 {
 	ConfigPageHeader_t	 hdr;
 	CONFIGPARMS		 cfg;
@@ -4220,6 +4228,8 @@
 	int			 data_sz;
 	int			 copy_sz;
 	int			 rc;
+	int			 count = 400;
+
 
 	/* Get FCPort Page 0 header */
 	hdr.PageVersion = 0;
@@ -4243,6 +4253,8 @@
 	rc = -ENOMEM;
 	ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
 	if (ppage0_alloc) {
+
+ try_again:
 		memset((u8 *)ppage0_alloc, 0, data_sz);
 		cfg.physAddr = page0_dma;
 		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4274,6 +4286,19 @@
 			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
 			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
 
+			/*
+			 * if still doing discovery,
+			 * hang loose a while until finished
+			 */
+			if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+				if (count-- > 0) {
+					msleep_interruptible(100);
+					goto try_again;
+				}
+				printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+							" complete.\n",
+						ioc->name);
+			}
 		}
 
 		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -6358,6 +6383,7 @@
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
 EXPORT_SYMBOL(mpt_alt_ioc_wait);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6c48d1f..47053ac 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.03.05"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.05"
+#define MPT_LINUX_VERSION_COMMON	"3.03.06"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.06"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -413,7 +413,7 @@
 	u8			 status;	/* current command status */
 	u8			 reset;		/* 1 if bus reset allowed */
 	u8			 target;	/* target for reset */
-	struct semaphore	 sem_ioc;
+	struct mutex		 ioctl_mutex;
 } MPT_IOCTL;
 
 #define MPT_SAS_MGMT_STATUS_RF_VALID	0x02	/* The Reply Frame is VALID */
@@ -421,7 +421,7 @@
 #define MPT_SAS_MGMT_STATUS_TM_FAILED	0x40	/* User TM request failed */
 
 typedef struct _MPT_SAS_MGMT {
-	struct semaphore	 mutex;
+	struct mutex		 mutex;
 	struct completion	 done;
 	u8			 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
 	u8			 status;	/* current command status */
@@ -499,6 +499,22 @@
 	int		 isRaid;		/* bit field, 1 if RAID */
 }RaidCfgData;
 
+#define MPT_RPORT_INFO_FLAGS_REGISTERED	0x01	/* rport registered */
+#define MPT_RPORT_INFO_FLAGS_MISSING	0x02	/* missing from DevPage0 scan */
+#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04	/* target mapped in vdev */
+
+/*
+ * data allocated for each fc rport device
+ */
+struct mptfc_rport_info
+{
+	struct list_head list;
+	struct fc_rport *rport;
+	VirtDevice	*vdev;
+	FCDevicePage0_t pg0;
+	u8		flags;
+};
+
 /*
  *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
  */
@@ -612,7 +628,16 @@
 	struct list_head	 list;
 	struct net_device	*netdev;
 	struct list_head	 sas_topology;
+	struct mutex		 sas_topology_mutex;
 	MPT_SAS_MGMT		 sas_mgmt;
+	int			 num_ports;
+
+	struct list_head	 fc_rports;
+	spinlock_t		 fc_rport_lock; /* list and ri flags */
+	spinlock_t		 fc_rescan_work_lock;
+	int			 fc_rescan_work_count;
+	struct work_struct	 fc_rescan_work;
+
 } MPT_ADAPTER;
 
 /*
@@ -999,6 +1024,7 @@
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int	 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 extern int	 mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
 
 /*
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 7c34024..bdf7099 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -177,10 +177,10 @@
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
 
 	if (nonblock) {
-		if (down_trylock(&ioc->ioctl->sem_ioc))
+		if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
 			rc = -EAGAIN;
 	} else {
-		if (down_interruptible(&ioc->ioctl->sem_ioc))
+		if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
 			rc = -ERESTARTSYS;
 	}
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -557,7 +557,7 @@
 	else
 		ret = -EINVAL;
 
-	up(&iocp->ioctl->sem_ioc);
+	mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
 	return ret;
 }
@@ -2619,7 +2619,7 @@
 
 	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-	up(&iocp->ioctl->sem_ioc);
+	mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
 	return ret;
 }
@@ -2673,7 +2673,7 @@
 	 */
 	ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-	up(&iocp->ioctl->sem_ioc);
+	mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
 	return ret;
 }
@@ -2743,7 +2743,7 @@
 	memset(mem, 0, sz);
 	ioc->ioctl = (MPT_IOCTL *) mem;
 	ioc->ioctl->ioc = ioc;
-	sema_init(&ioc->ioctl->sem_ioc, 1);
+	mutex_init(&ioc->ioctl->ioctl_mutex);
 	return 0;
 
 out_fail:
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ba61e18..b102c76 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -55,12 +55,14 @@
 #include <linux/reboot.h>	/* notifier code */
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/sort.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -79,19 +81,34 @@
 module_param(mpt_pq_filter, int, 0);
 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
 
+#define MPTFC_DEV_LOSS_TMO (60)
+static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;	/* reasonable default */
+module_param(mptfc_dev_loss_tmo, int, 0);
+MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
+    				     " transport to wait for an rport to "
+				     " return following a device loss event."
+				     "  Default=60.");
+
 static int	mptfcDoneCtx = -1;
 static int	mptfcTaskCtx = -1;
 static int	mptfcInternalCtx = -1; /* Used only for internal commands */
 
+int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
+    void (*done)(struct scsi_cmnd *));
+
+static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
+static void __devexit mptfc_remove(struct pci_dev *pdev);
+
 static struct scsi_host_template mptfc_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptfc",
 	.proc_info			= mptscsih_proc_info,
 	.name				= "MPT FC Host",
 	.info				= mptscsih_info,
-	.queuecommand			= mptscsih_qcmd,
+	.queuecommand			= mptfc_qcmd,
 	.target_alloc			= mptscsih_target_alloc,
-	.slave_alloc			= mptscsih_slave_alloc,
+	.slave_alloc			= mptfc_slave_alloc,
 	.slave_configure		= mptscsih_slave_configure,
 	.target_destroy			= mptscsih_target_destroy,
 	.slave_destroy			= mptscsih_slave_destroy,
@@ -128,19 +145,478 @@
 		PCI_ANY_ID, PCI_ANY_ID },
 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
 		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+		PCI_ANY_ID, PCI_ANY_ID },
 	{0}	/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	mptfc_probe - Installs scsi devices per bus.
- *	@pdev: Pointer to pci_dev structure
- *
- *	Returns 0 for success, non-zero for failure.
- *
+static struct scsi_transport_template *mptfc_transport_template = NULL;
+
+struct fc_function_template mptfc_transport_functions = {
+	.dd_fcrport_size = 8,
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_port_id = 1,
+	.show_rport_supported_classes = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+	.show_starget_port_id = 1,
+	.set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+
+};
+
+/* FIXME! values controlling firmware RESCAN event
+ * need to be set low to allow dev_loss_tmo to
+ * work as expected.  Currently, firmware doesn't
+ * notify driver of RESCAN event until some number
+ * of seconds elapse.  This value can be set via
+ * lsiutil.
  */
+static void
+mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+	if (timeout > 0)
+		rport->dev_loss_tmo = timeout;
+	else
+		rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+}
+
+static int
+mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
+{
+	FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
+	FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
+
+	if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
+		if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
+			return 0;
+		if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
+			return -1;
+		return 1;
+	}
+	if ((*aa)->CurrentBus < (*bb)->CurrentBus)
+		return -1;
+	return 1;
+}
+
+static int
+mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
+	void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	FCDevicePage0_t		*ppage0_alloc, *fc;
+	dma_addr_t		 page0_dma;
+	int			 data_sz;
+	int			 ii;
+
+	FCDevicePage0_t		*p0_array=NULL, *p_p0;
+	FCDevicePage0_t		**pp0_array=NULL, **p_pp0;
+
+	int			 rc = -ENOMEM;
+	U32			 port_id = 0xffffff;
+	int			 num_targ = 0;
+	int			 max_bus = ioc->facts.MaxBuses;
+	int			 max_targ = ioc->facts.MaxDevices;
+
+	if (max_bus == 0 || max_targ == 0)
+		goto out;
+
+	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
+	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
+	if (!p0_array)
+		goto out;
+
+	data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
+	p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
+	if (!pp0_array)
+		goto out;
+
+	do {
+		/* Get FC Device Page 0 header */
+		hdr.PageVersion = 0;
+		hdr.PageLength = 0;
+		hdr.PageNumber = 0;
+		hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
+		cfg.cfghdr.hdr = &hdr;
+		cfg.physAddr = -1;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+		cfg.dir = 0;
+		cfg.pageAddr = port_id;
+		cfg.timeout = 0;
+
+		if ((rc = mpt_config(ioc, &cfg)) != 0)
+			break;
+
+		if (hdr.PageLength <= 0)
+			break;
+
+		data_sz = hdr.PageLength * 4;
+		ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
+		    					&page0_dma);
+		rc = -ENOMEM;
+		if (!ppage0_alloc)
+			break;
+
+		cfg.physAddr = page0_dma;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+		if ((rc = mpt_config(ioc, &cfg)) == 0) {
+			ppage0_alloc->PortIdentifier =
+				le32_to_cpu(ppage0_alloc->PortIdentifier);
+
+			ppage0_alloc->WWNN.Low =
+				le32_to_cpu(ppage0_alloc->WWNN.Low);
+
+			ppage0_alloc->WWNN.High =
+				le32_to_cpu(ppage0_alloc->WWNN.High);
+
+			ppage0_alloc->WWPN.Low =
+				le32_to_cpu(ppage0_alloc->WWPN.Low);
+
+			ppage0_alloc->WWPN.High =
+				le32_to_cpu(ppage0_alloc->WWPN.High);
+
+			ppage0_alloc->BBCredit =
+				le16_to_cpu(ppage0_alloc->BBCredit);
+
+			ppage0_alloc->MaxRxFrameSize =
+				le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
+
+			port_id = ppage0_alloc->PortIdentifier;
+			num_targ++;
+			*p_p0 = *ppage0_alloc;	/* save data */
+			*p_pp0++ = p_p0++;	/* save addr */
+		}
+		pci_free_consistent(ioc->pcidev, data_sz,
+		    			(u8 *) ppage0_alloc, page0_dma);
+		if (rc != 0)
+			break;
+
+	} while (port_id <= 0xff0000);
+
+	if (num_targ) {
+		/* sort array */
+		if (num_targ > 1)
+			sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
+				mptfc_FcDevPage0_cmp_func, NULL);
+		/* call caller's func for each targ */
+		for (ii = 0; ii < num_targ;  ii++) {
+			fc = *(pp0_array+ii);
+			func(ioc, ioc_port, fc);
+		}
+	}
+
+ out:
+	if (pp0_array)
+		kfree(pp0_array);
+	if (p0_array)
+		kfree(p0_array);
+	return rc;
+}
+
+static int
+mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
+{
+	/* not currently usable */
+	if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
+			  MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
+		return -1;
+
+	if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
+		return -1;
+
+	if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
+		return -1;
+
+	/*
+	 * board data structure already normalized to platform endianness
+	 * shifted to avoid unaligned access on 64 bit architecture
+	 */
+	rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
+	rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
+	rid->port_id =   pg0->PortIdentifier;
+	rid->roles = FC_RPORT_ROLE_UNKNOWN;
+	rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
+	if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+		rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+	return 0;
+}
+
+static void
+mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
+{
+	struct fc_rport_identifiers rport_ids;
+	struct fc_rport		*rport;
+	struct mptfc_rport_info	*ri;
+	int			match = 0;
+	u64			port_name;
+	unsigned long		flags;
+
+	if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
+		return;
+
+	/* scan list looking for a match */
+	spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+	list_for_each_entry(ri, &ioc->fc_rports, list) {
+		port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+		if (port_name == rport_ids.port_name) {	/* match */
+			list_move_tail(&ri->list, &ioc->fc_rports);
+			match = 1;
+			break;
+		}
+	}
+	if (!match) {	/* allocate one */
+		spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+		ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
+		if (!ri)
+			return;
+		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+		list_add_tail(&ri->list, &ioc->fc_rports);
+	}
+
+	ri->pg0 = *pg0;	/* add/update pg0 data */
+	ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
+
+	if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
+		ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
+		spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+		rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+		if (rport) {
+			if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
+				ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+				ri->vdev = NULL;
+				ri->rport = rport;
+				*((struct mptfc_rport_info **)rport->dd_data) = ri;
+			}
+			rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+			/*
+			 * if already mapped, remap here.  If not mapped,
+			 * slave_alloc will allocate vdev and map
+			 */
+			if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
+				ri->vdev->target_id = ri->pg0.CurrentTargetID;
+				ri->vdev->bus_id = ri->pg0.CurrentBus;
+				ri->vdev->vtarget->target_id = ri->vdev->target_id;
+				ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+			}
+			#ifdef MPT_DEBUG
+			printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+				"rport tid %d, tmo %d\n",
+					ioc->sh->host_no,
+					pg0->PortIdentifier,
+					pg0->WWNN,
+					pg0->WWPN,
+					pg0->CurrentTargetID,
+					ri->rport->scsi_target_id,
+					ri->rport->dev_loss_tmo);
+			#endif
+		} else {
+			list_del(&ri->list);
+			kfree(ri);
+			ri = NULL;
+		}
+	}
+	spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+}
+
+/*
+ *	OS entry point to allow host driver to alloc memory
+ *	for each scsi device. Called once per device the bus scan.
+ *	Return non-zero if allocation fails.
+ *	Init memory once per LUN.
+ */
+int
+mptfc_slave_alloc(struct scsi_device *sdev)
+{
+	MPT_SCSI_HOST		*hd;
+	VirtTarget		*vtarget;
+	VirtDevice		*vdev;
+	struct scsi_target	*starget;
+	struct fc_rport		*rport;
+	struct mptfc_rport_info *ri;
+	unsigned long		flags;
+
+
+	rport = starget_to_rport(scsi_target(sdev));
+
+	if (!rport || fc_remote_port_chkready(rport))
+		return -ENXIO;
+
+	hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+
+	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+	if (!vdev) {
+		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+				hd->ioc->name, sizeof(VirtDevice));
+		return -ENOMEM;
+	}
+	memset(vdev, 0, sizeof(VirtDevice));
+
+	spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
+
+	if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
+		spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+		kfree(vdev);
+		return -ENODEV;
+	}
+
+	sdev->hostdata = vdev;
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	if (vtarget->num_luns == 0) {
+		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
+		    		  MPT_TARGET_FLAGS_VALID_INQUIRY;
+		hd->Targets[sdev->id] = vtarget;
+	}
+
+	vtarget->target_id = vdev->target_id;
+	vtarget->bus_id = vdev->bus_id;
+
+	vdev->vtarget = vtarget;
+	vdev->ioc_id = hd->ioc->id;
+	vdev->lun = sdev->lun;
+	vdev->target_id = ri->pg0.CurrentTargetID;
+	vdev->bus_id = ri->pg0.CurrentBus;
+
+	ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+	ri->vdev = vdev;
+
+	spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+
+	vtarget->num_luns++;
+
+#ifdef MPT_DEBUG
+	printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+	        "CurrentTargetID %d, %x %llx %llx\n",
+			sdev->host->host_no,
+			vtarget->num_luns,
+			sdev->id, ri->pg0.CurrentTargetID,
+			ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
+#endif
+
+	return 0;
+}
+
+static int
+mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
+	int		err;
+
+	err = fc_remote_port_chkready(rport);
+	if (unlikely(err)) {
+		SCpnt->result = err;
+		done(SCpnt);
+		return 0;
+	}
+	return mptscsih_qcmd(SCpnt,done);
+}
+
+static void
+mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
+{
+	unsigned class = 0, cos = 0;
+
+	/* don't know what to do as only one scsi (fc) host was allocated */
+	if (portnum != 0)
+		return;
+
+	class = ioc->fc_port_page0[portnum].SupportedServiceClass;
+	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
+		cos |= FC_COS_CLASS1;
+	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
+		cos |= FC_COS_CLASS2;
+	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
+		cos |= FC_COS_CLASS3;
+
+	fc_host_node_name(ioc->sh) =
+	    	(u64)ioc->fc_port_page0[portnum].WWNN.High << 32
+		    | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
+
+	fc_host_port_name(ioc->sh) =
+	    	(u64)ioc->fc_port_page0[portnum].WWPN.High << 32
+		    | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
+
+	fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
+
+	fc_host_supported_classes(ioc->sh) = cos;
+
+	fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
+}
+
+static void
+mptfc_rescan_devices(void *arg)
+{
+	MPT_ADAPTER		*ioc = (MPT_ADAPTER *)arg;
+	int			ii;
+	int			work_to_do;
+	unsigned long		flags;
+	struct mptfc_rport_info *ri;
+
+	do {
+		/* start by tagging all ports as missing */
+		spin_lock_irqsave(&ioc->fc_rport_lock,flags);
+		list_for_each_entry(ri, &ioc->fc_rports, list) {
+			if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+				ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+			}
+		}
+		spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+		/*
+		 * now rescan devices known to adapter,
+		 * will reregister existing rports
+		 */
+		for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+			(void) mptbase_GetFcPortPage0(ioc, ii);
+			mptfc_init_host_attr(ioc,ii);	/* refresh */
+			mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+		}
+
+		/* delete devices still missing */
+		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+		list_for_each_entry(ri, &ioc->fc_rports, list) {
+			/* if newly missing, delete it */
+			if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
+					  MPT_RPORT_INFO_FLAGS_MISSING))
+			  == (MPT_RPORT_INFO_FLAGS_REGISTERED |
+			      MPT_RPORT_INFO_FLAGS_MISSING)) {
+
+				ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+					       MPT_RPORT_INFO_FLAGS_MISSING);
+				fc_remote_port_delete(ri->rport);
+				/*
+				 * remote port not really deleted 'cause
+				 * binding is by WWPN and driver only
+				 * registers FCP_TARGETs
+				 */
+				#ifdef MPT_DEBUG
+				printk ("mptfc_rescan.%d: %llx deleted\n",
+					ioc->sh->host_no, ri->pg0.WWPN);
+				#endif
+			}
+		}
+		spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+		/*
+		 * allow multiple passes as target state
+		 * might have changed during scan
+		 */
+		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+		if (ioc->fc_rescan_work_count > 2) 	/* only need one more */
+			ioc->fc_rescan_work_count = 2;
+		work_to_do = --ioc->fc_rescan_work_count;
+		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+	} while (work_to_do);
+}
+
 static int
 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -148,17 +624,16 @@
 	MPT_SCSI_HOST		*hd;
 	MPT_ADAPTER 		*ioc;
 	unsigned long		 flags;
-	int			 sz, ii;
+	int			 ii;
 	int			 numSGE = 0;
 	int			 scale;
 	int			 ioc_cap;
-	u8			*mem;
 	int			error=0;
 	int			r;
-		
+
 	if ((r = mpt_attach(pdev,id)) != 0)
 		return r;
-	
+
 	ioc = pci_get_drvdata(pdev);
 	ioc->DoneCtx = mptfcDoneCtx;
 	ioc->TaskCtx = mptfcTaskCtx;
@@ -194,7 +669,7 @@
 		printk(MYIOC_s_WARN_FMT
 			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
 			ioc->name, ioc);
-		return 0;
+		return -ENODEV;
 	}
 
 	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -207,6 +682,8 @@
 		goto out_mptfc_probe;
         }
 
+	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
+
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 
 	/* Attach the SCSI Host to the IOC structure
@@ -268,36 +745,27 @@
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 */
-	sz = ioc->req_depth * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
+	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+	if (!hd->ScsiLookup) {
 		error = -ENOMEM;
 		goto out_mptfc_probe;
 	}
 
-	memset(mem, 0, sz);
-	hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-		 ioc->name, hd->ScsiLookup, sz));
+	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+		 ioc->name, hd->ScsiLookup));
 
 	/* Allocate memory for the device structures.
 	 * A non-Null pointer at an offset
 	 * indicates a device exists.
 	 * max_id = 1 + maximum id (hosts.h)
 	 */
-	sz = sh->max_id * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
+	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+	if (!hd->Targets) {
 		error = -ENOMEM;
 		goto out_mptfc_probe;
 	}
 
-	memset(mem, 0, sz);
-	hd->Targets = (VirtTarget **) mem;
-
-	dprintk((KERN_INFO
-	  "  vdev @ %p, sz=%d\n", hd->Targets, sz));
+	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
 
 	/* Clear the TM flags
 	 */
@@ -332,6 +800,7 @@
 	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
 
+	sh->transportt = mptfc_transport_template;
 	error = scsi_add_host (sh, &ioc->pcidev->dev);
 	if(error) {
 		dprintk((KERN_ERR MYNAM
@@ -339,7 +808,11 @@
 		goto out_mptfc_probe;
 	}
 
-	scsi_scan_host(sh);
+	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+		mptfc_init_host_attr(ioc,ii);
+		mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+	}
+
 	return 0;
 
 out_mptfc_probe:
@@ -352,7 +825,7 @@
 	.name		= "mptfc",
 	.id_table	= mptfc_pci_table,
 	.probe		= mptfc_probe,
-	.remove		= __devexit_p(mptscsih_remove),
+	.remove		= __devexit_p(mptfc_remove),
 	.shutdown	= mptscsih_shutdown,
 #ifdef CONFIG_PM
 	.suspend	= mptscsih_suspend,
@@ -370,9 +843,20 @@
 static int __init
 mptfc_init(void)
 {
+	int error;
 
 	show_mptmod_ver(my_NAME, my_VERSION);
 
+	/* sanity check module parameter */
+	if (mptfc_dev_loss_tmo == 0)
+		mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
+
+	mptfc_transport_template =
+		fc_attach_transport(&mptfc_transport_functions);
+
+	if (!mptfc_transport_template)
+		return -ENODEV;
+
 	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
 	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
@@ -387,7 +871,33 @@
 		  ": Registered for IOC reset notifications\n"));
 	}
 
-	return pci_register_driver(&mptfc_driver);
+	error = pci_register_driver(&mptfc_driver);
+	if (error) {
+		fc_release_transport(mptfc_transport_template);
+	}
+
+	return error;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptfc_remove - Removed fc infrastructure for devices
+ *	@pdev: Pointer to pci_dev structure
+ *
+ */
+static void __devexit mptfc_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+	struct mptfc_rport_info *p, *n;
+
+	fc_remove_host(ioc->sh);
+
+	list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
+		list_del(&p->list);
+		kfree(p);
+	}
+
+	mptscsih_remove(pdev);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -400,7 +910,8 @@
 mptfc_exit(void)
 {
 	pci_unregister_driver(&mptfc_driver);
-	
+	fc_release_transport(mptfc_transport_template);
+
 	mpt_reset_deregister(mptfcDoneCtx);
 	dprintk((KERN_INFO MYNAM
 	  ": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 014085d..0b1b728 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -411,14 +411,12 @@
 		goto out;
 	priv->mpt_txfidx_tail = -1;
 
-	priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),
+	priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),
 				GFP_KERNEL);
 	if (priv->SendCtl == NULL)
 		goto out_mpt_txfidx;
-	for (i = 0; i < priv->tx_max_out; i++) {
-		memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
+	for (i = 0; i < priv->tx_max_out; i++)
 		priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
-	}
 
 	dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
 
@@ -428,15 +426,13 @@
 		goto out_SendCtl;
 	priv->mpt_rxfidx_tail = -1;
 
-	priv->RcvCtl = kmalloc(priv->max_buckets_out *
-						sizeof(struct BufferControl),
+	priv->RcvCtl = kcalloc(priv->max_buckets_out,
+			       sizeof(struct BufferControl),
 			       GFP_KERNEL);
 	if (priv->RcvCtl == NULL)
 		goto out_mpt_rxfidx;
-	for (i = 0; i < priv->max_buckets_out; i++) {
-		memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
+	for (i = 0; i < priv->max_buckets_out; i++)
 		priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
-	}
 
 /**/	dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
 /**/	for (i = 0; i < priv->tx_max_out; i++)
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 17e9757e..5a06d8d 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5,7 +5,7 @@
  *
  *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
- *  Copyright (c) 2005 Dell
+ *  Copyright (c) 2005-2006 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -86,6 +86,24 @@
 static int	mptsasMgmtCtx = -1;
 
 
+enum mptsas_hotplug_action {
+	MPTSAS_ADD_DEVICE,
+	MPTSAS_DEL_DEVICE,
+};
+
+struct mptsas_hotplug_event {
+	struct work_struct	work;
+	MPT_ADAPTER		*ioc;
+	enum mptsas_hotplug_action event_type;
+	u64			sas_address;
+	u32			channel;
+	u32			id;
+	u32			device_info;
+	u16			handle;
+	u16			parent_handle;
+	u8			phy_id;
+};
+
 /*
  * SAS topology structures
  *
@@ -99,8 +117,8 @@
 	u8	phy_id;		/* phy number of parent device */
 	u8	port_id;	/* sas physical port this device
 				   is assoc'd with */
-	u8	target;		/* logical target id of this device */
-	u8	bus;		/* logical bus number of this device */
+	u8	id;		/* logical target id of this device */
+	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 */
@@ -114,6 +132,7 @@
 	u8	programmed_link_rate;	/* programmed max/min phy link rate */
 	struct mptsas_devinfo identify;	/* point to phy device info */
 	struct mptsas_devinfo attached;	/* point to attached device info */
+	struct sas_phy *phy;
 	struct sas_rphy *rphy;
 };
 
@@ -239,13 +258,12 @@
 	struct scsi_target 	*starget;
 	int i;
 
-	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
 	if (!vdev) {
 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
 				hd->ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 	}
-	memset(vdev, 0, sizeof(VirtDevice));
 	vdev->ioc_id = hd->ioc->id;
 	sdev->hostdata = vdev;
 	starget = scsi_target(sdev);
@@ -256,19 +274,32 @@
 		hd->Targets[sdev->id] = vtarget;
 	}
 
+	/*
+	  RAID volumes placed beyond the last expected port.
+	*/
+	if (sdev->channel == hd->ioc->num_ports) {
+		vdev->target_id = sdev->id;
+		vdev->bus_id = 0;
+		vdev->lun = 0;
+		goto out;
+	}
+
 	rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+	mutex_lock(&hd->ioc->sas_topology_mutex);
 	list_for_each_entry(p, &hd->ioc->sas_topology, list) {
 		for (i = 0; i < p->num_phys; i++) {
 			if (p->phy_info[i].attached.sas_address ==
 					rphy->identify.sas_address) {
 				vdev->target_id =
-					p->phy_info[i].attached.target;
-				vdev->bus_id = p->phy_info[i].attached.bus;
+					p->phy_info[i].attached.id;
+				vdev->bus_id = p->phy_info[i].attached.channel;
 				vdev->lun = sdev->lun;
+ 	mutex_unlock(&hd->ioc->sas_topology_mutex);
 				goto out;
 			}
 		}
 	}
+	mutex_unlock(&hd->ioc->sas_topology_mutex);
 
 	printk("No matching SAS device found!!\n");
 	kfree(vdev);
@@ -282,6 +313,42 @@
 	return 0;
 }
 
+static void
+mptsas_slave_destroy(struct scsi_device *sdev)
+{
+	struct Scsi_Host *host = sdev->host;
+	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+	struct sas_rphy *rphy;
+	struct mptsas_portinfo *p;
+	int i;
+
+	/*
+	 * Handle hotplug removal case.
+	 * We need to clear out attached data structure.
+	 */
+	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) {
+		for (i = 0; i < p->num_phys; i++) {
+			if (p->phy_info[i].attached.sas_address ==
+					rphy->identify.sas_address) {
+				memset(&p->phy_info[i].attached, 0,
+				    sizeof(struct mptsas_devinfo));
+				p->phy_info[i].rphy = NULL;
+				goto out;
+			}
+		}
+	}
+
+ out:
+	mutex_unlock(&hd->ioc->sas_topology_mutex);
+	/*
+	 * TODO: Issue target reset to flush firmware outstanding commands.
+	 */
+	mptscsih_slave_destroy(sdev);
+}
+
 static struct scsi_host_template mptsas_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptsas",
@@ -293,7 +360,7 @@
 	.slave_alloc			= mptsas_slave_alloc,
 	.slave_configure		= mptscsih_slave_configure,
 	.target_destroy			= mptscsih_target_destroy,
-	.slave_destroy			= mptscsih_slave_destroy,
+	.slave_destroy			= mptsas_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
 	.eh_device_reset_handler	= mptscsih_dev_reset,
@@ -399,7 +466,7 @@
 	if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
 		return -ENXIO;
 
-	if (down_interruptible(&ioc->sas_mgmt.mutex))
+	if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
 		goto out;
 
 	mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
@@ -450,7 +517,7 @@
 	error = 0;
 
  out_unlock:
-	up(&ioc->sas_mgmt.mutex);
+	mutex_unlock(&ioc->sas_mgmt.mutex);
  out:
 	return error;
 }
@@ -649,8 +716,8 @@
 	device_info->handle = le16_to_cpu(buffer->DevHandle);
 	device_info->phy_id = buffer->PhyNum;
 	device_info->port_id = buffer->PhysicalPort;
-	device_info->target = buffer->TargetID;
-	device_info->bus = buffer->Bus;
+	device_info->id = buffer->TargetID;
+	device_info->channel = buffer->Bus;
 	memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
 	device_info->sas_address = le64_to_cpu(sas_address);
 	device_info->device_info =
@@ -858,36 +925,36 @@
 static int mptsas_probe_one_phy(struct device *dev,
 		struct mptsas_phyinfo *phy_info, int index, int local)
 {
-	struct sas_phy *port;
+	struct sas_phy *phy;
 	int error;
 
-	port = sas_phy_alloc(dev, index);
-	if (!port)
+	phy = sas_phy_alloc(dev, index);
+	if (!phy)
 		return -ENOMEM;
 
-	port->port_identifier = phy_info->port_id;
-	mptsas_parse_device_info(&port->identify, &phy_info->identify);
+	phy->port_identifier = phy_info->port_id;
+	mptsas_parse_device_info(&phy->identify, &phy_info->identify);
 
 	/*
 	 * Set Negotiated link rate.
 	 */
 	switch (phy_info->negotiated_link_rate) {
 	case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
-		port->negotiated_linkrate = SAS_PHY_DISABLED;
+		phy->negotiated_linkrate = SAS_PHY_DISABLED;
 		break;
 	case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
-		port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+		phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
 		break;
 	case MPI_SAS_IOUNIT0_RATE_1_5:
-		port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+		phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
 		break;
 	case MPI_SAS_IOUNIT0_RATE_3_0:
-		port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
+		phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
 		break;
 	case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
 	case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
 	default:
-		port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+		phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
 		break;
 	}
 
@@ -896,10 +963,10 @@
 	 */
 	switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
 	case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
-		port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+		phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
 		break;
 	case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
-		port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+		phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
 		break;
 	default:
 		break;
@@ -911,10 +978,10 @@
 	switch (phy_info->programmed_link_rate &
 			MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
 	case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
-		port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+		phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
 		break;
 	case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
-		port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+		phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
 		break;
 	default:
 		break;
@@ -925,10 +992,10 @@
 	 */
 	switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
 	case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
-		port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+		phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
 		break;
 	case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
-		port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+		phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
 		break;
 	default:
 		break;
@@ -940,28 +1007,29 @@
 	switch (phy_info->programmed_link_rate &
 			MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
 	case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
-		port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+		phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
 		break;
 	case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
-		port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+		phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
 		break;
 	default:
 		break;
 	}
 
 	if (local)
-		port->local_attached = 1;
+		phy->local_attached = 1;
 
-	error = sas_phy_add(port);
+	error = sas_phy_add(phy);
 	if (error) {
-		sas_phy_free(port);
+		sas_phy_free(phy);
 		return error;
 	}
+	phy_info->phy = phy;
 
 	if (phy_info->attached.handle) {
 		struct sas_rphy *rphy;
 
-		rphy = sas_rphy_alloc(port);
+		rphy = sas_rphy_alloc(phy);
 		if (!rphy)
 			return 0; /* non-fatal: an rphy can be added later */
 
@@ -985,16 +1053,19 @@
 	u32 handle = 0xFFFF;
 	int error = -ENOMEM, i;
 
-	port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+	port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
 	if (!port_info)
 		goto out;
-	memset(port_info, 0, sizeof(*port_info));
 
 	error = mptsas_sas_io_unit_pg0(ioc, port_info);
 	if (error)
 		goto out_free_port_info;
 
+	ioc->num_ports = port_info->num_phys;
+	mutex_lock(&ioc->sas_topology_mutex);
 	list_add_tail(&port_info->list, &ioc->sas_topology);
+	mutex_unlock(&ioc->sas_topology_mutex);
+
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
 			(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
@@ -1034,10 +1105,9 @@
 	struct mptsas_portinfo *port_info, *p;
 	int error = -ENOMEM, i, j;
 
-	port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+	port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
 	if (!port_info)
 		goto out;
-	memset(port_info, 0, sizeof(*port_info));
 
 	error = mptsas_sas_expander_pg0(ioc, port_info,
 		(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
@@ -1047,7 +1117,10 @@
 
 	*handle = port_info->handle;
 
+	mutex_lock(&ioc->sas_topology_mutex);
 	list_add_tail(&port_info->list, &ioc->sas_topology);
+	mutex_unlock(&ioc->sas_topology_mutex);
+
 	for (i = 0; i < port_info->num_phys; i++) {
 		struct device *parent;
 
@@ -1079,6 +1152,7 @@
 		 * HBA phys.
 		 */
 		parent = &ioc->sh->shost_gendev;
+		mutex_lock(&ioc->sas_topology_mutex);
 		list_for_each_entry(p, &ioc->sas_topology, list) {
 			for (j = 0; j < p->num_phys; j++) {
 				if (port_info->phy_info[i].identify.handle ==
@@ -1086,6 +1160,7 @@
 					parent = &p->phy_info[j].rphy->dev;
 			}
 		}
+		mutex_unlock(&ioc->sas_topology_mutex);
 
 		mptsas_probe_one_phy(parent, &port_info->phy_info[i],
 				     *index, 0);
@@ -1111,6 +1186,211 @@
 		;
 }
 
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+{
+	struct mptsas_portinfo *port_info;
+	struct mptsas_devinfo device_info;
+	struct mptsas_phyinfo *phy_info = NULL;
+	int i, error;
+
+	/*
+	 * Retrieve the parent sas_address
+	 */
+	error = mptsas_sas_device_pg0(ioc, &device_info,
+		(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+		 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+		parent_handle);
+	if (error) {
+		printk("mptsas: failed to retrieve device page\n");
+		return NULL;
+	}
+
+	/*
+	 * The phy_info structures are never deallocated during lifetime of
+	 * a host, so the code below is safe without additional refcounting.
+	 */
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_for_each_entry(port_info, &ioc->sas_topology, list) {
+		for (i = 0; i < port_info->num_phys; i++) {
+			if (port_info->phy_info[i].identify.sas_address ==
+			    device_info.sas_address &&
+			    port_info->phy_info[i].phy_id == phy_id) {
+				phy_info = &port_info->phy_info[i];
+				break;
+			}
+		}
+	}
+	mutex_unlock(&ioc->sas_topology_mutex);
+
+	return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+	struct mptsas_portinfo *port_info;
+	struct mptsas_phyinfo *phy_info = NULL;
+	int i;
+
+	/*
+	 * The phy_info structures are never deallocated during lifetime of
+	 * a host, so the code below is safe without additional refcounting.
+	 */
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_for_each_entry(port_info, &ioc->sas_topology, list) {
+		for (i = 0; i < port_info->num_phys; i++) {
+			if (port_info->phy_info[i].attached.handle == handle) {
+				phy_info = &port_info->phy_info[i];
+				break;
+			}
+		}
+	}
+	mutex_unlock(&ioc->sas_topology_mutex);
+
+	return phy_info;
+}
+
+static void
+mptsas_hotplug_work(void *arg)
+{
+	struct mptsas_hotplug_event *ev = arg;
+	MPT_ADAPTER *ioc = ev->ioc;
+	struct mptsas_phyinfo *phy_info;
+	struct sas_rphy *rphy;
+	char *ds = NULL;
+
+	if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		ds = "ssp";
+	if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+		ds = "stp";
+	if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		ds = "sata";
+
+	switch (ev->event_type) {
+	case MPTSAS_DEL_DEVICE:
+		printk(MYIOC_s_INFO_FMT
+		       "removing %s device, channel %d, id %d, phy %d\n",
+		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+		phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+		if (!phy_info) {
+			printk("mptsas: remove event for non-existant PHY.\n");
+			break;
+		}
+
+		if (phy_info->rphy) {
+			sas_rphy_delete(phy_info->rphy);
+			phy_info->rphy = NULL;
+		}
+		break;
+	case MPTSAS_ADD_DEVICE:
+		printk(MYIOC_s_INFO_FMT
+		       "attaching %s device, channel %d, id %d, phy %d\n",
+		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+		phy_info = mptsas_find_phyinfo_by_parent(ioc,
+				ev->parent_handle, ev->phy_id);
+		if (!phy_info) {
+			printk("mptsas: add event for non-existant PHY.\n");
+			break;
+		}
+
+		if (phy_info->rphy) {
+			printk("mptsas: trying to add existing device.\n");
+			break;
+		}
+
+		/* fill attached info */
+		phy_info->attached.handle = ev->handle;
+		phy_info->attached.phy_id = ev->phy_id;
+		phy_info->attached.port_id = phy_info->identify.port_id;
+		phy_info->attached.id = ev->id;
+		phy_info->attached.channel = ev->channel;
+		phy_info->attached.sas_address = ev->sas_address;
+		phy_info->attached.device_info = ev->device_info;
+
+		rphy = sas_rphy_alloc(phy_info->phy);
+		if (!rphy)
+			break; /* non-fatal: an rphy can be added later */
+
+		mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+		if (sas_rphy_add(rphy)) {
+			sas_rphy_free(rphy);
+			break;
+		}
+
+		phy_info->rphy = rphy;
+		break;
+	}
+
+	kfree(ev);
+}
+
+static void
+mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+		EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+{
+	struct mptsas_hotplug_event *ev;
+	u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+	__le64 sas_address;
+
+	if ((device_info &
+	     (MPI_SAS_DEVICE_INFO_SSP_TARGET |
+	      MPI_SAS_DEVICE_INFO_STP_TARGET |
+	      MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
+		return;
+
+	if ((sas_event_data->ReasonCode &
+	     (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
+	      MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
+		return;
+
+	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev) {
+		printk(KERN_WARNING "mptsas: lost hotplug event\n");
+		return;
+	}
+
+
+	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+	ev->ioc = ioc;
+	ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+	ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+	ev->channel = sas_event_data->Bus;
+	ev->id = sas_event_data->TargetID;
+	ev->phy_id = sas_event_data->PhyNum;
+	memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
+	ev->sas_address = le64_to_cpu(sas_address);
+	ev->device_info = device_info;
+
+	if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
+		ev->event_type = MPTSAS_ADD_DEVICE;
+	else
+		ev->event_type = MPTSAS_DEL_DEVICE;
+
+	schedule_work(&ev->work);
+}
+
+static int
+mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+{
+	u8 event = le32_to_cpu(reply->Event) & 0xFF;
+
+	if (!ioc->sh)
+		return 1;
+
+	switch (event) {
+	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+		mptscsih_send_sas_event(ioc,
+			(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+		return 1;		/* currently means nothing really */
+
+	default:
+		return mptscsih_event_process(ioc, reply);
+	}
+}
+
 static int
 mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -1118,11 +1398,10 @@
 	MPT_SCSI_HOST		*hd;
 	MPT_ADAPTER 		*ioc;
 	unsigned long		 flags;
-	int			 sz, ii;
+	int			 ii;
 	int			 numSGE = 0;
 	int			 scale;
 	int			 ioc_cap;
-	u8			*mem;
 	int			error=0;
 	int			r;
 
@@ -1203,7 +1482,9 @@
 	sh->unique_id = ioc->id;
 
 	INIT_LIST_HEAD(&ioc->sas_topology);
-	init_MUTEX(&ioc->sas_mgmt.mutex);
+	mutex_init(&ioc->sas_topology_mutex);
+
+	mutex_init(&ioc->sas_mgmt.mutex);
 	init_completion(&ioc->sas_mgmt.done);
 
 	/* Verify that we won't exceed the maximum
@@ -1244,36 +1525,27 @@
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 */
-	sz = ioc->req_depth * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
+	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+	if (!hd->ScsiLookup) {
 		error = -ENOMEM;
 		goto out_mptsas_probe;
 	}
 
-	memset(mem, 0, sz);
-	hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-		 ioc->name, hd->ScsiLookup, sz));
+	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+		 ioc->name, hd->ScsiLookup));
 
 	/* Allocate memory for the device structures.
 	 * A non-Null pointer at an offset
 	 * indicates a device exists.
 	 * max_id = 1 + maximum id (hosts.h)
 	 */
-	sz = sh->max_id * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
+	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+	if (!hd->Targets) {
 		error = -ENOMEM;
 		goto out_mptsas_probe;
 	}
 
-	memset(mem, 0, sz);
-	hd->Targets = (VirtTarget **) mem;
-
-	dprintk((KERN_INFO
-	  "  vtarget @ %p, sz=%d\n", hd->Targets, sz));
+	dprintk((KERN_INFO "  vtarget @ %p\n", hd->Targets));
 
 	/* Clear the TM flags
 	 */
@@ -1324,6 +1596,20 @@
 
 	mptsas_scan_sas_topology(ioc);
 
+	/*
+	  Reporting RAID volumes.
+	*/
+	if (!ioc->raid_data.pIocPg2)
+		return 0;
+	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+		return 0;
+	for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
+		scsi_add_device(sh,
+			ioc->num_ports,
+			ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
+			0);
+	}
+
 	return 0;
 
 out_mptsas_probe:
@@ -1339,10 +1625,12 @@
 
 	sas_remove_host(ioc->sh);
 
+	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
 		list_del(&p->list);
 		kfree(p);
 	}
+	mutex_unlock(&ioc->sas_topology_mutex);
 
 	mptscsih_remove(pdev);
 }
@@ -1393,7 +1681,7 @@
 		mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
 	mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
 
-	if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+	if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
 		devtprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 93a16fa..cdac557 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -893,6 +893,7 @@
  *		when a lun is disable by mid-layer.
  *		Do NOT access the referenced scsi_cmnd structure or
  *		members. Will cause either a paging or NULL ptr error.
+ *		(BUT, BUT, BUT, the code does reference it! - mdr)
  *      @hd: Pointer to a SCSI HOST structure
  *	@vdevice: per device private data
  *
@@ -2162,10 +2163,9 @@
 {
 	VirtTarget		*vtarget;
 
-	vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL);
+	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
 	if (!vtarget)
 		return -ENOMEM;
-	memset(vtarget, 0, sizeof(VirtTarget));
 	starget->hostdata = vtarget;
 	return 0;
 }
@@ -2185,14 +2185,13 @@
 	VirtDevice		*vdev;
 	struct scsi_target 	*starget;
 
-	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
 	if (!vdev) {
 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
 				hd->ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 	}
 
-	memset(vdev, 0, sizeof(VirtDevice));
 	vdev->ioc_id = hd->ioc->id;
 	vdev->target_id = sdev->id;
 	vdev->bus_id = sdev->channel;
@@ -2559,13 +2558,25 @@
 			hd->cmdPtr = NULL;
 		}
 
-		/* 7. Set flag to force DV and re-read IOC Page 3
+		/* 7. SPI: Set flag to force DV and re-read IOC Page 3
 		 */
 		if (ioc->bus_type == SPI) {
 			ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
 			ddvtprintk(("Set reload IOC Pg3 Flag\n"));
 		}
 
+		/* 7. FC: Rescan for blocked rports which might have returned.
+		 */
+		else if (ioc->bus_type == FC) {
+			int work_count;
+			unsigned long flags;
+
+			spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+			work_count = ++ioc->fc_rescan_work_count;
+			spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+			if (work_count == 1)
+				schedule_work(&ioc->fc_rescan_work);
+		}
 		dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
 	}
@@ -2589,6 +2600,8 @@
 {
 	MPT_SCSI_HOST *hd;
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+	int work_count;
+	unsigned long flags;
 
 	devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
 			ioc->name, event));
@@ -2610,11 +2623,18 @@
 		/* FIXME! */
 		break;
 
+	case MPI_EVENT_RESCAN:				/* 06 */
+		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+		work_count = ++ioc->fc_rescan_work_count;
+		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+		if (work_count == 1)
+			schedule_work(&ioc->fc_rescan_work);
+		break;
+
 		/*
 		 *  CHECKME! Don't think we need to do
 		 *  anything for these, but...
 		 */
-	case MPI_EVENT_RESCAN:				/* 06 */
 	case MPI_EVENT_LINK_STATUS_CHANGE:		/* 07 */
 	case MPI_EVENT_LOOP_STATE_CHANGE:		/* 08 */
 		/*
@@ -3954,8 +3974,6 @@
 
 /* Search IOC page 3 to determine if this is hidden physical disk
  */
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
 static int
 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
 {
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index ce332a6..7dce292 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -158,11 +158,10 @@
 	MPT_SCSI_HOST		*hd;
 	MPT_ADAPTER 		*ioc;
 	unsigned long		 flags;
-	int			 sz, ii;
+	int			 ii;
 	int			 numSGE = 0;
 	int			 scale;
 	int			 ioc_cap;
-	u8			*mem;
 	int			error=0;
 	int			r;
 
@@ -288,36 +287,27 @@
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 */
-	sz = ioc->req_depth * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
+	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+	if (!hd->ScsiLookup) {
 		error = -ENOMEM;
 		goto out_mptspi_probe;
 	}
 
-	memset(mem, 0, sz);
-	hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-		 ioc->name, hd->ScsiLookup, sz));
+	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+		 ioc->name, hd->ScsiLookup));
 
 	/* Allocate memory for the device structures.
 	 * A non-Null pointer at an offset
 	 * indicates a device exists.
 	 * max_id = 1 + maximum id (hosts.h)
 	 */
-	sz = sh->max_id * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
+	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+	if (!hd->Targets) {
 		error = -ENOMEM;
 		goto out_mptspi_probe;
 	}
 
-	memset(mem, 0, sz);
-	hd->Targets = (VirtTarget **) mem;
-
-	dprintk((KERN_INFO
-	  "  vdev @ %p, sz=%d\n", hd->Targets, sz));
+	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
 
 	/* Clear the TM flags
 	 */
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index c5b656c..d698d77 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -88,11 +88,6 @@
 	struct device *dev = &pdev->dev;
 	int i;
 
-	if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
-		printk(KERN_ERR "%s: device already claimed\n", c->name);
-		return -ENODEV;
-	}
-
 	for (i = 0; i < 6; i++) {
 		/* Skip I/O spaces */
 		if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -319,6 +314,11 @@
 		return rc;
 	}
 
+	if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+		printk(KERN_ERR "i2o: device already claimed\n");
+		return -ENODEV;
+	}
+
 	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
 		       pci_name(pdev));
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 5e84c5a..167fef3 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1125,6 +1125,8 @@
 	zfcp_free_low_mem_buffers(adapter);
 	/* free memory of adapter data structure and queues */
 	zfcp_qdio_free_queues(adapter);
+	kfree(adapter->fc_stats);
+	kfree(adapter->stats_reset_data);
 	ZFCP_LOG_TRACE("freeing adapter structure\n");
 	kfree(adapter);
  out:
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d81b737..9bb5110 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -921,7 +921,6 @@
 	u32			physical_s_id;     /* local FC port ID */
 	struct ccw_device       *ccw_device;	   /* S/390 ccw device */
 	u8			fc_service_class;
-	u32			fc_topology;	   /* FC topology */
 	u32			hydra_version;	   /* Hydra version */
 	u32			fsf_lic_version;
 	u32			adapter_features;  /* FCP channel features */
@@ -978,6 +977,9 @@
 	struct zfcp_adapter_mempool	pool;      /* Adapter memory pools */
 	struct qdio_initialize  qdio_init_data;    /* for qdio_establish */
 	struct device           generic_services;  /* directory for WKA ports */
+	struct fc_host_statistics *fc_stats;
+	struct fsf_qtcb_bottom_port *stats_reset_data;
+	unsigned long		stats_reset;
 };
 
 /*
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index ee7314d..7bdb00b 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -2613,7 +2613,7 @@
 	case ZFCP_ERP_STEP_UNINITIALIZED:
 	case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
 	case ZFCP_ERP_STEP_PORT_CLOSING:
-		if (adapter->fc_topology == FSF_TOPO_P2P) {
+		if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
 			if (port->wwpn != adapter->peer_wwpn) {
 				ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
 						"on adapter %s.\nPeer WWPN "
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 5958795..cbfab09 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -964,6 +964,40 @@
 					| ZFCP_STATUS_COMMON_ERP_FAILED);
 		break;
 
+	case FSF_STATUS_READ_NOTIFICATION_LOST:
+		ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "
+				"adapter %s%s%s%s%s%s%s%s%s\n",
+				zfcp_get_busid_by_adapter(adapter),
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_INCOMING_ELS) ?
+					", incoming ELS" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_SENSE_DATA) ?
+					", sense data" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_LINK_STATUS) ?
+					", link status change" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_PORT_CLOSED) ?
+					", port close" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?
+					", bit error exception" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_ACT_UPDATED) ?
+					", ACT update" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_ACT_HARDENED) ?
+					", ACT hardening" : "",
+				(status_buffer->status_subtype &
+					FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?
+					", adapter feature change" : "");
+
+		if (status_buffer->status_subtype &
+		    FSF_STATUS_READ_SUB_ACT_UPDATED)
+			zfcp_erp_adapter_access_changed(adapter);
+		break;
+
 	case FSF_STATUS_READ_CFDC_UPDATED:
 		ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
 			      zfcp_get_busid_by_adapter(adapter));
@@ -1954,6 +1988,7 @@
 	erp_action->fsf_req->qtcb->bottom.config.feature_selection =
 			FSF_FEATURE_CFDC |
 			FSF_FEATURE_LUN_SHARING |
+			FSF_FEATURE_NOTIFICATION_LOST |
 			FSF_FEATURE_UPDATE_ALERT;
 
 	/* start QDIO request for this FSF request */
@@ -2008,27 +2043,30 @@
 		fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
 		fc_host_speed(shost) = bottom->fc_link_speed;
 		fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
-		adapter->fc_topology = bottom->fc_topology;
 		adapter->hydra_version = bottom->adapter_type;
-		if (adapter->physical_wwpn == 0)
-			adapter->physical_wwpn = fc_host_port_name(shost);
-		if (adapter->physical_s_id == 0)
-			adapter->physical_s_id = fc_host_port_id(shost);
+		if (fc_host_permanent_port_name(shost) == -1)
+			fc_host_permanent_port_name(shost) =
+				fc_host_port_name(shost);
+		if (bottom->fc_topology == FSF_TOPO_P2P) {
+			adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
+			adapter->peer_wwpn = bottom->plogi_payload.wwpn;
+			adapter->peer_wwnn = bottom->plogi_payload.wwnn;
+			fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+		} else if (bottom->fc_topology == FSF_TOPO_FABRIC)
+			fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+		else if (bottom->fc_topology == FSF_TOPO_AL)
+			fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+		else
+			fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
 	} else {
 		fc_host_node_name(shost) = 0;
 		fc_host_port_name(shost) = 0;
 		fc_host_port_id(shost) = 0;
 		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
-		adapter->fc_topology = 0;
+		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
 		adapter->hydra_version = 0;
 	}
 
-	if (adapter->fc_topology == FSF_TOPO_P2P) {
-		adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
-		adapter->peer_wwpn = bottom->plogi_payload.wwpn;
-		adapter->peer_wwnn = bottom->plogi_payload.wwnn;
-	}
-
 	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
 		adapter->hardware_version = bottom->hardware_version;
 		memcpy(fc_host_serial_number(shost), bottom->serial_number,
@@ -2097,8 +2135,8 @@
 		if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
 			return -EIO;
 
-		switch (adapter->fc_topology) {
-		case FSF_TOPO_P2P:
+		switch (fc_host_port_type(adapter->scsi_host)) {
+		case FC_PORTTYPE_PTP:
 			ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
 					"configuration detected at adapter %s\n"
 					"Peer WWNN 0x%016llx, "
@@ -2111,7 +2149,7 @@
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "top-p-to-p");
 			break;
-		case FSF_TOPO_AL:
+		case FC_PORTTYPE_NLPORT:
 			ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
 					"topology detected at adapter %s "
 					"unsupported, shutting down adapter\n",
@@ -2120,7 +2158,7 @@
 					 "top-al");
 			zfcp_erp_adapter_shutdown(adapter, 0);
 			return -EIO;
-		case FSF_TOPO_FABRIC:
+		case FC_PORTTYPE_NPORT:
 			ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
 				      "network detected at adapter %s.\n",
 				      zfcp_get_busid_by_adapter(adapter));
@@ -2133,7 +2171,6 @@
 					"of a type known to the zfcp "
 					"driver, shutting down adapter\n",
 					zfcp_get_busid_by_adapter(adapter));
-			adapter->fc_topology = FSF_TOPO_ERROR;
 			debug_text_exception(fsf_req->adapter->erp_dbf, 0,
 					     "unknown-topo");
 			zfcp_erp_adapter_shutdown(adapter, 0);
@@ -2293,14 +2330,13 @@
 		data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
 		if (data)
 			memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
-		if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
-			adapter->physical_wwpn = bottom->wwpn;
-			adapter->physical_s_id = bottom->fc_port_id;
-		} else {
-			adapter->physical_wwpn = fc_host_port_name(shost);
-			adapter->physical_s_id = fc_host_port_id(shost);
-		}
+		if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+			fc_host_permanent_port_name(shost) = bottom->wwpn;
+		else
+			fc_host_permanent_port_name(shost) =
+				fc_host_port_name(shost);
 		fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+		fc_host_supported_speeds(shost) = bottom->supported_speed;
 		break;
 
 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 48719f0..e734415 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -166,6 +166,7 @@
 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD	0x00000004
 #define FSF_STATUS_READ_LINK_DOWN		0x00000005
 #define FSF_STATUS_READ_LINK_UP          	0x00000006
+#define FSF_STATUS_READ_NOTIFICATION_LOST	0x00000009
 #define FSF_STATUS_READ_CFDC_UPDATED		0x0000000A
 #define FSF_STATUS_READ_CFDC_HARDENED		0x0000000B
 #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT	0x0000000C
@@ -179,6 +180,16 @@
 #define FSF_STATUS_READ_SUB_FDISC_FAILED	0x00000001
 #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE	0x00000002
 
+/* status subtypes for unsolicited status notification lost */
+#define FSF_STATUS_READ_SUB_INCOMING_ELS	0x00000001
+#define FSF_STATUS_READ_SUB_SENSE_DATA		0x00000002
+#define FSF_STATUS_READ_SUB_LINK_STATUS		0x00000004
+#define FSF_STATUS_READ_SUB_PORT_CLOSED		0x00000008
+#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD	0x00000010
+#define FSF_STATUS_READ_SUB_ACT_UPDATED		0x00000020
+#define FSF_STATUS_READ_SUB_ACT_HARDENED	0x00000040
+#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
+
 /* status subtypes for CFDC */
 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE	0x00000002
 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
@@ -188,7 +199,6 @@
 #define FSF_TOPO_P2P				0x00000001
 #define FSF_TOPO_FABRIC				0x00000002
 #define FSF_TOPO_AL				0x00000003
-#define FSF_TOPO_FABRIC_VIRT			0x00000004
 
 /* data direction for FCP commands */
 #define FSF_DATADIR_WRITE			0x00000001
@@ -211,6 +221,7 @@
 /* channel features */
 #define FSF_FEATURE_CFDC			0x00000002
 #define FSF_FEATURE_LUN_SHARING			0x00000004
+#define FSF_FEATURE_NOTIFICATION_LOST		0x00000008
 #define FSF_FEATURE_HBAAPI_MANAGEMENT           0x00000010
 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS        0x00000020
 #define FSF_FEATURE_UPDATE_ALERT		0x00000100
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 66608d1..3c2cbcc 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,8 +49,6 @@
 
 static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
 					  scsi_lun_t);
-static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int,
-					  scsi_id_t);
 
 static struct device_attribute *zfcp_sysfs_sdev_attrs[];
 
@@ -406,18 +404,6 @@
 	return retval;
 }
 
-static struct zfcp_port *
-zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
-{
-	struct zfcp_port *port;
-
-	list_for_each_entry(port, &adapter->port_list_head, list) {
-		if (port->rport && (id == port->rport->scsi_target_id))
-			return port;
-	}
-	return (struct zfcp_port *) NULL;
-}
-
 /**
  * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
  * @scpnt: pointer to scsi_cmnd to be aborted 
@@ -731,70 +717,164 @@
 /*
  * Support functions for FC transport class
  */
-static void
-zfcp_get_port_id(struct scsi_target *starget)
+static struct fc_host_statistics*
+zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
 {
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
-	struct zfcp_port *port;
-	unsigned long flags;
+	struct fc_host_statistics *fc_stats;
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	port = zfcp_port_lookup(adapter, starget->channel, starget->id);
-	if (port)
-		fc_starget_port_id(starget) = port->d_id;
-	else
-		fc_starget_port_id(starget) = -1;
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	if (!adapter->fc_stats) {
+		fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
+		if (!fc_stats)
+			return NULL;
+		adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
+	}
+	memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
+	return adapter->fc_stats;
 }
 
 static void
-zfcp_get_port_name(struct scsi_target *starget)
+zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
+			  struct fsf_qtcb_bottom_port *data,
+			  struct fsf_qtcb_bottom_port *old)
 {
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
-	struct zfcp_port *port;
-	unsigned long flags;
-
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	port = zfcp_port_lookup(adapter, starget->channel, starget->id);
-	if (port)
-		fc_starget_port_name(starget) = port->wwpn;
-	else
-		fc_starget_port_name(starget) = -1;
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -
+		old->seconds_since_last_reset;
+	fc_stats->tx_frames = data->tx_frames - old->tx_frames;
+	fc_stats->tx_words = data->tx_words - old->tx_words;
+	fc_stats->rx_frames = data->rx_frames - old->rx_frames;
+	fc_stats->rx_words = data->rx_words - old->rx_words;
+	fc_stats->lip_count = data->lip - old->lip;
+	fc_stats->nos_count = data->nos - old->nos;
+	fc_stats->error_frames = data->error_frames - old->error_frames;
+	fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
+	fc_stats->link_failure_count = data->link_failure - old->link_failure;
+	fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
+	fc_stats->loss_of_signal_count = data->loss_of_signal -
+		old->loss_of_signal;
+	fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -
+		old->psp_error_counts;
+	fc_stats->invalid_tx_word_count = data->invalid_tx_words -
+		old->invalid_tx_words;
+	fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
+	fc_stats->fcp_input_requests = data->input_requests -
+		old->input_requests;
+	fc_stats->fcp_output_requests = data->output_requests -
+		old->output_requests;
+	fc_stats->fcp_control_requests = data->control_requests -
+		old->control_requests;
+	fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
+	fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
 }
 
 static void
-zfcp_get_node_name(struct scsi_target *starget)
+zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
+		       struct fsf_qtcb_bottom_port *data)
 {
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
-	struct zfcp_port *port;
-	unsigned long flags;
+	fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
+	fc_stats->tx_frames = data->tx_frames;
+	fc_stats->tx_words = data->tx_words;
+	fc_stats->rx_frames = data->rx_frames;
+	fc_stats->rx_words = data->rx_words;
+	fc_stats->lip_count = data->lip;
+	fc_stats->nos_count = data->nos;
+	fc_stats->error_frames = data->error_frames;
+	fc_stats->dumped_frames = data->dumped_frames;
+	fc_stats->link_failure_count = data->link_failure;
+	fc_stats->loss_of_sync_count = data->loss_of_sync;
+	fc_stats->loss_of_signal_count = data->loss_of_signal;
+	fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
+	fc_stats->invalid_tx_word_count = data->invalid_tx_words;
+	fc_stats->invalid_crc_count = data->invalid_crcs;
+	fc_stats->fcp_input_requests = data->input_requests;
+	fc_stats->fcp_output_requests = data->output_requests;
+	fc_stats->fcp_control_requests = data->control_requests;
+	fc_stats->fcp_input_megabytes = data->input_mb;
+	fc_stats->fcp_output_megabytes = data->output_mb;
+}
 
-	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	port = zfcp_port_lookup(adapter, starget->channel, starget->id);
-	if (port)
-		fc_starget_node_name(starget) = port->wwnn;
-	else
-		fc_starget_node_name(starget) = -1;
-	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+/**
+ * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
+ *
+ * assumption: scsi_transport_fc synchronizes calls of
+ *             get_fc_host_stats and reset_fc_host_stats
+ *             (XXX to be checked otherwise introduce locking)
+ */
+static struct fc_host_statistics *
+zfcp_get_fc_host_stats(struct Scsi_Host *shost)
+{
+	struct zfcp_adapter *adapter;
+	struct fc_host_statistics *fc_stats;
+	struct fsf_qtcb_bottom_port *data;
+	int ret;
+
+	adapter = (struct zfcp_adapter *)shost->hostdata[0];
+	fc_stats = zfcp_init_fc_host_stats(adapter);
+	if (!fc_stats)
+		return NULL;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return NULL;
+	memset(data, 0, sizeof(*data));
+
+	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+	if (ret) {
+		kfree(data);
+		return NULL; /* XXX return zeroed fc_stats? */
+	}
+
+	if (adapter->stats_reset &&
+	    ((jiffies/HZ - adapter->stats_reset) <
+	     data->seconds_since_last_reset)) {
+		zfcp_adjust_fc_host_stats(fc_stats, data,
+					  adapter->stats_reset_data);
+	} else
+		zfcp_set_fc_host_stats(fc_stats, data);
+
+	kfree(data);
+	return fc_stats;
+}
+
+static void
+zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
+{
+	struct zfcp_adapter *adapter;
+	struct fsf_qtcb_bottom_port *data, *old_data;
+	int ret;
+
+	adapter = (struct zfcp_adapter *)shost->hostdata[0];
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return;
+	memset(data, 0, sizeof(*data));
+
+	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+	if (ret == 0) {
+		adapter->stats_reset = jiffies/HZ;
+		old_data = adapter->stats_reset_data;
+		adapter->stats_reset_data = data; /* finally freed in
+						     adater_dequeue */
+		kfree(old_data);
+	}
 }
 
 struct fc_function_template zfcp_transport_functions = {
-	.get_starget_port_id = zfcp_get_port_id,
-	.get_starget_port_name = zfcp_get_port_name,
-	.get_starget_node_name = zfcp_get_node_name,
 	.show_starget_port_id = 1,
 	.show_starget_port_name = 1,
 	.show_starget_node_name = 1,
 	.show_rport_supported_classes = 1,
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
+	.show_host_permanent_port_name = 1,
 	.show_host_supported_classes = 1,
+	.show_host_supported_speeds = 1,
 	.show_host_maxframe_size = 1,
 	.show_host_serial_number = 1,
+	.get_fc_host_stats = zfcp_get_fc_host_stats,
+	.reset_fc_host_stats = zfcp_reset_fc_host_stats,
+	/* no functions registered for following dynamic attributes but
+	   directly set by LLDD */
+	.show_host_port_type = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
 };
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 0cd4352..9f26225 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -33,14 +33,6 @@
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
 
-static const char fc_topologies[5][25] = {
-	"<error>",
-	"point-to-point",
-	"fabric",
-	"arbitrated loop",
-	"fabric (virt. adapter)"
-};
-
 /**
  * ZFCP_DEFINE_ADAPTER_ATTR
  * @_name:   name of show attribute
@@ -69,12 +61,8 @@
 ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
 ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
 ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
-			 fc_topologies[adapter->fc_topology]);
 ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
 			 adapter->hardware_version);
-ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
 ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
 			 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
 
@@ -259,9 +247,6 @@
 	&dev_attr_physical_s_id.attr,
 	&dev_attr_card_version.attr,
 	&dev_attr_lic_version.attr,
-	&dev_attr_fc_service_class.attr,
-	&dev_attr_fc_topology.attr,
-	&dev_attr_scsi_host_no.attr,
 	&dev_attr_status.attr,
 	&dev_attr_hardware_version.attr,
 	NULL
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index c55e82d..3924eb3 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -65,8 +65,6 @@
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
 
 ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
-ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
-ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
 ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
 		      (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
 ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -245,8 +243,6 @@
 	&dev_attr_failed.attr,
 	&dev_attr_in_recovery.attr,
 	&dev_attr_status.attr,
-	&dev_attr_wwnn.attr,
-	&dev_attr_d_id.attr,
 	&dev_attr_access_denied.attr,
 	NULL
 };
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 0556642..2f50815 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -65,7 +65,6 @@
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
 
 ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
-ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
 ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
 		      (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
 ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -138,7 +137,6 @@
 		   zfcp_sysfs_unit_failed_store);
 
 static struct attribute *zfcp_unit_attrs[] = {
-	&dev_attr_scsi_lun.attr,
 	&dev_attr_failed.attr,
 	&dev_attr_in_recovery.attr,
 	&dev_attr_status.attr,
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3ff74f4..31c4975 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -73,6 +73,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -615,7 +616,7 @@
 	void __user *argp = (void __user *)arg;
 
 	/* Only let one of these through at a time */
-	if (down_interruptible(&tw_dev->ioctl_sem)) {
+	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
 		retval = TW_IOCTL_ERROR_OS_EINTR;
 		goto out;
 	}
@@ -852,7 +853,7 @@
 	/* Now free ioctl buf memory */
 	dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
 out2:
-	up(&tw_dev->ioctl_sem);
+	mutex_unlock(&tw_dev->ioctl_lock);
 out:
 	return retval;
 } /* End twa_chrdev_ioctl() */
@@ -1182,7 +1183,7 @@
 	tw_dev->error_sequence_id = 1;
 	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
 
-	init_MUTEX(&tw_dev->ioctl_sem);
+	mutex_init(&tw_dev->ioctl_lock);
 	init_waitqueue_head(&tw_dev->ioctl_wqueue);
 
 	retval = 0;
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 46f22cd..1b16d57 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -672,7 +672,7 @@
 	u32                     ioctl_msec;
 	int			chrdev_request_id;
 	wait_queue_head_t	ioctl_wqueue;
-	struct semaphore	ioctl_sem;
+	struct mutex		ioctl_lock;
 	char			aen_clobber;
 	unsigned short		working_srl;
 	unsigned short		working_branch;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 283f6d2..25f678d 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -203,6 +203,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -888,7 +889,7 @@
 	dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
 
 	/* Only let one of these through at a time */
-	if (down_interruptible(&tw_dev->ioctl_sem))
+	if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
 		return -EINTR;
 
 	/* First copy down the buffer length */
@@ -1029,7 +1030,7 @@
 	/* Now free ioctl buf memory */
 	dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
 out:
-	up(&tw_dev->ioctl_sem);
+	mutex_unlock(&tw_dev->ioctl_lock);
 	return retval;
 } /* End tw_chrdev_ioctl() */
 
@@ -1270,7 +1271,7 @@
 	tw_dev->pending_tail = TW_Q_START;
 	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
 
-	init_MUTEX(&tw_dev->ioctl_sem);
+	mutex_init(&tw_dev->ioctl_lock);
 	init_waitqueue_head(&tw_dev->ioctl_wqueue);
 
 	return 0;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 4f81fc3..31fe5ea 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -420,7 +420,7 @@
 	u32			max_sector_count;
 	u32			aen_count;
 	struct Scsi_Host	*host;
-	struct semaphore	ioctl_sem;
+	struct mutex		ioctl_lock;
 	unsigned short		aen_queue[TW_Q_LENGTH];
 	unsigned char		aen_head;
 	unsigned char		aen_tail;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 9d6040b..1c45934 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2216,6 +2216,7 @@
 		HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
 		HostAdapter->Bus = ProbeInfo->Bus;
 		HostAdapter->Device = ProbeInfo->Device;
+		HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
 		HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
 		HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
 		/*
@@ -2296,7 +2297,7 @@
 				scsi_host_put(Host);
 			} else {
 				BusLogic_InitializeHostStructure(HostAdapter, Host);
-				scsi_add_host(Host, NULL);
+				scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
 				scsi_scan_host(Host);
 				BusLogicHostAdapterCount++;
 			}
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 6e0c059..320e765 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -80,7 +80,7 @@
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogicfas408.o
 obj-$(CONFIG_SCSI_QLOGIC_FC)	+= qlogicfc.o 
 obj-$(CONFIG_SCSI_QLOGIC_1280)	+= qla1280.o 
-obj-$(CONFIG_SCSI_QLA2XXX)	+= qla2xxx/
+obj-$(CONFIG_SCSI_QLA_FC)	+= qla2xxx/
 obj-$(CONFIG_SCSI_LPFC)		+= lpfc/
 obj-$(CONFIG_SCSI_PAS16)	+= pas16.o
 obj-$(CONFIG_SCSI_SEAGATE)	+= seagate.o
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
deleted file mode 100644
index 4193865..0000000
--- a/drivers/scsi/aacraid/README
+++ /dev/null
@@ -1,74 +0,0 @@
-AACRAID Driver for Linux (take two)
-
-Introduction
--------------------------
-The aacraid driver adds support for Adaptec (http://www.adaptec.com)
-RAID controllers. This is a major rewrite from the original 
-Adaptec supplied driver. It has signficantly cleaned up both the code
-and the running binary size (the module is less than half the size of
-the original).
-
-Supported Cards/Chipsets
--------------------------
-	Adaptec 2020S
-	Adaptec 2025S
-	Adaptec 2120S
-	Adaptec 2130S
-	Adaptec 2200S
-	Adaptec 2230S
-	Adaptec 2240S
-	Adaptec 2410SA
-	Adaptec 2610SA
-	Adaptec 2810SA
-	Adaptec 21610SA
-	Adaptec 3230S
-	Adaptec 3240S
-	Adaptec 4000SAS
-	Adaptec 4005SAS
-	Adaptec 4800SAS
-	Adaptec 4805SAS
-	Adaptec 5400S
-	Dell PERC 2 Quad Channel
-	Dell PERC 2/Si
-	Dell PERC 3/Si
-	Dell PERC 3/Di
-	Dell CERC 2
-	HP NetRAID-4M
-	Legend S220
-	Legend S230
-	IBM ServeRAID 8i
-	ICP 9014R0
-	ICP 9024R0
-	ICP 9047MA
-	ICP 9087MA
-	ICP 9085LI
-	ICP 5085AU
-
-People
--------------------------
-Alan Cox <alan@redhat.com>
-Christoph Hellwig <hch@infradead.org>	(updates for new-style PCI probing and SCSI host registration,
-					 small cleanups/fixes)
-Matt Domsch <matt_domsch@dell.com>	(revision ioctl, adapter messages)
-Deanna Bonds                            (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
-					 added new ioctls, changed scsi interface to use new error handler,
-					 increased the number of fibs and outstanding commands to a container)
-
-					(fixed 64bit and 64G memory model, changed confusing naming convention
-					 where fibs that go to the hardware are consistently called hw_fibs and
-					 not just fibs like the name of the driver tracking structure)
-Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
-
-Original Driver
--------------------------
-Adaptec Unix OEM Product Group
-
-Mailing List
--------------------------
-linux-scsi@vger.kernel.org (Interested parties troll here)
-Also note this is very different to Brian's original driver
-so don't expect him to support it.
-Adaptec does support this driver.  Contact either tech support or Mark Salyzyn.
-
-Original by Brian Boerner February 2001
-Rewritten by Alan Cox, November 2001
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 30fd8d6..66dbb6d 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -532,6 +532,13 @@
 #define AAC_QUIRK_MASTER 0x0008
 
 /*
+ * Some adapter firmware perform poorly when it must split up scatter gathers
+ * in order to deal with the limits of the underlying CHIM. This limit in this
+ * class of adapters is 17 scatter gather elements.
+ */
+#define AAC_QUIRK_17SG	0x0010
+
+/*
  *	The adapter interface specs all queues to be located in the same
  *	physically contigous block. The host structure that defines the
  *	commuication queues will assume they are each a separate physically
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index ef623bd..4fe79cd 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -85,6 +85,10 @@
 	if (size < le16_to_cpu(kfib->header.SenderSize))
 		size = le16_to_cpu(kfib->header.SenderSize);
 	if (size > dev->max_fib_size) {
+		if (size > 2048) {
+			retval = -EINVAL;
+			goto cleanup;
+		}
 		/* Highjack the hw_fib */
 		hw_fib = fibptr->hw_fib;
 		hw_fib_pa = fibptr->hw_fib_pa;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 9b9062f..0bf5f9a 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -200,10 +200,10 @@
 	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "Callisto        ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA       ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025SA       ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
-	{ aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+	{ aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2026ZCR     ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2610SA      ", 1 }, /* SATA 6Ch (Bearcat) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2240S       ", 1 }, /* ASR-2240S (SabreExpress) */
@@ -574,7 +574,15 @@
 	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
 	int len;
 
-	len = snprintf(buf, PAGE_SIZE, "%s\n",
+	if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+		char * cp = dev->supplement_adapter_info.AdapterTypeText;
+		while (*cp && *cp != ' ')
+			++cp;
+		while (*cp == ' ')
+			++cp;
+		len = snprintf(buf, PAGE_SIZE, "%s\n", cp);
+	} else
+		len = snprintf(buf, PAGE_SIZE, "%s\n",
 		  aac_drivers[dev->cardtype].model);
 	return len;
 }
@@ -585,7 +593,15 @@
 	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
 	int len;
 
-	len = snprintf(buf, PAGE_SIZE, "%s\n",
+	if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+		char * cp = dev->supplement_adapter_info.AdapterTypeText;
+		while (*cp && *cp != ' ')
+			++cp;
+		len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+		  (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText),
+		  dev->supplement_adapter_info.AdapterTypeText);
+	} else
+		len = snprintf(buf, PAGE_SIZE, "%s\n",
 		  aac_drivers[dev->cardtype].vname);
 	return len;
 }
@@ -837,6 +853,13 @@
  		  = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
  	}
 
+ 	if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
+			(aac->scsi_host_ptr->sg_tablesize > 17)) {
+ 		aac->scsi_host_ptr->sg_tablesize = 17;
+ 		aac->scsi_host_ptr->max_sectors
+ 		  = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+ 	}
+
 	/*
 	 * Firware printf works only with older firmware.
 	 */
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index ac8de03..6c2c395 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -42,13 +42,13 @@
 config AIC7XXX_RESET_DELAY_MS
 	int "Initial bus reset delay in milli-seconds"
 	depends on SCSI_AIC7XXX
-	default "15000"
+	default "5000"
 	---help---
 	The number of milliseconds to delay after an initial bus reset.
 	The bus settle delay following all error recovery actions is
 	dictated by the SCSI layer and is not affected by this value.
 
-	Default: 15000 (15 seconds)
+	Default: 5000 (5 seconds)
 
 config AIC7XXX_PROBE_EISA_VL
 	bool "Probe for EISA and VL AIC7XXX Adapters"
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 653fb0b..2cfdbef 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
  *
  * $FreeBSD$
  */
@@ -75,8 +75,7 @@
 #define INITIATOR_WILDCARD	(~0)
 #define	SCB_LIST_NULL		0xFF00
 #define	SCB_LIST_NULL_LE	(ahd_htole16(SCB_LIST_NULL))
-#define QOUTFIFO_ENTRY_VALID 0x8000
-#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
+#define QOUTFIFO_ENTRY_VALID 0x80
 #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
 
 #define SCSIID_TARGET(ahd, scsiid)	\
@@ -1053,6 +1052,13 @@
 
 typedef void ahd_callback_t (void *);
 
+struct ahd_completion
+{
+	uint16_t	tag;
+	uint8_t		sg_status;
+	uint8_t		valid_tag;
+};
+
 struct ahd_softc {
 	bus_space_tag_t           tags[2];
 	bus_space_handle_t        bshs[2];
@@ -1062,6 +1068,7 @@
 	struct scb_data		  scb_data;
 
 	struct hardware_scb	 *next_queued_hscb;
+	struct map_node		 *next_queued_hscb_map;
 
 	/*
 	 * SCBs that have been sent to the controller
@@ -1140,16 +1147,23 @@
 	ahd_flag		  flags;
 	struct seeprom_config	 *seep_config;
 
-	/* Values to store in the SEQCTL register for pause and unpause */
-	uint8_t			  unpause;
-	uint8_t			  pause;
-
 	/* Command Queues */
+	struct ahd_completion	  *qoutfifo;
 	uint16_t		  qoutfifonext;
 	uint16_t		  qoutfifonext_valid_tag;
 	uint16_t		  qinfifonext;
 	uint16_t		  qinfifo[AHD_SCB_MAX];
-	uint16_t		 *qoutfifo;
+
+	/*
+	 * Our qfreeze count.  The sequencer compares
+	 * this value with its own counter to determine
+	 * whether to allow selections to occur.
+	 */
+	uint16_t		  qfreeze_cnt;
+
+	/* Values to store in the SEQCTL register for pause and unpause */
+	uint8_t			  unpause;
+	uint8_t			  pause;
 
 	/* Critical Section Data */
 	struct cs		 *critical_sections;
@@ -1197,8 +1211,7 @@
 	 */
 	bus_dma_tag_t		  parent_dmat;
 	bus_dma_tag_t		  shared_data_dmat;
-	bus_dmamap_t		  shared_data_dmamap;
-	dma_addr_t		  shared_data_busaddr;
+	struct map_node		  shared_data_map;
 
 	/* Information saved through suspend/resume cycles */
 	struct ahd_suspend_state  suspend_state;
@@ -1296,9 +1309,9 @@
 };
 
 /****************************** PCI Structures ********************************/
-#define AHD_PCI_IOADDR0	PCIR_MAPS	/* I/O BAR*/
-#define AHD_PCI_MEMADDR	(PCIR_MAPS + 4)	/* Memory BAR */
-#define AHD_PCI_IOADDR1	(PCIR_MAPS + 12)/* Second I/O BAR */
+#define AHD_PCI_IOADDR0	PCIR_BAR(0)	/* I/O BAR*/
+#define AHD_PCI_MEMADDR	PCIR_BAR(1)	/* Memory BAR */
+#define AHD_PCI_IOADDR1	PCIR_BAR(3)	/* Second I/O BAR */
 
 typedef int (ahd_device_setup_t)(struct ahd_softc *);
 
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index cca58ed..3a32047 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -39,7 +39,7 @@
  *
  * $FreeBSD$
  */
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
 
 /*
  * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -65,13 +65,6 @@
 		mvi	MODE_PTR, MK_MODE(src, dst);			\
 	}
 
-#define TOGGLE_DFF_MODE							\
-	if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {			\
-		call	toggle_dff_mode_work_around;			\
-	} else {							\
-		xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);		\
-	}
-	
 #define RESTORE_MODE(mode)						\
 	if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {			\
 		mov	mode call set_mode_work_around;			\
@@ -1199,7 +1192,7 @@
 
 /*
  * LQ Packet In
- * The last LQ Packet received
+ * The last LQ Packet recieved
  */
 register LQIN {
 	address			0x020
@@ -3542,10 +3535,34 @@
 	COMPLETE_DMA_SCB_HEAD {
 		size		2
 	}
-	/* Counting semaphore to prevent new select-outs */
+	/*
+	 * tail of list of SCBs that have
+	 * completed but need to be uploaded
+	 * to the host prior to being completed.
+	 */
+	COMPLETE_DMA_SCB_TAIL {
+		size		2
+	}
+	/*
+	 * head of list of SCBs that have
+	 * been uploaded to the host, but cannot
+	 * be completed until the QFREEZE is in
+	 * full effect (i.e. no selections pending).
+	 */
+	COMPLETE_ON_QFREEZE_HEAD {
+		size		2
+	}
+	/*
+	 * Counting semaphore to prevent new select-outs
+	 * The queue is frozen so long as the sequencer
+	 * and kernel freeze counts differ.
+	 */
 	QFREEZE_COUNT {
 		size		2
 	}
+	KERNEL_QFREEZE_COUNT {
+		size		2
+	}
 	/*
 	 * Mode to restore on legacy idle loop exit.
 	 */
@@ -3625,6 +3642,17 @@
 		size		1
 	}
 	/*
+	 * Kernel and sequencer offsets into the queue of
+	 * incoming target mode command descriptors.  The
+	 * queue is full when the KERNEL_TQINPOS == TQINPOS.
+	 */
+	KERNEL_TQINPOS {
+		size		1
+	}
+	TQINPOS {                
+		size		1
+	}
+	/*
 	 * Base address of our shared data with the kernel driver in host
 	 * memory.  This includes the qoutfifo and target mode
 	 * incoming command queue.
@@ -3639,17 +3667,6 @@
 	QOUTFIFO_NEXT_ADDR {
 		size		4
 	}
-	/*
-	 * Kernel and sequencer offsets into the queue of
-	 * incoming target mode command descriptors.  The
-	 * queue is full when the KERNEL_TQINPOS == TQINPOS.
-	 */
-	KERNEL_TQINPOS {
-		size		1
-	}
-	TQINPOS {                
-		size		1
-	}
 	ARG_1 {
 		size		1
 		mask	SEND_MSG		0x80
@@ -3951,6 +3968,7 @@
 const SG_SIZEOF download
 const PKT_OVERRUN_BUFOFFSET download
 const SCB_TRANSFER_SIZE	download
+const CACHELINE_MASK download
 
 /*
  * BIOS SCB offsets
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq
index 65339bc..bef1f9d 100644
--- a/drivers/scsi/aic7xxx/aic79xx.seq
+++ b/drivers/scsi/aic7xxx/aic79xx.seq
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
 PATCH_ARG_LIST = "struct ahd_softc *ahd"
 PREFIX = "ahd_"
 
@@ -68,13 +68,47 @@
 	}
 	SET_MODE(M_SCSI, M_SCSI)
 	test	SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
-	test	SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;
+	test	SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list;
+	/*
+	 * If the kernel has caught up with us, thaw the queue.
+	 */
+	mov	A, KERNEL_QFREEZE_COUNT;
+	cmp	QFREEZE_COUNT, A jne check_frozen_completions;
+	mov	A, KERNEL_QFREEZE_COUNT[1];
+	cmp	QFREEZE_COUNT[1], A jne check_frozen_completions;
+	and	SEQ_FLAGS2, ~SELECTOUT_QFROZEN;
+	jmp	check_waiting_list;
+check_frozen_completions:
+	test	SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus;
+BEGIN_CRITICAL;
+	/*
+	 * If we have completions stalled waiting for the qfreeze
+	 * to take effect, move them over to the complete_scb list
+	 * now that no selections are pending.
+	 */
+	cmp	COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus;
+	/*
+	 * Find the end of the qfreeze list.  The first element has
+	 * to be treated specially.
+	 */
+	bmov	SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2;
+	cmp 	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists;
+	/*
+	 * Now the normal loop.
+	 */
+	bmov	SCBPTR, SCB_NEXT_COMPLETE, 2;
+	cmp 	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1;
+join_lists:
+	bmov	SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+	bmov	COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2;
+	mvi	COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL;
+	jmp	idle_loop_checkbus;
+check_waiting_list:
 	cmp	WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
 	/*
 	 * ENSELO is cleared by a SELDO, so we must test for SELDO
 	 * one last time.
 	 */
-BEGIN_CRITICAL;
 	test	SSTAT0, SELDO jnz select_out;
 END_CRITICAL;
 	call	start_selection;
@@ -90,6 +124,13 @@
 	test	SSTAT2, NONPACKREQ jz . + 2;
 	call	unexpected_nonpkt_phase_find_ctxt;
 	if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+		/*
+		 * On Rev A. hardware, the busy LED is only
+		 * turned on automaically during selections
+		 * and re-selections.  Make the LED status
+		 * more useful by forcing it to be on so
+		 * long as one of our data FIFOs is active.
+		 */
 		and	A, FIFO0FREE|FIFO1FREE, DFFSTAT;
 		cmp	A, FIFO0FREE|FIFO1FREE jne . + 3;
 		and	SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
@@ -101,9 +142,9 @@
 	call	idle_loop_cchan;
 	jmp	idle_loop;
 
-BEGIN_CRITICAL;
 idle_loop_gsfifo:
 	SET_MODE(M_SCSI, M_SCSI)
+BEGIN_CRITICAL;
 idle_loop_gsfifo_in_scsi_mode:
 	test	LQISTAT2, LQIGSAVAIL jz return;
 	/*
@@ -152,11 +193,15 @@
 
 idle_loop_service_fifos:
 	SET_MODE(M_DFF0, M_DFF0)
+BEGIN_CRITICAL;
 	test	LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
 	call	longjmp;
+END_CRITICAL;
 idle_loop_next_fifo:
 	SET_MODE(M_DFF1, M_DFF1)
+BEGIN_CRITICAL;
 	test	LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
+END_CRITICAL;
 return:
 	ret;
 
@@ -170,7 +215,6 @@
 	test	CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
 	test	CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
 	test	CCSCBCTL, CCSCBDONE jz return;
-END_CRITICAL;
 	/* FALLTHROUGH */
 scbdma_tohost_done:
 	test	CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
@@ -180,26 +224,18 @@
 	 * bad SCSI status (currently only for underruns), we
 	 * queue the SCB for normal completion.  Otherwise, we
 	 * wait until any select-out activity has halted, and
-	 * then notify the host so that the transaction can be
-	 * dealt with.
+	 * then queue the completion.
 	 */
-	test	SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
 	and	CCSCBCTL, ~(CCARREN|CCSCBEN);
 	bmov	COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+	cmp	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2;
+	mvi	COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL;
+	test	SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;
+	bmov	SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2;
+	bmov	COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret;
+scbdma_queue_completion:
 	bmov	SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
 	bmov	COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
-scbdma_notify_host:
-	SET_MODE(M_SCSI, M_SCSI)
-	test	SCSISEQ0, ENSELO jnz return;
-	test	SSTAT0, (SELDO|SELINGO) jnz return;
-	SET_MODE(M_CCHAN, M_CCHAN)
-	/*
-	 * Remove SCB and notify host.
-	 */
-	and	CCSCBCTL, ~(CCARREN|CCSCBEN);
-	bmov	COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
-	SET_SEQINTCODE(BAD_SCB_STATUS)
-	ret;
 fill_qoutfifo_dmadone:
 	and	CCSCBCTL, ~(CCARREN|CCSCBEN);
 	call	qoutfifo_updated;
@@ -208,6 +244,7 @@
 	test	QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
 	bmov	QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
 	xor	QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
+END_CRITICAL;
 
 qoutfifo_updated:
 	/*
@@ -324,14 +361,15 @@
 	 * Keep track of the SCBs we are dmaing just
 	 * in case the DMA fails or is aborted.
 	 */
-	mov	A, QOUTFIFO_ENTRY_VALID_TAG;
 	bmov	COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;
 	mvi	CCSCBCTL, CCSCBRESET;
 	bmov	SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;
+	mov	A, QOUTFIFO_NEXT_ADDR;
 	bmov	SCBPTR, COMPLETE_SCB_HEAD, 2;
 fill_qoutfifo_loop:
-	mov	CCSCBRAM, SCBPTR;
-	or	CCSCBRAM, A, SCBPTR[1];
+	bmov	CCSCBRAM, SCBPTR, 2;
+	mov	CCSCBRAM, SCB_SGPTR[0];
+	mov	CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG;
 	mov	NONE, SDSCB_QOFF;
 	inc	INT_COALESCING_CMDCOUNT;
 	add	CMDS_PENDING, -1;
@@ -339,6 +377,18 @@
 	cmp	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;
 	cmp	CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;
 	test	QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;
+	/*
+	 * Don't cross an ADB or Cachline boundary when DMA'ing
+	 * completion entries.  In PCI mode, at least in 32/33
+	 * configurations, the SCB DMA engine may lose its place
+	 * in the data-stream should the target force a retry on
+	 * something other than an 8byte aligned boundary. In
+	 * PCI-X mode, we do this to avoid split transactions since
+	 * many chipsets seem to be unable to format proper split
+	 * completions to continue the data transfer.
+	 */
+	add	SINDEX, A, CCSCBADDR;
+	test	SINDEX, CACHELINE_MASK jz fill_qoutfifo_done;
 	bmov	SCBPTR, SCB_NEXT_COMPLETE, 2;
 	jmp	fill_qoutfifo_loop;
 fill_qoutfifo_done:
@@ -354,7 +404,6 @@
 	bmov	SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
 	bmov	SCBHADDR, SCB_BUSADDR, 4;
 	mvi	CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
-END_CRITICAL;
 
 /*
  * Either post or fetch an SCB from host memory.  The caller
@@ -371,9 +420,19 @@
 	mvi	SCBHCNT, SCB_TRANSFER_SIZE;
 	mov	CCSCBCTL, SINDEX ret;
 
-BEGIN_CRITICAL;
 setjmp:
-	bmov	LONGJMP_ADDR, STACK, 2 ret;
+	/*
+	 * At least on the A, a return in the same
+	 * instruction as the bmov results in a return
+	 * to the caller, not to the new address at the
+	 * top of the stack.  Since we want the latter
+	 * (we use setjmp to register a handler from an
+	 * interrupt context but not invoke that handler
+	 * until we return to our idle loop), use a
+	 * separate ret instruction.
+	 */
+	bmov	LONGJMP_ADDR, STACK, 2;
+	ret;
 setjmp_inline:
 	bmov	LONGJMP_ADDR, STACK, 2;
 longjmp:
@@ -392,11 +451,6 @@
 	mvi	SEQINTCTL, INTVEC1DSL;
 	mov	MODE_PTR, SINDEX;
 	clr	SEQINTCTL ret;
-
-toggle_dff_mode_work_around:
-	mvi	SEQINTCTL, INTVEC1DSL;
-	xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
-	clr	SEQINTCTL ret;
 }
 
 
@@ -490,6 +544,21 @@
 SET_SRC_MODE	M_SCSI;
 SET_DST_MODE	M_SCSI;
 select_in:
+	if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+		/*
+		 * On Rev A. hardware, the busy LED is only
+		 * turned on automaically during selections
+		 * and re-selections.  Make the LED status
+		 * more useful by forcing it to be on from
+		 * the point of selection until our idle
+		 * loop determines that neither of our FIFOs
+		 * are busy.  This handles the non-packetized
+		 * case nicely as we will not return to the
+		 * idle loop until the busfree at the end of
+		 * each transaction.
+		 */
+		or	SBLKCTL, DIAGLEDEN|DIAGLEDON;
+	}
 	if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
 		/*
 		 * Test to ensure that the bus has not
@@ -528,6 +597,21 @@
 SET_DST_MODE	M_SCSI;
 select_out:
 BEGIN_CRITICAL;
+	if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+		/*
+		 * On Rev A. hardware, the busy LED is only
+		 * turned on automaically during selections
+		 * and re-selections.  Make the LED status
+		 * more useful by forcing it to be on from
+		 * the point of re-selection until our idle
+		 * loop determines that neither of our FIFOs
+		 * are busy.  This handles the non-packetized
+		 * case nicely as we will not return to the
+		 * idle loop until the busfree at the end of
+		 * each transaction.
+		 */
+		or	SBLKCTL, DIAGLEDEN|DIAGLEDON;
+	}
 	/* Clear out all SCBs that have been successfully sent. */
 	if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
 		/*
@@ -1000,15 +1084,9 @@
 /*
  * We received a "command complete" message.  Put the SCB on the complete
  * queue and trigger a completion interrupt via the idle loop.  Before doing
- * so, check to see if there
- * is a residual or the status byte is something other than STATUS_GOOD (0).
- * In either of these conditions, we upload the SCB back to the host so it can
- * process this information.  In the case of a non zero status byte, we 
- * additionally interrupt the kernel driver synchronously, allowing it to
- * decide if sense should be retrieved.  If the kernel driver wishes to request
- * sense, it will fill the kernel SCB with a request sense command, requeue
- * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting 
- * RETURN_1 to SEND_SENSE.
+ * so, check to see if there is a residual or the status byte is something
+ * other than STATUS_GOOD (0).  In either of these conditions, we upload the
+ * SCB back to the host so it can process this information.
  */
 mesgin_complete:
 
@@ -1053,6 +1131,7 @@
 	call	queue_scb_completion;
 	jmp	await_busfree;
 
+BEGIN_CRITICAL;
 freeze_queue:
 	/* Cancel any pending select-out. */
 	test	SSTAT0, SELDO|SELINGO jnz . + 2;
@@ -1063,6 +1142,7 @@
 	adc	QFREEZE_COUNT[1], A;
 	or	SEQ_FLAGS2, SELECTOUT_QFROZEN;
 	mov	A, ACCUM_SAVE ret;
+END_CRITICAL;
 
 /*
  * Complete the current FIFO's SCB if data for this same
@@ -1085,8 +1165,10 @@
 	test	SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
 	test	SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
 complete:
+BEGIN_CRITICAL;
 	bmov	SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
 	bmov	COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+END_CRITICAL;
 bad_status:
 	cmp	SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
 	call	freeze_queue;
@@ -1097,9 +1179,18 @@
 	 * it on the host.
 	 */
 	bmov	SCB_TAG, SCBPTR, 2;
-	bmov	SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
+BEGIN_CRITICAL;
+	or	SCB_SGPTR, SG_STATUS_VALID;
+	mvi	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;
+	cmp	COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;
 	bmov	COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
-	or	SCB_SGPTR, SG_STATUS_VALID ret;
+	bmov	COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;
+add_dma_scb_tail:
+	bmov	REG0, SCBPTR, 2;
+	bmov	SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;
+	bmov	SCB_NEXT_COMPLETE, REG0, 2;
+	bmov	COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;
+END_CRITICAL;
 
 /*
  * Is it a disconnect message?  Set a flag in the SCB to remind us
@@ -1146,8 +1237,18 @@
 await_busfree_clrchn:
 	mvi	DFFSXFRCTL, CLRCHN;
 await_busfree_not_m_dff:
-	call	clear_target_state;
+	/* clear target specific flags */
+	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
 	test	SSTAT1,REQINIT|BUSFREE	jz .;
+	/*
+	 * We only set BUSFREE status once either a new
+	 * phase has been detected or we are really
+	 * BUSFREE.  This allows the driver to know
+	 * that we are active on the bus even though
+	 * no identified transaction exists should a
+	 * timeout occur while awaiting busfree.
+	 */
+	mvi	LASTPHASE, P_BUSFREE;
 	test	SSTAT1, BUSFREE jnz idle_loop;
 	SET_SEQINTCODE(MISSED_BUSFREE)
 
@@ -1202,11 +1303,6 @@
 	call	allocate_fifo;
 	jmp	mesgin_done;
 
-clear_target_state:
-	mvi	LASTPHASE, P_BUSFREE;
-	/* clear target specific flags */
-	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
-
 phase_lock:     
 	if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
 		/*
@@ -1298,6 +1394,47 @@
 	test	CCSGCTL, CCSGENACK jnz return;
 
 	/*
+	 * Should the other FIFO get the S/G cache first?  If
+	 * both FIFOs have been allocated since we last checked
+	 * any FIFO, it is important that we service a FIFO
+	 * that is not actively on the bus first.  This guarantees
+	 * that a FIFO will be freed to handle snapshot requests for
+	 * any FIFO that is still on the bus.  Chips with RTI do not
+	 * perform snapshots, so don't bother with this test there.
+	 */
+	if ((ahd->features & AHD_RTI) == 0) {
+		/*
+		 * If we're not still receiving SCSI data,
+		 * it is safe to allocate the S/G cache to
+		 * this FIFO.
+		 */
+		test	DFCNTRL, SCSIEN jz idle_sgfetch_start;
+
+		/*
+		 * Switch to the other FIFO.  Non-RTI chips
+		 * also have the "set mode" bug, so we must
+		 * disable interrupts during the switch.
+		 */
+		mvi	SEQINTCTL, INTVEC1DSL;
+		xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+
+		/*
+		 * If the other FIFO needs loading, then it
+		 * must not have claimed the S/G cache yet
+		 * (SG_CACHE_AVAIL would have been cleared in
+		 * the orginal FIFO mode and we test this above).
+		 * Return to the idle loop so we can process the
+		 * FIFO not currently on the bus first.
+		 */
+		test	SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;
+		clr	SEQINTCTL ret;
+idle_sgfetch_okay:
+		xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+		clr	SEQINTCTL;
+	}
+
+idle_sgfetch_start:
+	/*
 	 * We fetch a "cacheline aligned" and sized amount of data
 	 * so we don't end up referencing a non-existant page.
 	 * Cacheline aligned is in quotes because the kernel will
@@ -1308,7 +1445,7 @@
 	mvi	SGHCNT, SG_PREFETCH_CNT;
 	if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
 		/*
-		 * Need two instruction between "touches" of SGHADDR.
+		 * Need two instructions between "touches" of SGHADDR.
 		 */
 		nop;
 	}
@@ -1658,7 +1795,7 @@
 		 * savepointer in the current FIFO.  We do this so that
 		 * a pending CTXTDONE or SAVEPTR is visible in the active
 		 * FIFO.  This status is the only way we can detect if we
-		 * have lost the race (e.g. host paused us) and our attepts
+		 * have lost the race (e.g. host paused us) and our attempts
 		 * to disable the channel occurred after all REQs were
 		 * already seen and acked (REQINIT never comes true).
 		 */
@@ -1667,7 +1804,7 @@
 		test	DFCNTRL, DIRECTION jz interrupt_return;
 		and	DFCNTRL, ~SCSIEN;
 snapshot_wait_data_valid:
-		test	SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
+		test	SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;
 		test	SSTAT1, REQINIT	jz snapshot_wait_data_valid;
 snapshot_data_valid:
 		or	DFCNTRL, SCSIEN;
@@ -1834,7 +1971,6 @@
 	dec	SCB_FIFO_USE_COUNT;
 	test	SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
 	mvi	DFFSXFRCTL, CLRCHN ret;
-END_CRITICAL;
 
 /*
  * LAST_SEG_DONE status has been seen in the current FIFO.
@@ -1843,7 +1979,6 @@
  * Check for overrun and see if we can complete this command.
  */
 pkt_last_seg_done:
-BEGIN_CRITICAL;
 	/*
 	 * Mark transfer as completed.
 	 */
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 4e8f00d..db8f5ce 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -37,9 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
  */
 
 #ifdef __linux__
@@ -332,6 +330,14 @@
 	ahd_outb(ahd, SCSISEQ1,
 		 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
 	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+	/*
+	 * Clear any pending sequencer interrupt.  It is no
+	 * longer relevant since we're resetting the Program
+	 * Counter.
+	 */
+	ahd_outb(ahd, CLRINT, CLRSEQINT);
+
 	ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
 	ahd_unpause(ahd);
 }
@@ -373,13 +379,7 @@
 	saved_modes = ahd_save_modes(ahd);
 
 	/*
-	 * Complete any SCBs that just finished being
-	 * DMA'ed into the qoutfifo.
-	 */
-	ahd_run_qoutfifo(ahd);
-
-	/*
-	 * Flush the good status FIFO for compelted packetized commands.
+	 * Flush the good status FIFO for completed packetized commands.
 	 */
 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
 	saved_scbptr = ahd_get_scbptr(ahd);
@@ -387,8 +387,7 @@
 		u_int fifo_mode;
 		u_int i;
 		
-		scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
-		      | ahd_inb(ahd, GSFIFO);
+		scbid = ahd_inw(ahd, GSFIFO);
 		scb = ahd_lookup_scb(ahd, scbid);
 		if (scb == NULL) {
 			printf("%s: Warning - GSFIFO SCB %d invalid\n",
@@ -401,22 +400,33 @@
 		 * the host before completing the  command.
 		 */
 		fifo_mode = 0;
+rescan_fifos:
 		for (i = 0; i < 2; i++) {
 			/* Toggle to the other mode. */
 			fifo_mode ^= 1;
 			ahd_set_modes(ahd, fifo_mode, fifo_mode);
+
 			if (ahd_scb_active_in_fifo(ahd, scb) == 0)
 				continue;
 
 			ahd_run_data_fifo(ahd, scb);
 
 			/*
-			 * Clearing this transaction in this FIFO may
-			 * cause a CFG4DATA for this same transaction
-			 * to assert in the other FIFO.  Make sure we
-			 * loop one more time and check the other FIFO.
+			 * Running this FIFO may cause a CFG4DATA for
+			 * this same transaction to assert in the other
+			 * FIFO or a new snapshot SAVEPTRS interrupt
+			 * in this FIFO.  Even running a FIFO may not
+			 * clear the transaction if we are still waiting
+			 * for data to drain to the host. We must loop
+			 * until the transaction is not active in either
+			 * FIFO just to be sure.  Reset our loop counter
+			 * so we will visit both FIFOs again before
+			 * declaring this transaction finished.  We
+			 * also delay a bit so that status has a chance
+			 * to change before we look at this FIFO again.
 			 */
-			i = 0;
+			ahd_delay(200);
+			goto rescan_fifos;
 		}
 		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
 		ahd_set_scbptr(ahd, scbid);
@@ -429,19 +439,28 @@
 			/*
 			 * The transfer completed with a residual.
 			 * Place this SCB on the complete DMA list
-			 * so that we Update our in-core copy of the
+			 * so that we update our in-core copy of the
 			 * SCB before completing the command.
 			 */
 			ahd_outb(ahd, SCB_SCSI_STATUS, 0);
 			ahd_outb(ahd, SCB_SGPTR,
 				 ahd_inb_scbram(ahd, SCB_SGPTR)
 				 | SG_STATUS_VALID);
-			ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+			ahd_outw(ahd, SCB_TAG, scbid);
+			ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
 			comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
-			ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
-			if (SCBID_IS_NULL(comp_head))
-				ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,
-					 SCB_GET_TAG(scb));
+			if (SCBID_IS_NULL(comp_head)) {
+				ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
+				ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+			} else {
+				u_int tail;
+
+				tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
+				ahd_set_scbptr(ahd, tail);
+				ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
+				ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+				ahd_set_scbptr(ahd, scbid);
+			}
 		} else
 			ahd_complete_scb(ahd, scb);
 	}
@@ -465,9 +484,22 @@
 			break;
 		ahd_delay(200);
 	}
-	if ((ccscbctl & CCSCBDIR) != 0)
+	/*
+	 * We leave the sequencer to cleanup in the case of DMA's to
+	 * update the qoutfifo.  In all other cases (DMA's to the
+	 * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
+	 * we disable the DMA engine so that the sequencer will not
+	 * attempt to handle the DMA completion.
+	 */
+	if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
 		ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
 
+	/*
+	 * Complete any SCBs that just finished
+	 * being DMA'ed into the qoutfifo.
+	 */
+	ahd_run_qoutfifo(ahd);
+
 	saved_scbptr = ahd_get_scbptr(ahd);
 	/*
 	 * Manually update/complete any completed SCBs that are waiting to be
@@ -494,6 +526,24 @@
 		scbid = next_scbid;
 	}
 	ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+	ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+
+	scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+	while (!SCBID_IS_NULL(scbid)) {
+
+		ahd_set_scbptr(ahd, scbid);
+		next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+		scb = ahd_lookup_scb(ahd, scbid);
+		if (scb == NULL) {
+			printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
+			       ahd_name(ahd), scbid);
+			continue;
+		}
+
+		ahd_complete_scb(ahd, scb);
+		scbid = next_scbid;
+	}
+	ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
 
 	scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
 	while (!SCBID_IS_NULL(scbid)) {
@@ -558,150 +608,146 @@
 {
 	u_int seqintsrc;
 
-	while (1) {
-		seqintsrc = ahd_inb(ahd, SEQINTSRC);
-		if ((seqintsrc & CFG4DATA) != 0) {
-			uint32_t datacnt;
-			uint32_t sgptr;
+	seqintsrc = ahd_inb(ahd, SEQINTSRC);
+	if ((seqintsrc & CFG4DATA) != 0) {
+		uint32_t datacnt;
+		uint32_t sgptr;
 
-			/*
-			 * Clear full residual flag.
-			 */
-			sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
-			ahd_outb(ahd, SCB_SGPTR, sgptr);
+		/*
+		 * Clear full residual flag.
+		 */
+		sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+		ahd_outb(ahd, SCB_SGPTR, sgptr);
 
-			/*
-			 * Load datacnt and address.
-			 */
-			datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
-			if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
-				sgptr |= LAST_SEG;
-				ahd_outb(ahd, SG_STATE, 0);
-			} else
-				ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
-			ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
-			ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
-			ahd_outb(ahd, SG_CACHE_PRE, sgptr);
-			ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
-
-			/*
-			 * Initialize Residual Fields.
-			 */
-			ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
-			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
-
-			/*
-			 * Mark the SCB as having a FIFO in use.
-			 */
-			ahd_outb(ahd, SCB_FIFO_USE_COUNT,
-				 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
-
-			/*
-			 * Install a "fake" handler for this FIFO.
-			 */
-			ahd_outw(ahd, LONGJMP_ADDR, 0);
-
-			/*
-			 * Notify the hardware that we have satisfied
-			 * this sequencer interrupt.
-			 */
-			ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
-		} else if ((seqintsrc & SAVEPTRS) != 0) {
-			uint32_t sgptr;
-			uint32_t resid;
-
-			if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
-				/*
-				 * Snapshot Save Pointers.  Clear
-				 * the snapshot and continue.
-				 */
-				ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
-				continue;
-			}
-
-			/*
-			 * Disable S/G fetch so the DMA engine
-			 * is available to future users.
-			 */
-			if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
-				ahd_outb(ahd, CCSGCTL, 0);
+		/*
+		 * Load datacnt and address.
+		 */
+		datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+		if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+			sgptr |= LAST_SEG;
 			ahd_outb(ahd, SG_STATE, 0);
+		} else
+			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+		ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+		ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+		ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
 
-			/*
-			 * Flush the data FIFO.  Strickly only
-			 * necessary for Rev A parts.
-			 */
-			ahd_outb(ahd, DFCNTRL,
-				 ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+		/*
+		 * Initialize Residual Fields.
+		 */
+		ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+		ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
 
-			/*
-			 * Calculate residual.
-			 */
-			sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
-			resid = ahd_inl(ahd, SHCNT);
-			resid |=
-			    ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
-			ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
-			if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
-				/*
-				 * Must back up to the correct S/G element.
-				 * Typically this just means resetting our
-				 * low byte to the offset in the SG_CACHE,
-				 * but if we wrapped, we have to correct
-				 * the other bytes of the sgptr too.
-				 */
-				if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
-				 && (sgptr & 0x80) == 0)
-					sgptr -= 0x100;
-				sgptr &= ~0xFF;
-				sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
-				       & SG_ADDR_MASK;
-				ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
-				ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
-			} else if ((resid & AHD_SG_LEN_MASK) == 0) {
-				ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
-					 sgptr | SG_LIST_NULL);
-			}
-			/*
-			 * Save Pointers.
-			 */
-			ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
-			ahd_outl(ahd, SCB_DATACNT, resid);
-			ahd_outl(ahd, SCB_SGPTR, sgptr);
-			ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
-			ahd_outb(ahd, SEQIMODE,
-				 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
-			/*
-			 * If the data is to the SCSI bus, we are
-			 * done, otherwise wait for FIFOEMP.
-			 */
-			if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
-				break;
-		} else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
-			uint32_t sgptr;
-			uint64_t data_addr;
-			uint32_t data_len;
-			u_int	 dfcntrl;
+		/*
+		 * Mark the SCB as having a FIFO in use.
+		 */
+		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
 
-			/*
-			 * Disable S/G fetch so the DMA engine
-			 * is available to future users.
-			 */
-			if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
-				ahd_outb(ahd, CCSGCTL, 0);
-				ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
-			}
+		/*
+		 * Install a "fake" handler for this FIFO.
+		 */
+		ahd_outw(ahd, LONGJMP_ADDR, 0);
 
+		/*
+		 * Notify the hardware that we have satisfied
+		 * this sequencer interrupt.
+		 */
+		ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+	} else if ((seqintsrc & SAVEPTRS) != 0) {
+		uint32_t sgptr;
+		uint32_t resid;
+
+		if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
 			/*
-			 * Wait for the DMA engine to notice that the
-			 * host transfer is enabled and that there is
-			 * space in the S/G FIFO for new segments before
-			 * loading more segments.
+			 * Snapshot Save Pointers.  All that
+			 * is necessary to clear the snapshot
+			 * is a CLRCHN.
 			 */
-			if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)
-				continue;
-			if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)
-				continue;
+			goto clrchn;
+		}
+
+		/*
+		 * Disable S/G fetch so the DMA engine
+		 * is available to future users.
+		 */
+		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+			ahd_outb(ahd, CCSGCTL, 0);
+		ahd_outb(ahd, SG_STATE, 0);
+
+		/*
+		 * Flush the data FIFO.  Strickly only
+		 * necessary for Rev A parts.
+		 */
+		ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+
+		/*
+		 * Calculate residual.
+		 */
+		sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+		resid = ahd_inl(ahd, SHCNT);
+		resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+		ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+		if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
+			/*
+			 * Must back up to the correct S/G element.
+			 * Typically this just means resetting our
+			 * low byte to the offset in the SG_CACHE,
+			 * but if we wrapped, we have to correct
+			 * the other bytes of the sgptr too.
+			 */
+			if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+			 && (sgptr & 0x80) == 0)
+				sgptr -= 0x100;
+			sgptr &= ~0xFF;
+			sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+			       & SG_ADDR_MASK;
+			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+			ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+		} else if ((resid & AHD_SG_LEN_MASK) == 0) {
+			ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+				 sgptr | SG_LIST_NULL);
+		}
+		/*
+		 * Save Pointers.
+		 */
+		ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+		ahd_outl(ahd, SCB_DATACNT, resid);
+		ahd_outl(ahd, SCB_SGPTR, sgptr);
+		ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+		ahd_outb(ahd, SEQIMODE,
+			 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+		/*
+		 * If the data is to the SCSI bus, we are
+		 * done, otherwise wait for FIFOEMP.
+		 */
+		if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+			goto clrchn;
+	} else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+		uint32_t sgptr;
+		uint64_t data_addr;
+		uint32_t data_len;
+		u_int	 dfcntrl;
+
+		/*
+		 * Disable S/G fetch so the DMA engine
+		 * is available to future users.  We won't
+		 * be using the DMA engine to load segments.
+		 */
+		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
+			ahd_outb(ahd, CCSGCTL, 0);
+			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+		}
+
+		/*
+		 * Wait for the DMA engine to notice that the
+		 * host transfer is enabled and that there is
+		 * space in the S/G FIFO for new segments before
+		 * loading more segments.
+		 */
+		if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
+		 && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
 
 			/*
 			 * Determine the offset of the next S/G
@@ -748,7 +794,7 @@
 			 * Advertise the segment to the hardware.
 			 */
 			dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
-			if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+			if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
 				/*
 				 * Use SCSIENWRDIS so that SCSIEN
 				 * is never modified by this
@@ -757,35 +803,44 @@
 				dfcntrl |= SCSIENWRDIS;
 			}
 			ahd_outb(ahd, DFCNTRL, dfcntrl);
-		} else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
-			 & LAST_SEG_DONE) != 0) {
-
-			/*
-			 * Transfer completed to the end of SG list
-			 * and has flushed to the host.
-			 */
-			ahd_outb(ahd, SCB_SGPTR,
-				 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
-			break;
-		} else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
-			break;
 		}
-		ahd_delay(200);
+	} else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
+
+		/*
+		 * Transfer completed to the end of SG list
+		 * and has flushed to the host.
+		 */
+		ahd_outb(ahd, SCB_SGPTR,
+			 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+		goto clrchn;
+	} else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+clrchn:
+		/*
+		 * Clear any handler for this FIFO, decrement
+		 * the FIFO use count for the SCB, and release
+		 * the FIFO.
+		 */
+		ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
+		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
+		ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
 	}
-	/*
-	 * Clear any handler for this FIFO, decrement
-	 * the FIFO use count for the SCB, and release
-	 * the FIFO.
-	 */
-	ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
-	ahd_outb(ahd, SCB_FIFO_USE_COUNT,
-		 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
-	ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
 }
 
+/*
+ * Look for entries in the QoutFIFO that have completed.
+ * The valid_tag completion field indicates the validity
+ * of the entry - the valid value toggles each time through
+ * the queue. We use the sg_status field in the completion
+ * entry to avoid referencing the hscb if the completion
+ * occurred with no errors and no residual.  sg_status is
+ * a copy of the first byte (little endian) of the sgptr
+ * hscb field.
+ */
 void
 ahd_run_qoutfifo(struct ahd_softc *ahd)
 {
+	struct ahd_completion *completion;
 	struct scb *scb;
 	u_int  scb_index;
 
@@ -793,11 +848,13 @@
 		panic("ahd_run_qoutfifo recursion");
 	ahd->flags |= AHD_RUNNING_QOUTFIFO;
 	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
-	while ((ahd->qoutfifo[ahd->qoutfifonext]
-	     & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {
+	for (;;) {
+		completion = &ahd->qoutfifo[ahd->qoutfifonext];
 
-		scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]
-				      & ~QOUTFIFO_ENTRY_VALID_LE);
+		if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
+			break;
+
+		scb_index = ahd_le16toh(completion->tag);
 		scb = ahd_lookup_scb(ahd, scb_index);
 		if (scb == NULL) {
 			printf("%s: WARNING no command for scb %d "
@@ -805,12 +862,15 @@
 			       ahd_name(ahd), scb_index,
 			       ahd->qoutfifonext);
 			ahd_dump_card_state(ahd);
-		} else
-			ahd_complete_scb(ahd, scb);
+		} else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
+			ahd_handle_scb_status(ahd, scb);
+		} else {
+			ahd_done(ahd, scb);
+		}
 
 		ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
 		if (ahd->qoutfifonext == 0)
-			ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE;
+			ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
 	}
 	ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
 }
@@ -876,26 +936,6 @@
 		       ahd_name(ahd), seqintcode);
 #endif
 	switch (seqintcode) {
-	case BAD_SCB_STATUS:
-	{
-		struct	scb *scb;
-		u_int	scbid;
-		int	cmds_pending;
-
-		scbid = ahd_get_scbptr(ahd);
-		scb = ahd_lookup_scb(ahd, scbid);
-		if (scb != NULL) {
-			ahd_complete_scb(ahd, scb);
-		} else {
-			printf("%s: WARNING no command for scb %d "
-			       "(bad status)\n", ahd_name(ahd), scbid);
-			ahd_dump_card_state(ahd);
-		}
-		cmds_pending = ahd_inw(ahd, CMDS_PENDING);
-		if (cmds_pending > 0)
-			ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
-		break;
-	}
 	case ENTERING_NONPACK:
 	{
 		struct	scb *scb;
@@ -1060,7 +1100,7 @@
 			ahd_outb(ahd, SAVED_LUN, 0);
 			ahd_outb(ahd, SEQ_FLAGS, 0);
 			ahd_assert_atn(ahd);
-			scb->flags &= ~(SCB_PACKETIZED);
+			scb->flags &= ~SCB_PACKETIZED;
 			scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
 			ahd_freeze_devq(ahd, scb);
 			ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
@@ -1503,9 +1543,6 @@
 	 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
 		scb = NULL;
 
-	/* Make sure the sequencer is in a safe location. */
-	ahd_clear_critical_section(ahd);
-
 	if ((status0 & IOERR) != 0) {
 		u_int now_lvd;
 
@@ -1521,26 +1558,35 @@
 		ahd_setup_iocell_workaround(ahd);
 		ahd_unpause(ahd);
 	} else if ((status0 & OVERRUN) != 0) {
+
 		printf("%s: SCSI offset overrun detected.  Resetting bus.\n",
 		       ahd_name(ahd));
 		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
 	} else if ((status & SCSIRSTI) != 0) {
+
 		printf("%s: Someone reset channel A\n", ahd_name(ahd));
 		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
 	} else if ((status & SCSIPERR) != 0) {
+
+		/* Make sure the sequencer is in a safe location. */
+		ahd_clear_critical_section(ahd);
+
 		ahd_handle_transmission_error(ahd);
 	} else if (lqostat0 != 0) {
+
 		printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
 		ahd_outb(ahd, CLRLQOINT0, lqostat0);
-		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
+		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
 			ahd_outb(ahd, CLRLQOINT1, 0);
-		}
 	} else if ((status & SELTO) != 0) {
 		u_int  scbid;
 
 		/* Stop the selection */
 		ahd_outb(ahd, SCSISEQ0, 0);
 
+		/* Make sure the sequencer is in a safe location. */
+		ahd_clear_critical_section(ahd);
+
 		/* No more pending messages */
 		ahd_clear_msg_state(ahd);
 
@@ -1573,24 +1619,27 @@
 				       scbid);
 			}
 #endif
-			/*
-			 * Force a renegotiation with this target just in
-			 * case the cable was pulled and will later be
-			 * re-attached.  The target may forget its negotiation
-			 * settings with us should it attempt to reselect
-			 * during the interruption.  The target will not issue
-			 * a unit attention in this case, so we must always
-			 * renegotiate.
-			 */
 			ahd_scb_devinfo(ahd, &devinfo, scb);
-			ahd_force_renegotiation(ahd, &devinfo);
 			ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
 			ahd_freeze_devq(ahd, scb);
+
+			/*
+			 * Cancel any pending transactions on the device
+			 * now that it seems to be missing.  This will
+			 * also revert us to async/narrow transfers until
+			 * we can renegotiate with the device.
+			 */
+			ahd_handle_devreset(ahd, &devinfo,
+					    CAM_LUN_WILDCARD,
+					    CAM_SEL_TIMEOUT,
+					    "Selection Timeout",
+					    /*verbose_level*/1);
 		}
 		ahd_outb(ahd, CLRINT, CLRSCSIINT);
 		ahd_iocell_first_selection(ahd);
 		ahd_unpause(ahd);
 	} else if ((status0 & (SELDI|SELDO)) != 0) {
+
 		ahd_iocell_first_selection(ahd);
 		ahd_unpause(ahd);
 	} else if (status3 != 0) {
@@ -1598,6 +1647,10 @@
 		       ahd_name(ahd), status3);
 		ahd_outb(ahd, CLRSINT3, status3);
 	} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
+
+		/* Make sure the sequencer is in a safe location. */
+		ahd_clear_critical_section(ahd);
+
 		ahd_handle_lqiphase_error(ahd, lqistat1);
 	} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
 		/*
@@ -1622,6 +1675,9 @@
 		 */
 		ahd_outb(ahd, SCSISEQ0, 0);
 
+		/* Make sure the sequencer is in a safe location. */
+		ahd_clear_critical_section(ahd);
+
 		/*
 		 * Determine what we were up to at the time of
 		 * the busfree.
@@ -1659,7 +1715,16 @@
 			clear_fifo = 0;
 			packetized =  (lqostat1 & LQOBUSFREE) != 0;
 			if (!packetized
-			 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE)
+			 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
+			 && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
+			 && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
+			  || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
+				/*
+				 * Assume packetized if we are not
+				 * on the bus in a non-packetized
+				 * capacity and any pending selection
+				 * was a packetized selection.
+				 */
 				packetized = 1;
 			break;
 		}
@@ -2310,8 +2375,7 @@
 		       "PRGMCNT == 0x%x\n",
 		       ahd_lookup_phase_entry(lastphase)->phasemsg,
 		       aborted,
-		       ahd_inb(ahd, PRGMCNT)
-			| (ahd_inb(ahd, PRGMCNT+1) << 8));
+		       ahd_inw(ahd, PRGMCNT));
 		ahd_dump_card_state(ahd);
 	}
 	/* Always restart the sequencer. */
@@ -2474,8 +2538,7 @@
 		u_int	i;
 
 		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-		seqaddr = ahd_inb(ahd, CURADDR)
-			| (ahd_inb(ahd, CURADDR+1) << 8);
+		seqaddr = ahd_inw(ahd, CURADDR);
 
 		cs = ahd->critical_sections;
 		for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
@@ -3196,14 +3259,25 @@
 		iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
 
 		if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
-		 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) {
+		 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
+		 && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
 			/*
 			 * Slow down our CRC interval to be
-			 * compatible with devices that can't
-			 * handle a CRC at full speed.
+			 * compatible with non-packetized
+			 * U160 devices that can't handle a
+			 * CRC at full speed.
 			 */
 			con_opts |= ENSLOWCRC;
 		}
+
+		if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
+			/*
+			 * On H2A4, revert to a slower slewrate
+			 * on non-paced transfers.
+			 */
+			iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
+			    ~AHD_SLEWRATE_MASK;
+		}
 	}
 
 	ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
@@ -3292,11 +3366,15 @@
 	 * Force the sequencer to reinitialize the selection for
 	 * the command at the head of the execution queue if it
 	 * has already been setup.  The negotiation changes may
-	 * effect whether we select-out with ATN.
+	 * effect whether we select-out with ATN.  It is only
+	 * safe to clear ENSELO when the bus is not free and no
+	 * selection is in progres or completed.
 	 */
 	saved_modes = ahd_save_modes(ahd);
 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-	ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
+	if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
+	 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
+		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
 	saved_scbptr = ahd_get_scbptr(ahd);
 	/* Ensure that the hscbs down on the card match the new information */
 	for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
@@ -4909,10 +4987,7 @@
 	 * Determine initial values for data_addr and data_cnt
 	 * for resuming the data phase.
 	 */
-	sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24)
-	      | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)
-	      | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)
-	      |	ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
+	sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
 	sgptr &= SG_PTR_MASK;
 
 	resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
@@ -4930,10 +5005,7 @@
 		dataptr = ahd_le64toh(sg->addr)
 			+ (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
 			- resid;
-		ahd_outb(ahd, HADDR + 7, dataptr >> 56);
-		ahd_outb(ahd, HADDR + 6, dataptr >> 48);
-		ahd_outb(ahd, HADDR + 5, dataptr >> 40);
-		ahd_outb(ahd, HADDR + 4, dataptr >> 32);
+		ahd_outl(ahd, HADDR + 4, dataptr >> 32);
 	} else {
 		struct	 ahd_dma_seg *sg;
 
@@ -4948,10 +5020,7 @@
 		ahd_outb(ahd, HADDR + 4,
 			 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
 	}
-	ahd_outb(ahd, HADDR + 3, dataptr >> 24);
-	ahd_outb(ahd, HADDR + 2, dataptr >> 16);
-	ahd_outb(ahd, HADDR + 1, dataptr >> 8);
-	ahd_outb(ahd, HADDR, dataptr);
+	ahd_outl(ahd, HADDR, dataptr);
 	ahd_outb(ahd, HCNT + 2, resid >> 16);
 	ahd_outb(ahd, HCNT + 1, resid >> 8);
 	ahd_outb(ahd, HCNT, resid);
@@ -5011,13 +5080,14 @@
 	ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
 		      AHD_TRANS_CUR, /*paused*/TRUE);
 	ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
-			 /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE);
+			 /*ppr_options*/0, AHD_TRANS_CUR,
+			 /*paused*/TRUE);
 	
-	ahd_send_async(ahd, devinfo->channel, devinfo->target,
-		       lun, AC_SENT_BDR, NULL);
+	if (status != CAM_SEL_TIMEOUT)
+		ahd_send_async(ahd, devinfo->channel, devinfo->target,
+			       CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
 
-	if (message != NULL
-	 && (verbose_level <= bootverbose))
+	if (message != NULL && bootverbose)
 		printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
 		       message, devinfo->channel, devinfo->target, found);
 }
@@ -5203,13 +5273,13 @@
 		/* FALLTHROUGH */
 	case 4:
 		ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
-				  ahd->shared_data_dmamap);
+				  ahd->shared_data_map.dmamap);
 		/* FALLTHROUGH */
 	case 3:
 		ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
-				ahd->shared_data_dmamap);
+				ahd->shared_data_map.dmamap);
 		ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
-				   ahd->shared_data_dmamap);
+				   ahd->shared_data_map.dmamap);
 		/* FALLTHROUGH */
 	case 2:
 		ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
@@ -5975,16 +6045,13 @@
 	newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
 	newcount = MIN(newcount, scb_data->sgs_left);
 	newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
-	scb_data->sense_left -= newcount;
-	scb_data->scbs_left -= newcount;
-	scb_data->sgs_left -= newcount;
 	for (i = 0; i < newcount; i++) {
-		u_int col_tag;
-
 		struct scb_platform_data *pdata;
+		u_int col_tag;
 #ifndef __linux__
 		int error;
 #endif
+
 		next_scb = (struct scb *)malloc(sizeof(*next_scb),
 						M_DEVBUF, M_NOWAIT);
 		if (next_scb == NULL)
@@ -6041,6 +6108,9 @@
 		sense_data += AHD_SENSE_BUFSIZE;
 		sense_busaddr += AHD_SENSE_BUFSIZE;
 		scb_data->numscbs++;
+		scb_data->sense_left--;
+		scb_data->scbs_left--;
+		scb_data->sgs_left--;
 	}
 }
 
@@ -6088,7 +6158,6 @@
 int
 ahd_init(struct ahd_softc *ahd)
 {
-	uint8_t		*base_vaddr;
 	uint8_t		*next_vaddr;
 	dma_addr_t	 next_baddr;
 	size_t		 driver_data_size;
@@ -6156,7 +6225,7 @@
 	 * for the target mode role, we must additionally provide space for
 	 * the incoming target command fifo.
 	 */
-	driver_data_size = AHD_SCB_MAX * sizeof(uint16_t)
+	driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
 			 + sizeof(struct hardware_scb);
 	if ((ahd->features & AHD_TARGETMODE) != 0)
 		driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6178,20 +6247,23 @@
 
 	/* Allocation of driver data */
 	if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
-			     (void **)&base_vaddr,
-			     BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) {
+			     (void **)&ahd->shared_data_map.vaddr,
+			     BUS_DMA_NOWAIT,
+			     &ahd->shared_data_map.dmamap) != 0) {
 		return (ENOMEM);
 	}
 
 	ahd->init_level++;
 
 	/* And permanently map it in */
-	ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
-			base_vaddr, driver_data_size, ahd_dmamap_cb,
-			&ahd->shared_data_busaddr, /*flags*/0);
-	ahd->qoutfifo = (uint16_t *)base_vaddr;
+	ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+			ahd->shared_data_map.vaddr, driver_data_size,
+			ahd_dmamap_cb, &ahd->shared_data_map.physaddr,
+			/*flags*/0);
+	ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
 	next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
-	next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t);
+	next_baddr = ahd->shared_data_map.physaddr
+		   + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
 	if ((ahd->features & AHD_TARGETMODE) != 0) {
 		ahd->targetcmds = (struct target_cmd *)next_vaddr;
 		next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6212,6 +6284,7 @@
 	 * specially from the DMA safe memory chunk used for the QOUTFIFO.
 	 */
 	ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
+	ahd->next_queued_hscb_map = &ahd->shared_data_map;
 	ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
 
 	ahd->init_level++;
@@ -6517,10 +6590,10 @@
 
 	/* All of our queues are empty */
 	ahd->qoutfifonext = 0;
-	ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE;
-	ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8);
+	ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
+	ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
 	for (i = 0; i < AHD_QOUT_SIZE; i++)
-		ahd->qoutfifo[i] = 0;
+		ahd->qoutfifo[i].valid_tag = 0;
 	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
 
 	ahd->qinfifonext = 0;
@@ -6553,24 +6626,22 @@
 	ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
 	ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
 	ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+	ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+	ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
 
 	/*
 	 * The Freeze Count is 0.
 	 */
+	ahd->qfreeze_cnt = 0;
 	ahd_outw(ahd, QFREEZE_COUNT, 0);
+	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
 
 	/*
 	 * Tell the sequencer where it can find our arrays in memory.
 	 */
-	busaddr = ahd->shared_data_busaddr;
-	ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF);
-	ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF);
-	ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);
-	ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);
-	ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);
-	ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);
-	ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);
-	ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);
+	busaddr = ahd->shared_data_map.physaddr;
+	ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
+	ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
 
 	/*
 	 * Setup the allowed SCSI Sequences based on operational mode.
@@ -6619,10 +6690,7 @@
 	 * Tell the sequencer which SCB will be the next one it receives.
 	 */
 	busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+	ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
 
 	/*
 	 * Default to coalescing disabled.
@@ -6926,43 +6994,34 @@
 {
 	u_int intstat;
 	u_int maxloops;
-	u_int qfreeze_cnt;
 
 	maxloops = 1000;
 	ahd->flags |= AHD_ALL_INTERRUPTS;
 	ahd_pause(ahd);
 	/*
-	 * Increment the QFreeze Count so that the sequencer
-	 * will not start new selections.  We do this only
+	 * Freeze the outgoing selections.  We do this only
 	 * until we are safely paused without further selections
 	 * pending.
 	 */
-	ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1);
+	ahd->qfreeze_cnt--;
+	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
 	ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
 	do {
-		struct scb *waiting_scb;
 
 		ahd_unpause(ahd);
+		/*
+		 * Give the sequencer some time to service
+		 * any active selections.
+		 */
+		ahd_delay(500);
+
 		ahd_intr(ahd);
 		ahd_pause(ahd);
-		ahd_clear_critical_section(ahd);
 		intstat = ahd_inb(ahd, INTSTAT);
-		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-		if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
-			ahd_outb(ahd, SCSISEQ0,
-				 ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
-		/*
-		 * In the non-packetized case, the sequencer (for Rev A),
-		 * relies on ENSELO remaining set after SELDO.  The hardware
-		 * auto-clears ENSELO in the packetized case.
-		 */
-		waiting_scb = ahd_lookup_scb(ahd,
-					     ahd_inw(ahd, WAITING_TID_HEAD));
-		if (waiting_scb != NULL
-		 && (waiting_scb->flags & SCB_PACKETIZED) == 0
-		 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)
-			ahd_outb(ahd, SCSISEQ0,
-				 ahd_inb(ahd, SCSISEQ0) | ENSELO);
+		if ((intstat & INT_PEND) == 0) {
+			ahd_clear_critical_section(ahd);
+			intstat = ahd_inb(ahd, INTSTAT);
+		}
 	} while (--maxloops
 	      && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
 	      && ((intstat & INT_PEND) != 0
@@ -6973,17 +7032,8 @@
 		printf("Infinite interrupt loop, INTSTAT = %x",
 		      ahd_inb(ahd, INTSTAT));
 	}
-	qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
-	if (qfreeze_cnt == 0) {
-		printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",
-		       ahd_name(ahd));
-	} else {
-		qfreeze_cnt--;
-	}
-	ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
-	if (qfreeze_cnt == 0)
-		ahd_outb(ahd, SEQ_FLAGS2,
-			 ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
+	ahd->qfreeze_cnt++;
+	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
 
 	ahd_flush_qoutfifo(ahd);
 
@@ -7155,10 +7205,7 @@
 		uint32_t busaddr;
 
 		busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);
-		ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-		ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-		ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-		ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+		ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
 	} else {
 		prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
 		ahd_sync_scb(ahd, prev_scb, 
@@ -7265,10 +7312,7 @@
 	 */
 	ahd->qinfifonext = qinstart;
 	busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-	ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+	ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
 
 	while (qinpos != qintail) {
 		scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
@@ -7330,6 +7374,7 @@
 	 * appropriate, traverse the SCBs of each "their id"
 	 * looking for matches.
 	 */
+	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
 	savedscbptr = ahd_get_scbptr(ahd);
 	tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
 	tid_prev = SCB_LIST_NULL;
@@ -7399,7 +7444,7 @@
 	u_int	prev;
 	int	found;
 
-	AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
 	found = 0;
 	prev = SCB_LIST_NULL;
 	next = *list_head;
@@ -7466,7 +7511,7 @@
 ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
 		    u_int tid_cur, u_int tid_next)
 {
-	AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
 
 	if (SCBID_IS_NULL(tid_cur)) {
 
@@ -7506,7 +7551,7 @@
 {
 	u_int tail_offset;
 
-	AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
 	if (!SCBID_IS_NULL(prev)) {
 		ahd_set_scbptr(ahd, prev);
 		ahd_outw(ahd, SCB_NEXT, next);
@@ -7739,7 +7784,7 @@
 	 */
 	ahd_clear_msg_state(ahd);
 	ahd_outb(ahd, SIMODE1,
-		 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
+		 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
 
 	if (initiate_reset)
 		ahd_reset_current_bus(ahd);
@@ -7910,30 +7955,35 @@
 void
 ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
 {
-	struct hardware_scb *hscb;
-	u_int  qfreeze_cnt;
+	struct	hardware_scb *hscb;
+	int	paused;
 
 	/*
 	 * The sequencer freezes its select-out queue
 	 * anytime a SCSI status error occurs.  We must
-	 * handle the error and decrement the QFREEZE count
-	 * to allow the sequencer to continue.
+	 * handle the error and increment our qfreeze count
+	 * to allow the sequencer to continue.  We don't
+	 * bother clearing critical sections here since all
+	 * operations are on data structures that the sequencer
+	 * is not touching once the queue is frozen.
 	 */
 	hscb = scb->hscb; 
 
+	if (ahd_is_paused(ahd)) {
+		paused = 1;
+	} else {
+		paused = 0;
+		ahd_pause(ahd);
+	}
+
 	/* Freeze the queue until the client sees the error. */
 	ahd_freeze_devq(ahd, scb);
 	ahd_freeze_scb(scb);
-	qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
-	if (qfreeze_cnt == 0) {
-		printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd));
-	} else {
-		qfreeze_cnt--;
-		ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
-	}
-	if (qfreeze_cnt == 0)
-		ahd_outb(ahd, SEQ_FLAGS2,
-			 ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
+	ahd->qfreeze_cnt++;
+	ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
+
+	if (paused == 0)
+		ahd_unpause(ahd);
 
 	/* Don't want to clobber the original sense code */
 	if ((scb->flags & SCB_SENSE) != 0) {
@@ -8317,8 +8367,7 @@
 	max_prog = 2048;
 
 	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
-	ahd_outb(ahd, PRGMCNT, 0);
-	ahd_outb(ahd, PRGMCNT+1, 0);
+	ahd_outw(ahd, PRGMCNT, 0);
 	for (i = 0; i < max_prog; i++) {
 		uint8_t ins_bytes[4];
 
@@ -8347,13 +8396,14 @@
 	u_int	sg_prefetch_cnt_limit;
 	u_int	sg_prefetch_align;
 	u_int	sg_size;
+	u_int	cacheline_mask;
 	uint8_t	download_consts[DOWNLOAD_CONST_COUNT];
 
 	if (bootverbose)
 		printf("%s: Downloading Sequencer Program...",
 		       ahd_name(ahd));
 
-#if DOWNLOAD_CONST_COUNT != 7
+#if DOWNLOAD_CONST_COUNT != 8
 #error "Download Const Mismatch"
 #endif
 	/*
@@ -8389,6 +8439,9 @@
 	/* Round down to the nearest power of 2. */
 	while (powerof2(sg_prefetch_align) == 0)
 		sg_prefetch_align--;
+
+	cacheline_mask = sg_prefetch_align - 1;
+
 	/*
 	 * If the cacheline boundary is greater than half our prefetch RAM
 	 * we risk not being able to fetch even a single complete S/G
@@ -8429,12 +8482,12 @@
 	download_consts[PKT_OVERRUN_BUFOFFSET] =
 		(ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
 	download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
+	download_consts[CACHELINE_MASK] = cacheline_mask;
 	cur_patch = patches;
 	downloaded = 0;
 	skip_addr = 0;
 	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
-	ahd_outb(ahd, PRGMCNT, 0);
-	ahd_outb(ahd, PRGMCNT+1, 0);
+	ahd_outw(ahd, PRGMCNT, 0);
 
 	for (i = 0; i < sizeof(seqprog)/4; i++) {
 		if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
@@ -8727,7 +8780,7 @@
 	printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
 	       "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
 	       ahd_name(ahd), 
-	       ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8),
+	       ahd_inw(ahd, CURADDR),
 	       ahd_build_mode_state(ahd, ahd->saved_src_mode,
 				    ahd->saved_dst_mode));
 	if (paused)
@@ -8843,6 +8896,15 @@
 		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
 	}
 	printf("\n");
+	printf("Sequencer On QFreeze and Complete list: ");
+	scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+	i = 0;
+	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
+		ahd_set_scbptr(ahd, scb_index);
+		printf("%d ", scb_index);
+		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+	}
+	printf("\n");
 	ahd_set_scbptr(ahd, saved_scb_index);
 	dffstat = ahd_inb(ahd, DFFSTAT);
 	for (i = 0; i < 2; i++) {
@@ -9077,7 +9139,7 @@
 {
 	int cnt;
 
-	cnt = 20;
+	cnt = 5000;
 	while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
 		ahd_delay(5);
 
@@ -9423,13 +9485,9 @@
 			if ((ahd->features & AHD_MULTI_TID) != 0) {
 				u_int targid_mask;
 
-				targid_mask = ahd_inb(ahd, TARGID)
-					    | (ahd_inb(ahd, TARGID + 1) << 8);
-
+				targid_mask = ahd_inw(ahd, TARGID);
 				targid_mask |= target_mask;
-				ahd_outb(ahd, TARGID, targid_mask);
-				ahd_outb(ahd, TARGID+1, (targid_mask >> 8));
-				
+				ahd_outw(ahd, TARGID, targid_mask);
 				ahd_update_scsiid(ahd, targid_mask);
 			} else {
 				u_int our_id;
@@ -9543,14 +9601,9 @@
 				if (ahd->features & AHD_MULTI_TID) {
 					u_int targid_mask;
 
-					targid_mask = ahd_inb(ahd, TARGID)
-						    | (ahd_inb(ahd, TARGID + 1)
-						       << 8);
-
+					targid_mask = ahd_inw(ahd, TARGID);
 					targid_mask &= ~target_mask;
-					ahd_outb(ahd, TARGID, targid_mask);
-					ahd_outb(ahd, TARGID+1,
-					 	 (targid_mask >> 8));
+					ahd_outw(ahd, TARGID, targid_mask);
 					ahd_update_scsiid(ahd, targid_mask);
 				}
 			}
@@ -9651,7 +9704,7 @@
 
 		cmd->cmd_valid = 0;
 		ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-				ahd->shared_data_dmamap,
+				ahd->shared_data_map.dmamap,
 				ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
 				sizeof(struct target_cmd),
 				BUS_DMASYNC_PREREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index d80bc51..91c4f7f 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $
  *
  * $FreeBSD$
  */
@@ -522,12 +522,21 @@
 static __inline uint16_t
 ahd_inw(struct ahd_softc *ahd, u_int port)
 {
+	/*
+	 * Read high byte first as some registers increment
+	 * or have other side effects when the low byte is
+	 * read.
+	 */
 	return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
 }
 
 static __inline void
 ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
 {
+	/*
+	 * Write low byte first to accomodate registers
+	 * such as PRGMCNT where the order maters.
+	 */
 	ahd_outb(ahd, port, value & 0xFF);
 	ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
 }
@@ -684,7 +693,7 @@
 	 * Razor #528
 	 */
 	value = ahd_inb(ahd, offset);
-	if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)
+	if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
 		ahd_inb(ahd, MODE_PTR);
 	return (value);
 }
@@ -727,7 +736,8 @@
 static __inline void
 ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
 {
-	struct hardware_scb *q_hscb;
+	struct	 hardware_scb *q_hscb;
+	struct	 map_node *q_hscb_map;
 	uint32_t saved_hscb_busaddr;
 
 	/*
@@ -743,6 +753,7 @@
 	 * locate the correct SCB by SCB_TAG.
 	 */
 	q_hscb = ahd->next_queued_hscb;
+	q_hscb_map = ahd->next_queued_hscb_map;
 	saved_hscb_busaddr = q_hscb->hscb_busaddr;
 	memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
 	q_hscb->hscb_busaddr = saved_hscb_busaddr;
@@ -750,7 +761,9 @@
 
 	/* Now swap HSCB pointers. */
 	ahd->next_queued_hscb = scb->hscb;
+	ahd->next_queued_hscb_map = scb->hscb_map;
 	scb->hscb = q_hscb;
+	scb->hscb_map = q_hscb_map;
 
 	/* Now define the mapping from tag to SCB in the scbindex */
 	ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
@@ -824,8 +837,9 @@
 static __inline void
 ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
 {
-	ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
-			/*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op);
+	ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+			/*offset*/0,
+			/*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
 }
 
 static __inline void
@@ -834,7 +848,7 @@
 #ifdef AHD_TARGET_MODE
 	if ((ahd->flags & AHD_TARGETROLE) != 0) {
 		ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-				ahd->shared_data_dmamap,
+				ahd->shared_data_map.dmamap,
 				ahd_targetcmd_offset(ahd, 0),
 				sizeof(struct target_cmd) * AHD_TMODE_CMDS,
 				op);
@@ -854,17 +868,17 @@
 	u_int retval;
 
 	retval = 0;
-	ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
-			/*offset*/ahd->qoutfifonext, /*len*/2,
-			BUS_DMASYNC_POSTREAD);
-	if ((ahd->qoutfifo[ahd->qoutfifonext]
-	     & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)
+	ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+			/*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
+			/*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
+	if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
+	  == ahd->qoutfifonext_valid_tag)
 		retval |= AHD_RUN_QOUTFIFO;
 #ifdef AHD_TARGET_MODE
 	if ((ahd->flags & AHD_TARGETROLE) != 0
 	 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
 		ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-				ahd->shared_data_dmamap,
+				ahd->shared_data_map.dmamap,
 				ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
 				/*len*/sizeof(struct target_cmd),
 				BUS_DMASYNC_POSTREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 1c8f872..2567e29 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1468,6 +1468,30 @@
 	if ((tstate->auto_negotiate & mask) != 0) {
 		scb->flags |= SCB_AUTO_NEGOTIATE;
 		scb->hscb->control |= MK_MESSAGE;
+		} else if (cmd->cmnd[0] == INQUIRY
+			&& (tinfo->curr.offset != 0
+			 || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT
+			 || tinfo->curr.ppr_options != 0)
+			&& (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {
+			/*
+			 * The SCSI spec requires inquiry
+			 * commands to complete without
+			 * reporting unit attention conditions.
+			 * Because of this, an inquiry command
+			 * that occurs just after a device is
+			 * reset will result in a data phase
+			 * with mismatched negotiated rates.
+			 * The core already forces a renegotiation
+			 * for reset events that are visible to
+			 * our controller or that we initiate,
+			 * but a third party device reset or a
+			 * hot-plug insertion can still cause this
+			 * issue.  Therefore, we force a re-negotiation
+			 * for every inquiry command unless we
+			 * are async.
+			 */
+			scb->flags |= SCB_NEGOTIATE;
+			scb->hscb->control |= MK_MESSAGE;
 	}
 
 	if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
@@ -2058,6 +2082,7 @@
 	int    paused;
 	int    wait;
 	int    disconnected;
+	int    found;
 	ahd_mode_state saved_modes;
 	unsigned long flags;
 
@@ -2176,7 +2201,8 @@
 	last_phase = ahd_inb(ahd, LASTPHASE);
 	saved_scbptr = ahd_get_scbptr(ahd);
 	active_scbptr = saved_scbptr;
-	if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
+	if (disconnected && ((last_phase != P_BUSFREE) || 
+			     (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
 		struct scb *bus_scb;
 
 		bus_scb = ahd_lookup_scb(ahd, active_scbptr);
@@ -2194,28 +2220,41 @@
 	 * bus or is in the disconnected state.
 	 */
 	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
-	if (last_phase != P_BUSFREE
-	 && (SCB_GET_TAG(pending_scb) == active_scbptr
+	if (SCB_GET_TAG(pending_scb) == active_scbptr
 	     || (flag == SCB_DEVICE_RESET
-		 && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) {
+		 && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
 
 		/*
 		 * We're active on the bus, so assert ATN
 		 * and hope that the target responds.
 		 */
 		pending_scb = ahd_lookup_scb(ahd, active_scbptr);
-		pending_scb->flags |= SCB_RECOVERY_SCB|flag;
+		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
 		ahd_outb(ahd, MSG_OUT, HOST_MSG);
 		ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
-		scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
+		scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n");
 		wait = TRUE;
+	} else if (last_phase != P_BUSFREE
+		   && ahd_inb(ahd, SCSIPHASE) == 0) {
+		/*
+		 * SCB is not identified, there
+		 * is no pending REQ, and the sequencer
+		 * has not seen a busfree.  Looks like
+		 * a stuck connection waiting to
+		 * go busfree.  Reset the bus.
+		 */
+		found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
+					  /*Initiate Reset*/TRUE);
+		printf("%s: Issued Channel %c Bus Reset. "
+		       "%d SCBs aborted\n", ahd_name(ahd),
+		       cmd->device->channel + 'A', found);
 	} else if (disconnected) {
 
 		/*
 		 * Actually re-queue this SCB in an attempt
 		 * to select the device before it reconnects.
 		 */
-		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
+		pending_scb->flags |= SCB_RECOVERY_SCB|flag;
 		ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
 		pending_scb->hscb->cdb_len = 0;
 		pending_scb->hscb->task_attribute = 0;
@@ -2296,16 +2335,17 @@
 		timer.expires = jiffies + (5 * HZ);
 		timer.function = ahd_linux_sem_timeout;
 		add_timer(&timer);
-		printf("Recovery code sleeping\n");
+		printf("%s: Recovery code sleeping\n", ahd_name(ahd));
 		down(&ahd->platform_data->eh_sem);
-		printf("Recovery code awake\n");
+		printf("%s: Recovery code awake\n", ahd_name(ahd));
         	ret = del_timer_sync(&timer);
 		if (ret == 0) {
-			printf("Timer Expired\n");
+			printf("%s: Timer Expired (active %d)\n",
+			       ahd_name(ahd), dev->active);
 			retval = FAILED;
 		}
 	}
-		ahd_unlock(ahd, &flags);
+	ahd_unlock(ahd, &flags);
 	return (retval);
 }
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index bc44222..cb74fcc 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -252,7 +252,7 @@
 /***************************** SMP support ************************************/
 #include <linux/spinlock.h>
 
-#define AIC79XX_DRIVER_VERSION "1.3.11"
+#define AIC79XX_DRIVER_VERSION "3.0"
 
 /*************************** Device Data Structures ***************************/
 /*
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 2131db6..196a634 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,9 +38,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $
  */
 
 #ifdef __linux__
@@ -114,6 +112,13 @@
 		"Adaptec 29320ALP Ultra320 SCSI adapter",
 		ahd_aic7901_setup
 	},
+	/* aic7901A based controllers */
+	{
+		ID_AHA_29320LP,
+		ID_ALL_MASK,
+		"Adaptec 29320LP Ultra320 SCSI adapter",
+		ahd_aic7901A_setup
+	},
 	/* aic7902 based controllers */	
 	{
 		ID_AHA_29320,
@@ -128,12 +133,6 @@
 		ahd_aic7902_setup
 	},
 	{
-		ID_AHA_29320LP,
-		ID_ALL_MASK,
-		"Adaptec 29320LP Ultra320 SCSI adapter",
-		ahd_aic7901A_setup
-	},
-	{
 		ID_AHA_39320,
 		ID_ALL_MASK,
 		"Adaptec 39320 Ultra320 SCSI adapter",
@@ -146,6 +145,12 @@
 		ahd_aic7902_setup
 	},
 	{
+		ID_AHA_39320_B_DELL,
+		ID_ALL_MASK,
+		"Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",
+		ahd_aic7902_setup
+	},
+	{
 		ID_AHA_39320A,
 		ID_ALL_MASK,
 		"Adaptec 39320A Ultra320 SCSI adapter",
@@ -668,6 +673,7 @@
 	 * Now set the termination based on what we found.
 	 */
 	sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
+	ahd->flags &= ~AHD_TERM_ENB_A;
 	if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
 		ahd->flags |= AHD_TERM_ENB_A;
 		sxfrctl1 |= STPWEN;
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h
index b5cfeab..da45153 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.h
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.h
@@ -53,14 +53,15 @@
 #define ID_AHA_29320ALP			0x8017900500449005ull
 
 #define ID_AIC7901A			0x801E9005FFFF9005ull
-#define ID_AHA_29320			0x8012900500429005ull
-#define ID_AHA_29320B			0x8013900500439005ull
 #define ID_AHA_29320LP			0x8014900500449005ull
 
 #define ID_AIC7902			0x801F9005FFFF9005ull
 #define ID_AIC7902_B			0x801D9005FFFF9005ull
 #define ID_AHA_39320			0x8010900500409005ull
+#define ID_AHA_29320			0x8012900500429005ull
+#define ID_AHA_29320B			0x8013900500439005ull
 #define ID_AHA_39320_B			0x8015900500409005ull
+#define ID_AHA_39320_B_DELL		0x8015900501681028ull
 #define ID_AHA_39320A			0x8016900500409005ull
 #define ID_AHA_39320D			0x8011900500419005ull
 #define ID_AHA_39320D_B			0x801C900500419005ull
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index c01ac39..8763b15 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
  */
 typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
 typedef struct ahd_reg_parse_entry {
@@ -83,13 +83,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrseqintstat_print;
-#else
-#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_seqintstat_print;
 #else
 #define ahd_seqintstat_print(regvalue, cur_col, wrap) \
@@ -97,6 +90,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_clrseqintstat_print;
+#else
+#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_swtimer_print;
 #else
 #define ahd_swtimer_print(regvalue, cur_col, wrap) \
@@ -412,13 +412,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_businitid_print;
-#else
-#define ahd_businitid_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dlcount_print;
 #else
 #define ahd_dlcount_print(regvalue, cur_col, wrap) \
@@ -426,6 +419,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_businitid_print;
+#else
+#define ahd_businitid_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_sxfrctl1_print;
 #else
 #define ahd_sxfrctl1_print(regvalue, cur_col, wrap) \
@@ -517,13 +517,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sblkctl_print;
-#else
-#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_optionmode_print;
 #else
 #define ahd_optionmode_print(regvalue, cur_col, wrap) \
@@ -531,10 +524,10 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sstat0_print;
+ahd_reg_print_t ahd_sblkctl_print;
 #else
-#define ahd_sstat0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
+#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -545,6 +538,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sstat0_print;
+#else
+#define ahd_sstat0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_simode0_print;
 #else
 #define ahd_simode0_print(regvalue, cur_col, wrap) \
@@ -573,13 +573,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint2_print;
-#else
-#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_simode2_print;
 #else
 #define ahd_simode2_print(regvalue, cur_col, wrap) \
@@ -587,6 +580,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_clrsint2_print;
+#else
+#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_perrdiag_print;
 #else
 #define ahd_perrdiag_print(regvalue, cur_col, wrap) \
@@ -685,13 +685,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqomode0_print;
-#else
-#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lqostat0_print;
 #else
 #define ahd_lqostat0_print(regvalue, cur_col, wrap) \
@@ -706,6 +699,20 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_lqomode0_print;
+#else
+#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_lqomode1_print;
+#else
+#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lqostat1_print;
 #else
 #define ahd_lqostat1_print(regvalue, cur_col, wrap) \
@@ -720,13 +727,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqomode1_print;
-#else
-#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lqostat2_print;
 #else
 #define ahd_lqostat2_print(regvalue, cur_col, wrap) \
@@ -909,13 +909,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scschkn_print;
-#else
-#define ahd_scschkn_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_annexdat_print;
 #else
 #define ahd_annexdat_print(regvalue, cur_col, wrap) \
@@ -923,6 +916,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_scschkn_print;
+#else
+#define ahd_scschkn_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_iownid_print;
 #else
 #define ahd_iownid_print(regvalue, cur_col, wrap) \
@@ -1000,13 +1000,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll400cnt0_print;
-#else
-#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_unfairness_print;
 #else
 #define ahd_unfairness_print(regvalue, cur_col, wrap) \
@@ -1014,6 +1007,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_pll400cnt0_print;
+#else
+#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_haddr_print;
 #else
 #define ahd_haddr_print(regvalue, cur_col, wrap) \
@@ -1056,13 +1056,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghaddr_print;
-#else
-#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scbhaddr_print;
 #else
 #define ahd_scbhaddr_print(regvalue, cur_col, wrap) \
@@ -1070,10 +1063,10 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghcnt_print;
+ahd_reg_print_t ahd_sghaddr_print;
 #else
-#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -1084,6 +1077,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sghcnt_print;
+#else
+#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dff_thrsh_print;
 #else
 #define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \
@@ -1154,13 +1154,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg1_print;
-#else
-#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmcrxmsg1_print;
 #else
 #define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \
@@ -1168,6 +1161,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dchrxmsg1_print;
+#else
+#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dchrxmsg2_print;
 #else
 #define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
@@ -1175,13 +1175,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg2_print;
-#else
-#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmcrxmsg2_print;
 #else
 #define ahd_cmcrxmsg2_print(regvalue, cur_col, wrap) \
@@ -1196,6 +1189,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ovlyrxmsg2_print;
+#else
+#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dchrxmsg3_print;
 #else
 #define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1203,6 +1203,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ovlyrxmsg3_print;
+#else
+#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmcrxmsg3_print;
 #else
 #define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1217,13 +1224,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg3_print;
-#else
-#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ovlyseqbcnt_print;
 #else
 #define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1231,13 +1231,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcseqbcnt_print;
-#else
-#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dchseqbcnt_print;
 #else
 #define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1245,6 +1238,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_cmcseqbcnt_print;
+#else
+#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmcspltstat0_print;
 #else
 #define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
@@ -1252,13 +1252,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyspltstat0_print;
-#else
-#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dchspltstat0_print;
 #else
 #define ahd_dchspltstat0_print(regvalue, cur_col, wrap) \
@@ -1266,10 +1259,10 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchspltstat1_print;
+ahd_reg_print_t ahd_ovlyspltstat0_print;
 #else
-#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -1287,6 +1280,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dchspltstat1_print;
+#else
+#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_sgrxmsg0_print;
 #else
 #define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \
@@ -1378,13 +1378,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sfunct_print;
-#else
-#define ahd_sfunct_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_sgspltstat1_print;
 #else
 #define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
@@ -1392,6 +1385,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sfunct_print;
+#else
+#define ahd_sfunct_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_df0pcistat_print;
 #else
 #define ahd_df0pcistat_print(regvalue, cur_col, wrap) \
@@ -1504,13 +1504,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbaddr_print;
-#else
-#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ccscbadr_bk_print;
 #else
 #define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
@@ -1518,6 +1511,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ccscbaddr_print;
+#else
+#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmc_rambist_print;
 #else
 #define ahd_cmc_rambist_print(regvalue, cur_col, wrap) \
@@ -1525,13 +1525,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccsgctl_print;
-#else
-#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ccscbctl_print;
 #else
 #define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
@@ -1539,6 +1532,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ccsgctl_print;
+#else
+#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_ccsgram_print;
 #else
 #define ahd_ccsgram_print(regvalue, cur_col, wrap) \
@@ -1707,13 +1707,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfptrs_print;
-#else
-#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_rcvrbiascalc_print;
 #else
 #define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \
@@ -1721,10 +1714,10 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfbkptr_print;
+ahd_reg_print_t ahd_dfptrs_print;
 #else
-#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -1735,6 +1728,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dfbkptr_print;
+#else
+#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dfdbctl_print;
 #else
 #define ahd_dfdbctl_print(regvalue, cur_col, wrap) \
@@ -1826,13 +1826,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr1_print;
-#else
-#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_brkaddr0_print;
 #else
 #define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
@@ -1840,6 +1833,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_brkaddr1_print;
+#else
+#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_allones_print;
 #else
 #define ahd_allones_print(regvalue, cur_col, wrap) \
@@ -1889,13 +1889,6 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_curaddr_print;
-#else
-#define ahd_curaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_intvec1_addr_print;
 #else
 #define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \
@@ -1903,10 +1896,10 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_intvec2_addr_print;
+ahd_reg_print_t ahd_curaddr_print;
 #else
-#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
+#define ahd_curaddr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -1917,6 +1910,13 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_intvec2_addr_print;
+#else
+#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_longjmp_addr_print;
 #else
 #define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \
@@ -1994,192 +1994,213 @@
 #endif
 
 #if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_complete_dma_scb_tail_print;
+#else
+#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_complete_on_qfreeze_head_print;
+#else
+#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_qfreeze_count_print;
 #else
 #define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_kernel_qfreeze_count_print;
+#else
+#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_saved_mode_print;
 #else
 #define ahd_saved_mode_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_msg_out_print;
 #else
 #define ahd_msg_out_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_dmaparams_print;
 #else
 #define ahd_dmaparams_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_seq_flags_print;
 #else
 #define ahd_seq_flags_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_saved_scsiid_print;
 #else
 #define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_saved_lun_print;
 #else
 #define ahd_saved_lun_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_lastphase_print;
 #else
 #define ahd_lastphase_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print;
 #else
 #define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_shared_data_addr_print;
-#else
-#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_qoutfifo_next_addr_print;
-#else
-#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_kernel_tqinpos_print;
 #else
 #define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_tqinpos_print;
 #else
 #define ahd_tqinpos_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_shared_data_addr_print;
+#else
+#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_qoutfifo_next_addr_print;
+#else
+#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_arg_1_print;
 #else
 #define ahd_arg_1_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_arg_2_print;
 #else
 #define ahd_arg_2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_last_msg_print;
 #else
 #define ahd_last_msg_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_scsiseq_template_print;
 #else
 #define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_initiator_tag_print;
 #else
 #define ahd_initiator_tag_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_seq_flags2_print;
 #else
 #define ahd_seq_flags2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_allocfifo_scbptr_print;
 #else
 #define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_int_coalescing_timer_print;
 #else
 #define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_int_coalescing_maxcmds_print;
 #else
 #define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_int_coalescing_mincmds_print;
 #else
 #define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmds_pending_print;
 #else
 #define ahd_cmds_pending_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_int_coalescing_cmdcount_print;
 #else
 #define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_local_hs_mailbox_print;
 #else
 #define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
 ahd_reg_print_t ahd_cmdsize_table_print;
 #else
 #define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap)
+    ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -2434,13 +2455,6 @@
 #define		HOST_TQINPOS    	0x80
 #define		ENINT_COALESCE  	0x40
 
-#define	CLRSEQINTSTAT   		0x0c
-#define		CLRSEQ_SWTMRTO  	0x10
-#define		CLRSEQ_SEQINT   	0x08
-#define		CLRSEQ_SCSIINT  	0x04
-#define		CLRSEQ_PCIINT   	0x02
-#define		CLRSEQ_SPLTINT  	0x01
-
 #define	SEQINTSTAT      		0x0c
 #define		SEQ_SWTMRTO     	0x10
 #define		SEQ_SEQINT      	0x08
@@ -2448,6 +2462,13 @@
 #define		SEQ_PCIINT      	0x02
 #define		SEQ_SPLTINT     	0x01
 
+#define	CLRSEQINTSTAT   		0x0c
+#define		CLRSEQ_SWTMRTO  	0x10
+#define		CLRSEQ_SEQINT   	0x08
+#define		CLRSEQ_SCSIINT  	0x04
+#define		CLRSEQ_PCIINT   	0x02
+#define		CLRSEQ_SPLTINT  	0x01
+
 #define	SWTIMER         		0x0e
 
 #define	SNSCB_QOFF      		0x10
@@ -2623,10 +2644,10 @@
 #define		BIOSCANCELEN    	0x10
 #define		SPIOEN          	0x08
 
-#define	BUSINITID       		0x3c
-
 #define	DLCOUNT         		0x3c
 
+#define	BUSINITID       		0x3c
+
 #define	SXFRCTL1        		0x3d
 #define		BITBUCKET       	0x80
 #define		ENSACHK         	0x40
@@ -2693,13 +2714,6 @@
 #define		SELID_MASK      	0xf0
 #define		ONEBIT          	0x08
 
-#define	SBLKCTL         		0x4a
-#define		DIAGLEDEN       	0x80
-#define		DIAGLEDON       	0x40
-#define		ENAB40          	0x08
-#define		ENAB20          	0x04
-#define		SELWIDE         	0x02
-
 #define	OPTIONMODE      		0x4a
 #define		OPTIONMODE_DEFAULTS	0x02
 #define		BIOSCANCTL      	0x80
@@ -2709,6 +2723,22 @@
 #define		ENDGFORMCHK     	0x04
 #define		AUTO_MSGOUT_DE  	0x02
 
+#define	SBLKCTL         		0x4a
+#define		DIAGLEDEN       	0x80
+#define		DIAGLEDON       	0x40
+#define		ENAB40          	0x08
+#define		ENAB20          	0x04
+#define		SELWIDE         	0x02
+
+#define	CLRSINT0        		0x4b
+#define		CLRSELDO        	0x40
+#define		CLRSELDI        	0x20
+#define		CLRSELINGO      	0x10
+#define		CLRIOERR        	0x08
+#define		CLROVERRUN      	0x04
+#define		CLRSPIORDY      	0x02
+#define		CLRARBDO        	0x01
+
 #define	SSTAT0          		0x4b
 #define		TARGET          	0x80
 #define		SELDO           	0x40
@@ -2719,15 +2749,6 @@
 #define		SPIORDY         	0x02
 #define		ARBDO           	0x01
 
-#define	CLRSINT0        		0x4b
-#define		CLRSELDO        	0x40
-#define		CLRSELDI        	0x20
-#define		CLRSELINGO      	0x10
-#define		CLRIOERR        	0x08
-#define		CLROVERRUN      	0x04
-#define		CLRSPIORDY      	0x02
-#define		CLRARBDO        	0x01
-
 #define	SIMODE0         		0x4b
 #define		ENSELDO         	0x40
 #define		ENSELDI         	0x20
@@ -2768,17 +2789,17 @@
 #define		BUSFREE_DFF0    	0x80
 #define		BUSFREE_LQO     	0x40
 
+#define	SIMODE2         		0x4d
+#define		ENWIDE_RES      	0x04
+#define		ENSDONE         	0x02
+#define		ENDMADONE       	0x01
+
 #define	CLRSINT2        		0x4d
 #define		CLRNONPACKREQ   	0x20
 #define		CLRWIDE_RES     	0x04
 #define		CLRSDONE        	0x02
 #define		CLRDMADONE      	0x01
 
-#define	SIMODE2         		0x4d
-#define		ENWIDE_RES      	0x04
-#define		ENSDONE         	0x02
-#define		ENDMADONE       	0x01
-
 #define	PERRDIAG        		0x4e
 #define		HIZERO          	0x80
 #define		HIPERR          	0x40
@@ -2871,13 +2892,6 @@
 #define		CLRNTRAMPERR    	0x02
 #define		CLROSRAMPERR    	0x01
 
-#define	LQOMODE0        		0x54
-#define		ENLQOTARGSCBPERR	0x10
-#define		ENLQOSTOPT2     	0x08
-#define		ENLQOATNLQ      	0x04
-#define		ENLQOATNPKT     	0x02
-#define		ENLQOTCRC       	0x01
-
 #define	LQOSTAT0        		0x54
 #define		LQOTARGSCBPERR  	0x10
 #define		LQOSTOPT2       	0x08
@@ -2892,6 +2906,20 @@
 #define		CLRLQOATNPKT    	0x02
 #define		CLRLQOTCRC      	0x01
 
+#define	LQOMODE0        		0x54
+#define		ENLQOTARGSCBPERR	0x10
+#define		ENLQOSTOPT2     	0x08
+#define		ENLQOATNLQ      	0x04
+#define		ENLQOATNPKT     	0x02
+#define		ENLQOTCRC       	0x01
+
+#define	LQOMODE1        		0x55
+#define		ENLQOINITSCBPERR	0x10
+#define		ENLQOSTOPI2     	0x08
+#define		ENLQOBADQAS     	0x04
+#define		ENLQOBUSFREE    	0x02
+#define		ENLQOPHACHGINPKT	0x01
+
 #define	LQOSTAT1        		0x55
 #define		LQOINITSCBPERR  	0x10
 #define		LQOSTOPI2       	0x08
@@ -2906,13 +2934,6 @@
 #define		CLRLQOBUSFREE   	0x02
 #define		CLRLQOPHACHGINPKT	0x01
 
-#define	LQOMODE1        		0x55
-#define		ENLQOINITSCBPERR	0x10
-#define		ENLQOSTOPI2     	0x08
-#define		ENLQOBADQAS     	0x04
-#define		ENLQOBUSFREE    	0x02
-#define		ENLQOPHACHGINPKT	0x01
-
 #define	LQOSTAT2        		0x56
 #define		LQOPKT          	0xe0
 #define		LQOWAITFIFO     	0x10
@@ -3028,6 +3049,8 @@
 
 #define	ANNEXCOL        		0x65
 
+#define	ANNEXDAT        		0x66
+
 #define	SCSCHKN         		0x66
 #define		STSELSKIDDIS    	0x40
 #define		CURRFIFODEF     	0x20
@@ -3037,8 +3060,6 @@
 #define		SHVALIDSTDIS    	0x02
 #define		LSTSGCLRDIS     	0x01
 
-#define	ANNEXDAT        		0x66
-
 #define	IOWNID          		0x67
 
 #define	PLL960CTL0      		0x68
@@ -3071,10 +3092,10 @@
 #define		PLL_CNTCLR      	0x40
 #define		PLL_RST         	0x01
 
-#define	PLL400CNT0      		0x6e
-
 #define	UNFAIRNESS      		0x6e
 
+#define	PLL400CNT0      		0x6e
+
 #define	HADDR           		0x70
 
 #define	PLLDELAY        		0x70
@@ -3088,14 +3109,14 @@
 
 #define	HODMAEN         		0x7a
 
-#define	SGHADDR         		0x7c
-
 #define	SCBHADDR        		0x7c
 
-#define	SGHCNT          		0x84
+#define	SGHADDR         		0x7c
 
 #define	SCBHCNT         		0x84
 
+#define	SGHCNT          		0x84
+
 #define	DFF_THRSH       		0x88
 #define		WR_DFTHRSH      	0x70
 #define		RD_DFTHRSH      	0x07
@@ -3113,8 +3134,8 @@
 #define		RD_DFTHRSH_63   	0x03
 #define		RD_DFTHRSH_50   	0x02
 #define		RD_DFTHRSH_25   	0x01
-#define		WR_DFTHRSH_MIN  	0x00
 #define		RD_DFTHRSH_MIN  	0x00
+#define		WR_DFTHRSH_MIN  	0x00
 
 #define	ROMADDR         		0x8a
 
@@ -3150,20 +3171,22 @@
 #define		DCH1NSEN        	0x02
 #define		DCH0NSEN        	0x01
 
-#define	DCHRXMSG1       		0x91
-
 #define	CMCRXMSG1       		0x91
 
-#define	DCHRXMSG2       		0x92
+#define	DCHRXMSG1       		0x91
 
-#define	OVLYRXMSG2      		0x92
+#define	DCHRXMSG2       		0x92
 
 #define	CMCRXMSG2       		0x92
 
 #define	OST             		0x92
 
+#define	OVLYRXMSG2      		0x92
+
 #define	DCHRXMSG3       		0x93
 
+#define	OVLYRXMSG3      		0x93
+
 #define	CMCRXMSG3       		0x93
 
 #define	PCIXCTL         		0x93
@@ -3175,26 +3198,24 @@
 #define		TSCSERREN       	0x02
 #define		CMPABCDIS       	0x01
 
-#define	OVLYRXMSG3      		0x93
-
 #define	OVLYSEQBCNT     		0x94
 
-#define	CMCSEQBCNT      		0x94
-
 #define	DCHSEQBCNT      		0x94
 
-#define	CMCSPLTSTAT0    		0x96
+#define	CMCSEQBCNT      		0x94
 
-#define	OVLYSPLTSTAT0   		0x96
+#define	CMCSPLTSTAT0    		0x96
 
 #define	DCHSPLTSTAT0    		0x96
 
-#define	DCHSPLTSTAT1    		0x97
+#define	OVLYSPLTSTAT0   		0x96
 
 #define	CMCSPLTSTAT1    		0x97
 
 #define	OVLYSPLTSTAT1   		0x97
 
+#define	DCHSPLTSTAT1    		0x97
+
 #define	SGRXMSG0        		0x98
 #define		CDNUM           	0xf8
 #define		CFNUM           	0x07
@@ -3244,13 +3265,13 @@
 #define		RXSCEMSG        	0x02
 #define		RXSPLTRSP       	0x01
 
+#define	SGSPLTSTAT1     		0x9f
+#define		RXDATABUCKET    	0x01
+
 #define	SFUNCT          		0x9f
 #define		TEST_GROUP      	0xf0
 #define		TEST_NUM        	0x0f
 
-#define	SGSPLTSTAT1     		0x9f
-#define		RXDATABUCKET    	0x01
-
 #define	DF0PCISTAT      		0xa0
 
 #define	REG0            		0xa0
@@ -3299,10 +3320,10 @@
 
 #define	CCSGADDR        		0xac
 
-#define	CCSCBADDR       		0xac
-
 #define	CCSCBADR_BK     		0xac
 
+#define	CCSCBADDR       		0xac
+
 #define	CMC_RAMBIST     		0xad
 #define		SG_ELEMENT_SIZE 	0x80
 #define		SCBRAMBIST_FAIL 	0x40
@@ -3311,14 +3332,6 @@
 #define		CMC_BUFFER_BIST_FAIL	0x02
 #define		CMC_BUFFER_BIST_EN	0x01
 
-#define	CCSGCTL         		0xad
-#define		CCSGEN          	0x0c
-#define		CCSGDONE        	0x80
-#define		SG_CACHE_AVAIL  	0x10
-#define		CCSGENACK       	0x08
-#define		SG_FETCH_REQ    	0x02
-#define		CCSGRESET       	0x01
-
 #define	CCSCBCTL        		0xad
 #define		CCSCBDONE       	0x80
 #define		ARRDONE         	0x40
@@ -3327,6 +3340,14 @@
 #define		CCSCBDIR        	0x04
 #define		CCSCBRESET      	0x01
 
+#define	CCSGCTL         		0xad
+#define		CCSGEN          	0x0c
+#define		CCSGDONE        	0x80
+#define		SG_CACHE_AVAIL  	0x10
+#define		CCSGENACK       	0x08
+#define		SG_FETCH_REQ    	0x02
+#define		CCSGRESET       	0x01
+
 #define	CCSGRAM         		0xb0
 
 #define	FLEXADR         		0xb0
@@ -3356,8 +3377,8 @@
 #define	SEEDAT          		0xbc
 
 #define	SEECTL          		0xbe
-#define		SEEOP_EWEN      	0x40
 #define		SEEOP_WALL      	0x40
+#define		SEEOP_EWEN      	0x40
 #define		SEEOP_EWDS      	0x40
 #define		SEEOPCODE       	0x70
 #define		SEERST          	0x02
@@ -3414,14 +3435,14 @@
 
 #define	WRTBIASCALC     		0xc7
 
-#define	DFPTRS          		0xc8
-
 #define	RCVRBIASCALC    		0xc8
 
-#define	DFBKPTR         		0xc9
+#define	DFPTRS          		0xc8
 
 #define	SKEWCALC        		0xc9
 
+#define	DFBKPTR         		0xc9
+
 #define	DFDBCTL         		0xcb
 #define		DFF_CIO_WR_RDY  	0x20
 #define		DFF_CIO_RD_RDY  	0x10
@@ -3475,11 +3496,11 @@
 
 #define	DINDEX          		0xe4
 
+#define	BRKADDR0        		0xe6
+
 #define	BRKADDR1        		0xe6
 #define		BRKDIS          	0x80
 
-#define	BRKADDR0        		0xe6
-
 #define	ALLONES         		0xe8
 
 #define	ALLZEROS        		0xea
@@ -3494,14 +3515,14 @@
 
 #define	STACK           		0xf2
 
-#define	CURADDR         		0xf4
-
 #define	INTVEC1_ADDR    		0xf4
 
-#define	INTVEC2_ADDR    		0xf6
+#define	CURADDR         		0xf4
 
 #define	LASTADDR        		0xf6
 
+#define	INTVEC2_ADDR    		0xf6
+
 #define	LONGJMP_ADDR    		0xf8
 
 #define	ACCUM_SAVE      		0xfa
@@ -3524,25 +3545,31 @@
 
 #define	COMPLETE_DMA_SCB_HEAD		0x12c
 
-#define	QFREEZE_COUNT   		0x12e
+#define	COMPLETE_DMA_SCB_TAIL		0x12e
 
-#define	SAVED_MODE      		0x130
+#define	COMPLETE_ON_QFREEZE_HEAD		0x130
 
-#define	MSG_OUT         		0x131
+#define	QFREEZE_COUNT   		0x132
 
-#define	DMAPARAMS       		0x132
+#define	KERNEL_QFREEZE_COUNT		0x134
+
+#define	SAVED_MODE      		0x136
+
+#define	MSG_OUT         		0x137
+
+#define	DMAPARAMS       		0x138
 #define		PRELOADEN       	0x80
 #define		WIDEODD         	0x40
 #define		SCSIEN          	0x20
 #define		SDMAEN          	0x10
 #define		SDMAENACK       	0x10
-#define		HDMAENACK       	0x08
 #define		HDMAEN          	0x08
+#define		HDMAENACK       	0x08
 #define		DIRECTION       	0x04
 #define		FIFOFLUSH       	0x02
 #define		FIFORESET       	0x01
 
-#define	SEQ_FLAGS       		0x133
+#define	SEQ_FLAGS       		0x139
 #define		NOT_IDENTIFIED  	0x80
 #define		NO_CDB_SENT     	0x40
 #define		TARGET_CMD_IS_TAGGED	0x40
@@ -3553,11 +3580,11 @@
 #define		SPHASE_PENDING  	0x02
 #define		NO_DISCONNECT   	0x01
 
-#define	SAVED_SCSIID    		0x134
+#define	SAVED_SCSIID    		0x13a
 
-#define	SAVED_LUN       		0x135
+#define	SAVED_LUN       		0x13b
 
-#define	LASTPHASE       		0x136
+#define	LASTPHASE       		0x13c
 #define		PHASE_MASK      	0xe0
 #define		CDI             	0x80
 #define		IOI             	0x40
@@ -3572,18 +3599,18 @@
 #define		P_DATAOUT_DT    	0x20
 #define		P_DATAOUT       	0x00
 
-#define	QOUTFIFO_ENTRY_VALID_TAG		0x137
+#define	QOUTFIFO_ENTRY_VALID_TAG		0x13d
 
-#define	SHARED_DATA_ADDR		0x138
+#define	KERNEL_TQINPOS  		0x13e
 
-#define	QOUTFIFO_NEXT_ADDR		0x13c
+#define	TQINPOS         		0x13f
 
-#define	KERNEL_TQINPOS  		0x140
+#define	SHARED_DATA_ADDR		0x140
 
-#define	TQINPOS         		0x141
+#define	QOUTFIFO_NEXT_ADDR		0x144
 
-#define	ARG_1           		0x142
-#define	RETURN_1        		0x142
+#define	ARG_1           		0x148
+#define	RETURN_1        		0x148
 #define		SEND_MSG        	0x80
 #define		SEND_SENSE      	0x40
 #define		SEND_REJ        	0x20
@@ -3593,12 +3620,12 @@
 #define		CONT_MSG_LOOP_READ	0x03
 #define		CONT_MSG_LOOP_TARG	0x02
 
-#define	ARG_2           		0x143
-#define	RETURN_2        		0x143
+#define	ARG_2           		0x149
+#define	RETURN_2        		0x149
 
-#define	LAST_MSG        		0x144
+#define	LAST_MSG        		0x14a
 
-#define	SCSISEQ_TEMPLATE		0x145
+#define	SCSISEQ_TEMPLATE		0x14b
 #define		MANUALCTL       	0x40
 #define		ENSELI          	0x20
 #define		ENRSELI         	0x10
@@ -3606,27 +3633,27 @@
 #define		ENAUTOATNP      	0x02
 #define		ALTSTIM         	0x01
 
-#define	INITIATOR_TAG   		0x146
+#define	INITIATOR_TAG   		0x14c
 
-#define	SEQ_FLAGS2      		0x147
+#define	SEQ_FLAGS2      		0x14d
 #define		SELECTOUT_QFROZEN	0x04
 #define		TARGET_MSG_PENDING	0x02
 
-#define	ALLOCFIFO_SCBPTR		0x148
+#define	ALLOCFIFO_SCBPTR		0x14e
 
-#define	INT_COALESCING_TIMER		0x14a
+#define	INT_COALESCING_TIMER		0x150
 
-#define	INT_COALESCING_MAXCMDS		0x14c
+#define	INT_COALESCING_MAXCMDS		0x152
 
-#define	INT_COALESCING_MINCMDS		0x14d
+#define	INT_COALESCING_MINCMDS		0x153
 
-#define	CMDS_PENDING    		0x14e
+#define	CMDS_PENDING    		0x154
 
-#define	INT_COALESCING_CMDCOUNT		0x150
+#define	INT_COALESCING_CMDCOUNT		0x156
 
-#define	LOCAL_HS_MAILBOX		0x151
+#define	LOCAL_HS_MAILBOX		0x157
 
-#define	CMDSIZE_TABLE   		0x152
+#define	CMDSIZE_TABLE   		0x158
 
 #define	SCB_BASE        		0x180
 
@@ -3701,6 +3728,16 @@
 #define	SCB_DISCONNECTED_LISTS		0x1b8
 
 
+#define	AHD_TIMER_MAX_US	0x18ffe7
+#define	AHD_TIMER_MAX_TICKS	0xffff
+#define	AHD_SENSE_BUFSIZE	0x100
+#define	BUS_8_BIT	0x00
+#define	TARGET_CMD_CMPLT	0xfe
+#define	SEEOP_WRAL_ADDR	0x40
+#define	AHD_AMPLITUDE_DEF	0x07
+#define	AHD_PRECOMP_CUTBACK_37	0x07
+#define	AHD_PRECOMP_SHIFT	0x00
+#define	AHD_ANNEXCOL_PRECOMP_SLEW	0x04
 #define	AHD_TIMER_US_PER_TICK	0x19
 #define	SCB_TRANSFER_SIZE_FULL_LUN	0x38
 #define	STATUS_QUEUE_FULL	0x28
@@ -3724,28 +3761,18 @@
 #define	B_CURRFIFO_0	0x02
 #define	LUNLEN_SINGLE_LEVEL_LUN	0x0f
 #define	NVRAM_SCB_OFFSET	0x2c
-#define	AHD_TIMER_MAX_US	0x18ffe7
-#define	AHD_TIMER_MAX_TICKS	0xffff
 #define	STATUS_PKT_SENSE	0xff
 #define	CMD_GROUP_CODE_SHIFT	0x05
-#define	AHD_SENSE_BUFSIZE	0x100
 #define	MAX_OFFSET_PACED_BUG	0x7f
-#define	BUS_8_BIT	0x00
 #define	STIMESEL_BUG_ADJ	0x08
 #define	STIMESEL_MIN	0x18
 #define	STIMESEL_SHIFT	0x03
 #define	CCSGRAM_MAXSEGS	0x10
 #define	INVALID_ADDR	0x80
-#define	TARGET_CMD_CMPLT	0xfe
-#define	SEEOP_WRAL_ADDR	0x40
 #define	SEEOP_ERAL_ADDR	0x80
-#define	AHD_AMPLITUDE_DEF	0x07
 #define	AHD_SLEWRATE_DEF_REVB	0x08
-#define	AHD_PRECOMP_CUTBACK_37	0x07
 #define	AHD_PRECOMP_CUTBACK_17	0x04
-#define	AHD_PRECOMP_SHIFT	0x00
 #define	AHD_PRECOMP_MASK	0x07
-#define	AHD_ANNEXCOL_PRECOMP_SLEW	0x04
 #define	SRC_MODE_SHIFT	0x00
 #define	PKT_OVERRUN_BUFSIZE	0x200
 #define	SCB_TRANSFER_SIZE_1BYTE_LUN	0x30
@@ -3761,6 +3788,7 @@
 
 
 /* Downloaded Constant Definitions */
+#define	CACHELINE_MASK	0x07
 #define	SCB_TRANSFER_SIZE	0x06
 #define	PKT_OVERRUN_BUFOFFSET	0x05
 #define	SG_SIZEOF	0x04
@@ -3768,9 +3796,9 @@
 #define	SG_PREFETCH_ALIGN_MASK	0x02
 #define	SG_PREFETCH_CNT_LIMIT	0x01
 #define	SG_PREFETCH_CNT	0x00
-#define	DOWNLOAD_CONST_COUNT	0x07
+#define	DOWNLOAD_CONST_COUNT	0x08
 
 
 /* Exported Labels */
-#define	LABEL_seq_isr 	0x269
-#define	LABEL_timer_isr	0x265
+#define	LABEL_seq_isr 	0x285
+#define	LABEL_timer_isr	0x281
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index 3098a75..a4137c9 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $
  */
 
 #include "aic79xx_osm.h"
@@ -172,21 +172,6 @@
 	    0x0b, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
-	{ "CLRSEQ_SPLTINT",	0x01, 0x01 },
-	{ "CLRSEQ_PCIINT",	0x02, 0x02 },
-	{ "CLRSEQ_SCSIINT",	0x04, 0x04 },
-	{ "CLRSEQ_SEQINT",	0x08, 0x08 },
-	{ "CLRSEQ_SWTMRTO",	0x10, 0x10 }
-};
-
-int
-ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
-	    0x0c, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
 	{ "SEQ_SPLTINT",	0x01, 0x01 },
 	{ "SEQ_PCIINT",		0x02, 0x02 },
@@ -202,6 +187,21 @@
 	    0x0c, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
+	{ "CLRSEQ_SPLTINT",	0x01, 0x01 },
+	{ "CLRSEQ_PCIINT",	0x02, 0x02 },
+	{ "CLRSEQ_SCSIINT",	0x04, 0x04 },
+	{ "CLRSEQ_SEQINT",	0x08, 0x08 },
+	{ "CLRSEQ_SWTMRTO",	0x10, 0x10 }
+};
+
+int
+ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
+	    0x0c, regvalue, cur_col, wrap));
+}
+
 int
 ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -670,16 +670,16 @@
 }
 
 int
-ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "BUSINITID",
+	return (ahd_print_register(NULL, 0, "DLCOUNT",
 	    0x3c, regvalue, cur_col, wrap));
 }
 
 int
-ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "DLCOUNT",
+	return (ahd_print_register(NULL, 0, "BUSINITID",
 	    0x3c, regvalue, cur_col, wrap));
 }
 
@@ -859,21 +859,6 @@
 	    0x49, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
-	{ "SELWIDE",		0x02, 0x02 },
-	{ "ENAB20",		0x04, 0x04 },
-	{ "ENAB40",		0x08, 0x08 },
-	{ "DIAGLEDON",		0x40, 0x40 },
-	{ "DIAGLEDEN",		0x80, 0x80 }
-};
-
-int
-ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
-	    0x4a, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
 	{ "AUTO_MSGOUT_DE",	0x02, 0x02 },
 	{ "ENDGFORMCHK",	0x04, 0x04 },
@@ -891,22 +876,19 @@
 	    0x4a, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
-	{ "ARBDO",		0x01, 0x01 },
-	{ "SPIORDY",		0x02, 0x02 },
-	{ "OVERRUN",		0x04, 0x04 },
-	{ "IOERR",		0x08, 0x08 },
-	{ "SELINGO",		0x10, 0x10 },
-	{ "SELDI",		0x20, 0x20 },
-	{ "SELDO",		0x40, 0x40 },
-	{ "TARGET",		0x80, 0x80 }
+static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
+	{ "SELWIDE",		0x02, 0x02 },
+	{ "ENAB20",		0x04, 0x04 },
+	{ "ENAB40",		0x08, 0x08 },
+	{ "DIAGLEDON",		0x40, 0x40 },
+	{ "DIAGLEDEN",		0x80, 0x80 }
 };
 
 int
-ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
-	    0x4b, regvalue, cur_col, wrap));
+	return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
+	    0x4a, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
@@ -926,6 +908,24 @@
 	    0x4b, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
+	{ "ARBDO",		0x01, 0x01 },
+	{ "SPIORDY",		0x02, 0x02 },
+	{ "OVERRUN",		0x04, 0x04 },
+	{ "IOERR",		0x08, 0x08 },
+	{ "SELINGO",		0x10, 0x10 },
+	{ "SELDI",		0x20, 0x20 },
+	{ "SELDO",		0x40, 0x40 },
+	{ "TARGET",		0x80, 0x80 }
+};
+
+int
+ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
+	    0x4b, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
 	{ "ENARBDO",		0x01, 0x01 },
 	{ "ENSPIORDY",		0x02, 0x02 },
@@ -998,6 +998,19 @@
 	    0x4d, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
+	{ "ENDMADONE",		0x01, 0x01 },
+	{ "ENSDONE",		0x02, 0x02 },
+	{ "ENWIDE_RES",		0x04, 0x04 }
+};
+
+int
+ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
+	    0x4d, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
 	{ "CLRDMADONE",		0x01, 0x01 },
 	{ "CLRSDONE",		0x02, 0x02 },
@@ -1012,19 +1025,6 @@
 	    0x4d, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
-	{ "ENDMADONE",		0x01, 0x01 },
-	{ "ENSDONE",		0x02, 0x02 },
-	{ "ENWIDE_RES",		0x04, 0x04 }
-};
-
-int
-ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
-	    0x4d, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t PERRDIAG_parse_table[] = {
 	{ "DTERR",		0x01, 0x01 },
 	{ "DGFORMERR",		0x02, 0x02 },
@@ -1220,21 +1220,6 @@
 	    0x53, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
-	{ "ENLQOTCRC",		0x01, 0x01 },
-	{ "ENLQOATNPKT",	0x02, 0x02 },
-	{ "ENLQOATNLQ",		0x04, 0x04 },
-	{ "ENLQOSTOPT2",	0x08, 0x08 },
-	{ "ENLQOTARGSCBPERR",	0x10, 0x10 }
-};
-
-int
-ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
-	    0x54, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
 	{ "LQOTCRC",		0x01, 0x01 },
 	{ "LQOATNPKT",		0x02, 0x02 },
@@ -1265,6 +1250,36 @@
 	    0x54, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
+	{ "ENLQOTCRC",		0x01, 0x01 },
+	{ "ENLQOATNPKT",	0x02, 0x02 },
+	{ "ENLQOATNLQ",		0x04, 0x04 },
+	{ "ENLQOSTOPT2",	0x08, 0x08 },
+	{ "ENLQOTARGSCBPERR",	0x10, 0x10 }
+};
+
+int
+ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
+	    0x54, regvalue, cur_col, wrap));
+}
+
+static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
+	{ "ENLQOPHACHGINPKT",	0x01, 0x01 },
+	{ "ENLQOBUSFREE",	0x02, 0x02 },
+	{ "ENLQOBADQAS",	0x04, 0x04 },
+	{ "ENLQOSTOPI2",	0x08, 0x08 },
+	{ "ENLQOINITSCBPERR",	0x10, 0x10 }
+};
+
+int
+ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
+	    0x55, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
 	{ "LQOPHACHGINPKT",	0x01, 0x01 },
 	{ "LQOBUSFREE",		0x02, 0x02 },
@@ -1295,21 +1310,6 @@
 	    0x55, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
-	{ "ENLQOPHACHGINPKT",	0x01, 0x01 },
-	{ "ENLQOBUSFREE",	0x02, 0x02 },
-	{ "ENLQOBADQAS",	0x04, 0x04 },
-	{ "ENLQOSTOPI2",	0x08, 0x08 },
-	{ "ENLQOINITSCBPERR",	0x10, 0x10 }
-};
-
-int
-ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
-	    0x55, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
 	{ "LQOSTOP0",		0x01, 0x01 },
 	{ "LQOPHACHGOUTPKT",	0x02, 0x02 },
@@ -1594,6 +1594,13 @@
 	    0x65, regvalue, cur_col, wrap));
 }
 
+int
+ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "ANNEXDAT",
+	    0x66, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
 	{ "LSTSGCLRDIS",	0x01, 0x01 },
 	{ "SHVALIDSTDIS",	0x02, 0x02 },
@@ -1612,13 +1619,6 @@
 }
 
 int
-ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "ANNEXDAT",
-	    0x66, regvalue, cur_col, wrap));
-}
-
-int
 ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "IOWNID",
@@ -1728,16 +1728,16 @@
 }
 
 int
-ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "PLL400CNT0",
+	return (ahd_print_register(NULL, 0, "UNFAIRNESS",
 	    0x6e, regvalue, cur_col, wrap));
 }
 
 int
-ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "UNFAIRNESS",
+	return (ahd_print_register(NULL, 0, "PLL400CNT0",
 	    0x6e, regvalue, cur_col, wrap));
 }
 
@@ -1788,13 +1788,6 @@
 }
 
 int
-ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "SGHADDR",
-	    0x7c, regvalue, cur_col, wrap));
-}
-
-int
 ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "SCBHADDR",
@@ -1802,10 +1795,10 @@
 }
 
 int
-ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "SGHCNT",
-	    0x84, regvalue, cur_col, wrap));
+	return (ahd_print_register(NULL, 0, "SGHADDR",
+	    0x7c, regvalue, cur_col, wrap));
 }
 
 int
@@ -1815,6 +1808,13 @@
 	    0x84, regvalue, cur_col, wrap));
 }
 
+int
+ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "SGHCNT",
+	    0x84, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t DFF_THRSH_parse_table[] = {
 	{ "WR_DFTHRSH_MIN",	0x00, 0x70 },
 	{ "RD_DFTHRSH_MIN",	0x00, 0x07 },
@@ -1950,17 +1950,6 @@
 	    0x91, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
-	{ "CBNUM",		0xff, 0xff }
-};
-
-int
-ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
-	    0x91, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
 	{ "CBNUM",		0xff, 0xff }
 };
@@ -1972,6 +1961,17 @@
 	    0x91, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
+	{ "CBNUM",		0xff, 0xff }
+};
+
+int
+ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
+	    0x91, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t DCHRXMSG2_parse_table[] = {
 	{ "MINDEX",		0xff, 0xff }
 };
@@ -1983,17 +1983,6 @@
 	    0x92, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
-	{ "MINDEX",		0xff, 0xff }
-};
-
-int
-ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
-	    0x92, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = {
 	{ "MINDEX",		0xff, 0xff }
 };
@@ -2012,6 +2001,17 @@
 	    0x92, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
+	{ "MINDEX",		0xff, 0xff }
+};
+
+int
+ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
+	    0x92, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = {
 	{ "MCLASS",		0x0f, 0x0f }
 };
@@ -2023,6 +2023,17 @@
 	    0x93, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
+	{ "MCLASS",		0x0f, 0x0f }
+};
+
+int
+ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
+	    0x93, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = {
 	{ "MCLASS",		0x0f, 0x0f }
 };
@@ -2051,17 +2062,6 @@
 	    0x93, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
-	{ "MCLASS",		0x0f, 0x0f }
-};
-
-int
-ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
-	    0x93, regvalue, cur_col, wrap));
-}
-
 int
 ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2070,16 +2070,16 @@
 }
 
 int
-ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
+	return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
 	    0x94, regvalue, cur_col, wrap));
 }
 
 int
-ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
+	return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
 	    0x94, regvalue, cur_col, wrap));
 }
 
@@ -2101,24 +2101,6 @@
 	    0x96, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
-	{ "RXSPLTRSP",		0x01, 0x01 },
-	{ "RXSCEMSG",		0x02, 0x02 },
-	{ "RXOVRUN",		0x04, 0x04 },
-	{ "CNTNOTCMPLT",	0x08, 0x08 },
-	{ "SCDATBUCKET",	0x10, 0x10 },
-	{ "SCADERR",		0x20, 0x20 },
-	{ "SCBCERR",		0x40, 0x40 },
-	{ "STAETERM",		0x80, 0x80 }
-};
-
-int
-ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
-	    0x96, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
 	{ "RXSPLTRSP",		0x01, 0x01 },
 	{ "RXSCEMSG",		0x02, 0x02 },
@@ -2137,15 +2119,22 @@
 	    0x96, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
-	{ "RXDATABUCKET",	0x01, 0x01 }
+static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
+	{ "RXSPLTRSP",		0x01, 0x01 },
+	{ "RXSCEMSG",		0x02, 0x02 },
+	{ "RXOVRUN",		0x04, 0x04 },
+	{ "CNTNOTCMPLT",	0x08, 0x08 },
+	{ "SCDATBUCKET",	0x10, 0x10 },
+	{ "SCADERR",		0x20, 0x20 },
+	{ "SCBCERR",		0x40, 0x40 },
+	{ "STAETERM",		0x80, 0x80 }
 };
 
 int
-ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
-	    0x97, regvalue, cur_col, wrap));
+	return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
+	    0x96, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
@@ -2170,6 +2159,17 @@
 	    0x97, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
+	{ "RXDATABUCKET",	0x01, 0x01 }
+};
+
+int
+ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
+	    0x97, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t SGRXMSG0_parse_table[] = {
 	{ "CFNUM",		0x07, 0x07 },
 	{ "CDNUM",		0xf8, 0xf8 }
@@ -2320,6 +2320,17 @@
 	    0x9e, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
+	{ "RXDATABUCKET",	0x01, 0x01 }
+};
+
+int
+ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
+	    0x9f, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
 	{ "TEST_NUM",		0x0f, 0x0f },
 	{ "TEST_GROUP",		0xf0, 0xf0 }
@@ -2332,17 +2343,6 @@
 	    0x9f, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
-	{ "RXDATABUCKET",	0x01, 0x01 }
-};
-
-int
-ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
-	    0x9f, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t DF0PCISTAT_parse_table[] = {
 	{ "DPR",		0x01, 0x01 },
 	{ "TWATERR",		0x02, 0x02 },
@@ -2537,16 +2537,16 @@
 }
 
 int
-ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "CCSCBADDR",
+	return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
 	    0xac, regvalue, cur_col, wrap));
 }
 
 int
-ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
+	return (ahd_print_register(NULL, 0, "CCSCBADDR",
 	    0xac, regvalue, cur_col, wrap));
 }
 
@@ -2566,22 +2566,6 @@
 	    0xad, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
-	{ "CCSGRESET",		0x01, 0x01 },
-	{ "SG_FETCH_REQ",	0x02, 0x02 },
-	{ "CCSGENACK",		0x08, 0x08 },
-	{ "SG_CACHE_AVAIL",	0x10, 0x10 },
-	{ "CCSGDONE",		0x80, 0x80 },
-	{ "CCSGEN",		0x0c, 0x0c }
-};
-
-int
-ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
-	    0xad, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
 	{ "CCSCBRESET",		0x01, 0x01 },
 	{ "CCSCBDIR",		0x04, 0x04 },
@@ -2598,6 +2582,22 @@
 	    0xad, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
+	{ "CCSGRESET",		0x01, 0x01 },
+	{ "SG_FETCH_REQ",	0x02, 0x02 },
+	{ "CCSGENACK",		0x08, 0x08 },
+	{ "SG_CACHE_AVAIL",	0x10, 0x10 },
+	{ "CCSGDONE",		0x80, 0x80 },
+	{ "CCSGEN",		0x0c, 0x0c }
+};
+
+int
+ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
+	    0xad, regvalue, cur_col, wrap));
+}
+
 int
 ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
@@ -2841,13 +2841,6 @@
 }
 
 int
-ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "DFPTRS",
-	    0xc8, regvalue, cur_col, wrap));
-}
-
-int
 ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
@@ -2855,10 +2848,10 @@
 }
 
 int
-ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "DFBKPTR",
-	    0xc9, regvalue, cur_col, wrap));
+	return (ahd_print_register(NULL, 0, "DFPTRS",
+	    0xc8, regvalue, cur_col, wrap));
 }
 
 int
@@ -2868,6 +2861,13 @@
 	    0xc9, regvalue, cur_col, wrap));
 }
 
+int
+ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "DFBKPTR",
+	    0xc9, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t DFDBCTL_parse_table[] = {
 	{ "DFF_RAMBIST_EN",	0x01, 0x01 },
 	{ "DFF_RAMBIST_DONE",	0x02, 0x02 },
@@ -3001,6 +3001,13 @@
 	    0xe4, regvalue, cur_col, wrap));
 }
 
+int
+ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "BRKADDR0",
+	    0xe6, regvalue, cur_col, wrap));
+}
+
 static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = {
 	{ "BRKDIS",		0x80, 0x80 }
 };
@@ -3013,13 +3020,6 @@
 }
 
 int
-ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "BRKADDR0",
-	    0xe6, regvalue, cur_col, wrap));
-}
-
-int
 ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "ALLONES",
@@ -3069,13 +3069,6 @@
 }
 
 int
-ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "CURADDR",
-	    0xf4, regvalue, cur_col, wrap));
-}
-
-int
 ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
@@ -3083,10 +3076,10 @@
 }
 
 int
-ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
-	    0xf6, regvalue, cur_col, wrap));
+	return (ahd_print_register(NULL, 0, "CURADDR",
+	    0xf4, regvalue, cur_col, wrap));
 }
 
 int
@@ -3097,6 +3090,13 @@
 }
 
 int
+ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
+	    0xf6, regvalue, cur_col, wrap));
+}
+
+int
 ahd_longjmp_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "LONGJMP_ADDR",
@@ -3174,24 +3174,45 @@
 }
 
 int
+ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL",
+	    0x12e, regvalue, cur_col, wrap));
+}
+
+int
+ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD",
+	    0x130, regvalue, cur_col, wrap));
+}
+
+int
 ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "QFREEZE_COUNT",
-	    0x12e, regvalue, cur_col, wrap));
+	    0x132, regvalue, cur_col, wrap));
+}
+
+int
+ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT",
+	    0x134, regvalue, cur_col, wrap));
 }
 
 int
 ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "SAVED_MODE",
-	    0x130, regvalue, cur_col, wrap));
+	    0x136, regvalue, cur_col, wrap));
 }
 
 int
 ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "MSG_OUT",
-	    0x131, regvalue, cur_col, wrap));
+	    0x137, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
@@ -3211,7 +3232,7 @@
 ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS",
-	    0x132, regvalue, cur_col, wrap));
+	    0x138, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
@@ -3230,21 +3251,21 @@
 ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS",
-	    0x133, regvalue, cur_col, wrap));
+	    0x139, regvalue, cur_col, wrap));
 }
 
 int
 ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "SAVED_SCSIID",
-	    0x134, regvalue, cur_col, wrap));
+	    0x13a, regvalue, cur_col, wrap));
 }
 
 int
 ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "SAVED_LUN",
-	    0x135, regvalue, cur_col, wrap));
+	    0x13b, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
@@ -3267,42 +3288,42 @@
 ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE",
-	    0x136, regvalue, cur_col, wrap));
+	    0x13c, regvalue, cur_col, wrap));
 }
 
 int
 ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG",
-	    0x137, regvalue, cur_col, wrap));
-}
-
-int
-ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
-	    0x138, regvalue, cur_col, wrap));
-}
-
-int
-ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
-	    0x13c, regvalue, cur_col, wrap));
+	    0x13d, regvalue, cur_col, wrap));
 }
 
 int
 ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
-	    0x140, regvalue, cur_col, wrap));
+	    0x13e, regvalue, cur_col, wrap));
 }
 
 int
 ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "TQINPOS",
-	    0x141, regvalue, cur_col, wrap));
+	    0x13f, regvalue, cur_col, wrap));
+}
+
+int
+ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
+	    0x140, regvalue, cur_col, wrap));
+}
+
+int
+ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
+	    0x144, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t ARG_1_parse_table[] = {
@@ -3320,21 +3341,21 @@
 ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1",
-	    0x142, regvalue, cur_col, wrap));
+	    0x148, regvalue, cur_col, wrap));
 }
 
 int
 ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "ARG_2",
-	    0x143, regvalue, cur_col, wrap));
+	    0x149, regvalue, cur_col, wrap));
 }
 
 int
 ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "LAST_MSG",
-	    0x144, regvalue, cur_col, wrap));
+	    0x14a, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
@@ -3350,14 +3371,14 @@
 ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE",
-	    0x145, regvalue, cur_col, wrap));
+	    0x14b, regvalue, cur_col, wrap));
 }
 
 int
 ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "INITIATOR_TAG",
-	    0x146, regvalue, cur_col, wrap));
+	    0x14c, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
@@ -3369,63 +3390,63 @@
 ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
-	    0x147, regvalue, cur_col, wrap));
+	    0x14d, regvalue, cur_col, wrap));
 }
 
 int
 ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR",
-	    0x148, regvalue, cur_col, wrap));
+	    0x14e, regvalue, cur_col, wrap));
 }
 
 int
 ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER",
-	    0x14a, regvalue, cur_col, wrap));
+	    0x150, regvalue, cur_col, wrap));
 }
 
 int
 ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS",
-	    0x14c, regvalue, cur_col, wrap));
+	    0x152, regvalue, cur_col, wrap));
 }
 
 int
 ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS",
-	    0x14d, regvalue, cur_col, wrap));
+	    0x153, regvalue, cur_col, wrap));
 }
 
 int
 ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "CMDS_PENDING",
-	    0x14e, regvalue, cur_col, wrap));
+	    0x154, regvalue, cur_col, wrap));
 }
 
 int
 ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT",
-	    0x150, regvalue, cur_col, wrap));
+	    0x156, regvalue, cur_col, wrap));
 }
 
 int
 ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX",
-	    0x151, regvalue, cur_col, wrap));
+	    0x157, regvalue, cur_col, wrap));
 }
 
 int
 ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE",
-	    0x152, regvalue, cur_col, wrap));
+	    0x158, regvalue, cur_col, wrap));
 }
 
 int
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
index 77c471f..b1e5365 100644
--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
@@ -2,215 +2,228 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
  */
 static uint8_t seqprog[] = {
 	0xff, 0x02, 0x06, 0x78,
-	0x00, 0xea, 0x50, 0x59,
+	0x00, 0xea, 0x64, 0x59,
 	0x01, 0xea, 0x04, 0x30,
 	0xff, 0x04, 0x0c, 0x78,
-	0x19, 0xea, 0x50, 0x59,
+	0x19, 0xea, 0x64, 0x59,
 	0x19, 0xea, 0x04, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x60, 0x3a, 0x1a, 0x68,
-	0x04, 0x47, 0x1b, 0x68,
-	0xff, 0x21, 0x1b, 0x70,
-	0x40, 0x4b, 0x92, 0x69,
-	0x00, 0xe2, 0x54, 0x59,
-	0x40, 0x4b, 0x92, 0x69,
-	0x20, 0x4b, 0x82, 0x69,
-	0xfc, 0x42, 0x24, 0x78,
-	0x10, 0x40, 0x24, 0x78,
-	0x00, 0xe2, 0xc4, 0x5d,
-	0x20, 0x4d, 0x28, 0x78,
-	0x00, 0xe2, 0xc4, 0x5d,
+	0x60, 0x3a, 0x3a, 0x68,
+	0x04, 0x4d, 0x35, 0x78,
+	0x01, 0x34, 0xc1, 0x31,
+	0x00, 0x32, 0x21, 0x60,
+	0x01, 0x35, 0xc1, 0x31,
+	0x00, 0x33, 0x21, 0x60,
+	0xfb, 0x4d, 0x9b, 0x0a,
+	0x00, 0xe2, 0x34, 0x40,
+	0x50, 0x4b, 0x3a, 0x68,
+	0xff, 0x31, 0x3b, 0x70,
+	0x02, 0x30, 0x51, 0x31,
+	0xff, 0x8d, 0x2d, 0x70,
+	0x02, 0x8c, 0x51, 0x31,
+	0xff, 0x8d, 0x29, 0x60,
+	0x02, 0x28, 0x19, 0x33,
+	0x02, 0x30, 0x51, 0x32,
+	0xff, 0xea, 0x62, 0x02,
+	0x00, 0xe2, 0x3a, 0x40,
+	0xff, 0x21, 0x3b, 0x70,
+	0x40, 0x4b, 0xaa, 0x69,
+	0x00, 0xe2, 0x68, 0x59,
+	0x40, 0x4b, 0xaa, 0x69,
+	0x20, 0x4b, 0x96, 0x69,
+	0xfc, 0x42, 0x44, 0x78,
+	0x10, 0x40, 0x44, 0x78,
+	0x00, 0xe2, 0xfc, 0x5d,
+	0x20, 0x4d, 0x48, 0x78,
+	0x00, 0xe2, 0xfc, 0x5d,
 	0x30, 0x3f, 0xc0, 0x09,
-	0x30, 0xe0, 0x30, 0x60,
+	0x30, 0xe0, 0x50, 0x60,
 	0x7f, 0x4a, 0x94, 0x08,
-	0x00, 0xe2, 0x32, 0x40,
+	0x00, 0xe2, 0x52, 0x40,
 	0xc0, 0x4a, 0x94, 0x00,
-	0x00, 0xe2, 0x3e, 0x58,
-	0x00, 0xe2, 0x56, 0x58,
-	0x00, 0xe2, 0x66, 0x58,
+	0x00, 0xe2, 0x5e, 0x58,
+	0x00, 0xe2, 0x76, 0x58,
+	0x00, 0xe2, 0x86, 0x58,
 	0x00, 0xe2, 0x06, 0x40,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x01, 0x52, 0x64, 0x78,
+	0x01, 0x52, 0x84, 0x78,
 	0x02, 0x58, 0x50, 0x31,
 	0xff, 0xea, 0x10, 0x0b,
-	0xff, 0x97, 0x4f, 0x78,
-	0x50, 0x4b, 0x4a, 0x68,
+	0xff, 0x97, 0x6f, 0x78,
+	0x50, 0x4b, 0x6a, 0x68,
 	0xbf, 0x3a, 0x74, 0x08,
-	0x14, 0xea, 0x50, 0x59,
+	0x14, 0xea, 0x64, 0x59,
 	0x14, 0xea, 0x04, 0x00,
 	0x08, 0x92, 0x25, 0x03,
-	0xff, 0x90, 0x3f, 0x68,
-	0x00, 0xe2, 0x56, 0x5b,
-	0x00, 0xe2, 0x3e, 0x40,
-	0x00, 0xea, 0x44, 0x59,
+	0xff, 0x90, 0x5f, 0x68,
+	0x00, 0xe2, 0x76, 0x5b,
+	0x00, 0xe2, 0x5e, 0x40,
+	0x00, 0xea, 0x5e, 0x59,
 	0x01, 0xea, 0x00, 0x30,
-	0x80, 0xf9, 0x5e, 0x68,
-	0x00, 0xe2, 0x42, 0x59,
-	0x11, 0xea, 0x44, 0x59,
+	0x80, 0xf9, 0x7e, 0x68,
+	0x00, 0xe2, 0x5c, 0x59,
+	0x11, 0xea, 0x5e, 0x59,
 	0x11, 0xea, 0x00, 0x00,
-	0x80, 0xf9, 0x42, 0x79,
+	0x80, 0xf9, 0x5c, 0x79,
 	0xff, 0xea, 0xd4, 0x0d,
-	0x22, 0xea, 0x44, 0x59,
+	0x22, 0xea, 0x5e, 0x59,
 	0x22, 0xea, 0x00, 0x00,
-	0x10, 0x16, 0x70, 0x78,
-	0x01, 0x0b, 0xa2, 0x32,
+	0x10, 0x16, 0x90, 0x78,
 	0x10, 0x16, 0x2c, 0x00,
-	0x18, 0xad, 0x00, 0x79,
-	0x04, 0xad, 0xca, 0x68,
-	0x80, 0xad, 0x64, 0x78,
-	0x10, 0xad, 0x98, 0x78,
-	0xff, 0x88, 0x83, 0x68,
+	0x01, 0x0b, 0xae, 0x32,
+	0x18, 0xad, 0x12, 0x79,
+	0x04, 0xad, 0xdc, 0x68,
+	0x80, 0xad, 0x84, 0x78,
+	0x10, 0xad, 0xaa, 0x78,
 	0xe7, 0xad, 0x5a, 0x09,
 	0x02, 0x8c, 0x59, 0x32,
+	0xff, 0x8d, 0xa1, 0x60,
+	0xff, 0xea, 0x5e, 0x02,
+	0xff, 0x88, 0xa7, 0x78,
+	0x02, 0x30, 0x19, 0x33,
+	0x02, 0xa8, 0x60, 0x36,
 	0x02, 0x28, 0x19, 0x33,
 	0x02, 0xa8, 0x50, 0x36,
-	0x33, 0xea, 0x44, 0x59,
-	0x33, 0xea, 0x00, 0x00,
-	0x40, 0x3a, 0x64, 0x68,
-	0x50, 0x4b, 0x64, 0x68,
-	0x22, 0xea, 0x44, 0x59,
-	0x22, 0xea, 0x00, 0x00,
 	0xe7, 0xad, 0x5a, 0x09,
-	0x02, 0x8c, 0x59, 0x32,
-	0x1a, 0xea, 0x50, 0x59,
-	0x1a, 0xea, 0x04, 0x00,
-	0xff, 0xea, 0xd4, 0x0d,
-	0xe7, 0xad, 0x5a, 0x09,
-	0x00, 0xe2, 0xa6, 0x58,
+	0x00, 0xe2, 0xb8, 0x58,
 	0xff, 0xea, 0x56, 0x02,
-	0x04, 0x7c, 0x78, 0x32,
-	0x20, 0x16, 0x64, 0x78,
-	0x04, 0x38, 0x79, 0x32,
-	0x80, 0x37, 0x6f, 0x16,
-	0xff, 0x2d, 0xb5, 0x60,
-	0xff, 0x29, 0xb5, 0x60,
-	0x40, 0x51, 0xc5, 0x78,
-	0xff, 0x4f, 0xb5, 0x68,
-	0xff, 0x4d, 0xc1, 0x19,
-	0x00, 0x4e, 0xd5, 0x19,
-	0x00, 0xe2, 0xc4, 0x50,
-	0x01, 0x4c, 0xc1, 0x31,
-	0x00, 0x50, 0xd5, 0x19,
-	0x00, 0xe2, 0xc4, 0x48,
-	0x80, 0x18, 0x64, 0x78,
-	0x02, 0x4a, 0x1d, 0x30,
+	0x04, 0x7c, 0x88, 0x32,
+	0x20, 0x16, 0x84, 0x78,
+	0x04, 0x40, 0x89, 0x32,
+	0x80, 0x3d, 0x7b, 0x16,
+	0xff, 0x2d, 0xc7, 0x60,
+	0xff, 0x29, 0xc7, 0x60,
+	0x40, 0x57, 0xd7, 0x78,
+	0xff, 0x55, 0xc7, 0x68,
+	0xff, 0x53, 0xc1, 0x19,
+	0x00, 0x54, 0xd5, 0x19,
+	0x00, 0xe2, 0xd6, 0x50,
+	0x01, 0x52, 0xc1, 0x31,
+	0x00, 0x56, 0xd5, 0x19,
+	0x00, 0xe2, 0xd6, 0x48,
+	0x80, 0x18, 0x84, 0x78,
+	0x02, 0x50, 0x1d, 0x30,
 	0x10, 0xea, 0x18, 0x00,
 	0x60, 0x18, 0x30, 0x00,
 	0x7f, 0x18, 0x30, 0x0c,
 	0x02, 0xea, 0x02, 0x00,
-	0xff, 0xea, 0xa0, 0x0a,
+	0xff, 0xea, 0xac, 0x0a,
 	0x80, 0x18, 0x30, 0x04,
-	0x40, 0xad, 0x64, 0x78,
+	0x40, 0xad, 0x84, 0x78,
 	0xe7, 0xad, 0x5a, 0x09,
 	0x02, 0xa8, 0x40, 0x31,
 	0xff, 0xea, 0xc0, 0x09,
-	0x01, 0x4e, 0x9d, 0x1a,
-	0x00, 0x4f, 0x9f, 0x22,
+	0x01, 0x54, 0xa9, 0x1a,
+	0x00, 0x55, 0xab, 0x22,
 	0x01, 0x94, 0x6d, 0x33,
-	0x01, 0xea, 0x20, 0x33,
+	0xff, 0xea, 0x20, 0x0b,
 	0x04, 0xac, 0x49, 0x32,
 	0xff, 0xea, 0x5a, 0x03,
 	0xff, 0xea, 0x5e, 0x03,
 	0x01, 0x10, 0xd4, 0x31,
-	0x10, 0x92, 0xf5, 0x68,
+	0x10, 0x92, 0x07, 0x69,
 	0x3d, 0x93, 0xc5, 0x29,
 	0xfe, 0xe2, 0xc4, 0x09,
 	0x01, 0xea, 0xc6, 0x01,
 	0x02, 0xe2, 0xc8, 0x31,
 	0x02, 0xec, 0x50, 0x31,
 	0x02, 0xa0, 0xda, 0x31,
-	0xff, 0xa9, 0xf4, 0x70,
+	0xff, 0xa9, 0x06, 0x71,
 	0x02, 0xa0, 0x58, 0x37,
-	0xff, 0x21, 0xfd, 0x70,
+	0xff, 0x21, 0x0f, 0x71,
 	0x02, 0x22, 0x51, 0x31,
 	0x02, 0xa0, 0x5c, 0x33,
 	0x02, 0xa0, 0x44, 0x36,
 	0x02, 0xa0, 0x40, 0x32,
 	0x02, 0xa0, 0x44, 0x36,
-	0x04, 0x47, 0x05, 0x69,
-	0x40, 0x16, 0x30, 0x69,
-	0xff, 0x2d, 0x35, 0x61,
-	0xff, 0x29, 0x65, 0x70,
-	0x01, 0x37, 0xc1, 0x31,
+	0x04, 0x4d, 0x17, 0x69,
+	0x40, 0x16, 0x48, 0x69,
+	0xff, 0x2d, 0x4d, 0x61,
+	0xff, 0x29, 0x85, 0x70,
 	0x02, 0x28, 0x55, 0x32,
 	0x01, 0xea, 0x5a, 0x01,
-	0x04, 0x3c, 0xf9, 0x30,
+	0x04, 0x44, 0xf9, 0x30,
+	0x01, 0x44, 0xc1, 0x31,
 	0x02, 0x28, 0x51, 0x31,
-	0x01, 0xa8, 0x60, 0x31,
-	0x00, 0xa9, 0x60, 0x01,
+	0x02, 0xa8, 0x60, 0x31,
+	0x01, 0xa4, 0x61, 0x31,
+	0x01, 0x3d, 0x61, 0x31,
 	0x01, 0x14, 0xd4, 0x31,
-	0x01, 0x50, 0xa1, 0x1a,
-	0xff, 0x4e, 0x9d, 0x1a,
-	0xff, 0x4f, 0x9f, 0x22,
-	0xff, 0x8d, 0x29, 0x71,
-	0x80, 0xac, 0x28, 0x71,
-	0x20, 0x16, 0x28, 0x69,
+	0x01, 0x56, 0xad, 0x1a,
+	0xff, 0x54, 0xa9, 0x1a,
+	0xff, 0x55, 0xab, 0x22,
+	0xff, 0x8d, 0x41, 0x71,
+	0x80, 0xac, 0x40, 0x71,
+	0x20, 0x16, 0x40, 0x69,
+	0x00, 0xac, 0xc4, 0x19,
+	0x07, 0xe2, 0x40, 0xf9,
 	0x02, 0x8c, 0x51, 0x31,
-	0x00, 0xe2, 0x12, 0x41,
+	0x00, 0xe2, 0x24, 0x41,
 	0x01, 0xac, 0x08, 0x31,
 	0x09, 0xea, 0x5a, 0x01,
 	0x02, 0x8c, 0x51, 0x32,
 	0xff, 0xea, 0x1a, 0x07,
 	0x04, 0x24, 0xf9, 0x30,
-	0x1d, 0xea, 0x3a, 0x41,
+	0x1d, 0xea, 0x52, 0x41,
 	0x02, 0x2c, 0x51, 0x31,
 	0x04, 0xa8, 0xf9, 0x30,
-	0x19, 0xea, 0x3a, 0x41,
+	0x19, 0xea, 0x52, 0x41,
 	0x06, 0xea, 0x08, 0x81,
 	0x01, 0xe2, 0x5a, 0x35,
-	0x02, 0xf2, 0xf0, 0x35,
+	0x02, 0xf2, 0xf0, 0x31,
+	0xff, 0xea, 0xd4, 0x0d,
 	0x02, 0xf2, 0xf0, 0x31,
 	0x02, 0xf8, 0xe4, 0x35,
 	0x80, 0xea, 0xb2, 0x01,
 	0x01, 0xe2, 0x00, 0x30,
 	0xff, 0xea, 0xb2, 0x0d,
-	0x80, 0xea, 0xb2, 0x01,
-	0x11, 0x00, 0x00, 0x10,
-	0xff, 0xea, 0xb2, 0x0d,
 	0x01, 0xe2, 0x04, 0x30,
 	0x01, 0xea, 0x04, 0x34,
 	0x02, 0x20, 0xbd, 0x30,
 	0x02, 0x20, 0xb9, 0x30,
 	0x02, 0x20, 0x51, 0x31,
 	0x4c, 0x93, 0xd7, 0x28,
-	0x10, 0x92, 0x63, 0x79,
+	0x10, 0x92, 0x77, 0x79,
 	0x01, 0x6b, 0xc0, 0x30,
 	0x02, 0x64, 0xc8, 0x00,
 	0x40, 0x3a, 0x74, 0x04,
-	0x00, 0xe2, 0x56, 0x58,
-	0x33, 0xea, 0x44, 0x59,
+	0x00, 0xe2, 0x76, 0x58,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x30, 0x3f, 0xc0, 0x09,
-	0x30, 0xe0, 0x64, 0x61,
-	0x20, 0x3f, 0x7a, 0x69,
-	0x10, 0x3f, 0x64, 0x79,
+	0x30, 0xe0, 0x78, 0x61,
+	0x20, 0x3f, 0x8e, 0x69,
+	0x10, 0x3f, 0x78, 0x79,
 	0x02, 0xea, 0x7e, 0x00,
-	0x00, 0xea, 0x44, 0x59,
+	0x00, 0xea, 0x5e, 0x59,
 	0x01, 0xea, 0x00, 0x30,
-	0x02, 0x48, 0x51, 0x35,
+	0x02, 0x4e, 0x51, 0x35,
 	0x01, 0xea, 0x7e, 0x00,
-	0x11, 0xea, 0x44, 0x59,
+	0x11, 0xea, 0x5e, 0x59,
 	0x11, 0xea, 0x00, 0x00,
-	0x02, 0x48, 0x51, 0x35,
+	0x02, 0x4e, 0x51, 0x35,
+	0xc0, 0x4a, 0x94, 0x00,
+	0x04, 0x41, 0x9c, 0x79,
 	0x08, 0xea, 0x98, 0x00,
 	0x08, 0x57, 0xae, 0x00,
 	0x08, 0x3c, 0x78, 0x00,
-	0xf0, 0x49, 0x68, 0x0a,
+	0xf0, 0x49, 0x74, 0x0a,
 	0x0f, 0x67, 0xc0, 0x09,
-	0x00, 0x34, 0x69, 0x02,
+	0x00, 0x3a, 0x75, 0x02,
 	0x20, 0xea, 0x96, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x40, 0x3a, 0xae, 0x69,
+	0x00, 0xe2, 0x14, 0x42,
+	0xc0, 0x4a, 0x94, 0x00,
+	0x40, 0x3a, 0xc8, 0x69,
 	0x02, 0x55, 0x06, 0x68,
-	0x02, 0x56, 0xae, 0x69,
-	0xff, 0x5b, 0xae, 0x61,
+	0x02, 0x56, 0xc8, 0x69,
+	0xff, 0x5b, 0xc8, 0x61,
 	0x02, 0x20, 0x51, 0x31,
 	0x80, 0xea, 0xb2, 0x01,
 	0x44, 0xea, 0x00, 0x00,
@@ -218,237 +231,246 @@
 	0x33, 0xea, 0x00, 0x00,
 	0xff, 0xea, 0xb2, 0x09,
 	0xff, 0xe0, 0xc0, 0x19,
-	0xff, 0xe0, 0xb0, 0x79,
+	0xff, 0xe0, 0xca, 0x79,
 	0x02, 0xac, 0x51, 0x31,
-	0x00, 0xe2, 0xa6, 0x41,
+	0x00, 0xe2, 0xc0, 0x41,
 	0x02, 0x5e, 0x50, 0x31,
 	0x02, 0xa8, 0xb8, 0x30,
 	0x02, 0x5c, 0x50, 0x31,
-	0xff, 0xad, 0xc1, 0x71,
+	0xff, 0xad, 0xdb, 0x71,
 	0x02, 0xac, 0x41, 0x31,
 	0x02, 0x22, 0x51, 0x31,
 	0x02, 0xa0, 0x5c, 0x33,
 	0x02, 0xa0, 0x44, 0x32,
-	0x00, 0xe2, 0xca, 0x41,
-	0x10, 0x92, 0xcb, 0x69,
+	0x00, 0xe2, 0xe4, 0x41,
+	0x10, 0x92, 0xe5, 0x69,
 	0x3d, 0x93, 0xc9, 0x29,
 	0x01, 0xe4, 0xc8, 0x01,
 	0x01, 0xea, 0xca, 0x01,
 	0xff, 0xea, 0xda, 0x01,
 	0x02, 0x20, 0x51, 0x31,
 	0x02, 0xae, 0x41, 0x32,
-	0xff, 0x21, 0xd3, 0x61,
+	0xff, 0x21, 0xed, 0x61,
 	0xff, 0xea, 0x46, 0x02,
 	0x02, 0x5c, 0x50, 0x31,
 	0x40, 0xea, 0x96, 0x00,
-	0x02, 0x56, 0xcc, 0x6d,
-	0x01, 0x55, 0xcc, 0x6d,
-	0x10, 0x92, 0xdf, 0x79,
-	0x10, 0x40, 0xe8, 0x69,
-	0x01, 0x56, 0xe8, 0x79,
+	0x02, 0x56, 0x04, 0x6e,
+	0x01, 0x55, 0x04, 0x6e,
+	0x10, 0x92, 0xf9, 0x79,
+	0x10, 0x40, 0x02, 0x6a,
+	0x01, 0x56, 0x02, 0x7a,
 	0xff, 0x97, 0x07, 0x78,
-	0x13, 0xea, 0x50, 0x59,
+	0x13, 0xea, 0x64, 0x59,
 	0x13, 0xea, 0x04, 0x00,
 	0x00, 0xe2, 0x06, 0x40,
 	0xbf, 0x3a, 0x74, 0x08,
+	0x04, 0x41, 0x08, 0x7a,
 	0x08, 0xea, 0x98, 0x00,
 	0x08, 0x57, 0xae, 0x00,
-	0x01, 0x93, 0x69, 0x32,
-	0x01, 0x94, 0x6b, 0x32,
-	0x40, 0xea, 0x66, 0x02,
+	0x01, 0x93, 0x75, 0x32,
+	0x01, 0x94, 0x77, 0x32,
+	0x40, 0xea, 0x72, 0x02,
 	0x08, 0x3c, 0x78, 0x00,
-	0x80, 0xea, 0x62, 0x02,
-	0x00, 0xe2, 0xb8, 0x5b,
-	0x01, 0x36, 0xc1, 0x31,
-	0x9f, 0xe0, 0x4c, 0x7c,
-	0x80, 0xe0, 0x0c, 0x72,
-	0xa0, 0xe0, 0x44, 0x72,
-	0xc0, 0xe0, 0x3a, 0x72,
-	0xe0, 0xe0, 0x74, 0x72,
-	0x01, 0xea, 0x50, 0x59,
+	0x80, 0xea, 0x6e, 0x02,
+	0x00, 0xe2, 0xe2, 0x5b,
+	0x01, 0x3c, 0xc1, 0x31,
+	0x9f, 0xe0, 0x84, 0x7c,
+	0x80, 0xe0, 0x28, 0x72,
+	0xa0, 0xe0, 0x64, 0x72,
+	0xc0, 0xe0, 0x5a, 0x72,
+	0xe0, 0xe0, 0x94, 0x72,
+	0x01, 0xea, 0x64, 0x59,
 	0x01, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x80, 0x33, 0x13, 0x7a,
-	0x03, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0x14, 0x42,
+	0x80, 0x39, 0x2f, 0x7a,
+	0x03, 0xea, 0x64, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0xee, 0x00, 0x1a, 0x6a,
+	0xee, 0x00, 0x36, 0x6a,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x02, 0xa8, 0x90, 0x32,
-	0x00, 0xe2, 0x6a, 0x59,
+	0x02, 0xa8, 0x9c, 0x32,
+	0x00, 0xe2, 0x7e, 0x59,
 	0xef, 0x96, 0xd5, 0x19,
-	0x00, 0xe2, 0x2a, 0x52,
+	0x00, 0xe2, 0x46, 0x52,
 	0x09, 0x80, 0xe1, 0x30,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x30, 0x42,
+	0x00, 0xe2, 0x4c, 0x42,
 	0x01, 0x96, 0xd1, 0x30,
 	0x10, 0x80, 0x89, 0x31,
 	0x20, 0xea, 0x32, 0x00,
-	0xbf, 0x33, 0x67, 0x0a,
-	0x20, 0x19, 0x32, 0x6a,
-	0x02, 0x4d, 0xf8, 0x69,
-	0x40, 0x33, 0x67, 0x02,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x80, 0x33, 0xb5, 0x6a,
+	0xbf, 0x39, 0x73, 0x0a,
+	0x10, 0x4c, 0x56, 0x6a,
+	0x20, 0x19, 0x4e, 0x6a,
+	0x20, 0x19, 0x52, 0x6a,
+	0x02, 0x4d, 0x14, 0x6a,
+	0x40, 0x39, 0x73, 0x02,
+	0x00, 0xe2, 0x14, 0x42,
+	0x80, 0x39, 0xd5, 0x6a,
 	0x01, 0x44, 0x10, 0x33,
 	0x08, 0x92, 0x25, 0x03,
-	0x00, 0xe2, 0xf8, 0x41,
+	0x00, 0xe2, 0x14, 0x42,
 	0x10, 0xea, 0x80, 0x00,
-	0x01, 0x31, 0xc5, 0x31,
-	0x80, 0xe2, 0x60, 0x62,
-	0x10, 0x92, 0x85, 0x6a,
+	0x01, 0x37, 0xc5, 0x31,
+	0x80, 0xe2, 0x80, 0x62,
+	0x10, 0x92, 0xa5, 0x6a,
 	0xc0, 0x94, 0xc5, 0x01,
-	0x40, 0x92, 0x51, 0x6a,
+	0x40, 0x92, 0x71, 0x6a,
 	0xbf, 0xe2, 0xc4, 0x09,
-	0x20, 0x92, 0x65, 0x7a,
+	0x20, 0x92, 0x85, 0x7a,
 	0x01, 0xe2, 0x88, 0x30,
-	0x00, 0xe2, 0xb8, 0x5b,
-	0xa0, 0x36, 0x6d, 0x62,
+	0x00, 0xe2, 0xe2, 0x5b,
+	0xa0, 0x3c, 0x8d, 0x62,
 	0x23, 0x92, 0x89, 0x08,
-	0x00, 0xe2, 0xb8, 0x5b,
-	0xa0, 0x36, 0x6d, 0x62,
-	0x00, 0xa8, 0x64, 0x42,
-	0xff, 0xe2, 0x64, 0x62,
-	0x00, 0xe2, 0x84, 0x42,
+	0x00, 0xe2, 0xe2, 0x5b,
+	0xa0, 0x3c, 0x8d, 0x62,
+	0x00, 0xa8, 0x84, 0x42,
+	0xff, 0xe2, 0x84, 0x62,
+	0x00, 0xe2, 0xa4, 0x42,
 	0x40, 0xea, 0x98, 0x00,
 	0x01, 0xe2, 0x88, 0x30,
-	0x00, 0xe2, 0xb8, 0x5b,
-	0xa0, 0x36, 0x43, 0x72,
+	0x00, 0xe2, 0xe2, 0x5b,
+	0xa0, 0x3c, 0x63, 0x72,
 	0x40, 0xea, 0x98, 0x00,
-	0x01, 0x31, 0x89, 0x32,
-	0x08, 0xea, 0x62, 0x02,
-	0x00, 0xe2, 0xf8, 0x41,
-	0xe0, 0xea, 0xd4, 0x5b,
-	0x80, 0xe0, 0xc0, 0x6a,
-	0x04, 0xe0, 0x66, 0x73,
-	0x02, 0xe0, 0x96, 0x73,
-	0x00, 0xea, 0x1e, 0x73,
-	0x03, 0xe0, 0xa6, 0x73,
-	0x23, 0xe0, 0x96, 0x72,
-	0x08, 0xe0, 0xbc, 0x72,
-	0x00, 0xe2, 0xb8, 0x5b,
-	0x07, 0xea, 0x50, 0x59,
+	0x01, 0x37, 0x95, 0x32,
+	0x08, 0xea, 0x6e, 0x02,
+	0x00, 0xe2, 0x14, 0x42,
+	0xe0, 0xea, 0xfe, 0x5b,
+	0x80, 0xe0, 0xe0, 0x6a,
+	0x04, 0xe0, 0x92, 0x73,
+	0x02, 0xe0, 0xc4, 0x73,
+	0x00, 0xea, 0x3e, 0x73,
+	0x03, 0xe0, 0xd4, 0x73,
+	0x23, 0xe0, 0xb6, 0x72,
+	0x08, 0xe0, 0xdc, 0x72,
+	0x00, 0xe2, 0xe2, 0x5b,
+	0x07, 0xea, 0x64, 0x59,
 	0x07, 0xea, 0x04, 0x00,
-	0x08, 0x42, 0xf9, 0x71,
-	0x04, 0x42, 0x93, 0x62,
-	0x01, 0x43, 0x89, 0x30,
-	0x00, 0xe2, 0x84, 0x42,
+	0x08, 0x48, 0x15, 0x72,
+	0x04, 0x48, 0xb3, 0x62,
+	0x01, 0x49, 0x89, 0x30,
+	0x00, 0xe2, 0xa4, 0x42,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0x84, 0x42,
-	0x01, 0x00, 0x60, 0x32,
-	0x33, 0xea, 0x44, 0x59,
+	0x00, 0xe2, 0xa4, 0x42,
+	0x01, 0x00, 0x6c, 0x32,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x4c, 0x34, 0xc1, 0x28,
+	0x4c, 0x3a, 0xc1, 0x28,
 	0x01, 0x64, 0xc0, 0x31,
-	0x00, 0x30, 0x45, 0x59,
-	0x01, 0x30, 0x01, 0x30,
-	0x01, 0xe0, 0xba, 0x7a,
-	0xa0, 0xea, 0xca, 0x5b,
-	0x01, 0xa0, 0xba, 0x62,
-	0x01, 0x84, 0xaf, 0x7a,
-	0x01, 0x95, 0xbd, 0x6a,
-	0x05, 0xea, 0x50, 0x59,
+	0x00, 0x36, 0x5f, 0x59,
+	0x01, 0x36, 0x01, 0x30,
+	0x01, 0xe0, 0xda, 0x7a,
+	0xa0, 0xea, 0xf4, 0x5b,
+	0x01, 0xa0, 0xda, 0x62,
+	0x01, 0x84, 0xcf, 0x7a,
+	0x01, 0x95, 0xdd, 0x6a,
+	0x05, 0xea, 0x64, 0x59,
 	0x05, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x03, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xdc, 0x42,
+	0x03, 0xea, 0x64, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x07, 0xea, 0xdc, 0x5b,
+	0x00, 0xe2, 0xdc, 0x42,
+	0x07, 0xea, 0x06, 0x5c,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x3f, 0xe0, 0x6a, 0x0a,
-	0xc0, 0x34, 0xc1, 0x09,
-	0x00, 0x35, 0x51, 0x01,
+	0x00, 0xe2, 0x14, 0x42,
+	0x3f, 0xe0, 0x76, 0x0a,
+	0xc0, 0x3a, 0xc1, 0x09,
+	0x00, 0x3b, 0x51, 0x01,
 	0xff, 0xea, 0x52, 0x09,
-	0x30, 0x34, 0xc5, 0x09,
+	0x30, 0x3a, 0xc5, 0x09,
 	0x3d, 0xe2, 0xc4, 0x29,
 	0xb8, 0xe2, 0xc4, 0x19,
 	0x01, 0xea, 0xc6, 0x01,
 	0x02, 0xe2, 0xc8, 0x31,
 	0x02, 0xec, 0x40, 0x31,
-	0xff, 0xa1, 0xdc, 0x72,
+	0xff, 0xa1, 0xfc, 0x72,
 	0x02, 0xe8, 0xda, 0x31,
 	0x02, 0xa0, 0x50, 0x31,
-	0x00, 0xe2, 0xfe, 0x42,
-	0x80, 0x33, 0x67, 0x02,
+	0x00, 0xe2, 0x1e, 0x43,
+	0x80, 0x39, 0x73, 0x02,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0xb8, 0x5b,
-	0x01, 0x33, 0x67, 0x02,
-	0xe0, 0x36, 0x19, 0x63,
-	0x02, 0x33, 0x67, 0x02,
-	0x20, 0x46, 0x12, 0x63,
+	0x00, 0xe2, 0xe2, 0x5b,
+	0x01, 0x39, 0x73, 0x02,
+	0xe0, 0x3c, 0x39, 0x63,
+	0x02, 0x39, 0x73, 0x02,
+	0x20, 0x46, 0x32, 0x63,
 	0xff, 0xea, 0x52, 0x09,
-	0xa8, 0xea, 0xca, 0x5b,
-	0x04, 0x92, 0xf9, 0x7a,
-	0x01, 0x34, 0xc1, 0x31,
-	0x00, 0x93, 0xf9, 0x62,
-	0x01, 0x35, 0xc1, 0x31,
-	0x00, 0x94, 0x03, 0x73,
+	0xa8, 0xea, 0xf4, 0x5b,
+	0x04, 0x92, 0x19, 0x7b,
+	0x01, 0x3a, 0xc1, 0x31,
+	0x00, 0x93, 0x19, 0x63,
+	0x01, 0x3b, 0xc1, 0x31,
+	0x00, 0x94, 0x23, 0x73,
 	0x01, 0xa9, 0x52, 0x11,
-	0xff, 0xa9, 0xee, 0x6a,
-	0x00, 0xe2, 0x12, 0x43,
-	0x10, 0x33, 0x67, 0x02,
-	0x04, 0x92, 0x13, 0x7b,
+	0xff, 0xa9, 0x0e, 0x6b,
+	0x00, 0xe2, 0x32, 0x43,
+	0x10, 0x39, 0x73, 0x02,
+	0x04, 0x92, 0x33, 0x7b,
 	0xfb, 0x92, 0x25, 0x0b,
-	0xff, 0xea, 0x66, 0x0a,
-	0x01, 0xa4, 0x0d, 0x6b,
-	0x02, 0xa8, 0x90, 0x32,
-	0x00, 0xe2, 0x6a, 0x59,
-	0x10, 0x92, 0xbd, 0x7a,
-	0xff, 0xea, 0xdc, 0x5b,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x04, 0xea, 0x50, 0x59,
+	0xff, 0xea, 0x72, 0x0a,
+	0x01, 0xa4, 0x2d, 0x6b,
+	0x02, 0xa8, 0x9c, 0x32,
+	0x00, 0xe2, 0x7e, 0x59,
+	0x10, 0x92, 0xdd, 0x7a,
+	0xff, 0xea, 0x06, 0x5c,
+	0x00, 0xe2, 0xdc, 0x42,
+	0x04, 0xea, 0x64, 0x59,
 	0x04, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x04, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xdc, 0x42,
+	0x04, 0xea, 0x64, 0x59,
 	0x04, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x08, 0x92, 0xb5, 0x7a,
-	0xc0, 0x33, 0x29, 0x7b,
-	0x80, 0x33, 0xb5, 0x6a,
-	0xff, 0x88, 0x29, 0x6b,
-	0x40, 0x33, 0xb5, 0x6a,
-	0x10, 0x92, 0x2f, 0x7b,
-	0x0a, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0x14, 0x42,
+	0x08, 0x92, 0xd5, 0x7a,
+	0xc0, 0x39, 0x49, 0x7b,
+	0x80, 0x39, 0xd5, 0x6a,
+	0xff, 0x88, 0x49, 0x6b,
+	0x40, 0x39, 0xd5, 0x6a,
+	0x10, 0x92, 0x4f, 0x7b,
+	0x0a, 0xea, 0x64, 0x59,
 	0x0a, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x4e, 0x5b,
-	0x00, 0xe2, 0x82, 0x43,
-	0x50, 0x4b, 0x36, 0x6b,
+	0x00, 0xe2, 0x6e, 0x5b,
+	0x00, 0xe2, 0xae, 0x43,
+	0x50, 0x4b, 0x56, 0x6b,
 	0xbf, 0x3a, 0x74, 0x08,
 	0x01, 0xe0, 0xf4, 0x31,
 	0xff, 0xea, 0xc0, 0x09,
-	0x01, 0x2e, 0x5d, 0x1a,
-	0x00, 0x2f, 0x5f, 0x22,
-	0x04, 0x47, 0x8f, 0x02,
+	0x01, 0x32, 0x65, 0x1a,
+	0x00, 0x33, 0x67, 0x22,
+	0x04, 0x4d, 0x9b, 0x02,
 	0x01, 0xfa, 0xc0, 0x35,
-	0x02, 0xa8, 0x84, 0x32,
+	0x02, 0xa8, 0x90, 0x32,
 	0x02, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x02, 0x42, 0x51, 0x31,
-	0xff, 0x90, 0x65, 0x68,
-	0xff, 0x88, 0x5b, 0x6b,
-	0x01, 0xa4, 0x57, 0x6b,
-	0x02, 0xa4, 0x5f, 0x6b,
-	0x01, 0x84, 0x5f, 0x7b,
+	0x02, 0x48, 0x51, 0x31,
+	0xff, 0x90, 0x85, 0x68,
+	0xff, 0x88, 0x7b, 0x6b,
+	0x01, 0xa4, 0x77, 0x6b,
+	0x02, 0xa4, 0x7f, 0x6b,
+	0x01, 0x84, 0x7f, 0x7b,
 	0x02, 0x28, 0x19, 0x33,
 	0x02, 0xa8, 0x50, 0x36,
-	0xff, 0x88, 0x5f, 0x73,
-	0x00, 0xe2, 0x32, 0x5b,
+	0xff, 0x88, 0x7f, 0x73,
+	0x00, 0xe2, 0x52, 0x5b,
 	0x02, 0xa8, 0x20, 0x33,
-	0x02, 0x2c, 0x19, 0x33,
+	0x04, 0xa4, 0x49, 0x03,
+	0xff, 0xea, 0x1a, 0x03,
+	0xff, 0x2d, 0x8b, 0x63,
 	0x02, 0xa8, 0x58, 0x32,
-	0x04, 0xa4, 0x49, 0x07,
-	0xc0, 0x33, 0xb5, 0x6a,
-	0x04, 0x92, 0x25, 0x03,
-	0x20, 0x92, 0x83, 0x6b,
+	0x02, 0xa8, 0x5c, 0x36,
 	0x02, 0xa8, 0x40, 0x31,
-	0xc0, 0x34, 0xc1, 0x09,
-	0x00, 0x35, 0x51, 0x01,
+	0x02, 0x2e, 0x51, 0x31,
+	0x02, 0xa0, 0x18, 0x33,
+	0x02, 0xa0, 0x5c, 0x36,
+	0xc0, 0x39, 0xd5, 0x6a,
+	0x04, 0x92, 0x25, 0x03,
+	0x20, 0x92, 0xaf, 0x6b,
+	0x02, 0xa8, 0x40, 0x31,
+	0xc0, 0x3a, 0xc1, 0x09,
+	0x00, 0x3b, 0x51, 0x01,
 	0xff, 0xea, 0x52, 0x09,
-	0x30, 0x34, 0xc5, 0x09,
+	0x30, 0x3a, 0xc5, 0x09,
 	0x3d, 0xe2, 0xc4, 0x29,
 	0xb8, 0xe2, 0xc4, 0x19,
 	0x01, 0xea, 0xc6, 0x01,
@@ -458,69 +480,75 @@
 	0xf7, 0x57, 0xae, 0x08,
 	0x08, 0xea, 0x98, 0x00,
 	0x01, 0x44, 0xd4, 0x31,
-	0xee, 0x00, 0x8c, 0x6b,
+	0xee, 0x00, 0xb8, 0x6b,
 	0x02, 0xea, 0xb4, 0x00,
-	0x00, 0xe2, 0xb4, 0x5b,
-	0x09, 0x4c, 0x8e, 0x7b,
+	0xc0, 0xea, 0x72, 0x02,
+	0x09, 0x4c, 0xba, 0x7b,
+	0x01, 0xea, 0x78, 0x02,
 	0x08, 0x4c, 0x06, 0x68,
-	0x0b, 0xea, 0x50, 0x59,
+	0x0b, 0xea, 0x64, 0x59,
 	0x0b, 0xea, 0x04, 0x00,
 	0x01, 0x44, 0xd4, 0x31,
-	0x20, 0x33, 0xf9, 0x79,
-	0x00, 0xe2, 0x9e, 0x5b,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x01, 0x84, 0xa3, 0x7b,
+	0x20, 0x39, 0x15, 0x7a,
+	0x00, 0xe2, 0xcc, 0x5b,
+	0x00, 0xe2, 0x14, 0x42,
+	0x01, 0x84, 0xd1, 0x7b,
 	0x01, 0xa4, 0x49, 0x07,
 	0x08, 0x60, 0x30, 0x33,
 	0x08, 0x80, 0x41, 0x37,
-	0xdf, 0x33, 0x67, 0x0a,
-	0xee, 0x00, 0xb0, 0x6b,
+	0xdf, 0x39, 0x73, 0x0a,
+	0xee, 0x00, 0xde, 0x6b,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x00, 0xe2, 0x6a, 0x59,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x01, 0xea, 0x6c, 0x02,
-	0xc0, 0xea, 0x66, 0x06,
-	0xff, 0x42, 0xc4, 0x6b,
-	0x01, 0x41, 0xb8, 0x6b,
-	0x02, 0x41, 0xb8, 0x7b,
-	0xff, 0x42, 0xc4, 0x6b,
-	0x01, 0x41, 0xb8, 0x6b,
-	0x02, 0x41, 0xb8, 0x7b,
-	0xff, 0x42, 0xc4, 0x7b,
-	0x04, 0x4c, 0xb8, 0x6b,
-	0xe0, 0x41, 0x6c, 0x0e,
+	0x00, 0xe2, 0x7e, 0x59,
+	0x00, 0xe2, 0xdc, 0x42,
+	0xff, 0x42, 0xee, 0x6b,
+	0x01, 0x41, 0xe2, 0x6b,
+	0x02, 0x41, 0xe2, 0x7b,
+	0xff, 0x42, 0xee, 0x6b,
+	0x01, 0x41, 0xe2, 0x6b,
+	0x02, 0x41, 0xe2, 0x7b,
+	0xff, 0x42, 0xee, 0x7b,
+	0x04, 0x4c, 0xe2, 0x6b,
+	0xe0, 0x41, 0x78, 0x0e,
 	0x01, 0x44, 0xd4, 0x31,
-	0xff, 0x42, 0xcc, 0x7b,
-	0x04, 0x4c, 0xcc, 0x6b,
-	0xe0, 0x41, 0x6c, 0x0a,
-	0xe0, 0x36, 0xf9, 0x61,
+	0xff, 0x42, 0xf6, 0x7b,
+	0x04, 0x4c, 0xf6, 0x6b,
+	0xe0, 0x41, 0x78, 0x0a,
+	0xe0, 0x3c, 0x15, 0x62,
 	0xff, 0xea, 0xca, 0x09,
 	0x01, 0xe2, 0xc8, 0x31,
 	0x01, 0x46, 0xda, 0x35,
 	0x01, 0x44, 0xd4, 0x35,
 	0x10, 0xea, 0x80, 0x00,
-	0x01, 0xe2, 0x62, 0x36,
-	0x04, 0xa6, 0xe4, 0x7b,
+	0x01, 0xe2, 0x6e, 0x36,
+	0x04, 0xa6, 0x0e, 0x7c,
 	0xff, 0xea, 0x5a, 0x09,
 	0xff, 0xea, 0x4c, 0x0d,
-	0x01, 0xa6, 0x02, 0x6c,
-	0x10, 0xad, 0x64, 0x78,
-	0x80, 0xad, 0xfa, 0x6b,
-	0x08, 0xad, 0x64, 0x68,
+	0x01, 0xa6, 0x3a, 0x6c,
+	0x10, 0xad, 0x84, 0x78,
+	0x80, 0xad, 0x32, 0x6c,
+	0x08, 0xad, 0x84, 0x68,
+	0x20, 0x19, 0x26, 0x7c,
+	0x80, 0xea, 0xb2, 0x01,
+	0x11, 0x00, 0x00, 0x10,
+	0x02, 0xa6, 0x22, 0x7c,
+	0xff, 0xea, 0xb2, 0x0d,
+	0x11, 0x00, 0x00, 0x10,
+	0xff, 0xea, 0xb2, 0x09,
 	0x04, 0x84, 0xf9, 0x30,
 	0x00, 0xea, 0x08, 0x81,
 	0xff, 0xea, 0xd4, 0x09,
 	0x02, 0x84, 0xf9, 0x88,
 	0x0d, 0xea, 0x5a, 0x01,
 	0x04, 0xa6, 0x4c, 0x05,
-	0x04, 0xa6, 0x64, 0x78,
+	0x04, 0xa6, 0x84, 0x78,
 	0xff, 0xea, 0x5a, 0x09,
 	0x03, 0x84, 0x59, 0x89,
 	0x03, 0xea, 0x4c, 0x01,
-	0x80, 0x1a, 0x64, 0x78,
-	0x08, 0x19, 0x64, 0x78,
+	0x80, 0x1a, 0x84, 0x78,
+	0x08, 0x19, 0x84, 0x78,
 	0x08, 0xb0, 0xe0, 0x30,
 	0x04, 0xb0, 0xe0, 0x30,
 	0x03, 0xb0, 0xf0, 0x30,
@@ -533,259 +561,259 @@
 	0x00, 0x86, 0x0d, 0x23,
 	0x00, 0x87, 0x0f, 0x23,
 	0x01, 0x84, 0xc5, 0x31,
-	0x80, 0x83, 0x25, 0x7c,
+	0x80, 0x83, 0x5d, 0x7c,
 	0x02, 0xe2, 0xc4, 0x01,
 	0xff, 0xea, 0x4c, 0x09,
 	0x01, 0xe2, 0x36, 0x30,
 	0xc8, 0x19, 0x32, 0x00,
 	0x88, 0x19, 0x32, 0x00,
 	0x01, 0xac, 0xd4, 0x99,
-	0x00, 0xe2, 0x64, 0x50,
+	0x00, 0xe2, 0x84, 0x50,
 	0xfe, 0xa6, 0x4c, 0x0d,
 	0x0b, 0x98, 0xe1, 0x30,
 	0xfd, 0xa4, 0x49, 0x09,
-	0x80, 0xa3, 0x39, 0x7c,
+	0x80, 0xa3, 0x71, 0x7c,
 	0x02, 0xa4, 0x48, 0x01,
 	0x01, 0xa4, 0x36, 0x30,
 	0xa8, 0xea, 0x32, 0x00,
 	0xfd, 0xa4, 0x49, 0x0b,
 	0x05, 0xa3, 0x07, 0x33,
-	0x80, 0x83, 0x45, 0x6c,
+	0x80, 0x83, 0x7d, 0x6c,
 	0x02, 0xea, 0x4c, 0x05,
 	0xff, 0xea, 0x4c, 0x0d,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x02, 0xa6, 0xe6, 0x6b,
+	0x00, 0xe2, 0x56, 0x59,
+	0x02, 0xa6, 0x10, 0x6c,
 	0x80, 0xf9, 0xf2, 0x05,
-	0xc0, 0x33, 0x53, 0x7c,
-	0x03, 0xea, 0x50, 0x59,
+	0xc0, 0x39, 0x8b, 0x7c,
+	0x03, 0xea, 0x64, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0x20, 0x33, 0x77, 0x7c,
-	0x01, 0x84, 0x5d, 0x6c,
-	0x06, 0xea, 0x50, 0x59,
+	0x20, 0x39, 0xaf, 0x7c,
+	0x01, 0x84, 0x95, 0x6c,
+	0x06, 0xea, 0x64, 0x59,
 	0x06, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x7a, 0x44,
-	0x01, 0x00, 0x60, 0x32,
-	0xee, 0x00, 0x66, 0x6c,
+	0x00, 0xe2, 0xb2, 0x44,
+	0x01, 0x00, 0x6c, 0x32,
+	0xee, 0x00, 0x9e, 0x6c,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x5e, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x80, 0x3d, 0x7a, 0x00,
-	0xfc, 0x42, 0x68, 0x7c,
+	0xfc, 0x42, 0xa0, 0x7c,
 	0x7f, 0x3d, 0x7a, 0x08,
-	0x00, 0x30, 0x45, 0x59,
-	0x01, 0x30, 0x01, 0x30,
-	0x09, 0xea, 0x50, 0x59,
+	0x00, 0x36, 0x5f, 0x59,
+	0x01, 0x36, 0x01, 0x30,
+	0x09, 0xea, 0x64, 0x59,
 	0x09, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x01, 0xa4, 0x5d, 0x6c,
-	0x00, 0xe2, 0x30, 0x5c,
-	0x20, 0x33, 0x67, 0x02,
-	0x01, 0x00, 0x60, 0x32,
-	0x02, 0xa6, 0x82, 0x7c,
-	0x00, 0xe2, 0x46, 0x5c,
-	0x00, 0xe2, 0x56, 0x58,
-	0x00, 0xe2, 0x66, 0x58,
-	0x00, 0xe2, 0x3a, 0x58,
-	0x00, 0x30, 0x45, 0x59,
-	0x01, 0x30, 0x01, 0x30,
-	0x20, 0x19, 0x82, 0x6c,
-	0x00, 0xe2, 0xb2, 0x5c,
-	0x04, 0x19, 0x9c, 0x6c,
+	0x00, 0xe2, 0x14, 0x42,
+	0x01, 0xa4, 0x95, 0x6c,
+	0x00, 0xe2, 0x68, 0x5c,
+	0x20, 0x39, 0x73, 0x02,
+	0x01, 0x00, 0x6c, 0x32,
+	0x02, 0xa6, 0xba, 0x7c,
+	0x00, 0xe2, 0x7e, 0x5c,
+	0x00, 0xe2, 0x76, 0x58,
+	0x00, 0xe2, 0x86, 0x58,
+	0x00, 0xe2, 0x5a, 0x58,
+	0x00, 0x36, 0x5f, 0x59,
+	0x01, 0x36, 0x01, 0x30,
+	0x20, 0x19, 0xba, 0x6c,
+	0x00, 0xe2, 0xea, 0x5c,
+	0x04, 0x19, 0xd4, 0x6c,
 	0x02, 0x19, 0x32, 0x00,
-	0x01, 0x84, 0x9d, 0x7c,
-	0x01, 0x1b, 0x96, 0x7c,
-	0x01, 0x1a, 0x9c, 0x6c,
-	0x00, 0xe2, 0x4c, 0x44,
-	0x80, 0x4b, 0xa2, 0x6c,
-	0x01, 0x4c, 0x9e, 0x7c,
-	0x03, 0x42, 0x4c, 0x6c,
-	0x00, 0xe2, 0xe0, 0x5b,
+	0x01, 0x84, 0xd5, 0x7c,
+	0x01, 0x1b, 0xce, 0x7c,
+	0x01, 0x1a, 0xd4, 0x6c,
+	0x00, 0xe2, 0x84, 0x44,
+	0x80, 0x4b, 0xda, 0x6c,
+	0x01, 0x4c, 0xd6, 0x7c,
+	0x03, 0x42, 0x84, 0x6c,
+	0x00, 0xe2, 0x0a, 0x5c,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x04, 0x33, 0xf9, 0x79,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x08, 0x5d, 0xba, 0x6c,
-	0x00, 0xe2, 0x56, 0x58,
-	0x00, 0x30, 0x45, 0x59,
-	0x01, 0x30, 0x01, 0x30,
-	0x02, 0x1b, 0xaa, 0x7c,
-	0x08, 0x5d, 0xb8, 0x7c,
+	0x04, 0x39, 0x15, 0x7a,
+	0x00, 0xe2, 0x14, 0x42,
+	0x08, 0x5d, 0xf2, 0x6c,
+	0x00, 0xe2, 0x76, 0x58,
+	0x00, 0x36, 0x5f, 0x59,
+	0x01, 0x36, 0x01, 0x30,
+	0x02, 0x1b, 0xe2, 0x7c,
+	0x08, 0x5d, 0xf0, 0x7c,
 	0x03, 0x68, 0x00, 0x37,
 	0x01, 0x84, 0x09, 0x07,
-	0x80, 0x1b, 0xc4, 0x7c,
-	0x80, 0x84, 0xc5, 0x6c,
+	0x80, 0x1b, 0xfc, 0x7c,
+	0x80, 0x84, 0xfd, 0x6c,
 	0xff, 0x85, 0x0b, 0x1b,
 	0xff, 0x86, 0x0d, 0x23,
 	0xff, 0x87, 0x0f, 0x23,
 	0xf8, 0x1b, 0x08, 0x0b,
 	0xff, 0xea, 0x06, 0x0b,
 	0x03, 0x68, 0x00, 0x37,
-	0x00, 0xe2, 0xc4, 0x58,
+	0x00, 0xe2, 0xd6, 0x58,
 	0x10, 0xea, 0x18, 0x00,
 	0xf9, 0xd9, 0xb2, 0x0d,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x01, 0x52, 0x48, 0x31,
-	0x20, 0xa4, 0xee, 0x7c,
-	0x20, 0x5b, 0xee, 0x7c,
-	0x80, 0xf9, 0xfc, 0x7c,
+	0x20, 0xa4, 0x26, 0x7d,
+	0x20, 0x5b, 0x26, 0x7d,
+	0x80, 0xf9, 0x34, 0x7d,
 	0x02, 0xea, 0xb4, 0x00,
 	0x11, 0x00, 0x00, 0x10,
-	0x04, 0x19, 0x08, 0x7d,
+	0x04, 0x19, 0x40, 0x7d,
 	0xdf, 0x19, 0x32, 0x08,
-	0x60, 0x5b, 0xe6, 0x6c,
-	0x01, 0x4c, 0xe2, 0x7c,
+	0x60, 0x5b, 0x40, 0x6d,
+	0x01, 0x4c, 0x1a, 0x7d,
 	0x20, 0x19, 0x32, 0x00,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x02, 0xea, 0xb4, 0x00,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x10, 0x5b, 0x00, 0x6d,
-	0x08, 0x5b, 0x0a, 0x6d,
-	0x20, 0x5b, 0xfa, 0x6c,
-	0x02, 0x5b, 0x2a, 0x6d,
-	0x0e, 0xea, 0x50, 0x59,
+	0x10, 0x5b, 0x38, 0x6d,
+	0x08, 0x5b, 0x42, 0x6d,
+	0x20, 0x5b, 0x32, 0x6d,
+	0x02, 0x5b, 0x62, 0x6d,
+	0x0e, 0xea, 0x64, 0x59,
 	0x0e, 0xea, 0x04, 0x00,
-	0x80, 0xf9, 0xea, 0x6c,
+	0x80, 0xf9, 0x22, 0x6d,
 	0xdf, 0x5c, 0xb8, 0x08,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x01, 0xa4, 0xe5, 0x6d,
-	0x00, 0xe2, 0x30, 0x5c,
-	0x00, 0xe2, 0x34, 0x5d,
+	0x01, 0xa4, 0x1d, 0x6e,
+	0x00, 0xe2, 0x68, 0x5c,
+	0x00, 0xe2, 0x6c, 0x5d,
 	0x01, 0x90, 0x21, 0x1b,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x00, 0xe2, 0x32, 0x5b,
+	0x00, 0xe2, 0x52, 0x5b,
 	0xf3, 0x96, 0xd5, 0x19,
-	0x00, 0xe2, 0x18, 0x55,
-	0x80, 0x96, 0x19, 0x6d,
-	0x0f, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0x50, 0x55,
+	0x80, 0x96, 0x51, 0x6d,
+	0x0f, 0xea, 0x64, 0x59,
 	0x0f, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x20, 0x45,
+	0x00, 0xe2, 0x58, 0x45,
 	0x04, 0x8c, 0xe1, 0x30,
 	0x01, 0xea, 0xf2, 0x00,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0xff, 0x97, 0x27, 0x7d,
-	0x14, 0xea, 0x50, 0x59,
+	0xff, 0x97, 0x5f, 0x7d,
+	0x14, 0xea, 0x64, 0x59,
 	0x14, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x96, 0x5d,
+	0x00, 0xe2, 0xce, 0x5d,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x09, 0x80, 0xe1, 0x30,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x8e, 0x5d,
+	0x00, 0xe2, 0xc6, 0x5d,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x02, 0xa6, 0x44, 0x7d,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x20, 0x5b, 0x52, 0x6d,
-	0xfc, 0x42, 0x3e, 0x7d,
-	0x10, 0x40, 0x40, 0x6d,
-	0x20, 0x4d, 0x42, 0x7d,
-	0x08, 0x5d, 0x52, 0x6d,
-	0x02, 0xa6, 0xe6, 0x6b,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x20, 0x5b, 0x52, 0x6d,
-	0x01, 0x1b, 0x72, 0x6d,
-	0xfc, 0x42, 0x4e, 0x7d,
-	0x10, 0x40, 0x50, 0x6d,
-	0x20, 0x4d, 0x64, 0x78,
-	0x08, 0x5d, 0x64, 0x78,
+	0x02, 0xa6, 0x7c, 0x7d,
+	0x00, 0xe2, 0x56, 0x59,
+	0x20, 0x5b, 0x8a, 0x6d,
+	0xfc, 0x42, 0x76, 0x7d,
+	0x10, 0x40, 0x78, 0x6d,
+	0x20, 0x4d, 0x7a, 0x7d,
+	0x08, 0x5d, 0x8a, 0x6d,
+	0x02, 0xa6, 0x10, 0x6c,
+	0x00, 0xe2, 0x56, 0x59,
+	0x20, 0x5b, 0x8a, 0x6d,
+	0x01, 0x1b, 0xaa, 0x6d,
+	0xfc, 0x42, 0x86, 0x7d,
+	0x10, 0x40, 0x88, 0x6d,
+	0x20, 0x4d, 0x84, 0x78,
+	0x08, 0x5d, 0x84, 0x78,
 	0x02, 0x19, 0x32, 0x00,
 	0x01, 0x5b, 0x40, 0x31,
-	0x00, 0xe2, 0xb2, 0x5c,
-	0x00, 0xe2, 0x9e, 0x5b,
+	0x00, 0xe2, 0xea, 0x5c,
+	0x00, 0xe2, 0xcc, 0x5b,
 	0x20, 0xea, 0xb6, 0x00,
-	0x00, 0xe2, 0xe0, 0x5b,
+	0x00, 0xe2, 0x0a, 0x5c,
 	0x20, 0x5c, 0xb8, 0x00,
-	0x04, 0x19, 0x68, 0x6d,
-	0x01, 0x1a, 0x68, 0x6d,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x01, 0x1a, 0x64, 0x78,
+	0x04, 0x19, 0xa0, 0x6d,
+	0x01, 0x1a, 0xa0, 0x6d,
+	0x00, 0xe2, 0x56, 0x59,
+	0x01, 0x1a, 0x84, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x20, 0xa0, 0xcc, 0x7d,
+	0x20, 0xa0, 0x04, 0x7e,
 	0xff, 0x90, 0x21, 0x1b,
-	0x08, 0x92, 0x43, 0x6b,
+	0x08, 0x92, 0x63, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
 	0x01, 0xa4, 0x49, 0x03,
-	0x40, 0x5b, 0x82, 0x6d,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x40, 0x5b, 0x82, 0x6d,
-	0x04, 0x5d, 0xe6, 0x7d,
-	0x01, 0x1a, 0xe6, 0x7d,
-	0x20, 0x4d, 0x64, 0x78,
-	0x40, 0x5b, 0xcc, 0x7d,
-	0x04, 0x5d, 0xe6, 0x7d,
-	0x01, 0x1a, 0xe6, 0x7d,
+	0x40, 0x5b, 0xba, 0x6d,
+	0x00, 0xe2, 0x56, 0x59,
+	0x40, 0x5b, 0xba, 0x6d,
+	0x04, 0x5d, 0x1e, 0x7e,
+	0x01, 0x1a, 0x1e, 0x7e,
+	0x20, 0x4d, 0x84, 0x78,
+	0x40, 0x5b, 0x04, 0x7e,
+	0x04, 0x5d, 0x1e, 0x7e,
+	0x01, 0x1a, 0x1e, 0x7e,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0x90, 0x21, 0x1b,
-	0x08, 0x92, 0x43, 0x6b,
+	0x08, 0x92, 0x63, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x01, 0x1b, 0x64, 0x78,
+	0x00, 0xe2, 0x56, 0x59,
+	0x01, 0x1b, 0x84, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0x02, 0xea, 0xb4, 0x04,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x01, 0x1b, 0xaa, 0x6d,
-	0x40, 0x5b, 0xb8, 0x7d,
-	0x01, 0x1b, 0xaa, 0x6d,
+	0x00, 0xe2, 0x56, 0x59,
+	0x01, 0x1b, 0xe2, 0x6d,
+	0x40, 0x5b, 0xf0, 0x7d,
+	0x01, 0x1b, 0xe2, 0x6d,
 	0x02, 0x19, 0x32, 0x00,
-	0x01, 0x1a, 0x64, 0x78,
+	0x01, 0x1a, 0x84, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0xea, 0x10, 0x03,
 	0x08, 0x92, 0x25, 0x03,
-	0x00, 0xe2, 0x42, 0x43,
-	0x01, 0x1a, 0xb4, 0x7d,
-	0x40, 0x5b, 0xb0, 0x7d,
-	0x01, 0x1a, 0x9e, 0x6d,
-	0xfc, 0x42, 0x64, 0x78,
-	0x01, 0x1a, 0xb8, 0x6d,
-	0x10, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0x62, 0x43,
+	0x01, 0x1a, 0xec, 0x7d,
+	0x40, 0x5b, 0xe8, 0x7d,
+	0x01, 0x1a, 0xd6, 0x6d,
+	0xfc, 0x42, 0x84, 0x78,
+	0x01, 0x1a, 0xf0, 0x6d,
+	0x10, 0xea, 0x64, 0x59,
 	0x10, 0xea, 0x04, 0x00,
-	0xfc, 0x42, 0x64, 0x78,
-	0x10, 0x40, 0xbe, 0x6d,
-	0x20, 0x4d, 0x64, 0x78,
-	0x40, 0x5b, 0x9e, 0x6d,
-	0x01, 0x1a, 0x64, 0x78,
+	0xfc, 0x42, 0x84, 0x78,
+	0x10, 0x40, 0xf6, 0x6d,
+	0x20, 0x4d, 0x84, 0x78,
+	0x40, 0x5b, 0xd6, 0x6d,
+	0x01, 0x1a, 0x84, 0x78,
 	0x01, 0x90, 0x21, 0x1b,
 	0x30, 0x3f, 0xc0, 0x09,
-	0x30, 0xe0, 0x64, 0x60,
-	0x40, 0x4b, 0x64, 0x68,
+	0x30, 0xe0, 0x84, 0x60,
+	0x40, 0x4b, 0x84, 0x68,
 	0xff, 0xea, 0x52, 0x01,
-	0xee, 0x00, 0xd2, 0x6d,
+	0xee, 0x00, 0x0c, 0x6e,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0x90, 0x21, 0x1b,
 	0x02, 0xea, 0xb4, 0x00,
 	0x20, 0xea, 0x9a, 0x00,
-	0xf3, 0x42, 0xde, 0x6d,
-	0x12, 0xea, 0x50, 0x59,
+	0xf3, 0x42, 0x16, 0x6e,
+	0x12, 0xea, 0x64, 0x59,
 	0x12, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x0d, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0x14, 0x42,
+	0x0d, 0xea, 0x64, 0x59,
 	0x0d, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
+	0x00, 0xe2, 0x14, 0x42,
 	0x01, 0x90, 0x21, 0x1b,
-	0x11, 0xea, 0x50, 0x59,
+	0x11, 0xea, 0x64, 0x59,
 	0x11, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x32, 0x5b,
+	0x00, 0xe2, 0x52, 0x5b,
 	0x08, 0x5a, 0xb4, 0x00,
-	0x00, 0xe2, 0x0c, 0x5e,
+	0x00, 0xe2, 0x44, 0x5e,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x3e, 0x59,
-	0x80, 0x1a, 0xfa, 0x7d,
-	0x00, 0xe2, 0x0c, 0x5e,
+	0x00, 0xe2, 0x56, 0x59,
+	0x80, 0x1a, 0x32, 0x7e,
+	0x00, 0xe2, 0x44, 0x5e,
 	0x80, 0x19, 0x32, 0x00,
-	0x40, 0x5b, 0x00, 0x6e,
-	0x08, 0x5a, 0x00, 0x7e,
-	0x20, 0x4d, 0x64, 0x78,
+	0x40, 0x5b, 0x38, 0x6e,
+	0x08, 0x5a, 0x38, 0x7e,
+	0x20, 0x4d, 0x84, 0x78,
 	0x02, 0x84, 0x09, 0x03,
-	0x40, 0x5b, 0xcc, 0x7d,
+	0x40, 0x5b, 0x04, 0x7e,
 	0xff, 0x90, 0x21, 0x1b,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x08, 0x92, 0x43, 0x6b,
+	0x08, 0x92, 0x63, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
-	0x01, 0x38, 0xe1, 0x30,
-	0x05, 0x39, 0xe3, 0x98,
+	0x01, 0x40, 0xe1, 0x30,
+	0x05, 0x41, 0xe3, 0x98,
 	0x01, 0xe0, 0xf4, 0x31,
 	0xff, 0xea, 0xc0, 0x09,
-	0x00, 0x3a, 0xe5, 0x20,
-	0x00, 0x3b, 0xe7, 0x20,
+	0x00, 0x42, 0xe5, 0x20,
+	0x00, 0x43, 0xe7, 0x20,
 	0x01, 0xfa, 0xc0, 0x31,
 	0x04, 0xea, 0xe8, 0x30,
 	0xff, 0xea, 0xf0, 0x08,
@@ -794,12 +822,20 @@
 };
 
 typedef int ahd_patch_func_t (struct ahd_softc *ahd);
+static ahd_patch_func_t ahd_patch23_func;
+
+static int
+ahd_patch23_func(struct ahd_softc *ahd)
+{
+	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+}
+
 static ahd_patch_func_t ahd_patch22_func;
 
 static int
 ahd_patch22_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
 }
 
 static ahd_patch_func_t ahd_patch21_func;
@@ -807,7 +843,7 @@
 static int
 ahd_patch21_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
+	return ((ahd->flags & AHD_INITIATORROLE) != 0);
 }
 
 static ahd_patch_func_t ahd_patch20_func;
@@ -815,7 +851,7 @@
 static int
 ahd_patch20_func(struct ahd_softc *ahd)
 {
-	return ((ahd->features & AHD_RTI) == 0);
+	return ((ahd->flags & AHD_TARGETROLE) != 0);
 }
 
 static ahd_patch_func_t ahd_patch19_func;
@@ -823,7 +859,7 @@
 static int
 ahd_patch19_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_INITIATORROLE) != 0);
+	return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch18_func;
@@ -831,7 +867,7 @@
 static int
 ahd_patch18_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_TARGETROLE) != 0);
+	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
 }
 
 static ahd_patch_func_t ahd_patch17_func;
@@ -839,7 +875,7 @@
 static int
 ahd_patch17_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
+	return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
 }
 
 static ahd_patch_func_t ahd_patch16_func;
@@ -847,7 +883,7 @@
 static int
 ahd_patch16_func(struct ahd_softc *ahd)
 {
-	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
+	return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
 }
 
 static ahd_patch_func_t ahd_patch15_func;
@@ -855,7 +891,7 @@
 static int
 ahd_patch15_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
+	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
 }
 
 static ahd_patch_func_t ahd_patch14_func;
@@ -863,7 +899,7 @@
 static int
 ahd_patch14_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
+	return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch13_func;
@@ -871,7 +907,7 @@
 static int
 ahd_patch13_func(struct ahd_softc *ahd)
 {
-	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
+	return ((ahd->features & AHD_RTI) == 0);
 }
 
 static ahd_patch_func_t ahd_patch12_func;
@@ -879,7 +915,7 @@
 static int
 ahd_patch12_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
+	return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch11_func;
@@ -887,7 +923,7 @@
 static int
 ahd_patch11_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
+	return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
 }
 
 static ahd_patch_func_t ahd_patch10_func;
@@ -895,7 +931,7 @@
 static int
 ahd_patch10_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
+	return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch9_func;
@@ -903,7 +939,7 @@
 static int
 ahd_patch9_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
+	return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0);
 }
 
 static ahd_patch_func_t ahd_patch8_func;
@@ -992,147 +1028,149 @@
 	{ ahd_patch0_func, 5, 1, 1 },
 	{ ahd_patch2_func, 6, 1, 2 },
 	{ ahd_patch0_func, 7, 1, 1 },
-	{ ahd_patch3_func, 20, 5, 1 },
-	{ ahd_patch2_func, 29, 1, 2 },
-	{ ahd_patch0_func, 30, 1, 1 },
-	{ ahd_patch1_func, 37, 1, 2 },
-	{ ahd_patch0_func, 38, 1, 1 },
-	{ ahd_patch2_func, 43, 1, 2 },
-	{ ahd_patch0_func, 44, 1, 1 },
-	{ ahd_patch2_func, 47, 1, 2 },
-	{ ahd_patch0_func, 48, 1, 1 },
-	{ ahd_patch2_func, 51, 1, 2 },
-	{ ahd_patch0_func, 52, 1, 1 },
-	{ ahd_patch2_func, 65, 1, 2 },
-	{ ahd_patch0_func, 66, 1, 1 },
-	{ ahd_patch2_func, 69, 1, 2 },
-	{ ahd_patch0_func, 70, 1, 1 },
-	{ ahd_patch1_func, 73, 1, 2 },
-	{ ahd_patch0_func, 74, 1, 1 },
-	{ ahd_patch4_func, 107, 1, 1 },
-	{ ahd_patch2_func, 162, 6, 1 },
-	{ ahd_patch1_func, 168, 2, 1 },
-	{ ahd_patch5_func, 170, 1, 1 },
-	{ ahd_patch2_func, 179, 1, 2 },
-	{ ahd_patch0_func, 180, 1, 1 },
-	{ ahd_patch6_func, 181, 2, 2 },
-	{ ahd_patch0_func, 183, 6, 3 },
-	{ ahd_patch2_func, 186, 1, 2 },
-	{ ahd_patch0_func, 187, 1, 1 },
-	{ ahd_patch2_func, 190, 1, 2 },
-	{ ahd_patch0_func, 191, 1, 1 },
-	{ ahd_patch7_func, 193, 2, 1 },
-	{ ahd_patch5_func, 201, 16, 2 },
-	{ ahd_patch0_func, 217, 1, 1 },
-	{ ahd_patch8_func, 237, 2, 1 },
-	{ ahd_patch1_func, 241, 1, 2 },
-	{ ahd_patch0_func, 242, 1, 1 },
-	{ ahd_patch7_func, 245, 2, 1 },
-	{ ahd_patch1_func, 259, 1, 2 },
-	{ ahd_patch0_func, 260, 1, 1 },
-	{ ahd_patch1_func, 263, 1, 2 },
-	{ ahd_patch0_func, 264, 1, 1 },
-	{ ahd_patch2_func, 267, 1, 2 },
-	{ ahd_patch0_func, 268, 1, 1 },
-	{ ahd_patch1_func, 323, 1, 2 },
-	{ ahd_patch0_func, 324, 1, 1 },
-	{ ahd_patch2_func, 332, 1, 2 },
-	{ ahd_patch0_func, 333, 1, 1 },
-	{ ahd_patch2_func, 336, 1, 2 },
-	{ ahd_patch0_func, 337, 1, 1 },
-	{ ahd_patch1_func, 343, 1, 2 },
-	{ ahd_patch0_func, 344, 1, 1 },
-	{ ahd_patch1_func, 346, 1, 2 },
-	{ ahd_patch0_func, 347, 1, 1 },
-	{ ahd_patch9_func, 366, 1, 1 },
-	{ ahd_patch9_func, 369, 1, 1 },
-	{ ahd_patch9_func, 371, 1, 1 },
-	{ ahd_patch9_func, 383, 1, 1 },
-	{ ahd_patch1_func, 393, 1, 2 },
-	{ ahd_patch0_func, 394, 1, 1 },
-	{ ahd_patch1_func, 396, 1, 2 },
-	{ ahd_patch0_func, 397, 1, 1 },
-	{ ahd_patch1_func, 405, 1, 2 },
-	{ ahd_patch0_func, 406, 1, 1 },
-	{ ahd_patch2_func, 419, 1, 2 },
-	{ ahd_patch0_func, 420, 1, 1 },
-	{ ahd_patch10_func, 450, 1, 1 },
-	{ ahd_patch1_func, 457, 1, 2 },
-	{ ahd_patch0_func, 458, 1, 1 },
-	{ ahd_patch2_func, 470, 1, 2 },
-	{ ahd_patch0_func, 471, 1, 1 },
-	{ ahd_patch11_func, 476, 6, 2 },
-	{ ahd_patch0_func, 482, 1, 1 },
-	{ ahd_patch12_func, 505, 1, 1 },
-	{ ahd_patch13_func, 514, 1, 1 },
-	{ ahd_patch14_func, 515, 1, 2 },
-	{ ahd_patch0_func, 516, 1, 1 },
-	{ ahd_patch15_func, 519, 1, 1 },
-	{ ahd_patch14_func, 520, 1, 1 },
-	{ ahd_patch16_func, 531, 1, 2 },
-	{ ahd_patch0_func, 532, 1, 1 },
-	{ ahd_patch1_func, 551, 1, 2 },
-	{ ahd_patch0_func, 552, 1, 1 },
-	{ ahd_patch1_func, 555, 1, 2 },
-	{ ahd_patch0_func, 556, 1, 1 },
-	{ ahd_patch2_func, 561, 1, 2 },
-	{ ahd_patch0_func, 562, 1, 1 },
-	{ ahd_patch2_func, 566, 1, 2 },
-	{ ahd_patch0_func, 567, 1, 1 },
-	{ ahd_patch1_func, 568, 1, 2 },
-	{ ahd_patch0_func, 569, 1, 1 },
-	{ ahd_patch2_func, 580, 1, 2 },
-	{ ahd_patch0_func, 581, 1, 1 },
-	{ ahd_patch17_func, 585, 1, 1 },
-	{ ahd_patch18_func, 590, 1, 1 },
-	{ ahd_patch19_func, 591, 2, 1 },
-	{ ahd_patch18_func, 595, 1, 2 },
-	{ ahd_patch0_func, 596, 1, 1 },
-	{ ahd_patch2_func, 599, 1, 2 },
-	{ ahd_patch0_func, 600, 1, 1 },
-	{ ahd_patch2_func, 615, 1, 2 },
-	{ ahd_patch0_func, 616, 1, 1 },
-	{ ahd_patch20_func, 617, 14, 1 },
-	{ ahd_patch1_func, 635, 1, 2 },
-	{ ahd_patch0_func, 636, 1, 1 },
-	{ ahd_patch20_func, 637, 1, 1 },
-	{ ahd_patch1_func, 649, 1, 2 },
-	{ ahd_patch0_func, 650, 1, 1 },
-	{ ahd_patch1_func, 657, 1, 2 },
-	{ ahd_patch0_func, 658, 1, 1 },
-	{ ahd_patch17_func, 681, 1, 1 },
-	{ ahd_patch17_func, 719, 1, 1 },
-	{ ahd_patch1_func, 730, 1, 2 },
-	{ ahd_patch0_func, 731, 1, 1 },
-	{ ahd_patch1_func, 748, 1, 2 },
-	{ ahd_patch0_func, 749, 1, 1 },
-	{ ahd_patch1_func, 751, 1, 2 },
-	{ ahd_patch0_func, 752, 1, 1 },
-	{ ahd_patch1_func, 755, 1, 2 },
-	{ ahd_patch0_func, 756, 1, 1 },
-	{ ahd_patch21_func, 758, 1, 2 },
-	{ ahd_patch0_func, 759, 2, 1 },
-	{ ahd_patch22_func, 762, 4, 2 },
-	{ ahd_patch0_func, 766, 1, 1 },
-	{ ahd_patch22_func, 774, 11, 1 }
+	{ ahd_patch3_func, 36, 5, 1 },
+	{ ahd_patch2_func, 45, 1, 2 },
+	{ ahd_patch0_func, 46, 1, 1 },
+	{ ahd_patch1_func, 53, 1, 2 },
+	{ ahd_patch0_func, 54, 1, 1 },
+	{ ahd_patch2_func, 59, 1, 2 },
+	{ ahd_patch0_func, 60, 1, 1 },
+	{ ahd_patch2_func, 63, 1, 2 },
+	{ ahd_patch0_func, 64, 1, 1 },
+	{ ahd_patch2_func, 67, 1, 2 },
+	{ ahd_patch0_func, 68, 1, 1 },
+	{ ahd_patch4_func, 116, 1, 1 },
+	{ ahd_patch2_func, 175, 3, 1 },
+	{ ahd_patch1_func, 178, 2, 1 },
+	{ ahd_patch5_func, 180, 1, 1 },
+	{ ahd_patch2_func, 189, 1, 2 },
+	{ ahd_patch0_func, 190, 1, 1 },
+	{ ahd_patch6_func, 191, 2, 2 },
+	{ ahd_patch0_func, 193, 6, 3 },
+	{ ahd_patch2_func, 196, 1, 2 },
+	{ ahd_patch0_func, 197, 1, 1 },
+	{ ahd_patch2_func, 200, 1, 2 },
+	{ ahd_patch0_func, 201, 1, 1 },
+	{ ahd_patch3_func, 203, 1, 1 },
+	{ ahd_patch7_func, 204, 3, 1 },
+	{ ahd_patch3_func, 213, 1, 1 },
+	{ ahd_patch5_func, 214, 16, 2 },
+	{ ahd_patch0_func, 230, 1, 1 },
+	{ ahd_patch8_func, 250, 2, 1 },
+	{ ahd_patch1_func, 254, 1, 2 },
+	{ ahd_patch0_func, 255, 1, 1 },
+	{ ahd_patch7_func, 258, 3, 1 },
+	{ ahd_patch1_func, 273, 1, 2 },
+	{ ahd_patch0_func, 274, 1, 1 },
+	{ ahd_patch1_func, 277, 1, 2 },
+	{ ahd_patch0_func, 278, 1, 1 },
+	{ ahd_patch2_func, 281, 1, 2 },
+	{ ahd_patch0_func, 282, 1, 1 },
+	{ ahd_patch9_func, 295, 2, 2 },
+	{ ahd_patch0_func, 297, 1, 1 },
+	{ ahd_patch1_func, 339, 1, 2 },
+	{ ahd_patch0_func, 340, 1, 1 },
+	{ ahd_patch2_func, 348, 1, 2 },
+	{ ahd_patch0_func, 349, 1, 1 },
+	{ ahd_patch2_func, 352, 1, 2 },
+	{ ahd_patch0_func, 353, 1, 1 },
+	{ ahd_patch1_func, 359, 1, 2 },
+	{ ahd_patch0_func, 360, 1, 1 },
+	{ ahd_patch1_func, 362, 1, 2 },
+	{ ahd_patch0_func, 363, 1, 1 },
+	{ ahd_patch10_func, 382, 1, 1 },
+	{ ahd_patch10_func, 385, 1, 1 },
+	{ ahd_patch10_func, 387, 1, 1 },
+	{ ahd_patch10_func, 399, 1, 1 },
+	{ ahd_patch1_func, 409, 1, 2 },
+	{ ahd_patch0_func, 410, 1, 1 },
+	{ ahd_patch1_func, 412, 1, 2 },
+	{ ahd_patch0_func, 413, 1, 1 },
+	{ ahd_patch1_func, 421, 1, 2 },
+	{ ahd_patch0_func, 422, 1, 1 },
+	{ ahd_patch2_func, 435, 1, 2 },
+	{ ahd_patch0_func, 436, 1, 1 },
+	{ ahd_patch11_func, 472, 1, 1 },
+	{ ahd_patch1_func, 480, 1, 2 },
+	{ ahd_patch0_func, 481, 1, 1 },
+	{ ahd_patch2_func, 493, 1, 2 },
+	{ ahd_patch0_func, 494, 1, 1 },
+	{ ahd_patch12_func, 497, 6, 2 },
+	{ ahd_patch0_func, 503, 1, 1 },
+	{ ahd_patch13_func, 524, 7, 1 },
+	{ ahd_patch14_func, 533, 1, 1 },
+	{ ahd_patch15_func, 542, 1, 1 },
+	{ ahd_patch16_func, 543, 1, 2 },
+	{ ahd_patch0_func, 544, 1, 1 },
+	{ ahd_patch17_func, 547, 1, 1 },
+	{ ahd_patch16_func, 548, 1, 1 },
+	{ ahd_patch18_func, 559, 1, 2 },
+	{ ahd_patch0_func, 560, 1, 1 },
+	{ ahd_patch1_func, 579, 1, 2 },
+	{ ahd_patch0_func, 580, 1, 1 },
+	{ ahd_patch1_func, 583, 1, 2 },
+	{ ahd_patch0_func, 584, 1, 1 },
+	{ ahd_patch2_func, 589, 1, 2 },
+	{ ahd_patch0_func, 590, 1, 1 },
+	{ ahd_patch2_func, 594, 1, 2 },
+	{ ahd_patch0_func, 595, 1, 1 },
+	{ ahd_patch1_func, 596, 1, 2 },
+	{ ahd_patch0_func, 597, 1, 1 },
+	{ ahd_patch2_func, 608, 1, 2 },
+	{ ahd_patch0_func, 609, 1, 1 },
+	{ ahd_patch19_func, 613, 1, 1 },
+	{ ahd_patch20_func, 618, 1, 1 },
+	{ ahd_patch21_func, 619, 2, 1 },
+	{ ahd_patch20_func, 623, 1, 2 },
+	{ ahd_patch0_func, 624, 1, 1 },
+	{ ahd_patch2_func, 627, 1, 2 },
+	{ ahd_patch0_func, 628, 1, 1 },
+	{ ahd_patch2_func, 643, 1, 2 },
+	{ ahd_patch0_func, 644, 1, 1 },
+	{ ahd_patch13_func, 645, 14, 1 },
+	{ ahd_patch1_func, 663, 1, 2 },
+	{ ahd_patch0_func, 664, 1, 1 },
+	{ ahd_patch13_func, 665, 1, 1 },
+	{ ahd_patch1_func, 677, 1, 2 },
+	{ ahd_patch0_func, 678, 1, 1 },
+	{ ahd_patch1_func, 685, 1, 2 },
+	{ ahd_patch0_func, 686, 1, 1 },
+	{ ahd_patch19_func, 709, 1, 1 },
+	{ ahd_patch19_func, 747, 1, 1 },
+	{ ahd_patch1_func, 758, 1, 2 },
+	{ ahd_patch0_func, 759, 1, 1 },
+	{ ahd_patch1_func, 776, 1, 2 },
+	{ ahd_patch0_func, 777, 1, 1 },
+	{ ahd_patch1_func, 779, 1, 2 },
+	{ ahd_patch0_func, 780, 1, 1 },
+	{ ahd_patch1_func, 783, 1, 2 },
+	{ ahd_patch0_func, 784, 1, 1 },
+	{ ahd_patch22_func, 786, 1, 2 },
+	{ ahd_patch0_func, 787, 2, 1 },
+	{ ahd_patch23_func, 790, 4, 2 },
+	{ ahd_patch0_func, 794, 1, 1 },
+	{ ahd_patch23_func, 802, 11, 1 }
 };
 
 static struct cs {
 	uint16_t	begin;
 	uint16_t	end;
 } critical_sections[] = {
-	{ 11, 12 },
-	{ 13, 14 },
-	{ 29, 42 },
-	{ 56, 59 },
-	{ 101, 128 },
-	{ 129, 157 },
-	{ 159, 162 },
-	{ 170, 178 },
-	{ 201, 250 },
-	{ 681, 697 },
-	{ 697, 711 },
-	{ 721, 725 }
+	{ 17, 28 },
+	{ 29, 30 },
+	{ 47, 58 },
+	{ 61, 63 },
+	{ 65, 66 },
+	{ 72, 92 },
+	{ 110, 137 },
+	{ 138, 175 },
+	{ 180, 188 },
+	{ 213, 264 },
+	{ 425, 433 },
+	{ 443, 445 },
+	{ 448, 457 },
+	{ 709, 739 },
+	{ 749, 753 }
 };
 
 static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index fd389e9..051970e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -375,7 +375,7 @@
 					 struct scsi_cmnd *cmd);
 static void ahc_linux_sem_timeout(u_long arg);
 static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
-static void ahc_linux_release_simq(u_long arg);
+static void ahc_linux_release_simq(struct ahc_softc *ahc);
 static int  ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
 static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
 static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
@@ -1073,7 +1073,6 @@
 		return (ENOMEM);
 
 	*((struct ahc_softc **)host->hostdata) = ahc;
-	ahc_lock(ahc, &s);
 	ahc->platform_data->host = host;
 	host->can_queue = AHC_MAX_QUEUE;
 	host->cmd_per_lun = 2;
@@ -1084,7 +1083,9 @@
 	host->max_lun = AHC_NUM_LUNS;
 	host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
 	host->sg_tablesize = AHC_NSEG;
+	ahc_lock(ahc, &s);
 	ahc_set_unit(ahc, ahc_linux_unit++);
+	ahc_unlock(ahc, &s);
 	sprintf(buf, "scsi%d", host->host_no);
 	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	if (new_name != NULL) {
@@ -1094,7 +1095,6 @@
 	host->unique_id = ahc->unit;
 	ahc_linux_initialize_scsi_bus(ahc);
 	ahc_intr_enable(ahc, TRUE);
-	ahc_unlock(ahc, &s);
 
 	host->transportt = ahc_linux_transport_template;
 
@@ -1120,10 +1120,13 @@
 {
 	int i;
 	int numtarg;
+	unsigned long s;
 
 	i = 0;
 	numtarg = 0;
 
+	ahc_lock(ahc, &s);
+
 	if (aic7xxx_no_reset != 0)
 		ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);
 
@@ -1170,16 +1173,12 @@
 		ahc_update_neg_request(ahc, &devinfo, tstate,
 				       tinfo, AHC_NEG_ALWAYS);
 	}
+	ahc_unlock(ahc, &s);
 	/* Give the bus some time to recover */
 	if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
 		ahc_linux_freeze_simq(ahc);
-		init_timer(&ahc->platform_data->reset_timer);
-		ahc->platform_data->reset_timer.data = (u_long)ahc;
-		ahc->platform_data->reset_timer.expires =
-		    jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
-		ahc->platform_data->reset_timer.function =
-		    ahc_linux_release_simq;
-		add_timer(&ahc->platform_data->reset_timer);
+		msleep(AIC7XXX_RESET_DELAY);
+		ahc_linux_release_simq(ahc);
 	}
 }
 
@@ -2059,6 +2058,9 @@
 static void
 ahc_linux_freeze_simq(struct ahc_softc *ahc)
 {
+	unsigned long s;
+
+	ahc_lock(ahc, &s);
 	ahc->platform_data->qfrozen++;
 	if (ahc->platform_data->qfrozen == 1) {
 		scsi_block_requests(ahc->platform_data->host);
@@ -2068,17 +2070,15 @@
 					CAM_LUN_WILDCARD, SCB_LIST_NULL,
 					ROLE_INITIATOR, CAM_REQUEUE_REQ);
 	}
+	ahc_unlock(ahc, &s);
 }
 
 static void
-ahc_linux_release_simq(u_long arg)
+ahc_linux_release_simq(struct ahc_softc *ahc)
 {
-	struct ahc_softc *ahc;
 	u_long s;
 	int    unblock_reqs;
 
-	ahc = (struct ahc_softc *)arg;
-
 	unblock_reqs = 0;
 	ahc_lock(ahc, &s);
 	if (ahc->platform_data->qfrozen > 0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index f2a9544..e0edaca 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -223,9 +223,6 @@
  */
 #define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op)
 
-/************************** Timer DataStructures ******************************/
-typedef struct timer_list ahc_timer_t;
-
 /********************************** Includes **********************************/
 #ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
 #define AIC_DEBUG_REGISTERS 1
@@ -235,30 +232,9 @@
 #include "aic7xxx.h"
 
 /***************************** Timer Facilities *******************************/
-#define ahc_timer_init init_timer
-#define ahc_timer_stop del_timer_sync
-typedef void ahc_linux_callback_t (u_long);  
-static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
-				     ahc_callback_t *func, void *arg);
-static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec);
-
-static __inline void
-ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg)
-{
-	struct ahc_softc *ahc;
-
-	ahc = (struct ahc_softc *)arg;
-	del_timer(timer);
-	timer->data = (u_long)arg;
-	timer->expires = jiffies + (usec * HZ)/1000000;
-	timer->function = (ahc_linux_callback_t*)func;
-	add_timer(timer);
-}
-
 static __inline void
 ahc_scb_timer_reset(struct scb *scb, u_int usec)
 {
-	mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
 }
 
 /***************************** SMP support ************************************/
@@ -393,7 +369,6 @@
 
 	spinlock_t		 spin_lock;
 	u_int			 qfrozen;
-	struct timer_list	 reset_timer;
 	struct semaphore	 eh_sem;
 	struct Scsi_Host        *host;		/* pointer to scsi host */
 #define AHC_LINUX_NOIRQ	((uint32_t)~0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index b3b2e22..5f58614 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -39,9 +39,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $
  */
 
 #ifdef __linux__
@@ -393,6 +391,12 @@
 		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
 		ahc_aic7892_setup
 	},
+	{
+		ID_AHA_2915_30LP,
+		ID_ALL_MASK,
+		"Adaptec 2915/30LP Ultra160 SCSI adapter",
+		ahc_aic7892_setup
+	},
 	/* aic7895 based controllers */	
 	{
 		ID_AHA_2940U_DUAL,
@@ -1193,9 +1197,19 @@
 	 * use for this test.
 	 */
 	hcntrl = ahc_inb(ahc, HCNTRL);
+
 	if (hcntrl == 0xFF)
 		goto fail;
 
+	if ((hcntrl & CHIPRST) != 0) {
+		/*
+		 * The chip has not been initialized since
+		 * PCI/EISA/VLB bus reset.  Don't trust
+		 * "left over BIOS data".
+		 */
+		ahc->flags |= AHC_NO_BIOS_INIT;
+	}
+
 	/*
 	 * Next create a situation where write combining
 	 * or read prefetching could be initiated by the
@@ -1307,6 +1321,10 @@
 			sd.sd_chip = C56_66;
 		}
 		ahc_release_seeprom(&sd);
+
+		/* Remember the SEEPROM type for later */
+		if (sd.sd_chip == C56_66)
+			ahc->flags |= AHC_LARGE_SEEPROM;
 	}
 
 	if (!have_seeprom) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.h b/drivers/scsi/aic7xxx/aic7xxx_pci.h
index be27fcb..263f85d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.h
@@ -105,6 +105,7 @@
 #define ID_AHA_29160C			0x0080900562209005ull
 #define ID_AHA_29160B			0x00809005E2209005ull
 #define ID_AHA_19160B			0x0081900562A19005ull
+#define ID_AHA_2915_30LP		0x0082900502109005ull
 
 #define ID_AIC7896			0x005F9005FFFF9005ull
 #define ID_AIC7896_ARO			0x00539005FFFF9005ull
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 4299fab..c3f2728 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -22,6 +22,7 @@
 #include <linux/completion.h>
 #include <linux/compat.h>
 #include <linux/chio.h>			/* here are all the ioctls */
+#include <linux/mutex.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -111,7 +112,7 @@
 	u_int               counts[CH_TYPES];
 	u_int               unit_attention;
 	u_int		    voltags;
-	struct semaphore    lock;
+	struct mutex	    lock;
 } scsi_changer;
 
 static LIST_HEAD(ch_devlist);
@@ -565,7 +566,7 @@
 	u_char data[16];
 	unsigned int i;
 	
-	down(&ch->lock);
+	mutex_lock(&ch->lock);
 	for (i = 0; i < ch->counts[type]; i++) {
 		if (0 != ch_read_element_status
 		    (ch, ch->firsts[type]+i,data)) {
@@ -582,7 +583,7 @@
 		if (0 != retval)
 			break;
 	}
-	up(&ch->lock);
+	mutex_unlock(&ch->lock);
 	return retval;
 }
 
@@ -687,11 +688,11 @@
 			dprintk("CHIOPOSITION: invalid parameter\n");
 			return -EBADSLT;
 		}
-		down(&ch->lock);
+		mutex_lock(&ch->lock);
 		retval = ch_position(ch,0,
 				     ch->firsts[pos.cp_type] + pos.cp_unit,
 				     pos.cp_flags & CP_INVERT);
-		up(&ch->lock);
+		mutex_unlock(&ch->lock);
 		return retval;
 	}
 	
@@ -708,12 +709,12 @@
 			return -EBADSLT;
 		}
 		
-		down(&ch->lock);
+		mutex_lock(&ch->lock);
 		retval = ch_move(ch,0,
 				 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
 				 ch->firsts[mv.cm_totype]   + mv.cm_tounit,
 				 mv.cm_flags & CM_INVERT);
-		up(&ch->lock);
+		mutex_unlock(&ch->lock);
 		return retval;
 	}
 
@@ -731,14 +732,14 @@
 			return -EBADSLT;
 		}
 		
-		down(&ch->lock);
+		mutex_lock(&ch->lock);
 		retval = ch_exchange
 			(ch,0,
 			 ch->firsts[mv.ce_srctype]  + mv.ce_srcunit,
 			 ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
 			 ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
 			 mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
-		up(&ch->lock);
+		mutex_unlock(&ch->lock);
 		return retval;
 	}
 
@@ -772,7 +773,7 @@
 		buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 		if (!buffer)
 			return -ENOMEM;
-		down(&ch->lock);
+		mutex_lock(&ch->lock);
 		
 	voltag_retry:
 		memset(cmd,0,sizeof(cmd));
@@ -823,7 +824,7 @@
 			goto voltag_retry;
 		}
 		kfree(buffer);
-		up(&ch->lock);
+		mutex_unlock(&ch->lock);
 		
 		if (copy_to_user(argp, &cge, sizeof (cge)))
 			return -EFAULT;
@@ -832,9 +833,9 @@
 
 	case CHIOINITELEM:
 	{
-		down(&ch->lock);
+		mutex_lock(&ch->lock);
 		retval = ch_init_elem(ch);
-		up(&ch->lock);
+		mutex_unlock(&ch->lock);
 		return retval;
 	}
 		
@@ -851,12 +852,12 @@
 			return -EBADSLT;
 		}
 		elem = ch->firsts[csv.csv_type] + csv.csv_unit;
-		down(&ch->lock);
+		mutex_lock(&ch->lock);
 		retval = ch_set_voltag(ch, elem,
 				       csv.csv_flags & CSV_AVOLTAG,
 				       csv.csv_flags & CSV_CLEARTAG,
 				       csv.csv_voltag);
-		up(&ch->lock);
+		mutex_unlock(&ch->lock);
 		return retval;
 	}
 
@@ -929,7 +930,7 @@
 	memset(ch,0,sizeof(*ch));
 	ch->minor = ch_devcount;
 	sprintf(ch->name,"ch%d",ch->minor);
-	init_MUTEX(&ch->lock);
+	mutex_init(&ch->lock);
 	ch->device = sd;
 	ch_readconfig(ch);
 	if (init)
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 6252b9d..6e6b293 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -61,6 +61,7 @@
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
+#include <linux/mutex.h>
 
 #include <asm/processor.h>	/* for boot_cpu_data */
 #include <asm/pgtable.h>
@@ -106,7 +107,7 @@
  *============================================================================
  */
 
-static DECLARE_MUTEX(adpt_configuration_lock);
+static DEFINE_MUTEX(adpt_configuration_lock);
 
 static struct i2o_sys_tbl *sys_tbl = NULL;
 static int sys_tbl_ind = 0;
@@ -537,13 +538,13 @@
 	 */
 
 	// Find HBA (host bus adapter) we are looking for
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
 		if (pHba->host == host) {
 			break;	/* found adapter */
 		}
 	}
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 	if (pHba == NULL) {
 		return 0;
 	}
@@ -898,6 +899,12 @@
 	if(pci_enable_device(pDev)) {
 		return -EINVAL;
 	}
+
+	if (pci_request_regions(pDev, "dpt_i2o")) {
+		PERROR("dpti: adpt_config_hba: pci request region failed\n");
+		return -EINVAL;
+	}
+
 	pci_set_master(pDev);
 	if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) &&
 	    pci_set_dma_mask(pDev, 0xffffffffULL))
@@ -923,10 +930,6 @@
 		raptorFlag = TRUE;
 	}
 
-	if (pci_request_regions(pDev, "dpt_i2o")) {
-		PERROR("dpti: adpt_config_hba: pci request region failed\n");
-		return -EINVAL;
-	}
 	base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
 	if (!base_addr_virt) {
 		pci_release_regions(pDev);
@@ -958,7 +961,7 @@
 	}
 	memset(pHba, 0, sizeof(adpt_hba));
 
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 
 	if(hba_chain != NULL){
 		for(p = hba_chain; p->next; p = p->next);
@@ -971,7 +974,7 @@
 	sprintf(pHba->name, "dpti%d", hba_count);
 	hba_count++;
 	
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 
 	pHba->pDev = pDev;
 	pHba->base_addr_phys = base_addr0_phys;
@@ -1027,7 +1030,7 @@
 	struct adpt_device* pNext;
 
 
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 	// scsi_unregister calls our adpt_release which
 	// does a quiese
 	if(pHba->host){
@@ -1046,7 +1049,7 @@
 	}
 
 	hba_count--;
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 
 	iounmap(pHba->base_addr_virt);
 	pci_release_regions(pHba->pDev);
@@ -1549,7 +1552,7 @@
  
 static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
 {
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 	d->controller=pHba;
 	d->owner=NULL;
 	d->next=pHba->devices;
@@ -1560,7 +1563,7 @@
 	pHba->devices=d;
 	*d->dev_name = 0;
 
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 	return 0;
 }
 
@@ -1575,24 +1578,24 @@
 	if (minor >= hba_count) {
 		return -ENXIO;
 	}
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
 		if (pHba->unit == minor) {
 			break;	/* found adapter */
 		}
 	}
 	if (pHba == NULL) {
-		up(&adpt_configuration_lock);
+		mutex_unlock(&adpt_configuration_lock);
 		return -ENXIO;
 	}
 
 //	if(pHba->in_use){
-	//	up(&adpt_configuration_lock);
+	//	mutex_unlock(&adpt_configuration_lock);
 //		return -EBUSY;
 //	}
 
 	pHba->in_use = 1;
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 
 	return 0;
 }
@@ -1606,13 +1609,13 @@
 	if (minor >= hba_count) {
 		return -ENXIO;
 	}
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
 		if (pHba->unit == minor) {
 			break;	/* found adapter */
 		}
 	}
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 	if (pHba == NULL) {
 		return -ENXIO;
 	}
@@ -1910,13 +1913,13 @@
 	if (minor >= DPTI_MAX_HBA){
 		return -ENXIO;
 	}
-	down(&adpt_configuration_lock);
+	mutex_lock(&adpt_configuration_lock);
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
 		if (pHba->unit == minor) {
 			break;	/* found adapter */
 		}
 	}
-	up(&adpt_configuration_lock);
+	mutex_unlock(&adpt_configuration_lock);
 	if(pHba == NULL){
 		return -ENXIO;
 	}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 66783c8..5881079 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -156,16 +156,16 @@
 void scsi_remove_host(struct Scsi_Host *shost)
 {
 	unsigned long flags;
-	down(&shost->scan_mutex);
+	mutex_lock(&shost->scan_mutex);
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (scsi_host_set_state(shost, SHOST_CANCEL))
 		if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
 			spin_unlock_irqrestore(shost->host_lock, flags);
-			up(&shost->scan_mutex);
+			mutex_unlock(&shost->scan_mutex);
 			return;
 		}
 	spin_unlock_irqrestore(shost->host_lock, flags);
-	up(&shost->scan_mutex);
+	mutex_unlock(&shost->scan_mutex);
 	scsi_forget_host(shost);
 	scsi_proc_host_rm(shost);
 
@@ -320,7 +320,7 @@
 	INIT_LIST_HEAD(&shost->starved_list);
 	init_waitqueue_head(&shost->host_wait);
 
-	init_MUTEX(&shost->scan_mutex);
+	mutex_init(&shost->scan_mutex);
 
 	shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */
 	shost->dma_channel = 0xff;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 3882d48..e5e1ca4 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1319,6 +1319,9 @@
 			min = ha->max_cmds - 1;
 		scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
 	}
+
+	SDptr->skip_ms_page_8 = 1;
+	SDptr->skip_ms_page_3f = 1;
 	return 0;
 }
 #endif
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 10bcf42..1b495af 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/kfifo.h>
 #include <linux/scatterlist.h>
+#include <linux/mutex.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -86,35 +87,32 @@
 {
 	sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
 	ibuf->sent = 0;
+	ibuf->use_sendmsg = 0;
 }
 
 static inline void
 iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
 {
-	ibuf->sg.page = (void*)vbuf;
-	ibuf->sg.offset = (unsigned int)-1;
+	ibuf->sg.page = virt_to_page(vbuf);
+	ibuf->sg.offset = offset_in_page(vbuf);
 	ibuf->sg.length = size;
 	ibuf->sent = 0;
-}
-
-static inline void*
-iscsi_buf_iov_base(struct iscsi_buf *ibuf)
-{
-	return (char*)ibuf->sg.page + ibuf->sent;
+	ibuf->use_sendmsg = 1;
 }
 
 static inline void
 iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
 {
+	ibuf->sg.page = sg->page;
+	ibuf->sg.offset = sg->offset;
+	ibuf->sg.length = sg->length;
 	/*
 	 * Fastpath: sg element fits into single page
 	 */
-	if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) {
-		ibuf->sg.page = sg->page;
-		ibuf->sg.offset = sg->offset;
-		ibuf->sg.length = sg->length;
-	} else
-		iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length);
+	if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
+		ibuf->use_sendmsg = 0;
+	else
+		ibuf->use_sendmsg = 1;
 	ibuf->sent = 0;
 }
 
@@ -356,7 +354,7 @@
 		struct scsi_cmnd *sc = ctask->sc;
 
 		conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
-		if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+		if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
 			int res_count = be32_to_cpu(rhdr->residual_count);
 
 			if (res_count > 0 &&
@@ -366,9 +364,7 @@
 			} else
 				sc->result = (DID_BAD_TARGET << 16) |
 					rhdr->cmd_status;
-		} else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
-			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-		else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) {
+		} else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
 			sc->resid = be32_to_cpu(rhdr->residual_count);
 			sc->result = (DID_OK << 16) | rhdr->cmd_status;
 		} else
@@ -529,7 +525,7 @@
 	__kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
 	__kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
 
-	schedule_work(&conn->xmitwork);
+	scsi_queue_work(session->host, &conn->xmitwork);
 	conn->r2t_pdus_cnt++;
 	spin_unlock(&session->lock);
 
@@ -686,7 +682,7 @@
 		switch(conn->in.opcode) {
 		case ISCSI_OP_LOGIN_RSP:
 		case ISCSI_OP_TEXT_RSP:
-		case ISCSI_OP_LOGOUT_RSP: 
+		case ISCSI_OP_LOGOUT_RSP:
 			rc = iscsi_check_assign_cmdsn(session,
 						 (struct iscsi_nopin*)hdr);
 			if (rc)
@@ -727,12 +723,12 @@
 			}
 			spin_unlock(&session->lock);
 			break;
-		case ISCSI_OP_NOOP_IN: 
+		case ISCSI_OP_NOOP_IN:
 			if (hdr->ttt != ISCSI_RESERVED_TAG) {
 				rc = ISCSI_ERR_PROTO;
 				break;
 			}
-			rc = iscsi_check_assign_cmdsn(session, 
+			rc = iscsi_check_assign_cmdsn(session,
 						(struct iscsi_nopin*)hdr);
 			if (rc)
 				break;
@@ -767,7 +763,7 @@
 				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
 					rc = iscsi_recv_pdu(iscsi_handle(conn),
 							    hdr, NULL, 0);
-			} else 
+			} else
 				rc = ISCSI_ERR_PROTO;
 			break;
 		case ISCSI_OP_REJECT:
@@ -929,7 +925,7 @@
 				      sc->request_bufflen, ctask->data_offset);
 		if (rc == -EAGAIN)
 			return rc;
-		if (conn->datadgst_en) 
+		if (conn->datadgst_en)
 			iscsi_recv_digest_update(conn, sc->request_buffer, i);
 		rc = 0;
 		goto done;
@@ -1024,7 +1020,7 @@
 		conn->in.hdr = &conn->hdr;
 		conn->senselen = (conn->data[0] << 8) | conn->data[1];
 		rc = iscsi_cmd_rsp(conn, conn->in.ctask);
-		if (!rc && conn->datadgst_en) 
+		if (!rc && conn->datadgst_en)
 			iscsi_recv_digest_update(conn, conn->data,
 						 conn->in.datalen);
 	}
@@ -1051,7 +1047,7 @@
 		rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
 				    conn->data, conn->in.datalen);
 
-		if (!rc && conn->datadgst_en && 
+		if (!rc && conn->datadgst_en &&
 			conn->in.opcode != ISCSI_OP_LOGIN_RSP)
 			iscsi_recv_digest_update(conn, conn->data,
 			  			conn->in.datalen);
@@ -1271,7 +1267,7 @@
 	conn->old_write_space(sk);
 	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
 	clear_bit(SUSPEND_BIT, &conn->suspend_tx);
-	schedule_work(&conn->xmitwork);
+	scsi_queue_work(conn->session->host, &conn->xmitwork);
 }
 
 static void
@@ -1312,35 +1308,25 @@
  * @buf: buffer to write from
  * @size: actual size to write
  * @flags: socket's flags
- *
- * Notes:
- *	depending on buffer will use tcp_sendpage() or tcp_sendmsg().
- *	buf->sg.offset == -1 tells us that buffer is non S/G and forces
- *	to use tcp_sendmsg().
  */
 static inline int
-iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
+iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
 {
-	int res;
+	struct socket *sk = conn->sock;
+	int offset = buf->sg.offset + buf->sent;
 
-	if ((int)buf->sg.offset >= 0) {
-		int offset = buf->sg.offset + buf->sent;
-
-		/* tcp_sendpage */
-		res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags);
-	} else {
-		struct msghdr msg;
-
-		buf->iov.iov_base = iscsi_buf_iov_base(buf);
-		buf->iov.iov_len = size;
-
-		memset(&msg, 0, sizeof(struct msghdr));
-
-		/* tcp_sendmsg */
-		res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size);
-	}
-
-	return res;
+	/*
+	 * if we got use_sg=0 or are sending something we kmallocd
+	 * then we did not have to do kmap (kmap returns page_address)
+	 *
+	 * if we got use_sg > 0, but had to drop down, we do not
+	 * set clustering so this should only happen for that
+	 * slab case.
+	 */
+	if (buf->use_sendmsg)
+		return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+	else
+		return conn->sendpage(sk, buf->sg.page, offset, size, flags);
 }
 
 /**
@@ -1355,7 +1341,6 @@
 static inline int
 iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
 {
-	struct socket *sk = conn->sock;
 	int flags = 0; /* MSG_DONTWAIT; */
 	int res, size;
 
@@ -1364,7 +1349,7 @@
 	if (buf->sent + size != buf->sg.length || datalen)
 		flags |= MSG_MORE;
 
-	res = iscsi_send(sk, buf, size, flags);
+	res = iscsi_send(conn, buf, size, flags);
 	debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
 	if (res >= 0) {
 		conn->txdata_octets += res;
@@ -1395,7 +1380,6 @@
 iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
 	       int *count, int *sent)
 {
-	struct socket *sk = conn->sock;
 	int flags = 0; /* MSG_DONTWAIT; */
 	int res, size;
 
@@ -1406,7 +1390,7 @@
 	if (buf->sent + size != buf->sg.length || *count != size)
 		flags |= MSG_MORE;
 
-	res = iscsi_send(sk, buf, size, flags);
+	res = iscsi_send(conn, buf, size, flags);
 	debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
 		  size, buf->sent, *count, *sent, res);
 	if (res >= 0) {
@@ -1434,19 +1418,6 @@
 	ctask->digest_count = 4;
 }
 
-static inline void
-iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf)
-{
-	struct scatterlist sg;
-
-	if (buf->sg.offset != -1)
-		crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1);
-	else {
-		sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length);
-		crypto_digest_update(conn->data_tx_tfm, &sg, 1);
-	}
-}
-
 static inline int
 iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
 			struct iscsi_buf *buf, uint32_t *digest, int final)
@@ -1680,7 +1651,7 @@
 		zero_data(ctask->hdr.dlength);
 	}
 
-	iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, 
+	iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
 			    sizeof(struct iscsi_hdr));
 	conn->scsicmd_pdus_cnt++;
 }
@@ -1746,7 +1717,7 @@
 handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
 	ctask->xmstate &= ~XMSTATE_R_HDR;
-	if (conn->hdrdgst_en) 
+	if (conn->hdrdgst_en)
 		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
 	if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
 		BUG_ON(ctask->xmstate != XMSTATE_IDLE);
@@ -1760,7 +1731,7 @@
 handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
 	ctask->xmstate &= ~XMSTATE_W_HDR;
-	if (conn->hdrdgst_en) 
+	if (conn->hdrdgst_en)
 		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
 	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
 		ctask->xmstate |= XMSTATE_W_HDR;
@@ -1809,7 +1780,8 @@
 			return -EAGAIN;
 		}
 		if (conn->datadgst_en)
-			iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+			crypto_digest_update(conn->data_tx_tfm,
+					     &ctask->sendbuf.sg, 1);
 
 		if (!ctask->imm_count)
 			break;
@@ -1894,7 +1866,8 @@
 		 * so pass it
 		 */
 		if (conn->datadgst_en && ctask->sent - start > 0)
-			iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+			crypto_digest_update(conn->data_tx_tfm,
+					     &ctask->sendbuf.sg, 1);
 
 		if (!ctask->data_count)
 			break;
@@ -1972,7 +1945,7 @@
 
 	BUG_ON(r2t->data_count < 0);
 	if (conn->datadgst_en)
-		iscsi_buf_data_digest_update(conn, &r2t->sendbuf);
+		crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
 
 	if (r2t->data_count) {
 		BUG_ON(ctask->sc->use_sg == 0);
@@ -2054,7 +2027,7 @@
 	}
 
 	if (conn->datadgst_en) {
-		iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+		crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
 		/* imm data? */
 		if (!dtask) {
 			if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
@@ -2148,7 +2121,7 @@
 solicit_head_again:
 		r2t = ctask->r2t;
 		if (conn->hdrdgst_en)
-			iscsi_hdr_digest(conn, &r2t->headbuf, 
+			iscsi_hdr_digest(conn, &r2t->headbuf,
 					(u8*)r2t->dtask->hdrext);
 		if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
 			ctask->xmstate &= ~XMSTATE_SOL_DATA;
@@ -2300,10 +2273,10 @@
 	/*
 	 * serialize Xmit worker on a per-connection basis.
 	 */
-	down(&conn->xmitsema);
+	mutex_lock(&conn->xmitmutex);
 	if (iscsi_data_xmit(conn))
-		schedule_work(&conn->xmitwork);
-	up(&conn->xmitsema);
+		scsi_queue_work(conn->session->host, &conn->xmitwork);
+	mutex_unlock(&conn->xmitmutex);
 }
 
 #define FAILURE_BAD_HOST		1
@@ -2367,15 +2340,7 @@
 		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
 	spin_unlock(&session->lock);
 
-        if (!in_interrupt() && !down_trylock(&conn->xmitsema)) {
-		spin_unlock_irq(host->host_lock);
-		if (iscsi_data_xmit(conn))
-			schedule_work(&conn->xmitwork);
-		up(&conn->xmitsema);
-		spin_lock_irq(host->host_lock);
-	} else
-		schedule_work(&conn->xmitwork);
-
+	scsi_queue_work(host, &conn->xmitwork);
 	return 0;
 
 reject:
@@ -2462,17 +2427,20 @@
 	kfree(items);
 }
 
-static iscsi_connh_t
-iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
+static struct iscsi_cls_conn *
+iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
 {
-	struct iscsi_session *session = iscsi_ptr(sessionh);
-	struct iscsi_conn *conn = NULL;
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+	struct iscsi_conn *conn;
+	struct iscsi_cls_conn *cls_conn;
 
-	conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
-	if (conn == NULL)
-		goto conn_alloc_fail;
+	cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
+				     conn_idx);
+	if (!cls_conn)
+		return NULL;
+	conn = cls_conn->dd_data;
+
 	memset(conn, 0, sizeof(struct iscsi_conn));
-
 	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
 	conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 	conn->id = conn_idx;
@@ -2531,10 +2499,10 @@
 		goto max_recv_dlenght_alloc_fail;
 
 	init_timer(&conn->tmabort_timer);
-	init_MUTEX(&conn->xmitsema);
+	mutex_init(&conn->xmitmutex);
 	init_waitqueue_head(&conn->ehwait);
 
-	return iscsi_handle(conn);
+	return cls_conn;
 
 max_recv_dlenght_alloc_fail:
 	spin_lock_bh(&session->lock);
@@ -2550,18 +2518,18 @@
 writequeue_alloc_fail:
 	kfifo_free(conn->xmitqueue);
 xmitqueue_alloc_fail:
-	kfree(conn);
-conn_alloc_fail:
-	return iscsi_handle(NULL);
+	iscsi_destroy_conn(cls_conn);
+	return NULL;
 }
 
 static void
-iscsi_conn_destroy(iscsi_connh_t connh)
+iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
 {
-	struct iscsi_conn *conn = iscsi_ptr(connh);
+	struct iscsi_conn *conn = cls_conn->dd_data;
 	struct iscsi_session *session = conn->session;
+	unsigned long flags;
 
-	down(&conn->xmitsema);
+	mutex_lock(&conn->xmitmutex);
 	set_bit(SUSPEND_BIT, &conn->suspend_tx);
 	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) {
 		struct sock *sk = conn->sock->sk;
@@ -2592,19 +2560,19 @@
 	}
 	spin_unlock_bh(&session->lock);
 
-	up(&conn->xmitsema);
+	mutex_unlock(&conn->xmitmutex);
 
 	/*
 	 * Block until all in-progress commands for this connection
 	 * time out or fail.
 	 */
 	for (;;) {
-		spin_lock_bh(&conn->lock);
+		spin_lock_irqsave(session->host->host_lock, flags);
 		if (!session->host->host_busy) { /* OK for ERL == 0 */
-			spin_unlock_bh(&conn->lock);
+			spin_unlock_irqrestore(session->host->host_lock, flags);
 			break;
 		}
-		spin_unlock_bh(&conn->lock);
+		spin_unlock_irqrestore(session->host->host_lock, flags);
 		msleep_interruptible(500);
 		printk("conn_destroy(): host_busy %d host_failed %d\n",
 			session->host->host_busy, session->host->host_failed);
@@ -2652,7 +2620,8 @@
 	kfifo_free(conn->writequeue);
 	kfifo_free(conn->immqueue);
 	kfifo_free(conn->mgmtqueue);
-	kfree(conn);
+
+	iscsi_destroy_conn(cls_conn);
 }
 
 static int
@@ -2713,6 +2682,8 @@
 		 */
 		iscsi_conn_set_callbacks(conn);
 
+		conn->sendpage = conn->sock->ops->sendpage;
+
 		/*
 		 * set receive state machine into initial state
 		 */
@@ -2796,7 +2767,7 @@
 	set_bit(SUSPEND_BIT, &conn->suspend_rx);
 	write_unlock_bh(&sk->sk_callback_lock);
 
-	down(&conn->xmitsema);
+	mutex_lock(&conn->xmitmutex);
 
 	spin_lock_irqsave(session->host->host_lock, flags);
 	spin_lock(&session->lock);
@@ -2878,7 +2849,7 @@
 			conn->datadgst_en = 0;
 		}
 	}
-	up(&conn->xmitsema);
+	mutex_unlock(&conn->xmitmutex);
 }
 
 static int
@@ -2963,8 +2934,7 @@
 	else
 	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
 
-	schedule_work(&conn->xmitwork);
-
+	scsi_queue_work(session->host, &conn->xmitwork);
 	return 0;
 }
 
@@ -3029,12 +2999,12 @@
 	 * 1) connection-level failure;
 	 * 2) recovery due protocol error;
 	 */
-	down(&conn->xmitsema);
+	mutex_lock(&conn->xmitmutex);
 	spin_lock_bh(&session->lock);
 	if (session->state != ISCSI_STATE_LOGGED_IN) {
 		if (session->state == ISCSI_STATE_TERMINATE) {
 			spin_unlock_bh(&session->lock);
-			up(&conn->xmitsema);
+			mutex_unlock(&conn->xmitmutex);
 			goto failed;
 		}
 		spin_unlock_bh(&session->lock);
@@ -3052,7 +3022,7 @@
 			 * 2) session was re-open during time out of ctask.
 			 */
 			spin_unlock_bh(&session->lock);
-			up(&conn->xmitsema);
+			mutex_unlock(&conn->xmitmutex);
 			goto success;
 		}
 		conn->tmabort_state = TMABORT_INITIAL;
@@ -3107,7 +3077,7 @@
 				    conn->tmabort_state == TMABORT_SUCCESS) {
 					conn->tmabort_state = TMABORT_INITIAL;
 					spin_unlock_bh(&session->lock);
-					up(&conn->xmitsema);
+					mutex_unlock(&conn->xmitmutex);
 					goto success;
 				}
 				conn->tmabort_state = TMABORT_INITIAL;
@@ -3116,7 +3086,7 @@
 			spin_unlock_bh(&session->lock);
 		}
 	}
-	up(&conn->xmitsema);
+	mutex_unlock(&conn->xmitmutex);
 
 
 	/*
@@ -3182,7 +3152,7 @@
 exit:
 	del_timer_sync(&conn->tmabort_timer);
 
-	down(&conn->xmitsema);
+	mutex_lock(&conn->xmitmutex);
 	if (conn->sock) {
 		struct sock *sk = conn->sock->sk;
 
@@ -3190,7 +3160,7 @@
 		iscsi_ctask_cleanup(conn, ctask);
 		write_unlock_bh(&sk->sk_callback_lock);
 	}
-	up(&conn->xmitsema);
+	mutex_unlock(&conn->xmitmutex);
 	return rc;
 }
 
@@ -3281,17 +3251,23 @@
 	.this_id		= -1,
 };
 
-static iscsi_sessionh_t
-iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
+static struct iscsi_transport iscsi_tcp_transport;
+
+static struct Scsi_Host *
+iscsi_session_create(struct scsi_transport_template *scsit,
+		     uint32_t initial_cmdsn)
 {
-	int cmd_i;
+	struct Scsi_Host *shost;
 	struct iscsi_session *session;
+	int cmd_i;
 
-	session = iscsi_hostdata(host->hostdata);
+	shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
+	if (!shost)
+		return NULL; 
+
+	session = iscsi_hostdata(shost->hostdata);
 	memset(session, 0, sizeof(struct iscsi_session));
-
-	session->host = host;
-	session->id = host->host_no;
+	session->host = shost;
 	session->state = ISCSI_STATE_LOGGED_IN;
 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
 	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
@@ -3335,7 +3311,7 @@
 	if (iscsi_r2tpool_alloc(session))
 		goto r2tpool_alloc_fail;
 
-	return iscsi_handle(session);
+	return shost;
 
 r2tpool_alloc_fail:
 	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
@@ -3345,15 +3321,15 @@
 mgmtpool_alloc_fail:
 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
 cmdpool_alloc_fail:
-	return iscsi_handle(NULL);
+	return NULL;
 }
 
 static void
-iscsi_session_destroy(iscsi_sessionh_t sessionh)
+iscsi_session_destroy(struct Scsi_Host *shost)
 {
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
 	int cmd_i;
 	struct iscsi_data_task *dtask, *n;
-	struct iscsi_session *session = iscsi_ptr(sessionh);
 
 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
 		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
@@ -3369,6 +3345,8 @@
 	iscsi_r2tpool_free(session);
 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+
+	iscsi_transport_destroy_session(shost);
 }
 
 static int
@@ -3467,6 +3445,8 @@
 			if (conn->data_rx_tfm)
 				crypto_free_tfm(conn->data_rx_tfm);
 		}
+		conn->sendpage = conn->datadgst_en ?
+			sock_no_sendpage : conn->sock->ops->sendpage;
 		break;
 	case ISCSI_PARAM_INITIAL_R2T_EN:
 		session->initial_r2t_en = value;
@@ -3515,25 +3495,12 @@
 }
 
 static int
-iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
-		     uint32_t *value)
+iscsi_session_get_param(struct Scsi_Host *shost,
+			enum iscsi_param param, uint32_t *value)
 {
-	struct iscsi_conn *conn = iscsi_ptr(connh);
-	struct iscsi_session *session = conn->session;
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
 
 	switch(param) {
-	case ISCSI_PARAM_MAX_RECV_DLENGTH:
-		*value = conn->max_recv_dlength;
-		break;
-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
-		*value = conn->max_xmit_dlength;
-		break;
-	case ISCSI_PARAM_HDRDGST_EN:
-		*value = conn->hdrdgst_en;
-		break;
-	case ISCSI_PARAM_DATADGST_EN:
-		*value = conn->datadgst_en;
-		break;
 	case ISCSI_PARAM_INITIAL_R2T_EN:
 		*value = session->initial_r2t_en;
 		break;
@@ -3571,6 +3538,31 @@
 	return 0;
 }
 
+static int
+iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
+{
+	struct iscsi_conn *conn = data;
+
+	switch(param) {
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		*value = conn->max_recv_dlength;
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		*value = conn->max_xmit_dlength;
+		break;
+	case ISCSI_PARAM_HDRDGST_EN:
+		*value = conn->hdrdgst_en;
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		*value = conn->datadgst_en;
+		break;
+	default:
+		return ISCSI_ERR_PARAM_NOT_FOUND;
+	}
+
+	return 0;
+}
+
 static void
 iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
 {
@@ -3601,9 +3593,9 @@
 	struct iscsi_conn *conn = iscsi_ptr(connh);
 	int rc;
 
-	down(&conn->xmitsema);
+	mutex_lock(&conn->xmitmutex);
 	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
-	up(&conn->xmitsema);
+	mutex_unlock(&conn->xmitmutex);
 
 	return rc;
 }
@@ -3615,6 +3607,7 @@
 				  | CAP_DATADGST,
 	.host_template		= &iscsi_sht,
 	.hostdata_size		= sizeof(struct iscsi_session),
+	.conndata_size		= sizeof(struct iscsi_conn),
 	.max_conn		= 1,
 	.max_cmd_len		= ISCSI_TCP_MAX_CMD_LEN,
 	.create_session		= iscsi_session_create,
@@ -3623,7 +3616,8 @@
 	.bind_conn		= iscsi_conn_bind,
 	.destroy_conn		= iscsi_conn_destroy,
 	.set_param		= iscsi_conn_set_param,
-	.get_param		= iscsi_conn_get_param,
+	.get_conn_param		= iscsi_conn_get_param,
+	.get_session_param	= iscsi_session_get_param,
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_conn_stop,
 	.send_pdu		= iscsi_conn_send_pdu,
@@ -3633,8 +3627,6 @@
 static int __init
 iscsi_tcp_init(void)
 {
-	int error;
-
 	if (iscsi_max_lun < 1) {
 		printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
 		return -EINVAL;
@@ -3647,11 +3639,10 @@
 	if (!taskcache)
 		return -ENOMEM;
 
-	error = iscsi_register_transport(&iscsi_tcp_transport);
-	if (error)
+	if (!iscsi_register_transport(&iscsi_tcp_transport))
 		kmem_cache_destroy(taskcache);
 
-	return error;
+	return 0;
 }
 
 static void __exit
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 855f2df..f95e61b 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -158,7 +158,7 @@
 	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
 	struct kfifo		*xmitqueue;	/* data-path cmd queue */
 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
-	struct semaphore	xmitsema;	/* serializes connection xmit,
+	struct mutex		xmitmutex;	/* serializes connection xmit,
 						 * access to kfifos:	  *
 						 * xmitqueue, writequeue, *
 						 * immqueue, mgmtqueue    */
@@ -191,6 +191,8 @@
 	uint32_t		sendpage_failures_cnt;
 	uint32_t		discontiguous_hdr_cnt;
 	uint32_t		eh_abort_cnt;
+
+	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
 };
 
 struct iscsi_session {
@@ -240,8 +242,8 @@
 
 struct iscsi_buf {
 	struct scatterlist	sg;
-	struct kvec		iov;
 	unsigned int		sent;
+	char			use_sendmsg;
 };
 
 struct iscsi_data_task {
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 9ee8218..dafabee 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -150,7 +150,7 @@
 	return psb;
 }
 
-struct  lpfc_scsi_buf*
+static struct lpfc_scsi_buf*
 lpfc_get_scsi_buf(struct lpfc_hba * phba)
 {
 	struct  lpfc_scsi_buf * lpfc_cmd = NULL;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 4a6feb1..d101a8a 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4479,7 +4479,7 @@
 	 * serialized. This is so because we want to reserve maximum number of
 	 * available command ids for the I/O commands.
 	 */
-	down(&adapter->int_mtx);
+	mutex_lock(&adapter->int_mtx);
 
 	scb = &adapter->int_scb;
 	memset(scb, 0, sizeof(scb_t));
@@ -4527,7 +4527,7 @@
 			mc->cmd, mc->opcode, mc->subopcode, scmd->result);
 	}
 
-	up(&adapter->int_mtx);
+	mutex_unlock(&adapter->int_mtx);
 
 	return rval;
 }
@@ -4866,7 +4866,7 @@
 		adapter->has_64bit_addr = 0;
 	}
 		
-	init_MUTEX(&adapter->int_mtx);
+	mutex_init(&adapter->int_mtx);
 	init_completion(&adapter->int_waitq);
 
 	adapter->this_id = DEFAULT_INITIATOR_ID;
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 6f90780..4b3e0d6 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -2,7 +2,7 @@
 #define __MEGARAID_H__
 
 #include <linux/spinlock.h>
-
+#include <linux/mutex.h>
 
 #define MEGARAID_VERSION	\
 	"v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
@@ -889,7 +889,7 @@
 
 	scb_t			int_scb;
 	Scsi_Cmnd		int_scmd;
-	struct semaphore	int_mtx;	/* To synchronize the internal
+	struct mutex		int_mtx;	/* To synchronize the internal
 						commands */
 	struct completion	int_waitq;	/* wait queue for internal
 						 cmds */
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 3c32e69..c0bb806 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -35,6 +35,7 @@
 #include <asm/uaccess.h>
 #include <linux/fs.h>
 #include <linux/compat.h>
+#include <linux/mutex.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -72,7 +73,7 @@
 static int megasas_mgmt_majorno;
 static struct megasas_mgmt_info megasas_mgmt_info;
 static struct fasync_struct *megasas_async_queue;
-static DECLARE_MUTEX(megasas_async_queue_mutex);
+static DEFINE_MUTEX(megasas_async_queue_mutex);
 
 /**
  * megasas_get_cmd -	Get a command from the free pool
@@ -2362,11 +2363,11 @@
 {
 	int rc;
 
-	down(&megasas_async_queue_mutex);
+	mutex_lock(&megasas_async_queue_mutex);
 
 	rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
 
-	up(&megasas_async_queue_mutex);
+	mutex_unlock(&megasas_async_queue_mutex);
 
 	if (rc >= 0) {
 		/* For sanity check when we get ioctl */
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 5205c4e..5758b25 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,4 +1,4 @@
-config SCSI_QLA2XXX
+config SCSI_QLA_FC
 	tristate "QLogic QLA2XXX Fibre Channel Support"
 	depends on PCI && SCSI
 	select SCSI_FC_ATTRS
@@ -22,49 +22,57 @@
 	Upon request, the driver caches the firmware image until
 	the driver is unloaded.
 
+	Firmware images can be retrieved from:
+
+		ftp://ftp.qlogic.com/outgoing/linux/firmware/
+
 	NOTE: The original method of building firmware-loader
 	modules has been deprecated as the firmware-images will
 	be removed from the kernel sources.
 
 config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	bool "  Use firmware-loader modules (DEPRECATED)"
-	depends on SCSI_QLA2XXX
+	depends on SCSI_QLA_FC
+	help
+	  This option offers you the deprecated firmware-loader
+	  modules that have been obsoleted by the usage of the
+	  Firmware Loader interface in the qla2xxx driver.
 
 config SCSI_QLA21XX
 	tristate "  Build QLogic ISP2100 firmware-module"
-	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 21xx (ISP2100) host adapter family.
 
 config SCSI_QLA22XX
 	tristate "  Build QLogic ISP2200 firmware-module"
-	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 22xx (ISP2200) host adapter family.
 
 config SCSI_QLA2300
 	tristate "  Build QLogic ISP2300 firmware-module"
-	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
 	adapter family.
 
 config SCSI_QLA2322
 	tristate "  Build QLogic ISP2322 firmware-module"
-	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 2322 (ISP2322) host adapter family.
 
 config SCSI_QLA6312
 	tristate "  Build QLogic ISP63xx firmware-module"
-	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
 	adapter family.
 
 config SCSI_QLA24XX
 	tristate "  Build QLogic ISP24xx firmware-module"
-	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
 	adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 40c0de1..d028bc50 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -3,7 +3,7 @@
 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
 		qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
 
-obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o
+obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
 
 qla2100-y := ql2100.o ql2100_fw.o
 qla2200-y := ql2200.o ql2200_fw.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 2efca52..b17ee62 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -541,7 +541,7 @@
 void
 qla2x00_init_host_attr(scsi_qla_host_t *ha)
 {
-	fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name);
-	fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name);
+	fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
+	fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
 	fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
 }
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 5c5d231..2d9b12f 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1003,10 +1003,10 @@
 	fw = (struct qla24xx_fw_dump *) ha->fw_dump24;
 
 	rval = QLA_SUCCESS;
-	fw->hccr = RD_REG_DWORD(&reg->hccr);
+	fw->host_status = RD_REG_DWORD(&reg->host_status);
 
 	/* Pause RISC. */
-	if ((fw->hccr & HCCRX_RISC_PAUSE) == 0) {
+	if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
 		WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
 		    HCCRX_CLR_HOST_INT);
 		RD_REG_DWORD(&reg->hccr);		/* PCI Posting. */
@@ -1021,16 +1021,54 @@
 		}
 	}
 
-	/* Disable interrupts. */
-	WRT_REG_DWORD(&reg->ictrl, 0);
-	RD_REG_DWORD(&reg->ictrl);
-
 	if (rval == QLA_SUCCESS) {
 		/* Host interface registers. */
 		dmp_reg = (uint32_t __iomem *)(reg + 0);
 		for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
 			fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++);
 
+		/* Disable interrupts. */
+		WRT_REG_DWORD(&reg->ictrl, 0);
+		RD_REG_DWORD(&reg->ictrl);
+
+		/* Shadow registers. */
+		WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
+		RD_REG_DWORD(&reg->iobase_addr);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0000000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
+
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0100000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
+
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0200000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
+
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0300000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
+
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0400000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
+
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0500000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
+
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+		WRT_REG_DWORD(dmp_reg, 0xB0600000);
+		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+		fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
+
 		/* Mailbox registers. */
 		mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
 		for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
@@ -1308,43 +1346,6 @@
 		for (cnt = 0; cnt < 16; cnt++)
 			*iter_reg++ = RD_REG_DWORD(dmp_reg++);
 
-		WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
-		RD_REG_DWORD(&reg->iobase_addr);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0000000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
-
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0100000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
-
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0200000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
-
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0300000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
-
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0400000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
-
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0500000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
-
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
-		WRT_REG_DWORD(dmp_reg, 0xB0600000);
-		dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-		fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
-
 		/* Local memory controller registers. */
 		iter_reg = fw->lmc_reg;
 		WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
@@ -1677,7 +1678,7 @@
 	    ha->fw_major_version, ha->fw_minor_version,
 	    ha->fw_subminor_version, ha->fw_attributes);
 
-	qla_uprintf(&uiter, "\nHCCR Register\n%04x\n", fw->hccr);
+	qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status);
 
 	qla_uprintf(&uiter, "\nHost Interface Registers");
 	for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) {
@@ -1687,6 +1688,14 @@
 		qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]);
 	}
 
+	qla_uprintf(&uiter, "\n\nShadow Registers");
+	for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
+		if (cnt % 8 == 0)
+			qla_uprintf(&uiter, "\n");
+
+		qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
+	}
+
 	qla_uprintf(&uiter, "\n\nMailbox Registers");
 	for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) {
 		if (cnt % 8 == 0)
@@ -1855,14 +1864,6 @@
 		qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]);
 	}
 
-	qla_uprintf(&uiter, "\n\nShadow Registers");
-	for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
-		if (cnt % 8 == 0)
-			qla_uprintf(&uiter, "\n");
-
-		qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
-	}
-
 	qla_uprintf(&uiter, "\n\nLMC Registers");
 	for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) {
 		if (cnt % 8 == 0)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 935a59a..ab6afea 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -227,8 +227,9 @@
 #define FW_DUMP_SIZE_24XX	0x2B0000
 
 struct qla24xx_fw_dump {
-	uint32_t hccr;
+	uint32_t host_status;
 	uint32_t host_reg[32];
+	uint32_t shadow_reg[7];
 	uint16_t mailbox_reg[32];
 	uint32_t xseq_gp_reg[128];
 	uint32_t xseq_0_reg[16];
@@ -250,7 +251,6 @@
 	uint32_t rcvt0_data_dma_reg[32];
 	uint32_t rcvt1_data_dma_reg[32];
 	uint32_t risc_gp_reg[128];
-	uint32_t shadow_reg[7];
 	uint32_t lmc_reg[112];
 	uint32_t fpm_hdw_reg[192];
 	uint32_t fb_hdw_reg[176];
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index bec81ad..32be4c1 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -62,6 +62,7 @@
 extern int ql2xplogiabsentdevice;
 extern int ql2xloginretrycount;
 extern int ql2xfdmienable;
+extern int ql2xprocessrscn;
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
@@ -96,10 +97,7 @@
  * Global Function Prototypes in qla_mbx.c source file.
  */
 extern int
-qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t);
-
-extern int
-qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
+qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
 
 extern int
 qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index cd6f7c3..d620a8e8 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -538,6 +538,7 @@
 	ct_req->req.rff_id.port_id[1] = ha->d_id.b.area;
 	ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa;
 
+	ct_req->req.rff_id.fc4_feature = BIT_1;
 	ct_req->req.rff_id.fc4_type = 0x08;		/* SCSI - FCP */
 
 	/* Execute MS IOCB */
@@ -1529,9 +1530,9 @@
 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
 	eiter->len = __constant_cpu_to_be16(4 + 4);
 	if (IS_QLA25XX(ha))
-		eiter->a.sup_speed = __constant_cpu_to_be32(4);
-	else if (IS_QLA24XX(ha))
 		eiter->a.sup_speed = __constant_cpu_to_be32(8);
+	else if (IS_QLA24XX(ha))
+		eiter->a.sup_speed = __constant_cpu_to_be32(4);
 	else if (IS_QLA23XX(ha))
 		eiter->a.sup_speed = __constant_cpu_to_be32(2);
 	else
@@ -1553,9 +1554,6 @@
 		eiter->a.cur_speed = __constant_cpu_to_be32(2);
 		break;
 	case 3:
-		eiter->a.cur_speed = __constant_cpu_to_be32(8);
-		break;
-	case 4:
 		eiter->a.cur_speed = __constant_cpu_to_be32(4);
 		break;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 7d973bd..a91fea6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1014,11 +1014,13 @@
 	int rval;
 
 	/* Update Serial Link options. */
-	if ((ha->fw_seriallink_options24[0] & BIT_0) == 0)
+	if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
 		return;
 
-	rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1],
-	    ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]);
+	rval = qla2x00_set_serdes_params(ha,
+	    le16_to_cpu(ha->fw_seriallink_options24[1]),
+	    le16_to_cpu(ha->fw_seriallink_options24[2]),
+	    le16_to_cpu(ha->fw_seriallink_options24[3]));
 	if (rval != QLA_SUCCESS) {
 		qla_printk(KERN_WARNING, ha,
 		    "Unable to update Serial Link options (%x).\n", rval);
@@ -1939,6 +1941,9 @@
 			    "information -- get_port_database=%x, "
 			    "loop_id=0x%04x\n",
 			    ha->host_no, rval2, new_fcport->loop_id));
+			DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
+			    ha->host_no));
+			set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
 			continue;
 		}
 
@@ -2648,7 +2653,8 @@
 
 		switch (format) {
 		case 0:
-			if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
+			if (ql2xprocessrscn &&
+			    !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
 			    !IS_QLA6312(ha) && !IS_QLA6322(ha) &&
 			    !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
 			    ha->flags.init_done) {
@@ -3402,6 +3408,8 @@
 	ha->node_name = icb->node_name;
 	ha->port_name = icb->port_name;
 
+	icb->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+
 	ha->retry_count = le16_to_cpu(nv->login_retry_count);
 
 	/* Set minimum login_timeout to 4 seconds. */
@@ -3667,8 +3675,8 @@
 			for (i = 0; i < dlen; i++)
 				dcode[i] = swab32(dcode[i]);
 
-			rval = qla2x00_load_ram_ext(ha, ha->request_dma,
-			    risc_addr, dlen);
+			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+			    dlen);
 			if (rval) {
 				DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
 				    "segment %d of firmware\n", ha->host_no,
@@ -3868,8 +3876,8 @@
 			for (i = 0; i < dlen; i++)
 				dcode[i] = swab32(fwcode[i]);
 
-			rval = qla2x00_load_ram_ext(ha, ha->request_dma,
-			    risc_addr, dlen);
+			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+			    dlen);
 			if (rval) {
 				DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
 				    "segment %d of firmware\n", ha->host_no,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5181d96..f63af08 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -519,7 +519,8 @@
 		 * us, create a new entry in our rscn fcports list and handle
 		 * the event like an RSCN.
 		 */
-		if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
+		if (ql2xprocessrscn &&
+		    !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
 		    !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
 		    ha->flags.init_done && mb[1] != 0xffff &&
 		    ((ha->operating_mode == P2P && mb[1] != 0) ||
@@ -963,15 +964,16 @@
 		break;
 
 	case CS_DATA_UNDERRUN:
-		DEBUG2(printk(KERN_INFO
-		    "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n",
-		    ha->host_no, cp->device->id, cp->device->lun, comp_status,
-		    scsi_status));
-
 		resid = resid_len;
 		if (scsi_status & SS_RESIDUAL_UNDER) {
 			cp->resid = resid;
 			CMD_RESID_LEN(cp) = resid;
+		} else {
+			DEBUG2(printk(KERN_INFO
+			    "scsi(%ld:%d:%d) UNDERRUN status detected "
+			    "0x%x-0x%x.\n", ha->host_no, cp->device->id,
+			    cp->device->lun, comp_status, scsi_status));
+
 		}
 
 		/*
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9746cd1..3099b37 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -196,7 +196,9 @@
 			/* Check for pending interrupts. */
 			qla2x00_poll(ha);
 
-			udelay(10); /* v4.27 */
+			if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
+			    !ha->flags.mbox_int)
+				msleep(10);
 		} /* while */
 	}
 
@@ -325,98 +327,9 @@
 	return rval;
 }
 
-/*
- * qla2x00_load_ram
- *	Load adapter RAM using DMA.
- *
- * Input:
- *	ha = adapter block pointer.
- *
- * Returns:
- *	qla2x00 local function return status code.
- *
- * Context:
- *	Kernel context.
- */
 int
-qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr,
-    uint16_t risc_code_size)
-{
-	int rval;
-	mbx_cmd_t mc;
-	mbx_cmd_t *mcp = &mc;
-	uint32_t	req_len;
-	dma_addr_t	nml_dma;
-	uint32_t	nml_len;
-	uint32_t	normalized;
-
-	DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n",
-	    ha->host_no);)
-
-	req_len = risc_code_size;
-	nml_dma = 0;
-	nml_len = 0;
-
-	normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma,
-	    &nml_len);
-
-	/* Load first segment */
-	mcp->mb[0] = MBC_LOAD_RISC_RAM;
-	mcp->mb[1] = risc_addr;
-	mcp->mb[2] = MSW(req_dma);
-	mcp->mb[3] = LSW(req_dma);
-	mcp->mb[4] = (uint16_t)req_len;
-	mcp->mb[6] = MSW(MSD(req_dma));
-	mcp->mb[7] = LSW(MSD(req_dma));
-	mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
-	mcp->in_mb = MBX_0;
-	mcp->tov = 30;
-	mcp->flags = 0;
-	rval = qla2x00_mailbox_command(ha, mcp);
-
-	/* Load second segment - if necessary */
-	if (normalized && (rval == QLA_SUCCESS)) {
-		mcp->mb[0] = MBC_LOAD_RISC_RAM;
-		mcp->mb[1] = risc_addr + (uint16_t)req_len;
-		mcp->mb[2] = MSW(nml_dma);
-		mcp->mb[3] = LSW(nml_dma);
-		mcp->mb[4] = (uint16_t)nml_len;
-		mcp->mb[6] = MSW(MSD(nml_dma));
-		mcp->mb[7] = LSW(MSD(nml_dma));
-		mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
-		mcp->in_mb = MBX_0;
-		mcp->tov = 30;
-		mcp->flags = 0;
-		rval = qla2x00_mailbox_command(ha, mcp);
-	}
-
-	if (rval == QLA_SUCCESS) {
-		/* Empty */
-		DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);)
-	} else {
-		/* Empty */
-		DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x "
-		    "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);)
-	}
-	return rval;
-}
-
-/*
- * qla2x00_load_ram_ext
- *	Load adapter extended RAM using DMA.
- *
- * Input:
- *	ha = adapter block pointer.
- *
- * Returns:
- *	qla2x00 local function return status code.
- *
- * Context:
- *	Kernel context.
- */
-int
-qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma,
-    uint32_t risc_addr, uint32_t risc_code_size)
+qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
+    uint32_t risc_code_size)
 {
 	int rval;
 	mbx_cmd_t mc;
@@ -424,14 +337,20 @@
 
 	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
-	mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
+	if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+		mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
+		mcp->mb[8] = MSW(risc_addr);
+		mcp->out_mb = MBX_8|MBX_0;
+	} else {
+		mcp->mb[0] = MBC_LOAD_RISC_RAM;
+		mcp->out_mb = MBX_0;
+	}
 	mcp->mb[1] = LSW(risc_addr);
 	mcp->mb[2] = MSW(req_dma);
 	mcp->mb[3] = LSW(req_dma);
 	mcp->mb[6] = MSW(MSD(req_dma));
 	mcp->mb[7] = LSW(MSD(req_dma));
-	mcp->mb[8] = MSW(risc_addr);
-	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
 	if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
 		mcp->mb[4] = MSW(risc_code_size);
 		mcp->mb[5] = LSW(risc_code_size);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2430430..4916847 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -71,6 +71,12 @@
 		"Enables FDMI registratons "
 		"Default is 0 - no FDMI. 1 - perfom FDMI.");
 
+int ql2xprocessrscn;
+module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xprocessrscn,
+		"Option to enable port RSCN handling via a series of less"
+		"fabric intrusive ADISCs and PLOGIs.");
+
 /*
  * SCSI host template entry points
  */
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index d54d2a9..f4d755a 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -573,6 +573,9 @@
 		}
 	} while (0);
 
+	/* Enable flash write-protection. */
+	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
+
 	/* Disable flash write. */
 	WRT_REG_DWORD(&reg->ctrl_status,
 	    RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index f7937f7..d537192 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.03-k"
+#define QLA2XXX_VERSION      "8.01.04-k"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
-#define QLA_DRIVER_PATCH_VER	3
+#define QLA_DRIVER_PATCH_VER	4
 #define QLA_DRIVER_BETA_VER	0
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 5ec5f44..50c398a 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -148,9 +148,11 @@
 	{ RAID_LEVEL_LINEAR, "linear" },
 	{ RAID_LEVEL_0, "raid0" },
 	{ RAID_LEVEL_1, "raid1" },
+	{ RAID_LEVEL_10, "raid10" },
 	{ RAID_LEVEL_3, "raid3" },
 	{ RAID_LEVEL_4, "raid4" },
 	{ RAID_LEVEL_5, "raid5" },
+	{ RAID_LEVEL_50, "raid50" },
 	{ RAID_LEVEL_6, "raid6" },
 };
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ee5f4df..245ca99 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -55,6 +55,7 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/mutex.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -209,7 +210,7 @@
 	.gfp_mask	= __GFP_DMA,
 };
 
-static DECLARE_MUTEX(host_cmd_pool_mutex);
+static DEFINE_MUTEX(host_cmd_pool_mutex);
 
 static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
 					    gfp_t gfp_mask)
@@ -330,7 +331,7 @@
 	 * Select a command slab for this host and create it if not
 	 * yet existant.
 	 */
-	down(&host_cmd_pool_mutex);
+	mutex_lock(&host_cmd_pool_mutex);
 	pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
 	if (!pool->users) {
 		pool->slab = kmem_cache_create(pool->name,
@@ -342,7 +343,7 @@
 
 	pool->users++;
 	shost->cmd_pool = pool;
-	up(&host_cmd_pool_mutex);
+	mutex_unlock(&host_cmd_pool_mutex);
 
 	/*
 	 * Get one backup command for this host.
@@ -359,7 +360,7 @@
 		kmem_cache_destroy(pool->slab);
 	return -ENOMEM;
  fail:
-	up(&host_cmd_pool_mutex);
+	mutex_unlock(&host_cmd_pool_mutex);
 	return -ENOMEM;
 
 }
@@ -381,10 +382,10 @@
 		kmem_cache_free(shost->cmd_pool->slab, cmd);
 	}
 
-	down(&host_cmd_pool_mutex);
+	mutex_lock(&host_cmd_pool_mutex);
 	if (!--shost->cmd_pool->users)
 		kmem_cache_destroy(shost->cmd_pool->slab);
-	up(&host_cmd_pool_mutex);
+	mutex_unlock(&host_cmd_pool_mutex);
 }
 
 #ifdef CONFIG_SCSI_LOGGING
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 00c9bf3..3574ba9 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1212,7 +1212,7 @@
 	return -EOPNOTSUPP;
 }
 
-static void scsi_generic_done(struct scsi_cmnd *cmd)
+static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
 {
 	BUG_ON(!blk_pc_request(cmd->request));
 	/*
@@ -1224,7 +1224,7 @@
 	scsi_io_completion(cmd, cmd->bufflen, 0);
 }
 
-void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
+static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
 {
 	struct request *req = cmd->request;
 
@@ -1241,8 +1241,8 @@
 	cmd->transfersize = req->data_len;
 	cmd->allowed = req->retries;
 	cmd->timeout_per_command = req->timeout;
+	cmd->done = scsi_blk_pc_done;
 }
-EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
 
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
@@ -1339,7 +1339,6 @@
 	 * happening now.
 	 */
 	if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
-		struct scsi_driver *drv;
 		int ret;
 
 		/*
@@ -1371,16 +1370,17 @@
 		/*
 		 * Initialize the actual SCSI command for this request.
 		 */
-		if (req->rq_disk) {
+		if (req->flags & REQ_BLOCK_PC) {
+			scsi_setup_blk_pc_cmnd(cmd);
+		} else if (req->rq_disk) {
+			struct scsi_driver *drv;
+
 			drv = *(struct scsi_driver **)req->rq_disk->private_data;
 			if (unlikely(!drv->init_command(cmd))) {
 				scsi_release_buffers(cmd);
 				scsi_put_command(cmd);
 				goto kill;
 			}
-		} else {
-			scsi_setup_blk_pc_cmnd(cmd);
-			cmd->done = scsi_generic_done;
 		}
 	}
 
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 14a6198..27c4827 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -26,12 +26,6 @@
 #define SCSI_SENSE_VALID(scmd) \
 	(((scmd)->sense_buffer[0] & 0x70) == 0x70)
 
-/*
- * Special value for scanning to specify scanning or rescanning of all
- * possible channels, (target) ids, or luns on a given shost.
- */
-#define SCAN_WILD_CARD	~0
-
 /* hosts.c */
 extern int scsi_init_hosts(void);
 extern void scsi_exit_hosts(void);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index a50958b..07be62b 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -25,11 +25,13 @@
 #include <linux/errno.h>
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -41,7 +43,7 @@
 static struct proc_dir_entry *proc_scsi;
 
 /* Protect sht->present and sht->proc_dir */
-static DECLARE_MUTEX(global_host_template_sem);
+static DEFINE_MUTEX(global_host_template_mutex);
 
 static int proc_scsi_read(char *buffer, char **start, off_t offset,
 			  int length, int *eof, void *data)
@@ -83,7 +85,7 @@
 	if (!sht->proc_info)
 		return;
 
-	down(&global_host_template_sem);
+	mutex_lock(&global_host_template_mutex);
 	if (!sht->present++) {
 		sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
         	if (!sht->proc_dir)
@@ -92,7 +94,7 @@
 		else
 			sht->proc_dir->owner = sht->module;
 	}
-	up(&global_host_template_sem);
+	mutex_unlock(&global_host_template_mutex);
 }
 
 void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
@@ -100,12 +102,12 @@
 	if (!sht->proc_info)
 		return;
 
-	down(&global_host_template_sem);
+	mutex_lock(&global_host_template_mutex);
 	if (!--sht->present && sht->proc_dir) {
 		remove_proc_entry(sht->proc_name, proc_scsi);
 		sht->proc_dir = NULL;
 	}
-	up(&global_host_template_sem);
+	mutex_unlock(&global_host_template_mutex);
 }
 
 void scsi_proc_host_add(struct Scsi_Host *shost)
@@ -199,7 +201,10 @@
 	if (IS_ERR(shost))
 		return PTR_ERR(shost);
 
-	error = scsi_scan_host_selected(shost, channel, id, lun, 1);
+	if (shost->transportt->user_scan)
+		error = shost->transportt->user_scan(shost, channel, id, lun);
+	else
+		error = scsi_scan_host_selected(shost, channel, id, lun, 1);
 	scsi_host_put(shost);
 	return error;
 }
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 05ebb9c..752fb5d 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -334,19 +334,6 @@
 	struct scsi_target *starget;
 	struct scsi_target *found_target;
 
-	/*
-	 * Obtain the real parent from the transport. The transport
-	 * is allowed to fail (no error) if there is nothing at that
-	 * target id.
-	 */
-	if (shost->transportt->target_parent) {
-		spin_lock_irqsave(shost->host_lock, flags);
-		parent = shost->transportt->target_parent(shost, channel, id);
-		spin_unlock_irqrestore(shost->host_lock, flags);
-		if (!parent)
-			return NULL;
-	}
-
 	starget = kmalloc(size, GFP_KERNEL);
 	if (!starget) {
 		printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
@@ -1283,20 +1270,21 @@
 	struct scsi_device *sdev;
 	struct device *parent = &shost->shost_gendev;
 	int res;
-	struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+	struct scsi_target *starget;
 
+	starget = scsi_alloc_target(parent, channel, id);
 	if (!starget)
 		return ERR_PTR(-ENOMEM);
 
 	get_device(&starget->dev);
-	down(&shost->scan_mutex);
+	mutex_lock(&shost->scan_mutex);
 	if (scsi_host_scan_allowed(shost)) {
 		res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
 					     hostdata);
 		if (res != SCSI_SCAN_LUN_PRESENT)
 			sdev = ERR_PTR(-ENODEV);
 	}
-	up(&shost->scan_mutex);
+	mutex_unlock(&shost->scan_mutex);
 	scsi_target_reap(starget);
 	put_device(&starget->dev);
 
@@ -1404,10 +1392,10 @@
 {
 	struct Scsi_Host *shost = dev_to_shost(parent);
 
-	down(&shost->scan_mutex);
+	mutex_lock(&shost->scan_mutex);
 	if (scsi_host_scan_allowed(shost))
 		__scsi_scan_target(parent, channel, id, lun, rescan);
-	up(&shost->scan_mutex);
+	mutex_unlock(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_scan_target);
 
@@ -1454,7 +1442,7 @@
 	    ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
 		return -EINVAL;
 
-	down(&shost->scan_mutex);
+	mutex_lock(&shost->scan_mutex);
 	if (scsi_host_scan_allowed(shost)) {
 		if (channel == SCAN_WILD_CARD)
 			for (channel = 0; channel <= shost->max_channel;
@@ -1464,7 +1452,7 @@
 		else
 			scsi_scan_channel(shost, channel, id, lun, rescan);
 	}
-	up(&shost->scan_mutex);
+	mutex_unlock(&shost->scan_mutex);
 
 	return 0;
 }
@@ -1522,7 +1510,7 @@
 	struct scsi_device *sdev = NULL;
 	struct scsi_target *starget;
 
-	down(&shost->scan_mutex);
+	mutex_lock(&shost->scan_mutex);
 	if (!scsi_host_scan_allowed(shost))
 		goto out;
 	starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
@@ -1536,7 +1524,7 @@
 	}
 	put_device(&starget->dev);
  out:
-	up(&shost->scan_mutex);
+	mutex_unlock(&shost->scan_mutex);
 	return sdev;
 }
 EXPORT_SYMBOL(scsi_get_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index ea7f3a4..a77b32d 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -106,7 +106,10 @@
 		return -EINVAL;
 	if (check_set(&lun, s3))
 		return -EINVAL;
-	res = scsi_scan_host_selected(shost, channel, id, lun, 1);
+	if (shost->transportt->user_scan)
+		res = shost->transportt->user_scan(shost, channel, id, lun);
+	else
+		res = scsi_scan_host_selected(shost, channel, id, lun, 1);
 	return res;
 }
 
@@ -745,9 +748,9 @@
 {
 	struct Scsi_Host *shost = sdev->host;
 
-	down(&shost->scan_mutex);
+	mutex_lock(&shost->scan_mutex);
 	__scsi_remove_device(sdev);
-	up(&shost->scan_mutex);
+	mutex_unlock(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
 
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 685b997..f2c9acf 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -295,6 +295,7 @@
 	 */
 	fc_host_node_name(shost) = -1;
 	fc_host_port_name(shost) = -1;
+	fc_host_permanent_port_name(shost) = -1;
 	fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
 	memset(fc_host_supported_fc4s(shost), 0,
 		sizeof(fc_host_supported_fc4s(shost)));
@@ -795,6 +796,8 @@
 
 fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
 fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
+			     unsigned long long);
 fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
 fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
 fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
@@ -1090,17 +1093,23 @@
 /*
  * Must be called with shost->host_lock held
  */
-static struct device *fc_target_parent(struct Scsi_Host *shost,
-					int channel, uint id)
+static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+		uint id, uint lun)
 {
 	struct fc_rport *rport;
 
-	list_for_each_entry(rport, &fc_host_rports(shost), peers)
-		if ((rport->channel == channel) &&
-		    (rport->scsi_target_id == id))
-			return &rport->dev;
+	list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+		if (rport->scsi_target_id == -1)
+			continue;
 
-	return NULL;
+		if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
+		    (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
+			scsi_scan_target(&rport->dev, rport->channel,
+					 rport->scsi_target_id, lun, 1);
+		}
+	}
+
+	return 0;
 }
 
 struct scsi_transport_template *
@@ -1139,7 +1148,7 @@
 	/* Transport uses the shost workq for scsi scanning */
 	i->t.create_work_queue = 1;
 
-	i->t.target_parent = fc_target_parent;
+	i->t.user_scan = fc_user_scan;
 	
 	/*
 	 * Setup SCSI Target Attributes.
@@ -1160,6 +1169,7 @@
 	count=0;
 	SETUP_HOST_ATTRIBUTE_RD(node_name);
 	SETUP_HOST_ATTRIBUTE_RD(port_name);
+	SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
 	SETUP_HOST_ATTRIBUTE_RD(supported_classes);
 	SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
 	SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e08462d..59a1c9d 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -21,11 +21,9 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 #include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
 #include <linux/mempool.h>
+#include <linux/mutex.h>
 #include <net/tcp.h>
-
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
@@ -45,11 +43,6 @@
 	 */
 	struct list_head sessions;
 	/*
-	 * lock to serialize access to the sessions list which must
-	 * be taken after the rx_queue_sema
-	 */
-	spinlock_t session_lock;
-	/*
 	 * based on transport capabilities, at register time we set these
 	 * bits to tell the transport class it wants attributes displayed
 	 * in sysfs or that it can support different iSCSI Data-Path
@@ -70,7 +63,7 @@
 /*
  * list of registered transports and lock that must
  * be held while accessing list. The iscsi_transport_lock must
- * be acquired after the rx_queue_sema.
+ * be acquired after the rx_queue_mutex.
  */
 static LIST_HEAD(iscsi_transports);
 static DEFINE_SPINLOCK(iscsi_transport_lock);
@@ -145,7 +138,7 @@
 
 static struct sock *nls;
 static int daemon_pid;
-static DECLARE_MUTEX(rx_queue_sema);
+static DEFINE_MUTEX(rx_queue_mutex);
 
 struct mempool_zone {
 	mempool_t *pool;
@@ -156,7 +149,7 @@
 	spinlock_t freelock;
 };
 
-static struct mempool_zone z_reply;
+static struct mempool_zone *z_reply;
 
 /*
  * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
@@ -171,50 +164,271 @@
 #define Z_MAX_ERROR	16
 #define Z_HIWAT_ERROR	12
 
-struct iscsi_if_conn {
-	struct list_head conn_list;	/* item in connlist */
-	struct list_head session_list;	/* item in session->connections */
-	iscsi_connh_t connh;
-	int active;			/* must be accessed with the connlock */
-	struct Scsi_Host *host;		/* originated shost */
-	struct device dev;		/* sysfs transport/container device */
-	struct iscsi_transport *transport;
-	struct mempool_zone z_error;
-	struct mempool_zone z_pdu;
-	struct list_head freequeue;
-};
-
-#define iscsi_dev_to_if_conn(_dev) \
-	container_of(_dev, struct iscsi_if_conn, dev)
-
-#define iscsi_cdev_to_if_conn(_cdev) \
-	iscsi_dev_to_if_conn(_cdev->dev)
-
 static LIST_HEAD(connlist);
 static DEFINE_SPINLOCK(connlock);
 
-struct iscsi_if_session {
-	struct list_head list;	/* item in session_list */
-	struct list_head connections;
-	iscsi_sessionh_t sessionh;
-	struct iscsi_transport *transport;
-	struct device dev;	/* sysfs transport/container device */
-};
+/*
+ * The following functions can be used by LLDs that allocate
+ * their own scsi_hosts or by software iscsi LLDs
+ */
+static void iscsi_session_release(struct device *dev)
+{
+	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
+	struct iscsi_transport *transport = session->transport;
+	struct Scsi_Host *shost;
 
-#define iscsi_dev_to_if_session(_dev) \
-	container_of(_dev, struct iscsi_if_session, dev)
+	shost = iscsi_session_to_shost(session);
+	scsi_host_put(shost);
+	kfree(session);
+	module_put(transport->owner);
+}
 
-#define iscsi_cdev_to_if_session(_cdev) \
-	iscsi_dev_to_if_session(_cdev->dev)
+static int iscsi_is_session_dev(const struct device *dev)
+{
+	return dev->release == iscsi_session_release;
+}
 
-#define iscsi_if_session_to_shost(_session) \
-	dev_to_shost(_session->dev.parent)
+/**
+ * iscsi_create_session - create iscsi class session
+ * @shost: scsi host
+ * @transport: iscsi transport
+ *
+ * This can be called from a LLD or iscsi_transport
+ **/
+struct iscsi_cls_session *
+iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+{
+	struct iscsi_cls_session *session;
+	int err;
 
-static struct iscsi_if_conn*
+	if (!try_module_get(transport->owner))
+		return NULL;
+
+	session = kzalloc(sizeof(*session), GFP_KERNEL);
+	if (!session)
+		goto module_put;
+	session->transport = transport;
+
+	/* this is released in the dev's release function */
+	scsi_host_get(shost);
+	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
+	session->dev.parent = &shost->shost_gendev;
+	session->dev.release = iscsi_session_release;
+	err = device_register(&session->dev);
+	if (err) {
+		dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
+			   "register session's dev\n");
+		goto free_session;
+	}
+	transport_register_device(&session->dev);
+
+	return session;
+
+free_session:
+	kfree(session);
+module_put:
+	module_put(transport->owner);
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_session);
+
+/**
+ * iscsi_destroy_session - destroy iscsi session
+ * @session: iscsi_session
+ *
+ * Can be called by a LLD or iscsi_transport. There must not be
+ * any running connections.
+ **/
+int iscsi_destroy_session(struct iscsi_cls_session *session)
+{
+	transport_unregister_device(&session->dev);
+	device_unregister(&session->dev);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+
+static void iscsi_conn_release(struct device *dev)
+{
+	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+	struct device *parent = conn->dev.parent;
+
+	kfree(conn);
+	put_device(parent);
+}
+
+static int iscsi_is_conn_dev(const struct device *dev)
+{
+	return dev->release == iscsi_conn_release;
+}
+
+/**
+ * iscsi_create_conn - create iscsi class connection
+ * @session: iscsi cls session
+ * @cid: connection id
+ *
+ * This can be called from a LLD or iscsi_transport. The connection
+ * is child of the session so cid must be unique for all connections
+ * on the session.
+ **/
+struct iscsi_cls_conn *
+iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+{
+	struct iscsi_transport *transport = session->transport;
+	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+	struct iscsi_cls_conn *conn;
+	int err;
+
+	conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
+	if (!conn)
+		return NULL;
+
+	if (transport->conndata_size)
+		conn->dd_data = &conn[1];
+
+	INIT_LIST_HEAD(&conn->conn_list);
+	conn->transport = transport;
+
+	/* this is released in the dev's release function */
+	if (!get_device(&session->dev))
+		goto free_conn;
+	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+		 shost->host_no, cid);
+	conn->dev.parent = &session->dev;
+	conn->dev.release = iscsi_conn_release;
+	err = device_register(&conn->dev);
+	if (err) {
+		dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
+			   "connection's dev\n");
+		goto release_parent_ref;
+	}
+	transport_register_device(&conn->dev);
+	return conn;
+
+release_parent_ref:
+	put_device(&session->dev);
+free_conn:
+	kfree(conn);
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_conn);
+
+/**
+ * iscsi_destroy_conn - destroy iscsi class connection
+ * @session: iscsi cls session
+ *
+ * This can be called from a LLD or iscsi_transport.
+ **/
+int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+{
+	transport_unregister_device(&conn->dev);
+	device_unregister(&conn->dev);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
+
+/*
+ * These functions are used only by software iscsi_transports
+ * which do not allocate and more their scsi_hosts since this
+ * is initiated from userspace.
+ */
+
+/*
+ * iSCSI Session's hostdata organization:
+ *
+ *    *------------------* <== hostdata_session(host->hostdata)
+ *    | ptr to class sess|
+ *    |------------------| <== iscsi_hostdata(host->hostdata)
+ *    | transport's data |
+ *    *------------------*
+ */
+
+#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
+				 _t->hostdata_size % sizeof(unsigned long))
+
+#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+
+/**
+ * iscsi_transport_create_session - create iscsi cls session and host
+ * scsit: scsi transport template
+ * transport: iscsi transport template
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+struct Scsi_Host *
+iscsi_transport_create_session(struct scsi_transport_template *scsit,
+			       struct iscsi_transport *transport)
+{
+	struct iscsi_cls_session *session;
+	struct Scsi_Host *shost;
+
+	shost = scsi_host_alloc(transport->host_template,
+				hostdata_privsize(transport));
+	if (!shost) {
+		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
+			"session\n");
+		return NULL;
+	}
+
+	shost->max_id = 1;
+	shost->max_channel = 0;
+	shost->max_lun = transport->max_lun;
+	shost->max_cmd_len = transport->max_cmd_len;
+	shost->transportt = scsit;
+	shost->transportt->create_work_queue = 1;
+
+	if (scsi_add_host(shost, NULL))
+		goto free_host;
+
+	session = iscsi_create_session(shost, transport);
+	if (!session)
+		goto remove_host;
+
+	*(unsigned long*)shost->hostdata = (unsigned long)session;
+	return shost;
+
+remove_host:
+	scsi_remove_host(shost);
+free_host:
+	scsi_host_put(shost);
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
+
+/**
+ * iscsi_transport_destroy_session - destroy session and scsi host
+ * shost: scsi host
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+int iscsi_transport_destroy_session(struct Scsi_Host *shost)
+{
+	struct iscsi_cls_session *session;
+
+	scsi_remove_host(shost);
+	session = hostdata_session(shost->hostdata);
+	iscsi_destroy_session(session);
+	/* ref from host alloc */
+	scsi_host_put(shost);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
+
+/*
+ * iscsi interface functions
+ */
+static struct iscsi_cls_conn*
 iscsi_if_find_conn(uint64_t key)
 {
 	unsigned long flags;
-	struct iscsi_if_conn *conn;
+	struct iscsi_cls_conn *conn;
 
 	spin_lock_irqsave(&connlock, flags);
 	list_for_each_entry(conn, &connlist, conn_list)
@@ -249,7 +463,7 @@
 }
 
 static void*
-mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
 {
 	struct mempool_zone *zone = pool_data;
 
@@ -281,14 +495,21 @@
 	spin_unlock_irqrestore(&zone->freelock, flags);
 }
 
-static int
-mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
-		unsigned hiwat)
+static struct mempool_zone *
+mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
 {
+	struct mempool_zone *zp;
+
+	zp = kzalloc(sizeof(*zp), GFP_KERNEL);
+	if (!zp)
+		return NULL;
+
 	zp->pool = mempool_create(max, mempool_zone_alloc_skb,
 				  mempool_zone_free_skb, zp);
-	if (!zp->pool)
-		return -ENOMEM;
+	if (!zp->pool) {
+		kfree(zp);
+		return NULL;
+	}
 
 	zp->size = size;
 	zp->hiwat = hiwat;
@@ -297,9 +518,14 @@
 	spin_lock_init(&zp->freelock);
 	atomic_set(&zp->allocated, 0);
 
-	return 0;
+	return zp;
 }
 
+static void mempool_zone_destroy(struct mempool_zone *zp)
+{
+	mempool_destroy(zp->pool);
+	kfree(zp);
+}
 
 static struct sk_buff*
 mempool_zone_get_skb(struct mempool_zone *zone)
@@ -339,7 +565,7 @@
 	struct nlmsghdr	*nlh;
 	struct sk_buff *skb;
 	struct iscsi_uevent *ev;
-	struct iscsi_if_conn *conn;
+	struct iscsi_cls_conn *conn;
 	char *pdu;
 	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
 			      data_size);
@@ -347,13 +573,13 @@
 	conn = iscsi_if_find_conn(connh);
 	BUG_ON(!conn);
 
-	mempool_zone_complete(&conn->z_pdu);
+	mempool_zone_complete(conn->z_pdu);
 
-	skb = mempool_zone_get_skb(&conn->z_pdu);
+	skb = mempool_zone_get_skb(conn->z_pdu);
 	if (!skb) {
 		iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
-		printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n",
-		       conn->host->host_no);
+		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
+			   "control PDU: OOM\n");
 		return -ENOMEM;
 	}
 
@@ -362,14 +588,14 @@
 	memset(ev, 0, sizeof(*ev));
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_RECV_PDU;
-	if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
+	if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
 		ev->iferror = -ENOMEM;
 	ev->r.recv_req.conn_handle = connh;
 	pdu = (char*)ev + sizeof(*ev);
 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
 
-	return iscsi_unicast_skb(&conn->z_pdu, skb);
+	return iscsi_unicast_skb(conn->z_pdu, skb);
 }
 EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
 
@@ -378,18 +604,18 @@
 	struct nlmsghdr	*nlh;
 	struct sk_buff	*skb;
 	struct iscsi_uevent *ev;
-	struct iscsi_if_conn *conn;
+	struct iscsi_cls_conn *conn;
 	int len = NLMSG_SPACE(sizeof(*ev));
 
 	conn = iscsi_if_find_conn(connh);
 	BUG_ON(!conn);
 
-	mempool_zone_complete(&conn->z_error);
+	mempool_zone_complete(conn->z_error);
 
-	skb = mempool_zone_get_skb(&conn->z_error);
+	skb = mempool_zone_get_skb(conn->z_error);
 	if (!skb) {
-		printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n",
-		       conn->host->host_no, error);
+		dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
+			  "conn error (%d)\n", error);
 		return;
 	}
 
@@ -397,15 +623,15 @@
 	ev = NLMSG_DATA(nlh);
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_CONN_ERROR;
-	if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat)
+	if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
 		ev->iferror = -ENOMEM;
 	ev->r.connerror.error = error;
 	ev->r.connerror.conn_handle = connh;
 
-	iscsi_unicast_skb(&conn->z_error, skb);
+	iscsi_unicast_skb(conn->z_error, skb);
 
-	printk(KERN_INFO "iscsi%d: detected conn error (%d)\n",
-	       conn->host->host_no, error);
+	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+		   error);
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_error);
 
@@ -419,9 +645,9 @@
 	int flags = multi ? NLM_F_MULTI : 0;
 	int t = done ? NLMSG_DONE : type;
 
-	mempool_zone_complete(&z_reply);
+	mempool_zone_complete(z_reply);
 
-	skb = mempool_zone_get_skb(&z_reply);
+	skb = mempool_zone_get_skb(z_reply);
 	/*
 	 * FIXME:
 	 * user is supposed to react on iferror == -ENOMEM;
@@ -432,304 +658,7 @@
 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
 	nlh->nlmsg_flags = flags;
 	memcpy(NLMSG_DATA(nlh), payload, size);
-	return iscsi_unicast_skb(&z_reply, skb);
-}
-
-/*
- * iSCSI Session's hostdata organization:
- *
- *    *------------------* <== host->hostdata
- *    | transport        |
- *    |------------------| <== iscsi_hostdata(host->hostdata)
- *    | transport's data |
- *    |------------------| <== hostdata_session(host->hostdata)
- *    | interface's data |
- *    *------------------*
- */
-
-#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
-				 _t->hostdata_size % sizeof(unsigned long) + \
-				 sizeof(struct iscsi_if_session))
-
-#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \
-			((struct iscsi_transport *) \
-			 iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
-
-static void iscsi_if_session_dev_release(struct device *dev)
-{
-	struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
-	struct iscsi_transport *transport = session->transport;
-	struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
-	struct iscsi_if_conn *conn, *tmp;
-	unsigned long flags;
-
-	/* now free connections */
-	spin_lock_irqsave(&connlock, flags);
-	list_for_each_entry_safe(conn, tmp, &session->connections,
-				 session_list) {
-		list_del(&conn->session_list);
-		mempool_destroy(conn->z_pdu.pool);
-		mempool_destroy(conn->z_error.pool);
-		kfree(conn);
-	}
-	spin_unlock_irqrestore(&connlock, flags);
-	scsi_host_put(shost);
-	module_put(transport->owner);
-}
-
-static int
-iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
-{
-	struct iscsi_transport *transport = priv->iscsi_transport;
-	struct iscsi_if_session *session;
-	struct Scsi_Host *shost;
-	unsigned long flags;
-	int error;
-
-	if (!try_module_get(transport->owner))
-		return -EPERM;
-
-	shost = scsi_host_alloc(transport->host_template,
-				hostdata_privsize(transport));
-	if (!shost) {
-		ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
-		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
-		       "session\n");
-		error = -ENOMEM;
-		goto out_module_put;
-	}
-	shost->max_id = 1;
-	shost->max_channel = 0;
-	shost->max_lun = transport->max_lun;
-	shost->max_cmd_len = transport->max_cmd_len;
-	shost->transportt = &priv->t;
-
-	/* store struct iscsi_transport in hostdata */
-	*(uint64_t*)shost->hostdata = ev->transport_handle;
-
-	ev->r.c_session_ret.session_handle = transport->create_session(
-					ev->u.c_session.initial_cmdsn, shost);
-	if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) {
-		error = 0;
-		goto out_host_put;
-	}
-
-	/* host_no becomes assigned SID */
-	ev->r.c_session_ret.sid = shost->host_no;
-	/* initialize session */
-	session = hostdata_session(shost->hostdata);
-	INIT_LIST_HEAD(&session->connections);
-	INIT_LIST_HEAD(&session->list);
-	session->sessionh = ev->r.c_session_ret.session_handle;
-	session->transport = transport;
-
-	error = scsi_add_host(shost, NULL);
-	if (error)
-		goto out_destroy_session;
-
-	/*
-	 * this is released in the dev's release function)
-	 */
-	scsi_host_get(shost);
-	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
-	session->dev.parent = &shost->shost_gendev;
-	session->dev.release = iscsi_if_session_dev_release;
-	error = device_register(&session->dev);
-	if (error) {
-		printk(KERN_ERR "iscsi: could not register session%d's dev\n",
-		       shost->host_no);
-		goto out_remove_host;
-	}
-	transport_register_device(&session->dev);
-
-	/* add this session to the list of active sessions */
-	spin_lock_irqsave(&priv->session_lock, flags);
-	list_add(&session->list, &priv->sessions);
-	spin_unlock_irqrestore(&priv->session_lock, flags);
-
-	return 0;
-
-out_remove_host:
-	scsi_remove_host(shost);
-out_destroy_session:
-	transport->destroy_session(ev->r.c_session_ret.session_handle);
-	ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
-out_host_put:
-	scsi_host_put(shost);
-out_module_put:
-	module_put(transport->owner);
-	return error;
-}
-
-static int
-iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
-{
-	struct iscsi_transport *transport = priv->iscsi_transport;
-	struct Scsi_Host *shost;
-	struct iscsi_if_session *session;
-	unsigned long flags;
-	struct iscsi_if_conn *conn;
-	int error = 0;
-
-	shost = scsi_host_lookup(ev->u.d_session.sid);
-	if (shost == ERR_PTR(-ENXIO))
-		return -EEXIST;
-	session = hostdata_session(shost->hostdata);
-
-	/* check if we have active connections */
-	spin_lock_irqsave(&connlock, flags);
-	list_for_each_entry(conn, &session->connections, session_list) {
-		if (conn->active) {
-			printk(KERN_ERR "iscsi%d: can not destroy session: "
-			       "has active connection (%p)\n",
-			       shost->host_no, iscsi_ptr(conn->connh));
-			spin_unlock_irqrestore(&connlock, flags);
-			error = EIO;
-			goto out_release_ref;
-		}
-	}
-	spin_unlock_irqrestore(&connlock, flags);
-
-	scsi_remove_host(shost);
-	transport->destroy_session(ev->u.d_session.session_handle);
-	transport_unregister_device(&session->dev);
-	device_unregister(&session->dev);
-
-	/* remove this session from the list of active sessions */
-	spin_lock_irqsave(&priv->session_lock, flags);
-	list_del(&session->list);
-	spin_unlock_irqrestore(&priv->session_lock, flags);
-
-	/* ref from host alloc */
-	scsi_host_put(shost);
-out_release_ref:
-	/* ref from host lookup */
-	scsi_host_put(shost);
-	return error;
-}
-
-static void iscsi_if_conn_dev_release(struct device *dev)
-{
-	struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
-	struct Scsi_Host *shost = conn->host;
-
-	scsi_host_put(shost);
-}
-
-static int
-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
-{
-	struct iscsi_if_session *session;
-	struct Scsi_Host *shost;
-	struct iscsi_if_conn *conn;
-	unsigned long flags;
-	int error;
-
-	shost = scsi_host_lookup(ev->u.c_conn.sid);
-	if (shost == ERR_PTR(-ENXIO))
-		return -EEXIST;
-	session = hostdata_session(shost->hostdata);
-
-	conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL);
-	if (!conn) {
-		error = -ENOMEM;
-		goto out_release_ref;
-	}
-	memset(conn, 0, sizeof(struct iscsi_if_conn));
-	INIT_LIST_HEAD(&conn->session_list);
-	INIT_LIST_HEAD(&conn->conn_list);
-	conn->host = shost;
-	conn->transport = transport;
-
-	error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU,
-			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
-				    sizeof(struct iscsi_hdr) +
-				    DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
-			Z_HIWAT_PDU);
-	if (error) {
-		printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new "
-		       "conn\n", shost->host_no);
-		goto out_free_conn;
-	}
-	error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR,
-			NLMSG_SPACE(sizeof(struct iscsi_uevent)),
-			Z_HIWAT_ERROR);
-	if (error) {
-		printk(KERN_ERR "iscsi%d: can not allocate error zone for "
-		       "new conn\n", shost->host_no);
-		goto out_free_pdu_pool;
-	}
-
-	ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
-					ev->u.c_conn.cid);
-	if (!ev->r.handle) {
-		error = -ENODEV;
-		goto out_free_error_pool;
-	}
-
-	conn->connh = ev->r.handle;
-
-	/*
-	 * this is released in the dev's release function
-	 */
-	if (!scsi_host_get(shost))
-		goto out_destroy_conn;
-	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
-		 shost->host_no, ev->u.c_conn.cid);
-	conn->dev.parent = &session->dev;
-	conn->dev.release = iscsi_if_conn_dev_release;
-	error = device_register(&conn->dev);
-	if (error) {
-		printk(KERN_ERR "iscsi%d: could not register connections%u "
-		       "dev\n", shost->host_no, ev->u.c_conn.cid);
-		goto out_release_parent_ref;
-	}
-	transport_register_device(&conn->dev);
-
-	spin_lock_irqsave(&connlock, flags);
-	list_add(&conn->conn_list, &connlist);
-	list_add(&conn->session_list, &session->connections);
-	conn->active = 1;
-	spin_unlock_irqrestore(&connlock, flags);
-
-	scsi_host_put(shost);
-	return 0;
-
-out_release_parent_ref:
-	scsi_host_put(shost);
-out_destroy_conn:
-	transport->destroy_conn(ev->r.handle);
-out_free_error_pool:
-	mempool_destroy(conn->z_error.pool);
-out_free_pdu_pool:
-	mempool_destroy(conn->z_pdu.pool);
-out_free_conn:
-	kfree(conn);
-out_release_ref:
-	scsi_host_put(shost);
-	return error;
-}
-
-static int
-iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
-{
-	unsigned long flags;
-	struct iscsi_if_conn *conn;
-
-	conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
-	if (!conn)
-		return -EEXIST;
-
-	transport->destroy_conn(ev->u.d_conn.conn_handle);
-
-	spin_lock_irqsave(&connlock, flags);
-	conn->active = 0;
-	list_del(&conn->conn_list);
-	spin_unlock_irqrestore(&connlock, flags);
-
-	transport_unregister_device(&conn->dev);
-	device_unregister(&conn->dev);
-	return 0;
+	return iscsi_unicast_skb(z_reply, skb);
 }
 
 static int
@@ -739,7 +668,7 @@
 	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
 	struct iscsi_stats *stats;
 	struct sk_buff *skbstat;
-	struct iscsi_if_conn *conn;
+	struct iscsi_cls_conn *conn;
 	struct nlmsghdr	*nlhstat;
 	struct iscsi_uevent *evstat;
 	int len = NLMSG_SPACE(sizeof(*ev) +
@@ -755,12 +684,12 @@
 	do {
 		int actual_size;
 
-		mempool_zone_complete(&conn->z_pdu);
+		mempool_zone_complete(conn->z_pdu);
 
-		skbstat = mempool_zone_get_skb(&conn->z_pdu);
+		skbstat = mempool_zone_get_skb(conn->z_pdu);
 		if (!skbstat) {
-			printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
-			       conn->host->host_no);
+			dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
+				   "deliver stats: OOM\n");
 			return -ENOMEM;
 		}
 
@@ -770,7 +699,7 @@
 		memset(evstat, 0, sizeof(*evstat));
 		evstat->transport_handle = iscsi_handle(conn->transport);
 		evstat->type = nlh->nlmsg_type;
-		if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
+		if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
 			evstat->iferror = -ENOMEM;
 		evstat->u.get_stats.conn_handle =
 			ev->u.get_stats.conn_handle;
@@ -788,13 +717,141 @@
 		skb_trim(skb, NLMSG_ALIGN(actual_size));
 		nlhstat->nlmsg_len = actual_size;
 
-		err = iscsi_unicast_skb(&conn->z_pdu, skbstat);
+		err = iscsi_unicast_skb(conn->z_pdu, skbstat);
 	} while (err < 0 && err != -ECONNREFUSED);
 
 	return err;
 }
 
 static int
+iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+{
+	struct iscsi_transport *transport = priv->iscsi_transport;
+	struct Scsi_Host *shost;
+
+	if (!transport->create_session)
+		return -EINVAL;
+
+	shost = transport->create_session(&priv->t,
+					  ev->u.c_session.initial_cmdsn);
+	if (!shost)
+		return -ENOMEM;
+
+	ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
+	ev->r.c_session_ret.sid = shost->host_no;
+	return 0;
+}
+
+static int
+iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+{
+	struct iscsi_transport *transport = priv->iscsi_transport;
+
+	struct Scsi_Host *shost;
+
+	if (!transport->destroy_session)
+		return -EINVAL;
+
+	shost = scsi_host_lookup(ev->u.d_session.sid);
+	if (shost == ERR_PTR(-ENXIO))
+		return -EEXIST;
+
+	if (transport->destroy_session)
+		transport->destroy_session(shost);
+        /* ref from host lookup */
+        scsi_host_put(shost);
+	return 0;
+}
+
+static int
+iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
+	struct Scsi_Host *shost;
+	struct iscsi_cls_conn *conn;
+	unsigned long flags;
+
+	if (!transport->create_conn)
+		return -EINVAL;
+
+	shost = scsi_host_lookup(ev->u.c_conn.sid);
+	if (shost == ERR_PTR(-ENXIO))
+		return -EEXIST;
+
+	conn = transport->create_conn(shost, ev->u.c_conn.cid);
+	if (!conn)
+		goto release_ref;
+
+	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
+			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+				    sizeof(struct iscsi_hdr) +
+				    DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
+			Z_HIWAT_PDU);
+	if (!conn->z_pdu) {
+		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+			   "pdu zone for new conn\n");
+		goto destroy_conn;
+	}
+
+	conn->z_error = mempool_zone_init(Z_MAX_ERROR,
+			NLMSG_SPACE(sizeof(struct iscsi_uevent)),
+			Z_HIWAT_ERROR);
+	if (!conn->z_error) {
+		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+			   "error zone for new conn\n");
+		goto free_pdu_pool;
+	}
+
+	ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
+
+	spin_lock_irqsave(&connlock, flags);
+	list_add(&conn->conn_list, &connlist);
+	conn->active = 1;
+	spin_unlock_irqrestore(&connlock, flags);
+
+	scsi_host_put(shost);
+	return 0;
+
+free_pdu_pool:
+	mempool_zone_destroy(conn->z_pdu);
+destroy_conn:
+	if (transport->destroy_conn)
+		transport->destroy_conn(conn->dd_data);
+release_ref:
+	scsi_host_put(shost);
+	return -ENOMEM;
+}
+
+static int
+iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+{
+	unsigned long flags;
+	struct iscsi_cls_conn *conn;
+	struct mempool_zone *z_error, *z_pdu;
+
+	conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
+	if (!conn)
+		return -EEXIST;
+
+	if (!transport->destroy_conn)
+		return -EINVAL;
+
+	spin_lock_irqsave(&connlock, flags);
+	conn->active = 0;
+	list_del(&conn->conn_list);
+	spin_unlock_irqrestore(&connlock, flags);
+
+	z_pdu = conn->z_pdu;
+	z_error = conn->z_error;
+
+	if (transport->destroy_conn)
+		transport->destroy_conn(conn);
+
+	mempool_zone_destroy(z_pdu);
+	mempool_zone_destroy(z_error);
+
+	return 0;
+}
+
+static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	int err = 0;
@@ -881,7 +938,7 @@
 {
 	struct sk_buff *skb;
 
-	down(&rx_queue_sema);
+	mutex_lock(&rx_queue_mutex);
 	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
 		while (skb->len >= NLMSG_SPACE(0)) {
 			int err;
@@ -915,17 +972,20 @@
 				err = iscsi_if_send_reply(
 					NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
 					nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
-				if (atomic_read(&z_reply.allocated) >=
-						z_reply.hiwat)
+				if (atomic_read(&z_reply->allocated) >=
+						z_reply->hiwat)
 					ev->iferror = -ENOMEM;
 			} while (err < 0 && err != -ECONNREFUSED);
 			skb_pull(skb, rlen);
 		}
 		kfree_skb(skb);
 	}
-	up(&rx_queue_sema);
+	mutex_unlock(&rx_queue_mutex);
 }
 
+#define iscsi_cdev_to_conn(_cdev) \
+	iscsi_dev_to_conn(_cdev->dev)
+
 /*
  * iSCSI connection attrs
  */
@@ -934,12 +994,10 @@
 show_conn_int_param_##param(struct class_device *cdev, char *buf)	\
 {									\
 	uint32_t value = 0;						\
-	struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev);	\
-	struct iscsi_internal *priv;					\
+	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+	struct iscsi_transport *t = conn->transport;			\
 									\
-	priv = to_iscsi_internal(conn->host->transportt);		\
-	if (priv->param_mask & (1 << param))				\
-		priv->iscsi_transport->get_param(conn->connh, param, &value); \
+	t->get_conn_param(conn->dd_data, param, &value);		\
 	return snprintf(buf, 20, format"\n", value);			\
 }
 
@@ -954,6 +1012,9 @@
 iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
 iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
 
+#define iscsi_cdev_to_session(_cdev) \
+	iscsi_dev_to_session(_cdev->dev)
+
 /*
  * iSCSI session attrs
  */
@@ -962,20 +1023,11 @@
 show_session_int_param_##param(struct class_device *cdev, char *buf)	\
 {									\
 	uint32_t value = 0;						\
-	struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \
-	struct Scsi_Host *shost = iscsi_if_session_to_shost(session);	\
-	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
-	struct iscsi_if_conn *conn = NULL;				\
-	unsigned long  flags;						\
+	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);	\
+	struct Scsi_Host *shost = iscsi_session_to_shost(session);	\
+	struct iscsi_transport *t = session->transport;			\
 									\
-	spin_lock_irqsave(&connlock, flags);				\
-	if (!list_empty(&session->connections))				\
-		conn = list_entry(session->connections.next,		\
-				  struct iscsi_if_conn, session_list);	\
-	spin_unlock_irqrestore(&connlock, flags);			\
-									\
-	if (conn && (priv->param_mask & (1 << param)))			\
-		priv->iscsi_transport->get_param(conn->connh, param, &value);\
+	t->get_session_param(shost, param, &value);			\
 	return snprintf(buf, 20, format"\n", value);			\
 }
 
@@ -1004,23 +1056,18 @@
 		count++;						\
 	}
 
-static int iscsi_is_session_dev(const struct device *dev)
-{
-	return dev->release == iscsi_if_session_dev_release;
-}
-
 static int iscsi_session_match(struct attribute_container *cont,
 			   struct device *dev)
 {
-	struct iscsi_if_session *session;
+	struct iscsi_cls_session *session;
 	struct Scsi_Host *shost;
 	struct iscsi_internal *priv;
 
 	if (!iscsi_is_session_dev(dev))
 		return 0;
 
-	session = iscsi_dev_to_if_session(dev);
-	shost = iscsi_if_session_to_shost(session);
+	session = iscsi_dev_to_session(dev);
+	shost = iscsi_session_to_shost(session);
 	if (!shost->transportt)
 		return 0;
 
@@ -1031,23 +1078,21 @@
 	return &priv->session_cont.ac == cont;
 }
 
-static int iscsi_is_conn_dev(const struct device *dev)
-{
-	return dev->release == iscsi_if_conn_dev_release;
-}
-
 static int iscsi_conn_match(struct attribute_container *cont,
 			   struct device *dev)
 {
-	struct iscsi_if_conn *conn;
+	struct iscsi_cls_session *session;
+	struct iscsi_cls_conn *conn;
 	struct Scsi_Host *shost;
 	struct iscsi_internal *priv;
 
 	if (!iscsi_is_conn_dev(dev))
 		return 0;
 
-	conn = iscsi_dev_to_if_conn(dev);
-	shost = conn->host;
+	conn = iscsi_dev_to_conn(dev);
+	session = iscsi_dev_to_session(conn->dev.parent);
+	shost = iscsi_session_to_shost(session);
+
 	if (!shost->transportt)
 		return 0;
 
@@ -1058,7 +1103,8 @@
 	return &priv->conn_cont.ac == cont;
 }
 
-int iscsi_register_transport(struct iscsi_transport *tt)
+struct scsi_transport_template *
+iscsi_register_transport(struct iscsi_transport *tt)
 {
 	struct iscsi_internal *priv;
 	unsigned long flags;
@@ -1068,15 +1114,14 @@
 
 	priv = iscsi_if_transport_lookup(tt);
 	if (priv)
-		return -EEXIST;
+		return NULL;
 
 	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
-		return -ENOMEM;
+		return NULL;
 	memset(priv, 0, sizeof(*priv));
 	INIT_LIST_HEAD(&priv->list);
 	INIT_LIST_HEAD(&priv->sessions);
-	spin_lock_init(&priv->session_lock);
 	priv->iscsi_transport = tt;
 
 	priv->cdev.class = &iscsi_transport_class;
@@ -1142,13 +1187,13 @@
 	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
 
 	printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
-	return 0;
+	return &priv->t;
 
 unregister_cdev:
 	class_device_unregister(&priv->cdev);
 free_priv:
 	kfree(priv);
-	return err;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(iscsi_register_transport);
 
@@ -1159,19 +1204,11 @@
 
 	BUG_ON(!tt);
 
-	down(&rx_queue_sema);
+	mutex_lock(&rx_queue_mutex);
 
 	priv = iscsi_if_transport_lookup(tt);
 	BUG_ON (!priv);
 
-	spin_lock_irqsave(&priv->session_lock, flags);
-	if (!list_empty(&priv->sessions)) {
-		spin_unlock_irqrestore(&priv->session_lock, flags);
-		up(&rx_queue_sema);
-		return -EPERM;
-	}
-	spin_unlock_irqrestore(&priv->session_lock, flags);
-
 	spin_lock_irqsave(&iscsi_transport_lock, flags);
 	list_del(&priv->list);
 	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -1181,7 +1218,7 @@
 
 	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
 	class_device_unregister(&priv->cdev);
-	up(&rx_queue_sema);
+	mutex_unlock(&rx_queue_mutex);
 
 	return 0;
 }
@@ -1194,14 +1231,14 @@
 
 	if (event == NETLINK_URELEASE &&
 	    n->protocol == NETLINK_ISCSI && n->pid) {
-		struct iscsi_if_conn *conn;
+		struct iscsi_cls_conn *conn;
 		unsigned long flags;
 
-		mempool_zone_complete(&z_reply);
+		mempool_zone_complete(z_reply);
 		spin_lock_irqsave(&connlock, flags);
 		list_for_each_entry(conn, &connlist, conn_list) {
-			mempool_zone_complete(&conn->z_error);
-			mempool_zone_complete(&conn->z_pdu);
+			mempool_zone_complete(conn->z_error);
+			mempool_zone_complete(conn->z_pdu);
 		}
 		spin_unlock_irqrestore(&connlock, flags);
 	}
@@ -1234,15 +1271,15 @@
 		goto unregister_session_class;
 
 	nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
-				    THIS_MODULE);
+			THIS_MODULE);
 	if (!nls) {
 		err = -ENOBUFS;
 		goto unregister_notifier;
 	}
 
-	err = mempool_zone_init(&z_reply, Z_MAX_REPLY,
+	z_reply = mempool_zone_init(Z_MAX_REPLY,
 		NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
-	if (!err)
+	if (z_reply)
 		return 0;
 
 	sock_release(nls->sk_socket);
@@ -1259,7 +1296,7 @@
 
 static void __exit iscsi_transport_exit(void)
 {
-	mempool_destroy(z_reply.pool);
+	mempool_zone_destroy(z_reply);
 	sock_release(nls->sk_socket);
 	netlink_unregister_notifier(&iscsi_nl_notifier);
 	transport_class_unregister(&iscsi_connection_class);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index edabbd0..a3e0b7b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
@@ -62,7 +63,7 @@
 
 struct sas_host_attrs {
 	struct list_head rphy_list;
-	spinlock_t lock;
+	struct mutex lock;
 	u32 next_target_id;
 };
 #define to_sas_host_attrs(host)	((struct sas_host_attrs *)(host)->shost_data)
@@ -165,7 +166,7 @@
 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
 	INIT_LIST_HEAD(&sas_host->rphy_list);
-	spin_lock_init(&sas_host->lock);
+	mutex_init(&sas_host->lock);
 	sas_host->next_target_id = 0;
 	return 0;
 }
@@ -626,7 +627,7 @@
 	transport_add_device(&rphy->dev);
 	transport_configure_device(&rphy->dev);
 
-	spin_lock(&sas_host->lock);
+	mutex_lock(&sas_host->lock);
 	list_add_tail(&rphy->list, &sas_host->rphy_list);
 	if (identify->device_type == SAS_END_DEVICE &&
 	    (identify->target_port_protocols &
@@ -634,10 +635,10 @@
 		rphy->scsi_target_id = sas_host->next_target_id++;
 	else
 		rphy->scsi_target_id = -1;
-	spin_unlock(&sas_host->lock);
+	mutex_unlock(&sas_host->lock);
 
 	if (rphy->scsi_target_id != -1) {
-		scsi_scan_target(&rphy->dev, parent->number,
+		scsi_scan_target(&rphy->dev, parent->port_identifier,
 				rphy->scsi_target_id, ~0, 0);
 	}
 
@@ -661,9 +662,9 @@
 	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
-	spin_lock(&sas_host->lock);
+	mutex_lock(&sas_host->lock);
 	list_del(&rphy->list);
-	spin_unlock(&sas_host->lock);
+	mutex_unlock(&sas_host->lock);
 
 	transport_destroy_device(&rphy->dev);
 	put_device(rphy->dev.parent);
@@ -687,15 +688,27 @@
 	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
-	scsi_remove_target(dev);
+	switch (rphy->identify.device_type) {
+	case SAS_END_DEVICE:
+		scsi_remove_target(dev);
+		break;
+	case SAS_EDGE_EXPANDER_DEVICE:
+	case SAS_FANOUT_EXPANDER_DEVICE:
+		device_for_each_child(dev, NULL, do_sas_phy_delete);
+		break;
+	default:
+		break;
+	}
 
 	transport_remove_device(dev);
 	device_del(dev);
 	transport_destroy_device(dev);
 
-	spin_lock(&sas_host->lock);
+	mutex_lock(&sas_host->lock);
 	list_del(&rphy->list);
-	spin_unlock(&sas_host->lock);
+	mutex_unlock(&sas_host->lock);
+
+	parent->rphy = NULL;
 
 	put_device(&parent->dev);
 }
@@ -719,23 +732,28 @@
  * SCSI scan helper
  */
 
-static struct device *sas_target_parent(struct Scsi_Host *shost,
-					int channel, uint id)
+static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+		uint id, uint lun)
 {
 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 	struct sas_rphy *rphy;
-	struct device *dev = NULL;
 
-	spin_lock(&sas_host->lock);
+	mutex_lock(&sas_host->lock);
 	list_for_each_entry(rphy, &sas_host->rphy_list, list) {
 		struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
-		if (parent->number == channel &&
-		    rphy->scsi_target_id == id)
-			dev = &rphy->dev;
-	}
-	spin_unlock(&sas_host->lock);
 
-	return dev;
+		if (rphy->scsi_target_id == -1)
+			continue;
+
+		if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
+		    (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
+			scsi_scan_target(&rphy->dev, parent->port_identifier,
+					 rphy->scsi_target_id, lun, 1);
+		}
+	}
+	mutex_unlock(&sas_host->lock);
+
+	return 0;
 }
 
 
@@ -780,7 +798,7 @@
 		return NULL;
 	memset(i, 0, sizeof(struct sas_internal));
 
-	i->t.target_parent = sas_target_parent;
+	i->t.user_scan = sas_user_scan;
 
 	i->t.host_attrs.ac.attrs = &i->host_attrs[0];
 	i->t.host_attrs.ac.class = &sas_host_class.class;
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 46da6fe..7ee95eb 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/workqueue.h>
 #include <linux/blkdev.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 #include <scsi/scsi.h>
 #include "scsi_priv.h"
 #include <scsi/scsi_device.h>
@@ -48,7 +48,7 @@
 
 /* Private data accessors (keep these out of the header file) */
 #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
-#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem)
+#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
 
 struct spi_internal {
 	struct scsi_transport_template t;
@@ -242,7 +242,7 @@
 	spi_hold_mcs(starget) = 0;
 	spi_dv_pending(starget) = 0;
 	spi_initial_dv(starget) = 0;
-	init_MUTEX(&spi_dv_sem(starget));
+	mutex_init(&spi_dv_mutex(starget));
 
 	return 0;
 }
@@ -915,7 +915,7 @@
 	scsi_target_quiesce(starget);
 
 	spi_dv_pending(starget) = 1;
-	down(&spi_dv_sem(starget));
+	mutex_lock(&spi_dv_mutex(starget));
 
 	starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");
 
@@ -923,7 +923,7 @@
 
 	starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");
 
-	up(&spi_dv_sem(starget));
+	mutex_unlock(&spi_dv_mutex(starget));
 	spi_dv_pending(starget) = 0;
 
 	scsi_target_resume(starget);
@@ -1075,7 +1075,7 @@
 /* 0x04 */ "Parallel Protocol Request"
 };
 
-void print_nego(const unsigned char *msg, int per, int off, int width)
+static void print_nego(const unsigned char *msg, int per, int off, int width)
 {
 	if (per) {
 		char buf[20];
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 4c5127e..930db39 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -49,6 +49,7 @@
 #include <linux/blkpg.h>
 #include <linux/kref.h>
 #include <linux/delay.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 #include <scsi/scsi.h>
@@ -111,7 +112,7 @@
 /* This semaphore is used to mediate the 0->1 reference get in the
  * face of object destruction (i.e. we can't allow a get on an
  * object after last put) */
-static DECLARE_MUTEX(sd_ref_sem);
+static DEFINE_MUTEX(sd_ref_mutex);
 
 static int sd_revalidate_disk(struct gendisk *disk);
 static void sd_rw_intr(struct scsi_cmnd * SCpnt);
@@ -193,9 +194,9 @@
 {
 	struct scsi_disk *sdkp;
 
-	down(&sd_ref_sem);
+	mutex_lock(&sd_ref_mutex);
 	sdkp = __scsi_disk_get(disk);
-	up(&sd_ref_sem);
+	mutex_unlock(&sd_ref_mutex);
 	return sdkp;
 }
 
@@ -203,11 +204,11 @@
 {
 	struct scsi_disk *sdkp;
 
-	down(&sd_ref_sem);
+	mutex_lock(&sd_ref_mutex);
 	sdkp = dev_get_drvdata(dev);
 	if (sdkp)
 		sdkp = __scsi_disk_get(sdkp->disk);
-	up(&sd_ref_sem);
+	mutex_unlock(&sd_ref_mutex);
 	return sdkp;
 }
 
@@ -215,10 +216,10 @@
 {
 	struct scsi_device *sdev = sdkp->device;
 
-	down(&sd_ref_sem);
+	mutex_lock(&sd_ref_mutex);
 	kref_put(&sdkp->kref, scsi_disk_release);
 	scsi_device_put(sdev);
-	up(&sd_ref_sem);
+	mutex_unlock(&sd_ref_mutex);
 }
 
 /**
@@ -231,34 +232,12 @@
  **/
 static int sd_init_command(struct scsi_cmnd * SCpnt)
 {
-	unsigned int this_count, timeout;
-	struct gendisk *disk;
-	sector_t block;
 	struct scsi_device *sdp = SCpnt->device;
 	struct request *rq = SCpnt->request;
-
-	timeout = sdp->timeout;
-
-	/*
-	 * SG_IO from block layer already setup, just copy cdb basically
-	 */
-	if (blk_pc_request(rq)) {
-		scsi_setup_blk_pc_cmnd(SCpnt);
-		if (rq->timeout)
-			timeout = rq->timeout;
-
-		goto queue;
-	}
-
-	/*
-	 * we only do REQ_CMD and REQ_BLOCK_PC
-	 */
-	if (!blk_fs_request(rq))
-		return 0;
-
-	disk = rq->rq_disk;
-	block = rq->sector;
-	this_count = SCpnt->request_bufflen >> 9;
+	struct gendisk *disk = rq->rq_disk;
+	sector_t block = rq->sector;
+	unsigned int this_count = SCpnt->request_bufflen >> 9;
+	unsigned int timeout = sdp->timeout;
 
 	SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
 			    "count=%d\n", disk->disk_name,
@@ -401,8 +380,6 @@
 	SCpnt->transfersize = sdp->sector_size;
 	SCpnt->underflow = this_count << 9;
 	SCpnt->allowed = SD_MAX_RETRIES;
-
-queue:
 	SCpnt->timeout_per_command = timeout;
 
 	/*
@@ -836,15 +813,7 @@
 	   relatively rare error condition, no care is taken to avoid
 	   unnecessary additional work such as memcpy's that could be avoided.
 	 */
-
-	/* 
-	 * If SG_IO from block layer then set good_bytes to stop retries;
-	 * else if errors, check them, and if necessary prepare for
-	 * (partial) retries.
-	 */
-	if (blk_pc_request(SCpnt->request))
-		good_bytes = this_count;
-	else if (driver_byte(result) != 0 &&
+	if (driver_byte(result) != 0 &&
 		 sense_valid && !sense_deferred) {
 		switch (sshdr.sense_key) {
 		case MEDIUM_ERROR:
@@ -1635,10 +1604,10 @@
 	del_gendisk(sdkp->disk);
 	sd_shutdown(dev);
 
-	down(&sd_ref_sem);
+	mutex_lock(&sd_ref_mutex);
 	dev_set_drvdata(dev, NULL);
 	kref_put(&sdkp->kref, scsi_disk_release);
-	up(&sd_ref_sem);
+	mutex_unlock(&sd_ref_mutex);
 
 	return 0;
 }
@@ -1647,7 +1616,7 @@
  *	scsi_disk_release - Called to free the scsi_disk structure
  *	@kref: pointer to embedded kref
  *
- *	sd_ref_sem must be held entering this routine.  Because it is
+ *	sd_ref_mutex must be held entering this routine.  Because it is
  *	called on last put, you should always use the scsi_disk_get()
  *	scsi_disk_put() helpers which manipulate the semaphore directly
  *	and never do a direct kref_put().
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index a4d9be7..dd80503 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -44,6 +44,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 #include <scsi/scsi.h>
@@ -90,7 +91,7 @@
 /* This semaphore is used to mediate the 0->1 reference get in the
  * face of object destruction (i.e. we can't allow a get on an
  * object after last put) */
-static DECLARE_MUTEX(sr_ref_sem);
+static DEFINE_MUTEX(sr_ref_mutex);
 
 static int sr_open(struct cdrom_device_info *, int);
 static void sr_release(struct cdrom_device_info *);
@@ -133,7 +134,7 @@
 {
 	struct scsi_cd *cd = NULL;
 
-	down(&sr_ref_sem);
+	mutex_lock(&sr_ref_mutex);
 	if (disk->private_data == NULL)
 		goto out;
 	cd = scsi_cd(disk);
@@ -146,7 +147,7 @@
 	kref_put(&cd->kref, sr_kref_release);
 	cd = NULL;
  out:
-	up(&sr_ref_sem);
+	mutex_unlock(&sr_ref_mutex);
 	return cd;
 }
 
@@ -154,10 +155,10 @@
 {
 	struct scsi_device *sdev = cd->device;
 
-	down(&sr_ref_sem);
+	mutex_lock(&sr_ref_mutex);
 	kref_put(&cd->kref, sr_kref_release);
 	scsi_device_put(sdev);
-	up(&sr_ref_sem);
+	mutex_unlock(&sr_ref_mutex);
 }
 
 /*
@@ -237,8 +238,6 @@
 		case ILLEGAL_REQUEST:
 			if (!(SCpnt->sense_buffer[0] & 0x90))
 				break;
-			if (!blk_fs_request(SCpnt->request))
-				break;
 			error_sector = (SCpnt->sense_buffer[3] << 24) |
 				(SCpnt->sense_buffer[4] << 16) |
 				(SCpnt->sense_buffer[5] << 8) |
@@ -317,23 +316,6 @@
 	}
 
 	/*
-	 * these are already setup, just copy cdb basically
-	 */
-	if (SCpnt->request->flags & REQ_BLOCK_PC) {
-		scsi_setup_blk_pc_cmnd(SCpnt);
-
-		if (SCpnt->timeout_per_command)
-			timeout = SCpnt->timeout_per_command;
-
-		goto queue;
-	}
-
-	if (!(SCpnt->request->flags & REQ_CMD)) {
-		blk_dump_rq_flags(SCpnt->request, "sr unsup command");
-		return 0;
-	}
-
-	/*
 	 * we do lazy blocksize switching (when reading XA sectors,
 	 * see CDROMREADMODE2 ioctl) 
 	 */
@@ -421,8 +403,6 @@
 	 */
 	SCpnt->transfersize = cd->device->sector_size;
 	SCpnt->underflow = this_count << 9;
-
-queue:
 	SCpnt->allowed = MAX_RETRIES;
 	SCpnt->timeout_per_command = timeout;
 
@@ -762,8 +742,9 @@
 		/* failed, drive doesn't have capabilities mode page */
 		cd->cdi.speed = 1;
 		cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
-					 CDC_DVD | CDC_DVD_RAM |
-					 CDC_SELECT_DISC | CDC_SELECT_SPEED);
+				 CDC_DVD | CDC_DVD_RAM |
+				 CDC_SELECT_DISC | CDC_SELECT_SPEED |
+				 CDC_MRW | CDC_MRW_W | CDC_RAM);
 		kfree(buffer);
 		printk("%s: scsi-1 drive\n", cd->cdi.name);
 		return;
@@ -845,7 +826,7 @@
  *	sr_kref_release - Called to free the scsi_cd structure
  *	@kref: pointer to embedded kref
  *
- *	sr_ref_sem must be held entering this routine.  Because it is
+ *	sr_ref_mutex must be held entering this routine.  Because it is
  *	called on last put, you should always use the scsi_cd_get()
  *	scsi_cd_put() helpers which manipulate the semaphore directly
  *	and never do a direct kref_put().
@@ -874,9 +855,9 @@
 
 	del_gendisk(cd->disk);
 
-	down(&sr_ref_sem);
+	mutex_lock(&sr_ref_mutex);
 	kref_put(&cd->kref, sr_kref_release);
-	up(&sr_ref_sem);
+	mutex_unlock(&sr_ref_mutex);
 
 	return 0;
 }
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 6e45ac3..5d02ff4 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -31,6 +31,79 @@
 
 module_param(xa_test, int, S_IRUGO | S_IWUSR);
 
+/* primitive to determine whether we need to have GFP_DMA set based on
+ * the status of the unchecked_isa_dma flag in the host structure */
+#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
+
+
+static int sr_read_tochdr(struct cdrom_device_info *cdi,
+		struct cdrom_tochdr *tochdr)
+{
+	struct scsi_cd *cd = cdi->handle;
+	struct packet_command cgc;
+	int result;
+	unsigned char *buffer;
+
+	buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+	if (!buffer)
+		return -ENOMEM;
+
+	memset(&cgc, 0, sizeof(struct packet_command));
+	cgc.timeout = IOCTL_TIMEOUT;
+	cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+	cgc.cmd[8] = 12;		/* LSB of length */
+	cgc.buffer = buffer;
+	cgc.buflen = 12;
+	cgc.quiet = 1;
+	cgc.data_direction = DMA_FROM_DEVICE;
+
+	result = sr_do_ioctl(cd, &cgc);
+
+	tochdr->cdth_trk0 = buffer[2];
+	tochdr->cdth_trk1 = buffer[3];
+
+	kfree(buffer);
+	return result;
+}
+
+static int sr_read_tocentry(struct cdrom_device_info *cdi,
+		struct cdrom_tocentry *tocentry)
+{
+	struct scsi_cd *cd = cdi->handle;
+	struct packet_command cgc;
+	int result;
+	unsigned char *buffer;
+
+	buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+	if (!buffer)
+		return -ENOMEM;
+
+	memset(&cgc, 0, sizeof(struct packet_command));
+	cgc.timeout = IOCTL_TIMEOUT;
+	cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+	cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
+	cgc.cmd[6] = tocentry->cdte_track;
+	cgc.cmd[8] = 12;		/* LSB of length */
+	cgc.buffer = buffer;
+	cgc.buflen = 12;
+	cgc.data_direction = DMA_FROM_DEVICE;
+
+	result = sr_do_ioctl(cd, &cgc);
+
+	tocentry->cdte_ctrl = buffer[5] & 0xf;
+	tocentry->cdte_adr = buffer[5] >> 4;
+	tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
+	if (tocentry->cdte_format == CDROM_MSF) {
+		tocentry->cdte_addr.msf.minute = buffer[9];
+		tocentry->cdte_addr.msf.second = buffer[10];
+		tocentry->cdte_addr.msf.frame = buffer[11];
+	} else
+		tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
+			+ buffer[10]) << 8) + buffer[11];
+
+	kfree(buffer);
+	return result;
+}
 
 #define IOCTL_RETRIES 3
 
@@ -45,7 +118,8 @@
 	struct packet_command cgc;
 	int ntracks, ret;
 
-	if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr)))
+	ret = sr_read_tochdr(cdi, &tochdr);
+	if (ret)
 		return ret;
 
 	ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
@@ -60,9 +134,11 @@
 	trk1_te.cdte_track = ti->cdti_trk1;
 	trk1_te.cdte_format = CDROM_MSF;
 	
-	if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te)))
+	ret = sr_read_tocentry(cdi, &trk0_te);
+	if (ret)
 		return ret;
-	if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te)))
+	ret = sr_read_tocentry(cdi, &trk1_te);
+	if (ret)
 		return ret;
 
 	memset(&cgc, 0, sizeof(struct packet_command));
@@ -78,6 +154,30 @@
 	return sr_do_ioctl(cdi->handle, &cgc);
 }
 
+static int sr_play_trkind(struct cdrom_device_info *cdi,
+		struct cdrom_ti *ti)
+
+{
+	struct scsi_cd *cd = cdi->handle;
+	struct packet_command cgc;
+	int result;
+
+	memset(&cgc, 0, sizeof(struct packet_command));
+	cgc.timeout = IOCTL_TIMEOUT;
+	cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
+	cgc.cmd[4] = ti->cdti_trk0;
+	cgc.cmd[5] = ti->cdti_ind0;
+	cgc.cmd[7] = ti->cdti_trk1;
+	cgc.cmd[8] = ti->cdti_ind1;
+	cgc.data_direction = DMA_NONE;
+
+	result = sr_do_ioctl(cd, &cgc);
+	if (result == -EDRIVE_CANT_DO_THIS)
+		result = sr_fake_playtrkind(cdi, ti);
+
+	return result;
+}
+
 /* We do our own retries because we want to know what the specific
    error code is.  Normally the UNIT_ATTENTION code will automatically
    clear after one error */
@@ -229,13 +329,14 @@
 	int i, rc, have_datatracks = 0;
 
 	/* look for data tracks */
-	if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h)))
+	rc = sr_read_tochdr(cdi, &toc_h);
+	if (rc)
 		return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
 
 	for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
 		toc_e.cdte_track = i;
 		toc_e.cdte_format = CDROM_LBA;
-		if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e))
+		if (sr_read_tocentry(cdi, &toc_e))
 			return CDS_NO_INFO;
 		if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {
 			have_datatracks = 1;
@@ -262,10 +363,6 @@
 	return 0;
 }
 
-/* primitive to determine whether we need to have GFP_DMA set based on
- * the status of the unchecked_isa_dma flag in the host structure */
-#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
-
 int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 {
 	Scsi_CD *cd = cdi->handle;
@@ -329,93 +426,16 @@
 
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 {
-	Scsi_CD *cd = cdi->handle;
-	struct packet_command cgc;
-	int result;
-	unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
-
-	if (!buffer)
-		return -ENOMEM;
-
-	memset(&cgc, 0, sizeof(struct packet_command));
-	cgc.timeout = IOCTL_TIMEOUT;
-
 	switch (cmd) {
 	case CDROMREADTOCHDR:
-		{
-			struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
-
-			cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-			cgc.cmd[8] = 12;		/* LSB of length */
-			cgc.buffer = buffer;
-			cgc.buflen = 12;
-			cgc.quiet = 1;
-			cgc.data_direction = DMA_FROM_DEVICE;
-
-			result = sr_do_ioctl(cd, &cgc);
-
-			tochdr->cdth_trk0 = buffer[2];
-			tochdr->cdth_trk1 = buffer[3];
-
-			break;
-		}
-
+		return sr_read_tochdr(cdi, arg);
 	case CDROMREADTOCENTRY:
-		{
-			struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
-
-			cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-			cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
-			cgc.cmd[6] = tocentry->cdte_track;
-			cgc.cmd[8] = 12;		/* LSB of length */
-			cgc.buffer = buffer;
-			cgc.buflen = 12;
-			cgc.data_direction = DMA_FROM_DEVICE;
-
-			result = sr_do_ioctl(cd, &cgc);
-
-			tocentry->cdte_ctrl = buffer[5] & 0xf;
-			tocentry->cdte_adr = buffer[5] >> 4;
-			tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
-			if (tocentry->cdte_format == CDROM_MSF) {
-				tocentry->cdte_addr.msf.minute = buffer[9];
-				tocentry->cdte_addr.msf.second = buffer[10];
-				tocentry->cdte_addr.msf.frame = buffer[11];
-			} else
-				tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
-					+ buffer[10]) << 8) + buffer[11];
-
-			break;
-		}
-
-	case CDROMPLAYTRKIND: {
-		struct cdrom_ti* ti = (struct cdrom_ti*)arg;
-
-		cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
-		cgc.cmd[4] = ti->cdti_trk0;
-		cgc.cmd[5] = ti->cdti_ind0;
-		cgc.cmd[7] = ti->cdti_trk1;
-		cgc.cmd[8] = ti->cdti_ind1;
-		cgc.data_direction = DMA_NONE;
-
-		result = sr_do_ioctl(cd, &cgc);
-		if (result == -EDRIVE_CANT_DO_THIS)
-			result = sr_fake_playtrkind(cdi, ti);
-
-		break;
-	}
-
+		return sr_read_tocentry(cdi, arg);
+	case CDROMPLAYTRKIND:
+		return sr_play_trkind(cdi, arg);
 	default:
-		result = -EINVAL;
+		return -EINVAL;
 	}
-
-#if 0
-	if (result)
-		printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);
-#endif
-
-	kfree(buffer);
-	return result;
 }
 
 /* -----------------------------------------------------------------------
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c4aade8..13b1d3a 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -38,6 +38,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/cdev.h>
 #include <linux/delay.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 #include <asm/dma.h>
@@ -193,7 +194,6 @@
 
 static int st_probe(struct device *);
 static int st_remove(struct device *);
-static int st_init_command(struct scsi_cmnd *);
 
 static void do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
@@ -206,7 +206,6 @@
 		.probe		= st_probe,
 		.remove		= st_remove,
 	},
-	.init_command		= st_init_command,
 };
 
 static int st_compression(struct scsi_tape *, int);
@@ -220,7 +219,7 @@
 
 #define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
 
-static DECLARE_MUTEX(st_ref_sem);
+static DEFINE_MUTEX(st_ref_mutex);
 
 
 #include "osst_detect.h"
@@ -237,7 +236,7 @@
 {
 	struct scsi_tape *STp = NULL;
 
-	down(&st_ref_sem);
+	mutex_lock(&st_ref_mutex);
 	write_lock(&st_dev_arr_lock);
 
 	if (dev < st_dev_max && scsi_tapes != NULL)
@@ -259,7 +258,7 @@
 	STp = NULL;
 out:
 	write_unlock(&st_dev_arr_lock);
-	up(&st_ref_sem);
+	mutex_unlock(&st_ref_mutex);
 	return STp;
 }
 
@@ -267,10 +266,10 @@
 {
 	struct scsi_device *sdev = STp->device;
 
-	down(&st_ref_sem);
+	mutex_lock(&st_ref_mutex);
 	kref_put(&STp->kref, scsi_tape_release);
 	scsi_device_put(sdev);
-	up(&st_ref_sem);
+	mutex_unlock(&st_ref_mutex);
 }
 
 struct st_reject_data {
@@ -4141,9 +4140,9 @@
 				}
 			}
 
-			down(&st_ref_sem);
+			mutex_lock(&st_ref_mutex);
 			kref_put(&tpnt->kref, scsi_tape_release);
-			up(&st_ref_sem);
+			mutex_unlock(&st_ref_mutex);
 			return 0;
 		}
 	}
@@ -4156,7 +4155,7 @@
  *      scsi_tape_release - Called to free the Scsi_Tape structure
  *      @kref: pointer to embedded kref
  *
- *      st_ref_sem must be held entering this routine.  Because it is
+ *      st_ref_mutex must be held entering this routine.  Because it is
  *      called on last put, you should always use the scsi_tape_get()
  *      scsi_tape_put() helpers which manipulate the semaphore directly
  *      and never do a direct kref_put().
@@ -4180,29 +4179,6 @@
 	return;
 }
 
-static void st_intr(struct scsi_cmnd *SCpnt)
-{
-	/*
-	 * The caller should be checking the request's errors
-	 * value.
-	 */
-	scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
-}
-
-/*
- * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)
- * interface for REQ_BLOCK_PC commands.
- */
-static int st_init_command(struct scsi_cmnd *SCpnt)
-{
-	if (!(SCpnt->request->flags & REQ_BLOCK_PC))
-		return 0;
-
-	scsi_setup_blk_pc_cmnd(SCpnt);
-	SCpnt->done = st_intr;
-	return 1;
-}
-
 static int __init init_st(void)
 {
 	validate_options();
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 7fb397e..5403257 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -181,6 +181,7 @@
 #define PCI_DEVICE_ID_LSI_FC929X	0x0626
 #define PCI_DEVICE_ID_LSI_FC939X	0x0642
 #define PCI_DEVICE_ID_LSI_FC949X	0x0640
+#define PCI_DEVICE_ID_LSI_FC949ES	0x0646
 #define PCI_DEVICE_ID_LSI_FC919X	0x0628
 #define PCI_DEVICE_ID_NCR_YELLOWFIN	0x0701
 #define PCI_DEVICE_ID_LSI_61C102	0x0901
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
index 48831ea..d0dd38b 100644
--- a/include/linux/raid_class.h
+++ b/include/linux/raid_class.h
@@ -31,9 +31,11 @@
 	RAID_LEVEL_LINEAR,
 	RAID_LEVEL_0,
 	RAID_LEVEL_1,
+	RAID_LEVEL_10,
 	RAID_LEVEL_3,
 	RAID_LEVEL_4,
 	RAID_LEVEL_5,
+	RAID_LEVEL_50,
 	RAID_LEVEL_6,
 };
 
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index be1bc79..3e5cb5a 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -168,6 +168,12 @@
 
 #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
 #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+
+/**
+ * iscsi_hostdata - get LLD hostdata from scsi_host
+ * @_hostdata: pointer to scsi host's hostdata
+ **/
 #define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long))
 
 /*
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 6cb1e27..c60b8ff 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -32,6 +32,12 @@
 extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
 
 /*
+ * Special value for scanning to specify scanning or rescanning of all
+ * possible channels, (target) ids, or luns on a given shost.
+ */
+#define SCAN_WILD_CARD	~0
+
+/*
  *      SCSI opcodes
  */
 
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 41cfc29..7529f43 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -151,6 +151,5 @@
 extern void scsi_put_command(struct scsi_cmnd *);
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
-extern void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd);
 
 #endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 230bc55..467274a 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <linux/mutex.h>
 
 struct block_device;
 struct completion;
@@ -469,7 +470,7 @@
 	spinlock_t		default_lock;
 	spinlock_t		*host_lock;
 
-	struct semaphore	scan_mutex;/* serialize scanning activity */
+	struct mutex		scan_mutex;/* serialize scanning activity */
 
 	struct list_head	eh_cmd_q;
 	struct task_struct    * ehandler;  /* Error recovery thread. */
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index f6e0bb4..e7b1054 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -30,12 +30,9 @@
 	struct transport_container device_attrs;
 
 	/*
-	 * If set, call target_parent prior to allocating a scsi_target,
-	 * so we get the appropriate parent for the target. This function
-	 * is required for transports like FC and iSCSI that do not put the
-	 * scsi_target under scsi_host.
+	 * If set, called from sysfs and legacy procfs rescanning code.
 	 */
-	struct device *(*target_parent)(struct Scsi_Host *, int, uint);
+	int (*user_scan)(struct Scsi_Host *, uint, uint, uint);
 
 	/* The size of the specific transport attribute structure (a
 	 * space of this size will be left at the end of the
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 394f14a..cf3fec8 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -303,6 +303,7 @@
 	/* Fixed Attributes */
 	u64 node_name;
 	u64 port_name;
+	u64 permanent_port_name;
 	u32 supported_classes;
 	u8  supported_fc4s[FC_FC4_LIST_SIZE];
 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
@@ -338,6 +339,8 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->node_name)
 #define fc_host_port_name(x)	\
 	(((struct fc_host_attrs *)(x)->shost_data)->port_name)
+#define fc_host_permanent_port_name(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name)
 #define fc_host_supported_classes(x)	\
 	(((struct fc_host_attrs *)(x)->shost_data)->supported_classes)
 #define fc_host_supported_fc4s(x)	\
@@ -426,6 +429,7 @@
 	/* host fixed attributes */
 	unsigned long	show_host_node_name:1;
 	unsigned long	show_host_port_name:1;
+	unsigned long	show_host_permanent_port_name:1;
 	unsigned long	show_host_supported_classes:1;
 	unsigned long	show_host_supported_fc4s:1;
 	unsigned long	show_host_symbolic_name:1;
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index f25041c..16602a5 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -23,8 +23,14 @@
 #ifndef SCSI_TRANSPORT_ISCSI_H
 #define SCSI_TRANSPORT_ISCSI_H
 
+#include <linux/device.h>
 #include <scsi/iscsi_if.h>
 
+struct scsi_transport_template;
+struct Scsi_Host;
+struct mempool_zone;
+struct iscsi_cls_conn;
+
 /**
  * struct iscsi_transport - iSCSI Transport template
  *
@@ -48,23 +54,31 @@
 	char *name;
 	unsigned int caps;
 	struct scsi_host_template *host_template;
+	/* LLD session/scsi_host data size */
 	int hostdata_size;
+	/* LLD iscsi_host data size */
+	int ihostdata_size;
+	/* LLD connection data size */
+	int conndata_size;
 	int max_lun;
 	unsigned int max_conn;
 	unsigned int max_cmd_len;
-	iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn,
-					    struct Scsi_Host *shost);
-	void (*destroy_session) (iscsi_sessionh_t session);
-	iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid);
+	struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,
+					     uint32_t initial_cmdsn);
+	void (*destroy_session) (struct Scsi_Host *shost);
+	struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,
+				uint32_t cid);
 	int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
 			  uint32_t transport_fd, int is_leading);
 	int (*start_conn) (iscsi_connh_t conn);
 	void (*stop_conn) (iscsi_connh_t conn, int flag);
-	void (*destroy_conn) (iscsi_connh_t conn);
+	void (*destroy_conn) (struct iscsi_cls_conn *conn);
 	int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
 			  uint32_t value);
-	int (*get_param) (iscsi_connh_t conn, enum iscsi_param param,
-			  uint32_t *value);
+	int (*get_conn_param) (void *conndata, enum iscsi_param param,
+			       uint32_t *value);
+	int (*get_session_param) (struct Scsi_Host *shost,
+				  enum iscsi_param param, uint32_t *value);
 	int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
 			 char *data, uint32_t data_size);
 	void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
@@ -73,7 +87,7 @@
 /*
  * transport registration upcalls
  */
-extern int iscsi_register_transport(struct iscsi_transport *tt);
+extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt);
 extern int iscsi_unregister_transport(struct iscsi_transport *tt);
 
 /*
@@ -83,4 +97,49 @@
 extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,
 			  char *data, uint32_t data_size);
 
+struct iscsi_cls_conn {
+	struct list_head conn_list;	/* item in connlist */
+	void *dd_data;			/* LLD private data */
+	struct iscsi_transport *transport;
+	iscsi_connh_t connh;
+	int active;			/* must be accessed with the connlock */
+	struct device dev;		/* sysfs transport/container device */
+	struct mempool_zone *z_error;
+	struct mempool_zone *z_pdu;
+	struct list_head freequeue;
+};
+
+#define iscsi_dev_to_conn(_dev) \
+	container_of(_dev, struct iscsi_cls_conn, dev)
+
+struct iscsi_cls_session {
+	struct list_head list;	/* item in session_list */
+	struct iscsi_transport *transport;
+	struct device dev;	/* sysfs transport/container device */
+};
+
+#define iscsi_dev_to_session(_dev) \
+	container_of(_dev, struct iscsi_cls_session, dev)
+
+#define iscsi_session_to_shost(_session) \
+	dev_to_shost(_session->dev.parent)
+
+/*
+ * session and connection functions that can be used by HW iSCSI LLDs
+ */
+extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+				struct iscsi_transport *t);
+extern int iscsi_destroy_session(struct iscsi_cls_session *session);
+extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+					    uint32_t cid);
+extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+
+/*
+ * session functions used by software iscsi
+ */
+extern struct Scsi_Host *
+iscsi_transport_create_session(struct scsi_transport_template *scsit,
+                               struct iscsi_transport *transport);
+extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);
+
 #endif
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 54a8961..2b5930b 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -54,7 +54,7 @@
 	unsigned int support_qas; /* supports quick arbitration and selection */
 	/* Private Fields */
 	unsigned int dv_pending:1; /* Internal flag */
-	struct semaphore dv_sem; /* semaphore to serialise dv */
+	struct mutex dv_mutex; /* semaphore to serialise dv */
 };
 
 enum spi_signal_type {