Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Feb 2011 13:35:42 -0700
From:      "Kenneth D. Merry" <ken@freebsd.org>
To:        Dmitry Morozovsky <marck@rinet.ru>
Cc:        freebsd-stable@freebsd.org, Daniel Kalchev <daniel@digsys.bg>
Subject:   Re: LSI SAS 2008 (mfi) on SuperMicro X8SI6-F
Message-ID:  <20110216203542.GA41226@nargothrond.kdm.org>
In-Reply-To: <alpine.BSF.2.00.1102162201090.93747@woozle.rinet.ru>
References:  <alpine.BSF.2.00.1102161842240.93747@woozle.rinet.ru> <4D5BF78E.7010306@digsys.bg> <alpine.BSF.2.00.1102161920240.93747@woozle.rinet.ru> <20110216172643.GA37858@nargothrond.kdm.org> <alpine.BSF.2.00.1102162201090.93747@woozle.rinet.ru>

next in thread | previous in thread | raw e-mail | index | archive | help

--qMm9M+Fa2AknHoGS
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Feb 16, 2011 at 22:07:11 +0300, Dmitry Morozovsky wrote:
> On Wed, 16 Feb 2011, Kenneth D. Merry wrote:
> 
> KDM> > Ah that makes sense. I'm a bit reluctant to use -current on this particular 
> KDM> > machine, so I would discuss MFCing mps driver wirh ken@
> KDM> 
> KDM> I have attached a patch against -stable, try it out and let me know whether
> KDM> it works.  If so I'll go ahead and MFC it.
> 
> I'm afraid something goes wrong at your side, at least in some files in 
> sys/dev/mps, like
> 
> Index: sys/dev/mps/mps_ioctl.h
> ===================================================================
> --- sys/dev/mps/mps_ioctl.h     (revision 212420)
> +++ sys/dev/mps/mps_ioctl.h     (working copy)
> 
> as there is no sys/dev/mps in stable/8 kernel sources

Whoops, svn diff doesn't do the right thing when there are multiple changes
merged.

I re-did the diffs manually, you should be able to do something like:

cd src
cat patch |patch -p4

Ken
-- 
Kenneth Merry
ken@FreeBSD.ORG

--qMm9M+Fa2AknHoGS
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="mps_stable.20110216.3.txt"

diff -x .svn -urN sys/amd64/conf/GENERIC ../../stable/8/sys/amd64/conf/GENERIC
--- sys/amd64/conf/GENERIC	2011-01-07 15:03:42.295368047 -0700
+++ ../../stable/8/sys/amd64/conf/GENERIC	2011-01-07 14:33:13.012014226 -0700
@@ -114,6 +114,7 @@
 device		isp		# Qlogic family
 #device		ispfw		# Firmware for QLogic HBAs- normally a module
 device		mpt		# LSI-Logic MPT-Fusion
+device		mps		# LSI-Logic MPT-Fusion 2
 #device		ncr		# NCR/Symbios Logic
 device		sym		# NCR/Symbios Logic (newer chipsets + those of `ncr')
 device		trm		# Tekram DC395U/UW/F DC315U adapters
diff -x .svn -urN sys/conf/files ../../stable/8/sys/conf/files
--- sys/conf/files	2011-02-16 10:02:31.958763733 -0700
+++ ../../stable/8/sys/conf/files	2011-02-16 10:08:39.323115505 -0700
@@ -1303,6 +1303,11 @@
 dev/mmc/mmcbus_if.m		standard
 dev/mmc/mmcsd.c			optional mmcsd
 dev/mn/if_mn.c			optional mn pci
+dev/mps/mps.c			optional mps
+dev/mps/mps_pci.c		optional mps pci
+dev/mps/mps_sas.c		optional mps
+dev/mps/mps_table.c		optional mps
+dev/mps/mps_user.c		optional mps
 dev/mpt/mpt.c			optional mpt
 dev/mpt/mpt_cam.c		optional mpt
 dev/mpt/mpt_debug.c		optional mpt
diff -x .svn -urN sys/dev/bwn/if_bwn.c ../../stable/8/sys/dev/bwn/if_bwn.c
--- sys/dev/bwn/if_bwn.c	2011-02-16 10:02:35.844775993 -0700
+++ ../../stable/8/sys/dev/bwn/if_bwn.c	2011-02-16 10:08:44.335701618 -0700
@@ -2882,7 +2882,7 @@
 
 	error = bwn_switch_band(sc, ic->ic_curchan);
 	if (error)
-		goto fail;;
+		goto fail;
 	bwn_mac_suspend(mac);
 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
@@ -8260,7 +8260,7 @@
 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
 
-	down_dev = sc->sc_curmac;;
+	down_dev = sc->sc_curmac;
 	status = down_dev->mac_status;
 	if (status >= BWN_MAC_STATUS_STARTED)
 		bwn_core_stop(down_dev);
diff -x .svn -urN sys/dev/mps/mpi/mpi2.h ../../stable/8/sys/dev/mps/mpi/mpi2.h
--- sys/dev/mps/mpi/mpi2.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2.h	2011-01-07 14:33:12.703724259 -0700
@@ -0,0 +1,1121 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2.h
+ *          Title:  MPI Message independent structures and definitions
+ *                  including System Interface Register Set and
+ *                  scatter/gather formats.
+ *  Creation Date:  June 21, 2006
+ *
+ *  mpi2.h Version:  02.00.14
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  06-26-07  02.00.02  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  08-31-07  02.00.03  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Moved ReplyPostHostIndex register to offset 0x6C of the
+ *                      MPI2_SYSTEM_INTERFACE_REGS and modified the define for
+ *                      MPI2_REPLY_POST_HOST_INDEX_OFFSET.
+ *                      Added union of request descriptors.
+ *                      Added union of reply descriptors.
+ *  10-31-07  02.00.04  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added define for MPI2_VERSION_02_00.
+ *                      Fixed the size of the FunctionDependent5 field in the
+ *                      MPI2_DEFAULT_REPLY structure.
+ *  12-18-07  02.00.05  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Removed the MPI-defined Fault Codes and extended the
+ *                      product specific codes up to 0xEFFF.
+ *                      Added a sixth key value for the WriteSequence register
+ *                      and changed the flush value to 0x0.
+ *                      Added message function codes for Diagnostic Buffer Post
+ *                      and Diagnsotic Release.
+ *                      New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
+ *                      Moved MPI2_VERSION_UNION from mpi2_ioc.h.
+ *  02-29-08  02.00.06  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  03-03-08  02.00.07  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-21-08  02.00.08  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added #defines for marking a reply descriptor as unused.
+ *  06-27-08  02.00.09  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Moved LUN field defines from mpi2_init.h.
+ *  01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      In all request and reply descriptors, replaced VF_ID
+ *                      field with MSIxIndex field.
+ *                      Removed DevHandle field from
+ *                      MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
+ *                      bytes reserved.
+ *                      Added RAID Accelerator functionality.
+ *  07-30-09  02.00.13  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  10-28-09  02.00.14  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added MSI-x index mask and shift for Reply Post Host
+ *                      Index register.
+ *                      Added function code for Host Based Discovery Action.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_H
+#define MPI2_H
+
+
+/*****************************************************************************
+*
+*        MPI Version Definitions
+*
+*****************************************************************************/
+
+#define MPI2_VERSION_MAJOR                  (0x02)
+#define MPI2_VERSION_MINOR                  (0x00)
+#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT            (8)
+#define MPI2_VERSION_MINOR_MASK             (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT            (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) |   \
+                                      MPI2_VERSION_MINOR)
+
+#define MPI2_VERSION_02_00                  (0x0200)
+
+/* versioning for this MPI header set */
+#define MPI2_HEADER_VERSION_UNIT            (0x0E)
+#define MPI2_HEADER_VERSION_DEV             (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
+#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
+
+
+/*****************************************************************************
+*
+*        IOC State Definitions
+*
+*****************************************************************************/
+
+#define MPI2_IOC_STATE_RESET               (0x00000000)
+#define MPI2_IOC_STATE_READY               (0x10000000)
+#define MPI2_IOC_STATE_OPERATIONAL         (0x20000000)
+#define MPI2_IOC_STATE_FAULT               (0x40000000)
+
+#define MPI2_IOC_STATE_MASK                (0xF0000000)
+#define MPI2_IOC_STATE_SHIFT               (28)
+
+/* Fault state range for prodcut specific codes */
+#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN                 (0x0000)
+#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX                 (0xEFFF)
+
+
+/*****************************************************************************
+*
+*        System Interface Register Definitions
+*
+*****************************************************************************/
+
+typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
+{
+    U32         Doorbell;                   /* 0x00 */
+    U32         WriteSequence;              /* 0x04 */
+    U32         HostDiagnostic;             /* 0x08 */
+    U32         Reserved1;                  /* 0x0C */
+    U32         DiagRWData;                 /* 0x10 */
+    U32         DiagRWAddressLow;           /* 0x14 */
+    U32         DiagRWAddressHigh;          /* 0x18 */
+    U32         Reserved2[5];               /* 0x1C */
+    U32         HostInterruptStatus;        /* 0x30 */
+    U32         HostInterruptMask;          /* 0x34 */
+    U32         DCRData;                    /* 0x38 */
+    U32         DCRAddress;                 /* 0x3C */
+    U32         Reserved3[2];               /* 0x40 */
+    U32         ReplyFreeHostIndex;         /* 0x48 */
+    U32         Reserved4[8];               /* 0x4C */
+    U32         ReplyPostHostIndex;         /* 0x6C */
+    U32         Reserved5;                  /* 0x70 */
+    U32         HCBSize;                    /* 0x74 */
+    U32         HCBAddressLow;              /* 0x78 */
+    U32         HCBAddressHigh;             /* 0x7C */
+    U32         Reserved6[16];              /* 0x80 */
+    U32         RequestDescriptorPostLow;   /* 0xC0 */
+    U32         RequestDescriptorPostHigh;  /* 0xC4 */
+    U32         Reserved7[14];              /* 0xC8 */
+} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS,
+  Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t;
+
+/*
+ * Defines for working with the Doorbell register.
+ */
+#define MPI2_DOORBELL_OFFSET                    (0x00000000)
+
+/* IOC --> System values */
+#define MPI2_DOORBELL_USED                      (0x08000000)
+#define MPI2_DOORBELL_WHO_INIT_MASK             (0x07000000)
+#define MPI2_DOORBELL_WHO_INIT_SHIFT            (24)
+#define MPI2_DOORBELL_FAULT_CODE_MASK           (0x0000FFFF)
+#define MPI2_DOORBELL_DATA_MASK                 (0x0000FFFF)
+
+/* System --> IOC values */
+#define MPI2_DOORBELL_FUNCTION_MASK             (0xFF000000)
+#define MPI2_DOORBELL_FUNCTION_SHIFT            (24)
+#define MPI2_DOORBELL_ADD_DWORDS_MASK           (0x00FF0000)
+#define MPI2_DOORBELL_ADD_DWORDS_SHIFT          (16)
+
+
+/*
+ * Defines for the WriteSequence register
+ */
+#define MPI2_WRITE_SEQUENCE_OFFSET              (0x00000004)
+#define MPI2_WRSEQ_KEY_VALUE_MASK               (0x0000000F)
+#define MPI2_WRSEQ_FLUSH_KEY_VALUE              (0x0)
+#define MPI2_WRSEQ_1ST_KEY_VALUE                (0xF)
+#define MPI2_WRSEQ_2ND_KEY_VALUE                (0x4)
+#define MPI2_WRSEQ_3RD_KEY_VALUE                (0xB)
+#define MPI2_WRSEQ_4TH_KEY_VALUE                (0x2)
+#define MPI2_WRSEQ_5TH_KEY_VALUE                (0x7)
+#define MPI2_WRSEQ_6TH_KEY_VALUE                (0xD)
+
+/*
+ * Defines for the HostDiagnostic register
+ */
+#define MPI2_HOST_DIAGNOSTIC_OFFSET             (0x00000008)
+
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK       (0x00001800)
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT    (0x00000000)
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW       (0x00000800)
+
+#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG           (0x00000400)
+#define MPI2_DIAG_FORCE_HCB_ON_RESET            (0x00000200)
+#define MPI2_DIAG_HCB_MODE                      (0x00000100)
+#define MPI2_DIAG_DIAG_WRITE_ENABLE             (0x00000080)
+#define MPI2_DIAG_FLASH_BAD_SIG                 (0x00000040)
+#define MPI2_DIAG_RESET_HISTORY                 (0x00000020)
+#define MPI2_DIAG_DIAG_RW_ENABLE                (0x00000010)
+#define MPI2_DIAG_RESET_ADAPTER                 (0x00000004)
+#define MPI2_DIAG_HOLD_IOC_RESET                (0x00000002)
+
+/*
+ * Offsets for DiagRWData and address
+ */
+#define MPI2_DIAG_RW_DATA_OFFSET                (0x00000010)
+#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET         (0x00000014)
+#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET        (0x00000018)
+
+/*
+ * Defines for the HostInterruptStatus register
+ */
+#define MPI2_HOST_INTERRUPT_STATUS_OFFSET       (0x00000030)
+#define MPI2_HIS_SYS2IOC_DB_STATUS              (0x80000000)
+#define MPI2_HIS_IOP_DOORBELL_STATUS            MPI2_HIS_SYS2IOC_DB_STATUS
+#define MPI2_HIS_RESET_IRQ_STATUS               (0x40000000)
+#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT     (0x00000008)
+#define MPI2_HIS_IOC2SYS_DB_STATUS              (0x00000001)
+#define MPI2_HIS_DOORBELL_INTERRUPT             MPI2_HIS_IOC2SYS_DB_STATUS
+
+/*
+ * Defines for the HostInterruptMask register
+ */
+#define MPI2_HOST_INTERRUPT_MASK_OFFSET         (0x00000034)
+#define MPI2_HIM_RESET_IRQ_MASK                 (0x40000000)
+#define MPI2_HIM_REPLY_INT_MASK                 (0x00000008)
+#define MPI2_HIM_RIM                            MPI2_HIM_REPLY_INT_MASK
+#define MPI2_HIM_IOC2SYS_DB_MASK                (0x00000001)
+#define MPI2_HIM_DIM                            MPI2_HIM_IOC2SYS_DB_MASK
+
+/*
+ * Offsets for DCRData and address
+ */
+#define MPI2_DCR_DATA_OFFSET                    (0x00000038)
+#define MPI2_DCR_ADDRESS_OFFSET                 (0x0000003C)
+
+/*
+ * Offset for the Reply Free Queue
+ */
+#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET       (0x00000048)
+
+/*
+ * Defines for the Reply Descriptor Post Queue
+ */
+#define MPI2_REPLY_POST_HOST_INDEX_OFFSET       (0x0000006C)
+#define MPI2_REPLY_POST_HOST_INDEX_MASK         (0x00FFFFFF)
+#define MPI2_RPHI_MSIX_INDEX_MASK               (0xFF000000)
+#define MPI2_RPHI_MSIX_INDEX_SHIFT              (24)
+
+/*
+ * Defines for the HCBSize and address
+ */
+#define MPI2_HCB_SIZE_OFFSET                    (0x00000074)
+#define MPI2_HCB_SIZE_SIZE_MASK                 (0xFFFFF000)
+#define MPI2_HCB_SIZE_HCB_ENABLE                (0x00000001)
+
+#define MPI2_HCB_ADDRESS_LOW_OFFSET             (0x00000078)
+#define MPI2_HCB_ADDRESS_HIGH_OFFSET            (0x0000007C)
+
+/*
+ * Offsets for the Request Queue
+ */
+#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET     (0x000000C0)
+#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET    (0x000000C4)
+
+
+/*****************************************************************************
+*
+*        Message Descriptors
+*
+*****************************************************************************/
+
+/* Request Descriptors */
+
+/* Default Request Descriptor */
+typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
+{
+    U8              RequestFlags;               /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             LMID;                       /* 0x04 */
+    U16             DescriptorTypeDependent;    /* 0x06 */
+} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+  Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
+
+/* defines for the RequestFlags field */
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK               (0x0E)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET             (0x02)
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE            (0x08)
+#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR        (0x0A)
+
+#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
+
+
+/* High Priority Request Descriptor */
+typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
+{
+    U8              RequestFlags;               /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             LMID;                       /* 0x04 */
+    U16             Reserved1;                  /* 0x06 */
+} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+  Mpi2HighPriorityRequestDescriptor_t,
+  MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
+
+
+/* SCSI IO Request Descriptor */
+typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
+{
+    U8              RequestFlags;               /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             LMID;                       /* 0x04 */
+    U16             DevHandle;                  /* 0x06 */
+} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+  Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
+
+
+/* SCSI Target Request Descriptor */
+typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
+{
+    U8              RequestFlags;               /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             LMID;                       /* 0x04 */
+    U16             IoIndex;                    /* 0x06 */
+} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+  Mpi2SCSITargetRequestDescriptor_t,
+  MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
+
+
+/* RAID Accelerator Request Descriptor */
+typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR
+{
+    U8              RequestFlags;               /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             LMID;                       /* 0x04 */
+    U16             Reserved;                   /* 0x06 */
+} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+  Mpi2RAIDAcceleratorRequestDescriptor_t,
+  MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t;
+
+
+/* union of Request Descriptors */
+typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
+{
+    MPI2_DEFAULT_REQUEST_DESCRIPTOR             Default;
+    MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR       HighPriority;
+    MPI2_SCSI_IO_REQUEST_DESCRIPTOR             SCSIIO;
+    MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR         SCSITarget;
+    MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR          RAIDAccelerator;
+    U64                                         Words;
+} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
+  Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t;
+
+
+/* Reply Descriptors */
+
+/* Default Reply Descriptor */
+typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
+{
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             DescriptorTypeDependent1;   /* 0x02 */
+    U32             DescriptorTypeDependent2;   /* 0x04 */
+} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
+  Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
+
+/* defines for the ReplyFlags field */
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK                   (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS             (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY               (0x01)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS        (0x02)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER       (0x03)
+#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS    (0x05)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED                      (0x0F)
+
+/* values for marking a reply descriptor as unused */
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK             (0xFFFFFFFF)
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK             (0xFFFFFFFF)
+
+/* Address Reply Descriptor */
+typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
+{
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U32             ReplyFrameAddress;          /* 0x04 */
+} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
+  Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
+
+#define MPI2_ADDRESS_REPLY_SMID_INVALID                 (0x00)
+
+
+/* SCSI IO Success Reply Descriptor */
+typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
+{
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             TaskTag;                    /* 0x04 */
+    U16             Reserved1;                  /* 0x06 */
+} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+  Mpi2SCSIIOSuccessReplyDescriptor_t,
+  MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
+
+
+/* TargetAssist Success Reply Descriptor */
+typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
+{
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U8              SequenceNumber;             /* 0x04 */
+    U8              Reserved1;                  /* 0x05 */
+    U16             IoIndex;                    /* 0x06 */
+} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+  Mpi2TargetAssistSuccessReplyDescriptor_t,
+  MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
+
+
+/* Target Command Buffer Reply Descriptor */
+typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
+{
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U8              VP_ID;                      /* 0x02 */
+    U8              Flags;                      /* 0x03 */
+    U16             InitiatorDevHandle;         /* 0x04 */
+    U16             IoIndex;                    /* 0x06 */
+} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+  Mpi2TargetCommandBufferReplyDescriptor_t,
+  MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
+
+/* defines for Flags field */
+#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK     (0x3F)
+
+
+/* RAID Accelerator Success Reply Descriptor */
+typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
+{
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U32             Reserved;                   /* 0x04 */
+} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+  Mpi2RAIDAcceleratorSuccessReplyDescriptor_t,
+  MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
+
+
+/* union of Reply Descriptors */
+typedef union _MPI2_REPLY_DESCRIPTORS_UNION
+{
+    MPI2_DEFAULT_REPLY_DESCRIPTOR                   Default;
+    MPI2_ADDRESS_REPLY_DESCRIPTOR                   AddressReply;
+    MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR           SCSIIOSuccess;
+    MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR      TargetAssistSuccess;
+    MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR     TargetCommandBuffer;
+    MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR  RAIDAcceleratorSuccess;
+    U64                                             Words;
+} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
+  Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
+
+
+
+/*****************************************************************************
+*
+*        Message Functions
+*              0x80 -> 0x8F reserved for private message use per product
+*
+*
+*****************************************************************************/
+
+#define MPI2_FUNCTION_SCSI_IO_REQUEST               (0x00) /* SCSI IO */
+#define MPI2_FUNCTION_SCSI_TASK_MGMT                (0x01) /* SCSI Task Management */
+#define MPI2_FUNCTION_IOC_INIT                      (0x02) /* IOC Init */
+#define MPI2_FUNCTION_IOC_FACTS                     (0x03) /* IOC Facts */
+#define MPI2_FUNCTION_CONFIG                        (0x04) /* Configuration */
+#define MPI2_FUNCTION_PORT_FACTS                    (0x05) /* Port Facts */
+#define MPI2_FUNCTION_PORT_ENABLE                   (0x06) /* Port Enable */
+#define MPI2_FUNCTION_EVENT_NOTIFICATION            (0x07) /* Event Notification */
+#define MPI2_FUNCTION_EVENT_ACK                     (0x08) /* Event Acknowledge */
+#define MPI2_FUNCTION_FW_DOWNLOAD                   (0x09) /* FW Download */
+#define MPI2_FUNCTION_TARGET_ASSIST                 (0x0B) /* Target Assist */
+#define MPI2_FUNCTION_TARGET_STATUS_SEND            (0x0C) /* Target Status Send */
+#define MPI2_FUNCTION_TARGET_MODE_ABORT             (0x0D) /* Target Mode Abort */
+#define MPI2_FUNCTION_FW_UPLOAD                     (0x12) /* FW Upload */
+#define MPI2_FUNCTION_RAID_ACTION                   (0x15) /* RAID Action */
+#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH      (0x16) /* SCSI IO RAID Passthrough */
+#define MPI2_FUNCTION_TOOLBOX                       (0x17) /* Toolbox */
+#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR      (0x18) /* SCSI Enclosure Processor */
+#define MPI2_FUNCTION_SMP_PASSTHROUGH               (0x1A) /* SMP Passthrough */
+#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL           (0x1B) /* SAS IO Unit Control */
+#define MPI2_FUNCTION_SATA_PASSTHROUGH              (0x1C) /* SATA Passthrough */
+#define MPI2_FUNCTION_DIAG_BUFFER_POST              (0x1D) /* Diagnostic Buffer Post */
+#define MPI2_FUNCTION_DIAG_RELEASE                  (0x1E) /* Diagnostic Release */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST      (0x24) /* Target Command Buffer Post Base */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST      (0x25) /* Target Command Buffer Post List */
+#define MPI2_FUNCTION_RAID_ACCELERATOR              (0x2C) /* RAID Accelerator */
+#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION   (0x2F) /* Host Based Discovery Action */
+
+
+
+/* Doorbell functions */
+#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET        (0x40)
+#define MPI2_FUNCTION_HANDSHAKE                     (0x42)
+
+
+/*****************************************************************************
+*
+*        IOC Status Values
+*
+*****************************************************************************/
+
+/* mask for IOCStatus status value */
+#define MPI2_IOCSTATUS_MASK                     (0x7FFF)
+
+/****************************************************************************
+*  Common IOCStatus values for all replies
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SUCCESS                      (0x0000)
+#define MPI2_IOCSTATUS_INVALID_FUNCTION             (0x0001)
+#define MPI2_IOCSTATUS_BUSY                         (0x0002)
+#define MPI2_IOCSTATUS_INVALID_SGL                  (0x0003)
+#define MPI2_IOCSTATUS_INTERNAL_ERROR               (0x0004)
+#define MPI2_IOCSTATUS_INVALID_VPID                 (0x0005)
+#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES       (0x0006)
+#define MPI2_IOCSTATUS_INVALID_FIELD                (0x0007)
+#define MPI2_IOCSTATUS_INVALID_STATE                (0x0008)
+#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED       (0x0009)
+
+/****************************************************************************
+*  Config IOCStatus values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION        (0x0020)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE          (0x0021)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE          (0x0022)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA          (0x0023)
+#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS           (0x0024)
+#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT           (0x0025)
+
+/****************************************************************************
+*  SCSI IO Reply
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR         (0x0040)
+#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE       (0x0042)
+#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE        (0x0043)
+#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN            (0x0044)
+#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN           (0x0045)
+#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR           (0x0046)
+#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR          (0x0047)
+#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED         (0x0048)
+#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH       (0x0049)
+#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED        (0x004A)
+#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED          (0x004B)
+#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED          (0x004C)
+
+/****************************************************************************
+*  For use by SCSI Initiator and SCSI Target end-to-end data protection
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR             (0x004D)
+#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR           (0x004E)
+#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR           (0x004F)
+
+/****************************************************************************
+*  SCSI Target values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX      (0x0062)
+#define MPI2_IOCSTATUS_TARGET_ABORTED               (0x0063)
+#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE     (0x0064)
+#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION         (0x0065)
+#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH   (0x006A)
+#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR     (0x006D)
+#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA   (0x006E)
+#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT          (0x006F)
+#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT       (0x0070)
+#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED          (0x0071)
+
+/****************************************************************************
+*  Serial Attached SCSI values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED       (0x0090)
+#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN         (0x0091)
+
+/****************************************************************************
+*  Diagnostic Buffer Post / Diagnostic Release values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED          (0x00A0)
+
+/****************************************************************************
+*  RAID Accelerator values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR             (0x00B0)
+
+/****************************************************************************
+*  IOCStatus flag to indicate that log info is available
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE      (0x8000)
+
+/****************************************************************************
+*  IOCLogInfo Types
+****************************************************************************/
+
+#define MPI2_IOCLOGINFO_TYPE_MASK               (0xF0000000)
+#define MPI2_IOCLOGINFO_TYPE_SHIFT              (28)
+#define MPI2_IOCLOGINFO_TYPE_NONE               (0x0)
+#define MPI2_IOCLOGINFO_TYPE_SCSI               (0x1)
+#define MPI2_IOCLOGINFO_TYPE_FC                 (0x2)
+#define MPI2_IOCLOGINFO_TYPE_SAS                (0x3)
+#define MPI2_IOCLOGINFO_TYPE_ISCSI              (0x4)
+#define MPI2_IOCLOGINFO_LOG_DATA_MASK           (0x0FFFFFFF)
+
+
+/*****************************************************************************
+*
+*        Standard Message Structures
+*
+*****************************************************************************/
+
+/****************************************************************************
+* Request Message Header for all request messages
+****************************************************************************/
+
+typedef struct _MPI2_REQUEST_HEADER
+{
+    U16             FunctionDependent1;         /* 0x00 */
+    U8              ChainOffset;                /* 0x02 */
+    U8              Function;                   /* 0x03 */
+    U16             FunctionDependent2;         /* 0x04 */
+    U8              FunctionDependent3;         /* 0x06 */
+    U8              MsgFlags;                   /* 0x07 */
+    U8              VP_ID;                      /* 0x08 */
+    U8              VF_ID;                      /* 0x09 */
+    U16             Reserved1;                  /* 0x0A */
+} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER,
+  MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t;
+
+
+/****************************************************************************
+*  Default Reply
+****************************************************************************/
+
+typedef struct _MPI2_DEFAULT_REPLY
+{
+    U16             FunctionDependent1;         /* 0x00 */
+    U8              MsgLength;                  /* 0x02 */
+    U8              Function;                   /* 0x03 */
+    U16             FunctionDependent2;         /* 0x04 */
+    U8              FunctionDependent3;         /* 0x06 */
+    U8              MsgFlags;                   /* 0x07 */
+    U8              VP_ID;                      /* 0x08 */
+    U8              VF_ID;                      /* 0x09 */
+    U16             Reserved1;                  /* 0x0A */
+    U16             FunctionDependent5;         /* 0x0C */
+    U16             IOCStatus;                  /* 0x0E */
+    U32             IOCLogInfo;                 /* 0x10 */
+} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY,
+  MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t;
+
+
+/* common version structure/union used in messages and configuration pages */
+
+typedef struct _MPI2_VERSION_STRUCT
+{
+    U8                      Dev;                        /* 0x00 */
+    U8                      Unit;                       /* 0x01 */
+    U8                      Minor;                      /* 0x02 */
+    U8                      Major;                      /* 0x03 */
+} MPI2_VERSION_STRUCT;
+
+typedef union _MPI2_VERSION_UNION
+{
+    MPI2_VERSION_STRUCT     Struct;
+    U32                     Word;
+} MPI2_VERSION_UNION;
+
+
+/* LUN field defines, common to many structures */
+#define MPI2_LUN_FIRST_LEVEL_ADDRESSING             (0x0000FFFF)
+#define MPI2_LUN_SECOND_LEVEL_ADDRESSING            (0xFFFF0000)
+#define MPI2_LUN_THIRD_LEVEL_ADDRESSING             (0x0000FFFF)
+#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING            (0xFFFF0000)
+#define MPI2_LUN_LEVEL_1_WORD                       (0xFF00)
+#define MPI2_LUN_LEVEL_1_DWORD                      (0x0000FF00)
+
+
+/*****************************************************************************
+*
+*        Fusion-MPT MPI Scatter Gather Elements
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  MPI Simple Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_SIMPLE32
+{
+    U32                     FlagsLength;
+    U32                     Address;
+} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32,
+  Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t;
+
+typedef struct _MPI2_SGE_SIMPLE64
+{
+    U32                     FlagsLength;
+    U64                     Address;
+} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64,
+  Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t;
+
+typedef struct _MPI2_SGE_SIMPLE_UNION
+{
+    U32                     FlagsLength;
+    union
+    {
+        U32                 Address32;
+        U64                 Address64;
+    } u;
+} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
+  Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
+
+
+/****************************************************************************
+*  MPI Chain Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_CHAIN32
+{
+    U16                     Length;
+    U8                      NextChainOffset;
+    U8                      Flags;
+    U32                     Address;
+} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32,
+  Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t;
+
+typedef struct _MPI2_SGE_CHAIN64
+{
+    U16                     Length;
+    U8                      NextChainOffset;
+    U8                      Flags;
+    U64                     Address;
+} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64,
+  Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t;
+
+typedef struct _MPI2_SGE_CHAIN_UNION
+{
+    U16                     Length;
+    U8                      NextChainOffset;
+    U8                      Flags;
+    union
+    {
+        U32                 Address32;
+        U64                 Address64;
+    } u;
+} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
+  Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
+
+
+/****************************************************************************
+*  MPI Transaction Context Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_TRANSACTION32
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[1];
+    U32                     TransactionDetails[1];
+} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32,
+  Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t;
+
+typedef struct _MPI2_SGE_TRANSACTION64
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[2];
+    U32                     TransactionDetails[1];
+} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64,
+  Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t;
+
+typedef struct _MPI2_SGE_TRANSACTION96
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[3];
+    U32                     TransactionDetails[1];
+} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96,
+  Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t;
+
+typedef struct _MPI2_SGE_TRANSACTION128
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    U32                     TransactionContext[4];
+    U32                     TransactionDetails[1];
+} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128,
+  Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128;
+
+typedef struct _MPI2_SGE_TRANSACTION_UNION
+{
+    U8                      Reserved;
+    U8                      ContextSize;
+    U8                      DetailsLength;
+    U8                      Flags;
+    union
+    {
+        U32                 TransactionContext32[1];
+        U32                 TransactionContext64[2];
+        U32                 TransactionContext96[3];
+        U32                 TransactionContext128[4];
+    } u;
+    U32                     TransactionDetails[1];
+} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION,
+  Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t;
+
+
+/****************************************************************************
+*  MPI SGE union for IO SGL's
+****************************************************************************/
+
+typedef struct _MPI2_MPI_SGE_IO_UNION
+{
+    union
+    {
+        MPI2_SGE_SIMPLE_UNION   Simple;
+        MPI2_SGE_CHAIN_UNION    Chain;
+    } u;
+} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION,
+  Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t;
+
+
+/****************************************************************************
+*  MPI SGE union for SGL's with Simple and Transaction elements
+****************************************************************************/
+
+typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION
+{
+    union
+    {
+        MPI2_SGE_SIMPLE_UNION       Simple;
+        MPI2_SGE_TRANSACTION_UNION  Transaction;
+    } u;
+} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
+  Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t;
+
+
+/****************************************************************************
+*  All MPI SGE types union
+****************************************************************************/
+
+typedef struct _MPI2_MPI_SGE_UNION
+{
+    union
+    {
+        MPI2_SGE_SIMPLE_UNION       Simple;
+        MPI2_SGE_CHAIN_UNION        Chain;
+        MPI2_SGE_TRANSACTION_UNION  Transaction;
+    } u;
+} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION,
+  Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t;
+
+
+/****************************************************************************
+*  MPI SGE field definition and masks
+****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI2_SGE_FLAGS_LAST_ELEMENT             (0x80)
+#define MPI2_SGE_FLAGS_END_OF_BUFFER            (0x40)
+#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK        (0x30)
+#define MPI2_SGE_FLAGS_LOCAL_ADDRESS            (0x08)
+#define MPI2_SGE_FLAGS_DIRECTION                (0x04)
+#define MPI2_SGE_FLAGS_ADDRESS_SIZE             (0x02)
+#define MPI2_SGE_FLAGS_END_OF_LIST              (0x01)
+
+#define MPI2_SGE_FLAGS_SHIFT                    (24)
+
+#define MPI2_SGE_LENGTH_MASK                    (0x00FFFFFF)
+#define MPI2_SGE_CHAIN_LENGTH_MASK              (0x0000FFFF)
+
+/* Element Type */
+
+#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT      (0x00)
+#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT           (0x10)
+#define MPI2_SGE_FLAGS_CHAIN_ELEMENT            (0x30)
+#define MPI2_SGE_FLAGS_ELEMENT_MASK             (0x30)
+
+/* Address location */
+
+#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS           (0x00)
+
+/* Direction */
+
+#define MPI2_SGE_FLAGS_IOC_TO_HOST              (0x00)
+#define MPI2_SGE_FLAGS_HOST_TO_IOC              (0x04)
+
+/* Address Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING        (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
+
+/* Context Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_CONTEXT           (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_CONTEXT           (0x02)
+#define MPI2_SGE_FLAGS_96_BIT_CONTEXT           (0x04)
+#define MPI2_SGE_FLAGS_128_BIT_CONTEXT          (0x06)
+
+#define MPI2_SGE_CHAIN_OFFSET_MASK              (0x00FF0000)
+#define MPI2_SGE_CHAIN_OFFSET_SHIFT             (16)
+
+/****************************************************************************
+*  MPI SGE operation Macros
+****************************************************************************/
+
+/* SIMPLE FlagsLength manipulations... */
+#define MPI2_SGE_SET_FLAGS(f)          ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
+#define MPI2_SGE_GET_FLAGS(f)          (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT)
+#define MPI2_SGE_LENGTH(f)             ((f) & MPI2_SGE_LENGTH_MASK)
+#define MPI2_SGE_CHAIN_LENGTH(f)       ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
+
+#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l))
+
+#define MPI2_pSGE_GET_FLAGS(psg)            MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
+#define MPI2_pSGE_GET_LENGTH(psg)           MPI2_SGE_LENGTH((psg)->FlagsLength)
+#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l)
+
+/* CAUTION - The following are READ-MODIFY-WRITE! */
+#define MPI2_pSGE_SET_FLAGS(psg,f)      (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f)
+#define MPI2_pSGE_SET_LENGTH(psg,l)     (psg)->FlagsLength |= MPI2_SGE_LENGTH(l)
+
+#define MPI2_GET_CHAIN_OFFSET(x)    ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT)
+
+
+/*****************************************************************************
+*
+*        Fusion-MPT IEEE Scatter Gather Elements
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  IEEE Simple Element structures
+****************************************************************************/
+
+typedef struct _MPI2_IEEE_SGE_SIMPLE32
+{
+    U32                     Address;
+    U32                     FlagsLength;
+} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
+  Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
+
+typedef struct _MPI2_IEEE_SGE_SIMPLE64
+{
+    U64                     Address;
+    U32                     Length;
+    U16                     Reserved1;
+    U8                      Reserved2;
+    U8                      Flags;
+} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
+  Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
+
+typedef union _MPI2_IEEE_SGE_SIMPLE_UNION
+{
+    MPI2_IEEE_SGE_SIMPLE32  Simple32;
+    MPI2_IEEE_SGE_SIMPLE64  Simple64;
+} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
+  Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
+
+
+/****************************************************************************
+*  IEEE Chain Element structures
+****************************************************************************/
+
+typedef MPI2_IEEE_SGE_SIMPLE32  MPI2_IEEE_SGE_CHAIN32;
+
+typedef MPI2_IEEE_SGE_SIMPLE64  MPI2_IEEE_SGE_CHAIN64;
+
+typedef union _MPI2_IEEE_SGE_CHAIN_UNION
+{
+    MPI2_IEEE_SGE_CHAIN32   Chain32;
+    MPI2_IEEE_SGE_CHAIN64   Chain64;
+} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
+  Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
+
+
+/****************************************************************************
+*  All IEEE SGE types union
+****************************************************************************/
+
+typedef struct _MPI2_IEEE_SGE_UNION
+{
+    union
+    {
+        MPI2_IEEE_SGE_SIMPLE_UNION  Simple;
+        MPI2_IEEE_SGE_CHAIN_UNION   Chain;
+    } u;
+} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION,
+  Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t;
+
+
+/****************************************************************************
+*  IEEE SGE field definitions and masks
+****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK   (0x80)
+
+#define MPI2_IEEE32_SGE_FLAGS_SHIFT             (24)
+
+#define MPI2_IEEE32_SGE_LENGTH_MASK             (0x00FFFFFF)
+
+/* Element Type */
+
+#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT      (0x00)
+#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT       (0x80)
+
+/* Data Location Address Space */
+
+#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK           (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR         (0x00)
+#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
+
+
+/****************************************************************************
+*  IEEE SGE operation Macros
+****************************************************************************/
+
+/* SIMPLE FlagsLength manipulations... */
+#define MPI2_IEEE32_SGE_SET_FLAGS(f)     ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
+#define MPI2_IEEE32_SGE_GET_FLAGS(f)     (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
+#define MPI2_IEEE32_SGE_LENGTH(f)        ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
+
+#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l)      (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l))
+
+#define MPI2_IEEE32_pSGE_GET_FLAGS(psg)             MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
+#define MPI2_IEEE32_pSGE_GET_LENGTH(psg)            MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
+#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l)  (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l)
+
+/* CAUTION - The following are READ-MODIFY-WRITE! */
+#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f)    (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f)
+#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l)   (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l)
+
+
+
+
+/*****************************************************************************
+*
+*        Fusion-MPT MPI/IEEE Scatter Gather Unions
+*
+*****************************************************************************/
+
+typedef union _MPI2_SIMPLE_SGE_UNION
+{
+    MPI2_SGE_SIMPLE_UNION       MpiSimple;
+    MPI2_IEEE_SGE_SIMPLE_UNION  IeeeSimple;
+} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION,
+  Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t;
+
+
+typedef union _MPI2_SGE_IO_UNION
+{
+    MPI2_SGE_SIMPLE_UNION       MpiSimple;
+    MPI2_SGE_CHAIN_UNION        MpiChain;
+    MPI2_IEEE_SGE_SIMPLE_UNION  IeeeSimple;
+    MPI2_IEEE_SGE_CHAIN_UNION   IeeeChain;
+} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
+  Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
+
+
+/****************************************************************************
+*
+*  Values for SGLFlags field, used in many request messages with an SGL
+*
+****************************************************************************/
+
+/* values for MPI SGL Data Location Address Space subfield */
+#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK            (0x0C)
+#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE          (0x00)
+#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE          (0x04)
+#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE          (0x08)
+#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE       (0x0C)
+/* values for SGL Type subfield */
+#define MPI2_SGLFLAGS_SGL_TYPE_MASK                 (0x03)
+#define MPI2_SGLFLAGS_SGL_TYPE_MPI                  (0x00)
+#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32               (0x01)
+#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64               (0x02)
+
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_cnfg.h ../../stable/8/sys/dev/mps/mpi/mpi2_cnfg.h
--- sys/dev/mps/mpi/mpi2_cnfg.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_cnfg.h	2011-01-07 14:33:12.677616339 -0700
@@ -0,0 +1,2646 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_cnfg.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_cnfg.h
+ *          Title:  MPI Configuration messages and pages
+ *  Creation Date:  November 10, 2006
+ *
+ *    mpi2_cnfg.h Version:  02.00.13
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  Added defines for SAS IO Unit Page 2 PhyFlags.
+ *                      Added Manufacturing Page 11.
+ *                      Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
+ *                      define.
+ *  06-26-07  02.00.02  Adding generic structure for product-specific
+ *                      Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
+ *                      Rework of BIOS Page 2 configuration page.
+ *                      Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
+ *                      forms.
+ *                      Added configuration pages IOC Page 8 and Driver
+ *                      Persistent Mapping Page 0.
+ *  08-31-07  02.00.03  Modified configuration pages dealing with Integrated
+ *                      RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
+ *                      RAID Physical Disk Pages 0 and 1, RAID Configuration
+ *                      Page 0).
+ *                      Added new value for AccessStatus field of SAS Device
+ *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
+ *  10-31-07  02.00.04  Added missing SEPDevHandle field to
+ *                      MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
+ *  12-18-07  02.00.05  Modified IO Unit Page 0 to use 32-bit version fields for
+ *                      NVDATA.
+ *                      Modified IOC Page 7 to use masks and added field for
+ *                      SASBroadcastPrimitiveMasks.
+ *                      Added MPI2_CONFIG_PAGE_BIOS_4.
+ *                      Added MPI2_CONFIG_PAGE_LOG_0.
+ *  02-29-08  02.00.06  Modified various names to make them 32-character unique.
+ *                      Added SAS Device IDs.
+ *                      Updated Integrated RAID configuration pages including
+ *                      Manufacturing Page 4, IOC Page 6, and RAID Configuration
+ *                      Page 0.
+ *  05-21-08  02.00.07  Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
+ *                      Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
+ *                      Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
+ *                      Added missing MaxNumRoutedSasAddresses field to
+ *                      MPI2_CONFIG_PAGE_EXPANDER_0.
+ *                      Added SAS Port Page 0.
+ *                      Modified structure layout for
+ *                      MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
+ *  06-27-08  02.00.08  Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
+ *                      MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
+ *  10-02-08  02.00.09  Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
+ *                      to 0x000000FF.
+ *                      Added two new values for the Physical Disk Coercion Size
+ *                      bits in the Flags field of Manufacturing Page 4.
+ *                      Added product-specific Manufacturing pages 16 to 31.
+ *                      Modified Flags bits for controlling write cache on SATA
+ *                      drives in IO Unit Page 1.
+ *                      Added new bit to AdditionalControlFlags of SAS IO Unit
+ *                      Page 1 to control Invalid Topology Correction.
+ *                      Added additional defines for RAID Volume Page 0
+ *                      VolumeStatusFlags field.
+ *                      Modified meaning of RAID Volume Page 0 VolumeSettings
+ *                      define for auto-configure of hot-swap drives.
+ *                      Added SupportedPhysDisks field to RAID Volume Page 1 and
+ *                      added related defines.
+ *                      Added PhysDiskAttributes field (and related defines) to
+ *                      RAID Physical Disk Page 0.
+ *                      Added MPI2_SAS_PHYINFO_PHY_VACANT define.
+ *                      Added three new DiscoveryStatus bits for SAS IO Unit
+ *                      Page 0 and SAS Expander Page 0.
+ *                      Removed multiplexing information from SAS IO Unit pages.
+ *                      Added BootDeviceWaitTime field to SAS IO Unit Page 4.
+ *                      Removed Zone Address Resolved bit from PhyInfo and from
+ *                      Expander Page 0 Flags field.
+ *                      Added two new AccessStatus values to SAS Device Page 0
+ *                      for indicating routing problems. Added 3 reserved words
+ *                      to this page.
+ *  01-19-09  02.00.10  Fixed defines for GPIOVal field of IO Unit Page 3.
+ *                      Inserted missing reserved field into structure for IOC
+ *                      Page 6.
+ *                      Added more pending task bits to RAID Volume Page 0
+ *                      VolumeStatusFlags defines.
+ *                      Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
+ *                      Added a new DiscoveryStatus bit for SAS IO Unit Page 0
+ *                      and SAS Expander Page 0 to flag a downstream initiator
+ *                      when in simplified routing mode.
+ *                      Removed SATA Init Failure defines for DiscoveryStatus
+ *                      fields of SAS IO Unit Page 0 and SAS Expander Page 0.
+ *                      Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
+ *                      Added PortGroups, DmaGroup, and ControlGroup fields to
+ *                      SAS Device Page 0.
+ *  05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
+ *                      Unit Page 6.
+ *                      Added expander reduced functionality data to SAS
+ *                      Expander Page 0.
+ *                      Added SAS PHY Page 2 and SAS PHY Page 3.
+ *  07-30-09  02.00.12  Added IO Unit Page 7.
+ *                      Added new device ids.
+ *                      Added SAS IO Unit Page 5.
+ *                      Added partial and slumber power management capable flags
+ *                      to SAS Device Page 0 Flags field.
+ *                      Added PhyInfo defines for power condition.
+ *                      Added Ethernet configuration pages.
+ *  10-28-09  02.00.13  Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
+ *                      Added SAS PHY Page 4 structure and defines.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_CNFG_H
+#define MPI2_CNFG_H
+
+/*****************************************************************************
+*   Configuration Page Header and defines
+*****************************************************************************/
+
+/* Config Page Header */
+typedef struct _MPI2_CONFIG_PAGE_HEADER
+{
+    U8                 PageVersion;                /* 0x00 */
+    U8                 PageLength;                 /* 0x01 */
+    U8                 PageNumber;                 /* 0x02 */
+    U8                 PageType;                   /* 0x03 */
+} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER,
+  Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t;
+
+typedef union _MPI2_CONFIG_PAGE_HEADER_UNION
+{
+   MPI2_CONFIG_PAGE_HEADER  Struct;
+   U8                       Bytes[4];
+   U16                      Word16[2];
+   U32                      Word32;
+} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
+  Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion;
+
+/* Extended Config Page Header */
+typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER
+{
+    U8                  PageVersion;                /* 0x00 */
+    U8                  Reserved1;                  /* 0x01 */
+    U8                  PageNumber;                 /* 0x02 */
+    U8                  PageType;                   /* 0x03 */
+    U16                 ExtPageLength;              /* 0x04 */
+    U8                  ExtPageType;                /* 0x06 */
+    U8                  Reserved2;                  /* 0x07 */
+} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
+  MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
+  Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t;
+
+typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
+{
+   MPI2_CONFIG_PAGE_HEADER          Struct;
+   MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
+   U8                               Bytes[8];
+   U16                              Word16[4];
+   U32                              Word32[2];
+} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
+  Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion;
+
+
+/* PageType field values */
+#define MPI2_CONFIG_PAGEATTR_READ_ONLY              (0x00)
+#define MPI2_CONFIG_PAGEATTR_CHANGEABLE             (0x10)
+#define MPI2_CONFIG_PAGEATTR_PERSISTENT             (0x20)
+#define MPI2_CONFIG_PAGEATTR_MASK                   (0xF0)
+
+#define MPI2_CONFIG_PAGETYPE_IO_UNIT                (0x00)
+#define MPI2_CONFIG_PAGETYPE_IOC                    (0x01)
+#define MPI2_CONFIG_PAGETYPE_BIOS                   (0x02)
+#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME            (0x08)
+#define MPI2_CONFIG_PAGETYPE_MANUFACTURING          (0x09)
+#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK          (0x0A)
+#define MPI2_CONFIG_PAGETYPE_EXTENDED               (0x0F)
+#define MPI2_CONFIG_PAGETYPE_MASK                   (0x0F)
+
+#define MPI2_CONFIG_TYPENUM_MASK                    (0x0FFF)
+
+
+/* ExtPageType field values */
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT         (0x10)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER        (0x11)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE          (0x12)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY             (0x13)
+#define MPI2_CONFIG_EXTPAGETYPE_LOG                 (0x14)
+#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE           (0x15)
+#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG         (0x16)
+#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING      (0x17)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT            (0x18)
+#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET            (0x19)
+
+
+/*****************************************************************************
+*   PageAddress defines
+*****************************************************************************/
+
+/* RAID Volume PageAddress format */
+#define MPI2_RAID_VOLUME_PGAD_FORM_MASK             (0xF0000000)
+#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE  (0x00000000)
+#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE           (0x10000000)
+
+#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK           (0x0000FFFF)
+
+
+/* RAID Physical Disk PageAddress format */
+#define MPI2_PHYSDISK_PGAD_FORM_MASK                    (0xF0000000)
+#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM    (0x00000000)
+#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM             (0x10000000)
+#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE               (0x20000000)
+
+#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK             (0x000000FF)
+#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK               (0x0000FFFF)
+
+
+/* SAS Expander PageAddress format */
+#define MPI2_SAS_EXPAND_PGAD_FORM_MASK              (0xF0000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL     (0x00000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM      (0x10000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL              (0x20000000)
+
+#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK            (0x0000FFFF)
+#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK            (0x00FF0000)
+#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT           (16)
+
+
+/* SAS Device PageAddress format */
+#define MPI2_SAS_DEVICE_PGAD_FORM_MASK              (0xF0000000)
+#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE   (0x00000000)
+#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE            (0x20000000)
+
+#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK            (0x0000FFFF)
+
+
+/* SAS PHY PageAddress format */
+#define MPI2_SAS_PHY_PGAD_FORM_MASK                 (0xF0000000)
+#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER           (0x00000000)
+#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX        (0x10000000)
+
+#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK           (0x000000FF)
+#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK        (0x0000FFFF)
+
+
+/* SAS Port PageAddress format */
+#define MPI2_SASPORT_PGAD_FORM_MASK                 (0xF0000000)
+#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT        (0x00000000)
+#define MPI2_SASPORT_PGAD_FORM_PORT_NUM             (0x10000000)
+
+#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK           (0x00000FFF)
+
+
+/* SAS Enclosure PageAddress format */
+#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK              (0xF0000000)
+#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE   (0x00000000)
+#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE            (0x10000000)
+
+#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK            (0x0000FFFF)
+
+
+/* RAID Configuration PageAddress format */
+#define MPI2_RAID_PGAD_FORM_MASK                    (0xF0000000)
+#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM      (0x00000000)
+#define MPI2_RAID_PGAD_FORM_CONFIGNUM               (0x10000000)
+#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG           (0x20000000)
+
+#define MPI2_RAID_PGAD_CONFIGNUM_MASK               (0x000000FF)
+
+
+/* Driver Persistent Mapping PageAddress format */
+#define MPI2_DPM_PGAD_FORM_MASK                     (0xF0000000)
+#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE              (0x00000000)
+
+#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK              (0x0FFF0000)
+#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT             (16)
+#define MPI2_DPM_PGAD_START_ENTRY_MASK              (0x0000FFFF)
+
+
+/* Ethernet PageAddress format */
+#define MPI2_ETHERNET_PGAD_FORM_MASK                (0xF0000000)
+#define MPI2_ETHERNET_PGAD_FORM_IF_NUM              (0x00000000)
+
+#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK           (0x000000FF)
+
+
+
+/****************************************************************************
+*   Configuration messages
+****************************************************************************/
+
+/* Configuration Request Message */
+typedef struct _MPI2_CONFIG_REQUEST
+{
+    U8                      Action;                     /* 0x00 */
+    U8                      SGLFlags;                   /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     ExtPageLength;              /* 0x04 */
+    U8                      ExtPageType;                /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved1;                  /* 0x0A */
+    U32                     Reserved2;                  /* 0x0C */
+    U32                     Reserved3;                  /* 0x10 */
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x14 */
+    U32                     PageAddress;                /* 0x18 */
+    MPI2_SGE_IO_UNION       PageBufferSGE;              /* 0x1C */
+} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST,
+  Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t;
+
+/* values for the Action field */
+#define MPI2_CONFIG_ACTION_PAGE_HEADER              (0x00)
+#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT        (0x01)
+#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT       (0x02)
+#define MPI2_CONFIG_ACTION_PAGE_DEFAULT             (0x03)
+#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM         (0x04)
+#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT        (0x05)
+#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM          (0x06)
+#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE      (0x07)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* Config Reply Message */
+typedef struct _MPI2_CONFIG_REPLY
+{
+    U8                      Action;                     /* 0x00 */
+    U8                      SGLFlags;                   /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     ExtPageLength;              /* 0x04 */
+    U8                      ExtPageType;                /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved1;                  /* 0x0A */
+    U16                     Reserved2;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x14 */
+} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY,
+  Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t;
+
+
+
+/*****************************************************************************
+*
+*               C o n f i g u r a t i o n    P a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************
+*   Manufacturing Config pages
+****************************************************************************/
+
+#define MPI2_MFGPAGE_VENDORID_LSI                   (0x1000)
+
+/* SAS */
+#define MPI2_MFGPAGE_DEVID_SAS2004                  (0x0070)
+#define MPI2_MFGPAGE_DEVID_SAS2008                  (0x0072)
+#define MPI2_MFGPAGE_DEVID_SAS2108_1                (0x0074)
+#define MPI2_MFGPAGE_DEVID_SAS2108_2                (0x0076)
+#define MPI2_MFGPAGE_DEVID_SAS2108_3                (0x0077)
+#define MPI2_MFGPAGE_DEVID_SAS2116_1                (0x0064)
+#define MPI2_MFGPAGE_DEVID_SAS2116_2                (0x0065)
+
+#define MPI2_MFGPAGE_DEVID_SAS2208_1                (0x0080)
+#define MPI2_MFGPAGE_DEVID_SAS2208_2                (0x0081)
+#define MPI2_MFGPAGE_DEVID_SAS2208_3                (0x0082)
+#define MPI2_MFGPAGE_DEVID_SAS2208_4                (0x0083)
+#define MPI2_MFGPAGE_DEVID_SAS2208_5                (0x0084)
+#define MPI2_MFGPAGE_DEVID_SAS2208_6                (0x0085)
+#define MPI2_MFGPAGE_DEVID_SAS2208_7                (0x0086)
+#define MPI2_MFGPAGE_DEVID_SAS2208_8                (0x0087)
+
+
+/* Manufacturing Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_0
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U8                      ChipName[16];               /* 0x04 */
+    U8                      ChipRevision[8];            /* 0x14 */
+    U8                      BoardName[16];              /* 0x1C */
+    U8                      BoardAssembly[16];          /* 0x2C */
+    U8                      BoardTracerNumber[16];      /* 0x3C */
+} MPI2_CONFIG_PAGE_MAN_0,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0,
+  Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t;
+
+#define MPI2_MANUFACTURING0_PAGEVERSION                (0x00)
+
+
+/* Manufacturing Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_1
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U8                      VPD[256];                   /* 0x04 */
+} MPI2_CONFIG_PAGE_MAN_1,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1,
+  Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t;
+
+#define MPI2_MANUFACTURING1_PAGEVERSION                (0x00)
+
+
+typedef struct _MPI2_CHIP_REVISION_ID
+{
+    U16 DeviceID;                                       /* 0x00 */
+    U8  PCIRevisionID;                                  /* 0x02 */
+    U8  Reserved;                                       /* 0x03 */
+} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID,
+  Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t;
+
+
+/* Manufacturing Page 2 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
+#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS   (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_2
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    MPI2_CHIP_REVISION_ID   ChipId;                     /* 0x04 */
+    U32                     HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */
+} MPI2_CONFIG_PAGE_MAN_2,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2,
+  Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t;
+
+#define MPI2_MANUFACTURING2_PAGEVERSION                 (0x00)
+
+
+/* Manufacturing Page 3 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
+#define MPI2_MAN_PAGE_3_INFO_WORDS          (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_3
+{
+    MPI2_CONFIG_PAGE_HEADER             Header;         /* 0x00 */
+    MPI2_CHIP_REVISION_ID               ChipId;         /* 0x04 */
+    U32                                 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */
+} MPI2_CONFIG_PAGE_MAN_3,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3,
+  Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t;
+
+#define MPI2_MANUFACTURING3_PAGEVERSION                 (0x00)
+
+
+/* Manufacturing Page 4 */
+
+typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS
+{
+    U8                          PowerSaveFlags;                 /* 0x00 */
+    U8                          InternalOperationsSleepTime;    /* 0x01 */
+    U8                          InternalOperationsRunTime;      /* 0x02 */
+    U8                          HostIdleTime;                   /* 0x03 */
+} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
+  MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
+  Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t;
+
+/* defines for the PowerSaveFlags field */
+#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE               (0x03)
+#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED           (0x00)
+#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE             (0x01)
+#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE               (0x02)
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_4
+{
+    MPI2_CONFIG_PAGE_HEADER             Header;                 /* 0x00 */
+    U32                                 Reserved1;              /* 0x04 */
+    U32                                 Flags;                  /* 0x08 */
+    U8                                  InquirySize;            /* 0x0C */
+    U8                                  Reserved2;              /* 0x0D */
+    U16                                 Reserved3;              /* 0x0E */
+    U8                                  InquiryData[56];        /* 0x10 */
+    U32                                 RAID0VolumeSettings;    /* 0x48 */
+    U32                                 RAID1EVolumeSettings;   /* 0x4C */
+    U32                                 RAID1VolumeSettings;    /* 0x50 */
+    U32                                 RAID10VolumeSettings;   /* 0x54 */
+    U32                                 Reserved4;              /* 0x58 */
+    U32                                 Reserved5;              /* 0x5C */
+    MPI2_MANPAGE4_PWR_SAVE_SETTINGS     PowerSaveSettings;      /* 0x60 */
+    U8                                  MaxOCEDisks;            /* 0x64 */
+    U8                                  ResyncRate;             /* 0x65 */
+    U16                                 DataScrubDuration;      /* 0x66 */
+    U8                                  MaxHotSpares;           /* 0x68 */
+    U8                                  MaxPhysDisksPerVol;     /* 0x69 */
+    U8                                  MaxPhysDisks;           /* 0x6A */
+    U8                                  MaxVolumes;             /* 0x6B */
+} MPI2_CONFIG_PAGE_MAN_4,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4,
+  Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t;
+
+#define MPI2_MANUFACTURING4_PAGEVERSION                 (0x0A)
+
+/* Manufacturing Page 4 Flags field */
+#define MPI2_MANPAGE4_METADATA_SIZE_MASK                (0x00030000)
+#define MPI2_MANPAGE4_METADATA_512MB                    (0x00000000)
+
+#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA                  (0x00008000)
+#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD               (0x00004000)
+#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR              (0x00002000)
+
+#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION            (0x00001C00)
+#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB             (0x00000000)
+#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION           (0x00000400)
+#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION        (0x00000800)
+#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION            (0x00000C00)
+
+#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING            (0x00000300)
+#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING         (0x00000000)
+#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING           (0x00000100)
+#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING      (0x00000200)
+
+#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER            (0x00000080)
+#define MPI2_MANPAGE4_RAID10_DISABLE                    (0x00000040)
+#define MPI2_MANPAGE4_RAID1E_DISABLE                    (0x00000020)
+#define MPI2_MANPAGE4_RAID1_DISABLE                     (0x00000010)
+#define MPI2_MANPAGE4_RAID0_DISABLE                     (0x00000008)
+#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE              (0x00000004)
+#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE            (0x00000002)
+#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA                (0x00000001)
+
+
+/* Manufacturing Page 5 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
+#define MPI2_MAN_PAGE_5_PHY_ENTRIES         (1)
+#endif
+
+typedef struct _MPI2_MANUFACTURING5_ENTRY
+{
+    U64                                 WWID;           /* 0x00 */
+    U64                                 DeviceName;     /* 0x08 */
+} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY,
+  Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_5
+{
+    MPI2_CONFIG_PAGE_HEADER             Header;         /* 0x00 */
+    U8                                  NumPhys;        /* 0x04 */
+    U8                                  Reserved1;      /* 0x05 */
+    U16                                 Reserved2;      /* 0x06 */
+    U32                                 Reserved3;      /* 0x08 */
+    U32                                 Reserved4;      /* 0x0C */
+    MPI2_MANUFACTURING5_ENTRY           Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */
+} MPI2_CONFIG_PAGE_MAN_5,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5,
+  Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t;
+
+#define MPI2_MANUFACTURING5_PAGEVERSION                 (0x03)
+
+
+/* Manufacturing Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_6
+{
+    MPI2_CONFIG_PAGE_HEADER         Header;             /* 0x00 */
+    U32                             ProductSpecificInfo;/* 0x04 */
+} MPI2_CONFIG_PAGE_MAN_6,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6,
+  Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t;
+
+#define MPI2_MANUFACTURING6_PAGEVERSION                 (0x00)
+
+
+/* Manufacturing Page 7 */
+
+typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
+{
+    U32                         Pinout;                 /* 0x00 */
+    U8                          Connector[16];          /* 0x04 */
+    U8                          Location;               /* 0x14 */
+    U8                          Reserved1;              /* 0x15 */
+    U16                         Slot;                   /* 0x16 */
+    U32                         Reserved2;              /* 0x18 */
+} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
+  Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
+
+/* defines for the Pinout field */
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4                (0x00080000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3                (0x00040000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2                (0x00020000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1                (0x00010000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4                (0x00000800)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3                (0x00000400)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2                (0x00000200)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1                (0x00000100)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482                   (0x00000002)
+#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN         (0x00000001)
+
+/* defines for the Location field */
+#define MPI2_MANPAGE7_LOCATION_UNKNOWN                  (0x01)
+#define MPI2_MANPAGE7_LOCATION_INTERNAL                 (0x02)
+#define MPI2_MANPAGE7_LOCATION_EXTERNAL                 (0x04)
+#define MPI2_MANPAGE7_LOCATION_SWITCHABLE               (0x08)
+#define MPI2_MANPAGE7_LOCATION_AUTO                     (0x10)
+#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT              (0x20)
+#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED            (0x80)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumPhys at runtime.
+ */
+#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
+#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX  (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_7
+{
+    MPI2_CONFIG_PAGE_HEADER         Header;             /* 0x00 */
+    U32                             Reserved1;          /* 0x04 */
+    U32                             Reserved2;          /* 0x08 */
+    U32                             Flags;              /* 0x0C */
+    U8                              EnclosureName[16];  /* 0x10 */
+    U8                              NumPhys;            /* 0x20 */
+    U8                              Reserved3;          /* 0x21 */
+    U16                             Reserved4;          /* 0x22 */
+    MPI2_MANPAGE7_CONNECTOR_INFO    ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */
+} MPI2_CONFIG_PAGE_MAN_7,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
+  Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
+
+#define MPI2_MANUFACTURING7_PAGEVERSION                 (0x00)
+
+/* defines for the Flags field */
+#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO                (0x00000001)
+
+
+/*
+ * Generic structure to use for product-specific manufacturing pages
+ * (currently Manufacturing Page 8 through Manufacturing Page 31).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_PS
+{
+    MPI2_CONFIG_PAGE_HEADER         Header;             /* 0x00 */
+    U32                             ProductSpecificInfo;/* 0x04 */
+} MPI2_CONFIG_PAGE_MAN_PS,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS,
+  Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t;
+
+#define MPI2_MANUFACTURING8_PAGEVERSION                 (0x00)
+#define MPI2_MANUFACTURING9_PAGEVERSION                 (0x00)
+#define MPI2_MANUFACTURING10_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING11_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING12_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING13_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING14_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING15_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING16_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING17_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING18_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING19_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING20_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING21_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING22_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING23_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING24_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING25_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING26_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING27_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING28_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING29_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING30_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING31_PAGEVERSION                (0x00)
+
+
+/****************************************************************************
+*   IO Unit Config Pages
+****************************************************************************/
+
+/* IO Unit Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U64                     UniqueValue;                /* 0x04 */
+    MPI2_VERSION_UNION      NvdataVersionDefault;       /* 0x08 */
+    MPI2_VERSION_UNION      NvdataVersionPersistent;    /* 0x0A */
+} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
+  Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t;
+
+#define MPI2_IOUNITPAGE0_PAGEVERSION                    (0x02)
+
+
+/* IO Unit Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U32                     Flags;                      /* 0x04 */
+} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
+  Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t;
+
+#define MPI2_IOUNITPAGE1_PAGEVERSION                    (0x04)
+
+/* IO Unit Page 1 Flags defines */
+#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY    (0x00000800)
+#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE          (0x00000600)
+#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE        (0x00000000)
+#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE       (0x00000200)
+#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE     (0x00000400)
+#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE       (0x00000100)
+#define MPI2_IOUNITPAGE1_DISABLE_IR                     (0x00000040)
+#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
+#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID        (0x00000004)
+#define MPI2_IOUNITPAGE1_MULTI_PATHING                  (0x00000002)
+#define MPI2_IOUNITPAGE1_SINGLE_PATHING                 (0x00000000)
+
+
+/* IO Unit Page 3 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
+#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                                   /* 0x00 */
+    U8                      GPIOCount;                                /* 0x04 */
+    U8                      Reserved1;                                /* 0x05 */
+    U16                     Reserved2;                                /* 0x06 */
+    U16                     GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */
+} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
+  Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t;
+
+#define MPI2_IOUNITPAGE3_PAGEVERSION                    (0x01)
+
+/* defines for IO Unit Page 3 GPIOVal field */
+#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK             (0xFFFC)
+#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT            (2)
+#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF               (0x0000)
+#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON                (0x0001)
+
+
+/* IO Unit Page 5 */
+
+/*
+ * Upper layer code (drivers, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumDmaEngines at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
+#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                                     /* 0x00 */
+    U64                     RaidAcceleratorBufferBaseAddress;           /* 0x04 */
+    U64                     RaidAcceleratorBufferSize;                  /* 0x0C */
+    U64                     RaidAcceleratorControlBaseAddress;          /* 0x14 */
+    U8                      RAControlSize;                              /* 0x1C */
+    U8                      NumDmaEngines;                              /* 0x1D */
+    U8                      RAMinControlSize;                           /* 0x1E */
+    U8                      RAMaxControlSize;                           /* 0x1F */
+    U32                     Reserved1;                                  /* 0x20 */
+    U32                     Reserved2;                                  /* 0x24 */
+    U32                     Reserved3;                                  /* 0x28 */
+    U32                     DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /* 0x2C */
+} MPI2_CONFIG_PAGE_IO_UNIT_5, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
+  Mpi2IOUnitPage5_t, MPI2_POINTER pMpi2IOUnitPage5_t;
+
+#define MPI2_IOUNITPAGE5_PAGEVERSION                    (0x00)
+
+/* defines for IO Unit Page 5 DmaEngineCapabilities field */
+#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS      (0xFF00)
+#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS     (16)
+
+#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP                   (0x0008)
+#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION      (0x0004)
+#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING                (0x0002)
+#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION             (0x0001)
+
+
+/* IO Unit Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                                 /* 0x00 */
+    U16                     Flags;                                  /* 0x04 */
+    U8                      RAHostControlSize;                      /* 0x06 */
+    U8                      Reserved0;                              /* 0x07 */
+    U64                     RaidAcceleratorHostControlBaseAddress;  /* 0x08 */
+    U32                     Reserved1;                              /* 0x10 */
+    U32                     Reserved2;                              /* 0x14 */
+    U32                     Reserved3;                              /* 0x18 */
+} MPI2_CONFIG_PAGE_IO_UNIT_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_6,
+  Mpi2IOUnitPage6_t, MPI2_POINTER pMpi2IOUnitPage6_t;
+
+#define MPI2_IOUNITPAGE6_PAGEVERSION                    (0x00)
+
+/* defines for IO Unit Page 6 Flags field */
+#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR  (0x0001)
+
+
+/* IO Unit Page 7 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                                 /* 0x00 */
+    U16                     Reserved1;                              /* 0x04 */
+    U8                      PCIeWidth;                              /* 0x06 */
+    U8                      PCIeSpeed;                              /* 0x07 */
+    U32                     ProcessorState;                         /* 0x08 */
+    U32                     Reserved2;                              /* 0x0C */
+    U16                     IOCTemperature;                         /* 0x10 */
+    U8                      IOCTemperatureUnits;                    /* 0x12 */
+    U8                      IOCSpeed;                               /* 0x13 */
+    U32                     Reserved3;                              /* 0x14 */
+} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
+  Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
+
+#define MPI2_IOUNITPAGE7_PAGEVERSION                    (0x00)
+
+/* defines for IO Unit Page 7 PCIeWidth field */
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1              (0x01)
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2              (0x02)
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4              (0x04)
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8              (0x08)
+
+/* defines for IO Unit Page 7 PCIeSpeed field */
+#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS        (0x00)
+#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS        (0x01)
+#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS        (0x02)
+
+/* defines for IO Unit Page 7 ProcessorState field */
+#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND         (0x0000000F)
+#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND        (0)
+
+#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT         (0x00)
+#define MPI2_IOUNITPAGE7_PSTATE_DISABLED            (0x01)
+#define MPI2_IOUNITPAGE7_PSTATE_ENABLED             (0x02)
+
+/* defines for IO Unit Page 7 IOCTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT       (0x00)
+#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT        (0x01)
+#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS           (0x02)
+
+/* defines for IO Unit Page 7 IOCSpeed field */
+#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL             (0x01)
+#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF             (0x02)
+#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER          (0x04)
+#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH           (0x08)
+
+
+
+/****************************************************************************
+*   IOC Config Pages
+****************************************************************************/
+
+/* IOC Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_0
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U32                     Reserved1;                  /* 0x04 */
+    U32                     Reserved2;                  /* 0x08 */
+    U16                     VendorID;                   /* 0x0C */
+    U16                     DeviceID;                   /* 0x0E */
+    U8                      RevisionID;                 /* 0x10 */
+    U8                      Reserved3;                  /* 0x11 */
+    U16                     Reserved4;                  /* 0x12 */
+    U32                     ClassCode;                  /* 0x14 */
+    U16                     SubsystemVendorID;          /* 0x18 */
+    U16                     SubsystemID;                /* 0x1A */
+} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0,
+  Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t;
+
+#define MPI2_IOCPAGE0_PAGEVERSION                       (0x02)
+
+
+/* IOC Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_1
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U32                     Flags;                      /* 0x04 */
+    U32                     CoalescingTimeout;          /* 0x08 */
+    U8                      CoalescingDepth;            /* 0x0C */
+    U8                      PCISlotNum;                 /* 0x0D */
+    U8                      PCIBusNum;                  /* 0x0E */
+    U8                      PCIDomainSegment;           /* 0x0F */
+    U32                     Reserved1;                  /* 0x10 */
+    U32                     Reserved2;                  /* 0x14 */
+} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1,
+  Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t;
+
+#define MPI2_IOCPAGE1_PAGEVERSION                       (0x05)
+
+/* defines for IOC Page 1 Flags field */
+#define MPI2_IOCPAGE1_REPLY_COALESCING                  (0x00000001)
+
+#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN                (0xFF)
+#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN                 (0xFF)
+#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN                 (0xFF)
+
+/* IOC Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_6
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                         /* 0x00 */
+    U32                     CapabilitiesFlags;              /* 0x04 */
+    U8                      MaxDrivesRAID0;                 /* 0x08 */
+    U8                      MaxDrivesRAID1;                 /* 0x09 */
+    U8                      MaxDrivesRAID1E;                /* 0x0A */
+    U8                      MaxDrivesRAID10;                /* 0x0B */
+    U8                      MinDrivesRAID0;                 /* 0x0C */
+    U8                      MinDrivesRAID1;                 /* 0x0D */
+    U8                      MinDrivesRAID1E;                /* 0x0E */
+    U8                      MinDrivesRAID10;                /* 0x0F */
+    U32                     Reserved1;                      /* 0x10 */
+    U8                      MaxGlobalHotSpares;             /* 0x14 */
+    U8                      MaxPhysDisks;                   /* 0x15 */
+    U8                      MaxVolumes;                     /* 0x16 */
+    U8                      MaxConfigs;                     /* 0x17 */
+    U8                      MaxOCEDisks;                    /* 0x18 */
+    U8                      Reserved2;                      /* 0x19 */
+    U16                     Reserved3;                      /* 0x1A */
+    U32                     SupportedStripeSizeMapRAID0;    /* 0x1C */
+    U32                     SupportedStripeSizeMapRAID1E;   /* 0x20 */
+    U32                     SupportedStripeSizeMapRAID10;   /* 0x24 */
+    U32                     Reserved4;                      /* 0x28 */
+    U32                     Reserved5;                      /* 0x2C */
+    U16                     DefaultMetadataSize;            /* 0x30 */
+    U16                     Reserved6;                      /* 0x32 */
+    U16                     MaxBadBlockTableEntries;        /* 0x34 */
+    U16                     Reserved7;                      /* 0x36 */
+    U32                     IRNvsramVersion;                /* 0x38 */
+} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6,
+  Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t;
+
+#define MPI2_IOCPAGE6_PAGEVERSION                       (0x04)
+
+/* defines for IOC Page 6 CapabilitiesFlags */
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT          (0x00000010)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT           (0x00000008)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT          (0x00000004)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT           (0x00000002)
+#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE        (0x00000001)
+
+
+/* IOC Page 7 */
+
+#define MPI2_IOCPAGE7_EVENTMASK_WORDS       (4)
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_7
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U32                     Reserved1;                  /* 0x04 */
+    U32                     EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
+    U16                     SASBroadcastPrimitiveMasks; /* 0x18 */
+    U16                     Reserved2;                  /* 0x1A */
+    U32                     Reserved3;                  /* 0x1C */
+} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
+  Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
+
+#define MPI2_IOCPAGE7_PAGEVERSION                       (0x01)
+
+
+/* IOC Page 8 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_8
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U8                      NumDevsPerEnclosure;        /* 0x04 */
+    U8                      Reserved1;                  /* 0x05 */
+    U16                     Reserved2;                  /* 0x06 */
+    U16                     MaxPersistentEntries;       /* 0x08 */
+    U16                     MaxNumPhysicalMappedIDs;    /* 0x0A */
+    U16                     Flags;                      /* 0x0C */
+    U16                     Reserved3;                  /* 0x0E */
+    U16                     IRVolumeMappingFlags;       /* 0x10 */
+    U16                     Reserved4;                  /* 0x12 */
+    U32                     Reserved5;                  /* 0x14 */
+} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8,
+  Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t;
+
+#define MPI2_IOCPAGE8_PAGEVERSION                       (0x00)
+
+/* defines for IOC Page 8 Flags field */
+#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1             (0x00000020)
+#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0         (0x00000010)
+
+#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE           (0x0000000E)
+#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING  (0x00000000)
+#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING      (0x00000002)
+
+#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING  (0x00000001)
+#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING   (0x00000000)
+
+/* defines for IOC Page 8 IRVolumeMappingFlags */
+#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE  (0x00000003)
+#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING        (0x00000000)
+#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING       (0x00000001)
+
+
+/****************************************************************************
+*   BIOS Config Pages
+****************************************************************************/
+
+/* BIOS Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_1
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U32                     BiosOptions;                /* 0x04 */
+    U32                     IOCSettings;                /* 0x08 */
+    U32                     Reserved1;                  /* 0x0C */
+    U32                     DeviceSettings;             /* 0x10 */
+    U16                     NumberOfDevices;            /* 0x14 */
+    U16                     Reserved2;                  /* 0x16 */
+    U16                     IOTimeoutBlockDevicesNonRM; /* 0x18 */
+    U16                     IOTimeoutSequential;        /* 0x1A */
+    U16                     IOTimeoutOther;             /* 0x1C */
+    U16                     IOTimeoutBlockDevicesRM;    /* 0x1E */
+} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1,
+  Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t;
+
+#define MPI2_BIOSPAGE1_PAGEVERSION                      (0x04)
+
+/* values for BIOS Page 1 BiosOptions field */
+#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS             (0x00000001)
+
+/* values for BIOS Page 1 IOCSettings field */
+#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE      (0x00030000)
+#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT       (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT          (0x00010000)
+
+#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING           (0x000000C0)
+#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING           (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING           (0x00000040)
+#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING          (0x00000080)
+
+#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT      (0x00000030)
+#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT                (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT              (0x00000010)
+#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT                (0x00000020)
+#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT               (0x00000030)
+
+#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS             (0x00000008)
+
+/* values for BIOS Page 1 DeviceSettings field */
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING     (0x00000010)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN           (0x00000008)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN            (0x00000004)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN        (0x00000002)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN         (0x00000001)
+
+
+/* BIOS Page 2 */
+
+typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER
+{
+    U32         Reserved1;                              /* 0x00 */
+    U32         Reserved2;                              /* 0x04 */
+    U32         Reserved3;                              /* 0x08 */
+    U32         Reserved4;                              /* 0x0C */
+    U32         Reserved5;                              /* 0x10 */
+    U32         Reserved6;                              /* 0x14 */
+} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
+  MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
+  Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t;
+
+typedef struct _MPI2_BOOT_DEVICE_SAS_WWID
+{
+    U64         SASAddress;                             /* 0x00 */
+    U8          LUN[8];                                 /* 0x08 */
+    U32         Reserved1;                              /* 0x10 */
+    U32         Reserved2;                              /* 0x14 */
+} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID,
+  Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t;
+
+typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT
+{
+    U64         EnclosureLogicalID;                     /* 0x00 */
+    U32         Reserved1;                              /* 0x08 */
+    U32         Reserved2;                              /* 0x0C */
+    U16         SlotNumber;                             /* 0x10 */
+    U16         Reserved3;                              /* 0x12 */
+    U32         Reserved4;                              /* 0x14 */
+} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
+  MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
+  Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t;
+
+typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME
+{
+    U64         DeviceName;                             /* 0x00 */
+    U8          LUN[8];                                 /* 0x08 */
+    U32         Reserved1;                              /* 0x10 */
+    U32         Reserved2;                              /* 0x14 */
+} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
+  Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t;
+
+typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE
+{
+    MPI2_BOOT_DEVICE_ADAPTER_ORDER  AdapterOrder;
+    MPI2_BOOT_DEVICE_SAS_WWID       SasWwid;
+    MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
+    MPI2_BOOT_DEVICE_DEVICE_NAME    DeviceName;
+} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
+  Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t;
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_2
+{
+    MPI2_CONFIG_PAGE_HEADER     Header;                 /* 0x00 */
+    U32                         Reserved1;              /* 0x04 */
+    U32                         Reserved2;              /* 0x08 */
+    U32                         Reserved3;              /* 0x0C */
+    U32                         Reserved4;              /* 0x10 */
+    U32                         Reserved5;              /* 0x14 */
+    U32                         Reserved6;              /* 0x18 */
+    U8                          ReqBootDeviceForm;      /* 0x1C */
+    U8                          Reserved7;              /* 0x1D */
+    U16                         Reserved8;              /* 0x1E */
+    MPI2_BIOSPAGE2_BOOT_DEVICE  RequestedBootDevice;    /* 0x20 */
+    U8                          ReqAltBootDeviceForm;   /* 0x38 */
+    U8                          Reserved9;              /* 0x39 */
+    U16                         Reserved10;             /* 0x3A */
+    MPI2_BIOSPAGE2_BOOT_DEVICE  RequestedAltBootDevice; /* 0x3C */
+    U8                          CurrentBootDeviceForm;  /* 0x58 */
+    U8                          Reserved11;             /* 0x59 */
+    U16                         Reserved12;             /* 0x5A */
+    MPI2_BIOSPAGE2_BOOT_DEVICE  CurrentBootDevice;      /* 0x58 */
+} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2,
+  Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t;
+
+#define MPI2_BIOSPAGE2_PAGEVERSION                      (0x04)
+
+/* values for BIOS Page 2 BootDeviceForm fields */
+#define MPI2_BIOSPAGE2_FORM_MASK                        (0x0F)
+#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED         (0x00)
+#define MPI2_BIOSPAGE2_FORM_SAS_WWID                    (0x05)
+#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT              (0x06)
+#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME                 (0x07)
+
+
+/* BIOS Page 3 */
+
+typedef struct _MPI2_ADAPTER_INFO
+{
+    U8      PciBusNumber;                               /* 0x00 */
+    U8      PciDeviceAndFunctionNumber;                 /* 0x01 */
+    U16     AdapterFlags;                               /* 0x02 */
+} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO,
+  Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t;
+
+#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED                (0x0001)
+#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS             (0x0002)
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_3
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U32                     GlobalFlags;                /* 0x04 */
+    U32                     BiosVersion;                /* 0x08 */
+    MPI2_ADAPTER_INFO       AdapterOrder[4];            /* 0x0C */
+    U32                     Reserved1;                  /* 0x1C */
+} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3,
+  Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t;
+
+#define MPI2_BIOSPAGE3_PAGEVERSION                      (0x00)
+
+/* values for BIOS Page 3 GlobalFlags */
+#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR             (0x00000002)
+#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE             (0x00000004)
+#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE        (0x00000010)
+
+#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK      (0x000000E0)
+#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY      (0x00000000)
+#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY            (0x00000020)
+#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY        (0x00000040)
+
+
+/* BIOS Page 4 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
+#define MPI2_BIOS_PAGE_4_PHY_ENTRIES        (1)
+#endif
+
+typedef struct _MPI2_BIOS4_ENTRY
+{
+    U64                     ReassignmentWWID;       /* 0x00 */
+    U64                     ReassignmentDeviceName; /* 0x08 */
+} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY,
+  Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_4
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                             /* 0x00 */
+    U8                      NumPhys;                            /* 0x04 */
+    U8                      Reserved1;                          /* 0x05 */
+    U16                     Reserved2;                          /* 0x06 */
+    MPI2_BIOS4_ENTRY        Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES];  /* 0x08 */
+} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4,
+  Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t;
+
+#define MPI2_BIOSPAGE4_PAGEVERSION                      (0x01)
+
+
+/****************************************************************************
+*   RAID Volume Config Pages
+****************************************************************************/
+
+/* RAID Volume Page 0 */
+
+typedef struct _MPI2_RAIDVOL0_PHYS_DISK
+{
+    U8                      RAIDSetNum;                 /* 0x00 */
+    U8                      PhysDiskMap;                /* 0x01 */
+    U8                      PhysDiskNum;                /* 0x02 */
+    U8                      Reserved;                   /* 0x03 */
+} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK,
+  Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t;
+
+/* defines for the PhysDiskMap field */
+#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY                  (0x01)
+#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY                (0x02)
+
+typedef struct _MPI2_RAIDVOL0_SETTINGS
+{
+    U16                     Settings;                   /* 0x00 */
+    U8                      HotSparePool;               /* 0x01 */
+    U8                      Reserved;                   /* 0x02 */
+} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS,
+  Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t;
+
+/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
+#define MPI2_RAID_HOT_SPARE_POOL_0                      (0x01)
+#define MPI2_RAID_HOT_SPARE_POOL_1                      (0x02)
+#define MPI2_RAID_HOT_SPARE_POOL_2                      (0x04)
+#define MPI2_RAID_HOT_SPARE_POOL_3                      (0x08)
+#define MPI2_RAID_HOT_SPARE_POOL_4                      (0x10)
+#define MPI2_RAID_HOT_SPARE_POOL_5                      (0x20)
+#define MPI2_RAID_HOT_SPARE_POOL_6                      (0x40)
+#define MPI2_RAID_HOT_SPARE_POOL_7                      (0x80)
+
+/* RAID Volume Page 0 VolumeSettings defines */
+#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX     (0x0008)
+#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
+
+#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING        (0x0003)
+#define MPI2_RAIDVOL0_SETTING_UNCHANGED                 (0x0000)
+#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING     (0x0001)
+#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING      (0x0002)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
+#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX       (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U16                     DevHandle;                  /* 0x04 */
+    U8                      VolumeState;                /* 0x06 */
+    U8                      VolumeType;                 /* 0x07 */
+    U32                     VolumeStatusFlags;          /* 0x08 */
+    MPI2_RAIDVOL0_SETTINGS  VolumeSettings;             /* 0x0C */
+    U64                     MaxLBA;                     /* 0x10 */
+    U32                     StripeSize;                 /* 0x18 */
+    U16                     BlockSize;                  /* 0x1C */
+    U16                     Reserved1;                  /* 0x1E */
+    U8                      SupportedPhysDisks;         /* 0x20 */
+    U8                      ResyncRate;                 /* 0x21 */
+    U16                     DataScrubDuration;          /* 0x22 */
+    U8                      NumPhysDisks;               /* 0x24 */
+    U8                      Reserved2;                  /* 0x25 */
+    U8                      Reserved3;                  /* 0x26 */
+    U8                      InactiveStatus;             /* 0x27 */
+    MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */
+} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
+  Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t;
+
+#define MPI2_RAIDVOLPAGE0_PAGEVERSION           (0x0A)
+
+/* values for RAID VolumeState */
+#define MPI2_RAID_VOL_STATE_MISSING                         (0x00)
+#define MPI2_RAID_VOL_STATE_FAILED                          (0x01)
+#define MPI2_RAID_VOL_STATE_INITIALIZING                    (0x02)
+#define MPI2_RAID_VOL_STATE_ONLINE                          (0x03)
+#define MPI2_RAID_VOL_STATE_DEGRADED                        (0x04)
+#define MPI2_RAID_VOL_STATE_OPTIMAL                         (0x05)
+
+/* values for RAID VolumeType */
+#define MPI2_RAID_VOL_TYPE_RAID0                            (0x00)
+#define MPI2_RAID_VOL_TYPE_RAID1E                           (0x01)
+#define MPI2_RAID_VOL_TYPE_RAID1                            (0x02)
+#define MPI2_RAID_VOL_TYPE_RAID10                           (0x05)
+#define MPI2_RAID_VOL_TYPE_UNKNOWN                          (0xFF)
+
+/* values for RAID Volume Page 0 VolumeStatusFlags field */
+#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC            (0x02000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING        (0x01000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING               (0x00800000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING      (0x00400000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT      (0x00200000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB                (0x00100000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK         (0x00080000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION        (0x00040000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT           (0x00020000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS        (0x00010000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED               (0x00000040)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE              (0x00000020)
+#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR          (0x00000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR        (0x00000010)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL      (0x00000008)
+#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE           (0x00000004)
+#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED                  (0x00000002)
+#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED                   (0x00000001)
+
+/* values for RAID Volume Page 0 SupportedPhysDisks field */
+#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS             (0x08)
+#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS                    (0x04)
+#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL                  (0x02)
+#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL                 (0x01)
+
+/* values for RAID Volume Page 0 InactiveStatus field */
+#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE                  (0x00)
+#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE           (0x01)
+#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE           (0x02)
+#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE    (0x03)
+#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE             (0x04)
+#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE    (0x05)
+#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED                (0x06)
+
+
+/* RAID Volume Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1
+{
+    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
+    U16                     DevHandle;                  /* 0x04 */
+    U16                     Reserved0;                  /* 0x06 */
+    U8                      GUID[24];                   /* 0x08 */
+    U8                      Name[16];                   /* 0x20 */
+    U64                     WWID;                       /* 0x30 */
+    U32                     Reserved1;                  /* 0x38 */
+    U32                     Reserved2;                  /* 0x3C */
+} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
+  Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t;
+
+#define MPI2_RAIDVOLPAGE1_PAGEVERSION           (0x03)
+
+
+/****************************************************************************
+*   RAID Physical Disk Config Pages
+****************************************************************************/
+
+/* RAID Physical Disk Page 0 */
+
+typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS
+{
+    U16                     Reserved1;                  /* 0x00 */
+    U8                      HotSparePool;               /* 0x02 */
+    U8                      Reserved2;                  /* 0x03 */
+} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
+  Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t;
+
+/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
+
+typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA
+{
+    U8                      VendorID[8];                /* 0x00 */
+    U8                      ProductID[16];              /* 0x08 */
+    U8                      ProductRevLevel[4];         /* 0x18 */
+    U8                      SerialNum[32];              /* 0x1C */
+} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
+  MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
+  Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t;
+
+typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0
+{
+    MPI2_CONFIG_PAGE_HEADER         Header;                     /* 0x00 */
+    U16                             DevHandle;                  /* 0x04 */
+    U8                              Reserved1;                  /* 0x06 */
+    U8                              PhysDiskNum;                /* 0x07 */
+    MPI2_RAIDPHYSDISK0_SETTINGS     PhysDiskSettings;           /* 0x08 */
+    U32                             Reserved2;                  /* 0x0C */
+    MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData;                /* 0x10 */
+    U32                             Reserved3;                  /* 0x4C */
+    U8                              PhysDiskState;              /* 0x50 */
+    U8                              OfflineReason;              /* 0x51 */
+    U8                              IncompatibleReason;         /* 0x52 */
+    U8                              PhysDiskAttributes;         /* 0x53 */
+    U32                             PhysDiskStatusFlags;        /* 0x54 */
+    U64                             DeviceMaxLBA;               /* 0x58 */
+    U64                             HostMaxLBA;                 /* 0x60 */
+    U64                             CoercedMaxLBA;              /* 0x68 */
+    U16                             BlockSize;                  /* 0x70 */
+    U16                             Reserved5;                  /* 0x72 */
+    U32                             Reserved6;                  /* 0x74 */
+} MPI2_CONFIG_PAGE_RD_PDISK_0,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
+  Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t;
+
+#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION          (0x05)
+
+/* PhysDiskState defines */
+#define MPI2_RAID_PD_STATE_NOT_CONFIGURED               (0x00)
+#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE               (0x01)
+#define MPI2_RAID_PD_STATE_OFFLINE                      (0x02)
+#define MPI2_RAID_PD_STATE_ONLINE                       (0x03)
+#define MPI2_RAID_PD_STATE_HOT_SPARE                    (0x04)
+#define MPI2_RAID_PD_STATE_DEGRADED                     (0x05)
+#define MPI2_RAID_PD_STATE_REBUILDING                   (0x06)
+#define MPI2_RAID_PD_STATE_OPTIMAL                      (0x07)
+
+/* OfflineReason defines */
+#define MPI2_PHYSDISK0_ONLINE                           (0x00)
+#define MPI2_PHYSDISK0_OFFLINE_MISSING                  (0x01)
+#define MPI2_PHYSDISK0_OFFLINE_FAILED                   (0x03)
+#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING             (0x04)
+#define MPI2_PHYSDISK0_OFFLINE_REQUESTED                (0x05)
+#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED         (0x06)
+#define MPI2_PHYSDISK0_OFFLINE_OTHER                    (0xFF)
+
+/* IncompatibleReason defines */
+#define MPI2_PHYSDISK0_COMPATIBLE                       (0x00)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL            (0x01)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE           (0x02)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA             (0x03)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD   (0x04)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA    (0x05)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN             (0xFF)
+
+/* PhysDiskAttributes defines */
+#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE         (0x08)
+#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE           (0x04)
+#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL              (0x02)
+#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL             (0x01)
+
+/* PhysDiskStatusFlags defines */
+#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED        (0x00000040)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET           (0x00000020)
+#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED  (0x00000010)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS     (0x00000000)
+#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
+#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME      (0x00000004)
+#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED             (0x00000002)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC          (0x00000001)
+
+
+/* RAID Physical Disk Page 1 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhysDiskPaths at runtime.
+ */
+#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
+#define MPI2_RAID_PHYS_DISK1_PATH_MAX   (1)
+#endif
+
+typedef struct _MPI2_RAIDPHYSDISK1_PATH
+{
+    U16             DevHandle;          /* 0x00 */
+    U16             Reserved1;          /* 0x02 */
+    U64             WWID;               /* 0x04 */
+    U64             OwnerWWID;          /* 0x0C */
+    U8              OwnerIdentifier;    /* 0x14 */
+    U8              Reserved2;          /* 0x15 */
+    U16             Flags;              /* 0x16 */
+} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH,
+  Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t;
+
+/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
+#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY        (0x0004)
+#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN         (0x0002)
+#define MPI2_RAID_PHYSDISK1_FLAG_INVALID        (0x0001)
+
+typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
+{
+    MPI2_CONFIG_PAGE_HEADER         Header;                     /* 0x00 */
+    U8                              NumPhysDiskPaths;           /* 0x04 */
+    U8                              PhysDiskNum;                /* 0x05 */
+    U16                             Reserved1;                  /* 0x06 */
+    U32                             Reserved2;                  /* 0x08 */
+    MPI2_RAIDPHYSDISK1_PATH         PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */
+} MPI2_CONFIG_PAGE_RD_PDISK_1,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
+  Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t;
+
+#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION          (0x02)
+
+
+/****************************************************************************
+*   values for fields used by several types of SAS Config Pages
+****************************************************************************/
+
+/* values for NegotiatedLinkRates fields */
+#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL             (0xF0)
+#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL            (4)
+#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL            (0x0F)
+/* link rates used for Negotiated Physical and Logical Link Rate */
+#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE        (0x00)
+#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED             (0x01)
+#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED       (0x02)
+#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE        (0x03)
+#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR            (0x04)
+#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS    (0x05)
+#define MPI2_SAS_NEG_LINK_RATE_1_5                      (0x08)
+#define MPI2_SAS_NEG_LINK_RATE_3_0                      (0x09)
+#define MPI2_SAS_NEG_LINK_RATE_6_0                      (0x0A)
+
+
+/* values for AttachedPhyInfo fields */
+#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT       (0x00000040)
+#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS        (0x00000020)
+#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE           (0x00000010)
+
+#define MPI2_SAS_APHYINFO_REASON_MASK                   (0x0000000F)
+#define MPI2_SAS_APHYINFO_REASON_UNKNOWN                (0x00000000)
+#define MPI2_SAS_APHYINFO_REASON_POWER_ON               (0x00000001)
+#define MPI2_SAS_APHYINFO_REASON_HARD_RESET             (0x00000002)
+#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL        (0x00000003)
+#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC           (0x00000004)
+#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ       (0x00000005)
+#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER    (0x00000006)
+#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT          (0x00000007)
+#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED       (0x00000008)
+
+
+/* values for PhyInfo fields */
+#define MPI2_SAS_PHYINFO_PHY_VACANT                     (0x80000000)
+
+#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK       (0x18000000)
+#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE               (0x00000000)
+#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL              (0x08000000)
+#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER              (0x10000000)
+
+#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS       (0x04000000)
+#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT        (0x02000000)
+#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS               (0x01000000)
+#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT          (0x00400000)
+#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS                   (0x00200000)
+#define MPI2_SAS_PHYINFO_ZONING_ENABLED                 (0x00100000)
+
+#define MPI2_SAS_PHYINFO_REASON_MASK                    (0x000F0000)
+#define MPI2_SAS_PHYINFO_REASON_UNKNOWN                 (0x00000000)
+#define MPI2_SAS_PHYINFO_REASON_POWER_ON                (0x00010000)
+#define MPI2_SAS_PHYINFO_REASON_HARD_RESET              (0x00020000)
+#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL         (0x00030000)
+#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC            (0x00040000)
+#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ        (0x00050000)
+#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER     (0x00060000)
+#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT           (0x00070000)
+#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED        (0x00080000)
+
+#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED         (0x00008000)
+#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE               (0x00004000)
+#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT     (0x00002000)
+#define MPI2_SAS_PHYINFO_VIRTUAL_PHY                    (0x00001000)
+
+#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME      (0x00000F00)
+#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME     (8)
+
+#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE         (0x000000F0)
+#define MPI2_SAS_PHYINFO_DIRECT_ROUTING                 (0x00000000)
+#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING            (0x00000010)
+#define MPI2_SAS_PHYINFO_TABLE_ROUTING                  (0x00000020)
+
+
+/* values for SAS ProgrammedLinkRate fields */
+#define MPI2_SAS_PRATE_MAX_RATE_MASK                    (0xF0)
+#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE        (0x00)
+#define MPI2_SAS_PRATE_MAX_RATE_1_5                     (0x80)
+#define MPI2_SAS_PRATE_MAX_RATE_3_0                     (0x90)
+#define MPI2_SAS_PRATE_MAX_RATE_6_0                     (0xA0)
+#define MPI2_SAS_PRATE_MIN_RATE_MASK                    (0x0F)
+#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE        (0x00)
+#define MPI2_SAS_PRATE_MIN_RATE_1_5                     (0x08)
+#define MPI2_SAS_PRATE_MIN_RATE_3_0                     (0x09)
+#define MPI2_SAS_PRATE_MIN_RATE_6_0                     (0x0A)
+
+
+/* values for SAS HwLinkRate fields */
+#define MPI2_SAS_HWRATE_MAX_RATE_MASK                   (0xF0)
+#define MPI2_SAS_HWRATE_MAX_RATE_1_5                    (0x80)
+#define MPI2_SAS_HWRATE_MAX_RATE_3_0                    (0x90)
+#define MPI2_SAS_HWRATE_MAX_RATE_6_0                    (0xA0)
+#define MPI2_SAS_HWRATE_MIN_RATE_MASK                   (0x0F)
+#define MPI2_SAS_HWRATE_MIN_RATE_1_5                    (0x08)
+#define MPI2_SAS_HWRATE_MIN_RATE_3_0                    (0x09)
+#define MPI2_SAS_HWRATE_MIN_RATE_6_0                    (0x0A)
+
+
+
+/****************************************************************************
+*   SAS IO Unit Config Pages
+****************************************************************************/
+
+/* SAS IO Unit Page 0 */
+
+typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA
+{
+    U8          Port;                   /* 0x00 */
+    U8          PortFlags;              /* 0x01 */
+    U8          PhyFlags;               /* 0x02 */
+    U8          NegotiatedLinkRate;     /* 0x03 */
+    U32         ControllerPhyDeviceInfo;/* 0x04 */
+    U16         AttachedDevHandle;      /* 0x08 */
+    U16         ControllerDevHandle;    /* 0x0A */
+    U32         DiscoveryStatus;        /* 0x0C */
+    U32         Reserved;               /* 0x10 */
+} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
+  Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
+#define MPI2_SAS_IOUNIT0_PHY_MAX        (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                             /* 0x00 */
+    U32                                 Reserved1;                          /* 0x08 */
+    U8                                  NumPhys;                            /* 0x0C */
+    U8                                  Reserved2;                          /* 0x0D */
+    U16                                 Reserved3;                          /* 0x0E */
+    MPI2_SAS_IO_UNIT0_PHY_DATA          PhyData[MPI2_SAS_IOUNIT0_PHY_MAX];  /* 0x10 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_0,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
+  Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t;
+
+#define MPI2_SASIOUNITPAGE0_PAGEVERSION                     (0x05)
+
+/* values for SAS IO Unit Page 0 PortFlags */
+#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS     (0x08)
+#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG          (0x01)
+
+/* values for SAS IO Unit Page 0 PhyFlags */
+#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED             (0x10)
+#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED               (0x08)
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
+
+/* values for SAS IO Unit Page 0 DiscoveryStatus */
+#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED            (0x80000000)
+#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED             (0x40000000)
+#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED               (0x20000000)
+#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED             (0x10000000)
+#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR             (0x08000000)
+#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE    (0x00008000)
+#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE            (0x00004000)
+#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN                (0x00002000)
+#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK        (0x00001000)
+#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
+#define MPI2_SASIOUNIT0_DS_TABLE_LINK                       (0x00000400)
+#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK                 (0x00000200)
+#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR                    (0x00000100)
+#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED              (0x00000080)
+#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST                  (0x00000040)
+#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES                (0x00000020)
+#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT                      (0x00000010)
+#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS                   (0x00000004)
+#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE             (0x00000002)
+#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED                    (0x00000001)
+
+
+/* SAS IO Unit Page 1 */
+
+typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA
+{
+    U8          Port;                       /* 0x00 */
+    U8          PortFlags;                  /* 0x01 */
+    U8          PhyFlags;                   /* 0x02 */
+    U8          MaxMinLinkRate;             /* 0x03 */
+    U32         ControllerPhyDeviceInfo;    /* 0x04 */
+    U16         MaxTargetPortConnectTime;   /* 0x08 */
+    U16         Reserved1;                  /* 0x0A */
+} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
+  Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
+#define MPI2_SAS_IOUNIT1_PHY_MAX        (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                             /* 0x00 */
+    U16                                 ControlFlags;                       /* 0x08 */
+    U16                                 SASNarrowMaxQueueDepth;             /* 0x0A */
+    U16                                 AdditionalControlFlags;             /* 0x0C */
+    U16                                 SASWideMaxQueueDepth;               /* 0x0E */
+    U8                                  NumPhys;                            /* 0x10 */
+    U8                                  SATAMaxQDepth;                      /* 0x11 */
+    U8                                  ReportDeviceMissingDelay;           /* 0x12 */
+    U8                                  IODeviceMissingDelay;               /* 0x13 */
+    MPI2_SAS_IO_UNIT1_PHY_DATA          PhyData[MPI2_SAS_IOUNIT1_PHY_MAX];  /* 0x14 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_1,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
+  Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t;
+
+#define MPI2_SASIOUNITPAGE1_PAGEVERSION     (0x09)
+
+/* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST                    (0x8000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX                        (0x4000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX                        (0x2000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE                    (0x1000)
+
+#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT                    (0x0600)
+#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT                   (9)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH                    (0x0)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT                     (0x1)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT                    (0x2)
+
+#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED             (0x0080)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED                 (0x0040)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED                   (0x0020)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED                   (0x0010)
+#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL           (0x0008)
+#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL                 (0x0004)
+#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY                 (0x0002)
+#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION                   (0x0001)
+
+/* values for SAS IO Unit Page 1 AdditionalControlFlags */
+#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL          (0x0080)
+#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
+#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION        (0x0020)
+#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
+#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET  (0x0008)
+#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET   (0x0004)
+#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET     (0x0002)
+#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE               (0x0001)
+
+/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
+#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK                 (0x7F)
+#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16                      (0x80)
+
+/* values for SAS IO Unit Page 1 PortFlags */
+#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG                 (0x01)
+
+/* values for SAS IO Unit Page 1 PhyFlags */
+#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE                      (0x10)
+#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE                        (0x08)
+
+/* values for SAS IO Unit Page 1 MaxMinLinkRate */
+#define MPI2_SASIOUNIT1_MAX_RATE_MASK                               (0xF0)
+#define MPI2_SASIOUNIT1_MAX_RATE_1_5                                (0x80)
+#define MPI2_SASIOUNIT1_MAX_RATE_3_0                                (0x90)
+#define MPI2_SASIOUNIT1_MAX_RATE_6_0                                (0xA0)
+#define MPI2_SASIOUNIT1_MIN_RATE_MASK                               (0x0F)
+#define MPI2_SASIOUNIT1_MIN_RATE_1_5                                (0x08)
+#define MPI2_SASIOUNIT1_MIN_RATE_3_0                                (0x09)
+#define MPI2_SASIOUNIT1_MIN_RATE_6_0                                (0x0A)
+
+/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
+
+
+/* SAS IO Unit Page 4 */
+
+typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP
+{
+    U8          MaxTargetSpinup;            /* 0x00 */
+    U8          SpinupDelay;                /* 0x01 */
+    U16         Reserved1;                  /* 0x02 */
+} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
+  Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * four and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
+#define MPI2_SAS_IOUNIT4_PHY_MAX        (4)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                         /* 0x00 */
+    MPI2_SAS_IOUNIT4_SPINUP_GROUP       SpinupGroupParameters[4];       /* 0x08 */
+    U32                                 Reserved1;                      /* 0x18 */
+    U32                                 Reserved2;                      /* 0x1C */
+    U32                                 Reserved3;                      /* 0x20 */
+    U8                                  BootDeviceWaitTime;             /* 0x24 */
+    U8                                  Reserved4;                      /* 0x25 */
+    U16                                 Reserved5;                      /* 0x26 */
+    U8                                  NumPhys;                        /* 0x28 */
+    U8                                  PEInitialSpinupDelay;           /* 0x29 */
+    U8                                  PEReplyDelay;                   /* 0x2A */
+    U8                                  Flags;                          /* 0x2B */
+    U8                                  PHY[MPI2_SAS_IOUNIT4_PHY_MAX];  /* 0x2C */
+} MPI2_CONFIG_PAGE_SASIOUNIT_4,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
+  Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t;
+
+#define MPI2_SASIOUNITPAGE4_PAGEVERSION     (0x02)
+
+/* defines for Flags field */
+#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE               (0x01)
+
+/* defines for PHY field */
+#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK               (0x03)
+
+
+/* SAS IO Unit Page 5 */
+
+typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS
+{
+    U8          ControlFlags;               /* 0x00 */
+    U8          Reserved1;                  /* 0x01 */
+    U16         InactivityTimerExponent;    /* 0x02 */
+    U8          SATAPartialTimeout;         /* 0x04 */
+    U8          Reserved2;                  /* 0x05 */
+    U8          SATASlumberTimeout;         /* 0x06 */
+    U8          Reserved3;                  /* 0x07 */
+    U8          SASPartialTimeout;          /* 0x08 */
+    U8          Reserved4;                  /* 0x09 */
+    U8          SASSlumberTimeout;          /* 0x0A */
+    U8          Reserved5;                  /* 0x0B */
+} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
+  MPI2_POINTER PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
+  Mpi2SasIOUnit5PhyPmSettings_t, MPI2_POINTER pMpi2SasIOUnit5PhyPmSettings_t;
+
+/* defines for ControlFlags field */
+#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE      (0x08)
+#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE      (0x04)
+#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE     (0x02)
+#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE     (0x01)
+
+/* defines for InactivityTimerExponent field */
+#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER            (0x7000)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER           (12)
+#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL            (0x0700)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL           (8)
+#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER           (0x0070)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER          (4)
+#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL           (0x0007)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL          (0)
+
+#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS                 (7)
+#define MPI2_SASIOUNIT5_ITE_ONE_SECOND                  (6)
+#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS        (5)
+#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS            (4)
+#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND             (3)
+#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS        (2)
+#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS            (1)
+#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND             (0)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
+#define MPI2_SAS_IOUNIT5_PHY_MAX        (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                             /* 0x00 */
+    U8                                  NumPhys;                            /* 0x08 */
+    U8                                  Reserved1;                          /* 0x09 */
+    U16                                 Reserved2;                          /* 0x0A */
+    U32                                 Reserved3;                          /* 0x0C */
+    MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS   SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];  /* 0x10 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_5,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
+  Mpi2SasIOUnitPage5_t, MPI2_POINTER pMpi2SasIOUnitPage5_t;
+
+#define MPI2_SASIOUNITPAGE5_PAGEVERSION     (0x00)
+
+
+
+
+/****************************************************************************
+*   SAS Expander Config Pages
+****************************************************************************/
+
+/* SAS Expander Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U8                                  PhysicalPort;               /* 0x08 */
+    U8                                  ReportGenLength;            /* 0x09 */
+    U16                                 EnclosureHandle;            /* 0x0A */
+    U64                                 SASAddress;                 /* 0x0C */
+    U32                                 DiscoveryStatus;            /* 0x14 */
+    U16                                 DevHandle;                  /* 0x18 */
+    U16                                 ParentDevHandle;            /* 0x1A */
+    U16                                 ExpanderChangeCount;        /* 0x1C */
+    U16                                 ExpanderRouteIndexes;       /* 0x1E */
+    U8                                  NumPhys;                    /* 0x20 */
+    U8                                  SASLevel;                   /* 0x21 */
+    U16                                 Flags;                      /* 0x22 */
+    U16                                 STPBusInactivityTimeLimit;  /* 0x24 */
+    U16                                 STPMaxConnectTimeLimit;     /* 0x26 */
+    U16                                 STP_SMP_NexusLossTime;      /* 0x28 */
+    U16                                 MaxNumRoutedSasAddresses;   /* 0x2A */
+    U64                                 ActiveZoneManagerSASAddress;/* 0x2C */
+    U16                                 ZoneLockInactivityLimit;    /* 0x34 */
+    U16                                 Reserved1;                  /* 0x36 */
+    U8                                  TimeToReducedFunc;          /* 0x38 */
+    U8                                  InitialTimeToReducedFunc;   /* 0x39 */
+    U8                                  MaxReducedFuncTime;         /* 0x3A */
+    U8                                  Reserved2;                  /* 0x3B */
+} MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
+  Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t;
+
+#define MPI2_SASEXPANDER0_PAGEVERSION       (0x06)
+
+/* values for SAS Expander Page 0 DiscoveryStatus field */
+#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED         (0x80000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED          (0x40000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED            (0x20000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED          (0x10000000)
+#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR          (0x08000000)
+#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
+#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE         (0x00004000)
+#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN             (0x00002000)
+#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK     (0x00001000)
+#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE            (0x00000800)
+#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK                    (0x00000400)
+#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK              (0x00000200)
+#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR                 (0x00000100)
+#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED           (0x00000080)
+#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST               (0x00000040)
+#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES             (0x00000020)
+#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT                   (0x00000010)
+#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS                (0x00000004)
+#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE          (0x00000002)
+#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED                 (0x00000001)
+
+/* values for SAS Expander Page 0 Flags field */
+#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY      (0x2000)
+#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED                (0x1000)
+#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES    (0x0800)
+#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES     (0x0400)
+#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT             (0x0200)
+#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING             (0x0100)
+#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT     (0x0080)
+#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE       (0x0010)
+#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG              (0x0004)
+#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS         (0x0002)
+#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG         (0x0001)
+
+
+/* SAS Expander Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U8                                  PhysicalPort;               /* 0x08 */
+    U8                                  Reserved1;                  /* 0x09 */
+    U16                                 Reserved2;                  /* 0x0A */
+    U8                                  NumPhys;                    /* 0x0C */
+    U8                                  Phy;                        /* 0x0D */
+    U16                                 NumTableEntriesProgrammed;  /* 0x0E */
+    U8                                  ProgrammedLinkRate;         /* 0x10 */
+    U8                                  HwLinkRate;                 /* 0x11 */
+    U16                                 AttachedDevHandle;          /* 0x12 */
+    U32                                 PhyInfo;                    /* 0x14 */
+    U32                                 AttachedDeviceInfo;         /* 0x18 */
+    U16                                 ExpanderDevHandle;          /* 0x1C */
+    U8                                  ChangeCount;                /* 0x1E */
+    U8                                  NegotiatedLinkRate;         /* 0x1F */
+    U8                                  PhyIdentifier;              /* 0x20 */
+    U8                                  AttachedPhyIdentifier;      /* 0x21 */
+    U8                                  Reserved3;                  /* 0x22 */
+    U8                                  DiscoveryInfo;              /* 0x23 */
+    U32                                 AttachedPhyInfo;            /* 0x24 */
+    U8                                  ZoneGroup;                  /* 0x28 */
+    U8                                  SelfConfigStatus;           /* 0x29 */
+    U16                                 Reserved4;                  /* 0x2A */
+} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
+  Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t;
+
+#define MPI2_SASEXPANDER1_PAGEVERSION       (0x02)
+
+/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
+
+/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
+
+/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
+
+/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
+
+/* values for SAS Expander Page 1 DiscoveryInfo field */
+#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED    (0x04)
+#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE  (0x02)
+#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES  (0x01)
+
+
+/****************************************************************************
+*   SAS Device Config Pages
+****************************************************************************/
+
+/* SAS Device Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+    U16                                 Slot;                   /* 0x08 */
+    U16                                 EnclosureHandle;        /* 0x0A */
+    U64                                 SASAddress;             /* 0x0C */
+    U16                                 ParentDevHandle;        /* 0x14 */
+    U8                                  PhyNum;                 /* 0x16 */
+    U8                                  AccessStatus;           /* 0x17 */
+    U16                                 DevHandle;              /* 0x18 */
+    U8                                  AttachedPhyIdentifier;  /* 0x1A */
+    U8                                  ZoneGroup;              /* 0x1B */
+    U32                                 DeviceInfo;             /* 0x1C */
+    U16                                 Flags;                  /* 0x20 */
+    U8                                  PhysicalPort;           /* 0x22 */
+    U8                                  MaxPortConnections;     /* 0x23 */
+    U64                                 DeviceName;             /* 0x24 */
+    U8                                  PortGroups;             /* 0x2C */
+    U8                                  DmaGroup;               /* 0x2D */
+    U8                                  ControlGroup;           /* 0x2E */
+    U8                                  Reserved1;              /* 0x2F */
+    U32                                 Reserved2;              /* 0x30 */
+    U32                                 Reserved3;              /* 0x34 */
+} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
+  Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t;
+
+#define MPI2_SASDEVICE0_PAGEVERSION         (0x08)
+
+/* values for SAS Device Page 0 AccessStatus field */
+#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS                  (0x00)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED           (0x01)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED     (0x02)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT  (0x03)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION  (0x04)
+#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE      (0x05)
+#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE  (0x06)
+#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED             (0x07)
+/* specific values for SATA Init failures */
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN                (0x10)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT   (0x11)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG                   (0x12)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION         (0x13)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER            (0x14)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN                 (0x15)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN                (0x16)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN                (0x17)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION       (0x18)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE        (0x19)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX                    (0x1F)
+
+/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
+
+/* values for SAS Device Page 0 Flags field */
+#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE           (0x1000)
+#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE           (0x0800)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY     (0x0400)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE             (0x0200)
+#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE           (0x0100)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED     (0x0080)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED         (0x0040)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED           (0x0020)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED           (0x0010)
+#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH         (0x0008)
+#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT               (0x0001)
+
+
+/* SAS Device Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+    U32                                 Reserved1;              /* 0x08 */
+    U64                                 SASAddress;             /* 0x0C */
+    U32                                 Reserved2;              /* 0x14 */
+    U16                                 DevHandle;              /* 0x18 */
+    U16                                 Reserved3;              /* 0x1A */
+    U8                                  InitialRegDeviceFIS[20];/* 0x1C */
+} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
+  Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t;
+
+#define MPI2_SASDEVICE1_PAGEVERSION         (0x01)
+
+
+/****************************************************************************
+*   SAS PHY Config Pages
+****************************************************************************/
+
+/* SAS PHY Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+    U16                                 OwnerDevHandle;         /* 0x08 */
+    U16                                 Reserved1;              /* 0x0A */
+    U16                                 AttachedDevHandle;      /* 0x0C */
+    U8                                  AttachedPhyIdentifier;  /* 0x0E */
+    U8                                  Reserved2;              /* 0x0F */
+    U32                                 AttachedPhyInfo;        /* 0x10 */
+    U8                                  ProgrammedLinkRate;     /* 0x14 */
+    U8                                  HwLinkRate;             /* 0x15 */
+    U8                                  ChangeCount;            /* 0x16 */
+    U8                                  Flags;                  /* 0x17 */
+    U32                                 PhyInfo;                /* 0x18 */
+    U8                                  NegotiatedLinkRate;     /* 0x1C */
+    U8                                  Reserved3;              /* 0x1D */
+    U16                                 Reserved4;              /* 0x1E */
+} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
+  Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t;
+
+#define MPI2_SASPHY0_PAGEVERSION            (0x03)
+
+/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
+
+/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
+
+/* values for SAS PHY Page 0 Flags field */
+#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC             (0x01)
+
+/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
+
+
+/* SAS PHY Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U32                                 InvalidDwordCount;          /* 0x0C */
+    U32                                 RunningDisparityErrorCount; /* 0x10 */
+    U32                                 LossDwordSynchCount;        /* 0x14 */
+    U32                                 PhyResetProblemCount;       /* 0x18 */
+} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
+  Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t;
+
+#define MPI2_SASPHY1_PAGEVERSION            (0x01)
+
+
+/* SAS PHY Page 2 */
+
+typedef struct _MPI2_SASPHY2_PHY_EVENT
+{
+    U8          PhyEventCode;       /* 0x00 */
+    U8          Reserved1;          /* 0x01 */
+    U16         Reserved2;          /* 0x02 */
+    U32         PhyEventInfo;       /* 0x04 */
+} MPI2_SASPHY2_PHY_EVENT, MPI2_POINTER PTR_MPI2_SASPHY2_PHY_EVENT,
+  Mpi2SasPhy2PhyEvent_t, MPI2_POINTER pMpi2SasPhy2PhyEvent_t;
+
+/* use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */
+
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhyEvents at runtime.
+ */
+#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
+#define MPI2_SASPHY2_PHY_EVENT_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U8                                  NumPhyEvents;               /* 0x0C */
+    U8                                  Reserved2;                  /* 0x0D */
+    U16                                 Reserved3;                  /* 0x0E */
+    MPI2_SASPHY2_PHY_EVENT              PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /* 0x10 */
+} MPI2_CONFIG_PAGE_SAS_PHY_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
+  Mpi2SasPhyPage2_t, MPI2_POINTER pMpi2SasPhyPage2_t;
+
+#define MPI2_SASPHY2_PAGEVERSION            (0x00)
+
+
+/* SAS PHY Page 3 */
+
+typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG
+{
+    U8          PhyEventCode;       /* 0x00 */
+    U8          Reserved1;          /* 0x01 */
+    U16         Reserved2;          /* 0x02 */
+    U8          CounterType;        /* 0x04 */
+    U8          ThresholdWindow;    /* 0x05 */
+    U8          TimeUnits;          /* 0x06 */
+    U8          Reserved3;          /* 0x07 */
+    U32         EventThreshold;     /* 0x08 */
+    U16         ThresholdFlags;     /* 0x0C */
+    U16         Reserved4;          /* 0x0E */
+} MPI2_SASPHY3_PHY_EVENT_CONFIG, MPI2_POINTER PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG,
+  Mpi2SasPhy3PhyEventConfig_t, MPI2_POINTER pMpi2SasPhy3PhyEventConfig_t;
+
+/* values for PhyEventCode field */
+#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT                    (0x00)
+#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD               (0x01)
+#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR     (0x02)
+#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC             (0x03)
+#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM           (0x04)
+#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW     (0x05)
+#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR                    (0x06)
+#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR         (0x20)
+#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT           (0x21)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT           (0x22)
+#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT           (0x23)
+#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT           (0x24)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON   (0x25)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON   (0x26)
+#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK                    (0x27)
+#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK                    (0x28)
+#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT               (0x29)
+#define MPI2_SASPHY3_EVENT_CODE_CONNECTION                  (0x2A)
+#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED      (0x2B)
+#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME        (0x2C)
+#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME          (0x2D)
+#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME           (0x2E)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES               (0x40)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES               (0x41)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES         (0x42)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES         (0x43)
+#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED           (0x44)
+#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED           (0x45)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES              (0x50)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES              (0x51)
+#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW               (0x52)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES               (0x60)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES               (0x61)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES         (0x63)
+#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT             (0xD0)
+#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE    (0xD1)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP                      (0xD2)
+
+/* values for the CounterType field */
+#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING                  (0x00)
+#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING                (0x01)
+#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE                (0x02)
+
+/* values for the TimeUnits field */
+#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS             (0x00)
+#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS            (0x01)
+#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND               (0x02)
+#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS             (0x03)
+
+/* values for the ThresholdFlags field */
+#define MPI2_SASPHY3_TFLAGS_PHY_RESET                       (0x0002)
+#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY                    (0x0001)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhyEvents at runtime.
+ */
+#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
+#define MPI2_SASPHY3_PHY_EVENT_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U8                                  NumPhyEvents;               /* 0x0C */
+    U8                                  Reserved2;                  /* 0x0D */
+    U16                                 Reserved3;                  /* 0x0E */
+    MPI2_SASPHY3_PHY_EVENT_CONFIG       PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /* 0x10 */
+} MPI2_CONFIG_PAGE_SAS_PHY_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
+  Mpi2SasPhyPage3_t, MPI2_POINTER pMpi2SasPhyPage3_t;
+
+#define MPI2_SASPHY3_PAGEVERSION            (0x00)
+
+
+/* SAS PHY Page 4 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U16                                 Reserved1;                  /* 0x08 */
+    U8                                  Reserved2;                  /* 0x0A */
+    U8                                  Flags;                      /* 0x0B */
+    U8                                  InitialFrame[28];           /* 0x0C */
+} MPI2_CONFIG_PAGE_SAS_PHY_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_4,
+  Mpi2SasPhyPage4_t, MPI2_POINTER pMpi2SasPhyPage4_t;
+
+#define MPI2_SASPHY4_PAGEVERSION            (0x00)
+
+/* values for the Flags field */
+#define MPI2_SASPHY4_FLAGS_FRAME_VALID        (0x02)
+#define MPI2_SASPHY4_FLAGS_SATA_FRAME         (0x01)
+
+
+
+
+/****************************************************************************
+*   SAS Port Config Pages
+****************************************************************************/
+
+/* SAS Port Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U8                                  PortNumber;                 /* 0x08 */
+    U8                                  PhysicalPort;               /* 0x09 */
+    U8                                  PortWidth;                  /* 0x0A */
+    U8                                  PhysicalPortWidth;          /* 0x0B */
+    U8                                  ZoneGroup;                  /* 0x0C */
+    U8                                  Reserved1;                  /* 0x0D */
+    U16                                 Reserved2;                  /* 0x0E */
+    U64                                 SASAddress;                 /* 0x10 */
+    U32                                 DeviceInfo;                 /* 0x18 */
+    U32                                 Reserved3;                  /* 0x1C */
+    U32                                 Reserved4;                  /* 0x20 */
+} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
+  Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t;
+
+#define MPI2_SASPORT0_PAGEVERSION           (0x00)
+
+/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
+
+
+/****************************************************************************
+*   SAS Enclosure Config Pages
+****************************************************************************/
+
+/* SAS Enclosure Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U64                                 EnclosureLogicalID;         /* 0x0C */
+    U16                                 Flags;                      /* 0x14 */
+    U16                                 EnclosureHandle;            /* 0x16 */
+    U16                                 NumSlots;                   /* 0x18 */
+    U16                                 StartSlot;                  /* 0x1A */
+    U16                                 Reserved2;                  /* 0x1C */
+    U16                                 SEPDevHandle;               /* 0x1E */
+    U32                                 Reserved3;                  /* 0x20 */
+    U32                                 Reserved4;                  /* 0x24 */
+} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
+  Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t;
+
+#define MPI2_SASENCLOSURE0_PAGEVERSION      (0x03)
+
+/* values for SAS Enclosure Page 0 Flags field */
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK              (0x000F)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN           (0x0000)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES           (0x0001)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO         (0x0002)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO         (0x0003)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE     (0x0004)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO          (0x0005)
+
+
+/****************************************************************************
+*   Log Config Page
+****************************************************************************/
+
+/* Log Page 0 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
+#define MPI2_LOG_0_NUM_LOG_ENTRIES          (1)
+#endif
+
+#define MPI2_LOG_0_LOG_DATA_LENGTH          (0x1C)
+
+typedef struct _MPI2_LOG_0_ENTRY
+{
+    U64         TimeStamp;                          /* 0x00 */
+    U32         Reserved1;                          /* 0x08 */
+    U16         LogSequence;                        /* 0x0C */
+    U16         LogEntryQualifier;                  /* 0x0E */
+    U8          VP_ID;                              /* 0x10 */
+    U8          VF_ID;                              /* 0x11 */
+    U16         Reserved2;                          /* 0x12 */
+    U8          LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */
+} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY,
+  Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t;
+
+/* values for Log Page 0 LogEntry LogEntryQualifier field */
+#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED          (0x0000)
+#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET        (0x0001)
+#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE      (0x0002)
+#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC    (0x8000)
+#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC    (0xFFFF)
+
+typedef struct _MPI2_CONFIG_PAGE_LOG_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U32                                 Reserved2;                  /* 0x0C */
+    U16                                 NumLogEntries;              /* 0x10 */
+    U16                                 Reserved3;                  /* 0x12 */
+    MPI2_LOG_0_ENTRY                    LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */
+} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0,
+  Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t;
+
+#define MPI2_LOG_0_PAGEVERSION              (0x02)
+
+
+/****************************************************************************
+*   RAID Config Page
+****************************************************************************/
+
+/* RAID Page 0 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
+#define MPI2_RAIDCONFIG0_MAX_ELEMENTS       (1)
+#endif
+
+typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT
+{
+    U16                     ElementFlags;               /* 0x00 */
+    U16                     VolDevHandle;               /* 0x02 */
+    U8                      HotSparePool;               /* 0x04 */
+    U8                      PhysDiskNum;                /* 0x05 */
+    U16                     PhysDiskDevHandle;          /* 0x06 */
+} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
+  MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
+  Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t;
+
+/* values for the ElementFlags field */
+#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE       (0x000F)
+#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT          (0x0000)
+#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT   (0x0001)
+#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT       (0x0002)
+#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT             (0x0003)
+
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U8                                  NumHotSpares;               /* 0x08 */
+    U8                                  NumPhysDisks;               /* 0x09 */
+    U8                                  NumVolumes;                 /* 0x0A */
+    U8                                  ConfigNum;                  /* 0x0B */
+    U32                                 Flags;                      /* 0x0C */
+    U8                                  ConfigGUID[24];             /* 0x10 */
+    U32                                 Reserved1;                  /* 0x28 */
+    U8                                  NumElements;                /* 0x2C */
+    U8                                  Reserved2;                  /* 0x2D */
+    U16                                 Reserved3;                  /* 0x2E */
+    MPI2_RAIDCONFIG0_CONFIG_ELEMENT     ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */
+} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
+  Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t;
+
+#define MPI2_RAIDCONFIG0_PAGEVERSION            (0x00)
+
+/* values for RAID Configuration Page 0 Flags field */
+#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG        (0x00000001)
+
+
+/****************************************************************************
+*   Driver Persistent Mapping Config Pages
+****************************************************************************/
+
+/* Driver Persistent Mapping Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY
+{
+    U64                                 PhysicalIdentifier;         /* 0x00 */
+    U16                                 MappingInformation;         /* 0x08 */
+    U16                                 DeviceIndex;                /* 0x0A */
+    U32                                 PhysicalBitsMapping;        /* 0x0C */
+    U32                                 Reserved1;                  /* 0x10 */
+} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
+  Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY  Entry;                      /* 0x08 */
+} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
+  Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t;
+
+#define MPI2_DRIVERMAPPING0_PAGEVERSION         (0x00)
+
+/* values for Driver Persistent Mapping Page 0 MappingInformation field */
+#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK              (0x07F0)
+#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT             (4)
+#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK           (0x000F)
+
+
+/****************************************************************************
+*   Ethernet Config Pages
+****************************************************************************/
+
+/* Ethernet Page 0 */
+
+/* IP address (union of IPv4 and IPv6) */
+typedef union _MPI2_ETHERNET_IP_ADDR
+{
+    U32     IPv4Addr;
+    U32     IPv6Addr[4];
+} MPI2_ETHERNET_IP_ADDR, MPI2_POINTER PTR_MPI2_ETHERNET_IP_ADDR,
+  Mpi2EthernetIpAddr_t, MPI2_POINTER pMpi2EthernetIpAddr_t;
+
+#define MPI2_ETHERNET_HOST_NAME_LENGTH          (32)
+
+typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+    U8                                  NumInterfaces;          /* 0x08 */
+    U8                                  Reserved0;              /* 0x09 */
+    U16                                 Reserved1;              /* 0x0A */
+    U32                                 Status;                 /* 0x0C */
+    U8                                  MediaState;             /* 0x10 */
+    U8                                  Reserved2;              /* 0x11 */
+    U16                                 Reserved3;              /* 0x12 */
+    U8                                  MacAddress[6];          /* 0x14 */
+    U8                                  Reserved4;              /* 0x1A */
+    U8                                  Reserved5;              /* 0x1B */
+    MPI2_ETHERNET_IP_ADDR               IpAddress;              /* 0x1C */
+    MPI2_ETHERNET_IP_ADDR               SubnetMask;             /* 0x2C */
+    MPI2_ETHERNET_IP_ADDR               GatewayIpAddress;       /* 0x3C */
+    MPI2_ETHERNET_IP_ADDR               DNS1IpAddress;          /* 0x4C */
+    MPI2_ETHERNET_IP_ADDR               DNS2IpAddress;          /* 0x5C */
+    MPI2_ETHERNET_IP_ADDR               DhcpIpAddress;          /* 0x6C */
+    U8                                  HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */
+} MPI2_CONFIG_PAGE_ETHERNET_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_0,
+  Mpi2EthernetPage0_t, MPI2_POINTER pMpi2EthernetPage0_t;
+
+#define MPI2_ETHERNETPAGE0_PAGEVERSION   (0x00)
+
+/* values for Ethernet Page 0 Status field */
+#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE             (0x80000000)
+#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE             (0x40000000)
+#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED        (0x20000000)
+#define MPI2_ETHPG0_STATUS_DEFAULT_IF               (0x00000100)
+#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED         (0x00000080)
+#define MPI2_ETHPG0_STATUS_TELNET_ENABLED           (0x00000040)
+#define MPI2_ETHPG0_STATUS_SSH2_ENABLED             (0x00000020)
+#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED      (0x00000010)
+#define MPI2_ETHPG0_STATUS_IPV6_ENABLED             (0x00000008)
+#define MPI2_ETHPG0_STATUS_IPV4_ENABLED             (0x00000004)
+#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES           (0x00000002)
+#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED           (0x00000001)
+
+/* values for Ethernet Page 0 MediaState field */
+#define MPI2_ETHPG0_MS_DUPLEX_MASK                  (0x80)
+#define MPI2_ETHPG0_MS_HALF_DUPLEX                  (0x00)
+#define MPI2_ETHPG0_MS_FULL_DUPLEX                  (0x80)
+
+#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK           (0x07)
+#define MPI2_ETHPG0_MS_NOT_CONNECTED                (0x00)
+#define MPI2_ETHPG0_MS_10MBIT                       (0x01)
+#define MPI2_ETHPG0_MS_100MBIT                      (0x02)
+#define MPI2_ETHPG0_MS_1GBIT                        (0x03)
+
+
+/* Ethernet Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+    U32                                 Reserved0;              /* 0x08 */
+    U32                                 Flags;                  /* 0x0C */
+    U8                                  MediaState;             /* 0x10 */
+    U8                                  Reserved1;              /* 0x11 */
+    U16                                 Reserved2;              /* 0x12 */
+    U8                                  MacAddress[6];          /* 0x14 */
+    U8                                  Reserved3;              /* 0x1A */
+    U8                                  Reserved4;              /* 0x1B */
+    MPI2_ETHERNET_IP_ADDR               StaticIpAddress;        /* 0x1C */
+    MPI2_ETHERNET_IP_ADDR               StaticSubnetMask;       /* 0x2C */
+    MPI2_ETHERNET_IP_ADDR               StaticGatewayIpAddress; /* 0x3C */
+    MPI2_ETHERNET_IP_ADDR               StaticDNS1IpAddress;    /* 0x4C */
+    MPI2_ETHERNET_IP_ADDR               StaticDNS2IpAddress;    /* 0x5C */
+    U32                                 Reserved5;              /* 0x6C */
+    U32                                 Reserved6;              /* 0x70 */
+    U32                                 Reserved7;              /* 0x74 */
+    U32                                 Reserved8;              /* 0x78 */
+    U8                                  HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */
+} MPI2_CONFIG_PAGE_ETHERNET_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_1,
+  Mpi2EthernetPage1_t, MPI2_POINTER pMpi2EthernetPage1_t;
+
+#define MPI2_ETHERNETPAGE1_PAGEVERSION   (0x00)
+
+/* values for Ethernet Page 1 Flags field */
+#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF             (0x00000100)
+#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD         (0x00000080)
+#define MPI2_ETHPG1_FLAG_ENABLE_TELNET              (0x00000040)
+#define MPI2_ETHPG1_FLAG_ENABLE_SSH2                (0x00000020)
+#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT         (0x00000010)
+#define MPI2_ETHPG1_FLAG_ENABLE_IPV6                (0x00000008)
+#define MPI2_ETHPG1_FLAG_ENABLE_IPV4                (0x00000004)
+#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES         (0x00000002)
+#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF              (0x00000001)
+
+/* values for Ethernet Page 1 MediaState field */
+#define MPI2_ETHPG1_MS_DUPLEX_MASK                  (0x80)
+#define MPI2_ETHPG1_MS_HALF_DUPLEX                  (0x00)
+#define MPI2_ETHPG1_MS_FULL_DUPLEX                  (0x80)
+
+#define MPI2_ETHPG1_MS_DATA_RATE_MASK               (0x07)
+#define MPI2_ETHPG1_MS_DATA_RATE_AUTO               (0x00)
+#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT             (0x01)
+#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT            (0x02)
+#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT              (0x03)
+
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_hbd.h ../../stable/8/sys/dev/mps/mpi/mpi2_hbd.h
--- sys/dev/mps/mpi/mpi2_hbd.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_hbd.h	2011-01-07 14:33:12.681632685 -0700
@@ -0,0 +1,114 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_hbd.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_hbd.h
+ *          Title:  MPI Host Based Discovery messages and structures
+ *  Creation Date:  October 21, 2009
+ *
+ *  mpi2_hbd.h Version:  02.00.00
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  10-28-09  02.00.00  Initial version.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_HBD_H
+#define MPI2_HBD_H
+
+/****************************************************************************
+*  Host Based Discovery Action messages
+****************************************************************************/
+
+/* Host Based Discovery Action Request Message */
+typedef struct _MPI2_HBD_ACTION_REQUEST
+{
+    U8                      Operation;          /* 0x00 */
+    U8                      Reserved1;          /* 0x01 */
+    U8                      ChainOffset;        /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     DevHandle;          /* 0x04 */
+    U8                      Reserved2;          /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved3;          /* 0x0A */
+    U32                     Reserved4;          /* 0x0C */
+    U64                     SASAddress;         /* 0x10 */
+    U32                     Reserved5;          /* 0x18 */
+    U32                     HbdDeviceInfo;      /* 0x1C */
+    U16                     ParentDevHandle;    /* 0x20 */
+    U16                     MaxQDepth;          /* 0x22 */
+    U8                      FirstPhyIdentifier; /* 0x24 */
+    U8                      Port;               /* 0x25 */
+    U8                      MaxConnections;     /* 0x26 */
+    U8                      MaxRate;            /* 0x27 */
+    U8                      PortGroups;         /* 0x28 */
+    U8                      DmaGroup;           /* 0x29 */
+    U8                      ControlGroup;       /* 0x2A */
+    U8                      Reserved6;          /* 0x2B */
+    U16                     InitialAWT;         /* 0x2C */
+    U16                     Reserved7;          /* 0x2E */
+    U32                     Reserved8;          /* 0x30 */
+} MPI2_HBD_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_HBD_ACTION_REQUEST,
+  Mpi2HbdActionRequest_t, MPI2_POINTER pMpi2HbdActionRequest_t;
+
+/* values for the Operation field */
+#define MPI2_HBD_OP_ADD_DEVICE                  (0x01)
+#define MPI2_HBD_OP_REMOVE_DEVICE               (0x02)
+#define MPI2_HBD_OP_UPDATE_DEVICE               (0x03)
+
+/* values for the HbdDeviceInfo field */
+#define MPI2_HBD_DEVICE_INFO_VIRTUAL_DEVICE     (0x00004000)
+#define MPI2_HBD_DEVICE_INFO_ATAPI_DEVICE       (0x00002000)
+#define MPI2_HBD_DEVICE_INFO_DIRECT_ATTACH      (0x00000800)
+#define MPI2_HBD_DEVICE_INFO_SSP_TARGET         (0x00000400)
+#define MPI2_HBD_DEVICE_INFO_STP_TARGET         (0x00000200)
+#define MPI2_HBD_DEVICE_INFO_SMP_TARGET         (0x00000100)
+#define MPI2_HBD_DEVICE_INFO_SATA_DEVICE        (0x00000080)
+#define MPI2_HBD_DEVICE_INFO_SSP_INITIATOR      (0x00000040)
+#define MPI2_HBD_DEVICE_INFO_STP_INITIATOR      (0x00000020)
+#define MPI2_HBD_DEVICE_INFO_SMP_INITIATOR      (0x00000010)
+#define MPI2_HBD_DEVICE_INFO_SATA_HOST          (0x00000008)
+
+#define MPI2_HBD_DEVICE_INFO_MASK_DEVICE_TYPE   (0x00000007)
+#define MPI2_HBD_DEVICE_INFO_NO_DEVICE          (0x00000000)
+#define MPI2_HBD_DEVICE_INFO_END_DEVICE         (0x00000001)
+#define MPI2_HBD_DEVICE_INFO_EDGE_EXPANDER      (0x00000002)
+#define MPI2_HBD_DEVICE_INFO_FANOUT_EXPANDER    (0x00000003)
+
+/* values for the MaxRate field */
+#define MPI2_HBD_MAX_RATE_MASK                  (0x0F)
+#define MPI2_HBD_MAX_RATE_1_5                   (0x08)
+#define MPI2_HBD_MAX_RATE_3_0                   (0x09)
+#define MPI2_HBD_MAX_RATE_6_0                   (0x0A)
+
+
+/* Host Based Discovery Action Reply Message */
+typedef struct _MPI2_HBD_ACTION_REPLY
+{
+    U8                      Operation;          /* 0x00 */
+    U8                      Reserved1;          /* 0x01 */
+    U8                      MsgLength;          /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     DevHandle;          /* 0x04 */
+    U8                      Reserved2;          /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved3;          /* 0x0A */
+    U16                     Reserved4;          /* 0x0C */
+    U16                     IOCStatus;          /* 0x0E */
+    U32                     IOCLogInfo;         /* 0x10 */
+} MPI2_HBD_ACTION_REPLY, MPI2_POINTER PTR_MPI2_HBD_ACTION_REPLY,
+  Mpi2HbdActionReply_t, MPI2_POINTER pMpi2HbdActionReply_t;
+
+
+#endif
+
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_history.txt ../../stable/8/sys/dev/mps/mpi/mpi2_history.txt
--- sys/dev/mps/mpi/mpi2_history.txt	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_history.txt	2011-01-07 14:33:12.652515579 -0700
@@ -0,0 +1,382 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_history.txt 212420 2010-09-10 15:03:56Z ken $ */
+ ==============================
+ Fusion-MPT MPI 2.0 Header File Change History
+ ==============================
+
+ Copyright (c) 2000-2009 LSI Corporation.
+
+ ---------------------------------------
+ Header Set Release Version:    02.00.14
+ Header Set Release Date:       10-28-09
+ ---------------------------------------
+
+ Filename               Current version     Prior version
+ ----------             ---------------     -------------
+ mpi2.h                 02.00.14            02.00.13
+ mpi2_cnfg.h            02.00.13            02.00.12
+ mpi2_init.h            02.00.08            02.00.07
+ mpi2_ioc.h             02.00.13            02.00.12
+ mpi2_raid.h            02.00.04            02.00.04
+ mpi2_sas.h             02.00.03            02.00.02
+ mpi2_targ.h            02.00.03            02.00.03
+ mpi2_tool.h            02.00.04            02.00.04
+ mpi2_type.h            02.00.00            02.00.00
+ mpi2_ra.h              02.00.00            02.00.00
+ mpi2_hbd.h             02.00.00
+ mpi2_history.txt       02.00.14            02.00.13
+
+
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+
+mpi2.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  06-26-07  02.00.02  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  08-31-07  02.00.03  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Moved ReplyPostHostIndex register to offset 0x6C of the
+ *                      MPI2_SYSTEM_INTERFACE_REGS and modified the define for
+ *                      MPI2_REPLY_POST_HOST_INDEX_OFFSET.
+ *                      Added union of request descriptors.
+ *                      Added union of reply descriptors.
+ *  10-31-07  02.00.04  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added define for MPI2_VERSION_02_00.
+ *                      Fixed the size of the FunctionDependent5 field in the
+ *                      MPI2_DEFAULT_REPLY structure.
+ *  12-18-07  02.00.05  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Removed the MPI-defined Fault Codes and extended the
+ *                      product specific codes up to 0xEFFF.
+ *                      Added a sixth key value for the WriteSequence register
+ *                      and changed the flush value to 0x0.
+ *                      Added message function codes for Diagnostic Buffer Post
+ *                      and Diagnsotic Release.
+ *                      New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
+ *                      Moved MPI2_VERSION_UNION from mpi2_ioc.h.
+ *  02-29-08  02.00.06  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  03-03-08  02.00.07  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-21-08  02.00.08  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added #defines for marking a reply descriptor as unused.
+ *  06-27-08  02.00.09  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Moved LUN field defines from mpi2_init.h.
+ *  01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      In all request and reply descriptors, replaced VF_ID
+ *                      field with MSIxIndex field.
+ *                      Removed DevHandle field from
+ *                      MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
+ *                      bytes reserved.
+ *                      Added RAID Accelerator functionality.
+ *  07-30-09  02.00.13  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  10-28-09  02.00.14  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added MSI-x index mask and shift for Reply Post Host
+ *                      Index register.
+ *                      Added function code for Host Based Discovery Action.
+ *  --------------------------------------------------------------------------
+
+mpi2_cnfg.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  Added defines for SAS IO Unit Page 2 PhyFlags.
+ *                      Added Manufacturing Page 11.
+ *                      Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
+ *                      define.
+ *  06-26-07  02.00.02  Adding generic structure for product-specific
+ *                      Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
+ *                      Rework of BIOS Page 2 configuration page.
+ *                      Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
+ *                      forms.
+ *                      Added configuration pages IOC Page 8 and Driver
+ *                      Persistent Mapping Page 0.
+ *  08-31-07  02.00.03  Modified configuration pages dealing with Integrated
+ *                      RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
+ *                      RAID Physical Disk Pages 0 and 1, RAID Configuration
+ *                      Page 0).
+ *                      Added new value for AccessStatus field of SAS Device
+ *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
+ *  10-31-07  02.00.04  Added missing SEPDevHandle field to
+ *                      MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
+ *  12-18-07  02.00.05  Modified IO Unit Page 0 to use 32-bit version fields for
+ *                      NVDATA.
+ *                      Modified IOC Page 7 to use masks and added field for
+ *                      SASBroadcastPrimitiveMasks.
+ *                      Added MPI2_CONFIG_PAGE_BIOS_4.
+ *                      Added MPI2_CONFIG_PAGE_LOG_0.
+ *  02-29-08  02.00.06  Modified various names to make them 32-character unique.
+ *                      Added SAS Device IDs.
+ *                      Updated Integrated RAID configuration pages including
+ *                      Manufacturing Page 4, IOC Page 6, and RAID Configuration
+ *                      Page 0.
+ *  05-21-08  02.00.07  Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
+ *                      Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
+ *                      Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
+ *                      Added missing MaxNumRoutedSasAddresses field to
+ *                      MPI2_CONFIG_PAGE_EXPANDER_0.
+ *                      Added SAS Port Page 0.
+ *                      Modified structure layout for
+ *                      MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
+ *  06-27-08  02.00.08  Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
+ *                      MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
+ *  10-02-08  02.00.09  Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
+ *                      to 0x000000FF.
+ *                      Added two new values for the Physical Disk Coercion Size
+ *                      bits in the Flags field of Manufacturing Page 4.
+ *                      Added product-specific Manufacturing pages 16 to 31.
+ *                      Modified Flags bits for controlling write cache on SATA
+ *                      drives in IO Unit Page 1.
+ *                      Added new bit to AdditionalControlFlags of SAS IO Unit
+ *                      Page 1 to control Invalid Topology Correction.
+ *                      Added SupportedPhysDisks field to RAID Volume Page 1 and
+ *                      added related defines.
+ *                      Added additional defines for RAID Volume Page 0
+ *                      VolumeStatusFlags field.
+ *                      Modified meaning of RAID Volume Page 0 VolumeSettings
+ *                      define for auto-configure of hot-swap drives.
+ *                      Added PhysDiskAttributes field (and related defines) to
+ *                      RAID Physical Disk Page 0.
+ *                      Added MPI2_SAS_PHYINFO_PHY_VACANT define.
+ *                      Added three new DiscoveryStatus bits for SAS IO Unit
+ *                      Page 0 and SAS Expander Page 0.
+ *                      Removed multiplexing information from SAS IO Unit pages.
+ *                      Added BootDeviceWaitTime field to SAS IO Unit Page 4.
+ *                      Removed Zone Address Resolved bit from PhyInfo and from
+ *                      Expander Page 0 Flags field.
+ *                      Added two new AccessStatus values to SAS Device Page 0
+ *                      for indicating routing problems. Added 3 reserved words
+ *                      to this page.
+ *  01-19-09  02.00.10  Fixed defines for GPIOVal field of IO Unit Page 3.
+ *                      Inserted missing reserved field into structure for IOC
+ *                      Page 6.
+ *                      Added more pending task bits to RAID Volume Page 0
+ *                      VolumeStatusFlags defines.
+ *                      Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
+ *                      Added a new DiscoveryStatus bit for SAS IO Unit Page 0
+ *                      and SAS Expander Page 0 to flag a downstream initiator
+ *                      when in simplified routing mode.
+ *                      Removed SATA Init Failure defines for DiscoveryStatus
+ *                      fields of SAS IO Unit Page 0 and SAS Expander Page 0.
+ *                      Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
+ *                      Added PortGroups, DmaGroup, and ControlGroup fields to
+ *                      SAS Device Page 0.
+ *  05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
+ *                      Unit Page 6.
+ *                      Added expander reduced functionality data to SAS
+ *                      Expander Page 0.
+ *                      Added SAS PHY Page 2 and SAS PHY Page 3.
+ *  07-30-09  02.00.12  Added IO Unit Page 7.
+ *                      Added new device ids.
+ *                      Added SAS IO Unit Page 5.
+ *                      Added partial and slumber power management capable flags
+ *                      to SAS Device Page 0 Flags field.
+ *                      Added PhyInfo defines for power condition.
+ *                      Added Ethernet configuration pages.
+ *  10-28-09  02.00.13  Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
+ *                      Added SAS PHY Page 4 structure and defines.
+ *  --------------------------------------------------------------------------
+
+mpi2_init.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  10-31-07  02.00.01  Fixed name for pMpi2SCSITaskManagementRequest_t.
+ *  12-18-07  02.00.02  Modified Task Management Target Reset Method defines.
+ *  02-29-08  02.00.03  Added Query Task Set and Query Unit Attention.
+ *  03-03-08  02.00.04  Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
+ *  05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
+ *  10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
+ *                      Control field Task Attribute flags.
+ *                      Moved LUN field defines to mpi2.h becasue they are
+ *                      common to many structures.
+ *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
+ *                      Query Asynchronous Event.
+ *                      Defined two new bits in the SlotStatus field of the SCSI
+ *                      Enclosure Processor Request and Reply.
+ *  10-28-09  02.00.08  Added defines for decoding the ResponseInfo bytes for
+ *                      both SCSI IO Error Reply and SCSI Task Management Reply.
+ *                      Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
+ *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
+ *  --------------------------------------------------------------------------
+
+mpi2_ioc.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  In IOCFacts Reply structure, renamed MaxDevices to
+ *                      MaxTargets.
+ *                      Added TotalImageSize field to FWDownload Request.
+ *                      Added reserved words to FWUpload Request.
+ *  06-26-07  02.00.02  Added IR Configuration Change List Event.
+ *  08-31-07  02.00.03  Removed SystemReplyQueueDepth field from the IOCInit
+ *                      request and replaced it with
+ *                      ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
+ *                      Replaced the MinReplyQueueDepth field of the IOCFacts
+ *                      reply with MaxReplyDescriptorPostQueueDepth.
+ *                      Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
+ *                      depth for the Reply Descriptor Post Queue.
+ *                      Added SASAddress field to Initiator Device Table
+ *                      Overflow Event data.
+ *  10-31-07  02.00.04  Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
+ *                      for SAS Initiator Device Status Change Event data.
+ *                      Modified Reason Code defines for SAS Topology Change
+ *                      List Event data, including adding a bit for PHY Vacant
+ *                      status, and adding a mask for the Reason Code.
+ *                      Added define for
+ *                      MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
+ *                      Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
+ *  12-18-07  02.00.05  Added Boot Status defines for the IOCExceptions field of
+ *                      the IOCFacts Reply.
+ *                      Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                      Moved MPI2_VERSION_UNION to mpi2.h.
+ *                      Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
+ *                      instead of enables, and added SASBroadcastPrimitiveMasks
+ *                      field.
+ *                      Added Log Entry Added Event and related structure.
+ *  02-29-08  02.00.06  Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
+ *                      Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
+ *                      Added MaxVolumes and MaxPersistentEntries fields to
+ *                      IOCFacts reply.
+ *                      Added ProtocalFlags and IOCCapabilities fields to
+ *                      MPI2_FW_IMAGE_HEADER.
+ *                      Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
+ *  03-03-08  02.00.07  Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
+ *                      a U16 (from a U32).
+ *                      Removed extra 's' from EventMasks name.
+ *  06-27-08  02.00.08  Fixed an offset in a comment.
+ *  10-02-08  02.00.09  Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
+ *                      Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
+ *                      renamed MinReplyFrameSize to ReplyFrameSize.
+ *                      Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
+ *                      Added two new RAIDOperation values for Integrated RAID
+ *                      Operations Status Event data.
+ *                      Added four new IR Configuration Change List Event data
+ *                      ReasonCode values.
+ *                      Added two new ReasonCode defines for SAS Device Status
+ *                      Change Event data.
+ *                      Added three new DiscoveryStatus bits for the SAS
+ *                      Discovery event data.
+ *                      Added Multiplexing Status Change bit to the PhyStatus
+ *                      field of the SAS Topology Change List event data.
+ *                      Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
+ *                      BootFlags are now product-specific.
+ *                      Added defines for the indivdual signature bytes
+ *                      for MPI2_INIT_IMAGE_FOOTER.
+ *  01-19-09  02.00.10  Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
+ *                      Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
+ *                      define.
+ *                      Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
+ *                      define.
+ *                      Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
+ *  05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
+ *                      Added two new reason codes for SAS Device Status Change
+ *                      Event.
+ *                      Added new event: SAS PHY Counter.
+ *  07-30-09  02.00.12  Added GPIO Interrupt event define and structure.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                      Added new product id family for 2208.
+ *  10-28-09  02.00.13  Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
+ *                      Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
+ *                      Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
+ *                      Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
+ *                      Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
+ *                      Added Host Based Discovery Phy Event data.
+ *                      Added defines for ProductID Product field
+ *                      (MPI2_FW_HEADER_PID_).
+ *                      Modified values for SAS ProductID Family
+ *                      (MPI2_FW_HEADER_PID_FAMILY_).
+ *  --------------------------------------------------------------------------
+
+mpi2_raid.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  08-31-07  02.00.01  Modifications to RAID Action request and reply,
+ *                      including the Actions and ActionData.
+ *  02-29-08  02.00.02  Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
+ *  05-21-08  02.00.03  Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
+ *                      the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
+ *                      can be sized by the build environment.
+ *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
+ *                      VolumeCreationFlags and marked the old one as obsolete.
+ *  --------------------------------------------------------------------------
+
+mpi2_sas.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-26-07  02.00.01  Added Clear All Persistent Operation to SAS IO Unit
+ *                      Control Request.
+ *  10-02-08  02.00.02  Added Set IOC Parameter Operation to SAS IO Unit Control
+ *                      Request.
+ *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
+ *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ *  --------------------------------------------------------------------------
+
+mpi2_targ.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  08-31-07  02.00.01  Added Command Buffer Data Location Address Space bits to
+ *                      BufferPostFlags field of CommandBufferPostBase Request.
+ *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  10-02-08  02.00.03  Removed NextCmdBufferOffset from
+ *                      MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST.
+ *                      Target Status Send Request only takes a single SGE for
+ *                      response data.
+ *  --------------------------------------------------------------------------
+
+mpi2_tool.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
+ *                      structures and defines.
+ *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
+ *  07-30-09  02.00.04  Added ExtendedType field to DiagnosticBufferPost request
+ *                      and reply messages.
+ *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
+ *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ *  --------------------------------------------------------------------------
+
+mpi2_type.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  --------------------------------------------------------------------------
+
+mpi2_ra.h
+ *  05-06-09  02.00.00  Initial version.
+ *  --------------------------------------------------------------------------
+
+mpi2_hbd.h
+ *  10-28-09  02.00.00  Initial version.
+ *  --------------------------------------------------------------------------
+
+
+mpi2_history.txt         Parts list history
+
+Filename     02.00.14  02.00.13  02.00.12
+----------   --------  --------  --------
+mpi2.h       02.00.14  02.00.13  02.00.12
+mpi2_cnfg.h  02.00.13  02.00.12  02.00.11
+mpi2_init.h  02.00.08  02.00.07  02.00.07
+mpi2_ioc.h   02.00.13  02.00.12  02.00.11
+mpi2_raid.h  02.00.04  02.00.04  02.00.03
+mpi2_sas.h   02.00.03  02.00.02  02.00.02
+mpi2_targ.h  02.00.03  02.00.03  02.00.03
+mpi2_tool.h  02.00.04  02.00.04  02.00.03
+mpi2_type.h  02.00.00  02.00.00  02.00.00
+mpi2_ra.h    02.00.00  02.00.00  02.00.00
+mpi2_hbd.h   02.00.00
+
+Filename     02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
+----------   --------  --------  --------  --------  --------  --------
+mpi2.h       02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
+mpi2_cnfg.h  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06  02.00.06
+mpi2_init.h  02.00.06  02.00.06  02.00.05  02.00.05  02.00.04  02.00.03
+mpi2_ioc.h   02.00.10  02.00.09  02.00.08  02.00.07  02.00.07  02.00.06
+mpi2_raid.h  02.00.03  02.00.03  02.00.03  02.00.03  02.00.02  02.00.02
+mpi2_sas.h   02.00.02  02.00.02  02.00.01  02.00.01  02.00.01  02.00.01
+mpi2_targ.h  02.00.03  02.00.03  02.00.02  02.00.02  02.00.02  02.00.02
+mpi2_tool.h  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02
+mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+
+Filename     02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+----------   --------  --------  --------  --------  --------  --------
+mpi2.h       02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+mpi2_cnfg.h  02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+mpi2_init.h  02.00.02  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00
+mpi2_ioc.h   02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+mpi2_raid.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
+mpi2_sas.h   02.00.01  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00
+mpi2_targ.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
+mpi2_tool.h  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_init.h ../../stable/8/sys/dev/mps/mpi/mpi2_init.h
--- sys/dev/mps/mpi/mpi2_init.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_init.h	2011-01-07 14:33:12.643483552 -0700
@@ -0,0 +1,454 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_init.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_init.h
+ *          Title:  MPI SCSI initiator mode messages and structures
+ *  Creation Date:  June 23, 2006
+ *
+ *    mpi2_init.h Version:  02.00.08
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  10-31-07  02.00.01  Fixed name for pMpi2SCSITaskManagementRequest_t.
+ *  12-18-07  02.00.02  Modified Task Management Target Reset Method defines.
+ *  02-29-08  02.00.03  Added Query Task Set and Query Unit Attention.
+ *  03-03-08  02.00.04  Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
+ *  05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
+ *  10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
+ *                      Control field Task Attribute flags.
+ *                      Moved LUN field defines to mpi2.h becasue they are
+ *                      common to many structures.
+ *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
+ *                      Query Asynchronous Event.
+ *                      Defined two new bits in the SlotStatus field of the SCSI
+ *                      Enclosure Processor Request and Reply.
+ *  10-28-09  02.00.08  Added defines for decoding the ResponseInfo bytes for
+ *                      both SCSI IO Error Reply and SCSI Task Management Reply.
+ *                      Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
+ *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_INIT_H
+#define MPI2_INIT_H
+
+/*****************************************************************************
+*
+*               SCSI Initiator Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  SCSI IO messages and associated structures
+****************************************************************************/
+
+typedef struct
+{
+    U8                      CDB[20];                    /* 0x00 */
+    U32                     PrimaryReferenceTag;        /* 0x14 */
+    U16                     PrimaryApplicationTag;      /* 0x18 */
+    U16                     PrimaryApplicationTagMask;  /* 0x1A */
+    U32                     TransferLength;             /* 0x1C */
+} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
+  Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
+
+/* TBD: I don't think this is needed for MPI2/Gen2 */
+#if 0
+typedef struct
+{
+    U8                      CDB[16];                    /* 0x00 */
+    U32                     DataLength;                 /* 0x10 */
+    U32                     PrimaryReferenceTag;        /* 0x14 */
+    U16                     PrimaryApplicationTag;      /* 0x18 */
+    U16                     PrimaryApplicationTagMask;  /* 0x1A */
+    U32                     TransferLength;             /* 0x1C */
+} MPI2_SCSI_IO32_CDB_EEDP16, MPI2_POINTER PTR_MPI2_SCSI_IO32_CDB_EEDP16,
+  Mpi2ScsiIo32CdbEedp16_t, MPI2_POINTER pMpi2ScsiIo32CdbEedp16_t;
+#endif
+
+typedef union
+{
+    U8                      CDB32[32];
+    MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+    MPI2_SGE_SIMPLE_UNION   SGE;
+} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
+  Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
+
+/* SCSI IO Request Message */
+typedef struct _MPI2_SCSI_IO_REQUEST
+{
+    U16                     DevHandle;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved1;                      /* 0x04 */
+    U8                      Reserved2;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved3;                      /* 0x0A */
+    U32                     SenseBufferLowAddress;          /* 0x0C */
+    U16                     SGLFlags;                       /* 0x10 */
+    U8                      SenseBufferLength;              /* 0x12 */
+    U8                      Reserved4;                      /* 0x13 */
+    U8                      SGLOffset0;                     /* 0x14 */
+    U8                      SGLOffset1;                     /* 0x15 */
+    U8                      SGLOffset2;                     /* 0x16 */
+    U8                      SGLOffset3;                     /* 0x17 */
+    U32                     SkipCount;                      /* 0x18 */
+    U32                     DataLength;                     /* 0x1C */
+    U32                     BidirectionalDataLength;        /* 0x20 */
+    U16                     IoFlags;                        /* 0x24 */
+    U16                     EEDPFlags;                      /* 0x26 */
+    U32                     EEDPBlockSize;                  /* 0x28 */
+    U32                     SecondaryReferenceTag;          /* 0x2C */
+    U16                     SecondaryApplicationTag;        /* 0x30 */
+    U16                     ApplicationTagTranslationMask;  /* 0x32 */
+    U8                      LUN[8];                         /* 0x34 */
+    U32                     Control;                        /* 0x3C */
+    MPI2_SCSI_IO_CDB_UNION  CDB;                            /* 0x40 */
+    MPI2_SGE_IO_UNION       SGL;                            /* 0x60 */
+} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
+  Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
+
+/* SCSI IO MsgFlags bits */
+
+/* MsgFlags for SenseBufferAddressSpace */
+#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR        (0x0C)
+#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR      (0x00)
+#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR      (0x04)
+#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR      (0x08)
+#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR   (0x0C)
+
+/* SCSI IO SGLFlags bits */
+
+/* base values for Data Location Address Space */
+#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK              (0x0C)
+#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR            (0x00)
+#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR            (0x04)
+#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR            (0x08)
+#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR         (0x0C)
+
+/* base values for Type */
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK              (0x03)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI               (0x00)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32            (0x01)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64            (0x02)
+
+/* shift values for each sub-field */
+#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT             (12)
+#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT             (8)
+#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT             (4)
+#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT             (0)
+
+/* SCSI IO IoFlags bits */
+
+/* Large CDB Address Space */
+#define MPI2_SCSIIO_CDB_ADDR_MASK                   (0x6000)
+#define MPI2_SCSIIO_CDB_ADDR_SYSTEM                 (0x0000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCDDR                 (0x2000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCPLB                 (0x4000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA              (0x6000)
+
+#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB               (0x1000)
+#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL           (0x0800)
+#define MPI2_SCSIIO_IOFLAGS_MULTICAST               (0x0400)
+#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
+#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK          (0x01FF)
+
+/* SCSI IO EEDPFlags bits */
+
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG        (0x8000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG        (0x4000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG        (0x2000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG        (0x1000)
+
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG          (0x0400)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG          (0x0200)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD           (0x0100)
+
+#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG       (0x0008)
+
+#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP               (0x0007)
+#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP               (0x0000)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP              (0x0001)
+#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP              (0x0002)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP       (0x0003)
+#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP             (0x0004)
+#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP            (0x0006)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP        (0x0007)
+
+/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
+
+/* SCSI IO Control bits */
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK      (0xFC000000)
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT     (26)
+
+#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK  (0x03000000)
+#define MPI2_SCSIIO_CONTROL_NODATATRANSFER      (0x00000000)
+#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
+#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL       (0x03000000)
+
+#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK        (0x00007800)
+#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT       (11)
+
+#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK  (0x00000700)
+#define MPI2_SCSIIO_CONTROL_SIMPLEQ             (0x00000000)
+#define MPI2_SCSIIO_CONTROL_HEADOFQ             (0x00000100)
+#define MPI2_SCSIIO_CONTROL_ORDEREDQ            (0x00000200)
+#define MPI2_SCSIIO_CONTROL_ACAQ                (0x00000400)
+
+#define MPI2_SCSIIO_CONTROL_TLR_MASK            (0x000000C0)
+#define MPI2_SCSIIO_CONTROL_NO_TLR              (0x00000000)
+#define MPI2_SCSIIO_CONTROL_TLR_ON              (0x00000040)
+#define MPI2_SCSIIO_CONTROL_TLR_OFF             (0x00000080)
+
+
+/* SCSI IO Error Reply Message */
+typedef struct _MPI2_SCSI_IO_REPLY
+{
+    U16                     DevHandle;                      /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved1;                      /* 0x04 */
+    U8                      Reserved2;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved3;                      /* 0x0A */
+    U8                      SCSIStatus;                     /* 0x0C */
+    U8                      SCSIState;                      /* 0x0D */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+    U32                     TransferCount;                  /* 0x14 */
+    U32                     SenseCount;                     /* 0x18 */
+    U32                     ResponseInfo;                   /* 0x1C */
+    U16                     TaskTag;                        /* 0x20 */
+    U16                     Reserved4;                      /* 0x22 */
+    U32                     BidirectionalTransferCount;     /* 0x24 */
+    U32                     Reserved5;                      /* 0x28 */
+    U32                     Reserved6;                      /* 0x2C */
+} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY,
+  Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t;
+
+/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
+
+#define MPI2_SCSI_STATUS_GOOD                   (0x00)
+#define MPI2_SCSI_STATUS_CHECK_CONDITION        (0x02)
+#define MPI2_SCSI_STATUS_CONDITION_MET          (0x04)
+#define MPI2_SCSI_STATUS_BUSY                   (0x08)
+#define MPI2_SCSI_STATUS_INTERMEDIATE           (0x10)
+#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET   (0x14)
+#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT   (0x18)
+#define MPI2_SCSI_STATUS_COMMAND_TERMINATED     (0x22) /* obsolete */
+#define MPI2_SCSI_STATUS_TASK_SET_FULL          (0x28)
+#define MPI2_SCSI_STATUS_ACA_ACTIVE             (0x30)
+#define MPI2_SCSI_STATUS_TASK_ABORTED           (0x40)
+
+/* SCSI IO Reply SCSIState flags */
+
+#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID     (0x10)
+#define MPI2_SCSI_STATE_TERMINATED              (0x08)
+#define MPI2_SCSI_STATE_NO_SCSI_STATUS          (0x04)
+#define MPI2_SCSI_STATE_AUTOSENSE_FAILED        (0x02)
+#define MPI2_SCSI_STATE_AUTOSENSE_VALID         (0x01)
+
+/* masks and shifts for the ResponseInfo field */
+
+#define MPI2_SCSI_RI_MASK_REASONCODE            (0x000000FF)
+#define MPI2_SCSI_RI_SHIFT_REASONCODE           (0)
+
+#define MPI2_SCSI_TASKTAG_UNKNOWN               (0xFFFF)
+
+
+/****************************************************************************
+*  SCSI Task Management messages
+****************************************************************************/
+
+/* SCSI Task Management Request Message */
+typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
+{
+    U16                     DevHandle;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U8                      Reserved1;                      /* 0x04 */
+    U8                      TaskType;                       /* 0x05 */
+    U8                      Reserved2;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved3;                      /* 0x0A */
+    U8                      LUN[8];                         /* 0x0C */
+    U32                     Reserved4[7];                   /* 0x14 */
+    U16                     TaskMID;                        /* 0x30 */
+    U16                     Reserved5;                      /* 0x32 */
+} MPI2_SCSI_TASK_MANAGE_REQUEST,
+  MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
+  Mpi2SCSITaskManagementRequest_t,
+  MPI2_POINTER pMpi2SCSITaskManagementRequest_t;
+
+/* TaskType values */
+
+#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK           (0x01)
+#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET        (0x02)
+#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET         (0x03)
+#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET   (0x05)
+#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET       (0x06)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK           (0x07)
+#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA              (0x08)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET         (0x09)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT      (0x0A)
+
+/* obsolete TaskType name */
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION   (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
+
+/* MsgFlags bits */
+
+#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET    (0x18)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET           (0x00)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST     (0x08)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET  (0x10)
+
+#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU  (0x01)
+
+
+
+/* SCSI Task Management Reply Message */
+typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY
+{
+    U16                     DevHandle;                      /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U8                      ResponseCode;                   /* 0x04 */
+    U8                      TaskType;                       /* 0x05 */
+    U8                      Reserved1;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved2;                      /* 0x0A */
+    U16                     Reserved3;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+    U32                     TerminationCount;               /* 0x14 */
+    U32                     ResponseInfo;                   /* 0x18 */
+} MPI2_SCSI_TASK_MANAGE_REPLY,
+  MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
+  Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t;
+
+/* ResponseCode values */
+
+#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE               (0x00)
+#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME             (0x02)
+#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED          (0x04)
+#define MPI2_SCSITASKMGMT_RSP_TM_FAILED                 (0x05)
+#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED              (0x08)
+#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN            (0x09)
+#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG         (0x0A)
+#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC          (0x80)
+
+/* masks and shifts for the ResponseInfo field */
+
+#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE            (0x000000FF)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE           (0)
+#define MPI2_SCSITASKMGMT_RI_MASK_ARI2                  (0x0000FF00)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2                 (8)
+#define MPI2_SCSITASKMGMT_RI_MASK_ARI1                  (0x00FF0000)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1                 (16)
+#define MPI2_SCSITASKMGMT_RI_MASK_ARI0                  (0xFF000000)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0                 (24)
+
+
+/****************************************************************************
+*  SCSI Enclosure Processor messages
+****************************************************************************/
+
+/* SCSI Enclosure Processor Request Message */
+typedef struct _MPI2_SEP_REQUEST
+{
+    U16                     DevHandle;          /* 0x00 */
+    U8                      ChainOffset;        /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U8                      Action;             /* 0x04 */
+    U8                      Flags;              /* 0x05 */
+    U8                      Reserved1;          /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved2;          /* 0x0A */
+    U32                     SlotStatus;         /* 0x0C */
+    U32                     Reserved3;          /* 0x10 */
+    U32                     Reserved4;          /* 0x14 */
+    U32                     Reserved5;          /* 0x18 */
+    U16                     Slot;               /* 0x1C */
+    U16                     EnclosureHandle;    /* 0x1E */
+} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST,
+  Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t;
+
+/* Action defines */
+#define MPI2_SEP_REQ_ACTION_WRITE_STATUS                (0x00)
+#define MPI2_SEP_REQ_ACTION_READ_STATUS                 (0x01)
+
+/* Flags defines */
+#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS            (0x00)
+#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS       (0x01)
+
+/* SlotStatus defines */
+#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE          (0x00040000)
+#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST        (0x00020000)
+#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED         (0x00000200)
+#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE               (0x00000100)
+#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED            (0x00000080)
+#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT         (0x00000040)
+#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY       (0x00000010)
+#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY         (0x00000008)
+#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING          (0x00000004)
+#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY              (0x00000002)
+#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR                (0x00000001)
+
+
+/* SCSI Enclosure Processor Reply Message */
+typedef struct _MPI2_SEP_REPLY
+{
+    U16                     DevHandle;          /* 0x00 */
+    U8                      MsgLength;          /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U8                      Action;             /* 0x04 */
+    U8                      Flags;              /* 0x05 */
+    U8                      Reserved1;          /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved2;          /* 0x0A */
+    U16                     Reserved3;          /* 0x0C */
+    U16                     IOCStatus;          /* 0x0E */
+    U32                     IOCLogInfo;         /* 0x10 */
+    U32                     SlotStatus;         /* 0x14 */
+    U32                     Reserved4;          /* 0x18 */
+    U16                     Slot;               /* 0x1C */
+    U16                     EnclosureHandle;    /* 0x1E */
+} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY,
+  Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t;
+
+/* SlotStatus defines */
+#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY          (0x00040000)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST      (0x00020000)
+#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED       (0x00000200)
+#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE             (0x00000100)
+#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED          (0x00000080)
+#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT       (0x00000040)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY     (0x00000010)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY       (0x00000008)
+#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING        (0x00000004)
+#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY            (0x00000002)
+#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR              (0x00000001)
+
+
+#endif
+
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_ioc.h ../../stable/8/sys/dev/mps/mpi/mpi2_ioc.h
--- sys/dev/mps/mpi/mpi2_ioc.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_ioc.h	2011-01-07 14:33:12.661552076 -0700
@@ -0,0 +1,1414 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_ioc.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_ioc.h
+ *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
+ *  Creation Date:  October 11, 2006
+ *
+ *  mpi2_ioc.h Version:  02.00.13
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  In IOCFacts Reply structure, renamed MaxDevices to
+ *                      MaxTargets.
+ *                      Added TotalImageSize field to FWDownload Request.
+ *                      Added reserved words to FWUpload Request.
+ *  06-26-07  02.00.02  Added IR Configuration Change List Event.
+ *  08-31-07  02.00.03  Removed SystemReplyQueueDepth field from the IOCInit
+ *                      request and replaced it with
+ *                      ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
+ *                      Replaced the MinReplyQueueDepth field of the IOCFacts
+ *                      reply with MaxReplyDescriptorPostQueueDepth.
+ *                      Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
+ *                      depth for the Reply Descriptor Post Queue.
+ *                      Added SASAddress field to Initiator Device Table
+ *                      Overflow Event data.
+ *  10-31-07  02.00.04  Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
+ *                      for SAS Initiator Device Status Change Event data.
+ *                      Modified Reason Code defines for SAS Topology Change
+ *                      List Event data, including adding a bit for PHY Vacant
+ *                      status, and adding a mask for the Reason Code.
+ *                      Added define for
+ *                      MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
+ *                      Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
+ *  12-18-07  02.00.05  Added Boot Status defines for the IOCExceptions field of
+ *                      the IOCFacts Reply.
+ *                      Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                      Moved MPI2_VERSION_UNION to mpi2.h.
+ *                      Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
+ *                      instead of enables, and added SASBroadcastPrimitiveMasks
+ *                      field.
+ *                      Added Log Entry Added Event and related structure.
+ *  02-29-08  02.00.06  Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
+ *                      Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
+ *                      Added MaxVolumes and MaxPersistentEntries fields to
+ *                      IOCFacts reply.
+ *                      Added ProtocalFlags and IOCCapabilities fields to
+ *                      MPI2_FW_IMAGE_HEADER.
+ *                      Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
+ *  03-03-08  02.00.07  Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
+ *                      a U16 (from a U32).
+ *                      Removed extra 's' from EventMasks name.
+ *  06-27-08  02.00.08  Fixed an offset in a comment.
+ *  10-02-08  02.00.09  Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
+ *                      Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
+ *                      renamed MinReplyFrameSize to ReplyFrameSize.
+ *                      Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
+ *                      Added two new RAIDOperation values for Integrated RAID
+ *                      Operations Status Event data.
+ *                      Added four new IR Configuration Change List Event data
+ *                      ReasonCode values.
+ *                      Added two new ReasonCode defines for SAS Device Status
+ *                      Change Event data.
+ *                      Added three new DiscoveryStatus bits for the SAS
+ *                      Discovery event data.
+ *                      Added Multiplexing Status Change bit to the PhyStatus
+ *                      field of the SAS Topology Change List event data.
+ *                      Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
+ *                      BootFlags are now product-specific.
+ *                      Added defines for the indivdual signature bytes
+ *                      for MPI2_INIT_IMAGE_FOOTER.
+ *  01-19-09  02.00.10  Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
+ *                      Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
+ *                      define.
+ *                      Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
+ *                      define.
+ *                      Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
+ *  05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
+ *                      Added two new reason codes for SAS Device Status Change
+ *                      Event.
+ *                      Added new event: SAS PHY Counter.
+ *  07-30-09  02.00.12  Added GPIO Interrupt event define and structure.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                      Added new product id family for 2208.
+ *  10-28-09  02.00.13  Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
+ *                      Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
+ *                      Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
+ *                      Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
+ *                      Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
+ *                      Added Host Based Discovery Phy Event data.
+ *                      Added defines for ProductID Product field
+ *                      (MPI2_FW_HEADER_PID_).
+ *                      Modified values for SAS ProductID Family
+ *                      (MPI2_FW_HEADER_PID_FAMILY_).
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_IOC_H
+#define MPI2_IOC_H
+
+/*****************************************************************************
+*
+*               IOC Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  IOCInit message
+****************************************************************************/
+
+/* IOCInit Request message */
+typedef struct _MPI2_IOC_INIT_REQUEST
+{
+    U8                      WhoInit;                        /* 0x00 */
+    U8                      Reserved1;                      /* 0x01 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+    U16                     MsgVersion;                     /* 0x0C */
+    U16                     HeaderVersion;                  /* 0x0E */
+    U32                     Reserved5;                      /* 0x10 */
+    U16                     Reserved6;                      /* 0x14 */
+    U8                      Reserved7;                      /* 0x16 */
+    U8                      HostMSIxVectors;                /* 0x17 */
+    U16                     Reserved8;                      /* 0x18 */
+    U16                     SystemRequestFrameSize;         /* 0x1A */
+    U16                     ReplyDescriptorPostQueueDepth;  /* 0x1C */
+    U16                     ReplyFreeQueueDepth;            /* 0x1E */
+    U32                     SenseBufferAddressHigh;         /* 0x20 */
+    U32                     SystemReplyAddressHigh;         /* 0x24 */
+    U64                     SystemRequestFrameBaseAddress;  /* 0x28 */
+    U64                     ReplyDescriptorPostQueueAddress;/* 0x30 */
+    U64                     ReplyFreeQueueAddress;          /* 0x38 */
+    U64                     TimeStamp;                      /* 0x40 */
+} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
+  Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
+
+/* WhoInit values */
+#define MPI2_WHOINIT_NOT_INITIALIZED            (0x00)
+#define MPI2_WHOINIT_SYSTEM_BIOS                (0x01)
+#define MPI2_WHOINIT_ROM_BIOS                   (0x02)
+#define MPI2_WHOINIT_PCI_PEER                   (0x03)
+#define MPI2_WHOINIT_HOST_DRIVER                (0x04)
+#define MPI2_WHOINIT_MANUFACTURER               (0x05)
+
+/* MsgVersion */
+#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK      (0xFF00)
+#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT     (8)
+#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK      (0x00FF)
+#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT     (0)
+
+/* HeaderVersion */
+#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK       (0xFF00)
+#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT      (8)
+#define MPI2_IOCINIT_HDRVERSION_DEV_MASK        (0x00FF)
+#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT       (0)
+
+/* minimum depth for the Reply Descriptor Post Queue */
+#define MPI2_RDPQ_DEPTH_MIN                     (16)
+
+
+/* IOCInit Reply message */
+typedef struct _MPI2_IOC_INIT_REPLY
+{
+    U8                      WhoInit;                        /* 0x00 */
+    U8                      Reserved1;                      /* 0x01 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+    U16                     Reserved5;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY,
+  Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t;
+
+
+/****************************************************************************
+*  IOCFacts message
+****************************************************************************/
+
+/* IOCFacts Request message */
+typedef struct _MPI2_IOC_FACTS_REQUEST
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST,
+  Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t;
+
+
+/* IOCFacts Reply message */
+typedef struct _MPI2_IOC_FACTS_REPLY
+{
+    U16                     MsgVersion;                     /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     HeaderVersion;                  /* 0x04 */
+    U8                      IOCNumber;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved1;                      /* 0x0A */
+    U16                     IOCExceptions;                  /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+    U8                      MaxChainDepth;                  /* 0x14 */
+    U8                      WhoInit;                        /* 0x15 */
+    U8                      NumberOfPorts;                  /* 0x16 */
+    U8                      MaxMSIxVectors;                 /* 0x17 */
+    U16                     RequestCredit;                  /* 0x18 */
+    U16                     ProductID;                      /* 0x1A */
+    U32                     IOCCapabilities;                /* 0x1C */
+    MPI2_VERSION_UNION      FWVersion;                      /* 0x20 */
+    U16                     IOCRequestFrameSize;            /* 0x24 */
+    U16                     Reserved3;                      /* 0x26 */
+    U16                     MaxInitiators;                  /* 0x28 */
+    U16                     MaxTargets;                     /* 0x2A */
+    U16                     MaxSasExpanders;                /* 0x2C */
+    U16                     MaxEnclosures;                  /* 0x2E */
+    U16                     ProtocolFlags;                  /* 0x30 */
+    U16                     HighPriorityCredit;             /* 0x32 */
+    U16                     MaxReplyDescriptorPostQueueDepth; /* 0x34 */
+    U8                      ReplyFrameSize;                 /* 0x36 */
+    U8                      MaxVolumes;                     /* 0x37 */
+    U16                     MaxDevHandle;                   /* 0x38 */
+    U16                     MaxPersistentEntries;           /* 0x3A */
+    U16                     MinDevHandle;                   /* 0x3C */
+    U16                     Reserved4;                      /* 0x3E */
+} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY,
+  Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t;
+
+/* MsgVersion */
+#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT            (8)
+#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK             (0x00FF)
+#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT            (0)
+
+/* HeaderVersion */
+#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK              (0xFF00)
+#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT             (8)
+#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK               (0x00FF)
+#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT              (0)
+
+/* IOCExceptions */
+#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX      (0x0100)
+
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK              (0x00E0)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD              (0x0000)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP            (0x0020)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED          (0x0040)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP    (0x0060)
+
+#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED       (0x0010)
+#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL     (0x0008)
+#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL           (0x0004)
+#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID        (0x0002)
+#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL       (0x0001)
+
+/* defines for WhoInit field are after the IOCInit Request */
+
+/* ProductID field uses MPI2_FW_HEADER_PID_ */
+
+/* IOCCapabilities */
+#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY   (0x00010000)
+#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX            (0x00008000)
+#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR       (0x00004000)
+#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY           (0x00002000)
+#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID        (0x00001000)
+#define MPI2_IOCFACTS_CAPABILITY_TLR                    (0x00000800)
+#define MPI2_IOCFACTS_CAPABILITY_MULTICAST              (0x00000100)
+#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET   (0x00000080)
+#define MPI2_IOCFACTS_CAPABILITY_EEDP                   (0x00000040)
+#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER        (0x00000020)
+#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER        (0x00000010)
+#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER      (0x00000008)
+#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
+
+/* ProtocolFlags */
+#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET              (0x0001)
+#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR           (0x0002)
+
+
+/****************************************************************************
+*  PortFacts message
+****************************************************************************/
+
+/* PortFacts Request message */
+typedef struct _MPI2_PORT_FACTS_REQUEST
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      PortNumber;                     /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved3;                      /* 0x0A */
+} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST,
+  Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t;
+
+/* PortFacts Reply message */
+typedef struct _MPI2_PORT_FACTS_REPLY
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      PortNumber;                     /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved3;                      /* 0x0A */
+    U16                     Reserved4;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+    U8                      Reserved5;                      /* 0x14 */
+    U8                      PortType;                       /* 0x15 */
+    U16                     Reserved6;                      /* 0x16 */
+    U16                     MaxPostedCmdBuffers;            /* 0x18 */
+    U16                     Reserved7;                      /* 0x1A */
+} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY,
+  Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t;
+
+/* PortType values */
+#define MPI2_PORTFACTS_PORTTYPE_INACTIVE            (0x00)
+#define MPI2_PORTFACTS_PORTTYPE_FC                  (0x10)
+#define MPI2_PORTFACTS_PORTTYPE_ISCSI               (0x20)
+#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL        (0x30)
+#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL         (0x31)
+
+
+/****************************************************************************
+*  PortEnable message
+****************************************************************************/
+
+/* PortEnable Request message */
+typedef struct _MPI2_PORT_ENABLE_REQUEST
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U8                      Reserved2;                      /* 0x04 */
+    U8                      PortFlags;                      /* 0x05 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST,
+  Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t;
+
+
+/* PortEnable Reply message */
+typedef struct _MPI2_PORT_ENABLE_REPLY
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U8                      Reserved2;                      /* 0x04 */
+    U8                      PortFlags;                      /* 0x05 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+    U16                     Reserved5;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY,
+  Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t;
+
+
+/****************************************************************************
+*  EventNotification message
+****************************************************************************/
+
+/* EventNotification Request message */
+#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS           (4)
+
+typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+    U32                     Reserved5;                      /* 0x0C */
+    U32                     Reserved6;                      /* 0x10 */
+    U32                     EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
+    U16                     SASBroadcastPrimitiveMasks;     /* 0x24 */
+    U16                     Reserved7;                      /* 0x26 */
+    U32                     Reserved8;                      /* 0x28 */
+} MPI2_EVENT_NOTIFICATION_REQUEST,
+  MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
+  Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t;
+
+
+/* EventNotification Reply message */
+typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
+{
+    U16                     EventDataLength;                /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved1;                      /* 0x04 */
+    U8                      AckRequired;                    /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved2;                      /* 0x0A */
+    U16                     Reserved3;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+    U16                     Event;                          /* 0x14 */
+    U16                     Reserved4;                      /* 0x16 */
+    U32                     EventContext;                   /* 0x18 */
+    U32                     EventData[1];                   /* 0x1C */
+} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY,
+  Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t;
+
+/* AckRequired */
+#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED    (0x00)
+#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED        (0x01)
+
+/* Event */
+#define MPI2_EVENT_LOG_DATA                         (0x0001)
+#define MPI2_EVENT_STATE_CHANGE                     (0x0002)
+#define MPI2_EVENT_HARD_RESET_RECEIVED              (0x0005)
+#define MPI2_EVENT_EVENT_CHANGE                     (0x000A)
+#define MPI2_EVENT_TASK_SET_FULL                    (0x000E)
+#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE         (0x000F)
+#define MPI2_EVENT_IR_OPERATION_STATUS              (0x0014)
+#define MPI2_EVENT_SAS_DISCOVERY                    (0x0016)
+#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE          (0x0017)
+#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE    (0x0018)
+#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW          (0x0019)
+#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST         (0x001C)
+#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE    (0x001D)
+#define MPI2_EVENT_IR_VOLUME                        (0x001E)
+#define MPI2_EVENT_IR_PHYSICAL_DISK                 (0x001F)
+#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST     (0x0020)
+#define MPI2_EVENT_LOG_ENTRY_ADDED                  (0x0021)
+#define MPI2_EVENT_SAS_PHY_COUNTER                  (0x0022)
+#define MPI2_EVENT_GPIO_INTERRUPT                   (0x0023)
+#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY         (0x0024)
+
+
+/* Log Entry Added Event data */
+
+/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
+#define MPI2_EVENT_DATA_LOG_DATA_LENGTH             (0x1C)
+
+typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED
+{
+    U64         TimeStamp;                          /* 0x00 */
+    U32         Reserved1;                          /* 0x08 */
+    U16         LogSequence;                        /* 0x0C */
+    U16         LogEntryQualifier;                  /* 0x0E */
+    U8          VP_ID;                              /* 0x10 */
+    U8          VF_ID;                              /* 0x11 */
+    U16         Reserved2;                          /* 0x12 */
+    U8          LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */
+} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
+  Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t;
+
+/* GPIO Interrupt Event data */
+
+typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT
+{
+    U8          GPIONum;                            /* 0x00 */
+    U8          Reserved1;                          /* 0x01 */
+    U16         Reserved2;                          /* 0x02 */
+} MPI2_EVENT_DATA_GPIO_INTERRUPT,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
+  Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t;
+
+/* Hard Reset Received Event data */
+
+typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
+{
+    U8                      Reserved1;                      /* 0x00 */
+    U8                      Port;                           /* 0x01 */
+    U16                     Reserved2;                      /* 0x02 */
+} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
+  Mpi2EventDataHardResetReceived_t,
+  MPI2_POINTER pMpi2EventDataHardResetReceived_t;
+
+/* Task Set Full Event data */
+
+typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
+{
+    U16                     DevHandle;                      /* 0x00 */
+    U16                     CurrentDepth;                   /* 0x02 */
+} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
+  Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t;
+
+
+/* SAS Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
+{
+    U16                     TaskTag;                        /* 0x00 */
+    U8                      ReasonCode;                     /* 0x02 */
+    U8                      Reserved1;                      /* 0x03 */
+    U8                      ASC;                            /* 0x04 */
+    U8                      ASCQ;                           /* 0x05 */
+    U16                     DevHandle;                      /* 0x06 */
+    U32                     Reserved2;                      /* 0x08 */
+    U64                     SASAddress;                     /* 0x0C */
+    U8                      LUN[8];                         /* 0x14 */
+} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+  Mpi2EventDataSasDeviceStatusChange_t,
+  MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t;
+
+/* SAS Device Status Change Event data ReasonCode values */
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA                           (0x05)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED                          (0x07)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET                (0x08)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL                  (0x09)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL              (0x0A)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL              (0x0B)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL                  (0x0C)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION                   (0x0D)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET               (0x0E)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL              (0x0F)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE                    (0x10)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY       (0x11)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY   (0x12)
+
+
+/* Integrated RAID Operation Status Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS
+{
+    U16                     VolDevHandle;               /* 0x00 */
+    U16                     Reserved1;                  /* 0x02 */
+    U8                      RAIDOperation;              /* 0x04 */
+    U8                      PercentComplete;            /* 0x05 */
+    U16                     Reserved2;                  /* 0x06 */
+    U32                     Resereved3;                 /* 0x08 */
+} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
+  Mpi2EventDataIrOperationStatus_t,
+  MPI2_POINTER pMpi2EventDataIrOperationStatus_t;
+
+/* Integrated RAID Operation Status Event data RAIDOperation values */
+#define MPI2_EVENT_IR_RAIDOP_RESYNC                     (0x00)
+#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION       (0x01)
+#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK          (0x02)
+#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT            (0x03)
+#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT       (0x04)
+
+
+/* Integrated RAID Volume Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_VOLUME
+{
+    U16                     VolDevHandle;               /* 0x00 */
+    U8                      ReasonCode;                 /* 0x02 */
+    U8                      Reserved1;                  /* 0x03 */
+    U32                     NewValue;                   /* 0x04 */
+    U32                     PreviousValue;              /* 0x08 */
+} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME,
+  Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t;
+
+/* Integrated RAID Volume Event data ReasonCode values */
+#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED        (0x01)
+#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED    (0x02)
+#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED           (0x03)
+
+
+/* Integrated RAID Physical Disk Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK
+{
+    U16                     Reserved1;                  /* 0x00 */
+    U8                      ReasonCode;                 /* 0x02 */
+    U8                      PhysDiskNum;                /* 0x03 */
+    U16                     PhysDiskDevHandle;          /* 0x04 */
+    U16                     Reserved2;                  /* 0x06 */
+    U16                     Slot;                       /* 0x08 */
+    U16                     EnclosureHandle;            /* 0x0A */
+    U32                     NewValue;                   /* 0x0C */
+    U32                     PreviousValue;              /* 0x10 */
+} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
+  Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t;
+
+/* Integrated RAID Physical Disk Event data ReasonCode values */
+#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED      (0x01)
+#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED  (0x02)
+#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED         (0x03)
+
+
+/* Integrated RAID Configuration Change List Event data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumElements at runtime.
+ */
+#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
+#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT          (1)
+#endif
+
+typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT
+{
+    U16                     ElementFlags;               /* 0x00 */
+    U16                     VolDevHandle;               /* 0x02 */
+    U8                      ReasonCode;                 /* 0x04 */
+    U8                      PhysDiskNum;                /* 0x05 */
+    U16                     PhysDiskDevHandle;          /* 0x06 */
+} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
+  Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t;
+
+/* IR Configuration Change List Event data ElementFlags values */
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK   (0x000F)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT      (0x0000)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT    (0x0002)
+
+/* IR Configuration Change List Event data ReasonCode values */
+#define MPI2_EVENT_IR_CHANGE_RC_ADDED                   (0x01)
+#define MPI2_EVENT_IR_CHANGE_RC_REMOVED                 (0x02)
+#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE               (0x03)
+#define MPI2_EVENT_IR_CHANGE_RC_HIDE                    (0x04)
+#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE                  (0x05)
+#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED          (0x06)
+#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED          (0x07)
+#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED              (0x08)
+#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED              (0x09)
+
+typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST
+{
+    U8                              NumElements;        /* 0x00 */
+    U8                              Reserved1;          /* 0x01 */
+    U8                              Reserved2;          /* 0x02 */
+    U8                              ConfigNum;          /* 0x03 */
+    U32                             Flags;              /* 0x04 */
+    MPI2_EVENT_IR_CONFIG_ELEMENT    ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];    /* 0x08 */
+} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
+  Mpi2EventDataIrConfigChangeList_t,
+  MPI2_POINTER pMpi2EventDataIrConfigChangeList_t;
+
+/* IR Configuration Change List Event data Flags values */
+#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG   (0x00000001)
+
+
+/* SAS Discovery Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY
+{
+    U8                      Flags;                      /* 0x00 */
+    U8                      ReasonCode;                 /* 0x01 */
+    U8                      PhysicalPort;               /* 0x02 */
+    U8                      Reserved1;                  /* 0x03 */
+    U32                     DiscoveryStatus;            /* 0x04 */
+} MPI2_EVENT_DATA_SAS_DISCOVERY,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
+  Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t;
+
+/* SAS Discovery Event data Flags values */
+#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE                   (0x02)
+#define MPI2_EVENT_SAS_DISC_IN_PROGRESS                     (0x01)
+
+/* SAS Discovery Event data ReasonCode values */
+#define MPI2_EVENT_SAS_DISC_RC_STARTED                      (0x01)
+#define MPI2_EVENT_SAS_DISC_RC_COMPLETED                    (0x02)
+
+/* SAS Discovery Event data DiscoveryStatus values */
+#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED            (0x80000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED             (0x40000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED               (0x20000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED             (0x10000000)
+#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR             (0x08000000)
+#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE    (0x00008000)
+#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE            (0x00004000)
+#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN                (0x00002000)
+#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK        (0x00001000)
+#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE               (0x00000800)
+#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK                       (0x00000400)
+#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK                 (0x00000200)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR                    (0x00000100)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED              (0x00000080)
+#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST                  (0x00000040)
+#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES                (0x00000020)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT                      (0x00000010)
+#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS                   (0x00000004)
+#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE             (0x00000002)
+#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED                    (0x00000001)
+
+
+/* SAS Broadcast Primitive Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
+{
+    U8                      PhyNum;                     /* 0x00 */
+    U8                      Port;                       /* 0x01 */
+    U8                      PortWidth;                  /* 0x02 */
+    U8                      Primitive;                  /* 0x03 */
+} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+  Mpi2EventDataSasBroadcastPrimitive_t,
+  MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t;
+
+/* defines for the Primitive field */
+#define MPI2_EVENT_PRIMITIVE_CHANGE                         (0x01)
+#define MPI2_EVENT_PRIMITIVE_SES                            (0x02)
+#define MPI2_EVENT_PRIMITIVE_EXPANDER                       (0x03)
+#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT             (0x04)
+#define MPI2_EVENT_PRIMITIVE_RESERVED3                      (0x05)
+#define MPI2_EVENT_PRIMITIVE_RESERVED4                      (0x06)
+#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED               (0x07)
+#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED               (0x08)
+
+
+/* SAS Initiator Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
+{
+    U8                      ReasonCode;                 /* 0x00 */
+    U8                      PhysicalPort;               /* 0x01 */
+    U16                     DevHandle;                  /* 0x02 */
+    U64                     SASAddress;                 /* 0x04 */
+} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+  Mpi2EventDataSasInitDevStatusChange_t,
+  MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t;
+
+/* SAS Initiator Device Status Change event ReasonCode values */
+#define MPI2_EVENT_SAS_INIT_RC_ADDED                (0x01)
+#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING       (0x02)
+
+
+/* SAS Initiator Device Table Overflow Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
+{
+    U16                     MaxInit;                    /* 0x00 */
+    U16                     CurrentInit;                /* 0x02 */
+    U64                     SASAddress;                 /* 0x04 */
+} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+  Mpi2EventDataSasInitTableOverflow_t,
+  MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t;
+
+
+/* SAS Topology Change List Event data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumEntries at runtime.
+ */
+#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
+#define MPI2_EVENT_SAS_TOPO_PHY_COUNT           (1)
+#endif
+
+typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY
+{
+    U16                     AttachedDevHandle;          /* 0x00 */
+    U8                      LinkRate;                   /* 0x02 */
+    U8                      PhyStatus;                  /* 0x03 */
+} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
+  Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t;
+
+typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
+{
+    U16                             EnclosureHandle;            /* 0x00 */
+    U16                             ExpanderDevHandle;          /* 0x02 */
+    U8                              NumPhys;                    /* 0x04 */
+    U8                              Reserved1;                  /* 0x05 */
+    U16                             Reserved2;                  /* 0x06 */
+    U8                              NumEntries;                 /* 0x08 */
+    U8                              StartPhyNum;                /* 0x09 */
+    U8                              ExpStatus;                  /* 0x0A */
+    U8                              PhysicalPort;               /* 0x0B */
+    MPI2_EVENT_SAS_TOPO_PHY_ENTRY   PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/
+} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
+  Mpi2EventDataSasTopologyChangeList_t,
+  MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t;
+
+/* values for the ExpStatus field */
+#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER                  (0x00)
+#define MPI2_EVENT_SAS_TOPO_ES_ADDED                        (0x01)
+#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING               (0x02)
+#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING                   (0x03)
+#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING         (0x04)
+
+/* defines for the LinkRate field */
+#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK                 (0xF0)
+#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT                (4)
+#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK                    (0x0F)
+#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT                   (0)
+
+#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE            (0x00)
+#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED                 (0x01)
+#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED           (0x02)
+#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE            (0x03)
+#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR                (0x04)
+#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS        (0x05)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5                     (0x08)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0                     (0x09)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0                     (0x0A)
+
+/* values for the PhyStatus field */
+#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT                (0x80)
+#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE             (0x10)
+/* values for the PhyStatus ReasonCode sub-field */
+#define MPI2_EVENT_SAS_TOPO_RC_MASK                         (0x0F)
+#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED                   (0x01)
+#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING          (0x02)
+#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED                  (0x03)
+#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE                    (0x04)
+#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING         (0x05)
+
+
+/* SAS Enclosure Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
+{
+    U16                     EnclosureHandle;            /* 0x00 */
+    U8                      ReasonCode;                 /* 0x02 */
+    U8                      PhysicalPort;               /* 0x03 */
+    U64                     EnclosureLogicalID;         /* 0x04 */
+    U16                     NumSlots;                   /* 0x0C */
+    U16                     StartSlot;                  /* 0x0E */
+    U32                     PhyBits;                    /* 0x10 */
+} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
+  Mpi2EventDataSasEnclDevStatusChange_t,
+  MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t;
+
+/* SAS Enclosure Device Status Change event ReasonCode values */
+#define MPI2_EVENT_SAS_ENCL_RC_ADDED                (0x01)
+#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING       (0x02)
+
+
+/* SAS PHY Counter Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER
+{
+    U64         TimeStamp;          /* 0x00 */
+    U32         Reserved1;          /* 0x08 */
+    U8          PhyEventCode;       /* 0x0C */
+    U8          PhyNum;             /* 0x0D */
+    U16         Reserved2;          /* 0x0E */
+    U32         PhyEventInfo;       /* 0x10 */
+    U8          CounterType;        /* 0x14 */
+    U8          ThresholdWindow;    /* 0x15 */
+    U8          TimeUnits;          /* 0x16 */
+    U8          Reserved3;          /* 0x17 */
+    U32         EventThreshold;     /* 0x18 */
+    U16         ThresholdFlags;     /* 0x1C */
+    U16         Reserved4;          /* 0x1E */
+} MPI2_EVENT_DATA_SAS_PHY_COUNTER,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER,
+  Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t;
+
+/* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the PhyEventCode field */
+
+/* use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the CounterType field */
+
+/* use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the TimeUnits field */
+
+/* use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the ThresholdFlags field */
+
+
+/* Host Based Discovery Phy Event data */
+
+typedef struct _MPI2_EVENT_HBD_PHY_SAS
+{
+    U8          Flags;                      /* 0x00 */
+    U8          NegotiatedLinkRate;         /* 0x01 */
+    U8          PhyNum;                     /* 0x02 */
+    U8          PhysicalPort;               /* 0x03 */
+    U32         Reserved1;                  /* 0x04 */
+    U8          InitialFrame[28];           /* 0x08 */
+} MPI2_EVENT_HBD_PHY_SAS, MPI2_POINTER PTR_MPI2_EVENT_HBD_PHY_SAS,
+  Mpi2EventHbdPhySas_t, MPI2_POINTER pMpi2EventHbdPhySas_t;
+
+/* values for the Flags field */
+#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID        (0x02)
+#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME         (0x01)
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h for the NegotiatedLinkRate field */
+
+typedef union _MPI2_EVENT_HBD_DESCRIPTOR
+{
+    MPI2_EVENT_HBD_PHY_SAS      Sas;
+} MPI2_EVENT_HBD_DESCRIPTOR, MPI2_POINTER PTR_MPI2_EVENT_HBD_DESCRIPTOR,
+  Mpi2EventHbdDescriptor_t, MPI2_POINTER pMpi2EventHbdDescriptor_t;
+
+typedef struct _MPI2_EVENT_DATA_HBD_PHY
+{
+    U8                          DescriptorType;     /* 0x00 */
+    U8                          Reserved1;          /* 0x01 */
+    U16                         Reserved2;          /* 0x02 */
+    U32                         Reserved3;          /* 0x04 */
+    MPI2_EVENT_HBD_DESCRIPTOR   Descriptor;         /* 0x08 */
+} MPI2_EVENT_DATA_HBD_PHY, MPI2_POINTER PTR_MPI2_EVENT_DATA_HBD_PHY,
+  Mpi2EventDataHbdPhy_t, MPI2_POINTER pMpi2EventDataMpi2EventDataHbdPhy_t;
+
+/* values for the DescriptorType field */
+#define MPI2_EVENT_HBD_DT_SAS               (0x01)
+
+
+
+/****************************************************************************
+*  EventAck message
+****************************************************************************/
+
+/* EventAck Request message */
+typedef struct _MPI2_EVENT_ACK_REQUEST
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+    U16                     Event;                          /* 0x0C */
+    U16                     Reserved5;                      /* 0x0E */
+    U32                     EventContext;                   /* 0x10 */
+} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST,
+  Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t;
+
+
+/* EventAck Reply message */
+typedef struct _MPI2_EVENT_ACK_REPLY
+{
+    U16                     Reserved1;                      /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved2;                      /* 0x04 */
+    U8                      Reserved3;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved4;                      /* 0x0A */
+    U16                     Reserved5;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY,
+  Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t;
+
+
+/****************************************************************************
+*  FWDownload message
+****************************************************************************/
+
+/* FWDownload Request message */
+typedef struct _MPI2_FW_DOWNLOAD_REQUEST
+{
+    U8                      ImageType;                  /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U32                     TotalImageSize;             /* 0x0C */
+    U32                     Reserved5;                  /* 0x10 */
+    MPI2_MPI_SGE_UNION      SGL;                        /* 0x14 */
+} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST,
+  Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest;
+
+#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT   (0x01)
+
+#define MPI2_FW_DOWNLOAD_ITYPE_FW                   (0x01)
+#define MPI2_FW_DOWNLOAD_ITYPE_BIOS                 (0x02)
+#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING        (0x06)
+#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1             (0x07)
+#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2             (0x08)
+#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID             (0x09)
+#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK    (0x0B)
+
+/* FWDownload TransactionContext Element */
+typedef struct _MPI2_FW_DOWNLOAD_TCSGE
+{
+    U8                      Reserved1;                  /* 0x00 */
+    U8                      ContextSize;                /* 0x01 */
+    U8                      DetailsLength;              /* 0x02 */
+    U8                      Flags;                      /* 0x03 */
+    U32                     Reserved2;                  /* 0x04 */
+    U32                     ImageOffset;                /* 0x08 */
+    U32                     ImageSize;                  /* 0x0C */
+} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE,
+  Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t;
+
+/* FWDownload Reply message */
+typedef struct _MPI2_FW_DOWNLOAD_REPLY
+{
+    U8                      ImageType;                  /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY,
+  Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t;
+
+
+/****************************************************************************
+*  FWUpload message
+****************************************************************************/
+
+/* FWUpload Request message */
+typedef struct _MPI2_FW_UPLOAD_REQUEST
+{
+    U8                      ImageType;                  /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U32                     Reserved5;                  /* 0x0C */
+    U32                     Reserved6;                  /* 0x10 */
+    MPI2_MPI_SGE_UNION      SGL;                        /* 0x14 */
+} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST,
+  Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t;
+
+#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT         (0x00)
+#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH           (0x01)
+#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH         (0x02)
+#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP          (0x05)
+#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING      (0x06)
+#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1           (0x07)
+#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2           (0x08)
+#define MPI2_FW_UPLOAD_ITYPE_MEGARAID           (0x09)
+#define MPI2_FW_UPLOAD_ITYPE_COMPLETE           (0x0A)
+#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK  (0x0B)
+
+typedef struct _MPI2_FW_UPLOAD_TCSGE
+{
+    U8                      Reserved1;                  /* 0x00 */
+    U8                      ContextSize;                /* 0x01 */
+    U8                      DetailsLength;              /* 0x02 */
+    U8                      Flags;                      /* 0x03 */
+    U32                     Reserved2;                  /* 0x04 */
+    U32                     ImageOffset;                /* 0x08 */
+    U32                     ImageSize;                  /* 0x0C */
+} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE,
+  Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t;
+
+/* FWUpload Reply message */
+typedef struct _MPI2_FW_UPLOAD_REPLY
+{
+    U8                      ImageType;                  /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U32                     ActualImageSize;            /* 0x14 */
+} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY,
+  Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t;
+
+
+/* FW Image Header */
+typedef struct _MPI2_FW_IMAGE_HEADER
+{
+    U32                     Signature;                  /* 0x00 */
+    U32                     Signature0;                 /* 0x04 */
+    U32                     Signature1;                 /* 0x08 */
+    U32                     Signature2;                 /* 0x0C */
+    MPI2_VERSION_UNION      MPIVersion;                 /* 0x10 */
+    MPI2_VERSION_UNION      FWVersion;                  /* 0x14 */
+    MPI2_VERSION_UNION      NVDATAVersion;              /* 0x18 */
+    MPI2_VERSION_UNION      PackageVersion;             /* 0x1C */
+    U16                     VendorID;                   /* 0x20 */
+    U16                     ProductID;                  /* 0x22 */
+    U16                     ProtocolFlags;              /* 0x24 */
+    U16                     Reserved26;                 /* 0x26 */
+    U32                     IOCCapabilities;            /* 0x28 */
+    U32                     ImageSize;                  /* 0x2C */
+    U32                     NextImageHeaderOffset;      /* 0x30 */
+    U32                     Checksum;                   /* 0x34 */
+    U32                     Reserved38;                 /* 0x38 */
+    U32                     Reserved3C;                 /* 0x3C */
+    U32                     Reserved40;                 /* 0x40 */
+    U32                     Reserved44;                 /* 0x44 */
+    U32                     Reserved48;                 /* 0x48 */
+    U32                     Reserved4C;                 /* 0x4C */
+    U32                     Reserved50;                 /* 0x50 */
+    U32                     Reserved54;                 /* 0x54 */
+    U32                     Reserved58;                 /* 0x58 */
+    U32                     Reserved5C;                 /* 0x5C */
+    U32                     Reserved60;                 /* 0x60 */
+    U32                     FirmwareVersionNameWhat;    /* 0x64 */
+    U8                      FirmwareVersionName[32];    /* 0x68 */
+    U32                     VendorNameWhat;             /* 0x88 */
+    U8                      VendorName[32];             /* 0x8C */
+    U32                     PackageNameWhat;            /* 0x88 */
+    U8                      PackageName[32];            /* 0x8C */
+    U32                     ReservedD0;                 /* 0xD0 */
+    U32                     ReservedD4;                 /* 0xD4 */
+    U32                     ReservedD8;                 /* 0xD8 */
+    U32                     ReservedDC;                 /* 0xDC */
+    U32                     ReservedE0;                 /* 0xE0 */
+    U32                     ReservedE4;                 /* 0xE4 */
+    U32                     ReservedE8;                 /* 0xE8 */
+    U32                     ReservedEC;                 /* 0xEC */
+    U32                     ReservedF0;                 /* 0xF0 */
+    U32                     ReservedF4;                 /* 0xF4 */
+    U32                     ReservedF8;                 /* 0xF8 */
+    U32                     ReservedFC;                 /* 0xFC */
+} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER,
+  Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t;
+
+/* Signature field */
+#define MPI2_FW_HEADER_SIGNATURE_OFFSET         (0x00)
+#define MPI2_FW_HEADER_SIGNATURE_MASK           (0xFF000000)
+#define MPI2_FW_HEADER_SIGNATURE                (0xEA000000)
+
+/* Signature0 field */
+#define MPI2_FW_HEADER_SIGNATURE0_OFFSET        (0x04)
+#define MPI2_FW_HEADER_SIGNATURE0               (0x5AFAA55A)
+
+/* Signature1 field */
+#define MPI2_FW_HEADER_SIGNATURE1_OFFSET        (0x08)
+#define MPI2_FW_HEADER_SIGNATURE1               (0xA55AFAA5)
+
+/* Signature2 field */
+#define MPI2_FW_HEADER_SIGNATURE2_OFFSET        (0x0C)
+#define MPI2_FW_HEADER_SIGNATURE2               (0x5AA55AFA)
+
+
+/* defines for using the ProductID field */
+#define MPI2_FW_HEADER_PID_TYPE_MASK            (0xF000)
+#define MPI2_FW_HEADER_PID_TYPE_SAS             (0x2000)
+
+#define MPI2_FW_HEADER_PID_PROD_MASK                    (0x0F00)
+#define MPI2_FW_HEADER_PID_PROD_A                       (0x0000)
+#define MPI2_FW_HEADER_PID_PROD_MASK                    (0x0F00)
+#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI   (0x0200)
+#define MPI2_FW_HEADER_PID_PROD_IR_SCSI                 (0x0700)
+
+
+#define MPI2_FW_HEADER_PID_FAMILY_MASK          (0x00FF)
+/* SAS */
+#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS      (0x0013)
+#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS      (0x0014)
+
+/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
+
+/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
+
+
+#define MPI2_FW_HEADER_IMAGESIZE_OFFSET         (0x2C)
+#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET         (0x30)
+#define MPI2_FW_HEADER_VERNMHWAT_OFFSET         (0x64)
+
+#define MPI2_FW_HEADER_WHAT_SIGNATURE           (0x29232840)
+
+#define MPI2_FW_HEADER_SIZE                     (0x100)
+
+
+/* Extended Image Header */
+typedef struct _MPI2_EXT_IMAGE_HEADER
+
+{
+    U8                      ImageType;                  /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U16                     Reserved2;                  /* 0x02 */
+    U32                     Checksum;                   /* 0x04 */
+    U32                     ImageSize;                  /* 0x08 */
+    U32                     NextImageHeaderOffset;      /* 0x0C */
+    U32                     PackageVersion;             /* 0x10 */
+    U32                     Reserved3;                  /* 0x14 */
+    U32                     Reserved4;                  /* 0x18 */
+    U32                     Reserved5;                  /* 0x1C */
+    U8                      IdentifyString[32];         /* 0x20 */
+} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER,
+  Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t;
+
+/* useful offsets */
+#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET         (0x00)
+#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET         (0x08)
+#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET         (0x0C)
+
+#define MPI2_EXT_IMAGE_HEADER_SIZE              (0x40)
+
+/* defines for the ImageType field */
+#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED         (0x00)
+#define MPI2_EXT_IMAGE_TYPE_FW                  (0x01)
+#define MPI2_EXT_IMAGE_TYPE_NVDATA              (0x03)
+#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER          (0x04)
+#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION      (0x05)
+#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT        (0x06)
+#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES   (0x07)
+#define MPI2_EXT_IMAGE_TYPE_MEGARAID            (0x08)
+
+#define MPI2_EXT_IMAGE_TYPE_MAX                 (MPI2_EXT_IMAGE_TYPE_MEGARAID)
+
+
+
+/* FLASH Layout Extended Image Data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check RegionsPerLayout at runtime.
+ */
+#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
+#define MPI2_FLASH_NUMBER_OF_REGIONS        (1)
+#endif
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumberOfLayouts at runtime.
+ */
+#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
+#define MPI2_FLASH_NUMBER_OF_LAYOUTS        (1)
+#endif
+
+typedef struct _MPI2_FLASH_REGION
+{
+    U8                      RegionType;                 /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U16                     Reserved2;                  /* 0x02 */
+    U32                     RegionOffset;               /* 0x04 */
+    U32                     RegionSize;                 /* 0x08 */
+    U32                     Reserved3;                  /* 0x0C */
+} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION,
+  Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t;
+
+typedef struct _MPI2_FLASH_LAYOUT
+{
+    U32                     FlashSize;                  /* 0x00 */
+    U32                     Reserved1;                  /* 0x04 */
+    U32                     Reserved2;                  /* 0x08 */
+    U32                     Reserved3;                  /* 0x0C */
+    MPI2_FLASH_REGION       Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */
+} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT,
+  Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t;
+
+typedef struct _MPI2_FLASH_LAYOUT_DATA
+{
+    U8                      ImageRevision;              /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      SizeOfRegion;               /* 0x02 */
+    U8                      Reserved2;                  /* 0x03 */
+    U16                     NumberOfLayouts;            /* 0x04 */
+    U16                     RegionsPerLayout;           /* 0x06 */
+    U16                     MinimumSectorAlignment;     /* 0x08 */
+    U16                     Reserved3;                  /* 0x0A */
+    U32                     Reserved4;                  /* 0x0C */
+    MPI2_FLASH_LAYOUT       Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */
+} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA,
+  Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t;
+
+/* defines for the RegionType field */
+#define MPI2_FLASH_REGION_UNUSED                (0x00)
+#define MPI2_FLASH_REGION_FIRMWARE              (0x01)
+#define MPI2_FLASH_REGION_BIOS                  (0x02)
+#define MPI2_FLASH_REGION_NVDATA                (0x03)
+#define MPI2_FLASH_REGION_FIRMWARE_BACKUP       (0x05)
+#define MPI2_FLASH_REGION_MFG_INFORMATION       (0x06)
+#define MPI2_FLASH_REGION_CONFIG_1              (0x07)
+#define MPI2_FLASH_REGION_CONFIG_2              (0x08)
+#define MPI2_FLASH_REGION_MEGARAID              (0x09)
+#define MPI2_FLASH_REGION_INIT                  (0x0A)
+
+/* ImageRevision */
+#define MPI2_FLASH_LAYOUT_IMAGE_REVISION        (0x00)
+
+
+
+/* Supported Devices Extended Image Data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumberOfDevices at runtime.
+ */
+#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
+#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES    (1)
+#endif
+
+typedef struct _MPI2_SUPPORTED_DEVICE
+{
+    U16                     DeviceID;                   /* 0x00 */
+    U16                     VendorID;                   /* 0x02 */
+    U16                     DeviceIDMask;               /* 0x04 */
+    U16                     Reserved1;                  /* 0x06 */
+    U8                      LowPCIRev;                  /* 0x08 */
+    U8                      HighPCIRev;                 /* 0x09 */
+    U16                     Reserved2;                  /* 0x0A */
+    U32                     Reserved3;                  /* 0x0C */
+} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE,
+  Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t;
+
+typedef struct _MPI2_SUPPORTED_DEVICES_DATA
+{
+    U8                      ImageRevision;              /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      NumberOfDevices;            /* 0x02 */
+    U8                      Reserved2;                  /* 0x03 */
+    U32                     Reserved3;                  /* 0x04 */
+    MPI2_SUPPORTED_DEVICE   SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */
+} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA,
+  Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t;
+
+/* ImageRevision */
+#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION   (0x00)
+
+
+/* Init Extended Image Data */
+
+typedef struct _MPI2_INIT_IMAGE_FOOTER
+
+{
+    U32                     BootFlags;                  /* 0x00 */
+    U32                     ImageSize;                  /* 0x04 */
+    U32                     Signature0;                 /* 0x08 */
+    U32                     Signature1;                 /* 0x0C */
+    U32                     Signature2;                 /* 0x10 */
+    U32                     ResetVector;                /* 0x14 */
+} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER,
+  Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t;
+
+/* defines for the BootFlags field */
+#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET        (0x00)
+
+/* defines for the ImageSize field */
+#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET        (0x04)
+
+/* defines for the Signature0 field */
+#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET       (0x08)
+#define MPI2_INIT_IMAGE_SIGNATURE0              (0x5AA55AEA)
+
+/* defines for the Signature1 field */
+#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET       (0x0C)
+#define MPI2_INIT_IMAGE_SIGNATURE1              (0xA55AEAA5)
+
+/* defines for the Signature2 field */
+#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET       (0x10)
+#define MPI2_INIT_IMAGE_SIGNATURE2              (0x5AEAA55A)
+
+/* Signature fields as individual bytes */
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0        (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1        (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2        (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3        (0x5A)
+
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4        (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5        (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6        (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7        (0xA5)
+
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8        (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9        (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A        (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B        (0x5A)
+
+/* defines for the ResetVector field */
+#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET      (0x14)
+
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_ra.h ../../stable/8/sys/dev/mps/mpi/mpi2_ra.h
--- sys/dev/mps/mpi/mpi2_ra.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_ra.h	2011-01-07 14:33:12.638459489 -0700
@@ -0,0 +1,86 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_ra.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_ra.h
+ *          Title:  MPI RAID Accelerator messages and structures
+ *  Creation Date:  April 13, 2009
+ *
+ *  mpi2_ra.h Version:  02.00.00
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  05-06-09  02.00.00  Initial version.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_RA_H
+#define MPI2_RA_H
+
+/* generic structure for RAID Accelerator Control Block */
+typedef struct _MPI2_RAID_ACCELERATOR_CONTROL_BLOCK
+{
+    U32                 Reserved[8];                /* 0x00 */
+    U32                 RaidAcceleratorCDB[1];      /* 0x20 */
+} MPI2_RAID_ACCELERATOR_CONTROL_BLOCK,
+  MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_CONTROL_BLOCK,
+  Mpi2RAIDAcceleratorControlBlock_t,
+  MPI2_POINTER pMpi2RAIDAcceleratorControlBlock_t;
+
+
+/******************************************************************************
+*
+*        RAID Accelerator Messages
+*
+*******************************************************************************/
+
+/* RAID Accelerator Request Message */
+typedef struct _MPI2_RAID_ACCELERATOR_REQUEST
+{
+    U16                     Reserved0;                          /* 0x00 */
+    U8                      ChainOffset;                        /* 0x02 */
+    U8                      Function;                           /* 0x03 */
+    U16                     Reserved1;                          /* 0x04 */
+    U8                      Reserved2;                          /* 0x06 */
+    U8                      MsgFlags;                           /* 0x07 */
+    U8                      VP_ID;                              /* 0x08 */
+    U8                      VF_ID;                              /* 0x09 */
+    U16                     Reserved3;                          /* 0x0A */
+    U64                     RaidAcceleratorControlBlockAddress; /* 0x0C */
+    U8                      DmaEngineNumber;                    /* 0x14 */
+    U8                      Reserved4;                          /* 0x15 */
+    U16                     Reserved5;                          /* 0x16 */
+    U32                     Reserved6;                          /* 0x18 */
+    U32                     Reserved7;                          /* 0x1C */
+    U32                     Reserved8;                          /* 0x20 */
+} MPI2_RAID_ACCELERATOR_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REQUEST,
+  Mpi2RAIDAcceleratorRequest_t, MPI2_POINTER pMpi2RAIDAcceleratorRequest_t;
+
+
+/* RAID Accelerator Error Reply Message */
+typedef struct _MPI2_RAID_ACCELERATOR_REPLY
+{
+    U16                     Reserved0;                      /* 0x00 */
+    U8                      MsgLength;                      /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     Reserved1;                      /* 0x04 */
+    U8                      Reserved2;                      /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved3;                      /* 0x0A */
+    U16                     Reserved4;                      /* 0x0C */
+    U16                     IOCStatus;                      /* 0x0E */
+    U32                     IOCLogInfo;                     /* 0x10 */
+    U32                     ProductSpecificData[3];         /* 0x14 */
+} MPI2_RAID_ACCELERATOR_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REPLY,
+  Mpi2RAIDAcceleratorReply_t, MPI2_POINTER pMpi2RAIDAcceleratorReply_t;
+
+
+#endif
+
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_raid.h ../../stable/8/sys/dev/mps/mpi/mpi2_raid.h
--- sys/dev/mps/mpi/mpi2_raid.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_raid.h	2011-01-07 14:33:12.696693420 -0700
@@ -0,0 +1,302 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_raid.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2008 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_raid.h
+ *          Title:  MPI Integrated RAID messages and structures
+ *  Creation Date:  April 26, 2007
+ *
+ *    mpi2_raid.h Version:  02.00.04
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  08-31-07  02.00.01  Modifications to RAID Action request and reply,
+ *                      including the Actions and ActionData.
+ *  02-29-08  02.00.02  Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
+ *  05-21-08  02.00.03  Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
+ *                      the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
+ *                      can be sized by the build environment.
+ *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
+ *                      VolumeCreationFlags and marked the old one as obsolete.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_RAID_H
+#define MPI2_RAID_H
+
+/*****************************************************************************
+*
+*               Integrated RAID Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  RAID Action messages
+****************************************************************************/
+
+/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
+#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0            (0x00000000)
+#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0            (0x00000001)
+
+/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
+
+/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
+#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD  (0x00000001)
+
+/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
+typedef struct _MPI2_RAID_ACTION_RATE_DATA
+{
+    U8              RateToChange;               /* 0x00 */
+    U8              RateOrMode;                 /* 0x01 */
+    U16             DataScrubDuration;          /* 0x02 */
+} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
+  Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
+
+#define MPI2_RAID_ACTION_SET_RATE_RESYNC            (0x00)
+#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB        (0x01)
+#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE    (0x02)
+
+/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
+typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
+{
+    U8              RAIDFunction;                       /* 0x00 */
+    U8              Flags;                              /* 0x01 */
+    U16             Reserved1;                          /* 0x02 */
+} MPI2_RAID_ACTION_START_RAID_FUNCTION,
+  MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
+  Mpi2RaidActionStartRaidFunction_t,
+  MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
+
+/* defines for the RAIDFunction field */
+#define MPI2_RAID_ACTION_START_BACKGROUND_INIT      (0x00)
+#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
+#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK    (0x02)
+
+/* defines for the Flags field */
+#define MPI2_RAID_ACTION_START_NEW                  (0x00)
+#define MPI2_RAID_ACTION_START_RESUME               (0x01)
+
+/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
+typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
+{
+    U8              RAIDFunction;                       /* 0x00 */
+    U8              Flags;                              /* 0x01 */
+    U16             Reserved1;                          /* 0x02 */
+} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
+  MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
+  Mpi2RaidActionStopRaidFunction_t,
+  MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
+
+/* defines for the RAIDFunction field */
+#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT       (0x00)
+#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION  (0x01)
+#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK     (0x02)
+
+/* defines for the Flags field */
+#define MPI2_RAID_ACTION_STOP_ABORT                 (0x00)
+#define MPI2_RAID_ACTION_STOP_PAUSE                 (0x01)
+
+/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
+typedef struct _MPI2_RAID_ACTION_HOT_SPARE
+{
+    U8              HotSparePool;               /* 0x00 */
+    U8              Reserved1;                  /* 0x01 */
+    U16             DevHandle;                  /* 0x02 */
+} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
+  Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
+
+/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
+typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
+{
+    U8              Flags;                              /* 0x00 */
+    U8              DeviceFirmwareUpdateModeTimeout;    /* 0x01 */
+    U16             Reserved1;                          /* 0x02 */
+} MPI2_RAID_ACTION_FW_UPDATE_MODE,
+  MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
+  Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
+
+/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
+#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE        (0x00)
+#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE         (0x01)
+
+typedef union _MPI2_RAID_ACTION_DATA
+{
+    U32                                     Word;
+    MPI2_RAID_ACTION_RATE_DATA              Rates;
+    MPI2_RAID_ACTION_START_RAID_FUNCTION    StartRaidFunction;
+    MPI2_RAID_ACTION_STOP_RAID_FUNCTION     StopRaidFunction;
+    MPI2_RAID_ACTION_HOT_SPARE              HotSpare;
+    MPI2_RAID_ACTION_FW_UPDATE_MODE         FwUpdateMode;
+} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
+  Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
+
+
+/* RAID Action Request Message */
+typedef struct _MPI2_RAID_ACTION_REQUEST
+{
+    U8                      Action;                         /* 0x00 */
+    U8                      Reserved1;                      /* 0x01 */
+    U8                      ChainOffset;                    /* 0x02 */
+    U8                      Function;                       /* 0x03 */
+    U16                     VolDevHandle;                   /* 0x04 */
+    U8                      PhysDiskNum;                    /* 0x06 */
+    U8                      MsgFlags;                       /* 0x07 */
+    U8                      VP_ID;                          /* 0x08 */
+    U8                      VF_ID;                          /* 0x09 */
+    U16                     Reserved2;                      /* 0x0A */
+    U32                     Reserved3;                      /* 0x0C */
+    MPI2_RAID_ACTION_DATA   ActionDataWord;                 /* 0x10 */
+    MPI2_SGE_SIMPLE_UNION   ActionDataSGE;                  /* 0x14 */
+} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
+  Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
+
+/* RAID Action request Action values */
+
+#define MPI2_RAID_ACTION_INDICATOR_STRUCT           (0x01)
+#define MPI2_RAID_ACTION_CREATE_VOLUME              (0x02)
+#define MPI2_RAID_ACTION_DELETE_VOLUME              (0x03)
+#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES        (0x04)
+#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES         (0x05)
+#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE           (0x0A)
+#define MPI2_RAID_ACTION_PHYSDISK_ONLINE            (0x0B)
+#define MPI2_RAID_ACTION_FAIL_PHYSDISK              (0x0F)
+#define MPI2_RAID_ACTION_ACTIVATE_VOLUME            (0x11)
+#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE      (0x15)
+#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE     (0x17)
+#define MPI2_RAID_ACTION_SET_VOLUME_NAME            (0x18)
+#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE     (0x19)
+#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME       (0x1C)
+#define MPI2_RAID_ACTION_CREATE_HOT_SPARE           (0x1D)
+#define MPI2_RAID_ACTION_DELETE_HOT_SPARE           (0x1E)
+#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED  (0x20)
+#define MPI2_RAID_ACTION_START_RAID_FUNCTION        (0x21)
+#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION         (0x22)
+
+
+/* RAID Volume Creation Structure */
+
+/*
+ * The following define can be customized for the targeted product.
+ */
+#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
+#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS        (1)
+#endif
+
+typedef struct _MPI2_RAID_VOLUME_PHYSDISK
+{
+    U8                      RAIDSetNum;                     /* 0x00 */
+    U8                      PhysDiskMap;                    /* 0x01 */
+    U16                     PhysDiskDevHandle;              /* 0x02 */
+} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
+  Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
+
+/* defines for the PhysDiskMap field */
+#define MPI2_RAIDACTION_PHYSDISK_PRIMARY            (0x01)
+#define MPI2_RAIDACTION_PHYSDISK_SECONDARY          (0x02)
+
+typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
+{
+    U8                          NumPhysDisks;               /* 0x00 */
+    U8                          VolumeType;                 /* 0x01 */
+    U16                         Reserved1;                  /* 0x02 */
+    U32                         VolumeCreationFlags;        /* 0x04 */
+    U32                         VolumeSettings;             /* 0x08 */
+    U8                          Reserved2;                  /* 0x0C */
+    U8                          ResyncRate;                 /* 0x0D */
+    U16                         DataScrubDuration;          /* 0x0E */
+    U64                         VolumeMaxLBA;               /* 0x10 */
+    U32                         StripeSize;                 /* 0x18 */
+    U8                          Name[16];                   /* 0x1C */
+    MPI2_RAID_VOLUME_PHYSDISK   PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
+} MPI2_RAID_VOLUME_CREATION_STRUCT,
+  MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
+  Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
+
+/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
+
+/* defines for the VolumeCreationFlags field */
+#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS     (0x80000000)
+#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT      (0x00000004)
+#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT       (0x00000002)
+#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA         (0x00000001)
+/* The following is an obsolete define.
+ * It must be shifted left 24 bits in order to set the proper bit.
+ */
+#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
+
+
+/* RAID Online Capacity Expansion Structure */
+
+typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
+{
+    U32                     Flags;                          /* 0x00 */
+    U16                     DevHandle0;                     /* 0x04 */
+    U16                     Reserved1;                      /* 0x06 */
+    U16                     DevHandle1;                     /* 0x08 */
+    U16                     Reserved2;                      /* 0x0A */
+} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
+  MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
+  Mpi2RaidOnlineCapacityExpansion_t,
+  MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
+
+
+/* RAID Volume Indicator Structure */
+
+typedef struct _MPI2_RAID_VOL_INDICATOR
+{
+    U64                     TotalBlocks;                    /* 0x00 */
+    U64                     BlocksRemaining;                /* 0x08 */
+    U32                     Flags;                          /* 0x10 */
+} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
+  Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
+
+/* defines for RAID Volume Indicator Flags field */
+#define MPI2_RAID_VOL_FLAGS_OP_MASK                 (0x0000000F)
+#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT      (0x00000000)
+#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
+#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK    (0x00000002)
+#define MPI2_RAID_VOL_FLAGS_OP_RESYNC               (0x00000003)
+
+
+/* RAID Action Reply ActionData union */
+typedef union _MPI2_RAID_ACTION_REPLY_DATA
+{
+    U32                     Word[5];
+    MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
+    U16                     VolDevHandle;
+    U8                      VolumeState;
+    U8                      PhysDiskNum;
+} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
+  Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
+
+/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
+
+
+/* RAID Action Reply Message */
+typedef struct _MPI2_RAID_ACTION_REPLY
+{
+    U8                          Action;                     /* 0x00 */
+    U8                          Reserved1;                  /* 0x01 */
+    U8                          MsgLength;                  /* 0x02 */
+    U8                          Function;                   /* 0x03 */
+    U16                         VolDevHandle;               /* 0x04 */
+    U8                          PhysDiskNum;                /* 0x06 */
+    U8                          MsgFlags;                   /* 0x07 */
+    U8                          VP_ID;                      /* 0x08 */
+    U8                          VF_ID;                      /* 0x09 */
+    U16                         Reserved2;                  /* 0x0A */
+    U16                         Reserved3;                  /* 0x0C */
+    U16                         IOCStatus;                  /* 0x0E */
+    U32                         IOCLogInfo;                 /* 0x10 */
+    MPI2_RAID_ACTION_REPLY_DATA ActionData;                 /* 0x14 */
+} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
+  Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
+
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_sas.h ../../stable/8/sys/dev/mps/mpi/mpi2_sas.h
--- sys/dev/mps/mpi/mpi2_sas.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_sas.h	2011-01-07 14:33:12.647495427 -0700
@@ -0,0 +1,285 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_sas.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2007 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_sas.h
+ *          Title:  MPI Serial Attached SCSI structures and definitions
+ *  Creation Date:  February 9, 2007
+ *
+ *  mpi2.h Version:  02.00.03
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-26-07  02.00.01  Added Clear All Persistent Operation to SAS IO Unit
+ *                      Control Request.
+ *  10-02-08  02.00.02  Added Set IOC Parameter Operation to SAS IO Unit Control
+ *                      Request.
+ *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
+ *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_SAS_H
+#define MPI2_SAS_H
+
+/*
+ * Values for SASStatus.
+ */
+#define MPI2_SASSTATUS_SUCCESS                          (0x00)
+#define MPI2_SASSTATUS_UNKNOWN_ERROR                    (0x01)
+#define MPI2_SASSTATUS_INVALID_FRAME                    (0x02)
+#define MPI2_SASSTATUS_UTC_BAD_DEST                     (0x03)
+#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED               (0x04)
+#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED   (0x05)
+#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST           (0x06)
+#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED       (0x07)
+#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY           (0x08)
+#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION            (0x09)
+#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT           (0x0A)
+#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT            (0x0B)
+#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA    (0x0C)
+#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR    (0x0D)
+#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED            (0x0E)
+#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH       (0x0F)
+#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA          (0x10)
+#define MPI2_SASSTATUS_DATA_OFFSET_ERROR                (0x11)
+#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED                (0x12)
+#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED           (0x13)
+#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT       (0x14)
+
+
+/*
+ * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
+ * data and SAS Configuration pages.
+ */
+#define MPI2_SAS_DEVICE_INFO_SEP                (0x00004000)
+#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE       (0x00002000)
+#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE         (0x00001000)
+#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH      (0x00000800)
+#define MPI2_SAS_DEVICE_INFO_SSP_TARGET         (0x00000400)
+#define MPI2_SAS_DEVICE_INFO_STP_TARGET         (0x00000200)
+#define MPI2_SAS_DEVICE_INFO_SMP_TARGET         (0x00000100)
+#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE        (0x00000080)
+#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR      (0x00000040)
+#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR      (0x00000020)
+#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR      (0x00000010)
+#define MPI2_SAS_DEVICE_INFO_SATA_HOST          (0x00000008)
+
+#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE   (0x00000007)
+#define MPI2_SAS_DEVICE_INFO_NO_DEVICE          (0x00000000)
+#define MPI2_SAS_DEVICE_INFO_END_DEVICE         (0x00000001)
+#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER      (0x00000002)
+#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER    (0x00000003)
+
+
+/*****************************************************************************
+*
+*        SAS Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  SMP Passthrough messages
+****************************************************************************/
+
+/* SMP Passthrough Request Message */
+typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
+{
+    U8                      PassthroughFlags;   /* 0x00 */
+    U8                      PhysicalPort;       /* 0x01 */
+    U8                      ChainOffset;        /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     RequestDataLength;  /* 0x04 */
+    U8                      SGLFlags;           /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved1;          /* 0x0A */
+    U32                     Reserved2;          /* 0x0C */
+    U64                     SASAddress;         /* 0x10 */
+    U32                     Reserved3;          /* 0x18 */
+    U32                     Reserved4;          /* 0x1C */
+    MPI2_SIMPLE_SGE_UNION   SGL;                /* 0x20 */
+} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
+  Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE      (0x80)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* SMP Passthrough Reply Message */
+typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
+{
+    U8                      PassthroughFlags;   /* 0x00 */
+    U8                      PhysicalPort;       /* 0x01 */
+    U8                      MsgLength;          /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     ResponseDataLength; /* 0x04 */
+    U8                      SGLFlags;           /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved1;          /* 0x0A */
+    U8                      Reserved2;          /* 0x0C */
+    U8                      SASStatus;          /* 0x0D */
+    U16                     IOCStatus;          /* 0x0E */
+    U32                     IOCLogInfo;         /* 0x10 */
+    U32                     Reserved3;          /* 0x14 */
+    U8                      ResponseData[4];    /* 0x18 */
+} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
+  Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
+
+/* values for PassthroughFlags field */
+#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE    (0x80)
+
+/* values for SASStatus field are at the top of this file */
+
+
+/****************************************************************************
+*  SATA Passthrough messages
+****************************************************************************/
+
+/* SATA Passthrough Request Message */
+typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
+{
+    U16                     DevHandle;          /* 0x00 */
+    U8                      ChainOffset;        /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     PassthroughFlags;   /* 0x04 */
+    U8                      SGLFlags;           /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved1;          /* 0x0A */
+    U32                     Reserved2;          /* 0x0C */
+    U32                     Reserved3;          /* 0x10 */
+    U32                     Reserved4;          /* 0x14 */
+    U32                     DataLength;         /* 0x18 */
+    U8                      CommandFIS[20];     /* 0x1C */
+    MPI2_SGE_IO_UNION       SGL;                /* 0x20 */
+} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
+  Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG      (0x0100)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA               (0x0020)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO               (0x0010)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU    (0x0004)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE             (0x0002)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_READ              (0x0001)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* SATA Passthrough Reply Message */
+typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
+{
+    U16                     DevHandle;          /* 0x00 */
+    U8                      MsgLength;          /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     PassthroughFlags;   /* 0x04 */
+    U8                      SGLFlags;           /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved1;          /* 0x0A */
+    U8                      Reserved2;          /* 0x0C */
+    U8                      SASStatus;          /* 0x0D */
+    U16                     IOCStatus;          /* 0x0E */
+    U32                     IOCLogInfo;         /* 0x10 */
+    U8                      StatusFIS[20];      /* 0x14 */
+    U32                     StatusControlRegisters; /* 0x28 */
+    U32                     TransferCount;      /* 0x2C */
+} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
+  Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
+
+/* values for SASStatus field are at the top of this file */
+
+
+/****************************************************************************
+*  SAS IO Unit Control messages
+****************************************************************************/
+
+/* SAS IO Unit Control Request Message */
+typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
+{
+    U8                      Operation;          /* 0x00 */
+    U8                      Reserved1;          /* 0x01 */
+    U8                      ChainOffset;        /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     DevHandle;          /* 0x04 */
+    U8                      IOCParameter;       /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved3;          /* 0x0A */
+    U16                     Reserved4;          /* 0x0C */
+    U8                      PhyNum;             /* 0x0E */
+    U8                      PrimFlags;          /* 0x0F */
+    U32                     Primitive;          /* 0x10 */
+    U8                      LookupMethod;       /* 0x14 */
+    U8                      Reserved5;          /* 0x15 */
+    U16                     SlotNumber;         /* 0x16 */
+    U64                     LookupAddress;      /* 0x18 */
+    U32                     IOCParameterValue;  /* 0x20 */
+    U32                     Reserved7;          /* 0x24 */
+    U32                     Reserved8;          /* 0x28 */
+} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
+  MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
+  Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
+
+/* values for the Operation field */
+#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT        (0x02)
+#define MPI2_SAS_OP_PHY_LINK_RESET              (0x06)
+#define MPI2_SAS_OP_PHY_HARD_RESET              (0x07)
+#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG         (0x08)
+#define MPI2_SAS_OP_SEND_PRIMITIVE              (0x0A)
+#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY        (0x0B)
+#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
+#define MPI2_SAS_OP_REMOVE_DEVICE               (0x0D)
+#define MPI2_SAS_OP_LOOKUP_MAPPING              (0x0E)
+#define MPI2_SAS_OP_SET_IOC_PARAMETER           (0x0F)
+#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN        (0x80)
+
+/* values for the PrimFlags field */
+#define MPI2_SAS_PRIMFLAGS_SINGLE               (0x08)
+#define MPI2_SAS_PRIMFLAGS_TRIPLE               (0x02)
+#define MPI2_SAS_PRIMFLAGS_REDUNDANT            (0x01)
+
+/* values for the LookupMethod field */
+#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS          (0x01)
+#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT   (0x02)
+#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME      (0x03)
+
+
+/* SAS IO Unit Control Reply Message */
+typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
+{
+    U8                      Operation;          /* 0x00 */
+    U8                      Reserved1;          /* 0x01 */
+    U8                      MsgLength;          /* 0x02 */
+    U8                      Function;           /* 0x03 */
+    U16                     DevHandle;          /* 0x04 */
+    U8                      IOCParameter;       /* 0x06 */
+    U8                      MsgFlags;           /* 0x07 */
+    U8                      VP_ID;              /* 0x08 */
+    U8                      VF_ID;              /* 0x09 */
+    U16                     Reserved3;          /* 0x0A */
+    U16                     Reserved4;          /* 0x0C */
+    U16                     IOCStatus;          /* 0x0E */
+    U32                     IOCLogInfo;         /* 0x10 */
+} MPI2_SAS_IOUNIT_CONTROL_REPLY,
+  MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
+  Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
+
+
+#endif
+
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_targ.h ../../stable/8/sys/dev/mps/mpi/mpi2_targ.h
--- sys/dev/mps/mpi/mpi2_targ.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_targ.h	2011-01-07 14:33:12.686655630 -0700
@@ -0,0 +1,441 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_targ.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2008 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_targ.h
+ *          Title:  MPI Target mode messages and structures
+ *  Creation Date:  September 8, 2006
+ *
+ *    mpi2_targ.h Version: 02.00.03
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  08-31-07  02.00.01  Added Command Buffer Data Location Address Space bits to
+ *                      BufferPostFlags field of CommandBufferPostBase Request.
+ *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  10-02-08  02.00.03  Removed NextCmdBufferOffset from
+ *                      MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST.
+ *                      Target Status Send Request only takes a single SGE for
+ *                      response data.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TARG_H
+#define MPI2_TARG_H
+
+
+/******************************************************************************
+*
+*        SCSI Target Messages
+*
+*******************************************************************************/
+
+/****************************************************************************
+*  Target Command Buffer Post Base Request
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST
+{
+    U8                      BufferPostFlags;        /* 0x00 */
+    U8                      Reserved1;              /* 0x01 */
+    U8                      ChainOffset;            /* 0x02 */
+    U8                      Function;               /* 0x03 */
+    U16                     TotalCmdBuffers;        /* 0x04 */
+    U8                      Reserved;               /* 0x06 */
+    U8                      MsgFlags;               /* 0x07 */
+    U8                      VP_ID;                  /* 0x08 */
+    U8                      VF_ID;                  /* 0x09 */
+    U16                     Reserved2;              /* 0x0A */
+    U32                     Reserved3;              /* 0x0C */
+    U16                     CmdBufferLength;        /* 0x10 */
+    U16                     Reserved4;              /* 0x12 */
+    U32                     BaseAddressLow;         /* 0x14 */
+    U32                     BaseAddressHigh;        /* 0x18 */
+} MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST,
+  MPI2_POINTER PTR_MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST,
+  Mpi2TargetCmdBufferPostBaseRequest_t,
+  MPI2_POINTER pMpi2TargetCmdBufferPostBaseRequest_t;
+
+/* values for the BufferPostflags field */
+#define MPI2_CMD_BUF_POST_BASE_ADDRESS_SPACE_MASK            (0x0C)
+#define MPI2_CMD_BUF_POST_BASE_SYSTEM_ADDRESS_SPACE          (0x00)
+#define MPI2_CMD_BUF_POST_BASE_IOCDDR_ADDRESS_SPACE          (0x04)
+#define MPI2_CMD_BUF_POST_BASE_IOCPLB_ADDRESS_SPACE          (0x08)
+#define MPI2_CMD_BUF_POST_BASE_IOCPLBNTA_ADDRESS_SPACE       (0x0C)
+
+#define MPI2_CMD_BUF_POST_BASE_FLAGS_AUTO_POST_ALL           (0x01)
+
+
+/****************************************************************************
+*  Target Command Buffer Post List Request
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_CMD_BUF_POST_LIST_REQUEST
+{
+    U16                     Reserved;               /* 0x00 */
+    U8                      ChainOffset;            /* 0x02 */
+    U8                      Function;               /* 0x03 */
+    U16                     CmdBufferCount;         /* 0x04 */
+    U8                      Reserved1;              /* 0x06 */
+    U8                      MsgFlags;               /* 0x07 */
+    U8                      VP_ID;                  /* 0x08 */
+    U8                      VF_ID;                  /* 0x09 */
+    U16                     Reserved2;              /* 0x0A */
+    U32                     Reserved3;              /* 0x0C */
+    U16                     IoIndex[2];             /* 0x10 */
+} MPI2_TARGET_CMD_BUF_POST_LIST_REQUEST,
+  MPI2_POINTER PTR_MPI2_TARGET_CMD_BUF_POST_LIST_REQUEST,
+  Mpi2TargetCmdBufferPostListRequest_t,
+  MPI2_POINTER pMpi2TargetCmdBufferPostListRequest_t;
+
+/****************************************************************************
+*  Target Command Buffer Post Base List Reply
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_BUF_POST_BASE_LIST_REPLY
+{
+    U8                      Flags;                  /* 0x00 */
+    U8                      Reserved;               /* 0x01 */
+    U8                      MsgLength;              /* 0x02 */
+    U8                      Function;               /* 0x03 */
+    U16                     Reserved1;              /* 0x04 */
+    U8                      Reserved2;              /* 0x06 */
+    U8                      MsgFlags;               /* 0x07 */
+    U8                      VP_ID;                  /* 0x08 */
+    U8                      VF_ID;                  /* 0x09 */
+    U16                     Reserved3;              /* 0x0A */
+    U16                     Reserved4;              /* 0x0C */
+    U16                     IOCStatus;              /* 0x0E */
+    U32                     IOCLogInfo;             /* 0x10 */
+    U16                     IoIndex;                /* 0x14 */
+    U16                     Reserved5;              /* 0x16 */
+    U32                     Reserved6;              /* 0x18 */
+} MPI2_TARGET_BUF_POST_BASE_LIST_REPLY,
+  MPI2_POINTER PTR_MPI2_TARGET_BUF_POST_BASE_LIST_REPLY,
+  Mpi2TargetCmdBufferPostBaseListReply_t,
+  MPI2_POINTER pMpi2TargetCmdBufferPostBaseListReply_t;
+
+/* Flags defines */
+#define MPI2_CMD_BUF_POST_REPLY_IOINDEX_VALID       (0x01)
+
+
+/****************************************************************************
+*  Command Buffer Formats (with 16 byte CDB)
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_SSP_CMD_BUFFER
+{
+    U8      FrameType;                                  /* 0x00 */
+    U8      Reserved1;                                  /* 0x01 */
+    U16     InitiatorConnectionTag;                     /* 0x02 */
+    U32     HashedSourceSASAddress;                     /* 0x04 */
+    U16     Reserved2;                                  /* 0x08 */
+    U16     Flags;                                      /* 0x0A */
+    U32     Reserved3;                                  /* 0x0C */
+    U16     Tag;                                        /* 0x10 */
+    U16     TargetPortTransferTag;                      /* 0x12 */
+    U32     DataOffset;                                 /* 0x14 */
+    /* COMMAND information unit starts here */
+    U8      LogicalUnitNumber[8];                       /* 0x18 */
+    U8      Reserved4;                                  /* 0x20 */
+    U8      TaskAttribute; /* lower 3 bits */           /* 0x21 */
+    U8      Reserved5;                                  /* 0x22 */
+    U8      AdditionalCDBLength; /* upper 5 bits */     /* 0x23 */
+    U8      CDB[16];                                    /* 0x24 */
+    /* Additional CDB bytes extend past the CDB field */
+} MPI2_TARGET_SSP_CMD_BUFFER, MPI2_POINTER PTR_MPI2_TARGET_SSP_CMD_BUFFER,
+  Mpi2TargetSspCmdBuffer, MPI2_POINTER pMp2iTargetSspCmdBuffer;
+
+typedef struct _MPI2_TARGET_SSP_TASK_BUFFER
+{
+    U8      FrameType;                                  /* 0x00 */
+    U8      Reserved1;                                  /* 0x01 */
+    U16     InitiatorConnectionTag;                     /* 0x02 */
+    U32     HashedSourceSASAddress;                     /* 0x04 */
+    U16     Reserved2;                                  /* 0x08 */
+    U16     Flags;                                      /* 0x0A */
+    U32     Reserved3;                                  /* 0x0C */
+    U16     Tag;                                        /* 0x10 */
+    U16     TargetPortTransferTag;                      /* 0x12 */
+    U32     DataOffset;                                 /* 0x14 */
+    /* TASK information unit starts here */
+    U8      LogicalUnitNumber[8];                       /* 0x18 */
+    U16     Reserved4;                                  /* 0x20 */
+    U8      TaskManagementFunction;                     /* 0x22 */
+    U8      Reserved5;                                  /* 0x23 */
+    U16     ManagedTaskTag;                             /* 0x24 */
+    U16     Reserved6;                                  /* 0x26 */
+    U32     Reserved7;                                  /* 0x28 */
+    U32     Reserved8;                                  /* 0x2C */
+    U32     Reserved9;                                  /* 0x30 */
+} MPI2_TARGET_SSP_TASK_BUFFER, MPI2_POINTER PTR_MPI2_TARGET_SSP_TASK_BUFFER,
+  Mpi2TargetSspTaskBuffer, MPI2_POINTER pMpi2TargetSspTaskBuffer;
+
+/* mask and shift for HashedSourceSASAddress field */
+#define MPI2_TARGET_HASHED_SAS_ADDRESS_MASK     (0xFFFFFF00)
+#define MPI2_TARGET_HASHED_SAS_ADDRESS_SHIFT    (8)
+
+
+/****************************************************************************
+*   Target Assist Request
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_ASSIST_REQUEST
+{
+    U8                  Reserved1;                          /* 0x00 */
+    U8                  TargetAssistFlags;                  /* 0x01 */
+    U8                  ChainOffset;                        /* 0x02 */
+    U8                  Function;                           /* 0x03 */
+    U16                 QueueTag;                           /* 0x04 */
+    U8                  Reserved2;                          /* 0x06 */
+    U8                  MsgFlags;                           /* 0x07 */
+    U8                  VP_ID;                              /* 0x08 */
+    U8                  VF_ID;                              /* 0x09 */
+    U16                 Reserved3;                          /* 0x0A */
+    U16                 IoIndex;                            /* 0x0C */
+    U16                 InitiatorConnectionTag;             /* 0x0E */
+    U16                 SGLFlags;                           /* 0x10 */
+    U8                  SequenceNumber;                     /* 0x12 */
+    U8                  Reserved4;                          /* 0x13 */
+    U8                  SGLOffset0;                         /* 0x14 */
+    U8                  SGLOffset1;                         /* 0x15 */
+    U8                  SGLOffset2;                         /* 0x16 */
+    U8                  SGLOffset3;                         /* 0x17 */
+    U32                 SkipCount;                          /* 0x18 */
+    U32                 DataLength;                         /* 0x1C */
+    U32                 BidirectionalDataLength;            /* 0x20 */
+    U16                 IoFlags;                            /* 0x24 */
+    U16                 EEDPFlags;                          /* 0x26 */
+    U32                 EEDPBlockSize;                      /* 0x28 */
+    U32                 SecondaryReferenceTag;              /* 0x2C */
+    U16                 SecondaryApplicationTag;            /* 0x30 */
+    U16                 ApplicationTagTranslationMask;      /* 0x32 */
+    U32                 PrimaryReferenceTag;                /* 0x34 */
+    U16                 PrimaryApplicationTag;              /* 0x38 */
+    U16                 PrimaryApplicationTagMask;          /* 0x3A */
+    U32                 RelativeOffset;                     /* 0x3C */
+    U32                 Reserved5;                          /* 0x40 */
+    U32                 Reserved6;                          /* 0x44 */
+    U32                 Reserved7;                          /* 0x48 */
+    U32                 Reserved8;                          /* 0x4C */
+    MPI2_SGE_IO_UNION   SGL[1];                             /* 0x50 */
+} MPI2_TARGET_ASSIST_REQUEST, MPI2_POINTER PTR_MPI2_TARGET_ASSIST_REQUEST,
+  Mpi2TargetAssistRequest_t, MPI2_POINTER pMpi2TargetAssistRequest_t;
+
+/* Target Assist TargetAssistFlags bits */
+
+#define MPI2_TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER      (0x80)
+#define MPI2_TARGET_ASSIST_FLAGS_TLR                    (0x10)
+#define MPI2_TARGET_ASSIST_FLAGS_RETRANSMIT             (0x04)
+#define MPI2_TARGET_ASSIST_FLAGS_AUTO_STATUS            (0x02)
+#define MPI2_TARGET_ASSIST_FLAGS_DATA_DIRECTION         (0x01)
+
+/* Target Assist SGLFlags bits */
+
+/* base values for Data Location Address Space */
+#define MPI2_TARGET_ASSIST_SGLFLAGS_ADDR_MASK           (0x0C)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_SYSTEM_ADDR         (0x00)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_IOCDDR_ADDR         (0x04)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_IOCPLB_ADDR         (0x08)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_PLBNTA_ADDR         (0x0C)
+
+/* base values for Type */
+#define MPI2_TARGET_ASSIST_SGLFLAGS_TYPE_MASK           (0x03)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_MPI_TYPE            (0x00)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_32IEEE_TYPE         (0x01)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_64IEEE_TYPE         (0x02)
+
+/* shift values for each sub-field */
+#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL3_SHIFT          (12)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL2_SHIFT          (8)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL1_SHIFT          (4)
+#define MPI2_TARGET_ASSIST_SGLFLAGS_SGL0_SHIFT          (0)
+
+/* Target Assist IoFlags bits */
+
+#define MPI2_TARGET_ASSIST_IOFLAGS_BIDIRECTIONAL        (0x0800)
+#define MPI2_TARGET_ASSIST_IOFLAGS_MULTICAST            (0x0400)
+#define MPI2_TARGET_ASSIST_IOFLAGS_RECEIVE_FIRST        (0x0200)
+
+/* Target Assist EEDPFlags bits */
+
+#define MPI2_TA_EEDPFLAGS_INC_PRI_REFTAG            (0x8000)
+#define MPI2_TA_EEDPFLAGS_INC_SEC_REFTAG            (0x4000)
+#define MPI2_TA_EEDPFLAGS_INC_PRI_APPTAG            (0x2000)
+#define MPI2_TA_EEDPFLAGS_INC_SEC_APPTAG            (0x1000)
+
+#define MPI2_TA_EEDPFLAGS_CHECK_REFTAG              (0x0400)
+#define MPI2_TA_EEDPFLAGS_CHECK_APPTAG              (0x0200)
+#define MPI2_TA_EEDPFLAGS_CHECK_GUARD               (0x0100)
+
+#define MPI2_TA_EEDPFLAGS_PASSTHRU_REFTAG           (0x0008)
+
+#define MPI2_TA_EEDPFLAGS_MASK_OP                   (0x0007)
+#define MPI2_TA_EEDPFLAGS_NOOP_OP                   (0x0000)
+#define MPI2_TA_EEDPFLAGS_CHECK_OP                  (0x0001)
+#define MPI2_TA_EEDPFLAGS_STRIP_OP                  (0x0002)
+#define MPI2_TA_EEDPFLAGS_CHECK_REMOVE_OP           (0x0003)
+#define MPI2_TA_EEDPFLAGS_INSERT_OP                 (0x0004)
+#define MPI2_TA_EEDPFLAGS_REPLACE_OP                (0x0006)
+#define MPI2_TA_EEDPFLAGS_CHECK_REGEN_OP            (0x0007)
+
+
+/****************************************************************************
+*  Target Status Send Request
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_STATUS_SEND_REQUEST
+{
+    U8                      Reserved1;                  /* 0x00 */
+    U8                      StatusFlags;                /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     QueueTag;                   /* 0x04 */
+    U8                      Reserved2;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved3;                  /* 0x0A */
+    U16                     IoIndex;                    /* 0x0C */
+    U16                     InitiatorConnectionTag;     /* 0x0E */
+    U16                     SGLFlags;                   /* 0x10 */
+    U16                     Reserved4;                  /* 0x12 */
+    U8                      SGLOffset0;                 /* 0x14 */
+    U8                      Reserved5;                  /* 0x15 */
+    U16                     Reserved6;                  /* 0x16 */
+    U32                     Reserved7;                  /* 0x18 */
+    U32                     Reserved8;                  /* 0x1C */
+    MPI2_SIMPLE_SGE_UNION   StatusDataSGE;              /* 0x20 */
+} MPI2_TARGET_STATUS_SEND_REQUEST,
+  MPI2_POINTER PTR_MPI2_TARGET_STATUS_SEND_REQUEST,
+  Mpi2TargetStatusSendRequest_t, MPI2_POINTER pMpi2TargetStatusSendRequest_t;
+
+/* Target Status Send StatusFlags bits */
+
+#define MPI2_TSS_FLAGS_REPOST_CMD_BUFFER            (0x80)
+#define MPI2_TSS_FLAGS_RETRANSMIT                   (0x04)
+#define MPI2_TSS_FLAGS_AUTO_GOOD_STATUS             (0x01)
+
+/* Target Status Send SGLFlags bits */
+/* Data Location Address Space */
+#define MPI2_TSS_SGLFLAGS_ADDR_MASK                 (0x0C)
+#define MPI2_TSS_SGLFLAGS_SYSTEM_ADDR               (0x00)
+#define MPI2_TSS_SGLFLAGS_IOCDDR_ADDR               (0x04)
+#define MPI2_TSS_SGLFLAGS_IOCPLB_ADDR               (0x08)
+#define MPI2_TSS_SGLFLAGS_IOCPLBNTA_ADDR            (0x0C)
+/* Type */
+#define MPI2_TSS_SGLFLAGS_TYPE_MASK                 (0x03)
+#define MPI2_TSS_SGLFLAGS_MPI_TYPE                  (0x00)
+#define MPI2_TSS_SGLFLAGS_IEEE32_TYPE               (0x01)
+#define MPI2_TSS_SGLFLAGS_IEEE64_TYPE               (0x02)
+
+
+
+/*
+ * NOTE: The SSP status IU is big-endian. When used on a little-endian system,
+ * this structure properly orders the bytes.
+ */
+typedef struct _MPI2_TARGET_SSP_RSP_IU
+{
+    U32     Reserved0[6]; /* reserved for SSP header */ /* 0x00 */
+    /* start of RESPONSE information unit */
+    U32     Reserved1;                                  /* 0x18 */
+    U32     Reserved2;                                  /* 0x1C */
+    U16     Reserved3;                                  /* 0x20 */
+    U8      DataPres; /* lower 2 bits */                /* 0x22 */
+    U8      Status;                                     /* 0x23 */
+    U32     Reserved4;                                  /* 0x24 */
+    U32     SenseDataLength;                            /* 0x28 */
+    U32     ResponseDataLength;                         /* 0x2C */
+    U8      ResponseSenseData[4];                       /* 0x30 */
+} MPI2_TARGET_SSP_RSP_IU, MPI2_POINTER PTR_MPI2_TARGET_SSP_RSP_IU,
+  Mpi2TargetSspRspIu_t, MPI2_POINTER pMpi2TargetSspRspIu_t;
+
+
+/****************************************************************************
+*  Target Standard Reply - used with Target Assist or Target Status Send
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_STANDARD_REPLY
+{
+    U16                     Reserved;                   /* 0x00 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved1;                  /* 0x04 */
+    U8                      Reserved2;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved3;                  /* 0x0A */
+    U16                     Reserved4;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U16                     IoIndex;                    /* 0x14 */
+    U16                     Reserved5;                  /* 0x16 */
+    U32                     TransferCount;              /* 0x18 */
+    U32                     BidirectionalTransferCount; /* 0x1C */
+} MPI2_TARGET_STANDARD_REPLY, MPI2_POINTER PTR_MPI2_TARGET_STANDARD_REPLY,
+  Mpi2TargetErrorReply_t, MPI2_POINTER pMpi2TargetErrorReply_t;
+
+
+/****************************************************************************
+*  Target Mode Abort Request
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_MODE_ABORT_REQUEST
+{
+    U8                      AbortType;                  /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     IoIndexToAbort;             /* 0x0C */
+    U16                     Reserved6;                  /* 0x0E */
+    U32                     MidToAbort;                 /* 0x10 */
+} MPI2_TARGET_MODE_ABORT, MPI2_POINTER PTR_MPI2_TARGET_MODE_ABORT,
+  Mpi2TargetModeAbort_t, MPI2_POINTER pMpi2TargetModeAbort_t;
+
+/* Target Mode Abort AbortType values */
+
+#define MPI2_TARGET_MODE_ABORT_ALL_CMD_BUFFERS      (0x00)
+#define MPI2_TARGET_MODE_ABORT_ALL_IO               (0x01)
+#define MPI2_TARGET_MODE_ABORT_EXACT_IO             (0x02)
+#define MPI2_TARGET_MODE_ABORT_EXACT_IO_REQUEST     (0x03)
+#define MPI2_TARGET_MODE_ABORT_IO_REQUEST_AND_IO    (0x04)
+
+
+/****************************************************************************
+*  Target Mode Abort Reply
+****************************************************************************/
+
+typedef struct _MPI2_TARGET_MODE_ABORT_REPLY
+{
+    U16                     Reserved;                   /* 0x00 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved1;                  /* 0x04 */
+    U8                      Reserved2;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved3;                  /* 0x0A */
+    U16                     Reserved4;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U32                     AbortCount;                 /* 0x14 */
+} MPI2_TARGET_MODE_ABORT_REPLY, MPI2_POINTER PTR_MPI2_TARGET_MODE_ABORT_REPLY,
+  Mpi2TargetModeAbortReply_t, MPI2_POINTER pMpi2TargetModeAbortReply_t;
+
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_tool.h ../../stable/8/sys/dev/mps/mpi/mpi2_tool.h
--- sys/dev/mps/mpi/mpi2_tool.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_tool.h	2011-01-07 14:33:12.691672709 -0700
@@ -0,0 +1,391 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_tool.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_tool.h
+ *          Title:  MPI diagnostic tool structures and definitions
+ *  Creation Date:  March 26, 2007
+ *
+ *    mpi2_tool.h Version:  02.00.04
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
+ *                      structures and defines.
+ *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
+ *  07-30-09  02.00.04  Added ExtendedType field to DiagnosticBufferPost request
+ *                      and reply messages.
+ *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
+ *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TOOL_H
+#define MPI2_TOOL_H
+
+/*****************************************************************************
+*
+*               Toolbox Messages
+*
+*****************************************************************************/
+
+/* defines for the Tools */
+#define MPI2_TOOLBOX_CLEAN_TOOL                     (0x00)
+#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL               (0x01)
+#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL          (0x03)
+#define MPI2_TOOLBOX_BEACON_TOOL                    (0x05)
+#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL            (0x06)
+
+
+/****************************************************************************
+*  Toolbox reply
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_REPLY
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY,
+  Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t;
+
+
+/****************************************************************************
+*  Toolbox Clean Tool request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U32                     Flags;                      /* 0x0C */
+   } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
+  Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t;
+
+/* values for the Flags field */
+#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES            (0x80000000)
+#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES   (0x40000000)
+#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES      (0x20000000)
+#define MPI2_TOOLBOX_CLEAN_FW_CURRENT               (0x10000000)
+#define MPI2_TOOLBOX_CLEAN_FW_BACKUP                (0x08000000)
+#define MPI2_TOOLBOX_CLEAN_MEGARAID                 (0x02000000)
+#define MPI2_TOOLBOX_CLEAN_INITIALIZATION           (0x01000000)
+#define MPI2_TOOLBOX_CLEAN_FLASH                    (0x00000004)
+#define MPI2_TOOLBOX_CLEAN_SEEPROM                  (0x00000002)
+#define MPI2_TOOLBOX_CLEAN_NVSRAM                   (0x00000001)
+
+
+/****************************************************************************
+*  Toolbox Memory Move request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x0C */
+} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
+  Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t;
+
+
+/****************************************************************************
+*  Toolbox ISTWI Read Write Tool
+****************************************************************************/
+
+/* Toolbox ISTWI Read Write Tool request message */
+typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U32                     Reserved5;                  /* 0x0C */
+    U32                     Reserved6;                  /* 0x10 */
+    U8                      DevIndex;                   /* 0x14 */
+    U8                      Action;                     /* 0x15 */
+    U8                      SGLFlags;                   /* 0x16 */
+    U8                      Reserved7;                  /* 0x17 */
+    U16                     TxDataLength;               /* 0x18 */
+    U16                     RxDataLength;               /* 0x1A */
+    U32                     Reserved8;                  /* 0x1C */
+    U32                     Reserved9;                  /* 0x20 */
+    U32                     Reserved10;                 /* 0x24 */
+    U32                     Reserved11;                 /* 0x28 */
+    U32                     Reserved12;                 /* 0x2C */
+    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x30 */
+} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+  Mpi2ToolboxIstwiReadWriteRequest_t,
+  MPI2_POINTER pMpi2ToolboxIstwiReadWriteRequest_t;
+
+/* values for the Action field */
+#define MPI2_TOOL_ISTWI_ACTION_READ_DATA            (0x01)
+#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA           (0x02)
+#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE             (0x03)
+#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS          (0x10)
+#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS          (0x11)
+#define MPI2_TOOL_ISTWI_ACTION_RESET                (0x12)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* Toolbox ISTWI Read Write Tool reply message */
+typedef struct _MPI2_TOOLBOX_ISTWI_REPLY
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U8                      DevIndex;                   /* 0x14 */
+    U8                      Action;                     /* 0x15 */
+    U8                      IstwiStatus;                /* 0x16 */
+    U8                      Reserved6;                  /* 0x17 */
+    U16                     TxDataCount;                /* 0x18 */
+    U16                     RxDataCount;                /* 0x1A */
+} MPI2_TOOLBOX_ISTWI_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_REPLY,
+  Mpi2ToolboxIstwiReply_t, MPI2_POINTER pMpi2ToolboxIstwiReply_t;
+
+
+/****************************************************************************
+*  Toolbox Beacon Tool request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_BEACON_REQUEST
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U8                      Reserved5;                  /* 0x0C */
+    U8                      PhysicalPort;               /* 0x0D */
+    U8                      Reserved6;                  /* 0x0E */
+    U8                      Flags;                      /* 0x0F */
+} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST,
+  Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t;
+
+/* values for the Flags field */
+#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF       (0x00)
+#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON        (0x01)
+
+
+/****************************************************************************
+*  Toolbox Diagnostic CLI Tool
+****************************************************************************/
+
+#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH    (0x5C)
+
+/* Toolbox Diagnostic CLI Tool request message */
+typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U8                      SGLFlags;                   /* 0x0C */
+    U8                      Reserved5;                  /* 0x0D */
+    U16                     Reserved6;                  /* 0x0E */
+    U32                     DataLength;                 /* 0x10 */
+    U8                      DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH]; /* 0x14 */
+    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x70 */
+} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+  Mpi2ToolboxDiagnosticCliRequest_t,
+  MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t;
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* Toolbox Diagnostic CLI Tool reply message */
+typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY
+{
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U32                     ReturnedDataLength;         /* 0x14 */
+} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY,
+  Mpi2ToolboxDiagnosticCliReply_t,
+  MPI2_POINTER pMpi2ToolboxDiagnosticCliReply_t;
+
+
+/*****************************************************************************
+*
+*       Diagnostic Buffer Messages
+*
+*****************************************************************************/
+
+
+/****************************************************************************
+*  Diagnostic Buffer Post request
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST
+{
+    U8                      ExtendedType;               /* 0x00 */
+    U8                      BufferType;                 /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U64                     BufferAddress;              /* 0x0C */
+    U32                     BufferLength;               /* 0x14 */
+    U32                     Reserved5;                  /* 0x18 */
+    U32                     Reserved6;                  /* 0x1C */
+    U32                     Flags;                      /* 0x20 */
+    U32                     ProductSpecific[23];        /* 0x24 */
+} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
+  Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t;
+
+/* values for the ExtendedType field */
+#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION         (0x02)
+
+/* values for the BufferType field */
+#define MPI2_DIAG_BUF_TYPE_TRACE                    (0x00)
+#define MPI2_DIAG_BUF_TYPE_SNAPSHOT                 (0x01)
+#define MPI2_DIAG_BUF_TYPE_EXTENDED                 (0x02)
+/* count of the number of buffer types */
+#define MPI2_DIAG_BUF_TYPE_COUNT                    (0x03)
+
+
+/****************************************************************************
+*  Diagnostic Buffer Post reply
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_BUFFER_POST_REPLY
+{
+    U8                      ExtendedType;               /* 0x00 */
+    U8                      BufferType;                 /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U32                     TransferLength;             /* 0x14 */
+} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY,
+  Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t;
+
+
+/****************************************************************************
+*  Diagnostic Release request
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_RELEASE_REQUEST
+{
+    U8                      Reserved1;                  /* 0x00 */
+    U8                      BufferType;                 /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST,
+  Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t;
+
+
+/****************************************************************************
+*  Diagnostic Buffer Post reply
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_RELEASE_REPLY
+{
+    U8                      Reserved1;                  /* 0x00 */
+    U8                      BufferType;                 /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY,
+  Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t;
+
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mpi/mpi2_type.h ../../stable/8/sys/dev/mps/mpi/mpi2_type.h
--- sys/dev/mps/mpi/mpi2_type.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpi/mpi2_type.h	2011-01-07 14:33:12.707737251 -0700
@@ -0,0 +1,99 @@
+/* $FreeBSD: stable/8/sys/dev/mps/mpi/mpi2_type.h 212420 2010-09-10 15:03:56Z ken $ */
+/*
+ *  Copyright (c) 2000-2007 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_type.h
+ *          Title:  MPI basic type definitions
+ *  Creation Date:  August 16, 2006
+ *
+ *    mpi2_type.h Version:  02.00.00
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TYPE_H
+#define MPI2_TYPE_H
+
+
+/*******************************************************************************
+ * Define MPI2_POINTER if it hasn't already been defined. By default
+ * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
+ * a far pointer by defining MPI2_POINTER as "far *" before this header file is
+ * included.
+ */
+#ifndef MPI2_POINTER
+#define MPI2_POINTER     *
+#endif
+
+/* the basic types may have already been included by mpi_type.h */
+#ifndef MPI_TYPE_H
+/*****************************************************************************
+*
+*               Basic Types
+*
+*****************************************************************************/
+
+typedef signed   char   S8;
+typedef unsigned char   U8;
+typedef signed   short  S16;
+typedef unsigned short  U16;
+
+#ifdef	__FreeBSD__
+
+typedef int32_t  S32;
+typedef uint32_t U32;
+
+#else
+
+#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc)
+
+    typedef signed   int   S32;
+    typedef unsigned int   U32;
+
+#else
+
+    typedef signed   long  S32;
+    typedef unsigned long  U32;
+
+#endif
+#endif
+
+typedef struct _S64
+{
+    U32          Low;
+    S32          High;
+} S64;
+
+typedef struct _U64
+{
+    U32          Low;
+    U32          High;
+} U64;
+
+
+/*****************************************************************************
+*
+*               Pointer Types
+*
+*****************************************************************************/
+
+typedef S8      *PS8;
+typedef U8      *PU8;
+typedef S16     *PS16;
+typedef U16     *PU16;
+typedef S32     *PS32;
+typedef U32     *PU32;
+typedef S64     *PS64;
+typedef U64     *PU64;
+
+#endif
+
+#endif
+
diff -x .svn -urN sys/dev/mps/mps.c ../../stable/8/sys/dev/mps/mps.c
--- sys/dev/mps/mps.c	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps.c	2011-01-07 14:37:54.164882195 -0700
@@ -0,0 +1,1821 @@
+/*-
+ * Copyright (c) 2009 Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/8/sys/dev/mps/mps.c 212420 2010-09-10 15:03:56Z ken $");
+
+/* Communications core for LSI MPT2 */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/selinfo.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <cam/scsi/scsi_all.h>
+
+#include <dev/mps/mpi/mpi2_type.h>
+#include <dev/mps/mpi/mpi2.h>
+#include <dev/mps/mpi/mpi2_ioc.h>
+#include <dev/mps/mpi/mpi2_cnfg.h>
+#include <dev/mps/mpsvar.h>
+#include <dev/mps/mps_table.h>
+
+static void mps_startup(void *arg);
+static void mps_startup_complete(struct mps_softc *sc, struct mps_command *cm);
+static int mps_send_iocinit(struct mps_softc *sc);
+static int mps_attach_log(struct mps_softc *sc);
+static void mps_dispatch_event(struct mps_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *reply);
+static void mps_config_complete(struct mps_softc *sc, struct mps_command *cm);
+static void mps_periodic(void *);
+
+SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
+
+MALLOC_DEFINE(M_MPT2, "mps", "mpt2 driver memory");
+
+/*
+ * Do a "Diagnostic Reset" aka a hard reset.  This should get the chip out of
+ * any state and back to its initialization state machine.
+ */
+static char mpt2_reset_magic[] = { 0x00, 0x0f, 0x04, 0x0b, 0x02, 0x07, 0x0d };
+
+static int
+mps_hard_reset(struct mps_softc *sc)
+{
+	uint32_t reg;
+	int i, error, tries = 0;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	/* Clear any pending interrupts */
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+
+	/* Push the magic sequence */
+	error = ETIMEDOUT;
+	while (tries++ < 20) {
+		for (i = 0; i < sizeof(mpt2_reset_magic); i++)
+			mps_regwrite(sc, MPI2_WRITE_SEQUENCE_OFFSET,
+			    mpt2_reset_magic[i]);
+
+		DELAY(100 * 1000);
+
+		reg = mps_regread(sc, MPI2_HOST_DIAGNOSTIC_OFFSET);
+		if (reg & MPI2_DIAG_DIAG_WRITE_ENABLE) {
+			error = 0;
+			break;
+		}
+	}
+	if (error)
+		return (error);
+
+	/* Send the actual reset.  XXX need to refresh the reg? */
+	mps_regwrite(sc, MPI2_HOST_DIAGNOSTIC_OFFSET,
+	    reg | MPI2_DIAG_RESET_ADAPTER);
+
+	/* Wait up to 300 seconds in 50ms intervals */
+	error = ETIMEDOUT;
+	for (i = 0; i < 60000; i++) {
+		DELAY(50000);
+		reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+		if ((reg & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_RESET) {
+			error = 0;
+			break;
+		}
+	}
+	if (error)
+		return (error);
+
+	mps_regwrite(sc, MPI2_WRITE_SEQUENCE_OFFSET, 0x0);
+
+	return (0);
+}
+
+static int
+mps_soft_reset(struct mps_softc *sc)
+{
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	mps_regwrite(sc, MPI2_DOORBELL_OFFSET,
+	    MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET <<
+	    MPI2_DOORBELL_FUNCTION_SHIFT);
+	DELAY(50000);
+
+	return (0);
+}
+
+static int
+mps_transition_ready(struct mps_softc *sc)
+{
+	uint32_t reg, state;
+	int error, tries = 0;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	error = 0;
+	while (tries++ < 5) {
+		reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+		mps_dprint(sc, MPS_INFO, "Doorbell= 0x%x\n", reg);
+
+		/*
+		 * Ensure the IOC is ready to talk.  If it's not, try
+		 * resetting it.
+		 */
+		if (reg & MPI2_DOORBELL_USED) {
+			mps_hard_reset(sc);
+			DELAY(50000);
+			continue;
+		}
+
+		/* Is the adapter owned by another peer? */
+		if ((reg & MPI2_DOORBELL_WHO_INIT_MASK) ==
+		    (MPI2_WHOINIT_PCI_PEER << MPI2_DOORBELL_WHO_INIT_SHIFT)) {
+			device_printf(sc->mps_dev, "IOC is under the control "
+			    "of another peer host, aborting initialization.\n");
+			return (ENXIO);
+		}
+		
+		state = reg & MPI2_IOC_STATE_MASK;
+		if (state == MPI2_IOC_STATE_READY) {
+			/* Ready to go! */
+			error = 0;
+			break;
+		} else if (state == MPI2_IOC_STATE_FAULT) {
+			mps_dprint(sc, MPS_INFO, "IOC in fault state 0x%x\n",
+			    state & MPI2_DOORBELL_FAULT_CODE_MASK);
+			mps_hard_reset(sc);
+		} else if (state == MPI2_IOC_STATE_OPERATIONAL) {
+			/* Need to take ownership */
+			mps_soft_reset(sc);
+		} else if (state == MPI2_IOC_STATE_RESET) {
+			/* Wait a bit, IOC might be in transition */
+			mps_dprint(sc, MPS_FAULT,
+			    "IOC in unexpected reset state\n");
+		} else {
+			mps_dprint(sc, MPS_FAULT,
+			    "IOC in unknown state 0x%x\n", state);
+			error = EINVAL;
+			break;
+		}
+	
+		/* Wait 50ms for things to settle down. */
+		DELAY(50000);
+	}
+
+	if (error)
+		device_printf(sc->mps_dev, "Cannot transition IOC to ready\n");
+
+	return (error);
+}
+
+static int
+mps_transition_operational(struct mps_softc *sc)
+{
+	uint32_t reg, state;
+	int error;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	error = 0;
+	reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+	mps_dprint(sc, MPS_INFO, "Doorbell= 0x%x\n", reg);
+
+	state = reg & MPI2_IOC_STATE_MASK;
+	if (state != MPI2_IOC_STATE_READY) {
+		if ((error = mps_transition_ready(sc)) != 0)
+			return (error);
+	}
+
+	error = mps_send_iocinit(sc);
+	return (error);
+}
+
+/* Wait for the chip to ACK a word that we've put into its FIFO */
+static int
+mps_wait_db_ack(struct mps_softc *sc)
+{
+	int retry;
+
+	for (retry = 0; retry < MPS_DB_MAX_WAIT; retry++) {
+		if ((mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET) &
+		    MPI2_HIS_SYS2IOC_DB_STATUS) == 0)
+			return (0);
+		DELAY(2000);
+	}
+	return (ETIMEDOUT);
+}
+
+/* Wait for the chip to signal that the next word in its FIFO can be fetched */
+static int
+mps_wait_db_int(struct mps_softc *sc)
+{
+	int retry;
+
+	for (retry = 0; retry < MPS_DB_MAX_WAIT; retry++) {
+		if ((mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET) &
+		    MPI2_HIS_IOC2SYS_DB_STATUS) != 0)
+			return (0);
+		DELAY(2000);
+	}
+	return (ETIMEDOUT);
+}
+
+/* Step through the synchronous command state machine, i.e. "Doorbell mode" */
+static int
+mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
+    int req_sz, int reply_sz, int timeout)
+{
+	uint32_t *data32;
+	uint16_t *data16;
+	int i, count, ioc_sz, residual;
+
+	/* Step 1 */
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+
+	/* Step 2 */
+	if (mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_USED)
+		return (EBUSY);
+
+	/* Step 3
+	 * Announce that a message is coming through the doorbell.  Messages
+	 * are pushed at 32bit words, so round up if needed.
+	 */
+	count = (req_sz + 3) / 4;
+	mps_regwrite(sc, MPI2_DOORBELL_OFFSET,
+	    (MPI2_FUNCTION_HANDSHAKE << MPI2_DOORBELL_FUNCTION_SHIFT) |
+	    (count << MPI2_DOORBELL_ADD_DWORDS_SHIFT));
+
+	/* Step 4 */
+	if (mps_wait_db_int(sc) ||
+	    (mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_USED) == 0) {
+		mps_dprint(sc, MPS_FAULT, "Doorbell failed to activate\n");
+		return (ENXIO);
+	}
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+	if (mps_wait_db_ack(sc) != 0) {
+		mps_dprint(sc, MPS_FAULT, "Doorbell handshake failed\n");
+		return (ENXIO);
+	}
+
+	/* Step 5 */
+	/* Clock out the message data synchronously in 32-bit dwords*/
+	data32 = (uint32_t *)req;
+	for (i = 0; i < count; i++) {
+		mps_regwrite(sc, MPI2_DOORBELL_OFFSET, data32[i]);
+		if (mps_wait_db_ack(sc) != 0) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Timeout while writing doorbell\n");
+			return (ENXIO);
+		}
+	}
+
+	/* Step 6 */
+	/* Clock in the reply in 16-bit words.  The total length of the
+	 * message is always in the 4th byte, so clock out the first 2 words
+	 * manually, then loop the rest.
+	 */
+	data16 = (uint16_t *)reply;
+	if (mps_wait_db_int(sc) != 0) {
+		mps_dprint(sc, MPS_FAULT, "Timeout reading doorbell 0\n");
+		return (ENXIO);
+	}
+	data16[0] =
+	    mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK;
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+	if (mps_wait_db_int(sc) != 0) {
+		mps_dprint(sc, MPS_FAULT, "Timeout reading doorbell 1\n");
+		return (ENXIO);
+	}
+	data16[1] =
+	    mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK;
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+
+	/* Number of 32bit words in the message */
+	ioc_sz = reply->MsgLength;
+
+	/*
+	 * Figure out how many 16bit words to clock in without overrunning.
+	 * The precision loss with dividing reply_sz can safely be
+	 * ignored because the messages can only be multiples of 32bits.
+	 */
+	residual = 0;
+	count = MIN((reply_sz / 4), ioc_sz) * 2;
+	if (count < ioc_sz * 2) {
+		residual = ioc_sz * 2 - count;
+		mps_dprint(sc, MPS_FAULT, "Driver error, throwing away %d "
+		    "residual message words\n", residual);
+	}
+
+	for (i = 2; i < count; i++) {
+		if (mps_wait_db_int(sc) != 0) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Timeout reading doorbell %d\n", i);
+			return (ENXIO);
+		}
+		data16[i] = mps_regread(sc, MPI2_DOORBELL_OFFSET) &
+		    MPI2_DOORBELL_DATA_MASK;
+		mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+	}
+
+	/*
+	 * Pull out residual words that won't fit into the provided buffer.
+	 * This keeps the chip from hanging due to a driver programming
+	 * error.
+	 */
+	while (residual--) {
+		if (mps_wait_db_int(sc) != 0) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Timeout reading doorbell\n");
+			return (ENXIO);
+		}
+		(void)mps_regread(sc, MPI2_DOORBELL_OFFSET);
+		mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+	}
+
+	/* Step 7 */
+	if (mps_wait_db_int(sc) != 0) {
+		mps_dprint(sc, MPS_FAULT, "Timeout waiting to exit doorbell\n");
+		return (ENXIO);
+	}
+	if (mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_USED)
+		mps_dprint(sc, MPS_FAULT, "Warning, doorbell still active\n");
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+
+	return (0);
+}
+
+void
+mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
+{
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	mps_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET,
+	    cm->cm_desc.Words.Low);
+	mps_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET,
+	    cm->cm_desc.Words.High);
+}
+
+int
+mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
+{
+	int error, timeout = 0;
+
+	error = 0;
+
+	cm->cm_flags |= MPS_CM_FLAGS_POLLED;
+	cm->cm_complete = NULL;
+	mps_map_command(sc, cm);
+
+	while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
+		mps_intr(sc);
+		DELAY(50 * 1000);
+		if (timeout++ > 1000) {
+			mps_dprint(sc, MPS_FAULT, "polling failed\n");
+			error = ETIMEDOUT;
+			break;
+		}
+	}
+
+	return (error);
+}
+
+/*
+ * Just the FACTS, ma'am.
+ */
+static int
+mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts)
+{
+	MPI2_DEFAULT_REPLY *reply;
+	MPI2_IOC_FACTS_REQUEST request;
+	int error, req_sz, reply_sz;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	req_sz = sizeof(MPI2_IOC_FACTS_REQUEST);
+	reply_sz = sizeof(MPI2_IOC_FACTS_REPLY);
+	reply = (MPI2_DEFAULT_REPLY *)facts;
+
+	bzero(&request, req_sz);
+	request.Function = MPI2_FUNCTION_IOC_FACTS;
+	error = mps_request_sync(sc, &request, reply, req_sz, reply_sz, 5);
+
+	return (error);
+}
+
+static int
+mps_get_portfacts(struct mps_softc *sc, MPI2_PORT_FACTS_REPLY *facts, int port)
+{
+	MPI2_PORT_FACTS_REQUEST *request;
+	MPI2_PORT_FACTS_REPLY *reply;
+	struct mps_command *cm;
+	int error;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL)
+		return (EBUSY);
+	request = (MPI2_PORT_FACTS_REQUEST *)cm->cm_req;
+	request->Function = MPI2_FUNCTION_PORT_FACTS;
+	request->PortNumber = port;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_PORT_FACTS_REPLY *)cm->cm_reply;
+	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
+		error = ENXIO;
+	bcopy(reply, facts, sizeof(MPI2_PORT_FACTS_REPLY));
+	mps_free_command(sc, cm);
+
+	return (error);
+}
+
+static int
+mps_send_iocinit(struct mps_softc *sc)
+{
+	MPI2_IOC_INIT_REQUEST	init;
+	MPI2_DEFAULT_REPLY	reply;
+	int req_sz, reply_sz, error;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	req_sz = sizeof(MPI2_IOC_INIT_REQUEST);
+	reply_sz = sizeof(MPI2_IOC_INIT_REPLY);
+	bzero(&init, req_sz);
+	bzero(&reply, reply_sz);
+
+	/*
+	 * Fill in the init block.  Note that most addresses are
+	 * deliberately in the lower 32bits of memory.  This is a micro-
+	 * optimzation for PCI/PCIX, though it's not clear if it helps PCIe.
+	 */
+	init.Function = MPI2_FUNCTION_IOC_INIT;
+	init.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
+	init.MsgVersion = MPI2_VERSION;
+	init.HeaderVersion = MPI2_HEADER_VERSION;
+	init.SystemRequestFrameSize = sc->facts->IOCRequestFrameSize;
+	init.ReplyDescriptorPostQueueDepth = sc->pqdepth;
+	init.ReplyFreeQueueDepth = sc->fqdepth;
+	init.SenseBufferAddressHigh = 0;
+	init.SystemReplyAddressHigh = 0;
+	init.SystemRequestFrameBaseAddress.High = 0;
+	init.SystemRequestFrameBaseAddress.Low = (uint32_t)sc->req_busaddr;
+	init.ReplyDescriptorPostQueueAddress.High = 0;
+	init.ReplyDescriptorPostQueueAddress.Low = (uint32_t)sc->post_busaddr;
+	init.ReplyFreeQueueAddress.High = 0;
+	init.ReplyFreeQueueAddress.Low = (uint32_t)sc->free_busaddr;
+	init.TimeStamp.High = 0;
+	init.TimeStamp.Low = (uint32_t)time_uptime;
+
+	error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
+	if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
+		error = ENXIO;
+
+	mps_dprint(sc, MPS_INFO, "IOCInit status= 0x%x\n", reply.IOCStatus);
+	return (error);
+}
+
+static int
+mps_send_portenable(struct mps_softc *sc)
+{
+	MPI2_PORT_ENABLE_REQUEST *request;
+	struct mps_command *cm;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL)
+		return (EBUSY);
+	request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req;
+	request->Function = MPI2_FUNCTION_PORT_ENABLE;
+	request->MsgFlags = 0;
+	request->VP_ID = 0;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_complete = mps_startup_complete;
+
+	mps_enqueue_request(sc, cm);
+	return (0);
+}
+
+static int
+mps_send_mur(struct mps_softc *sc)
+{
+
+	/* Placeholder */
+	return (0);
+}
+
+void
+mps_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	bus_addr_t *addr;
+
+	addr = arg;
+	*addr = segs[0].ds_addr;
+}
+
+static int
+mps_alloc_queues(struct mps_softc *sc)
+{
+	bus_addr_t queues_busaddr;
+	uint8_t *queues;
+	int qsize, fqsize, pqsize;
+
+	/*
+	 * The reply free queue contains 4 byte entries in multiples of 16 and
+	 * aligned on a 16 byte boundary. There must always be an unused entry.
+	 * This queue supplies fresh reply frames for the firmware to use.
+	 *
+	 * The reply descriptor post queue contains 8 byte entries in
+	 * multiples of 16 and aligned on a 16 byte boundary.  This queue
+	 * contains filled-in reply frames sent from the firmware to the host.
+	 *
+	 * These two queues are allocated together for simplicity.
+	 */
+	sc->fqdepth = roundup2((sc->num_replies + 1), 16);
+	sc->pqdepth = roundup2((sc->num_replies + 1), 16);
+	fqsize= sc->fqdepth * 4;
+	pqsize = sc->pqdepth * 8;
+	qsize = fqsize + pqsize;
+
+        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+				16, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+                                qsize,			/* maxsize */
+                                1,			/* nsegments */
+                                qsize,			/* maxsegsize */
+                                0,			/* flags */
+                                NULL, NULL,		/* lockfunc, lockarg */
+                                &sc->queues_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate queues DMA tag\n");
+		return (ENOMEM);
+        }
+        if (bus_dmamem_alloc(sc->queues_dmat, (void **)&queues, BUS_DMA_NOWAIT,
+	    &sc->queues_map)) {
+		device_printf(sc->mps_dev, "Cannot allocate queues memory\n");
+		return (ENOMEM);
+        }
+        bzero(queues, qsize);
+        bus_dmamap_load(sc->queues_dmat, sc->queues_map, queues, qsize,
+	    mps_memaddr_cb, &queues_busaddr, 0);
+
+	sc->free_queue = (uint32_t *)queues;
+	sc->free_busaddr = queues_busaddr;
+	sc->post_queue = (MPI2_REPLY_DESCRIPTORS_UNION *)(queues + fqsize);
+	sc->post_busaddr = queues_busaddr + fqsize;
+
+	return (0);
+}
+
+static int
+mps_alloc_replies(struct mps_softc *sc)
+{
+	int rsize, num_replies;
+
+	/*
+	 * sc->num_replies should be one less than sc->fqdepth.  We need to
+	 * allocate space for sc->fqdepth replies, but only sc->num_replies
+	 * replies can be used at once.
+	 */
+	num_replies = max(sc->fqdepth, sc->num_replies);
+
+	rsize = sc->facts->ReplyFrameSize * num_replies * 4; 
+        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+				4, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+                                rsize,			/* maxsize */
+                                1,			/* nsegments */
+                                rsize,			/* maxsegsize */
+                                0,			/* flags */
+                                NULL, NULL,		/* lockfunc, lockarg */
+                                &sc->reply_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate replies DMA tag\n");
+		return (ENOMEM);
+        }
+        if (bus_dmamem_alloc(sc->reply_dmat, (void **)&sc->reply_frames,
+	    BUS_DMA_NOWAIT, &sc->reply_map)) {
+		device_printf(sc->mps_dev, "Cannot allocate replies memory\n");
+		return (ENOMEM);
+        }
+        bzero(sc->reply_frames, rsize);
+        bus_dmamap_load(sc->reply_dmat, sc->reply_map, sc->reply_frames, rsize,
+	    mps_memaddr_cb, &sc->reply_busaddr, 0);
+
+	return (0);
+}
+
+static int
+mps_alloc_requests(struct mps_softc *sc)
+{
+	struct mps_command *cm;
+	struct mps_chain *chain;
+	int i, rsize, nsegs;
+
+	rsize = sc->facts->IOCRequestFrameSize * sc->num_reqs * 4;
+        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+				16, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+                                rsize,			/* maxsize */
+                                1,			/* nsegments */
+                                rsize,			/* maxsegsize */
+                                0,			/* flags */
+                                NULL, NULL,		/* lockfunc, lockarg */
+                                &sc->req_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate request DMA tag\n");
+		return (ENOMEM);
+        }
+        if (bus_dmamem_alloc(sc->req_dmat, (void **)&sc->req_frames,
+	    BUS_DMA_NOWAIT, &sc->req_map)) {
+		device_printf(sc->mps_dev, "Cannot allocate request memory\n");
+		return (ENOMEM);
+        }
+        bzero(sc->req_frames, rsize);
+        bus_dmamap_load(sc->req_dmat, sc->req_map, sc->req_frames, rsize,
+	    mps_memaddr_cb, &sc->req_busaddr, 0);
+
+	rsize = sc->facts->IOCRequestFrameSize * MPS_CHAIN_FRAMES * 4;
+        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+				16, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+                                rsize,			/* maxsize */
+                                1,			/* nsegments */
+                                rsize,			/* maxsegsize */
+                                0,			/* flags */
+                                NULL, NULL,		/* lockfunc, lockarg */
+                                &sc->chain_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate chain DMA tag\n");
+		return (ENOMEM);
+        }
+        if (bus_dmamem_alloc(sc->chain_dmat, (void **)&sc->chain_frames,
+	    BUS_DMA_NOWAIT, &sc->chain_map)) {
+		device_printf(sc->mps_dev, "Cannot allocate chain memory\n");
+		return (ENOMEM);
+        }
+        bzero(sc->chain_frames, rsize);
+        bus_dmamap_load(sc->chain_dmat, sc->chain_map, sc->chain_frames, rsize,
+	    mps_memaddr_cb, &sc->chain_busaddr, 0);
+
+	rsize = MPS_SENSE_LEN * sc->num_reqs;
+        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+                                rsize,			/* maxsize */
+                                1,			/* nsegments */
+                                rsize,			/* maxsegsize */
+                                0,			/* flags */
+                                NULL, NULL,		/* lockfunc, lockarg */
+                                &sc->sense_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate sense DMA tag\n");
+		return (ENOMEM);
+        }
+        if (bus_dmamem_alloc(sc->sense_dmat, (void **)&sc->sense_frames,
+	    BUS_DMA_NOWAIT, &sc->sense_map)) {
+		device_printf(sc->mps_dev, "Cannot allocate sense memory\n");
+		return (ENOMEM);
+        }
+        bzero(sc->sense_frames, rsize);
+        bus_dmamap_load(sc->sense_dmat, sc->sense_map, sc->sense_frames, rsize,
+	    mps_memaddr_cb, &sc->sense_busaddr, 0);
+
+	sc->chains = malloc(sizeof(struct mps_chain) * MPS_CHAIN_FRAMES,
+	    M_MPT2, M_WAITOK | M_ZERO);
+	for (i = 0; i < MPS_CHAIN_FRAMES; i++) {
+		chain = &sc->chains[i];
+		chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames +
+		    i * sc->facts->IOCRequestFrameSize * 4);
+		chain->chain_busaddr = sc->chain_busaddr +
+		    i * sc->facts->IOCRequestFrameSize * 4;
+		mps_free_chain(sc, chain);
+	}
+
+	/* XXX Need to pick a more precise value */
+	nsegs = (MAXPHYS / PAGE_SIZE) + 1;
+        if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR,	/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+                                BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
+                                nsegs,			/* nsegments */
+                                BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+                                BUS_DMA_ALLOCNOW,	/* flags */
+                                busdma_lock_mutex,	/* lockfunc */
+				&sc->mps_mtx,		/* lockarg */
+                                &sc->buffer_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate sense DMA tag\n");
+		return (ENOMEM);
+        }
+
+	/*
+	 * SMID 0 cannot be used as a free command per the firmware spec.
+	 * Just drop that command instead of risking accounting bugs.
+	 */
+	sc->commands = malloc(sizeof(struct mps_command) * sc->num_reqs,
+	    M_MPT2, M_WAITOK | M_ZERO);
+	for (i = 1; i < sc->num_reqs; i++) {
+		cm = &sc->commands[i];
+		cm->cm_req = sc->req_frames +
+		    i * sc->facts->IOCRequestFrameSize * 4;
+		cm->cm_req_busaddr = sc->req_busaddr +
+		    i * sc->facts->IOCRequestFrameSize * 4;
+		cm->cm_sense = &sc->sense_frames[i];
+		cm->cm_sense_busaddr = sc->sense_busaddr + i * MPS_SENSE_LEN;
+		cm->cm_desc.Default.SMID = i;
+		cm->cm_sc = sc;
+		TAILQ_INIT(&cm->cm_chain_list);
+		callout_init(&cm->cm_callout, 1 /*MPSAFE*/);
+
+		/* XXX Is a failure here a critical problem? */
+		if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) == 0)
+			mps_free_command(sc, cm);
+		else {
+			sc->num_reqs = i;
+			break;
+		}
+	}
+
+	return (0);
+}
+
+static int
+mps_init_queues(struct mps_softc *sc)
+{
+	int i;
+
+	memset((uint8_t *)sc->post_queue, 0xff, sc->pqdepth * 8);
+
+	/*
+	 * According to the spec, we need to use one less reply than we
+	 * have space for on the queue.  So sc->num_replies (the number we
+	 * use) should be less than sc->fqdepth (allocated size).
+	 */
+	if (sc->num_replies >= sc->fqdepth)
+		return (EINVAL);
+
+	/*
+	 * Initialize all of the free queue entries.
+	 */
+	for (i = 0; i < sc->fqdepth; i++)
+		sc->free_queue[i] = sc->reply_busaddr + (i * sc->facts->ReplyFrameSize * 4);
+	sc->replyfreeindex = sc->num_replies;
+
+	return (0);
+}
+
+int
+mps_attach(struct mps_softc *sc)
+{
+	int i, error;
+	char tmpstr[80], tmpstr2[80];
+
+	/*
+	 * Grab any tunable-set debug level so that tracing works as early
+	 * as possible.
+	 */
+	snprintf(tmpstr, sizeof(tmpstr), "hw.mps.%d.debug_level",
+	    device_get_unit(sc->mps_dev));
+	TUNABLE_INT_FETCH(tmpstr, &sc->mps_debug);
+	snprintf(tmpstr, sizeof(tmpstr), "hw.mps.%d.allow_multiple_tm_cmds",
+	    device_get_unit(sc->mps_dev));
+	TUNABLE_INT_FETCH(tmpstr, &sc->allow_multiple_tm_cmds);
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	mtx_init(&sc->mps_mtx, "MPT2SAS lock", NULL, MTX_DEF);
+	callout_init_mtx(&sc->periodic, &sc->mps_mtx, 0);
+	TAILQ_INIT(&sc->event_list);
+
+	/*
+	 * Setup the sysctl variable so the user can change the debug level
+	 * on the fly.
+	 */
+	snprintf(tmpstr, sizeof(tmpstr), "MPS controller %d",
+	    device_get_unit(sc->mps_dev));
+	snprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mps_dev));
+
+	sysctl_ctx_init(&sc->sysctl_ctx);
+	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
+	    SYSCTL_STATIC_CHILDREN(_hw_mps), OID_AUTO, tmpstr2, CTLFLAG_RD,
+	    0, tmpstr);
+	if (sc->sysctl_tree == NULL)
+		return (ENOMEM);
+
+	SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
+	    OID_AUTO, "debug_level", CTLFLAG_RW, &sc->mps_debug, 0,
+	    "mps debug level");
+
+	SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
+	    OID_AUTO, "allow_multiple_tm_cmds", CTLFLAG_RW,
+	    &sc->allow_multiple_tm_cmds, 0,
+	    "allow multiple simultaneous task management cmds");
+
+	if ((error = mps_transition_ready(sc)) != 0)
+		return (error);
+
+	sc->facts = malloc(sizeof(MPI2_IOC_FACTS_REPLY), M_MPT2,
+	    M_ZERO|M_NOWAIT);
+	if ((error = mps_get_iocfacts(sc, sc->facts)) != 0)
+		return (error);
+
+	mps_print_iocfacts(sc, sc->facts);
+
+	mps_printf(sc, "Firmware: %02d.%02d.%02d.%02d\n",
+	    sc->facts->FWVersion.Struct.Major,
+	    sc->facts->FWVersion.Struct.Minor,
+	    sc->facts->FWVersion.Struct.Unit,
+	    sc->facts->FWVersion.Struct.Dev);
+	mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities,
+	    "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
+	    "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
+	    "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
+
+	/*
+	 * If the chip doesn't support event replay then a hard reset will be
+	 * required to trigger a full discovery.  Do the reset here then
+	 * retransition to Ready.  A hard reset might have already been done,
+	 * but it doesn't hurt to do it again.
+	 */
+	if ((sc->facts->IOCCapabilities &
+	    MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
+		mps_hard_reset(sc);
+		if ((error = mps_transition_ready(sc)) != 0)
+			return (error);
+	}
+
+	/*
+	 * Size the queues. Since the reply queues always need one free entry,
+	 * we'll just deduct one reply message here.
+	 */
+	sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
+	sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
+	    sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
+	TAILQ_INIT(&sc->req_list);
+	TAILQ_INIT(&sc->chain_list);
+	TAILQ_INIT(&sc->tm_list);
+
+	if (((error = mps_alloc_queues(sc)) != 0) ||
+	    ((error = mps_alloc_replies(sc)) != 0) ||
+	    ((error = mps_alloc_requests(sc)) != 0)) {
+		mps_free(sc);
+		return (error);
+	}
+
+	if (((error = mps_init_queues(sc)) != 0) ||
+	    ((error = mps_transition_operational(sc)) != 0)) {
+		mps_free(sc);
+		return (error);
+	}
+
+	/*
+	 * Finish the queue initialization.
+	 * These are set here instead of in mps_init_queues() because the
+	 * IOC resets these values during the state transition in
+	 * mps_transition_operational().  The free index is set to 1
+	 * because the corresponding index in the IOC is set to 0, and the
+	 * IOC treats the queues as full if both are set to the same value.
+	 * Hence the reason that the queue can't hold all of the possible
+	 * replies.
+	 */
+	sc->replypostindex = 0;
+	mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
+	mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0);
+
+	sc->pfacts = malloc(sizeof(MPI2_PORT_FACTS_REPLY) *
+	    sc->facts->NumberOfPorts, M_MPT2, M_ZERO|M_WAITOK);
+	for (i = 0; i < sc->facts->NumberOfPorts; i++) {
+		if ((error = mps_get_portfacts(sc, &sc->pfacts[i], i)) != 0) {
+			mps_free(sc);
+			return (error);
+		}
+		mps_print_portfacts(sc, &sc->pfacts[i]);
+	}
+
+	/* Attach the subsystems so they can prepare their event masks. */
+	/* XXX Should be dynamic so that IM/IR and user modules can attach */
+	if (((error = mps_attach_log(sc)) != 0) ||
+	    ((error = mps_attach_sas(sc)) != 0) ||
+	    ((error = mps_attach_user(sc)) != 0)) {
+		mps_printf(sc, "%s failed to attach all subsystems: error %d\n",
+		    __func__, error);
+		mps_free(sc);
+		return (error);
+	}
+
+	if ((error = mps_pci_setup_interrupts(sc)) != 0) {
+		mps_free(sc);
+		return (error);
+	}
+
+	/* Start the periodic watchdog check on the IOC Doorbell */
+	mps_periodic(sc);
+
+	/*
+	 * The portenable will kick off discovery events that will drive the
+	 * rest of the initialization process.  The CAM/SAS module will
+	 * hold up the boot sequence until discovery is complete.
+	 */
+	sc->mps_ich.ich_func = mps_startup;
+	sc->mps_ich.ich_arg = sc;
+	if (config_intrhook_establish(&sc->mps_ich) != 0) {
+		mps_dprint(sc, MPS_FAULT, "Cannot establish MPS config hook\n");
+		error = EINVAL;
+	}
+
+	return (error);
+}
+
+static void
+mps_startup(void *arg)
+{
+	struct mps_softc *sc;
+
+	sc = (struct mps_softc *)arg;
+
+	mps_lock(sc);
+	mps_unmask_intr(sc);
+	mps_send_portenable(sc);
+	mps_unlock(sc);
+}
+
+/* Periodic watchdog.  Is called with the driver lock already held. */
+static void
+mps_periodic(void *arg)
+{
+	struct mps_softc *sc;
+	uint32_t db;
+
+	sc = (struct mps_softc *)arg;
+	if (sc->mps_flags & MPS_FLAGS_SHUTDOWN)
+		return;
+
+	db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+	if ((db & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+		device_printf(sc->mps_dev, "IOC Fault 0x%08x, Resetting\n", db);
+		/* XXX Need to broaden this to re-initialize the chip */
+		mps_hard_reset(sc);
+		db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+		if ((db & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+			device_printf(sc->mps_dev, "Second IOC Fault 0x%08x, "
+			    "Giving up!\n", db);
+			return;
+		}
+	}
+
+	callout_reset(&sc->periodic, MPS_PERIODIC_DELAY * hz, mps_periodic, sc);
+}
+
+static void
+mps_startup_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_PORT_ENABLE_REPLY *reply;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply;
+	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
+		mps_dprint(sc, MPS_FAULT, "Portenable failed\n");
+
+	mps_free_command(sc, cm);
+	config_intrhook_disestablish(&sc->mps_ich);
+
+}
+
+static void
+mps_log_evt_handler(struct mps_softc *sc, uintptr_t data,
+    MPI2_EVENT_NOTIFICATION_REPLY *event)
+{
+	MPI2_EVENT_DATA_LOG_ENTRY_ADDED *entry;
+
+	mps_print_event(sc, event);
+
+	switch (event->Event) {
+	case MPI2_EVENT_LOG_DATA:
+		device_printf(sc->mps_dev, "MPI2_EVENT_LOG_DATA:\n");
+		hexdump(event->EventData, event->EventDataLength, NULL, 0);
+		break;
+	case MPI2_EVENT_LOG_ENTRY_ADDED:
+		entry = (MPI2_EVENT_DATA_LOG_ENTRY_ADDED *)event->EventData;
+		mps_dprint(sc, MPS_INFO, "MPI2_EVENT_LOG_ENTRY_ADDED event "
+		    "0x%x Sequence %d:\n", entry->LogEntryQualifier,
+		     entry->LogSequence);
+		break;
+	default:
+		break;
+	}
+	return;
+}
+
+static int
+mps_attach_log(struct mps_softc *sc)
+{
+	uint8_t events[16];
+
+	bzero(events, 16);
+	setbit(events, MPI2_EVENT_LOG_DATA);
+	setbit(events, MPI2_EVENT_LOG_ENTRY_ADDED);
+
+	mps_register_events(sc, events, mps_log_evt_handler, NULL,
+	    &sc->mps_log_eh);
+
+	return (0);
+}
+
+static int
+mps_detach_log(struct mps_softc *sc)
+{
+
+	if (sc->mps_log_eh != NULL)
+		mps_deregister_events(sc, sc->mps_log_eh);
+	return (0);
+}
+
+/*
+ * Free all of the driver resources and detach submodules.  Should be called
+ * without the lock held.
+ */
+int
+mps_free(struct mps_softc *sc)
+{
+	struct mps_command *cm;
+	int i, error;
+
+	/* Turn off the watchdog */
+	mps_lock(sc);
+	sc->mps_flags |= MPS_FLAGS_SHUTDOWN;
+	mps_unlock(sc);
+	/* Lock must not be held for this */
+	callout_drain(&sc->periodic);
+
+	if (((error = mps_detach_log(sc)) != 0) ||
+	    ((error = mps_detach_sas(sc)) != 0))
+		return (error);
+
+	/* Put the IOC back in the READY state. */
+	mps_lock(sc);
+	if ((error = mps_send_mur(sc)) != 0) {
+		mps_unlock(sc);
+		return (error);
+	}
+	mps_unlock(sc);
+
+	if (sc->facts != NULL)
+		free(sc->facts, M_MPT2);
+
+	if (sc->pfacts != NULL)
+		free(sc->pfacts, M_MPT2);
+
+	if (sc->post_busaddr != 0)
+		bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
+	if (sc->post_queue != NULL)
+		bus_dmamem_free(sc->queues_dmat, sc->post_queue,
+		    sc->queues_map);
+	if (sc->queues_dmat != NULL)
+		bus_dma_tag_destroy(sc->queues_dmat);
+
+	if (sc->chain_busaddr != 0)
+		bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
+	if (sc->chain_frames != NULL)
+		bus_dmamem_free(sc->chain_dmat, sc->chain_frames,sc->chain_map);
+	if (sc->chain_dmat != NULL)
+		bus_dma_tag_destroy(sc->chain_dmat);
+
+	if (sc->sense_busaddr != 0)
+		bus_dmamap_unload(sc->sense_dmat, sc->sense_map);
+	if (sc->sense_frames != NULL)
+		bus_dmamem_free(sc->sense_dmat, sc->sense_frames,sc->sense_map);
+	if (sc->sense_dmat != NULL)
+		bus_dma_tag_destroy(sc->sense_dmat);
+
+	if (sc->reply_busaddr != 0)
+		bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
+	if (sc->reply_frames != NULL)
+		bus_dmamem_free(sc->reply_dmat, sc->reply_frames,sc->reply_map);
+	if (sc->reply_dmat != NULL)
+		bus_dma_tag_destroy(sc->reply_dmat);
+
+	if (sc->req_busaddr != 0)
+		bus_dmamap_unload(sc->req_dmat, sc->req_map);
+	if (sc->req_frames != NULL)
+		bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map);
+	if (sc->req_dmat != NULL)
+		bus_dma_tag_destroy(sc->req_dmat);
+
+	if (sc->chains != NULL)
+		free(sc->chains, M_MPT2);
+	if (sc->commands != NULL) {
+		for (i = 1; i < sc->num_reqs; i++) {
+			cm = &sc->commands[i];
+			bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap);
+		}
+		free(sc->commands, M_MPT2);
+	}
+	if (sc->buffer_dmat != NULL)
+		bus_dma_tag_destroy(sc->buffer_dmat);
+
+	if (sc->sysctl_tree != NULL)
+		sysctl_ctx_free(&sc->sysctl_ctx);
+
+	mtx_destroy(&sc->mps_mtx);
+
+	return (0);
+}
+
+void
+mps_intr(void *data)
+{
+	struct mps_softc *sc;
+	uint32_t status;
+
+	sc = (struct mps_softc *)data;
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	/*
+	 * Check interrupt status register to flush the bus.  This is
+	 * needed for both INTx interrupts and driver-driven polling
+	 */
+	status = mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET);
+	if ((status & MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT) == 0)
+		return;
+
+	mps_lock(sc);
+	mps_intr_locked(data);
+	mps_unlock(sc);
+	return;
+}
+
+/*
+ * In theory, MSI/MSIX interrupts shouldn't need to read any registers on the
+ * chip.  Hopefully this theory is correct.
+ */
+void
+mps_intr_msi(void *data)
+{
+	struct mps_softc *sc;
+
+	sc = (struct mps_softc *)data;
+	mps_lock(sc);
+	mps_intr_locked(data);
+	mps_unlock(sc);
+	return;
+}
+
+/*
+ * The locking is overly broad and simplistic, but easy to deal with for now.
+ */
+void
+mps_intr_locked(void *data)
+{
+	MPI2_REPLY_DESCRIPTORS_UNION *desc;
+	struct mps_softc *sc;
+	struct mps_command *cm = NULL;
+	uint8_t flags;
+	u_int pq;
+
+	sc = (struct mps_softc *)data;
+
+	pq = sc->replypostindex;
+
+	for ( ;; ) {
+		cm = NULL;
+		desc = &sc->post_queue[pq];
+		flags = desc->Default.ReplyFlags &
+		    MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+		if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+		 || (desc->Words.High == 0xffffffff))
+			break;
+
+		switch (flags) {
+		case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS:
+			cm = &sc->commands[desc->SCSIIOSuccess.SMID];
+			cm->cm_reply = NULL;
+			break;
+		case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY:
+		{
+			uint32_t baddr;
+			uint8_t *reply;
+
+			/*
+			 * Re-compose the reply address from the address
+			 * sent back from the chip.  The ReplyFrameAddress
+			 * is the lower 32 bits of the physical address of
+			 * particular reply frame.  Convert that address to
+			 * host format, and then use that to provide the
+			 * offset against the virtual address base
+			 * (sc->reply_frames).
+			 */
+			baddr = le32toh(desc->AddressReply.ReplyFrameAddress);
+			reply = sc->reply_frames +
+				(baddr - ((uint32_t)sc->reply_busaddr));
+			/*
+			 * Make sure the reply we got back is in a valid
+			 * range.  If not, go ahead and panic here, since
+			 * we'll probably panic as soon as we deference the
+			 * reply pointer anyway.
+			 */
+			if ((reply < sc->reply_frames)
+			 || (reply > (sc->reply_frames +
+			     (sc->fqdepth * sc->facts->ReplyFrameSize * 4)))) {
+				printf("%s: WARNING: reply %p out of range!\n",
+				       __func__, reply);
+				printf("%s: reply_frames %p, fqdepth %d, "
+				       "frame size %d\n", __func__,
+				       sc->reply_frames, sc->fqdepth,
+				       sc->facts->ReplyFrameSize * 4);
+				printf("%s: baddr %#x,\n", __func__, baddr);
+				panic("Reply address out of range");
+			}
+			if (desc->AddressReply.SMID == 0) {
+				mps_dispatch_event(sc, baddr,
+				   (MPI2_EVENT_NOTIFICATION_REPLY *) reply);
+			} else {
+				cm = &sc->commands[desc->AddressReply.SMID];
+				cm->cm_reply = reply;
+				cm->cm_reply_data =
+				    desc->AddressReply.ReplyFrameAddress;
+			}
+			break;
+		}
+		case MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS:
+		case MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER:
+		case MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS:
+		default:
+			/* Unhandled */
+			device_printf(sc->mps_dev, "Unhandled reply 0x%x\n",
+			    desc->Default.ReplyFlags);
+			cm = NULL;
+			break;
+		}
+
+		if (cm != NULL) {
+			if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
+				cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
+
+			if (cm->cm_complete != NULL)
+				cm->cm_complete(sc, cm);
+
+			if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP)
+				wakeup(cm);
+		}
+
+		desc->Words.Low = 0xffffffff;
+		desc->Words.High = 0xffffffff;
+		if (++pq >= sc->pqdepth)
+			pq = 0;
+	}
+
+	if (pq != sc->replypostindex) {
+		mps_dprint(sc, MPS_INFO, "writing postindex %d\n", pq);
+		mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, pq);
+		sc->replypostindex = pq;
+	}
+
+	return;
+}
+
+static void
+mps_dispatch_event(struct mps_softc *sc, uintptr_t data,
+    MPI2_EVENT_NOTIFICATION_REPLY *reply)
+{
+	struct mps_event_handle *eh;
+	int event, handled = 0;
+
+	event = reply->Event;
+	TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
+		if (isset(eh->mask, event)) {
+			eh->callback(sc, data, reply);
+			handled++;
+		}
+	}
+
+	if (handled == 0)
+		device_printf(sc->mps_dev, "Unhandled event 0x%x\n", event);
+}
+
+/*
+ * For both register_events and update_events, the caller supplies a bitmap
+ * of events that it _wants_.  These functions then turn that into a bitmask
+ * suitable for the controller.
+ */
+int
+mps_register_events(struct mps_softc *sc, uint8_t *mask,
+    mps_evt_callback_t *cb, void *data, struct mps_event_handle **handle)
+{
+	struct mps_event_handle *eh;
+	int error = 0;
+
+	eh = malloc(sizeof(struct mps_event_handle), M_MPT2, M_WAITOK|M_ZERO);
+	eh->callback = cb;
+	eh->data = data;
+	TAILQ_INSERT_TAIL(&sc->event_list, eh, eh_list);
+	if (mask != NULL)
+		error = mps_update_events(sc, eh, mask);
+	*handle = eh;
+
+	return (error);
+}
+
+int
+mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle,
+    uint8_t *mask)
+{
+	MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
+	MPI2_EVENT_NOTIFICATION_REPLY *reply;
+	struct mps_command *cm;
+	struct mps_event_handle *eh;
+	int error, i;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((mask != NULL) && (handle != NULL))
+		bcopy(mask, &handle->mask[0], 16);
+	memset(sc->event_mask, 0xff, 16);
+
+	TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
+		for (i = 0; i < 16; i++)
+			sc->event_mask[i] &= ~eh->mask[i];
+	}
+
+	if ((cm = mps_alloc_command(sc)) == NULL)
+		return (EBUSY);
+	evtreq = (MPI2_EVENT_NOTIFICATION_REQUEST *)cm->cm_req;
+	evtreq->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
+	evtreq->MsgFlags = 0;
+	evtreq->SASBroadcastPrimitiveMasks = 0;
+#ifdef MPS_DEBUG_ALL_EVENTS
+	{
+		u_char fullmask[16];
+		memset(fullmask, 0x00, 16);
+		bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16);
+	}
+#else
+		bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16);
+#endif
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply;
+	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
+		error = ENXIO;
+	mps_print_event(sc, reply);
+
+	mps_free_command(sc, cm);
+	return (error);
+}
+
+int
+mps_deregister_events(struct mps_softc *sc, struct mps_event_handle *handle)
+{
+
+	TAILQ_REMOVE(&sc->event_list, handle, eh_list);
+	free(handle, M_MPT2);
+	return (mps_update_events(sc, NULL, NULL));
+}
+
+/*
+ * Add a chain element as the next SGE for the specified command.
+ * Reset cm_sge and cm_sgesize to indicate all the available space.
+ */
+static int
+mps_add_chain(struct mps_command *cm)
+{
+	MPI2_SGE_CHAIN32 *sgc;
+	struct mps_chain *chain;
+	int space;
+
+	if (cm->cm_sglsize < MPS_SGC_SIZE)
+		panic("MPS: Need SGE Error Code\n");
+
+	chain = mps_alloc_chain(cm->cm_sc);
+	if (chain == NULL)
+		return (ENOBUFS);
+
+	space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4;
+
+	/*
+	 * Note: a double-linked list is used to make it easier to
+	 * walk for debugging.
+	 */
+	TAILQ_INSERT_TAIL(&cm->cm_chain_list, chain, chain_link);
+
+	sgc = (MPI2_SGE_CHAIN32 *)&cm->cm_sge->MpiChain;
+	sgc->Length = space;
+	sgc->NextChainOffset = 0;
+	sgc->Flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT;
+	sgc->Address = chain->chain_busaddr;
+
+	cm->cm_sge = (MPI2_SGE_IO_UNION *)&chain->chain->MpiSimple;
+	cm->cm_sglsize = space;
+	return (0);
+}
+
+/*
+ * Add one scatter-gather element (chain, simple, transaction context)
+ * to the scatter-gather list for a command.  Maintain cm_sglsize and
+ * cm_sge as the remaining size and pointer to the next SGE to fill
+ * in, respectively.
+ */
+int
+mps_push_sge(struct mps_command *cm, void *sgep, size_t len, int segsleft)
+{
+	MPI2_SGE_TRANSACTION_UNION *tc = sgep;
+	MPI2_SGE_SIMPLE64 *sge = sgep;
+	int error, type;
+
+	type = (tc->Flags & MPI2_SGE_FLAGS_ELEMENT_MASK);
+
+#ifdef INVARIANTS
+	switch (type) {
+	case MPI2_SGE_FLAGS_TRANSACTION_ELEMENT: {
+		if (len != tc->DetailsLength + 4)
+			panic("TC %p length %u or %zu?", tc,
+			    tc->DetailsLength + 4, len);
+		}
+		break;
+	case MPI2_SGE_FLAGS_CHAIN_ELEMENT:
+		/* Driver only uses 32-bit chain elements */
+		if (len != MPS_SGC_SIZE)
+			panic("CHAIN %p length %u or %zu?", sgep,
+			    MPS_SGC_SIZE, len);
+		break;
+	case MPI2_SGE_FLAGS_SIMPLE_ELEMENT:
+		/* Driver only uses 64-bit SGE simple elements */
+		sge = sgep;
+		if (len != MPS_SGE64_SIZE)
+			panic("SGE simple %p length %u or %zu?", sge,
+			    MPS_SGE64_SIZE, len);
+		if (((sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT) &
+		    MPI2_SGE_FLAGS_ADDRESS_SIZE) == 0)
+			panic("SGE simple %p flags %02x not marked 64-bit?",
+			    sge, sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT);
+
+		break;
+	default:
+		panic("Unexpected SGE %p, flags %02x", tc, tc->Flags);
+	}
+#endif
+
+	/*
+	 * case 1: 1 more segment, enough room for it
+	 * case 2: 2 more segments, enough room for both
+	 * case 3: >=2 more segments, only enough room for 1 and a chain
+	 * case 4: >=1 more segment, enough room for only a chain
+	 * case 5: >=1 more segment, no room for anything (error)
+         */
+
+	/*
+	 * There should be room for at least a chain element, or this
+	 * code is buggy.  Case (5).
+	 */
+	if (cm->cm_sglsize < MPS_SGC_SIZE)
+		panic("MPS: Need SGE Error Code\n");
+
+	if (segsleft >= 2 &&
+	    cm->cm_sglsize < len + MPS_SGC_SIZE + MPS_SGE64_SIZE) {
+		/*
+		 * There are 2 or more segments left to add, and only
+		 * enough room for 1 and a chain.  Case (3).
+		 *
+		 * Mark as last element in this chain if necessary.
+		 */
+		if (type == MPI2_SGE_FLAGS_SIMPLE_ELEMENT) {
+			sge->FlagsLength |=
+				(MPI2_SGE_FLAGS_LAST_ELEMENT << MPI2_SGE_FLAGS_SHIFT);
+		}
+
+		/*
+		 * Add the item then a chain.  Do the chain now,
+		 * rather than on the next iteration, to simplify
+		 * understanding the code.
+		 */
+		cm->cm_sglsize -= len;
+		bcopy(sgep, cm->cm_sge, len);
+		cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
+		return (mps_add_chain(cm));
+	}
+
+	if (segsleft >= 1 && cm->cm_sglsize < len + MPS_SGC_SIZE) {
+		/*
+		 * 1 or more segment, enough room for only a chain.
+		 * Hope the previous element wasn't a Simple entry
+		 * that needed to be marked with
+		 * MPI2_SGE_FLAGS_LAST_ELEMENT.  Case (4).
+		 */
+		if ((error = mps_add_chain(cm)) != 0)
+			return (error);
+	}
+
+#ifdef INVARIANTS
+	/* Case 1: 1 more segment, enough room for it. */
+	if (segsleft == 1 && cm->cm_sglsize < len)
+		panic("1 seg left and no room? %u versus %zu",
+		    cm->cm_sglsize, len);
+
+	/* Case 2: 2 more segments, enough room for both */
+	if (segsleft == 2 && cm->cm_sglsize < len + MPS_SGE64_SIZE)
+		panic("2 segs left and no room? %u versus %zu",
+		    cm->cm_sglsize, len);
+#endif
+
+	if (segsleft == 1 && type == MPI2_SGE_FLAGS_SIMPLE_ELEMENT) {
+		/*
+		 * Last element of the last segment of the entire
+		 * buffer.
+		 */
+		sge->FlagsLength |= ((MPI2_SGE_FLAGS_LAST_ELEMENT |
+		    MPI2_SGE_FLAGS_END_OF_BUFFER |
+		    MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
+	}
+
+	cm->cm_sglsize -= len;
+	bcopy(sgep, cm->cm_sge, len);
+	cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
+	return (0);
+}
+
+/*
+ * Add one dma segment to the scatter-gather list for a command.
+ */
+int
+mps_add_dmaseg(struct mps_command *cm, vm_paddr_t pa, size_t len, u_int flags,
+    int segsleft)
+{
+	MPI2_SGE_SIMPLE64 sge;
+
+	/*
+	 * This driver always uses 64-bit address elements for
+	 * simplicity.
+	 */
+	flags |= MPI2_SGE_FLAGS_SIMPLE_ELEMENT | MPI2_SGE_FLAGS_ADDRESS_SIZE;
+	sge.FlagsLength = len | (flags << MPI2_SGE_FLAGS_SHIFT);
+	mps_from_u64(pa, &sge.Address);
+
+	return (mps_push_sge(cm, &sge, sizeof sge, segsleft));
+}
+
+static void
+mps_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct mps_softc *sc;
+	struct mps_command *cm;
+	u_int i, dir, sflags;
+
+	cm = (struct mps_command *)arg;
+	sc = cm->cm_sc;
+
+	/*
+	 * In this case, just print out a warning and let the chip tell the
+	 * user they did the wrong thing.
+	 */
+	if ((cm->cm_max_segs != 0) && (nsegs > cm->cm_max_segs)) {
+		mps_printf(sc, "%s: warning: busdma returned %d segments, "
+			   "more than the %d allowed\n", __func__, nsegs,
+			   cm->cm_max_segs);
+	}
+
+	/*
+	 * Set up DMA direction flags.  Note that we don't support
+	 * bi-directional transfers, with the exception of SMP passthrough.
+	 */
+	sflags = 0;
+	if (cm->cm_flags & MPS_CM_FLAGS_SMP_PASS) {
+		/*
+		 * We have to add a special case for SMP passthrough, there
+		 * is no easy way to generically handle it.  The first
+		 * S/G element is used for the command (therefore the
+		 * direction bit needs to be set).  The second one is used
+		 * for the reply.  We'll leave it to the caller to make
+		 * sure we only have two buffers.
+		 */
+		/*
+		 * Even though the busdma man page says it doesn't make
+		 * sense to have both direction flags, it does in this case.
+		 * We have one s/g element being accessed in each direction.
+		 */
+		dir = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD;
+
+		/*
+		 * Set the direction flag on the first buffer in the SMP
+		 * passthrough request.  We'll clear it for the second one.
+		 */
+		sflags |= MPI2_SGE_FLAGS_DIRECTION |
+			  MPI2_SGE_FLAGS_END_OF_BUFFER;
+	} else if (cm->cm_flags & MPS_CM_FLAGS_DATAOUT) {
+		sflags |= MPI2_SGE_FLAGS_DIRECTION;
+		dir = BUS_DMASYNC_PREWRITE;
+	} else
+		dir = BUS_DMASYNC_PREREAD;
+
+	for (i = 0; i < nsegs; i++) {
+		if ((cm->cm_flags & MPS_CM_FLAGS_SMP_PASS)
+		 && (i != 0)) {
+			sflags &= ~MPI2_SGE_FLAGS_DIRECTION;
+		}
+		error = mps_add_dmaseg(cm, segs[i].ds_addr, segs[i].ds_len,
+		    sflags, nsegs - i);
+		if (error != 0) {
+			/* Resource shortage, roll back! */
+			mps_printf(sc, "out of chain frames\n");
+			return;
+		}
+	}
+
+	bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
+	mps_enqueue_request(sc, cm);
+
+	return;
+}
+
+static void
+mps_data_cb2(void *arg, bus_dma_segment_t *segs, int nsegs, bus_size_t mapsize,
+	     int error)
+{
+	mps_data_cb(arg, segs, nsegs, error);
+}
+
+/*
+ * Note that the only error path here is from bus_dmamap_load(), which can
+ * return EINPROGRESS if it is waiting for resources.
+ */
+int
+mps_map_command(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SGE_SIMPLE32 *sge;
+	int error = 0;
+
+	if (cm->cm_flags & MPS_CM_FLAGS_USE_UIO) {
+		error = bus_dmamap_load_uio(sc->buffer_dmat, cm->cm_dmamap,
+		    &cm->cm_uio, mps_data_cb2, cm, 0);
+	} else if ((cm->cm_data != NULL) && (cm->cm_length != 0)) {
+		error = bus_dmamap_load(sc->buffer_dmat, cm->cm_dmamap,
+		    cm->cm_data, cm->cm_length, mps_data_cb, cm, 0);
+	} else {
+		/* Add a zero-length element as needed */
+		if (cm->cm_sge != NULL) {
+			sge = (MPI2_SGE_SIMPLE32 *)cm->cm_sge;
+			sge->FlagsLength = (MPI2_SGE_FLAGS_LAST_ELEMENT |
+			    MPI2_SGE_FLAGS_END_OF_BUFFER |
+			    MPI2_SGE_FLAGS_END_OF_LIST |
+			    MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
+			    MPI2_SGE_FLAGS_SHIFT;
+			sge->Address = 0;
+		}
+		mps_enqueue_request(sc, cm);
+	}
+
+	return (error);
+}
+
+/*
+ * The MPT driver had a verbose interface for config pages.  In this driver,
+ * reduce it to much simplier terms, similar to the Linux driver.
+ */
+int
+mps_read_config_page(struct mps_softc *sc, struct mps_config_params *params)
+{
+	MPI2_CONFIG_REQUEST *req;
+	struct mps_command *cm;
+	int error;
+
+	if (sc->mps_flags & MPS_FLAGS_BUSY) {
+		return (EBUSY);
+	}
+
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		return (EBUSY);
+	}
+
+	req = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	req->Function = MPI2_FUNCTION_CONFIG;
+	req->Action = params->action;
+	req->SGLFlags = 0;
+	req->ChainOffset = 0;
+	req->PageAddress = params->page_address;
+	if (params->hdr.Ext.ExtPageType != 0) {
+		MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
+
+		hdr = &params->hdr.Ext;
+		req->ExtPageType = hdr->ExtPageType;
+		req->ExtPageLength = hdr->ExtPageLength;
+		req->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+		req->Header.PageLength = 0; /* Must be set to zero */
+		req->Header.PageNumber = hdr->PageNumber;
+		req->Header.PageVersion = hdr->PageVersion;
+	} else {
+		MPI2_CONFIG_PAGE_HEADER *hdr;
+
+		hdr = &params->hdr.Struct;
+		req->Header.PageType = hdr->PageType;
+		req->Header.PageNumber = hdr->PageNumber;
+		req->Header.PageLength = hdr->PageLength;
+		req->Header.PageVersion = hdr->PageVersion;
+	}
+
+	cm->cm_data = params->buffer;
+	cm->cm_length = params->length;
+	cm->cm_sge = &req->PageBufferSGE;
+	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
+	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+
+	cm->cm_complete_data = params;
+	if (params->callback != NULL) {
+		cm->cm_complete = mps_config_complete;
+		return (mps_map_command(sc, cm));
+	} else {
+		cm->cm_complete = NULL;
+		cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
+		if ((error = mps_map_command(sc, cm)) != 0)
+			return (error);
+		msleep(cm, &sc->mps_mtx, 0, "mpswait", 0);
+		mps_config_complete(sc, cm);
+	}
+
+	return (0);
+}
+
+int
+mps_write_config_page(struct mps_softc *sc, struct mps_config_params *params)
+{
+	return (EINVAL);
+}
+
+static void
+mps_config_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_config_params *params;
+
+	params = cm->cm_complete_data;
+
+	if (cm->cm_data != NULL) {
+		bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap,
+		    BUS_DMASYNC_POSTREAD);
+		bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
+	}
+
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	params->status = reply->IOCStatus;
+	if (params->hdr.Ext.ExtPageType != 0) {
+		params->hdr.Ext.ExtPageType = reply->ExtPageType;
+		params->hdr.Ext.ExtPageLength = reply->ExtPageLength;
+	} else {
+		params->hdr.Struct.PageType = reply->Header.PageType;
+		params->hdr.Struct.PageNumber = reply->Header.PageNumber;
+		params->hdr.Struct.PageLength = reply->Header.PageLength;
+		params->hdr.Struct.PageVersion = reply->Header.PageVersion;
+	}
+
+	mps_free_command(sc, cm);
+	if (params->callback != NULL)
+		params->callback(sc, params);
+
+	return;
+}
diff -x .svn -urN sys/dev/mps/mps_ioctl.h ../../stable/8/sys/dev/mps/mps_ioctl.h
--- sys/dev/mps/mps_ioctl.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps_ioctl.h	2011-01-07 14:33:43.864929596 -0700
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD userland interface
+ *
+ * $FreeBSD: stable/8/sys/dev/mps/mps_ioctl.h 212420 2010-09-10 15:03:56Z ken $
+ */
+
+#ifndef _MPS_IOCTL_H_
+#define	_MPS_IOCTL_H_
+
+#include <dev/mps/mpi/mpi2_type.h>
+#include <dev/mps/mpi/mpi2.h>
+#include <dev/mps/mpi/mpi2_cnfg.h>
+#include <dev/mps/mpi/mpi2_sas.h>
+
+/*
+ * For the read header requests, the header should include the page
+ * type or extended page type, page number, and page version.  The
+ * buffer and length are unused.  The completed header is returned in
+ * the 'header' member.
+ *
+ * For the read page and write page requests, 'buf' should point to a
+ * buffer of 'len' bytes which holds the entire page (including the
+ * header).
+ *
+ * All requests specify the page address in 'page_address'.
+ */
+struct mps_cfg_page_req {	
+	MPI2_CONFIG_PAGE_HEADER header;
+	uint32_t page_address;
+	void	*buf;
+	int	len;
+	uint16_t ioc_status;
+};
+
+struct mps_ext_cfg_page_req {
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
+	uint32_t page_address;
+	void	*buf;
+	int	len;
+	uint16_t ioc_status;
+};
+
+struct mps_raid_action {
+	uint8_t action;
+	uint8_t volume_bus;
+	uint8_t volume_id;
+	uint8_t phys_disk_num;
+	uint32_t action_data_word;
+	void *buf;
+	int len;
+	uint32_t volume_status;
+	uint32_t action_data[4];
+	uint16_t action_status;
+	uint16_t ioc_status;
+	uint8_t write;
+};
+
+struct mps_usr_command {
+	void *req;
+	uint32_t req_len;
+	void *rpl;
+	uint32_t rpl_len;
+	void *buf;
+	int len;
+	uint32_t flags;
+};
+
+#define MPSIO_MPS_COMMAND_FLAG_VERBOSE 0x01
+#define MPSIO_MPS_COMMAND_FLAG_DEBUG 0x02
+#define	MPSIO_READ_CFG_HEADER	_IOWR('M', 200, struct mps_cfg_page_req)
+#define	MPSIO_READ_CFG_PAGE	_IOWR('M', 201, struct mps_cfg_page_req)
+#define	MPSIO_READ_EXT_CFG_HEADER _IOWR('M', 202, struct mps_ext_cfg_page_req)
+#define	MPSIO_READ_EXT_CFG_PAGE	_IOWR('M', 203, struct mps_ext_cfg_page_req)
+#define	MPSIO_WRITE_CFG_PAGE	_IOWR('M', 204, struct mps_cfg_page_req)
+#define	MPSIO_RAID_ACTION	_IOWR('M', 205, struct mps_raid_action)
+#define	MPSIO_MPS_COMMAND	_IOWR('M', 210, struct mps_usr_command)
+
+#endif /* !_MPS_IOCTL_H_ */
diff -x .svn -urN sys/dev/mps/mps_pci.c ../../stable/8/sys/dev/mps/mps_pci.c
--- sys/dev/mps/mps_pci.c	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps_pci.c	2011-01-07 14:36:19.527671382 -0700
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2009 Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/8/sys/dev/mps/mps_pci.c 212420 2010-09-10 15:03:56Z ken $");
+
+/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/mps/mpi/mpi2_type.h>
+#include <dev/mps/mpi/mpi2.h>
+#include <dev/mps/mpi/mpi2_ioc.h>
+#include <dev/mps/mpi/mpi2_cnfg.h>
+
+#include <dev/mps/mpsvar.h>
+
+static int	mps_pci_probe(device_t);
+static int	mps_pci_attach(device_t);
+static int	mps_pci_detach(device_t);
+static int	mps_pci_suspend(device_t);
+static int	mps_pci_resume(device_t);
+static void	mps_pci_free(struct mps_softc *);
+static int	mps_alloc_msix(struct mps_softc *sc, int msgs);
+static int	mps_alloc_msi(struct mps_softc *sc, int msgs);
+
+int mps_disable_msix = 0;
+TUNABLE_INT("hw.mps.disable_msix", &mps_disable_msix);
+SYSCTL_INT(_hw_mps, OID_AUTO, disable_msix, CTLFLAG_RD, &mps_disable_msix, 0,
+    "Disable MSIX interrupts\n");
+int mps_disable_msi = 0;
+TUNABLE_INT("hw.mps.disable_msi", &mps_disable_msi);
+SYSCTL_INT(_hw_mps, OID_AUTO, disable_msi, CTLFLAG_RD, &mps_disable_msi, 0,
+    "Disable MSI interrupts\n");
+
+static device_method_t mps_methods[] = {
+	DEVMETHOD(device_probe,		mps_pci_probe),
+	DEVMETHOD(device_attach,	mps_pci_attach),
+	DEVMETHOD(device_detach,	mps_pci_detach),
+	DEVMETHOD(device_suspend,	mps_pci_suspend),
+	DEVMETHOD(device_resume,	mps_pci_resume),
+	DEVMETHOD(bus_print_child,	bus_generic_print_child),
+	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
+	{ 0, 0 }
+};
+
+static driver_t mps_pci_driver = {
+	"mps",
+	mps_methods,
+	sizeof(struct mps_softc)
+};
+
+static devclass_t	mps_devclass;
+DRIVER_MODULE(mps, pci, mps_pci_driver, mps_devclass, 0, 0);
+
+struct mps_ident {
+	uint16_t	vendor;
+	uint16_t	device;
+	uint16_t	subvendor;
+	uint16_t	subdevice;
+	u_int		flags;
+	const char	*desc;
+} mps_identifiers[] = {
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
+	    0xffff, 0xffff, 0, "LSI SAS2004" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
+	    0xffff, 0xffff, 0, "LSI SAS2008" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
+	    0xffff, 0xffff, 0, "LSI SAS2108" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
+	    0xffff, 0xffff, 0, "LSI SAS2108" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
+	    0xffff, 0xffff, 0, "LSI SAS2108" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
+	    0xffff, 0xffff, 0, "LSI SAS2116" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
+	    0xffff, 0xffff, 0, "LSI SAS2116" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_7,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_8,
+	    0xffff, 0xffff, 0, "LSI SAS2208" },
+	{ 0, 0, 0, 0, 0, NULL }
+};
+
+static struct mps_ident *
+mps_find_ident(device_t dev)
+{
+	struct mps_ident *m;
+
+	for (m = mps_identifiers; m->vendor != 0; m++) {
+		if (m->vendor != pci_get_vendor(dev))
+			continue;
+		if (m->device != pci_get_device(dev))
+			continue;
+		if ((m->subvendor != 0xffff) &&
+		    (m->subvendor != pci_get_subvendor(dev)))
+			continue;
+		if ((m->subdevice != 0xffff) &&
+		    (m->subdevice != pci_get_subdevice(dev)))
+			continue;
+		return (m);
+	}
+
+	return (NULL);
+}
+
+static int
+mps_pci_probe(device_t dev)
+{
+	struct mps_ident *id;
+
+	if ((id = mps_find_ident(dev)) != NULL) {
+		device_set_desc(dev, id->desc);
+		return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+static int
+mps_pci_attach(device_t dev)
+{
+	struct mps_softc *sc;
+	struct mps_ident *m;
+	uint16_t command;
+	int error;
+
+	sc = device_get_softc(dev);
+	bzero(sc, sizeof(*sc));
+	sc->mps_dev = dev;
+	m = mps_find_ident(dev);
+	sc->mps_flags = m->flags;
+
+	/* Twiddle basic PCI config bits for a sanity check */
+	command = pci_read_config(dev, PCIR_COMMAND, 2);
+	command |= PCIM_CMD_BUSMASTEREN;
+	pci_write_config(dev, PCIR_COMMAND, command, 2);
+	command = pci_read_config(dev, PCIR_COMMAND, 2);
+	if ((command & PCIM_CMD_BUSMASTEREN) == 0) {
+		device_printf(dev, "Cannot enable PCI busmaster\n");
+		return (ENXIO);
+	}
+	if ((command & PCIM_CMD_MEMEN) == 0) {
+		device_printf(dev, "PCI memory window not available\n");
+		return (ENXIO);
+	}
+
+	/* Allocate the System Interface Register Set */
+	sc->mps_regs_rid = PCIR_BAR(1);
+	if ((sc->mps_regs_resource = bus_alloc_resource_any(dev,
+	    SYS_RES_MEMORY, &sc->mps_regs_rid, RF_ACTIVE)) == NULL) {
+		device_printf(dev, "Cannot allocate PCI registers\n");
+		return (ENXIO);
+	}
+	sc->mps_btag = rman_get_bustag(sc->mps_regs_resource);
+	sc->mps_bhandle = rman_get_bushandle(sc->mps_regs_resource);
+
+	/* Allocate the parent DMA tag */
+	if (bus_dma_tag_create( NULL,			/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR,	/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
+				BUS_SPACE_UNRESTRICTED,	/* nsegments */
+				BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+				0,			/* flags */
+				NULL, NULL,		/* lockfunc, lockarg */
+				&sc->mps_parent_dmat)) {
+		device_printf(dev, "Cannot allocate parent DMA tag\n");
+		mps_pci_free(sc);
+		return (ENOMEM);
+	}
+
+	if ((error = mps_attach(sc)) != 0)
+		mps_pci_free(sc);
+
+	return (error);
+}
+
+int
+mps_pci_setup_interrupts(struct mps_softc *sc)
+{
+	device_t dev;
+	int i, error, msgs;
+
+	dev = sc->mps_dev;
+	error = ENXIO;
+	if ((mps_disable_msix == 0) &&
+	    ((msgs = pci_msix_count(dev)) >= MPS_MSI_COUNT))
+		error = mps_alloc_msix(sc, MPS_MSI_COUNT);
+	if ((error != 0) && (mps_disable_msi == 0) &&
+	    ((msgs = pci_msi_count(dev)) >= MPS_MSI_COUNT))
+		error = mps_alloc_msi(sc, MPS_MSI_COUNT);
+
+	if (error != 0) {
+		sc->mps_flags |= MPS_FLAGS_INTX;
+		sc->mps_irq_rid[0] = 0;
+		sc->mps_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+		    &sc->mps_irq_rid[0],  RF_SHAREABLE | RF_ACTIVE);
+		if (sc->mps_irq[0] == NULL) {
+			device_printf(dev, "Cannot allocate INTx interrupt\n");
+			return (ENXIO);
+		}
+		error = bus_setup_intr(dev, sc->mps_irq[0],
+		    INTR_TYPE_BIO | INTR_MPSAFE, NULL, mps_intr, sc,
+		    &sc->mps_intrhand[0]);
+		if (error)
+			device_printf(dev, "Cannot setup INTx interrupt\n");
+	} else {
+		sc->mps_flags |= MPS_FLAGS_MSI;
+		for (i = 0; i < MPS_MSI_COUNT; i++) {
+			sc->mps_irq_rid[i] = i + 1;
+			sc->mps_irq[i] = bus_alloc_resource_any(dev,
+			    SYS_RES_IRQ, &sc->mps_irq_rid[i], RF_ACTIVE);
+			if (sc->mps_irq[i] == NULL) {
+				device_printf(dev,
+				    "Cannot allocate MSI interrupt\n");
+				return (ENXIO);
+			}
+			error = bus_setup_intr(dev, sc->mps_irq[i],
+			    INTR_TYPE_BIO | INTR_MPSAFE, NULL, mps_intr_msi,
+			    sc, &sc->mps_intrhand[i]);
+			if (error) {
+				device_printf(dev,
+				    "Cannot setup MSI interrupt %d\n", i);
+				break;
+			}
+		}
+	}
+
+	return (error);
+}
+
+static int
+mps_pci_detach(device_t dev)
+{
+	struct mps_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+
+	if ((error = mps_free(sc)) != 0)
+		return (error);
+
+	mps_pci_free(sc);
+	return (0);
+}
+
+static void
+mps_pci_free(struct mps_softc *sc)
+{
+	int i;
+
+	if (sc->mps_parent_dmat != NULL) {
+		bus_dma_tag_destroy(sc->mps_parent_dmat);
+	}
+
+	if (sc->mps_flags & MPS_FLAGS_MSI) {
+		for (i = 0; i < MPS_MSI_COUNT; i++) {
+			if (sc->mps_irq[i] != NULL) {
+				bus_teardown_intr(sc->mps_dev, sc->mps_irq[i],
+				    sc->mps_intrhand[i]);
+				bus_release_resource(sc->mps_dev, SYS_RES_IRQ,
+				    sc->mps_irq_rid[i], sc->mps_irq[i]);
+			}
+		}
+		pci_release_msi(sc->mps_dev);
+	}
+
+	if (sc->mps_flags & MPS_FLAGS_INTX) {
+		bus_teardown_intr(sc->mps_dev, sc->mps_irq[0],
+		    sc->mps_intrhand[0]);
+		bus_release_resource(sc->mps_dev, SYS_RES_IRQ,
+		    sc->mps_irq_rid[0], sc->mps_irq[0]);
+	}
+
+	if (sc->mps_regs_resource != NULL) {
+		bus_release_resource(sc->mps_dev, SYS_RES_MEMORY,
+		    sc->mps_regs_rid, sc->mps_regs_resource);
+	}
+
+	return;
+}
+
+static int
+mps_pci_suspend(device_t dev)
+{
+	return (EINVAL);
+}
+
+static int
+mps_pci_resume(device_t dev)
+{
+	return (EINVAL);
+}
+
+static int
+mps_alloc_msix(struct mps_softc *sc, int msgs)
+{
+	int error;
+
+	error = pci_alloc_msix(sc->mps_dev, &msgs);
+	return (error);
+}
+
+static int
+mps_alloc_msi(struct mps_softc *sc, int msgs)
+{
+	int error;
+
+	error = pci_alloc_msi(sc->mps_dev, &msgs);
+	return (error);
+}
+
diff -x .svn -urN sys/dev/mps/mps_sas.c ../../stable/8/sys/dev/mps/mps_sas.c
--- sys/dev/mps/mps_sas.c	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps_sas.c	2011-01-07 14:38:00.422301954 -0700
@@ -0,0 +1,2007 @@
+/*-
+ * Copyright (c) 2009 Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/8/sys/dev/mps/mps_sas.c 212420 2010-09-10 15:03:56Z ken $");
+
+/* Communications core for LSI MPT2 */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/selinfo.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/sglist.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/cam_xpt_periph.h>
+#include <cam/cam_periph.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+#if __FreeBSD_version >= 900026
+#include <cam/scsi/smp_all.h>
+#endif
+
+#include <dev/mps/mpi/mpi2_type.h>
+#include <dev/mps/mpi/mpi2.h>
+#include <dev/mps/mpi/mpi2_ioc.h>
+#include <dev/mps/mpi/mpi2_sas.h>
+#include <dev/mps/mpi/mpi2_cnfg.h>
+#include <dev/mps/mpi/mpi2_init.h>
+#include <dev/mps/mpsvar.h>
+#include <dev/mps/mps_table.h>
+
+struct mpssas_target {
+	uint16_t	handle;
+	uint8_t		linkrate;
+	uint64_t	devname;
+	uint64_t	sasaddr;
+	uint32_t	devinfo;
+	uint16_t	encl_handle;
+	uint16_t	encl_slot;
+	uint16_t	parent_handle;
+	int		flags;
+#define MPSSAS_TARGET_INABORT	(1 << 0)
+#define MPSSAS_TARGET_INRESET	(1 << 1)
+#define MPSSAS_TARGET_INCHIPRESET (1 << 2)
+#define MPSSAS_TARGET_INRECOVERY 0x7
+	uint16_t	tid;
+};
+
+struct mpssas_softc {
+	struct mps_softc	*sc;
+	u_int			flags;
+#define MPSSAS_IN_DISCOVERY	(1 << 0)
+#define MPSSAS_IN_STARTUP	(1 << 1)
+#define MPSSAS_DISCOVERY_TIMEOUT_PENDING	(1 << 2)
+#define MPSSAS_QUEUE_FROZEN	(1 << 3)
+	struct mpssas_target	*targets;
+	struct cam_devq		*devq;
+	struct cam_sim		*sim;
+	struct cam_path		*path;
+	struct intr_config_hook	sas_ich;
+	struct callout		discovery_callout;
+	u_int			discovery_timeouts;
+	struct mps_event_handle	*mpssas_eh;
+};
+
+struct mpssas_devprobe {
+	struct mps_config_params	params;
+	u_int			state;
+#define MPSSAS_PROBE_DEV1	0x01
+#define MPSSAS_PROBE_DEV2	0x02
+#define MPSSAS_PROBE_PHY	0x03
+#define MPSSAS_PROBE_EXP	0x04
+#define MPSSAS_PROBE_PHY2	0x05
+#define MPSSAS_PROBE_EXP2	0x06
+	struct mpssas_target	target;
+};
+
+#define MPSSAS_DISCOVERY_TIMEOUT	20
+#define MPSSAS_MAX_DISCOVERY_TIMEOUTS	10 /* 200 seconds */
+
+MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory");
+
+static __inline int mpssas_set_lun(uint8_t *lun, u_int ccblun);
+static struct mpssas_target * mpssas_alloc_target(struct mpssas_softc *,
+    struct mpssas_target *);
+static struct mpssas_target * mpssas_find_target(struct mpssas_softc *, int,
+     uint16_t);
+static void mpssas_announce_device(struct mpssas_softc *,
+     struct mpssas_target *);
+static void mpssas_startup(void *data);
+static void mpssas_discovery_end(struct mpssas_softc *sassc);
+static void mpssas_discovery_timeout(void *data);
+static void mpssas_prepare_remove(struct mpssas_softc *,
+    MPI2_EVENT_SAS_TOPO_PHY_ENTRY *);
+static void mpssas_remove_device(struct mps_softc *, struct mps_command *);
+static void mpssas_remove_complete(struct mps_softc *, struct mps_command *);
+static void mpssas_action(struct cam_sim *sim, union ccb *ccb);
+static void mpssas_poll(struct cam_sim *sim);
+static void mpssas_probe_device(struct mps_softc *sc, uint16_t handle);
+static void mpssas_probe_device_complete(struct mps_softc *sc,
+     struct mps_config_params *params);
+static void mpssas_scsiio_timeout(void *data);
+static void mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm);
+static void mpssas_recovery(struct mps_softc *, struct mps_command *);
+static int mpssas_map_tm_request(struct mps_softc *sc, struct mps_command *cm);
+static void mpssas_issue_tm_request(struct mps_softc *sc,
+				    struct mps_command *cm);
+static void mpssas_tm_complete(struct mps_softc *sc, struct mps_command *cm,
+			       int error);
+static int mpssas_complete_tm_request(struct mps_softc *sc,
+				      struct mps_command *cm, int free_cm);
+static void mpssas_action_scsiio(struct mpssas_softc *, union ccb *);
+static void mpssas_scsiio_complete(struct mps_softc *, struct mps_command *);
+#if __FreeBSD_version >= 900026
+static void mpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm);
+static void mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb,
+			       uint64_t sasaddr);
+static void mpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb);
+#endif /* __FreeBSD_version >= 900026 */
+static void mpssas_resetdev(struct mpssas_softc *, struct mps_command *);
+static void mpssas_action_resetdev(struct mpssas_softc *, union ccb *);
+static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *);
+static void mpssas_freeze_device(struct mpssas_softc *, struct mpssas_target *);
+static void mpssas_unfreeze_device(struct mpssas_softc *, struct mpssas_target *) __unused;
+
+/*
+ * Abstracted so that the driver can be backwards and forwards compatible
+ * with future versions of CAM that will provide this functionality.
+ */
+#define MPS_SET_LUN(lun, ccblun)	\
+	mpssas_set_lun(lun, ccblun)
+
+static __inline int
+mpssas_set_lun(uint8_t *lun, u_int ccblun)
+{
+	uint64_t *newlun;
+
+	newlun = (uint64_t *)lun;
+	*newlun = 0;
+	if (ccblun <= 0xff) {
+		/* Peripheral device address method, LUN is 0 to 255 */
+		lun[1] = ccblun;
+	} else if (ccblun <= 0x3fff) {
+		/* Flat space address method, LUN is <= 16383 */
+		scsi_ulto2b(ccblun, lun);
+		lun[0] |= 0x40;
+	} else if (ccblun <= 0xffffff) {
+		/* Extended flat space address method, LUN is <= 16777215 */
+		scsi_ulto3b(ccblun, &lun[1]);
+		/* Extended Flat space address method */
+		lun[0] = 0xc0;
+		/* Length = 1, i.e. LUN is 3 bytes long */
+		lun[0] |= 0x10;
+		/* Extended Address Method */
+		lun[0] |= 0x02;
+	} else {
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+static struct mpssas_target *
+mpssas_alloc_target(struct mpssas_softc *sassc, struct mpssas_target *probe)
+{
+	struct mpssas_target *target;
+	int start;
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	/*
+	 * If it's not a sata or sas target, CAM won't be able to see it.  Put
+	 * it into a high-numbered slot so that it's accessible but not
+	 * interrupting the target numbering sequence of real drives.
+	 */
+	if ((probe->devinfo & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
+	    MPI2_SAS_DEVICE_INFO_STP_TARGET | MPI2_SAS_DEVICE_INFO_SATA_DEVICE))
+	    == 0) {
+		start = 200;
+	} else {
+		/*
+		 * Use the enclosure number and slot number as a hint for target
+		 * numbering.  If that doesn't produce a sane result, search the
+		 * entire space.
+		 */
+#if 0
+		start = probe->encl_handle * 16 + probe->encl_slot;
+#else
+		start = probe->encl_slot;
+#endif
+		if (start >= sassc->sc->facts->MaxTargets)
+			start = 0;
+	}
+
+	target = mpssas_find_target(sassc, start, 0);
+
+	/*
+	 * Nothing found on the first pass, try a second pass that searches the
+	 * entire space.
+	 */
+	if (target == NULL)
+		target = mpssas_find_target(sassc, 0, 0);
+
+	return (target);
+}
+
+static struct mpssas_target *
+mpssas_find_target(struct mpssas_softc *sassc, int start, uint16_t handle)
+{
+	struct mpssas_target *target;
+	int i;
+
+	for (i = start; i < sassc->sc->facts->MaxTargets; i++) {
+		target = &sassc->targets[i];
+		if (target->handle == handle)
+			return (target);
+	}
+
+	return (NULL);
+}
+
+/*
+ * Start the probe sequence for a given device handle.  This will not
+ * block.
+ */
+static void
+mpssas_probe_device(struct mps_softc *sc, uint16_t handle)
+{
+	struct mpssas_devprobe *probe;
+	struct mps_config_params *params;
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
+	int error;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	probe = malloc(sizeof(*probe), M_MPSSAS, M_NOWAIT | M_ZERO);
+	if (probe == NULL) {
+		mps_dprint(sc, MPS_FAULT, "Out of memory starting probe\n");
+		return;
+	}
+	params = &probe->params;
+	hdr = &params->hdr.Ext;
+
+	params->action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	params->page_address = MPI2_SAS_DEVICE_PGAD_FORM_HANDLE | handle;
+	hdr->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+	hdr->ExtPageLength = 0;
+	hdr->PageNumber = 0;
+	hdr->PageVersion = 0;
+	params->buffer = NULL;
+	params->length = 0;
+	params->callback = mpssas_probe_device_complete;
+	params->cbdata = probe;
+	probe->target.handle = handle;
+	probe->state = MPSSAS_PROBE_DEV1;
+
+	if ((error = mps_read_config_page(sc, params)) != 0) {
+		free(probe, M_MPSSAS);
+		mps_dprint(sc, MPS_FAULT, "Failure starting device probe\n");
+		return;
+	}
+}
+
+static void
+mpssas_probe_device_complete(struct mps_softc *sc,
+    struct mps_config_params *params)
+{
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
+	struct mpssas_devprobe *probe;
+	int error;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	hdr = &params->hdr.Ext;
+	probe = params->cbdata;
+
+	switch (probe->state) {
+	case MPSSAS_PROBE_DEV1:
+	case MPSSAS_PROBE_PHY:
+	case MPSSAS_PROBE_EXP:
+		if (params->status != MPI2_IOCSTATUS_SUCCESS) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Probe Failure 0x%x state %d\n", params->status,
+			    probe->state);
+			free(probe, M_MPSSAS);
+			return;
+		}
+		params->action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+		params->length = hdr->ExtPageLength * 4;
+		params->buffer = malloc(params->length, M_MPSSAS,
+		    M_ZERO|M_NOWAIT);
+		if (params->buffer == NULL) {
+			mps_dprint(sc, MPS_FAULT, "Out of memory at state "
+			   "0x%x, size 0x%x\n", probe->state, params->length);
+			free(probe, M_MPSSAS);
+			return;
+		}
+		if (probe->state == MPSSAS_PROBE_DEV1)
+			probe->state = MPSSAS_PROBE_DEV2;
+		else if (probe->state == MPSSAS_PROBE_PHY)
+			probe->state = MPSSAS_PROBE_PHY2;
+		else if (probe->state == MPSSAS_PROBE_EXP)
+			probe->state = MPSSAS_PROBE_EXP2;
+		error = mps_read_config_page(sc, params);
+		break;
+	case MPSSAS_PROBE_DEV2:
+	{
+		MPI2_CONFIG_PAGE_SAS_DEV_0 *buf;
+
+		if (params->status != MPI2_IOCSTATUS_SUCCESS) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Probe Failure 0x%x state %d\n", params->status,
+			    probe->state);
+			free(params->buffer, M_MPSSAS);
+			free(probe, M_MPSSAS);
+			return;
+		}
+		buf = params->buffer;
+		mps_print_sasdev0(sc, buf);
+
+		probe->target.devname = mps_to_u64(&buf->DeviceName);
+		probe->target.devinfo = buf->DeviceInfo;
+		probe->target.encl_handle = buf->EnclosureHandle;
+		probe->target.encl_slot = buf->Slot;
+		probe->target.sasaddr = mps_to_u64(&buf->SASAddress);
+		probe->target.parent_handle = buf->ParentDevHandle;
+
+		if (buf->DeviceInfo & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
+			params->page_address =
+			    MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | buf->PhyNum;
+			hdr->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
+			hdr->PageNumber = 0;
+			probe->state = MPSSAS_PROBE_PHY;
+		} else {
+			params->page_address =
+			    MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
+			    buf->ParentDevHandle | (buf->PhyNum << 16);
+			hdr->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+			hdr->PageNumber = 1;
+			probe->state = MPSSAS_PROBE_EXP;
+		}
+		params->action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+		hdr->ExtPageLength = 0;
+		hdr->PageVersion = 0;
+		params->buffer = NULL;
+		params->length = 0;
+		free(buf, M_MPSSAS);
+		error = mps_read_config_page(sc, params);
+		break;
+	}
+	case MPSSAS_PROBE_PHY2:
+	case MPSSAS_PROBE_EXP2:
+	{
+		MPI2_CONFIG_PAGE_SAS_PHY_0 *phy;
+		MPI2_CONFIG_PAGE_EXPANDER_1 *exp;
+		struct mpssas_softc *sassc;
+		struct mpssas_target *targ;
+		char devstring[80];
+		uint16_t handle;
+
+		if (params->status != MPI2_IOCSTATUS_SUCCESS) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Probe Failure 0x%x state %d\n", params->status,
+			    probe->state);
+			free(params->buffer, M_MPSSAS);
+			free(probe, M_MPSSAS);
+			return;
+		}
+
+		if (probe->state == MPSSAS_PROBE_PHY2) {
+			phy = params->buffer;
+			mps_print_sasphy0(sc, phy);
+			probe->target.linkrate = phy->NegotiatedLinkRate & 0xf;
+		} else {
+			exp = params->buffer;
+			mps_print_expander1(sc, exp);
+			probe->target.linkrate = exp->NegotiatedLinkRate & 0xf;
+		}
+		free(params->buffer, M_MPSSAS);
+
+		sassc = sc->sassc;
+		handle = probe->target.handle;
+		if ((targ = mpssas_find_target(sassc, 0, handle)) != NULL) {
+			mps_printf(sc, "Ignoring dup device handle 0x%04x\n",
+			    handle);
+			free(probe, M_MPSSAS);
+			return;
+		}
+		if ((targ = mpssas_alloc_target(sassc, &probe->target)) == NULL) {
+			mps_printf(sc, "Target table overflow, handle 0x%04x\n",
+			    handle);
+			free(probe, M_MPSSAS);
+			return;
+		}
+
+		*targ = probe->target;	/* Copy the attributes */
+		targ->tid = targ - sassc->targets;
+		mps_describe_devinfo(targ->devinfo, devstring, 80);
+		if (bootverbose)
+			mps_printf(sc, "Found device <%s> <%s> <0x%04x> "
+			    "<%d/%d>\n", devstring,
+			    mps_describe_table(mps_linkrate_names,
+			    targ->linkrate), targ->handle, targ->encl_handle,
+			    targ->encl_slot);
+
+		free(probe, M_MPSSAS);
+		mpssas_announce_device(sassc, targ);
+		break;
+	}
+	default:
+		printf("what?\n");
+	}
+}
+
+/*
+ * The MPT2 firmware performs debounce on the link to avoid transient link errors
+ * and false removals.  When it does decide that link has been lost and a device
+ * need to go away, it expects that the host will perform a target reset and then
+ * an op remove.  The reset has the side-effect of aborting any outstanding
+ * requests for the device, which is required for the op-remove to succeed.  It's
+ * not clear if the host should check for the device coming back alive after the
+ * reset.
+ */
+static void
+mpssas_prepare_remove(struct mpssas_softc *sassc, MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mps_softc *sc;
+	struct mps_command *cm;
+	struct mpssas_target *targ = NULL;
+	uint16_t handle;
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	handle = phy->AttachedDevHandle;
+	targ = mpssas_find_target(sassc, 0, handle);
+	if (targ == NULL)
+		/* We don't know about this device? */
+		return;
+
+	sc = sassc->sc;
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "comand alloc failure in mpssas_prepare_remove\n");
+		return;
+	}
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+	req->DevHandle = targ->handle;
+	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+
+	/* SAS Hard Link Reset / SATA Link Reset */
+	req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+
+	cm->cm_data = NULL;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_complete = mpssas_remove_device;
+	cm->cm_targ = targ;
+	mpssas_issue_tm_request(sc, cm);
+}
+
+static void
+mpssas_remove_device(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
+	MPI2_SAS_IOUNIT_CONTROL_REQUEST *req;
+	struct mpssas_target *targ;
+	uint16_t handle;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)cm->cm_reply;
+	handle = cm->cm_targ->handle;
+
+	mpssas_complete_tm_request(sc, cm, /*free_cm*/ 0);
+
+	if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
+		mps_printf(sc, "Failure 0x%x reseting device 0x%04x\n", 
+		   reply->IOCStatus, handle);
+		mps_free_command(sc, cm);
+		return;
+	}
+
+	mps_printf(sc, "Reset aborted %d commands\n", reply->TerminationCount);
+	mps_free_reply(sc, cm->cm_reply_data);
+
+	/* Reuse the existing command */
+	req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)cm->cm_req;
+	req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+	req->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
+	req->DevHandle = handle;
+	cm->cm_data = NULL;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_flags &= ~MPS_CM_FLAGS_COMPLETE;
+	cm->cm_complete = mpssas_remove_complete;
+
+	mps_map_command(sc, cm);
+
+	mps_dprint(sc, MPS_INFO, "clearing target handle 0x%04x\n", handle);
+	targ = mpssas_find_target(sc->sassc, 0, handle);
+	if (targ != NULL) {
+		targ->handle = 0x0;
+		mpssas_announce_device(sc->sassc, targ);
+	}
+}
+
+static void
+mpssas_remove_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SAS_IOUNIT_CONTROL_REPLY *reply;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)cm->cm_reply;
+
+	mps_printf(sc, "mpssas_remove_complete on target 0x%04x,"
+	   " IOCStatus= 0x%x\n", cm->cm_targ->tid, reply->IOCStatus);
+
+	mps_free_command(sc, cm);
+}
+
+static void
+mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
+    MPI2_EVENT_NOTIFICATION_REPLY *event)
+{
+	struct mpssas_softc *sassc;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	sassc = sc->sassc;
+	mps_print_evt_sas(sc, event);
+
+	switch (event->Event) {
+	case MPI2_EVENT_SAS_DISCOVERY:
+	{
+		MPI2_EVENT_DATA_SAS_DISCOVERY *data;
+
+		data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)&event->EventData;
+
+		if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED)
+			mps_dprint(sc, MPS_TRACE,"SAS discovery start event\n");
+		if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) {
+			mps_dprint(sc, MPS_TRACE, "SAS discovery end event\n");
+			sassc->flags &= ~MPSSAS_IN_DISCOVERY;
+			mpssas_discovery_end(sassc);
+		}
+		break;
+	}
+	case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+	{
+		MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
+		MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
+		int i;
+
+		data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
+		    &event->EventData;
+
+		if (data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) {
+			if (bootverbose)
+				printf("Expander found at enclosure %d\n",
+				    data->EnclosureHandle);
+			mpssas_probe_device(sc, data->ExpanderDevHandle);
+		}
+
+		for (i = 0; i < data->NumEntries; i++) {
+			phy = &data->PHY[i];
+			switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
+			case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
+				mpssas_probe_device(sc, phy->AttachedDevHandle);
+				break;
+			case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
+				mpssas_prepare_remove(sassc, phy);
+				break;
+			case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
+			case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
+			case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
+			default:
+				break;
+			}
+		}
+
+		break;
+	}
+	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+		break;
+	default:
+		break;
+	}
+
+	mps_free_reply(sc, data);
+}
+
+static int
+mpssas_register_events(struct mps_softc *sc)
+{
+	uint8_t events[16];
+
+	bzero(events, 16);
+	setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
+	setbit(events, MPI2_EVENT_SAS_DISCOVERY);
+	setbit(events, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
+	setbit(events, MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE);
+	setbit(events, MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW);
+	setbit(events, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
+	setbit(events, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
+
+	mps_register_events(sc, events, mpssas_evt_handler, NULL,
+	    &sc->sassc->mpssas_eh);
+
+	return (0);
+}
+
+int
+mps_attach_sas(struct mps_softc *sc)
+{
+	struct mpssas_softc *sassc;
+	int error = 0;
+	int num_sim_reqs;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	sassc = malloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO);
+	sassc->targets = malloc(sizeof(struct mpssas_target) *
+	    sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO);
+	sc->sassc = sassc;
+	sassc->sc = sc;
+
+	/*
+	 * Tell CAM that we can handle 5 fewer requests than we have
+	 * allocated.  If we allow the full number of requests, all I/O
+	 * will halt when we run out of resources.  Things work fine with
+	 * just 1 less request slot given to CAM than we have allocated.
+	 * We also need a couple of extra commands so that we can send down
+	 * abort, reset, etc. requests when commands time out.  Otherwise
+	 * we could wind up in a situation with sc->num_reqs requests down
+	 * on the card and no way to send an abort.
+	 *
+	 * XXX KDM need to figure out why I/O locks up if all commands are
+	 * used.
+	 */
+	num_sim_reqs = sc->num_reqs - 5;
+
+	if ((sassc->devq = cam_simq_alloc(num_sim_reqs)) == NULL) {
+		mps_dprint(sc, MPS_FAULT, "Cannot allocate SIMQ\n");
+		error = ENOMEM;
+		goto out;
+	}
+
+	sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mps", sassc,
+	    device_get_unit(sc->mps_dev), &sc->mps_mtx, num_sim_reqs,
+	    num_sim_reqs, sassc->devq);
+	if (sassc->sim == NULL) {
+		mps_dprint(sc, MPS_FAULT, "Cannot allocate SIM\n");
+		error = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * XXX There should be a bus for every port on the adapter, but since
+	 * we're just going to fake the topology for now, we'll pretend that
+	 * everything is just a target on a single bus.
+	 */
+	mps_lock(sc);
+	if ((error = xpt_bus_register(sassc->sim, sc->mps_dev, 0)) != 0) {
+		mps_dprint(sc, MPS_FAULT, "Error %d registering SCSI bus\n",
+		    error);
+		mps_unlock(sc);
+		goto out;
+	}
+
+	/*
+	 * Assume that discovery events will start right away.  Freezing
+	 * the simq will prevent the CAM boottime scanner from running
+	 * before discovery is complete.
+	 */
+	sassc->flags = MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY;
+	xpt_freeze_simq(sassc->sim, 1);
+
+	mps_unlock(sc);
+
+	callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
+	sassc->discovery_timeouts = 0;
+
+	mpssas_register_events(sc);
+out:
+	if (error)
+		mps_detach_sas(sc);
+	return (error);
+}
+
+int
+mps_detach_sas(struct mps_softc *sc)
+{
+	struct mpssas_softc *sassc;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if (sc->sassc == NULL)
+		return (0);
+
+	sassc = sc->sassc;
+
+	/* Make sure CAM doesn't wedge if we had to bail out early. */
+	mps_lock(sc);
+	if (sassc->flags & MPSSAS_IN_STARTUP)
+		xpt_release_simq(sassc->sim, 1);
+	mps_unlock(sc);
+
+	if (sassc->mpssas_eh != NULL)
+		mps_deregister_events(sc, sassc->mpssas_eh);
+
+	mps_lock(sc);
+
+	if (sassc->sim != NULL) {
+		xpt_bus_deregister(cam_sim_path(sassc->sim));
+		cam_sim_free(sassc->sim, FALSE);
+	}
+	mps_unlock(sc);
+
+	if (sassc->devq != NULL)
+		cam_simq_free(sassc->devq);
+
+	free(sassc->targets, M_MPT2);
+	free(sassc, M_MPT2);
+	sc->sassc = NULL;
+
+	return (0);
+}
+
+static void
+mpssas_discovery_end(struct mpssas_softc *sassc)
+{
+	struct mps_softc *sc = sassc->sc;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if (sassc->flags & MPSSAS_DISCOVERY_TIMEOUT_PENDING)
+		callout_stop(&sassc->discovery_callout);
+
+	if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) {
+		mps_dprint(sc, MPS_INFO,
+		    "mpssas_discovery_end: removing confighook\n");
+		sassc->flags &= ~MPSSAS_IN_STARTUP;
+		xpt_release_simq(sassc->sim, 1);
+	}
+#if 0
+	mpssas_announce_device(sassc, NULL);
+#endif
+
+}
+
+static void
+mpssas_announce_device(struct mpssas_softc *sassc, struct mpssas_target *targ)
+{
+	union ccb *ccb;
+	int bus, tid, lun;
+
+	/*
+	 * Force a rescan, a hackish way to announce devices.
+	 * XXX Doing a scan on an individual device is hackish in that it
+	 *     won't scan the LUNs.
+	 * XXX Does it matter if any of this fails?
+	 */
+	bus = cam_sim_path(sassc->sim);
+	if (targ != NULL) {
+		tid = targ->tid;
+		lun = 0;
+	} else {
+		tid = CAM_TARGET_WILDCARD;
+		lun = CAM_LUN_WILDCARD;
+	}
+	ccb = xpt_alloc_ccb_nowait();
+	if (ccb == NULL)
+		return;
+	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, bus, tid,
+	    CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 
+		xpt_free_ccb(ccb);
+		return;
+	}
+	mps_dprint(sassc->sc, MPS_INFO, "Triggering rescan of %d:%d:-1\n",
+	    bus, tid);
+	xpt_rescan(ccb);
+}
+
+static void
+mpssas_startup(void *data)
+{
+	struct mpssas_softc *sassc = data;
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	mps_lock(sassc->sc);
+	if ((sassc->flags & MPSSAS_IN_DISCOVERY) == 0) {
+		mpssas_discovery_end(sassc);
+	} else {
+		if (sassc->discovery_timeouts < MPSSAS_MAX_DISCOVERY_TIMEOUTS) {
+			sassc->flags |= MPSSAS_DISCOVERY_TIMEOUT_PENDING;
+			callout_reset(&sassc->discovery_callout,
+			    MPSSAS_DISCOVERY_TIMEOUT * hz,
+			    mpssas_discovery_timeout, sassc);
+			sassc->discovery_timeouts++;
+		} else {
+			mps_dprint(sassc->sc, MPS_FAULT,
+			    "Discovery timed out, continuing.\n");
+			sassc->flags &= ~MPSSAS_IN_DISCOVERY;
+			mpssas_discovery_end(sassc);
+		}
+	}
+	mps_unlock(sassc->sc);
+
+	return;
+}
+
+static void
+mpssas_discovery_timeout(void *data)
+{
+	struct mpssas_softc *sassc = data;
+	struct mps_softc *sc;
+
+	sc = sassc->sc;
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	mps_lock(sc);
+	mps_printf(sc,
+	    "Timeout waiting for discovery, interrupts may not be working!\n");
+	sassc->flags &= ~MPSSAS_DISCOVERY_TIMEOUT_PENDING;
+
+	/* Poll the hardware for events in case interrupts aren't working */
+	mps_intr_locked(sc);
+	mps_unlock(sc);
+
+	/* Check the status of discovery and re-arm the timeout if needed */
+	mpssas_startup(sassc);
+}
+
+static void
+mpssas_action(struct cam_sim *sim, union ccb *ccb)
+{
+	struct mpssas_softc *sassc;
+
+	sassc = cam_sim_softc(sim);
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s func 0x%x\n", __func__,
+	    ccb->ccb_h.func_code);
+
+	switch (ccb->ccb_h.func_code) {
+	case XPT_PATH_INQ:
+	{
+		struct ccb_pathinq *cpi = &ccb->cpi;
+
+		cpi->version_num = 1;
+		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
+		cpi->target_sprt = 0;
+		cpi->hba_misc = PIM_NOBUSRESET;
+		cpi->hba_eng_cnt = 0;
+		cpi->max_target = sassc->sc->facts->MaxTargets - 1;
+		cpi->max_lun = 0;
+		cpi->initiator_id = 255;
+		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+		strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN);
+		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+		cpi->unit_number = cam_sim_unit(sim);
+		cpi->bus_id = cam_sim_bus(sim);
+		cpi->base_transfer_speed = 150000;
+		cpi->transport = XPORT_SAS;
+		cpi->transport_version = 0;
+		cpi->protocol = PROTO_SCSI;
+		cpi->protocol_version = SCSI_REV_SPC;
+		cpi->ccb_h.status = CAM_REQ_CMP;
+		break;
+	}
+	case XPT_GET_TRAN_SETTINGS:
+	{
+		struct ccb_trans_settings	*cts;
+		struct ccb_trans_settings_sas	*sas;
+		struct ccb_trans_settings_scsi	*scsi;
+		struct mpssas_target *targ;
+
+		cts = &ccb->cts;
+		sas = &cts->xport_specific.sas;
+		scsi = &cts->proto_specific.scsi;
+
+		targ = &sassc->targets[cts->ccb_h.target_id];
+		if (targ->handle == 0x0) {
+			cts->ccb_h.status = CAM_TID_INVALID;
+			break;
+		}
+
+		cts->protocol_version = SCSI_REV_SPC2;
+		cts->transport = XPORT_SAS;
+		cts->transport_version = 0;
+
+		sas->valid = CTS_SAS_VALID_SPEED;
+		switch (targ->linkrate) {
+		case 0x08:
+			sas->bitrate = 150000;
+			break;
+		case 0x09:
+			sas->bitrate = 300000;
+			break;
+		case 0x0a:
+			sas->bitrate = 600000;
+			break;
+		default:
+			sas->valid = 0;
+		}
+
+		cts->protocol = PROTO_SCSI;
+		scsi->valid = CTS_SCSI_VALID_TQ;
+		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
+
+		cts->ccb_h.status = CAM_REQ_CMP;
+		break;
+	}
+	case XPT_CALC_GEOMETRY:
+		cam_calc_geometry(&ccb->ccg, /*extended*/1);
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	case XPT_RESET_DEV:
+		mpssas_action_resetdev(sassc, ccb);
+		return;
+	case XPT_RESET_BUS:
+	case XPT_ABORT:
+	case XPT_TERM_IO:
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	case XPT_SCSI_IO:
+		mpssas_action_scsiio(sassc, ccb);
+		return;
+#if __FreeBSD_version >= 900026
+	case XPT_SMP_IO:
+		mpssas_action_smpio(sassc, ccb);
+		return;
+#endif /* __FreeBSD_version >= 900026 */
+	default:
+		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+		break;
+	}
+	xpt_done(ccb);
+
+}
+
+#if 0
+static void
+mpssas_resettimeout_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *resp;
+	uint16_t code;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)cm->cm_reply;
+	code = resp->ResponseCode;
+
+	mps_free_command(sc, cm);
+	mpssas_unfreeze_device(sassc, targ);
+
+	if (code != MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) {
+		mps_reset_controller(sc);
+	}
+
+	return;
+}
+#endif
+
+static void
+mpssas_scsiio_timeout(void *data)
+{
+	union ccb *ccb;
+	struct mps_softc *sc;
+	struct mps_command *cm;
+	struct mpssas_target *targ;
+#if 0
+	char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
+#endif
+
+	cm = (struct mps_command *)data;
+	sc = cm->cm_sc;
+
+	/*
+	 * Run the interrupt handler to make sure it's not pending.  This
+	 * isn't perfect because the command could have already completed
+	 * and been re-used, though this is unlikely.
+	 */
+	mps_lock(sc);
+	mps_intr_locked(sc);
+	if (cm->cm_state == MPS_CM_STATE_FREE) {
+		mps_unlock(sc);
+		return;
+	}
+
+	ccb = cm->cm_complete_data;
+	targ = cm->cm_targ;
+	if (targ == 0x00)
+		/* Driver bug */
+		targ = &sc->sassc->targets[ccb->ccb_h.target_id];
+
+	xpt_print(ccb->ccb_h.path, "SCSI command timeout on device handle "
+		  "0x%04x SMID %d\n", targ->handle, cm->cm_desc.Default.SMID);
+	/*
+	 * XXX KDM this is useful for debugging purposes, but the existing
+	 * scsi_op_desc() implementation can't handle a NULL value for
+	 * inq_data.  So this will remain commented out until I bring in
+	 * those changes as well.
+	 */
+#if 0
+	xpt_print(ccb->ccb_h.path, "Timed out command: %s. CDB %s\n",
+		  scsi_op_desc((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+		  		ccb->csio.cdb_io.cdb_ptr[0] :
+				ccb->csio.cdb_io.cdb_bytes[0], NULL),
+		  scsi_cdb_string((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+				   ccb->csio.cdb_io.cdb_ptr :
+				   ccb->csio.cdb_io.cdb_bytes, cdb_str,
+		  		   sizeof(cdb_str)));
+#endif
+
+	/* Inform CAM about the timeout and that recovery is starting. */
+#if 0
+	if ((targ->flags & MPSSAS_TARGET_INRECOVERY) == 0) {
+		mpssas_freeze_device(sc->sassc, targ);
+		ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+		xpt_done(ccb);
+	}
+#endif
+	mpssas_freeze_device(sc->sassc, targ);
+	ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+
+	/*
+	 * recycle the command into recovery so that there's no risk of
+	 * command allocation failure.
+	 */
+	cm->cm_state = MPS_CM_STATE_TIMEDOUT;
+	mpssas_recovery(sc, cm);
+	mps_unlock(sc);
+}
+
+static void
+mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+
+	mps_printf(sc, "%s: abort request on handle %#04x SMID %d "
+		   "complete\n", __func__, req->DevHandle, req->TaskMID);
+
+	mpssas_complete_tm_request(sc, cm, /*free_cm*/ 1);
+}
+
+static void
+mpssas_recovery(struct mps_softc *sc, struct mps_command *abort_cm)
+{
+	struct mps_command *cm;
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req, *orig_req;
+
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "%s: command allocation failure\n", __func__);
+		return;
+	}
+
+	cm->cm_targ = abort_cm->cm_targ;
+	cm->cm_complete = mpssas_abort_complete;
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+	orig_req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)abort_cm->cm_req;
+	req->DevHandle = abort_cm->cm_targ->handle;
+	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+	memcpy(req->LUN, orig_req->LUN, sizeof(req->LUN));
+	req->TaskMID = abort_cm->cm_desc.Default.SMID;
+
+	cm->cm_data = NULL;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+
+	mpssas_issue_tm_request(sc, cm);
+
+}
+
+/*
+ * Can return 0 or EINPROGRESS on success.  Any other value means failure.
+ */
+static int
+mpssas_map_tm_request(struct mps_softc *sc, struct mps_command *cm)
+{
+	int error;
+
+	error = 0;
+
+	cm->cm_flags |= MPS_CM_FLAGS_ACTIVE;
+	error = mps_map_command(sc, cm);
+	if ((error == 0)
+	 || (error == EINPROGRESS))
+		sc->tm_cmds_active++;
+
+	return (error);
+}
+
+static void
+mpssas_issue_tm_request(struct mps_softc *sc, struct mps_command *cm)
+{
+	int freeze_queue, send_command, error;
+
+	freeze_queue = 0;
+	send_command = 0;
+	error = 0;
+
+	mtx_assert(&sc->mps_mtx, MA_OWNED);
+
+	/*
+	 * If there are no other pending task management commands, go
+	 * ahead and send this one.  There is a small amount of anecdotal
+	 * evidence that sending lots of task management commands at once
+	 * may cause the controller to lock up.  Or, if the user has
+	 * configured the driver (via the allow_multiple_tm_cmds variable) to
+	 * not serialize task management commands, go ahead and send the
+	 * command if even other task management commands are pending.
+	 */
+	if (TAILQ_FIRST(&sc->tm_list) == NULL) {
+		send_command = 1;
+		freeze_queue = 1;
+	} else if (sc->allow_multiple_tm_cmds != 0)
+		send_command = 1;
+
+	TAILQ_INSERT_TAIL(&sc->tm_list, cm, cm_link);
+	if (send_command != 0) {
+		/*
+		 * Freeze the SIM queue while we issue the task management
+		 * command.  According to the Fusion-MPT 2.0 spec, task
+		 * management requests are serialized, and so the host
+		 * should not send any I/O requests while task management
+		 * requests are pending.
+		 */
+		if (freeze_queue != 0)
+			xpt_freeze_simq(sc->sassc->sim, 1);
+
+		error = mpssas_map_tm_request(sc, cm);
+
+		/*
+		 * At present, there is no error path back from
+		 * mpssas_map_tm_request() (which calls mps_map_command())
+		 * when cm->cm_data == NULL.  But since there is a return
+		 * value, we check it just in case the implementation
+		 * changes later.
+		 */
+		if ((error != 0)
+		 && (error != EINPROGRESS))
+			mpssas_tm_complete(sc, cm,
+			    MPI2_SCSITASKMGMT_RSP_TM_FAILED);
+	}
+}
+
+static void
+mpssas_tm_complete(struct mps_softc *sc, struct mps_command *cm, int error)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *resp;
+
+	resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)cm->cm_reply;
+
+	resp->ResponseCode = error;
+
+	/*
+	 * Call the callback for this command, it will be
+	 * removed from the list and freed via the callback.
+	 */
+	cm->cm_complete(sc, cm);
+}
+
+/*
+ * Complete a task management request.  The basic completion operation will
+ * always succeed.  Returns status for sending any further task management
+ * commands that were queued.
+ */
+static int
+mpssas_complete_tm_request(struct mps_softc *sc, struct mps_command *cm,
+			   int free_cm)
+{
+	int error;
+
+	error = 0;
+
+	mtx_assert(&sc->mps_mtx, MA_OWNED);
+
+	TAILQ_REMOVE(&sc->tm_list, cm, cm_link);
+	cm->cm_flags &= ~MPS_CM_FLAGS_ACTIVE;
+	sc->tm_cmds_active--;
+
+	if (free_cm != 0)
+		mps_free_command(sc, cm);
+
+	if (TAILQ_FIRST(&sc->tm_list) == NULL) {
+		/*
+		 * Release the SIM queue, we froze it when we sent the first
+		 * task management request.
+		 */
+		xpt_release_simq(sc->sassc->sim, 1);
+	} else if ((sc->tm_cmds_active == 0)
+		|| (sc->allow_multiple_tm_cmds != 0)) {
+		int error;
+		struct mps_command *cm2;
+
+restart_traversal:
+
+		/*
+		 * We don't bother using TAILQ_FOREACH_SAFE here, but
+		 * rather use the standard version and just restart the
+		 * list traversal if we run into the error case.
+		 * TAILQ_FOREACH_SAFE allows safe removal of the current
+		 * list element, but if you have a queue of task management
+		 * commands, all of which have mapping errors, you'll end
+		 * up with recursive calls to this routine and so you could
+		 * wind up removing more than just the current list element.
+		 */
+		TAILQ_FOREACH(cm2, &sc->tm_list, cm_link) {
+			MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+
+			/* This command is active, no need to send it again */
+			if (cm2->cm_flags & MPS_CM_FLAGS_ACTIVE)
+				continue;
+
+			req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm2->cm_req;
+
+			mps_printf(sc, "%s: sending deferred task management "
+			    "request for handle %#04x SMID %d\n", __func__,
+			    req->DevHandle, req->TaskMID);
+
+			error = mpssas_map_tm_request(sc, cm2);
+
+			/*
+			 * Check for errors.  If we had an error, complete
+			 * this command with an error, and keep going through
+			 * the list until we are able to send at least one
+			 * command or all of them are completed with errors.
+			 *
+			 * We don't want to wind up in a situation where
+			 * we're stalled out with no way for queued task
+			 * management commands to complete.
+			 *
+			 * Note that there is not currently an error path
+			 * back from mpssas_map_tm_request() (which calls
+			 * mps_map_command()) when cm->cm_data == NULL.
+			 * But we still want to check for errors here in
+			 * case the implementation changes, or in case
+			 * there is some reason for a data payload here.
+			 */
+			if ((error != 0)
+			 && (error != EINPROGRESS)) {
+				mpssas_tm_complete(sc, cm,
+				    MPI2_SCSITASKMGMT_RSP_TM_FAILED);
+
+				/*
+				 * If we don't currently have any commands
+				 * active, go back to the beginning and see
+				 * if there are any more that can be started.
+				 * Otherwise, we're done here.
+				 */
+				if (sc->tm_cmds_active == 0)
+					goto restart_traversal;
+				else
+					break;
+			}
+
+			/*
+			 * If the user only wants one task management command
+			 * active at a time, we're done, since we've
+			 * already successfully sent a command at this point.
+			 */
+			if (sc->allow_multiple_tm_cmds == 0)
+				break;
+		}
+	}
+
+	return (error);
+}
+
+static void
+mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
+{
+	MPI2_SCSI_IO_REQUEST *req;
+	struct ccb_scsiio *csio;
+	struct mps_softc *sc;
+	struct mpssas_target *targ;
+	struct mps_command *cm;
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	sc = sassc->sc;
+
+	csio = &ccb->csio;
+	targ = &sassc->targets[csio->ccb_h.target_id];
+	if (targ->handle == 0x0) {
+		csio->ccb_h.status = CAM_SEL_TIMEOUT;
+		xpt_done(ccb);
+		return;
+	}
+
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) {
+			xpt_freeze_simq(sassc->sim, 1);
+			sassc->flags |= MPSSAS_QUEUE_FROZEN;
+		}
+		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+		xpt_done(ccb);
+		return;
+	}
+
+	req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req;
+	req->DevHandle = targ->handle;
+	req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+	req->MsgFlags = 0;
+	req->SenseBufferLowAddress = cm->cm_sense_busaddr;
+	req->SenseBufferLength = MPS_SENSE_LEN;
+	req->SGLFlags = 0;
+	req->ChainOffset = 0;
+	req->SGLOffset0 = 24;	/* 32bit word offset to the SGL */
+	req->SGLOffset1= 0;
+	req->SGLOffset2= 0;
+	req->SGLOffset3= 0;
+	req->SkipCount = 0;
+	req->DataLength = csio->dxfer_len;
+	req->BidirectionalDataLength = 0;
+	req->IoFlags = csio->cdb_len;
+	req->EEDPFlags = 0;
+
+	/* Note: BiDirectional transfers are not supported */
+	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
+	case CAM_DIR_IN:
+		req->Control = MPI2_SCSIIO_CONTROL_READ;
+		cm->cm_flags |= MPS_CM_FLAGS_DATAIN;
+		break;
+	case CAM_DIR_OUT:
+		req->Control = MPI2_SCSIIO_CONTROL_WRITE;
+		cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
+		break;
+	case CAM_DIR_NONE:
+	default:
+		req->Control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
+		break;
+	}
+
+	/*
+	 * It looks like the hardware doesn't require an explicit tag
+	 * number for each transaction.  SAM Task Management not supported
+	 * at the moment.
+	 */
+	switch (csio->tag_action) {
+	case MSG_HEAD_OF_Q_TAG:
+		req->Control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
+		break;
+	case MSG_ORDERED_Q_TAG:
+		req->Control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
+		break;
+	case MSG_ACA_TASK:
+		req->Control |= MPI2_SCSIIO_CONTROL_ACAQ;
+		break;
+	case CAM_TAG_ACTION_NONE:
+	case MSG_SIMPLE_Q_TAG:
+	default:
+		req->Control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+		break;
+	}
+
+	if (MPS_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) {
+		mps_free_command(sc, cm);
+		ccb->ccb_h.status = CAM_LUN_INVALID;
+		xpt_done(ccb);
+		return;
+	}
+
+	if (csio->ccb_h.flags & CAM_CDB_POINTER)
+		bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len);
+	else
+		bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len);
+	req->IoFlags = csio->cdb_len;
+
+	/*
+	 * XXX need to handle S/G lists and physical addresses here.
+	 */
+	cm->cm_data = csio->data_ptr;
+	cm->cm_length = csio->dxfer_len;
+	cm->cm_sge = &req->SGL;
+	cm->cm_sglsize = (32 - 24) * 4;
+	cm->cm_desc.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
+	cm->cm_desc.SCSIIO.DevHandle = targ->handle;
+	cm->cm_complete = mpssas_scsiio_complete;
+	cm->cm_complete_data = ccb;
+	cm->cm_targ = targ;
+
+	callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000,
+	   mpssas_scsiio_timeout, cm);
+
+	mps_map_command(sc, cm);
+	return;
+}
+
+static void
+mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SCSI_IO_REPLY *rep;
+	union ccb *ccb;
+	struct mpssas_softc *sassc;
+	u_int sense_len;
+	int dir = 0;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	callout_stop(&cm->cm_callout);
+
+	sassc = sc->sassc;
+	ccb = cm->cm_complete_data;
+	rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply;
+
+	if (cm->cm_data != NULL) {
+		if (cm->cm_flags & MPS_CM_FLAGS_DATAIN)
+			dir = BUS_DMASYNC_POSTREAD;
+		else if (cm->cm_flags & MPS_CM_FLAGS_DATAOUT)
+			dir = BUS_DMASYNC_POSTWRITE;;
+		bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
+		bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
+	}
+
+	if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
+		ccb->ccb_h.flags |= CAM_RELEASE_SIMQ;
+		sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
+	}
+
+	/* Take the fast path to completion */
+	if (cm->cm_reply == NULL) {
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		ccb->csio.scsi_status = SCSI_STATUS_OK;
+		mps_free_command(sc, cm);
+		xpt_done(ccb);
+		return;
+	}
+
+	mps_dprint(sc, MPS_INFO, "(%d:%d:%d) IOCStatus= 0x%x, "
+	    "ScsiStatus= 0x%x, SCSIState= 0x%x TransferCount= 0x%x\n",
+	    xpt_path_path_id(ccb->ccb_h.path),
+	    xpt_path_target_id(ccb->ccb_h.path),
+	    xpt_path_lun_id(ccb->ccb_h.path), rep->IOCStatus,
+	    rep->SCSIStatus, rep->SCSIState, rep->TransferCount);
+
+	switch (rep->IOCStatus & MPI2_IOCSTATUS_MASK) {
+	case MPI2_IOCSTATUS_BUSY:
+	case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
+		/*
+		 * The controller is overloaded, try waiting a bit for it
+		 * to free up.
+		 */
+		ccb->ccb_h.status = CAM_BUSY;
+		break;
+	case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+		ccb->csio.resid = cm->cm_length - rep->TransferCount;
+		/* FALLTHROUGH */
+	case MPI2_IOCSTATUS_SUCCESS:
+	case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+		/* resid is ignored for this condition */
+		ccb->csio.resid = 0;
+		ccb->ccb_h.status = CAM_DATA_RUN_ERR;
+		break;
+	case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+	case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+		break;
+	case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+		/*
+		 * This is one of the responses that comes back when an I/O
+		 * has been aborted.  If it is because of a timeout that we
+		 * initiated, just set the status to CAM_CMD_TIMEOUT.
+		 * Otherwise set it to CAM_REQ_ABORTED.  The effect on the
+		 * command is the same (it gets retried, subject to the
+		 * retry counter), the only difference is what gets printed
+		 * on the console.
+		 */
+		if (cm->cm_state == MPS_CM_STATE_TIMEDOUT)
+			ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+		else
+			ccb->ccb_h.status = CAM_REQ_ABORTED;
+		break;
+	case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+	case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+		ccb->ccb_h.status = CAM_REQ_ABORTED;
+		break;
+	case MPI2_IOCSTATUS_INVALID_SGL:
+		mps_print_scsiio_cmd(sc, cm);
+		ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
+		break;
+	case MPI2_IOCSTATUS_INVALID_FUNCTION:
+	case MPI2_IOCSTATUS_INTERNAL_ERROR:
+	case MPI2_IOCSTATUS_INVALID_VPID:
+	case MPI2_IOCSTATUS_INVALID_FIELD:
+	case MPI2_IOCSTATUS_INVALID_STATE:
+	case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
+	case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+	case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+	case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+	case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+	default:
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+	}
+
+
+	if ((rep->SCSIState & MPI2_SCSI_STATE_NO_SCSI_STATUS) == 0) {
+		ccb->csio.scsi_status = rep->SCSIStatus;
+
+		switch (rep->SCSIStatus) {
+		case MPI2_SCSI_STATUS_TASK_SET_FULL:
+		case MPI2_SCSI_STATUS_CHECK_CONDITION:
+			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+			break;
+		case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
+		case MPI2_SCSI_STATUS_TASK_ABORTED:
+			ccb->ccb_h.status = CAM_REQ_ABORTED;
+			break;
+		case MPI2_SCSI_STATUS_GOOD:
+		default:
+			break;
+		}
+	}
+
+	if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+		sense_len = MIN(rep->SenseCount,
+		    sizeof(struct scsi_sense_data));
+		if (sense_len < rep->SenseCount)
+			ccb->csio.sense_resid = rep->SenseCount - sense_len;
+		bcopy(cm->cm_sense, &ccb->csio.sense_data, sense_len);
+		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+	}
+
+	if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
+		ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+
+	if (rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+
+	mps_free_command(sc, cm);
+	xpt_done(ccb);
+}
+
+#if __FreeBSD_version >= 900026
+static void
+mpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SMP_PASSTHROUGH_REPLY *rpl;
+	MPI2_SMP_PASSTHROUGH_REQUEST *req;
+	uint64_t sasaddr;
+	union ccb *ccb;
+
+	ccb = cm->cm_complete_data;
+	rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply;
+	if (rpl == NULL) {
+		mps_dprint(sc, MPS_INFO, "%s: NULL cm_reply!\n", __func__);
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+		goto bailout;
+	}
+
+	req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req;
+	sasaddr = le32toh(req->SASAddress.Low);
+	sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
+
+	if ((rpl->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS ||
+	    rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
+		mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n",
+		    __func__, rpl->IOCStatus, rpl->SASStatus);
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+		goto bailout;
+	}
+
+	mps_dprint(sc, MPS_INFO, "%s: SMP request to SAS address "
+		   "%#jx completed successfully\n", __func__,
+		   (uintmax_t)sasaddr);
+
+	if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED)
+		ccb->ccb_h.status = CAM_REQ_CMP;
+	else
+		ccb->ccb_h.status = CAM_SMP_STATUS_ERROR;
+
+bailout:
+	/*
+	 * We sync in both directions because we had DMAs in the S/G list
+	 * in both directions.
+	 */
+	bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap,
+			BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+	bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
+	mps_free_command(sc, cm);
+	xpt_done(ccb);
+}
+
+static void
+mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr)
+{
+	struct mps_command *cm;
+	uint8_t *request, *response;
+	MPI2_SMP_PASSTHROUGH_REQUEST *req;
+	struct mps_softc *sc;
+	struct sglist *sg;
+	int error;
+
+	sc = sassc->sc;
+	sg = NULL;
+	error = 0;
+
+	/*
+	 * XXX We don't yet support physical addresses here.
+	 */
+	if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) {
+		mps_printf(sc, "%s: physical addresses not supported\n",
+			   __func__);
+		ccb->ccb_h.status = CAM_REQ_INVALID;
+		xpt_done(ccb);
+		return;
+	}
+
+	/*
+	 * If the user wants to send an S/G list, check to make sure they
+	 * have single buffers.
+	 */
+	if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
+		/*
+		 * The chip does not support more than one buffer for the
+		 * request or response.
+		 */
+	 	if ((ccb->smpio.smp_request_sglist_cnt > 1)
+		  || (ccb->smpio.smp_response_sglist_cnt > 1)) {
+			mps_printf(sc, "%s: multiple request or response "
+				   "buffer segments not supported for SMP\n",
+				   __func__);
+			ccb->ccb_h.status = CAM_REQ_INVALID;
+			xpt_done(ccb);
+			return;
+		}
+
+		/*
+		 * The CAM_SCATTER_VALID flag was originally implemented
+		 * for the XPT_SCSI_IO CCB, which only has one data pointer.
+		 * We have two.  So, just take that flag to mean that we
+		 * might have S/G lists, and look at the S/G segment count
+		 * to figure out whether that is the case for each individual
+		 * buffer.
+		 */
+		if (ccb->smpio.smp_request_sglist_cnt != 0) {
+			bus_dma_segment_t *req_sg;
+
+			req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request;
+			request = (uint8_t *)req_sg[0].ds_addr;
+		} else
+			request = ccb->smpio.smp_request;
+
+		if (ccb->smpio.smp_response_sglist_cnt != 0) {
+			bus_dma_segment_t *rsp_sg;
+
+			rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response;
+			response = (uint8_t *)rsp_sg[0].ds_addr;
+		} else
+			response = ccb->smpio.smp_response;
+	} else {
+		request = ccb->smpio.smp_request;
+		response = ccb->smpio.smp_response;
+	}
+
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "%s: cannot allocate command\n", __func__);
+		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+		xpt_done(ccb);
+		return;
+	}
+
+	req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req;
+	bzero(req, sizeof(*req));
+	req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+
+	/* Allow the chip to use any route to this SAS address. */
+	req->PhysicalPort = 0xff;
+
+	req->RequestDataLength = ccb->smpio.smp_request_len;
+	req->SGLFlags = 
+	    MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
+
+	mps_dprint(sc, MPS_INFO, "%s: sending SMP request to SAS "
+		   "address %#jx\n", __func__, (uintmax_t)sasaddr);
+
+	mpi_init_sge(cm, req, &req->SGL);
+
+	/*
+	 * Set up a uio to pass into mps_map_command().  This allows us to
+	 * do one map command, and one busdma call in there.
+	 */
+	cm->cm_uio.uio_iov = cm->cm_iovec;
+	cm->cm_uio.uio_iovcnt = 2;
+	cm->cm_uio.uio_segflg = UIO_SYSSPACE;
+
+	/*
+	 * The read/write flag isn't used by busdma, but set it just in
+	 * case.  This isn't exactly accurate, either, since we're going in
+	 * both directions.
+	 */
+	cm->cm_uio.uio_rw = UIO_WRITE;
+
+	cm->cm_iovec[0].iov_base = request;
+	cm->cm_iovec[0].iov_len = req->RequestDataLength;
+	cm->cm_iovec[1].iov_base = response;
+	cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len;
+
+	cm->cm_uio.uio_resid = cm->cm_iovec[0].iov_len +
+			       cm->cm_iovec[1].iov_len;
+
+	/*
+	 * Trigger a warning message in mps_data_cb() for the user if we
+	 * wind up exceeding two S/G segments.  The chip expects one
+	 * segment for the request and another for the response.
+	 */
+	cm->cm_max_segs = 2;
+
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_complete = mpssas_smpio_complete;
+	cm->cm_complete_data = ccb;
+
+	/*
+	 * Tell the mapping code that we're using a uio, and that this is
+	 * an SMP passthrough request.  There is a little special-case
+	 * logic there (in mps_data_cb()) to handle the bidirectional
+	 * transfer.  
+	 */
+	cm->cm_flags |= MPS_CM_FLAGS_USE_UIO | MPS_CM_FLAGS_SMP_PASS |
+			MPS_CM_FLAGS_DATAIN | MPS_CM_FLAGS_DATAOUT;
+
+	/* The chip data format is little endian. */
+	req->SASAddress.High = htole32(sasaddr >> 32);
+	req->SASAddress.Low = htole32(sasaddr);
+
+	/*
+	 * XXX Note that we don't have a timeout/abort mechanism here.
+	 * From the manual, it looks like task management requests only
+	 * work for SCSI IO and SATA passthrough requests.  We may need to
+	 * have a mechanism to retry requests in the event of a chip reset
+	 * at least.  Hopefully the chip will insure that any errors short
+	 * of that are relayed back to the driver.
+	 */
+	error = mps_map_command(sc, cm);
+	if ((error != 0) && (error != EINPROGRESS)) {
+		mps_printf(sc, "%s: error %d returned from mps_map_command()\n",
+			   __func__, error);
+		goto bailout_error;
+	}
+
+	return;
+
+bailout_error:
+	mps_free_command(sc, cm);
+	ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+	xpt_done(ccb);
+	return;
+
+}
+
+static void
+mpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb)
+{
+	struct mps_softc *sc;
+	struct mpssas_target *targ;
+	uint64_t sasaddr = 0;
+
+	sc = sassc->sc;
+
+	/*
+	 * Make sure the target exists.
+	 */
+	targ = &sassc->targets[ccb->ccb_h.target_id];
+	if (targ->handle == 0x0) {
+		mps_printf(sc, "%s: target %d does not exist!\n", __func__,
+			   ccb->ccb_h.target_id);
+		ccb->ccb_h.status = CAM_SEL_TIMEOUT;
+		xpt_done(ccb);
+		return;
+	}
+
+	/*
+	 * If this device has an embedded SMP target, we'll talk to it
+	 * directly.
+	 * figure out what the expander's address is.
+	 */
+	if ((targ->devinfo & MPI2_SAS_DEVICE_INFO_SMP_TARGET) != 0)
+		sasaddr = targ->sasaddr;
+
+	/*
+	 * If we don't have a SAS address for the expander yet, try
+	 * grabbing it from the page 0x83 information cached in the
+	 * transport layer for this target.  LSI expanders report the
+	 * expander SAS address as the port-associated SAS address in
+	 * Inquiry VPD page 0x83.  Maxim expanders don't report it in page
+	 * 0x83.
+	 *
+	 * XXX KDM disable this for now, but leave it commented out so that
+	 * it is obvious that this is another possible way to get the SAS
+	 * address.
+	 *
+	 * The parent handle method below is a little more reliable, and
+	 * the other benefit is that it works for devices other than SES
+	 * devices.  So you can send a SMP request to a da(4) device and it
+	 * will get routed to the expander that device is attached to.
+	 * (Assuming the da(4) device doesn't contain an SMP target...)
+	 */
+#if 0
+	if (sasaddr == 0)
+		sasaddr = xpt_path_sas_addr(ccb->ccb_h.path);
+#endif
+
+	/*
+	 * If we still don't have a SAS address for the expander, look for
+	 * the parent device of this device, which is probably the expander.
+	 */
+	if (sasaddr == 0) {
+		struct mpssas_target *parent_target;
+
+		if (targ->parent_handle == 0x0) {
+			mps_printf(sc, "%s: handle %d does not have a valid "
+				   "parent handle!\n", __func__, targ->handle);
+			ccb->ccb_h.status = CAM_REQ_INVALID;
+			goto bailout;
+		}
+		parent_target = mpssas_find_target(sassc, 0,
+						   targ->parent_handle);
+
+		if (parent_target == NULL) {
+			mps_printf(sc, "%s: handle %d does not have a valid "
+				   "parent target!\n", __func__, targ->handle);
+			ccb->ccb_h.status = CAM_REQ_INVALID;
+			goto bailout;
+		}
+
+		if ((parent_target->devinfo &
+		     MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) {
+			mps_printf(sc, "%s: handle %d parent %d does not "
+				   "have an SMP target!\n", __func__,
+				   targ->handle, parent_target->handle);
+			ccb->ccb_h.status = CAM_REQ_INVALID;
+			goto bailout;
+
+		}
+
+		sasaddr = parent_target->sasaddr;
+	}
+
+	if (sasaddr == 0) {
+		mps_printf(sc, "%s: unable to find SAS address for handle %d\n",
+			   __func__, targ->handle);
+		ccb->ccb_h.status = CAM_REQ_INVALID;
+		goto bailout;
+	}
+	mpssas_send_smpcmd(sassc, ccb, sasaddr);
+
+	return;
+
+bailout:
+	xpt_done(ccb);
+
+}
+
+#endif /* __FreeBSD_version >= 900026 */
+
+static void
+mpssas_action_resetdev(struct mpssas_softc *sassc, union ccb *ccb)
+{
+	struct mps_softc *sc;
+	struct mps_command *cm;
+	struct mpssas_target *targ;
+
+	sc = sassc->sc;
+	targ = &sassc->targets[ccb->ccb_h.target_id];
+
+	if (targ->flags & MPSSAS_TARGET_INRECOVERY) {
+		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+		xpt_done(ccb);
+		return;
+	}
+
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "%s: cannot alloc command\n", __func__);
+		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+		xpt_done(ccb);
+		return;
+	}
+
+	cm->cm_targ = targ;
+	cm->cm_complete = mpssas_resetdev_complete;
+	cm->cm_complete_data = ccb;
+
+	mpssas_resetdev(sassc, cm);
+}
+
+static void
+mpssas_resetdev(struct mpssas_softc *sassc, struct mps_command *cm)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mps_softc *sc;
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	sc = sassc->sc;
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+	req->DevHandle = cm->cm_targ->handle;
+	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+
+	/* SAS Hard Link Reset / SATA Link Reset */
+	req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+
+	cm->cm_data = NULL;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+
+	mpssas_issue_tm_request(sc, cm);
+}
+
+static void
+mpssas_resetdev_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *resp;
+	union ccb *ccb;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)cm->cm_reply;
+	ccb = cm->cm_complete_data;
+
+	printf("resetdev complete IOCStatus= 0x%x ResponseCode= 0x%x\n",
+	    resp->IOCStatus, resp->ResponseCode);
+
+	if (resp->ResponseCode == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE)
+		ccb->ccb_h.status = CAM_REQ_CMP;
+	else
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+
+	mpssas_complete_tm_request(sc, cm, /*free_cm*/ 1);
+
+	xpt_done(ccb);
+}
+
+static void
+mpssas_poll(struct cam_sim *sim)
+{
+	struct mpssas_softc *sassc;
+
+	sassc = cam_sim_softc(sim);
+	mps_intr_locked(sassc->sc);
+}
+
+static void
+mpssas_freeze_device(struct mpssas_softc *sassc, struct mpssas_target *targ)
+{
+}
+
+static void
+mpssas_unfreeze_device(struct mpssas_softc *sassc, struct mpssas_target *targ)
+{
+}
+
diff -x .svn -urN sys/dev/mps/mps_table.c ../../stable/8/sys/dev/mps/mps_table.c
--- sys/dev/mps/mps_table.c	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps_table.c	2011-01-07 14:33:12.718781641 -0700
@@ -0,0 +1,493 @@
+/*-
+ * Copyright (c) 2009 Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/8/sys/dev/mps/mps_table.c 212420 2010-09-10 15:03:56Z ken $");
+
+/* Debugging tables for MPT2 */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/selinfo.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <cam/scsi/scsi_all.h>
+
+#include <dev/mps/mpi/mpi2_type.h>
+#include <dev/mps/mpi/mpi2.h>
+#include <dev/mps/mpi/mpi2_ioc.h>
+#include <dev/mps/mpi/mpi2_cnfg.h>
+#include <dev/mps/mpi/mpi2_init.h>
+#include <dev/mps/mpsvar.h>
+#include <dev/mps/mps_table.h>
+
+char *
+mps_describe_table(struct mps_table_lookup *table, u_int code)
+{
+	int i;
+
+	for (i = 0; table[i].string != NULL; i++) {
+		if (table[i].code == code)
+			return(table[i].string);
+	}
+	return(table[i+1].string);
+}
+
+struct mps_table_lookup mps_event_names[] = {
+	{"LogData",			0x01},
+	{"StateChange",			0x02},
+	{"HardResetReceived",		0x05},
+	{"EventChange",			0x0a},
+	{"TaskSetFull",			0x0e},
+	{"SasDeviceStatusChange",	0x0f},
+	{"IrOperationStatus",		0x14},
+	{"SasDiscovery",		0x16},
+	{"SasBroadcastPrimitive",	0x17},
+	{"SasInitDeviceStatusChange",	0x18},
+	{"SasInitTableOverflow",	0x19},
+	{"SasTopologyChangeList",	0x1c},
+	{"SasEnclDeviceStatusChange",	0x1d},
+	{"IrVolume",			0x1e},
+	{"IrPhysicalDisk",		0x1f},
+	{"IrConfigurationChangeList",	0x20},
+	{"LogEntryAdded",		0x21},
+	{"SasPhyCounter",		0x22},
+	{"GpioInterrupt",		0x23},
+	{"HbdPhyEvent",			0x24},
+	{NULL, 0},
+	{"Unknown Event", 0}
+};
+
+struct mps_table_lookup mps_phystatus_names[] = {
+	{"NewTargetAdded",		0x01},
+	{"TargetGone",			0x02},
+	{"PHYLinkStatusChange",		0x03},
+	{"PHYLinkStatusUnchanged",	0x04},
+	{"TargetMissing",		0x05},
+	{NULL, 0},
+	{"Unknown Status", 0}
+};
+
+struct mps_table_lookup mps_linkrate_names[] = {
+	{"PHY disabled",		0x01},
+	{"Speed Negotiation Failed",	0x02},
+	{"SATA OOB Complete",		0x03},
+	{"SATA Port Selector",		0x04},
+	{"SMP Reset in Progress",	0x05},
+	{"1.5Gbps",			0x08},
+	{"3.0Gbps",			0x09},
+	{"6.0Gbps",			0x0a},
+	{NULL, 0},
+	{"LinkRate Unknown",		0x00}
+};
+
+struct mps_table_lookup mps_sasdev0_devtype[] = {
+	{"End Device",			0x01},
+	{"Edge Expander",		0x02},
+	{"Fanout Expander",		0x03},
+	{NULL, 0},
+	{"No Device",			0x00}
+};
+
+struct mps_table_lookup mps_phyinfo_reason_names[] = {
+	{"Power On",			0x01},
+	{"Hard Reset",			0x02},
+	{"SMP Phy Control Link Reset",	0x03},
+	{"Loss DWORD Sync",		0x04},
+	{"Multiplex Sequence",		0x05},
+	{"I-T Nexus Loss Timer",	0x06},
+	{"Break Timeout Timer",		0x07},
+	{"PHY Test Function",		0x08},
+	{NULL, 0},
+	{"Unknown Reason",		0x00}
+};
+
+struct mps_table_lookup mps_whoinit_names[] = {
+	{"System BIOS",			0x01},
+	{"ROM BIOS",			0x02},
+	{"PCI Peer",			0x03},
+	{"Host Driver",			0x04},
+	{"Manufacturing",		0x05},
+	{NULL, 0},
+	{"Not Initialized",		0x00}
+};
+
+struct mps_table_lookup mps_sasdisc_reason[] = {
+	{"Discovery Started",		0x01},
+	{"Discovery Complete",		0x02},
+	{NULL, 0},
+	{"Unknown",			0x00}
+};
+
+struct mps_table_lookup mps_sastopo_exp[] = {
+	{"Added",			0x01},
+	{"Not Responding",		0x02},
+	{"Responding",			0x03},
+	{"Delay Not Responding",	0x04},
+	{NULL, 0},
+	{"Unknown",			0x00}
+};
+
+struct mps_table_lookup mps_sasdev_reason[] = {
+	{"SMART Data",			0x05},
+	{"Unsupported",			0x07},
+	{"Internal Device Reset",	0x08},
+	{"Task Abort Internal",		0x09},
+	{"Abort Task Set Internal",	0x0a},
+	{"Clear Task Set Internal",	0x0b},
+	{"Query Task Internal",		0x0c},
+	{"Async Notification",		0x0d},
+	{"Cmp Internal Device Reset",	0x0e},
+	{"Cmp Task Abort Internal",	0x0f},
+	{"Sata Init Failure",		0x10},
+	{NULL, 0},
+	{"Unknown",			0x00}
+};
+
+void
+mps_describe_devinfo(uint32_t devinfo, char *string, int len)
+{
+	snprintf(string, len, "%b,%s", devinfo,
+	    "\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit"
+	    "\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct"
+	    "\15LsiDev" "\16AtapiDev" "\17SepDev",
+	    mps_describe_table(mps_sasdev0_devtype, devinfo & 0x03));
+}
+
+void
+mps_print_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts)
+{
+
+	MPS_PRINTFIELD_START(sc, "IOCFacts");
+	MPS_PRINTFIELD(sc, facts, MsgVersion, 0x%x);
+	MPS_PRINTFIELD(sc, facts, HeaderVersion, 0x%x);
+	MPS_PRINTFIELD(sc, facts, IOCNumber, %d);
+	MPS_PRINTFIELD(sc, facts, IOCExceptions, 0x%x);
+	MPS_PRINTFIELD(sc, facts, MaxChainDepth, %d);
+	mps_dprint_field(sc, MPS_INFO, "WhoInit: %s\n",
+	    mps_describe_table(mps_whoinit_names, facts->WhoInit));
+	MPS_PRINTFIELD(sc, facts, NumberOfPorts, %d);
+	MPS_PRINTFIELD(sc, facts, RequestCredit, %d);
+	MPS_PRINTFIELD(sc, facts, ProductID, 0x%x);
+	mps_dprint_field(sc, MPS_INFO, "IOCCapabilities: %b\n",
+	    facts->IOCCapabilities, "\20" "\3ScsiTaskFull" "\4DiagTrace"
+	    "\5SnapBuf" "\6ExtBuf" "\7EEDP" "\10BiDirTarg" "\11Multicast"
+	    "\14TransRetry" "\15IR" "\16EventReplay" "\17RaidAccel"
+	    "\20MSIXIndex" "\21HostDisc");
+	mps_dprint_field(sc, MPS_INFO, "FWVersion= %d-%d-%d-%d\n",
+	    facts->FWVersion.Struct.Major,
+	    facts->FWVersion.Struct.Minor,
+	    facts->FWVersion.Struct.Unit,
+	    facts->FWVersion.Struct.Dev);
+	MPS_PRINTFIELD(sc, facts, IOCRequestFrameSize, %d);
+	MPS_PRINTFIELD(sc, facts, MaxInitiators, %d);
+	MPS_PRINTFIELD(sc, facts, MaxTargets, %d);
+	MPS_PRINTFIELD(sc, facts, MaxSasExpanders, %d);
+	MPS_PRINTFIELD(sc, facts, MaxEnclosures, %d);
+	mps_dprint_field(sc, MPS_INFO, "ProtocolFlags: %b\n",
+	    facts->ProtocolFlags, "\20" "\1ScsiTarg" "\2ScsiInit");
+	MPS_PRINTFIELD(sc, facts, HighPriorityCredit, %d);
+	MPS_PRINTFIELD(sc, facts, MaxReplyDescriptorPostQueueDepth, %d);
+	MPS_PRINTFIELD(sc, facts, ReplyFrameSize, %d);
+	MPS_PRINTFIELD(sc, facts, MaxVolumes, %d);
+	MPS_PRINTFIELD(sc, facts, MaxDevHandle, %d);
+	MPS_PRINTFIELD(sc, facts, MaxPersistentEntries, %d);
+}
+
+void
+mps_print_portfacts(struct mps_softc *sc, MPI2_PORT_FACTS_REPLY *facts)
+{
+
+	MPS_PRINTFIELD_START(sc, "PortFacts");
+	MPS_PRINTFIELD(sc, facts, PortNumber, %d);
+	MPS_PRINTFIELD(sc, facts, PortType, 0x%x);
+	MPS_PRINTFIELD(sc, facts, MaxPostedCmdBuffers, %d);
+}
+
+void
+mps_print_event(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
+{
+
+	MPS_EVENTFIELD_START(sc, "EventReply");
+	MPS_EVENTFIELD(sc, event, EventDataLength, %d);
+	MPS_EVENTFIELD(sc, event, AckRequired, %d);
+	mps_dprint_field(sc, MPS_EVENT, "Event: %s (0x%x)\n",
+	    mps_describe_table(mps_event_names, event->Event), event->Event);
+	MPS_EVENTFIELD(sc, event, EventContext, 0x%x);
+}
+
+void
+mps_print_sasdev0(struct mps_softc *sc, MPI2_CONFIG_PAGE_SAS_DEV_0 *buf)
+{
+	MPS_PRINTFIELD_START(sc, "SAS Device Page 0");
+	MPS_PRINTFIELD(sc, buf, Slot, %d);
+	MPS_PRINTFIELD(sc, buf, EnclosureHandle, 0x%x);
+	mps_dprint_field(sc, MPS_INFO, "SASAddress: 0x%jx\n",
+	    mps_to_u64(&buf->SASAddress));
+	MPS_PRINTFIELD(sc, buf, ParentDevHandle, 0x%x);
+	MPS_PRINTFIELD(sc, buf, PhyNum, %d);
+	MPS_PRINTFIELD(sc, buf, AccessStatus, 0x%x);
+	MPS_PRINTFIELD(sc, buf, DevHandle, 0x%x);
+	MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, 0x%x);
+	MPS_PRINTFIELD(sc, buf, ZoneGroup, %d);
+	mps_dprint_field(sc, MPS_INFO, "DeviceInfo: %b,%s\n", buf->DeviceInfo,
+	    "\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit"
+	    "\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct"
+	    "\15LsiDev" "\16AtapiDev" "\17SepDev",
+	    mps_describe_table(mps_sasdev0_devtype, buf->DeviceInfo & 0x03));
+	MPS_PRINTFIELD(sc, buf, Flags, 0x%x);
+	MPS_PRINTFIELD(sc, buf, PhysicalPort, %d);
+	MPS_PRINTFIELD(sc, buf, MaxPortConnections, %d);
+	mps_dprint_field(sc, MPS_INFO, "DeviceName: 0x%jx\n",
+	    mps_to_u64(&buf->DeviceName));
+	MPS_PRINTFIELD(sc, buf, PortGroups, %d);
+	MPS_PRINTFIELD(sc, buf, DmaGroup, %d);
+	MPS_PRINTFIELD(sc, buf, ControlGroup, %d);
+}
+
+void
+mps_print_evt_sas(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
+{
+
+	mps_print_event(sc, event);
+
+	switch(event->Event) {
+	case MPI2_EVENT_SAS_DISCOVERY:
+	{
+		MPI2_EVENT_DATA_SAS_DISCOVERY *data;
+
+		data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)&event->EventData;
+		mps_dprint_field(sc, MPS_EVENT, "Flags: %b\n", data->Flags,
+		    "\20" "\1InProgress" "\2DeviceChange");
+		mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n",
+		    mps_describe_table(mps_sasdisc_reason, data->ReasonCode));
+		MPS_EVENTFIELD(sc, data, PhysicalPort, %d);
+		mps_dprint_field(sc, MPS_EVENT, "DiscoveryStatus: %b\n",
+		    data->DiscoveryStatus,  "\20"
+		    "\1Loop" "\2UnaddressableDev" "\3DupSasAddr" "\5SmpTimeout"
+		    "\6ExpRouteFull" "\7RouteIndexError" "\10SmpFailed"
+		    "\11SmpCrcError" "\12SubSubLink" "\13TableTableLink"
+		    "\14UnsupDevice" "\15TableSubLink" "\16MultiDomain"
+		    "\17MultiSub" "\20MultiSubSub" "\34DownstreamInit"
+		    "\35MaxPhys" "\36MaxTargs" "\37MaxExpanders"
+		    "\40MaxEnclosures");
+		break;
+	}
+	case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+	{
+		MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
+		MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
+		int i, phynum;
+
+		data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
+		    &event->EventData;
+		MPS_EVENTFIELD(sc, data, EnclosureHandle, 0x%x);
+		MPS_EVENTFIELD(sc, data, ExpanderDevHandle, 0x%x);
+		MPS_EVENTFIELD(sc, data, NumPhys, %d);
+		MPS_EVENTFIELD(sc, data, NumEntries, %d);
+		MPS_EVENTFIELD(sc, data, StartPhyNum, %d);
+		mps_dprint_field(sc, MPS_EVENT, "ExpStatus: %s (0x%x)\n",
+		    mps_describe_table(mps_sastopo_exp, data->ExpStatus),
+		    data->ExpStatus);
+		MPS_EVENTFIELD(sc, data, PhysicalPort, %d);
+		for (i = 0; i < data->NumEntries; i++) {
+			phy = &data->PHY[i];
+			phynum = data->StartPhyNum + i;
+			mps_dprint_field(sc, MPS_EVENT,
+			    "PHY[%d].AttachedDevHandle: 0x%04x\n", phynum,
+			    phy->AttachedDevHandle);
+			mps_dprint_field(sc, MPS_EVENT,
+			    "PHY[%d].LinkRate: %s (0x%x)\n", phynum,
+			    mps_describe_table(mps_linkrate_names,
+			    (phy->LinkRate >> 4) & 0xf), phy->LinkRate);
+			mps_dprint_field(sc,MPS_EVENT,"PHY[%d].PhyStatus: %s\n",
+			    phynum, mps_describe_table(mps_phystatus_names,
+			    phy->PhyStatus));
+		}
+		break;
+	}
+	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+	{
+		MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *data;
+
+		data = (MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *)
+		    &event->EventData;
+		MPS_EVENTFIELD(sc, data, EnclosureHandle, 0x%x);
+		mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n",
+		    mps_describe_table(mps_sastopo_exp, data->ReasonCode));
+		MPS_EVENTFIELD(sc, data, PhysicalPort, %d);
+		MPS_EVENTFIELD(sc, data, NumSlots, %d);
+		MPS_EVENTFIELD(sc, data, StartSlot, %d);
+		MPS_EVENTFIELD(sc, data, PhyBits, 0x%x);
+		break;
+	}
+	case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+	{
+		MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *data;
+
+		data = (MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
+		    &event->EventData;
+		MPS_EVENTFIELD(sc, data, TaskTag, 0x%x);
+		mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n",
+		    mps_describe_table(mps_sasdev_reason, data->ReasonCode));
+		MPS_EVENTFIELD(sc, data, ASC, 0x%x);
+		MPS_EVENTFIELD(sc, data, ASCQ, 0x%x);
+		MPS_EVENTFIELD(sc, data, DevHandle, 0x%x);
+		mps_dprint_field(sc, MPS_EVENT, "SASAddress: 0x%jx\n",
+		    mps_to_u64(&data->SASAddress));
+	}
+	default:
+		break;
+	}
+}
+
+void
+mps_print_expander1(struct mps_softc *sc, MPI2_CONFIG_PAGE_EXPANDER_1 *buf)
+{
+	MPS_PRINTFIELD_START(sc, "SAS Expander Page 1 #%d", buf->Phy);
+	MPS_PRINTFIELD(sc, buf, PhysicalPort, %d);
+	MPS_PRINTFIELD(sc, buf, NumPhys, %d);
+	MPS_PRINTFIELD(sc, buf, Phy, %d);
+	MPS_PRINTFIELD(sc, buf, NumTableEntriesProgrammed, %d);
+	mps_dprint_field(sc, MPS_INFO, "ProgrammedLinkRate: %s (0x%x)\n",
+	    mps_describe_table(mps_linkrate_names,
+	    (buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate);
+	mps_dprint_field(sc, MPS_INFO, "HwLinkRate: %s (0x%x)\n",
+	    mps_describe_table(mps_linkrate_names,
+	    (buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate);
+	MPS_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x);
+	mps_dprint_field(sc, MPS_INFO, "PhyInfo Reason: %s (0x%x)\n",
+	    mps_describe_table(mps_phyinfo_reason_names,
+	    (buf->PhyInfo >> 16) & 0xf), buf->PhyInfo);
+	mps_dprint_field(sc, MPS_INFO, "AttachedDeviceInfo: %b,%s\n",
+	    buf->AttachedDeviceInfo, "\20" "\4SATAhost" "\5SMPinit" "\6STPinit"
+	    "\7SSPinit" "\10SATAdev" "\11SMPtarg" "\12STPtarg" "\13SSPtarg"
+	    "\14Direct" "\15LSIdev" "\16ATAPIdev" "\17SEPdev",
+	    mps_describe_table(mps_sasdev0_devtype,
+	    buf->AttachedDeviceInfo & 0x03));
+	MPS_PRINTFIELD(sc, buf, ExpanderDevHandle, 0x%04x);
+	MPS_PRINTFIELD(sc, buf, ChangeCount, %d);
+	mps_dprint_field(sc, MPS_INFO, "NegotiatedLinkRate: %s (0x%x)\n",
+	    mps_describe_table(mps_linkrate_names,
+	    buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate);
+	MPS_PRINTFIELD(sc, buf, PhyIdentifier, %d);
+	MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d);
+	MPS_PRINTFIELD(sc, buf, DiscoveryInfo, 0x%x);
+	MPS_PRINTFIELD(sc, buf, AttachedPhyInfo, 0x%x);
+	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
+	    mps_describe_table(mps_phyinfo_reason_names,
+	    buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo);
+	MPS_PRINTFIELD(sc, buf, ZoneGroup, %d);
+	MPS_PRINTFIELD(sc, buf, SelfConfigStatus, 0x%x);
+}
+
+void
+mps_print_sasphy0(struct mps_softc *sc, MPI2_CONFIG_PAGE_SAS_PHY_0 *buf)
+{
+	MPS_PRINTFIELD_START(sc, "SAS PHY Page 0");
+	MPS_PRINTFIELD(sc, buf, OwnerDevHandle, 0x%04x);
+	MPS_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x);
+	MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d);
+	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
+	    mps_describe_table(mps_phyinfo_reason_names,
+	    buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo);
+	mps_dprint_field(sc, MPS_INFO, "ProgrammedLinkRate: %s (0x%x)\n",
+	    mps_describe_table(mps_linkrate_names,
+	    (buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate);
+	mps_dprint_field(sc, MPS_INFO, "HwLinkRate: %s (0x%x)\n",
+	    mps_describe_table(mps_linkrate_names,
+	    (buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate);
+	MPS_PRINTFIELD(sc, buf, ChangeCount, %d);
+	MPS_PRINTFIELD(sc, buf, Flags, 0x%x);
+	mps_dprint_field(sc, MPS_INFO, "PhyInfo Reason: %s (0x%x)\n",
+	    mps_describe_table(mps_phyinfo_reason_names,
+	    (buf->PhyInfo >> 16) & 0xf), buf->PhyInfo);
+	mps_dprint_field(sc, MPS_INFO, "NegotiatedLinkRate: %s (0x%x)\n",
+	    mps_describe_table(mps_linkrate_names,
+	    buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate);
+}
+
+void
+mps_print_sgl(struct mps_softc *sc, struct mps_command *cm, int offset)
+{
+	MPI2_SGE_SIMPLE64 *sge;
+	MPI2_SGE_CHAIN32 *sgc;
+	MPI2_REQUEST_HEADER *req;
+	struct mps_chain *chain = NULL;
+	char *frame;
+	u_int i = 0, flags;
+
+	req = (MPI2_REQUEST_HEADER *)cm->cm_req;
+	frame = (char *)cm->cm_req;
+	sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4];
+	printf("SGL for command %p\n", cm);
+
+	while (frame != NULL) {
+		flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT;
+		printf("seg%d flags=0x%x len=0x%x addr=0x%jx\n", i, flags,
+		    sge->FlagsLength & 0xffffff, mps_to_u64(&sge->Address));
+		if (flags & (MPI2_SGE_FLAGS_END_OF_LIST |
+		    MPI2_SGE_FLAGS_END_OF_BUFFER))
+			break;
+		sge++;
+		i++;
+		if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) {
+			sgc = (MPI2_SGE_CHAIN32 *)sge;
+			printf("chain flags=0x%x len=0x%x Offset=0x%x "
+			    "Address=0x%x\n", sgc->Flags, sgc->Length,
+			    sgc->NextChainOffset, sgc->Address);
+			if (chain == NULL)
+				chain = TAILQ_FIRST(&cm->cm_chain_list);
+			else
+				chain = TAILQ_NEXT(chain, chain_link);
+			frame = (char *)chain->chain;
+			sge = (MPI2_SGE_SIMPLE64 *)frame;
+			hexdump(frame, 128, NULL, 0);
+		}
+	}
+}
+
+void
+mps_print_scsiio_cmd(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_SCSI_IO_REQUEST *req;
+
+	req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req;
+	mps_print_sgl(sc, cm, req->SGLOffset0);
+}
+
diff -x .svn -urN sys/dev/mps/mps_table.h ../../stable/8/sys/dev/mps/mps_table.h
--- sys/dev/mps/mps_table.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps_table.h	2011-01-07 14:33:12.726814052 -0700
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2009 Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/8/sys/dev/mps/mps_table.h 212420 2010-09-10 15:03:56Z ken $
+ */
+
+#ifndef _MPS_TABLE_H
+#define _MPS_TABLE_H
+
+struct mps_table_lookup {
+	char	*string;
+	u_int	code;
+};
+
+char * mps_describe_table(struct mps_table_lookup *table, u_int code);
+void mps_describe_devinfo(uint32_t devinfo, char *string, int len);
+
+extern struct mps_table_lookup mps_event_names[];
+extern struct mps_table_lookup mps_phystatus_names[];
+extern struct mps_table_lookup mps_linkrate_names[];
+
+void mps_print_iocfacts(struct mps_softc *, MPI2_IOC_FACTS_REPLY *);
+void mps_print_portfacts(struct mps_softc *, MPI2_PORT_FACTS_REPLY *);
+void mps_print_event(struct mps_softc *, MPI2_EVENT_NOTIFICATION_REPLY *);
+void mps_print_sasdev0(struct mps_softc *, MPI2_CONFIG_PAGE_SAS_DEV_0 *);
+void mps_print_evt_sas(struct mps_softc *, MPI2_EVENT_NOTIFICATION_REPLY *);
+void mps_print_expander1(struct mps_softc *, MPI2_CONFIG_PAGE_EXPANDER_1 *);
+void mps_print_sasphy0(struct mps_softc *, MPI2_CONFIG_PAGE_SAS_PHY_0 *);
+void mps_print_sgl(struct mps_softc *, struct mps_command *, int);
+void mps_print_scsiio_cmd(struct mps_softc *, struct mps_command *);
+#endif
diff -x .svn -urN sys/dev/mps/mps_user.c ../../stable/8/sys/dev/mps/mps_user.c
--- sys/dev/mps/mps_user.c	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mps_user.c	2011-01-07 14:36:19.755462069 -0700
@@ -0,0 +1,944 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * LSI MPS-Fusion Host Adapter FreeBSD userland interface
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/8/sys/dev/mps/mps_user.c 212420 2010-09-10 15:03:56Z ken $");
+
+#include "opt_compat.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/selinfo.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/ioccom.h>
+#include <sys/endian.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <cam/scsi/scsi_all.h>
+
+#include <dev/mps/mpi/mpi2_type.h>
+#include <dev/mps/mpi/mpi2.h>
+#include <dev/mps/mpi/mpi2_ioc.h>
+#include <dev/mps/mpi/mpi2_cnfg.h>
+#include <dev/mps/mpsvar.h>
+#include <dev/mps/mps_table.h>
+#include <dev/mps/mps_ioctl.h>
+
+static d_open_t		mps_open;
+static d_close_t	mps_close;
+static d_ioctl_t	mps_ioctl_devsw;
+
+static struct cdevsw mps_cdevsw = {
+	.d_version =	D_VERSION,
+	.d_flags =	0,
+	.d_open =	mps_open,
+	.d_close =	mps_close,
+	.d_ioctl =	mps_ioctl_devsw,
+	.d_name =	"mps",
+};
+
+typedef int (mps_user_f)(struct mps_command *, struct mps_usr_command *);
+static mps_user_f	mpi_pre_ioc_facts;
+static mps_user_f	mpi_pre_port_facts;
+static mps_user_f	mpi_pre_fw_download;
+static mps_user_f	mpi_pre_fw_upload;
+static mps_user_f	mpi_pre_sata_passthrough;
+static mps_user_f	mpi_pre_smp_passthrough;
+static mps_user_f	mpi_pre_config;
+static mps_user_f	mpi_pre_sas_io_unit_control;
+
+static int mps_user_read_cfg_header(struct mps_softc *,
+				    struct mps_cfg_page_req *);
+static int mps_user_read_cfg_page(struct mps_softc *,
+				  struct mps_cfg_page_req *, void *);
+static int mps_user_read_extcfg_header(struct mps_softc *,
+				     struct mps_ext_cfg_page_req *);
+static int mps_user_read_extcfg_page(struct mps_softc *,
+				     struct mps_ext_cfg_page_req *, void *);
+static int mps_user_write_cfg_page(struct mps_softc *,
+				   struct mps_cfg_page_req *, void *);
+static int mps_user_setup_request(struct mps_command *,
+				  struct mps_usr_command *);
+static int mps_user_command(struct mps_softc *, struct mps_usr_command *);
+
+static MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls");
+
+int
+mps_attach_user(struct mps_softc *sc)
+{
+	int unit;
+
+	unit = device_get_unit(sc->mps_dev);
+	sc->mps_cdev = make_dev(&mps_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640,
+	    "mps%d", unit);
+	if (sc->mps_cdev == NULL) {
+		return (ENOMEM);
+	}
+	sc->mps_cdev->si_drv1 = sc;
+	return (0);
+}
+
+void
+mps_detach_user(struct mps_softc *sc)
+{
+
+	/* XXX: do a purge of pending requests? */
+	destroy_dev(sc->mps_cdev);
+
+}
+
+static int
+mps_open(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+
+	return (0);
+}
+
+static int
+mps_close(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+
+	return (0);
+}
+
+static int
+mps_user_read_cfg_header(struct mps_softc *sc,
+    struct mps_cfg_page_req *page_req)
+{
+	MPI2_CONFIG_PAGE_HEADER *hdr;
+	struct mps_config_params params;
+	int	    error;
+
+	hdr = &params.hdr.Struct;
+	params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	params.page_address = le32toh(page_req->page_address);
+	hdr->PageVersion = 0;
+	hdr->PageLength = 0;
+	hdr->PageNumber = page_req->header.PageNumber;
+	hdr->PageType = page_req->header.PageType;
+	params.buffer = NULL;
+	params.length = 0;
+	params.callback = NULL;
+
+	if ((error = mps_read_config_page(sc, &params)) != 0) {
+		/*
+		 * Leave the request. Without resetting the chip, it's
+		 * still owned by it and we'll just get into trouble
+		 * freeing it now. Mark it as abandoned so that if it
+		 * shows up later it can be freed.
+		 */
+		mps_printf(sc, "read_cfg_header timed out\n");
+		return (ETIMEDOUT);
+	}
+
+	page_req->ioc_status = htole16(params.status);
+	if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
+	    MPI2_IOCSTATUS_SUCCESS) {
+		bcopy(hdr, &page_req->header, sizeof(page_req->header));
+	}
+
+	return (0);
+}
+
+static int
+mps_user_read_cfg_page(struct mps_softc *sc, struct mps_cfg_page_req *page_req,
+    void *buf)
+{
+	MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
+	struct mps_config_params params;
+	int	      error;
+
+	reqhdr = buf;
+	hdr = &params.hdr.Struct;
+	hdr->PageVersion = reqhdr->PageVersion;
+	hdr->PageLength = reqhdr->PageLength;
+	hdr->PageNumber = reqhdr->PageNumber;
+	hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK;
+	params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	params.page_address = le32toh(page_req->page_address);
+	params.buffer = buf;
+	params.length = le32toh(page_req->len);
+	params.callback = NULL;
+
+	if ((error = mps_read_config_page(sc, &params)) != 0) {
+		mps_printf(sc, "mps_user_read_cfg_page timed out\n");
+		return (ETIMEDOUT);
+	}
+
+	page_req->ioc_status = htole16(params.status);
+	return (0);
+}
+
+static int
+mps_user_read_extcfg_header(struct mps_softc *sc,
+    struct mps_ext_cfg_page_req *ext_page_req)
+{
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
+	struct mps_config_params params;
+	int	    error;
+
+	hdr = &params.hdr.Ext;
+	params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	hdr->PageVersion = ext_page_req->header.PageVersion;
+	hdr->ExtPageLength = 0;
+	hdr->PageNumber = ext_page_req->header.PageNumber;
+	hdr->ExtPageType = ext_page_req->header.ExtPageType;
+	params.page_address = le32toh(ext_page_req->page_address);
+	if ((error = mps_read_config_page(sc, &params)) != 0) {
+		/*
+		 * Leave the request. Without resetting the chip, it's
+		 * still owned by it and we'll just get into trouble
+		 * freeing it now. Mark it as abandoned so that if it
+		 * shows up later it can be freed.
+		 */
+		mps_printf(sc, "mps_user_read_extcfg_header timed out\n");
+		return (ETIMEDOUT);
+	}
+
+	ext_page_req->ioc_status = htole16(params.status);
+	if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
+	    MPI2_IOCSTATUS_SUCCESS) {
+		ext_page_req->header.PageVersion = hdr->PageVersion;
+		ext_page_req->header.PageNumber = hdr->PageNumber;
+		ext_page_req->header.PageType = hdr->PageType;
+		ext_page_req->header.ExtPageLength = hdr->ExtPageLength;
+		ext_page_req->header.ExtPageType = hdr->ExtPageType;
+	}
+
+	return (0);
+}
+
+static int
+mps_user_read_extcfg_page(struct mps_softc *sc,
+    struct mps_ext_cfg_page_req *ext_page_req, void *buf)
+{
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr;
+	struct mps_config_params params;
+	int error;
+
+	reqhdr = buf;
+	hdr = &params.hdr.Ext;
+	params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	params.page_address = le32toh(ext_page_req->page_address);
+	hdr->PageVersion = reqhdr->PageVersion;
+	hdr->PageNumber = reqhdr->PageNumber;
+	hdr->ExtPageType = reqhdr->ExtPageType;
+	hdr->ExtPageLength = reqhdr->ExtPageLength;
+	params.buffer = buf;
+	params.length = le32toh(ext_page_req->len);
+	params.callback = NULL;
+
+	if ((error = mps_read_config_page(sc, &params)) != 0) {
+		mps_printf(sc, "mps_user_read_extcfg_page timed out\n");
+		return (ETIMEDOUT);
+	}
+
+	ext_page_req->ioc_status = htole16(params.status);
+	return (0);
+}
+
+static int
+mps_user_write_cfg_page(struct mps_softc *sc,
+    struct mps_cfg_page_req *page_req, void *buf)
+{
+	MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
+	struct mps_config_params params;
+	u_int	      hdr_attr;
+	int	      error;
+
+	reqhdr = buf;
+	hdr = &params.hdr.Struct;
+	hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK;
+	if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE &&
+	    hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) {
+		mps_printf(sc, "page type 0x%x not changeable\n",
+			reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK);
+		return (EINVAL);
+	}
+
+	/*
+	 * There isn't any point in restoring stripped out attributes
+	 * if you then mask them going down to issue the request.
+	 */
+
+	hdr->PageVersion = reqhdr->PageVersion;
+	hdr->PageLength = reqhdr->PageLength;
+	hdr->PageNumber = reqhdr->PageNumber;
+	hdr->PageType = reqhdr->PageType;
+	params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	params.page_address = le32toh(page_req->page_address);
+	params.buffer = buf;
+	params.length = le32toh(page_req->len);
+	params.callback = NULL;
+
+	if ((error = mps_write_config_page(sc, &params)) != 0) {
+		mps_printf(sc, "mps_write_cfg_page timed out\n");
+		return (ETIMEDOUT);
+	}
+
+	page_req->ioc_status = htole16(params.status);
+	return (0);
+}
+
+void
+mpi_init_sge(struct mps_command *cm, void *req, void *sge)
+{
+	int off, space;
+
+	space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4;
+	off = (uintptr_t)sge - (uintptr_t)req;
+
+	KASSERT(off < space, ("bad pointers %p %p, off %d, space %d",
+            req, sge, off, space));
+
+	cm->cm_sge = sge;
+	cm->cm_sglsize = space - off;
+}
+
+/*
+ * Prepare the mps_command for an IOC_FACTS request.
+ */
+static int
+mpi_pre_ioc_facts(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_IOC_FACTS_REQUEST *req = (void *)cm->cm_req;
+	MPI2_IOC_FACTS_REPLY *rpl;
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	cm->cm_sge = NULL;
+	cm->cm_sglsize = 0;
+	return (0);
+}
+
+/*
+ * Prepare the mps_command for a PORT_FACTS request.
+ */
+static int
+mpi_pre_port_facts(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_PORT_FACTS_REQUEST *req = (void *)cm->cm_req;
+	MPI2_PORT_FACTS_REPLY *rpl;
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	cm->cm_sge = NULL;
+	cm->cm_sglsize = 0;
+	return (0);
+}
+
+/*
+ * Prepare the mps_command for a FW_DOWNLOAD request.
+ */
+static int
+mpi_pre_fw_download(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_FW_DOWNLOAD_REQUEST *req = (void *)cm->cm_req;
+	MPI2_FW_DOWNLOAD_REPLY *rpl;
+	MPI2_FW_DOWNLOAD_TCSGE tc;
+	int error;
+
+	/*
+	 * This code assumes there is room in the request's SGL for
+	 * the TransactionContext plus at least a SGL chain element.
+	 */
+	CTASSERT(sizeof req->SGL >= sizeof tc + MPS_SGC_SIZE);
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	if (cmd->len == 0)
+		return (EINVAL);
+
+	error = copyin(cmd->buf, cm->cm_data, cmd->len);
+	if (error != 0)
+		return (error);
+
+	mpi_init_sge(cm, req, &req->SGL);
+	bzero(&tc, sizeof tc);
+
+	/*
+	 * For now, the F/W image must be provided in a single request.
+	 */
+	if ((req->MsgFlags & MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT) == 0)
+		return (EINVAL);
+	if (req->TotalImageSize != cmd->len)
+		return (EINVAL);
+
+	/*
+	 * The value of the first two elements is specified in the
+	 * Fusion-MPT Message Passing Interface document.
+	 */
+	tc.ContextSize = 0;
+	tc.DetailsLength = 12;
+	tc.ImageOffset = 0;
+	tc.ImageSize = cmd->len;
+
+	cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
+
+	return (mps_push_sge(cm, &tc, sizeof tc, 0));
+}
+
+/*
+ * Prepare the mps_command for a FW_UPLOAD request.
+ */
+static int
+mpi_pre_fw_upload(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_FW_UPLOAD_REQUEST *req = (void *)cm->cm_req;
+	MPI2_FW_UPLOAD_REPLY *rpl;
+	MPI2_FW_UPLOAD_TCSGE tc;
+
+	/*
+	 * This code assumes there is room in the request's SGL for
+	 * the TransactionContext plus at least a SGL chain element.
+	 */
+	CTASSERT(sizeof req->SGL >= sizeof tc + MPS_SGC_SIZE);
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	mpi_init_sge(cm, req, &req->SGL);
+	if (cmd->len == 0) {
+		/* Perhaps just asking what the size of the fw is? */
+		return (0);
+	}
+
+	bzero(&tc, sizeof tc);
+
+	/*
+	 * The value of the first two elements is specified in the
+	 * Fusion-MPT Message Passing Interface document.
+	 */
+	tc.ContextSize = 0;
+	tc.DetailsLength = 12;
+	/*
+	 * XXX Is there any reason to fetch a partial image?  I.e. to
+	 * set ImageOffset to something other than 0?
+	 */
+	tc.ImageOffset = 0;
+	tc.ImageSize = cmd->len;
+
+	return (mps_push_sge(cm, &tc, sizeof tc, 0));
+}
+
+/*
+ * Prepare the mps_command for a SATA_PASSTHROUGH request.
+ */
+static int
+mpi_pre_sata_passthrough(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_SATA_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
+	MPI2_SATA_PASSTHROUGH_REPLY *rpl;
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	mpi_init_sge(cm, req, &req->SGL);
+	return (0);
+}
+
+/*
+ * Prepare the mps_command for a SMP_PASSTHROUGH request.
+ */
+static int
+mpi_pre_smp_passthrough(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_SMP_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
+	MPI2_SMP_PASSTHROUGH_REPLY *rpl;
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	mpi_init_sge(cm, req, &req->SGL);
+	return (0);
+}
+
+/*
+ * Prepare the mps_command for a CONFIG request.
+ */
+static int
+mpi_pre_config(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_CONFIG_REQUEST *req = (void *)cm->cm_req;
+	MPI2_CONFIG_REPLY *rpl;
+
+	if (cmd->req_len != sizeof *req)
+		return (EINVAL);
+	if (cmd->rpl_len != sizeof *rpl)
+		return (EINVAL);
+
+	mpi_init_sge(cm, req, &req->PageBufferSGE);
+	return (0);
+}
+
+/*
+ * Prepare the mps_command for a SAS_IO_UNIT_CONTROL request.
+ */
+static int
+mpi_pre_sas_io_unit_control(struct mps_command *cm,
+			     struct mps_usr_command *cmd)
+{
+
+	cm->cm_sge = NULL;
+	cm->cm_sglsize = 0;
+	return (0);
+}
+
+/*
+ * A set of functions to prepare an mps_command for the various
+ * supported requests.
+ */
+struct mps_user_func {
+	U8		Function;
+	mps_user_f	*f_pre;
+} mps_user_func_list[] = {
+	{ MPI2_FUNCTION_IOC_FACTS,		mpi_pre_ioc_facts },
+	{ MPI2_FUNCTION_PORT_FACTS,		mpi_pre_port_facts },
+	{ MPI2_FUNCTION_FW_DOWNLOAD, 		mpi_pre_fw_download },
+	{ MPI2_FUNCTION_FW_UPLOAD,		mpi_pre_fw_upload },
+	{ MPI2_FUNCTION_SATA_PASSTHROUGH,	mpi_pre_sata_passthrough },
+	{ MPI2_FUNCTION_SMP_PASSTHROUGH,	mpi_pre_smp_passthrough},
+	{ MPI2_FUNCTION_CONFIG,			mpi_pre_config},
+	{ MPI2_FUNCTION_SAS_IO_UNIT_CONTROL,	mpi_pre_sas_io_unit_control },
+	{ 0xFF,					NULL } /* list end */
+};
+
+static int
+mps_user_setup_request(struct mps_command *cm, struct mps_usr_command *cmd)
+{
+	MPI2_REQUEST_HEADER *hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;	
+	struct mps_user_func *f;
+
+	for (f = mps_user_func_list; f->f_pre != NULL; f++) {
+		if (hdr->Function == f->Function)
+			return (f->f_pre(cm, cmd));
+	}
+	return (EINVAL);
+}	
+
+static int
+mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
+{
+	MPI2_REQUEST_HEADER *hdr;	
+	MPI2_DEFAULT_REPLY *rpl;
+	void *buf = NULL;
+	struct mps_command *cm = NULL;
+	int err = 0;
+	int sz;
+
+	mps_lock(sc);
+	cm = mps_alloc_command(sc);
+
+	if (cm == NULL) {
+		mps_printf(sc, "mps_user_command: no mps requests\n");
+		err = ENOMEM;
+		goto Ret;
+	}
+	mps_unlock(sc);
+
+	hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
+
+	mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d  rpl %p %d\n",
+		    cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );
+
+	if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
+		err = EINVAL;
+		goto RetFreeUnlocked;
+	}
+	err = copyin(cmd->req, hdr, cmd->req_len);
+	if (err != 0)
+		goto RetFreeUnlocked;
+
+	mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X  "
+	    "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );
+
+	err = mps_user_setup_request(cm, cmd);
+	if (err != 0) {
+		mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
+		    hdr->Function );
+		goto RetFreeUnlocked;
+	}
+
+	if (cmd->len > 0) {
+		buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
+		cm->cm_data = buf;
+		cm->cm_length = cmd->len;
+	} else {
+		cm->cm_data = NULL;
+		cm->cm_length = 0;
+	}
+
+	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_WAKEUP;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+
+	mps_lock(sc);
+	err = mps_map_command(sc, cm);
+
+	if (err != 0 && err != EINPROGRESS) {
+		mps_printf(sc, "%s: invalid request: error %d\n",
+		    __func__, err);
+		goto Ret;
+	}
+	msleep(cm, &sc->mps_mtx, 0, "mpsuser", 0);
+
+	rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
+	sz = rpl->MsgLength * 4;
+	
+	if (sz > cmd->rpl_len) {
+		mps_printf(sc,
+		    "mps_user_command: reply buffer too small %d required %d\n",
+		    cmd->rpl_len, sz );
+		err = EINVAL;
+		sz = cmd->rpl_len;
+	}	
+
+	mps_unlock(sc);
+	copyout(rpl, cmd->rpl, sz);
+	if (buf != NULL)
+		copyout(buf, cmd->buf, cmd->len);
+	mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz );
+
+RetFreeUnlocked:
+	mps_lock(sc);
+	if (cm != NULL)
+		mps_free_command(sc, cm);
+Ret:
+	mps_unlock(sc);
+	if (buf != NULL)
+		free(buf, M_MPSUSER);
+	return (err);
+}	
+
+static int
+mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
+    struct thread *td)
+{
+	struct mps_softc *sc;
+	struct mps_cfg_page_req *page_req;
+	struct mps_ext_cfg_page_req *ext_page_req;
+	void *mps_page;
+	int error;
+
+	mps_page = NULL;
+	sc = dev->si_drv1;
+	page_req = (void *)arg;
+	ext_page_req = (void *)arg;
+
+	switch (cmd) {
+	case MPSIO_READ_CFG_HEADER:
+		mps_lock(sc);
+		error = mps_user_read_cfg_header(sc, page_req);
+		mps_unlock(sc);
+		break;
+	case MPSIO_READ_CFG_PAGE:
+		mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO);
+		error = copyin(page_req->buf, mps_page,
+		    sizeof(MPI2_CONFIG_PAGE_HEADER));
+		if (error)
+			break;
+		mps_lock(sc);
+		error = mps_user_read_cfg_page(sc, page_req, mps_page);
+		mps_unlock(sc);
+		if (error)
+			break;
+		error = copyout(mps_page, page_req->buf, page_req->len);
+		break;
+	case MPSIO_READ_EXT_CFG_HEADER:
+		mps_lock(sc);
+		error = mps_user_read_extcfg_header(sc, ext_page_req);
+		mps_unlock(sc);
+		break;
+	case MPSIO_READ_EXT_CFG_PAGE:
+		mps_page = malloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
+		error = copyin(ext_page_req->buf, mps_page,
+		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+		if (error)
+			break;
+		mps_lock(sc);
+		error = mps_user_read_extcfg_page(sc, ext_page_req, mps_page);
+		mps_unlock(sc);
+		if (error)
+			break;
+		error = copyout(mps_page, ext_page_req->buf, ext_page_req->len);
+		break;
+	case MPSIO_WRITE_CFG_PAGE:
+		mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
+		error = copyin(page_req->buf, mps_page, page_req->len);
+		if (error)
+			break;
+		mps_lock(sc);
+		error = mps_user_write_cfg_page(sc, page_req, mps_page);
+		mps_unlock(sc);
+		break;
+	case MPSIO_MPS_COMMAND:
+		error = mps_user_command(sc, (struct mps_usr_command *)arg);
+		break;
+	default:
+		error = ENOIOCTL;
+		break;
+	}
+
+	if (mps_page != NULL)
+		free(mps_page, M_MPSUSER);
+
+	return (error);
+}
+
+#ifdef COMPAT_FREEBSD32
+
+/* Macros from compat/freebsd32/freebsd32.h */
+#define	PTRIN(v)	(void *)(uintptr_t)(v)
+#define	PTROUT(v)	(uint32_t)(uintptr_t)(v)
+
+#define	CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define	PTRIN_CP(src,dst,fld)				\
+	do { (dst).fld = PTRIN((src).fld); } while (0)
+#define	PTROUT_CP(src,dst,fld) \
+	do { (dst).fld = PTROUT((src).fld); } while (0)
+
+struct mps_cfg_page_req32 {
+	MPI2_CONFIG_PAGE_HEADER header;
+	uint32_t page_address;
+	uint32_t buf;
+	int	len;	
+	uint16_t ioc_status;
+};
+
+struct mps_ext_cfg_page_req32 {
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
+	uint32_t page_address;
+	uint32_t buf;
+	int	len;
+	uint16_t ioc_status;
+};
+
+struct mps_raid_action32 {
+	uint8_t action;
+	uint8_t volume_bus;
+	uint8_t volume_id;
+	uint8_t phys_disk_num;
+	uint32_t action_data_word;
+	uint32_t buf;
+	int len;
+	uint32_t volume_status;
+	uint32_t action_data[4];
+	uint16_t action_status;
+	uint16_t ioc_status;
+	uint8_t write;
+};
+
+struct mps_usr_command32 {
+	uint32_t req;
+	uint32_t req_len;
+	uint32_t rpl;
+	uint32_t rpl_len;
+	uint32_t buf;
+	int len;
+	uint32_t flags;
+};
+
+#define	MPSIO_READ_CFG_HEADER32	_IOWR('M', 200, struct mps_cfg_page_req32)
+#define	MPSIO_READ_CFG_PAGE32	_IOWR('M', 201, struct mps_cfg_page_req32)
+#define	MPSIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mps_ext_cfg_page_req32)
+#define	MPSIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mps_ext_cfg_page_req32)
+#define	MPSIO_WRITE_CFG_PAGE32	_IOWR('M', 204, struct mps_cfg_page_req32)
+#define	MPSIO_RAID_ACTION32	_IOWR('M', 205, struct mps_raid_action32)
+#define	MPSIO_MPS_COMMAND32	_IOWR('M', 210, struct mps_usr_command32)
+
+static int
+mps_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag,
+    struct thread *td)
+{
+	struct mps_cfg_page_req32 *page32 = _arg;
+	struct mps_ext_cfg_page_req32 *ext32 = _arg;
+	struct mps_raid_action32 *raid32 = _arg;
+	struct mps_usr_command32 *user32 = _arg;
+	union {
+		struct mps_cfg_page_req page;
+		struct mps_ext_cfg_page_req ext;
+		struct mps_raid_action raid;
+		struct mps_usr_command user;
+	} arg;
+	u_long cmd;
+	int error;
+
+	switch (cmd32) {
+	case MPSIO_READ_CFG_HEADER32:
+	case MPSIO_READ_CFG_PAGE32:
+	case MPSIO_WRITE_CFG_PAGE32:
+		if (cmd32 == MPSIO_READ_CFG_HEADER32)
+			cmd = MPSIO_READ_CFG_HEADER;
+		else if (cmd32 == MPSIO_READ_CFG_PAGE32)
+			cmd = MPSIO_READ_CFG_PAGE;
+		else
+			cmd = MPSIO_WRITE_CFG_PAGE;
+		CP(*page32, arg.page, header);
+		CP(*page32, arg.page, page_address);
+		PTRIN_CP(*page32, arg.page, buf);
+		CP(*page32, arg.page, len);
+		CP(*page32, arg.page, ioc_status);
+		break;
+
+	case MPSIO_READ_EXT_CFG_HEADER32:
+	case MPSIO_READ_EXT_CFG_PAGE32:
+		if (cmd32 == MPSIO_READ_EXT_CFG_HEADER32)
+			cmd = MPSIO_READ_EXT_CFG_HEADER;
+		else
+			cmd = MPSIO_READ_EXT_CFG_PAGE;
+		CP(*ext32, arg.ext, header);
+		CP(*ext32, arg.ext, page_address);
+		PTRIN_CP(*ext32, arg.ext, buf);
+		CP(*ext32, arg.ext, len);
+		CP(*ext32, arg.ext, ioc_status);
+		break;
+
+	case MPSIO_RAID_ACTION32:
+		cmd = MPSIO_RAID_ACTION;
+		CP(*raid32, arg.raid, action);
+		CP(*raid32, arg.raid, volume_bus);
+		CP(*raid32, arg.raid, volume_id);
+		CP(*raid32, arg.raid, phys_disk_num);
+		CP(*raid32, arg.raid, action_data_word);
+		PTRIN_CP(*raid32, arg.raid, buf);
+		CP(*raid32, arg.raid, len);
+		CP(*raid32, arg.raid, volume_status);
+		bcopy(raid32->action_data, arg.raid.action_data,
+		    sizeof arg.raid.action_data);
+		CP(*raid32, arg.raid, ioc_status);
+		CP(*raid32, arg.raid, write);
+		break;
+
+	case MPSIO_MPS_COMMAND32:
+		cmd = MPSIO_MPS_COMMAND;
+		PTRIN_CP(*user32, arg.user, req);
+		CP(*user32, arg.user, req_len);
+		PTRIN_CP(*user32, arg.user, rpl);
+		CP(*user32, arg.user, rpl_len);
+		PTRIN_CP(*user32, arg.user, buf);
+		CP(*user32, arg.user, len);
+		CP(*user32, arg.user, flags);
+		break;
+	default:
+		return (ENOIOCTL);
+	}
+
+	error = mps_ioctl(dev, cmd, &arg, flag, td);
+	if (error == 0 && (cmd32 & IOC_OUT) != 0) {
+		switch (cmd32) {
+		case MPSIO_READ_CFG_HEADER32:
+		case MPSIO_READ_CFG_PAGE32:
+		case MPSIO_WRITE_CFG_PAGE32:
+			CP(arg.page, *page32, header);
+			CP(arg.page, *page32, page_address);
+			PTROUT_CP(arg.page, *page32, buf);
+			CP(arg.page, *page32, len);
+			CP(arg.page, *page32, ioc_status);
+			break;
+
+		case MPSIO_READ_EXT_CFG_HEADER32:
+		case MPSIO_READ_EXT_CFG_PAGE32:
+			CP(arg.ext, *ext32, header);
+			CP(arg.ext, *ext32, page_address);
+			PTROUT_CP(arg.ext, *ext32, buf);
+			CP(arg.ext, *ext32, len);
+			CP(arg.ext, *ext32, ioc_status);
+			break;
+
+		case MPSIO_RAID_ACTION32:
+			CP(arg.raid, *raid32, action);
+			CP(arg.raid, *raid32, volume_bus);
+			CP(arg.raid, *raid32, volume_id);
+			CP(arg.raid, *raid32, phys_disk_num);
+			CP(arg.raid, *raid32, action_data_word);
+			PTROUT_CP(arg.raid, *raid32, buf);
+			CP(arg.raid, *raid32, len);
+			CP(arg.raid, *raid32, volume_status);
+			bcopy(arg.raid.action_data, raid32->action_data,
+			    sizeof arg.raid.action_data);
+			CP(arg.raid, *raid32, ioc_status);
+			CP(arg.raid, *raid32, write);
+			break;
+
+		case MPSIO_MPS_COMMAND32:
+			PTROUT_CP(arg.user, *user32, req);
+			CP(arg.user, *user32, req_len);
+			PTROUT_CP(arg.user, *user32, rpl);
+			CP(arg.user, *user32, rpl_len);
+			PTROUT_CP(arg.user, *user32, buf);
+			CP(arg.user, *user32, len);
+			CP(arg.user, *user32, flags);
+			break;
+		}
+	}
+
+	return (error);
+}
+#endif /* COMPAT_FREEBSD32 */
+
+static int
+mps_ioctl_devsw(struct cdev *dev, u_long com, caddr_t arg, int flag,
+    struct thread *td)
+{
+#ifdef COMPAT_FREEBSD32
+	if (SV_CURPROC_FLAG(SV_ILP32))
+		return (mps_ioctl32(dev, com, arg, flag, td));
+#endif
+	return (mps_ioctl(dev, com, arg, flag, td));
+}
diff -x .svn -urN sys/dev/mps/mpsvar.h ../../stable/8/sys/dev/mps/mpsvar.h
--- sys/dev/mps/mpsvar.h	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/dev/mps/mpsvar.h	2011-01-07 14:37:54.308555093 -0700
@@ -0,0 +1,390 @@
+/*-
+ * Copyright (c) 2009 Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD: stable/8/sys/dev/mps/mpsvar.h 212420 2010-09-10 15:03:56Z ken $
+ */
+
+#ifndef _MPSVAR_H
+#define _MPSVAR_H
+
+#define MPS_DB_MAX_WAIT		2500
+
+#define MPS_REQ_FRAMES		1024
+#define MPS_EVT_REPLY_FRAMES	32
+#define MPS_REPLY_FRAMES	MPS_REQ_FRAMES
+#define MPS_CHAIN_FRAMES	1024
+#define MPS_SENSE_LEN		SSD_FULL_SIZE
+#define MPS_MSI_COUNT		1
+#define MPS_SGE64_SIZE		12
+#define MPS_SGE32_SIZE		8
+#define MPS_SGC_SIZE		8
+
+#define MPS_PERIODIC_DELAY	1	/* 1 second heartbeat/watchdog check */
+
+struct mps_softc;
+struct mps_command;
+struct mpssas_softc;
+struct mpssas_target;
+
+MALLOC_DECLARE(M_MPT2);
+
+typedef void mps_evt_callback_t(struct mps_softc *, uintptr_t,
+    MPI2_EVENT_NOTIFICATION_REPLY *reply);
+typedef void mps_command_callback_t(struct mps_softc *, struct mps_command *cm);
+
+struct mps_chain {
+	TAILQ_ENTRY(mps_chain)		chain_link;
+	MPI2_SGE_IO_UNION		*chain;
+	uint32_t			chain_busaddr;
+};
+
+/*
+ * This needs to be at least 2 to support SMP passthrough.
+ */
+#define	MPS_IOVEC_COUNT	2
+
+struct mps_command {
+	TAILQ_ENTRY(mps_command)	cm_link;
+	struct mps_softc		*cm_sc;
+	void				*cm_data;
+	u_int				cm_length;
+	struct uio			cm_uio;
+	struct iovec			cm_iovec[MPS_IOVEC_COUNT];
+	u_int				cm_max_segs;
+	u_int				cm_sglsize;
+	MPI2_SGE_IO_UNION		*cm_sge;
+	uint8_t				*cm_req;
+	uint8_t				*cm_reply;
+	uint32_t			cm_reply_data;
+	mps_command_callback_t		*cm_complete;
+	void				*cm_complete_data;
+	struct mpssas_target		*cm_targ;
+	MPI2_REQUEST_DESCRIPTOR_UNION	cm_desc;
+	u_int				cm_flags;
+#define MPS_CM_FLAGS_POLLED		(1 << 0)
+#define MPS_CM_FLAGS_COMPLETE		(1 << 1)
+#define MPS_CM_FLAGS_SGE_SIMPLE		(1 << 2)
+#define MPS_CM_FLAGS_DATAOUT		(1 << 3)
+#define MPS_CM_FLAGS_DATAIN		(1 << 4)
+#define MPS_CM_FLAGS_WAKEUP		(1 << 5)
+#define MPS_CM_FLAGS_ACTIVE		(1 << 6)
+#define MPS_CM_FLAGS_USE_UIO		(1 << 7)
+#define MPS_CM_FLAGS_SMP_PASS		(1 << 8)
+	u_int				cm_state;
+#define MPS_CM_STATE_FREE		0
+#define MPS_CM_STATE_BUSY		1
+#define MPS_CM_STATE_TIMEDOUT		2
+	bus_dmamap_t			cm_dmamap;
+	struct scsi_sense_data		*cm_sense;
+	TAILQ_HEAD(, mps_chain)		cm_chain_list;
+	uint32_t			cm_req_busaddr;
+	uint32_t			cm_sense_busaddr;
+	struct callout			cm_callout;
+};
+
+struct mps_event_handle {
+	TAILQ_ENTRY(mps_event_handle)	eh_list;
+	mps_evt_callback_t		*callback;
+	void				*data;
+	uint8_t				mask[16];
+};
+
+struct mps_softc {
+	device_t			mps_dev;
+	struct cdev			*mps_cdev;
+	u_int				mps_flags;
+#define MPS_FLAGS_INTX		(1 << 0)
+#define MPS_FLAGS_MSI		(1 << 1)
+#define MPS_FLAGS_BUSY		(1 << 2)
+#define MPS_FLAGS_SHUTDOWN	(1 << 3)
+	u_int				mps_debug;
+	u_int				allow_multiple_tm_cmds;
+	int				tm_cmds_active;
+	struct sysctl_ctx_list		sysctl_ctx;
+	struct sysctl_oid		*sysctl_tree;
+	struct mps_command		*commands;
+	struct mps_chain		*chains;
+	struct callout			periodic;
+
+	struct mpssas_softc		*sassc;
+
+	TAILQ_HEAD(, mps_command)	req_list;
+	TAILQ_HEAD(, mps_chain)		chain_list;
+	TAILQ_HEAD(, mps_command)	tm_list;
+	int				replypostindex;
+	int				replyfreeindex;
+
+	struct resource			*mps_regs_resource;
+	bus_space_handle_t		mps_bhandle;
+	bus_space_tag_t			mps_btag;
+	int				mps_regs_rid;
+
+	bus_dma_tag_t			mps_parent_dmat;
+	bus_dma_tag_t			buffer_dmat;
+
+	MPI2_IOC_FACTS_REPLY		*facts;
+	MPI2_PORT_FACTS_REPLY		*pfacts;
+	int				num_reqs;
+	int				num_replies;
+	int				fqdepth;	/* Free queue */
+	int				pqdepth;	/* Post queue */
+
+	uint8_t				event_mask[16];
+	TAILQ_HEAD(, mps_event_handle)	event_list;
+	struct mps_event_handle		*mps_log_eh;
+
+	struct mtx			mps_mtx;
+	struct intr_config_hook		mps_ich;
+	struct resource			*mps_irq[MPS_MSI_COUNT];
+	void				*mps_intrhand[MPS_MSI_COUNT];
+	int				mps_irq_rid[MPS_MSI_COUNT];
+
+	uint8_t				*req_frames;
+	bus_addr_t			req_busaddr;
+	bus_dma_tag_t			req_dmat;
+	bus_dmamap_t			req_map;
+
+	uint8_t				*reply_frames;
+	bus_addr_t			reply_busaddr;
+	bus_dma_tag_t			reply_dmat;
+	bus_dmamap_t			reply_map;
+
+	struct scsi_sense_data		*sense_frames;
+	bus_addr_t			sense_busaddr;
+	bus_dma_tag_t			sense_dmat;
+	bus_dmamap_t			sense_map;
+
+	uint8_t				*chain_frames;
+	bus_addr_t			chain_busaddr;
+	bus_dma_tag_t			chain_dmat;
+	bus_dmamap_t			chain_map;
+
+	MPI2_REPLY_DESCRIPTORS_UNION	*post_queue;
+	bus_addr_t			post_busaddr;
+	uint32_t			*free_queue;
+	bus_addr_t			free_busaddr;
+	bus_dma_tag_t			queues_dmat;
+	bus_dmamap_t			queues_map;
+};
+
+struct mps_config_params {
+	MPI2_CONFIG_EXT_PAGE_HEADER_UNION	hdr;
+	u_int		action;
+	u_int		page_address;	/* Attributes, not a phys address */
+	u_int		status;
+	void		*buffer;
+	u_int		length;
+	int		timeout;
+	void		(*callback)(struct mps_softc *, struct mps_config_params *);
+	void		*cbdata;
+};
+
+static __inline uint32_t
+mps_regread(struct mps_softc *sc, uint32_t offset)
+{
+	return (bus_space_read_4(sc->mps_btag, sc->mps_bhandle, offset));
+}
+
+static __inline void
+mps_regwrite(struct mps_softc *sc, uint32_t offset, uint32_t val)
+{
+	bus_space_write_4(sc->mps_btag, sc->mps_bhandle, offset, val);
+}
+
+static __inline void
+mps_free_reply(struct mps_softc *sc, uint32_t busaddr)
+{
+
+	if (++sc->replyfreeindex >= sc->fqdepth)
+		sc->replyfreeindex = 0;
+	sc->free_queue[sc->replyfreeindex] = busaddr;
+	mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
+}
+
+static __inline struct mps_chain *
+mps_alloc_chain(struct mps_softc *sc)
+{
+	struct mps_chain *chain;
+
+	if ((chain = TAILQ_FIRST(&sc->chain_list)) != NULL)
+		TAILQ_REMOVE(&sc->chain_list, chain, chain_link);
+	return (chain);
+}
+
+static __inline void
+mps_free_chain(struct mps_softc *sc, struct mps_chain *chain)
+{
+#if 0
+	bzero(chain->chain, 128);
+#endif
+	TAILQ_INSERT_TAIL(&sc->chain_list, chain, chain_link);
+}
+
+static __inline void
+mps_free_command(struct mps_softc *sc, struct mps_command *cm)
+{
+	struct mps_chain *chain, *chain_temp;
+
+	if (cm->cm_reply != NULL) {
+		mps_free_reply(sc, cm->cm_reply_data);
+		cm->cm_reply = NULL;
+	}
+	cm->cm_flags = 0;
+	cm->cm_complete = NULL;
+	cm->cm_complete_data = NULL;
+	cm->cm_targ = 0;
+	cm->cm_max_segs = 0;
+	cm->cm_state = MPS_CM_STATE_FREE;
+	TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) {
+		TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link);
+		mps_free_chain(sc, chain);
+	}
+	TAILQ_INSERT_TAIL(&sc->req_list, cm, cm_link);
+}
+
+static __inline struct mps_command *
+mps_alloc_command(struct mps_softc *sc)
+{
+	struct mps_command *cm;
+
+	cm = TAILQ_FIRST(&sc->req_list);
+	if (cm == NULL)
+		return (NULL);
+
+	TAILQ_REMOVE(&sc->req_list, cm, cm_link);
+	KASSERT(cm->cm_state == MPS_CM_STATE_FREE, ("mps: Allocating busy command\n"));
+	cm->cm_state = MPS_CM_STATE_BUSY;
+	return (cm);
+}
+
+static __inline void
+mps_lock(struct mps_softc *sc)
+{
+	mtx_lock(&sc->mps_mtx);
+}
+
+static __inline void
+mps_unlock(struct mps_softc *sc)
+{
+	mtx_unlock(&sc->mps_mtx);
+}
+
+#define MPS_INFO	(1 << 0)
+#define MPS_TRACE	(1 << 1)
+#define MPS_FAULT	(1 << 2)
+#define MPS_EVENT	(1 << 3)
+#define MPS_LOG		(1 << 4)
+
+#define mps_printf(sc, args...)				\
+	device_printf((sc)->mps_dev, ##args)
+
+#define mps_dprint(sc, level, msg, args...)		\
+do {							\
+	if (sc->mps_debug & level)			\
+		device_printf(sc->mps_dev, msg, ##args);	\
+} while (0)
+
+#define mps_dprint_field(sc, level, msg, args...)		\
+do {								\
+	if (sc->mps_debug & level)				\
+		printf("\t" msg, ##args);			\
+} while (0)
+
+#define MPS_PRINTFIELD_START(sc, tag...)	\
+	mps_dprint((sc), MPS_INFO, ##tag);	\
+	mps_dprint_field((sc), MPS_INFO, ":\n")
+#define MPS_PRINTFIELD_END(sc, tag)		\
+	mps_dprint((sc), MPS_INFO, tag "\n")
+#define MPS_PRINTFIELD(sc, facts, attr, fmt)	\
+	mps_dprint_field((sc), MPS_INFO, #attr ": " #fmt "\n", (facts)->attr)
+
+#define MPS_EVENTFIELD_START(sc, tag...)	\
+	mps_dprint((sc), MPS_EVENT, ##tag);	\
+	mps_dprint_field((sc), MPS_EVENT, ":\n")
+#define MPS_EVENTFIELD(sc, facts, attr, fmt)	\
+	mps_dprint_field((sc), MPS_EVENT, #attr ": " #fmt "\n", (facts)->attr)
+
+static __inline void
+mps_from_u64(uint64_t data, U64 *mps)
+{
+	(mps)->High = (uint32_t)((data) >> 32);
+	(mps)->Low = (uint32_t)((data) & 0xffffffff);
+}
+
+static __inline uint64_t
+mps_to_u64(U64 *data)
+{
+
+	return (((uint64_t)data->High << 32) | data->Low);
+}
+
+static __inline void
+mps_mask_intr(struct mps_softc *sc)
+{
+	uint32_t mask;
+
+	mask = mps_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET);
+	mask |= MPI2_HIM_REPLY_INT_MASK;
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask);
+}
+
+static __inline void
+mps_unmask_intr(struct mps_softc *sc)
+{
+	uint32_t mask;
+
+	mask = mps_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET);
+	mask &= ~MPI2_HIM_REPLY_INT_MASK;
+	mps_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask);
+}
+
+int mps_pci_setup_interrupts(struct mps_softc *);
+int mps_attach(struct mps_softc *sc);
+int mps_free(struct mps_softc *sc);
+void mps_intr(void *);
+void mps_intr_msi(void *);
+void mps_intr_locked(void *);
+int mps_register_events(struct mps_softc *, uint8_t *, mps_evt_callback_t *,
+    void *, struct mps_event_handle **);
+int mps_update_events(struct mps_softc *, struct mps_event_handle *, uint8_t *);
+int mps_deregister_events(struct mps_softc *, struct mps_event_handle *);
+int mps_request_polled(struct mps_softc *sc, struct mps_command *cm);
+void mps_enqueue_request(struct mps_softc *, struct mps_command *);
+int mps_push_sge(struct mps_command *, void *, size_t, int);
+int mps_add_dmaseg(struct mps_command *, vm_paddr_t, size_t, u_int, int);
+int mps_attach_sas(struct mps_softc *sc);
+int mps_detach_sas(struct mps_softc *sc);
+int mps_map_command(struct mps_softc *sc, struct mps_command *cm);
+int mps_read_config_page(struct mps_softc *, struct mps_config_params *);
+int mps_write_config_page(struct mps_softc *, struct mps_config_params *);
+void mps_memaddr_cb(void *, bus_dma_segment_t *, int , int );
+void mpi_init_sge(struct mps_command *cm, void *req, void *sge);
+int mps_attach_user(struct mps_softc *);
+void mps_detach_user(struct mps_softc *);
+
+SYSCTL_DECL(_hw_mps);
+
+#endif
+
diff -x .svn -urN sys/dev/siba/siba_bwn.c ../../stable/8/sys/dev/siba/siba_bwn.c
--- sys/dev/siba/siba_bwn.c	2011-01-07 15:00:45.469801884 -0700
+++ ../../stable/8/sys/dev/siba/siba_bwn.c	2011-01-07 14:37:44.836153655 -0700
@@ -326,7 +326,7 @@
 siba_bwn_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
 {
 	struct siba_dev_softc *sd;
-	struct siba_softc *siba;;
+	struct siba_softc *siba;
 
 	sd = device_get_ivars(child);
 	siba = sd->sd_bus;
diff -x .svn -urN sys/dev/sis/if_sisreg.h ../../stable/8/sys/dev/sis/if_sisreg.h
--- sys/dev/sis/if_sisreg.h	2011-01-07 15:00:36.994918194 -0700
+++ ../../stable/8/sys/dev/sis/if_sisreg.h	2011-01-07 14:37:44.596577947 -0700
@@ -497,7 +497,7 @@
 	int			sis_tx_prod;
 	int			sis_tx_cons;
 	int			sis_tx_cnt;
-	int			sis_rx_cons;;
+	int			sis_rx_cons;
 	bus_addr_t		sis_rx_paddr;
 	bus_addr_t		sis_tx_paddr;
 	struct callout		sis_stat_ch;
diff -x .svn -urN sys/mips/mips/mp_machdep.c ../../stable/8/sys/mips/mips/mp_machdep.c
--- sys/mips/mips/mp_machdep.c	2011-01-07 15:00:11.980853153 -0700
+++ ../../stable/8/sys/mips/mips/mp_machdep.c	2011-01-07 14:37:44.269017853 -0700
@@ -165,7 +165,7 @@
 #if 0
 		case IPI_HARDCLOCK:
 			CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
-			hardclockintr();;
+			hardclockintr();
 			break;
 #endif
 		default:
diff -x .svn -urN sys/modules/Makefile ../../stable/8/sys/modules/Makefile
--- sys/modules/Makefile	2011-02-16 10:02:33.828579762 -0700
+++ ../../stable/8/sys/modules/Makefile	2011-02-16 10:08:41.397265959 -0700
@@ -186,6 +186,7 @@
 	mmc \
 	mmcsd \
 	${_mpt} \
+	mps \
 	mqueue \
 	msdosfs \
 	msdosfs_iconv \
diff -x .svn -urN sys/modules/mps/Makefile ../../stable/8/sys/modules/mps/Makefile
--- sys/modules/mps/Makefile	1969-12-31 17:00:00.000000000 -0700
+++ ../../stable/8/sys/modules/mps/Makefile	2011-02-16 10:24:45.658558415 -0700
@@ -0,0 +1,14 @@
+# $FreeBSD: stable/8/sys/modules/mps/Makefile 212420 2010-09-10 15:03:56Z ken $
+
+.PATH: ${.CURDIR}/../../dev/mps
+
+KMOD=	mps
+SRCS=	mps_pci.c mps.c mps_sas.c mps_table.c mps_user.c
+SRCS+=	opt_compat.h
+SRCS+=	opt_cam.h
+SRCS+=	device_if.h bus_if.h pci_if.h
+
+#CFLAGS += -DMPS_DEBUG
+DEBUG += -g
+
+.include <bsd.kmod.mk>

--qMm9M+Fa2AknHoGS--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110216203542.GA41226>