From 6d5d3999fb74e925fe43f0ca010db1d404813d7b Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Tue, 7 Feb 2012 06:38:38 +0100
Subject: [PATCH] mps(4): Sync with FreeBSD.

---
 share/man/man4/mps.4                  |   32 +-
 sys/conf/files                        |   13 +-
 sys/dev/disk/Makefile                 |    2 +-
 sys/dev/disk/mps/Makefile             |   10 -
 sys/dev/disk/mps/mpi/mpi2.h           | 1120 ------------
 sys/dev/disk/mps/mpi/mpi2_cnfg.h      | 2645 ---------------------------
 sys/dev/disk/mps/mpi/mpi2_hbd.h       |  112 --
 sys/dev/disk/mps/mpi/mpi2_history.txt |  381 ----
 sys/dev/disk/mps/mpi/mpi2_init.h      |  452 -----
 sys/dev/disk/mps/mpi/mpi2_ioc.h       | 1413 --------------
 sys/dev/disk/mps/mpi/mpi2_ra.h        |   84 -
 sys/dev/disk/mps/mpi/mpi2_raid.h      |  301 ---
 sys/dev/disk/mps/mpi/mpi2_sas.h       |  283 ---
 sys/dev/disk/mps/mpi/mpi2_targ.h      |  440 -----
 sys/dev/disk/mps/mpi/mpi2_tool.h      |  390 ----
 sys/dev/disk/mps/mpi/mpi2_type.h      |   98 -
 sys/dev/disk/mps/mps.c                | 1814 ------------------
 sys/dev/disk/mps/mps_ioctl.h          |  106 --
 sys/dev/disk/mps/mps_pci.c            |  370 ----
 sys/dev/disk/mps/mps_sas.c            | 2016 --------------------
 sys/dev/disk/mps/mps_table.c          |  495 -----
 sys/dev/disk/mps/mps_table.h          |   53 -
 sys/dev/disk/mps/mps_user.c           |  943 ----------
 sys/dev/disk/mps/mpsvar.h             |  389 ----
 sys/dev/raid/Makefile                 |    2 +-
 sys/dev/raid/mps/Makefile             |   14 +
 sys/dev/raid/mps/mpi/mpi2.h           | 1162 ++++++++++++
 sys/dev/raid/mps/mpi/mpi2_cnfg.h      | 2886 +++++++++++++++++++++++++++++
 sys/dev/raid/mps/mpi/mpi2_hbd.h       |  140 ++
 sys/dev/raid/mps/mpi/mpi2_history.txt |  476 +++++
 sys/dev/raid/mps/mpi/mpi2_init.h      |  479 +++++
 sys/dev/raid/mps/mpi/mpi2_ioc.h       | 1565 ++++++++++++++++
 sys/dev/raid/mps/mpi/mpi2_ra.h        |  113 ++
 sys/dev/raid/mps/mpi/mpi2_raid.h      |  332 ++++
 sys/dev/raid/mps/mpi/mpi2_sas.h       |  316 ++++
 sys/dev/raid/mps/mpi/mpi2_targ.h      |  473 +++++
 sys/dev/raid/mps/mpi/mpi2_tool.h      |  467 +++++
 sys/dev/raid/mps/mpi/mpi2_type.h      |  127 ++
 sys/dev/raid/mps/mps.c                | 2298 +++++++++++++++++++++++
 sys/dev/raid/mps/mps_config.c         | 1390 ++++++++++++++
 sys/dev/raid/mps/mps_ioctl.h          |  387 ++++
 sys/dev/raid/mps/mps_mapping.c        | 2265 +++++++++++++++++++++++
 sys/dev/raid/mps/mps_mapping.h        |   71 +
 sys/dev/raid/mps/mps_pci.c            |  344 ++++
 sys/dev/raid/mps/mps_sas.c            | 3234 +++++++++++++++++++++++++++++++++
 sys/dev/raid/mps/mps_sas.h            |  161 ++
 sys/dev/raid/mps/mps_sas_lsi.c        |  862 +++++++++
 sys/dev/raid/mps/mps_table.c          |  500 +++++
 sys/dev/raid/mps/mps_table.h          |   53 +
 sys/dev/raid/mps/mps_user.c           | 2399 ++++++++++++++++++++++++
 sys/dev/raid/mps/mpsvar.h             |  768 ++++++++
 51 files changed, 23308 insertions(+), 13938 deletions(-)
 delete mode 100644 sys/dev/disk/mps/Makefile
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_cnfg.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_hbd.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_history.txt
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_init.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_ioc.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_ra.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_raid.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_sas.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_targ.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_tool.h
 delete mode 100644 sys/dev/disk/mps/mpi/mpi2_type.h
 delete mode 100644 sys/dev/disk/mps/mps.c
 delete mode 100644 sys/dev/disk/mps/mps_ioctl.h
 delete mode 100644 sys/dev/disk/mps/mps_pci.c
 delete mode 100644 sys/dev/disk/mps/mps_sas.c
 delete mode 100644 sys/dev/disk/mps/mps_table.c
 delete mode 100644 sys/dev/disk/mps/mps_table.h
 delete mode 100644 sys/dev/disk/mps/mps_user.c
 delete mode 100644 sys/dev/disk/mps/mpsvar.h
 create mode 100644 sys/dev/raid/mps/Makefile
 create mode 100644 sys/dev/raid/mps/mpi/mpi2.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_cnfg.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_hbd.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_history.txt
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_init.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_ioc.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_ra.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_raid.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_sas.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_targ.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_tool.h
 create mode 100644 sys/dev/raid/mps/mpi/mpi2_type.h
 create mode 100644 sys/dev/raid/mps/mps.c
 create mode 100644 sys/dev/raid/mps/mps_config.c
 create mode 100644 sys/dev/raid/mps/mps_ioctl.h
 create mode 100644 sys/dev/raid/mps/mps_mapping.c
 create mode 100644 sys/dev/raid/mps/mps_mapping.h
 create mode 100644 sys/dev/raid/mps/mps_pci.c
 create mode 100644 sys/dev/raid/mps/mps_sas.c
 create mode 100644 sys/dev/raid/mps/mps_sas.h
 create mode 100644 sys/dev/raid/mps/mps_sas_lsi.c
 create mode 100644 sys/dev/raid/mps/mps_table.c
 create mode 100644 sys/dev/raid/mps/mps_table.h
 create mode 100644 sys/dev/raid/mps/mps_user.c
 create mode 100644 sys/dev/raid/mps/mpsvar.h

diff --git a/share/man/man4/mps.4 b/share/man/man4/mps.4
index 8516e19..bcdfa7e 100644
--- a/share/man/man4/mps.4
+++ b/share/man/man4/mps.4
@@ -32,7 +32,7 @@
 .\" Author: Ken Merry <ken@FreeBSD.org>
 .\"
 .\" $Id: //depot/SpectraBSD/head/share/man/man4/mps.4#4 $
-.\" $FreeBSD: src/share/man/man4/mps.4,v 1.3 2010/10/07 21:56:10 ken Exp $
+.\" $FreeBSD: src/share/man/man4/mps.4,v 1.5 2011/11/11 12:06:09 brueffer Exp $
 .\"
 .Dd September 13, 2010
 .Dt MPS 4
@@ -60,9 +60,9 @@ driver provides support for LSI Logic Fusion-MPT 2
 .Tn SAS
 controllers.
 .Sh HARDWARE
-The following controllers are supported by the
+The
 .Nm
-driver
+driver supports the following controllers:
 .Pp
 .Bl -bullet -compact
 .It
@@ -143,6 +143,19 @@ Enable prints for controller events.
 .Xr sa 4 ,
 .Xr scsi 4 ,
 .Xr targ 4
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was originally written by
+.An Scott Long Aq scottl@FreeBSD.org .
+This man page was written by
+.An Ken Merry Aq ken@FreeBSD.org .
 .Sh BUGS
 This driver is still in development, it has only been tested on the amd64
 architecture and has some known shortcomings:
@@ -158,16 +171,3 @@ times, without user intervention.
 .It
 The error recovery code isn't complete.
 .El
-.Sh HISTORY
-The
-.Nm
-driver first appeared in
-.Fx 9.0 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm
-driver was originally written by
-.An Scott Long Aq scottl@FreeBSD.org .
-This man page was written by
-.An Ken Merry Aq ken@FreeBSD.org .
diff --git a/sys/conf/files b/sys/conf/files
index 47314f3..cf01bf8 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -617,11 +617,14 @@ bus/mmc/mmc.c			optional mmc
 bus/mmc/mmcbr_if.m		standard
 bus/mmc/mmcbus_if.m		standard
 dev/disk/mmcsd/mmcsd.c		optional mmcsd
-dev/disk/mps/mps.c		optional mps
-dev/disk/mps/mps_pci.c		optional mps pci
-dev/disk/mps/mps_sas.c		optional mps
-dev/disk/mps/mps_table.c	optional mps
-dev/disk/mps/mps_user.c		optional mps
+dev/raid/mps/mps.c		optional mps
+dev/raid/mps/mps_config.c	optional mps
+dev/raid/mps/mps_mapping.c	optional mps
+dev/raid/mps/mps_pci.c		optional mps pci
+dev/raid/mps/mps_sas.c		optional mps
+dev/raid/mps/mps_sas_lsi.c	optional mps
+dev/raid/mps/mps_table.c	optional mps
+dev/raid/mps/mps_user.c		optional mps
 dev/disk/mpt/mpt.c		optional mpt
 dev/disk/mpt/mpt_cam.c		optional mpt
 dev/disk/mpt/mpt_debug.c	optional mpt
diff --git a/sys/dev/disk/Makefile b/sys/dev/disk/Makefile
index 66ef8ea..ca649a2 100644
--- a/sys/dev/disk/Makefile
+++ b/sys/dev/disk/Makefile
@@ -1,6 +1,6 @@
 .include "${.CURDIR}/../../platform/${MACHINE_PLATFORM}/Makefile.inc"
 
-SUBDIR= ahci aic aic7xxx ccd dm iscsi isp ispfw md mmcsd mps mpt ncv nsp
+SUBDIR= ahci aic aic7xxx ccd dm iscsi isp ispfw md mmcsd mpt ncv nsp
 SUBDIR+= sbp sdhci sili stg sym trm vn vpo
 
 .for dir in ${SUBDIR}
diff --git a/sys/dev/disk/mps/Makefile b/sys/dev/disk/mps/Makefile
deleted file mode 100644
index 77b1a1e..0000000
--- a/sys/dev/disk/mps/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD: src/sys/modules/mps/Makefile,v 1.3 2010/10/17 20:01:56 scottl Exp $
-
-KMOD=	mps
-SRCS=	mps_pci.c mps.c mps_sas.c mps_table.c mps_user.c
-SRCS+=	opt_mps.h opt_cam.h opt_compat.h
-SRCS+=	device_if.h bus_if.h pci_if.h
-
-#CFLAGS += -DMPS_DEBUG
-
-.include <bsd.kmod.mk>
diff --git a/sys/dev/disk/mps/mpi/mpi2.h b/sys/dev/disk/mps/mpi/mpi2.h
deleted file mode 100644
index e336234..0000000
--- a/sys/dev/disk/mps/mpi/mpi2.h
+++ /dev/null
@@ -1,1120 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_cnfg.h b/sys/dev/disk/mps/mpi/mpi2_cnfg.h
deleted file mode 100644
index 7c7ba2f..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_cnfg.h
+++ /dev/null
@@ -1,2645 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_cnfg.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_hbd.h b/sys/dev/disk/mps/mpi/mpi2_hbd.h
deleted file mode 100644
index c2d81e7..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_hbd.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_hbd.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_history.txt b/sys/dev/disk/mps/mpi/mpi2_history.txt
deleted file mode 100644
index 6247f92..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_history.txt
+++ /dev/null
@@ -1,381 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_history.txt,v 1.1 2010/09/10 15:03:56 ken Exp $ */
- ==============================
- 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 --git a/sys/dev/disk/mps/mpi/mpi2_init.h b/sys/dev/disk/mps/mpi/mpi2_init.h
deleted file mode 100644
index 7d0c435..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_init.h
+++ /dev/null
@@ -1,452 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_init.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_ioc.h b/sys/dev/disk/mps/mpi/mpi2_ioc.h
deleted file mode 100644
index c25b2f4..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_ioc.h
+++ /dev/null
@@ -1,1413 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_ioc.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_ra.h b/sys/dev/disk/mps/mpi/mpi2_ra.h
deleted file mode 100644
index 859925d..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_ra.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_ra.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_raid.h b/sys/dev/disk/mps/mpi/mpi2_raid.h
deleted file mode 100644
index d106352..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_raid.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_raid.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_sas.h b/sys/dev/disk/mps/mpi/mpi2_sas.h
deleted file mode 100644
index 2d2e469..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_sas.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_sas.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_targ.h b/sys/dev/disk/mps/mpi/mpi2_targ.h
deleted file mode 100644
index b1d8ab3..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_targ.h
+++ /dev/null
@@ -1,440 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_targ.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_tool.h b/sys/dev/disk/mps/mpi/mpi2_tool.h
deleted file mode 100644
index c827e3a..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_tool.h
+++ /dev/null
@@ -1,390 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_tool.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mpi/mpi2_type.h b/sys/dev/disk/mps/mpi/mpi2_type.h
deleted file mode 100644
index fca0fa6..0000000
--- a/sys/dev/disk/mps/mpi/mpi2_type.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* $FreeBSD: src/sys/dev/mps/mpi/mpi2_type.h,v 1.1 2010/09/10 15:03:56 ken Exp $ */
-/*
- *  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 --git a/sys/dev/disk/mps/mps.c b/sys/dev/disk/mps/mps.c
deleted file mode 100644
index 013cca8..0000000
--- a/sys/dev/disk/mps/mps.c
+++ /dev/null
@@ -1,1814 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mps.c,v 1.9 2010/12/10 21:45:10 ken Exp $
- */
-
-/* Communications core for LSI MPT2 */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.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 <sys/rman.h>
-
-#include <bus/cam/scsi/scsi_all.h>
-
-#include <dev/disk/mps/mpi/mpi2_type.h>
-#include <dev/disk/mps/mpi/mpi2.h>
-#include <dev/disk/mps/mpi/mpi2_ioc.h>
-#include <dev/disk/mps/mpi/mpi2_cnfg.h>
-#include <dev/disk/mps/mpsvar.h>
-#include <dev/disk/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_second;
-
-	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 */
-                                &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 */
-                                &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 */
-                                &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 */
-                                &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 */
-                                &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 = kmalloc(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 */
-                                &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 = kmalloc(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);
-
-		/* 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.
-	 */
-	ksnprintf(tmpstr, sizeof(tmpstr), "hw.mps.%d.debug_level",
-	    device_get_unit(sc->mps_dev));
-	TUNABLE_INT_FETCH(tmpstr, &sc->mps_debug);
-	ksnprintf(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__);
-
-	lockinit(&sc->mps_lock, "MPT2SAS lock", 0, LK_CANRECURSE);
-	callout_init(&sc->periodic);
-	TAILQ_INIT(&sc->event_list);
-
-	/*
-	 * Setup the sysctl variable so the user can change the debug level
-	 * on the fly.
-	 */
-	ksnprintf(tmpstr, sizeof(tmpstr), "MPS controller %d",
-	    device_get_unit(sc->mps_dev));
-	ksnprintf(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 = kmalloc(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",
-	    (u_int)(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 = kmalloc(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);
-#if 0 /* XXX swildner */
-	/* Lock must not be held for this */
-	callout_drain(&sc->periodic);
-#endif
-
-	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)
-		kfree(sc->facts, M_MPT2);
-
-	if (sc->pfacts != NULL)
-		kfree(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)
-		kfree(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);
-		}
-		kfree(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);
-
-	lockuninit(&sc->mps_lock);
-
-	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)))) {
-				kprintf("%s: WARNING: reply %p out of range!\n",
-				       __func__, reply);
-				kprintf("%s: reply_frames %p, fqdepth %d, "
-				       "frame size %d\n", __func__,
-				       sc->reply_frames, sc->fqdepth,
-				       sc->facts->ReplyFrameSize * 4);
-				kprintf("%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 = kmalloc(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);
-	kfree(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,
-			    (u_int)(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);
-		lksleep(cm, &sc->mps_lock, 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 --git a/sys/dev/disk/mps/mps_ioctl.h b/sys/dev/disk/mps/mps_ioctl.h
deleted file mode 100644
index d804d05..0000000
--- a/sys/dev/disk/mps/mps_ioctl.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mps_ioctl.h,v 1.2 2010/10/11 21:26:24 mdf Exp $
- */
-
-#ifndef _MPS_IOCTL_H_
-#define	_MPS_IOCTL_H_
-
-#include <dev/disk/mps/mpi/mpi2_type.h>
-#include <dev/disk/mps/mpi/mpi2.h>
-#include <dev/disk/mps/mpi/mpi2_cnfg.h>
-#include <dev/disk/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 --git a/sys/dev/disk/mps/mps_pci.c b/sys/dev/disk/mps/mps_pci.c
deleted file mode 100644
index 3b4642d..0000000
--- a/sys/dev/disk/mps/mps_pci.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mps_pci.c,v 1.2 2010/11/30 22:39:46 ken Exp $
- */
-
-/* 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 <sys/rman.h>
-#include <sys/lock.h>
-
-#include <bus/pci/pcireg.h>
-#include <bus/pci/pcivar.h>
-
-#include <dev/disk/mps/mpi/mpi2_type.h>
-#include <dev/disk/mps/mpi/mpi2.h>
-#include <dev/disk/mps/mpi/mpi2_ioc.h>
-#include <dev/disk/mps/mpi/mpi2_cnfg.h>
-
-#include <dev/disk/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 *);
-#ifdef OLD_MSI
-static int	mps_alloc_msix(struct mps_softc *sc, int msgs);
-static int	mps_alloc_msi(struct mps_softc *sc, int msgs);
-#endif
-
-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, NULL, NULL);
-
-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 */
-				&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;
-#ifdef OLD_MSI
-	int msgs;
-#endif
-
-	dev = sc->mps_dev;
-	error = ENXIO;
-#ifdef OLD_MSI
-	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);
-#endif
-
-	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_MPSAFE, mps_intr, sc,
-		    &sc->mps_intrhand[0], NULL);
-		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_MPSAFE, mps_intr_msi,
-			    sc, &sc->mps_intrhand[i], NULL);
-			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);
-}
-
-#ifdef OLD_MSI
-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);
-}
-#endif
diff --git a/sys/dev/disk/mps/mps_sas.c b/sys/dev/disk/mps/mps_sas.c
deleted file mode 100644
index bc34cec..0000000
--- a/sys/dev/disk/mps/mps_sas.c
+++ /dev/null
@@ -1,2016 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mps_sas.c,v 1.7 2010/12/11 00:36:35 ken Exp $
- */
-
-/* Communications core for LSI MPT2 */
-
-#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/bio.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
-#include <sys/sysctl.h>
-#include <sys/endian.h>
-
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/globaldata.h>
-
-#include <bus/cam/cam.h>
-#include <bus/cam/cam_ccb.h>
-#include <bus/cam/cam_debug.h>
-#include <bus/cam/cam_sim.h>
-#include <bus/cam/cam_xpt_sim.h>
-#include <bus/cam/cam_xpt_periph.h>
-#include <bus/cam/cam_periph.h>
-#include <bus/cam/scsi/scsi_all.h>
-#include <bus/cam/scsi/scsi_message.h>
-#if __FreeBSD_version >= 900026
-#include <bus/cam/scsi/smp_all.h>
-#endif
-
-#include <dev/disk/mps/mpi/mpi2_type.h>
-#include <dev/disk/mps/mpi/mpi2.h>
-#include <dev/disk/mps/mpi/mpi2_ioc.h>
-#include <dev/disk/mps/mpi/mpi2_sas.h>
-#include <dev/disk/mps/mpi/mpi2_cnfg.h>
-#include <dev/disk/mps/mpi/mpi2_init.h>
-#include <dev/disk/mps/mpsvar.h>
-#include <dev/disk/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_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
-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 = kmalloc(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) {
-		kfree(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);
-			kfree(probe, M_MPSSAS);
-			return;
-		}
-		params->action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-		params->length = hdr->ExtPageLength * 4;
-		params->buffer = kmalloc(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);
-			kfree(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);
-			kfree(params->buffer, M_MPSSAS);
-			kfree(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;
-		kfree(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);
-			kfree(params->buffer, M_MPSSAS);
-			kfree(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;
-		}
-		kfree(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);
-			kfree(probe, M_MPSSAS);
-			return;
-		}
-		if ((targ = mpssas_alloc_target(sassc, &probe->target)) == NULL) {
-			mps_printf(sc, "Target table overflow, handle 0x%04x\n",
-			    handle);
-			kfree(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);
-
-		kfree(probe, M_MPSSAS);
-		mpssas_announce_device(sassc, targ);
-		break;
-	}
-	default:
-		kprintf("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, "command 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",
-	    (u_int)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)
-				kprintf("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 = kmalloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO);
-	sassc->targets = kmalloc(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_lock, 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, 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);
-	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);
-	}
-	mps_unlock(sc);
-
-	if (sassc->devq != NULL)
-		cam_simq_release(sassc->devq);
-
-	kfree(sassc->targets, M_MPT2);
-	kfree(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();
-	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_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/);
-	ccb->ccb_h.func_code = XPT_SCAN_BUS;
-	ccb->ccb_h.cbfcnp = mpssas_bus_scan_cb;
-	ccb->crcn.flags = CAM_FLAG_NONE;
-	xpt_action(ccb);
-}
-
-static void
-mpssas_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
-{
-	xpt_free_path(ccb->ccb_h.path);
-	kfree(ccb, M_TEMP);
-}
-
-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 == NULL)
-		/* 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;
-
-	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
-
-	/*
-	 * 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;
-
-	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
-
-	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, (u_int)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;
-
-	kprintf("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 --git a/sys/dev/disk/mps/mps_table.c b/sys/dev/disk/mps/mps_table.c
deleted file mode 100644
index adffe50..0000000
--- a/sys/dev/disk/mps/mps_table.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mps_table.c,v 1.1 2010/09/10 15:03:56 ken Exp $
- */
-
-/* Debugging tables for MPT2 */
-
-#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/bio.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
-#include <sys/sysctl.h>
-
-#include <sys/rman.h>
-#include <sys/lock.h>
-
-#include <bus/cam/scsi/scsi_all.h>
-
-#include <dev/disk/mps/mpi/mpi2_type.h>
-#include <dev/disk/mps/mpi/mpi2.h>
-#include <dev/disk/mps/mpi/mpi2_ioc.h>
-#include <dev/disk/mps/mpi/mpi2_cnfg.h>
-#include <dev/disk/mps/mpi/mpi2_init.h>
-#include <dev/disk/mps/mpsvar.h>
-#include <dev/disk/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)
-{
-	ksnprintf(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",
-	    (u_int)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_dprint_field(sc, MPS_EVENT, "EventContext: 0x%x\n",
-	    (u_int)event->EventContext);
-}
-
-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",
-	    (u_int)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",
-		    (u_int)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_dprint_field(sc, MPS_EVENT, "PhyBits: 0x%x\n",
-		    (u_int)data->PhyBits);
-		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), (u_int)buf->PhyInfo);
-	mps_dprint_field(sc, MPS_INFO, "AttachedDeviceInfo: %b,%s\n",
-	    (u_int)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_dprint_field(sc, MPS_INFO, "DiscoveryInfo: 0x%x\n",
-	    (u_int)buf->DiscoveryInfo);
-	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo: 0x%x\n",
-	    (u_int)buf->AttachedPhyInfo);
-	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
-	    mps_describe_table(mps_phyinfo_reason_names,
-	    buf->AttachedPhyInfo & 0xf), (u_int)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), (u_int)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), (u_int)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];
-	kprintf("SGL for command %p\n", cm);
-
-	while (frame != NULL) {
-		flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT;
-		kprintf("seg%d flags=0x%x len=0x%lx 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;
-			kprintf("chain flags=0x%x len=0x%x Offset=0x%x "
-			    "Address=0x%x\n", sgc->Flags, sgc->Length,
-			    sgc->NextChainOffset, (u_int)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 --git a/sys/dev/disk/mps/mps_table.h b/sys/dev/disk/mps/mps_table.h
deleted file mode 100644
index 9c9f78c..0000000
--- a/sys/dev/disk/mps/mps_table.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mps_table.h,v 1.1 2010/09/10 15:03:56 ken Exp $
- */
-
-#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 --git a/sys/dev/disk/mps/mps_user.c b/sys/dev/disk/mps/mps_user.c
deleted file mode 100644
index 920eea7..0000000
--- a/sys/dev/disk/mps/mps_user.c
+++ /dev/null
@@ -1,943 +0,0 @@
-/*-
- * 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
- *
- * $FreeBSD: src/sys/dev/mps/mps_user.c,v 1.9 2010/11/30 22:39:46 ken Exp $
- */
-
-#include "opt_compat.h"
-
-#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/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 <sys/rman.h>
-#include <sys/device.h>
-
-#include <bus/cam/scsi/scsi_all.h>
-
-#include <dev/disk/mps/mpi/mpi2_type.h>
-#include <dev/disk/mps/mpi/mpi2.h>
-#include <dev/disk/mps/mpi/mpi2_ioc.h>
-#include <dev/disk/mps/mpi/mpi2_cnfg.h>
-#include <dev/disk/mps/mpsvar.h>
-#include <dev/disk/mps/mps_table.h>
-#include <dev/disk/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 dev_ops mps_ops = {
-	{ "mps", 0, 0 },
-	.d_open =	mps_open,
-	.d_close =	mps_close,
-	.d_ioctl =	mps_ioctl_devsw,
-};
-
-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_ops, 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);
-	dev_ops_remove_minor(&mps_ops, device_get_unit(sc->mps_dev));
-
-}
-
-static int
-mps_open(struct dev_open_args *ap)
-{
-
-	return (0);
-}
-
-static int
-mps_close(struct dev_close_args *ap)
-{
-
-	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 = kmalloc(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;
-	}
-	lksleep(cm, &sc->mps_lock, 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)
-		kfree(buf, M_MPSUSER);
-	return (err);
-}
-
-static int
-mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag)
-{
-	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 = kmalloc(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 = kmalloc(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 = kmalloc(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)
-		kfree(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 dev_ioctl_args *ap)
-{
-	cdev_t dev = ap->a_head.a_dev;
-	u_long com = ap->a_cmd;
-	caddr_t arg = ap->a_data;
-	int flag = ap->a_fflag;
-
-#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));
-}
diff --git a/sys/dev/disk/mps/mpsvar.h b/sys/dev/disk/mps/mpsvar.h
deleted file mode 100644
index b7461a3..0000000
--- a/sys/dev/disk/mps/mpsvar.h
+++ /dev/null
@@ -1,389 +0,0 @@
-/*-
- * 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: src/sys/dev/mps/mpsvar.h,v 1.5 2010/12/10 21:45:10 ken Exp $
- */
-
-#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 lock			mps_lock;
-	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_MUTABLE(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)
-{
-	lockmgr(&sc->mps_lock, LK_EXCLUSIVE);
-}
-
-static __inline void
-mps_unlock(struct mps_softc *sc)
-{
-	lockmgr(&sc->mps_lock, LK_RELEASE);
-}
-
-#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)				\
-		kprintf("\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 --git a/sys/dev/raid/Makefile b/sys/dev/raid/Makefile
index 3ce204e..44461cd 100644
--- a/sys/dev/raid/Makefile
+++ b/sys/dev/raid/Makefile
@@ -1,4 +1,4 @@
 SUBDIR=	aac amr arcmsr asr ciss hptiop hptmv \
-	iir ips mfi mlx mly pst twa twe tws vinum
+	iir ips mfi mlx mly mps pst twa twe tws vinum
 
 .include <bsd.subdir.mk>
diff --git a/sys/dev/raid/mps/Makefile b/sys/dev/raid/mps/Makefile
new file mode 100644
index 0000000..57e8bb6
--- /dev/null
+++ b/sys/dev/raid/mps/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD: src/sys/modules/mps/Makefile,v 1.4 2012/01/26 18:17:21 ken Exp $
+
+.PATH: ${.CURDIR}/../../dev/mps
+
+KMOD=	mps
+SRCS=	mps_pci.c mps.c mps_sas.c mps_table.c mps_user.c
+SRCS+=	mps_config.c mps_mapping.c mps_sas_lsi.c
+SRCS+=	opt_cam.h opt_compat.h
+SRCS+=	device_if.h bus_if.h pci_if.h
+
+#CFLAGS += -DMPS_DEBUG
+DEBUG_FLAGS += -g
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/raid/mps/mpi/mpi2.h b/sys/dev/raid/mps/mpi/mpi2.h
new file mode 100644
index 0000000..4196be7
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2.h
@@ -0,0 +1,1162 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 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.18
+ *
+ *  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.
+ *  02-10-10  02.00.15  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
+ *                      Added defines for product-specific range of message
+ *                      function codes, 0xF0 to 0xFF.
+ *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added alternative defines for the SGE Direction bit.
+ *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  11-10-10  02.00.18  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
+ *  --------------------------------------------------------------------------
+ */
+
+#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            (0x12)
+#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
+*
+*****************************************************************************/
+
+#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 */
+#define MPI2_FUNCTION_PWR_MGMT_CONTROL              (0x30) /* Power Management Control */
+#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC          (0xF0) /* beginning of product-specific range */
+#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC          (0xFF) /* end of product-specific range */
+
+
+
+/* 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)
+
+#define MPI2_SGE_FLAGS_DEST                     (MPI2_SGE_FLAGS_IOC_TO_HOST)
+#define MPI2_SGE_FLAGS_SOURCE                   (MPI2_SGE_FLAGS_HOST_TO_IOC)
+
+/* 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) /* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01) /* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03) /* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR   (0x03) /* IEEE Chain Element only */
+
+/****************************************************************************
+*  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 --git a/sys/dev/raid/mps/mpi/mpi2_cnfg.h b/sys/dev/raid/mps/mpi/mpi2_cnfg.h
new file mode 100644
index 0000000..fc0f6d8
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_cnfg.h
@@ -0,0 +1,2886 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_cnfg.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_cnfg.h
+ *          Title:  MPI Configuration messages and pages
+ *  Creation Date:  November 10, 2006
+ *
+ *    mpi2_cnfg.h Version:  02.00.17
+ *
+ *  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.
+ *  02-10-10  02.00.14  Modified the comments for the configuration page
+ *                      structures that contain an array of data. The host
+ *                      should use the "count" field in the page data (e.g. the
+ *                      NumPhys field) to determine the number of valid elements
+ *                      in the array.
+ *                      Added/modified some MPI2_MFGPAGE_DEVID_SAS defines.
+ *                      Added PowerManagementCapabilities to IO Unit Page 7.
+ *                      Added PortWidthModGroup field to
+ *                      MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS.
+ *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
+ *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
+ *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
+ *  05-12-10  02.00.15  Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
+ *                      define.
+ *                      Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
+ *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
+ *  08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
+ *                      defines.
+ *  11-10-10  02.00.17  Added ReceptacleID field (replacing Reserved1) to
+ *                      MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ *                      the Pinout field.
+ *                      Added BoardTemperature and BoardTemperatureUnits fields
+ *                      to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ *                      Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ *                      and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
+ *  --------------------------------------------------------------------------
+ */
+
+#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)
+#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING   (0x1A)
+
+
+/*****************************************************************************
+*   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)
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+/* 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_SSS6200                  (0x007E)
+
+#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_SAS2308_1                (0x0086)
+#define MPI2_MFGPAGE_DEVID_SAS2308_2                (0x0087)
+#define MPI2_MFGPAGE_DEVID_SAS2308_3                (0x006E)
+
+
+
+
+/* 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 the value returned for 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                          ReceptacleID;           /* 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_LANE_MASK                  (0x0000FF00)
+#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT                 (8)
+
+#define MPI2_MANPAGE7_PINOUT_TYPE_MASK                  (0x000000FF)
+#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN               (0x00)
+#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE                (0x01)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482                   (0x02)
+#define MPI2_MANPAGE7_PINOUT_SFF_8486                   (0x03)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484                   (0x04)
+#define MPI2_MANPAGE7_PINOUT_SFF_8087                   (0x05)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I                (0x06)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I                (0x07)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470                   (0x08)
+#define MPI2_MANPAGE7_PINOUT_SFF_8088                   (0x09)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X                (0x0A)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X                (0x0B)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X               (0x0C)
+#define MPI2_MANPAGE7_PINOUT_SFF_8436                   (0x0D)
+
+/* 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 the value returned for 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                 (0x01)
+
+/* 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_SATA_WRITE_CACHE_SHIFT         (9)
+#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)
+
+
+/* IO Unit Page 3 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for GPIOCount 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 the value returned for 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                     PowerManagementCapabilities;            /* 0x0C */
+    U16                     IOCTemperature;                         /* 0x10 */
+    U8                      IOCTemperatureUnits;                    /* 0x12 */
+    U8                      IOCSpeed;                               /* 0x13 */
+    U16                     BoardTemperature;                       /* 0x14 */
+    U8                      BoardTemperatureUnits;                  /* 0x16 */
+    U8                      Reserved3;                              /* 0x17 */
+} 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                    (0x02)
+
+/* 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 PowerManagementCapabilities field */
+#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED    (0x00000400)
+#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED    (0x00000200)
+#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED    (0x00000100)
+#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE    (0x00000008)
+#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE    (0x00000004)
+
+/* 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)
+
+/* defines for IO Unit Page 7 BoardTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT     (0x00)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT      (0x01)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS         (0x02)
+
+
+
+/****************************************************************************
+*   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 the value returned for 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 the value returned for NumPhysDisks 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_VOL_NOT_CONSISTENT        (0x00000080)
+#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_MEDIA_TYPE          (0x06)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN             (0xFF)
+
+/* PhysDiskAttributes defines */
+#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK                (0x0C)
+#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE         (0x08)
+#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE           (0x04)
+
+#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK             (0x03)
+#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 the value returned for 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_UNSUPPORTED_PHY          (0x06)
+#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_SHIFT_PHY_POWER_CONDITION      (27)
+#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 the value returned for 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 the value returned for 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
+ * one and check the value returned for 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          PortWidthModGroup;          /* 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 PortWidthModeGroup field */
+#define MPI2_SASIOUNIT5_PWMG_DISABLE                    (0xFF)
+
+/* 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 the value returned for 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     (0x01)
+
+
+/* SAS IO Unit Page 6 */
+
+typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
+{
+    U8          CurrentStatus;              /* 0x00 */
+    U8          CurrentModulation;          /* 0x01 */
+    U8          CurrentUtilization;         /* 0x02 */
+    U8          Reserved1;                  /* 0x03 */
+    U32         Reserved2;                  /* 0x04 */
+} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
+  MPI2_POINTER PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
+  Mpi2SasIOUnit6PortWidthModGroupStatus_t,
+  MPI2_POINTER pMpi2SasIOUnit6PortWidthModGroupStatus_t;
+
+/* defines for CurrentStatus field */
+#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE                      (0x00)
+#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED                     (0x01)
+#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG                   (0x02)
+#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN                        (0x03)
+#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY                 (0x04)
+#define MPI2_SASIOUNIT6_STATUS_INACTIVE                         (0x05)
+#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT                    (0x06)
+#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST                      (0x07)
+
+/* defines for CurrentModulation field */
+#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT                   (0x00)
+#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT                   (0x01)
+#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT                   (0x02)
+#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT                  (0x03)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumGroups at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
+#define MPI2_SAS_IOUNIT6_GROUP_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U32                                 Reserved2;                  /* 0x0C */
+    U8                                  NumGroups;                  /* 0x10 */
+    U8                                  Reserved3;                  /* 0x11 */
+    U16                                 Reserved4;                  /* 0x12 */
+    MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
+        PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /* 0x14 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_6,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
+  Mpi2SasIOUnitPage6_t, MPI2_POINTER pMpi2SasIOUnitPage6_t;
+
+#define MPI2_SASIOUNITPAGE6_PAGEVERSION     (0x00)
+
+
+/* SAS IO Unit Page 7 */
+
+typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
+{
+    U8          Flags;                      /* 0x00 */
+    U8          Reserved1;                  /* 0x01 */
+    U16         Reserved2;                  /* 0x02 */
+    U8          Threshold75Pct;             /* 0x04 */
+    U8          Threshold50Pct;             /* 0x05 */
+    U8          Threshold25Pct;             /* 0x06 */
+    U8          Reserved3;                  /* 0x07 */
+} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
+  MPI2_POINTER PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
+  Mpi2SasIOUnit7PortWidthModGroupSettings_t,
+  MPI2_POINTER pMpi2SasIOUnit7PortWidthModGroupSettings_t;
+
+/* defines for Flags field */
+#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION  (0x01)
+
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumGroups at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
+#define MPI2_SAS_IOUNIT7_GROUP_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER            Header;             /* 0x00 */
+    U8                                          SamplingInterval;   /* 0x08 */
+    U8                                          WindowLength;       /* 0x09 */
+    U16                                         Reserved1;          /* 0x0A */
+    U32                                         Reserved2;          /* 0x0C */
+    U32                                         Reserved3;          /* 0x10 */
+    U8                                          NumGroups;          /* 0x14 */
+    U8                                          Reserved4;          /* 0x15 */
+    U16                                         Reserved5;          /* 0x16 */
+    MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
+        PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX]; /* 0x18 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_7,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
+  Mpi2SasIOUnitPage7_t, MPI2_POINTER pMpi2SasIOUnitPage7_t;
+
+#define MPI2_SASIOUNITPAGE7_PAGEVERSION     (0x00)
+
+
+/* SAS IO Unit Page 8 */
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                             /* 0x00 */
+    U32                                 Reserved1;                          /* 0x08 */
+    U32                                 PowerManagementCapabilities;        /* 0x0C */
+    U32                                 Reserved2;                          /* 0x10 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_8,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8,
+  Mpi2SasIOUnitPage8_t, MPI2_POINTER pMpi2SasIOUnitPage8_t;
+
+#define MPI2_SASIOUNITPAGE8_PAGEVERSION     (0x00)
+
+/* defines for PowerManagementCapabilities field */
+#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD          (0x000001000)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE        (0x000000800)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE        (0x000000400)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE       (0x000000200)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE       (0x000000100)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD        (0x000000010)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE      (0x000000008)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE      (0x000000004)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE     (0x000000002)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE     (0x000000001)
+
+
+
+
+/****************************************************************************
+*   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 the value returned for 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 the value returned for 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 the value returned for NumLogEntries 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 the value returned for NumElements 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)
+
+
+/****************************************************************************
+*   Extended Manufacturing Config Pages
+****************************************************************************/
+
+/*
+ * Generic structure to use for product-specific extended manufacturing pages
+ * (currently Extended Manufacturing Page 40 through Extended Manufacturing
+ * Page 60).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS
+{
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+    U32                                 ProductSpecificInfo;    /* 0x08 */
+} MPI2_CONFIG_PAGE_EXT_MAN_PS,
+  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
+  Mpi2ExtManufacturingPagePS_t, MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
+
+/* PageVersion should be provided by product-specific code */
+
+#endif
diff --git a/sys/dev/raid/mps/mpi/mpi2_hbd.h b/sys/dev/raid/mps/mpi/mpi2_hbd.h
new file mode 100644
index 0000000..41ac3fb
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_hbd.h
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_hbd.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2009-2011 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.01
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  10-28-09  02.00.00  Initial version.
+ *  08-11-10  02.00.01  Removed PortGroups, DmaGroup, and ControlGroup from
+ *                      HBD Action request, replaced by AdditionalInfo field.
+ *  --------------------------------------------------------------------------
+ */
+
+#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 */
+    U32                     AdditionalInfo;     /* 0x28 */
+    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 --git a/sys/dev/raid/mps/mpi/mpi2_history.txt b/sys/dev/raid/mps/mpi/mpi2_history.txt
new file mode 100644
index 0000000..a87375f
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_history.txt
@@ -0,0 +1,476 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_history.txt,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+ ==============================
+ Fusion-MPT MPI 2.0 Header File Change History
+ ==============================
+
+ Copyright (c) 2000-2011 LSI Corporation.
+
+ ---------------------------------------
+ Header Set Release Version:    02.00.18
+ Header Set Release Date:       11-10-10
+ ---------------------------------------
+
+ Filename               Current version     Prior version
+ ----------             ---------------     -------------
+ mpi2.h                 02.00.18            02.00.17
+ mpi2_cnfg.h            02.00.17            02.00.16
+ mpi2_init.h            02.00.11            02.00.10
+ mpi2_ioc.h             02.00.16            02.00.15
+ mpi2_raid.h            02.00.05            02.00.05
+ mpi2_sas.h             02.00.05            02.00.05
+ mpi2_targ.h            02.00.04            02.00.04
+ mpi2_tool.h            02.00.06            02.00.06
+ mpi2_type.h            02.00.00            02.00.00
+ mpi2_ra.h              02.00.00            02.00.00
+ mpi2_hbd.h             02.00.01            02.00.01
+ mpi2_history.txt       02.00.18            02.00.17
+
+
+ *  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.
+ *  02-10-10  02.00.15  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
+ *                      Added defines for product-specific range of message
+ *                      function codes, 0xF0 to 0xFF.
+ *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added alternative defines for the SGE Direction bit.
+ *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  11-10-10  02.00.18  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  02-10-10  02.00.14  Modified the comments for the configuration page
+ *                      structures that contain an array of data. The host
+ *                      should use the "count" field in the page data (e.g. the
+ *                      NumPhys field) to determine the number of valid elements
+ *                      in the array.
+ *                      Added/modified some MPI2_MFGPAGE_DEVID_SAS defines.
+ *                      Added PowerManagementCapabilities to IO Unit Page 7.
+ *                      Added PortWidthModGroup field to
+ *                      MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS.
+ *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
+ *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
+ *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
+ *  05-12-10  02.00.15  Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
+ *                      define.
+ *                      Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
+ *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
+ *  08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
+ *                      defines.
+ *  11-10-10  02.00.17  Added ReceptacleID field (replacing Reserved1) to
+ *                      MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ *                      the Pinout field.
+ *                      Added BoardTemperature and BoardTemperatureUnits fields
+ *                      to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ *                      Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ *                      and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  02-10-10  02.00.09  Removed unused structure that had "#if 0" around it.
+ *  05-12-10  02.00.10  Added optional vendor-unique region to SCSI IO Request.
+ *  11-10-10  02.00.11  Added MPI2_SCSIIO_NUM_SGLOFFSETS 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_).
+ *  02-10-10  02.00.14  Added SAS Quiesce Event structure and defines.
+ *                      Added PowerManagementControl Request structures and
+ *                      defines.
+ *  05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
+ *                      Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ *  11-10-10  02.00.16  Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  05-12-10  02.00.04  Modified some comments.
+ *  08-11-10  02.00.05  Added NCQ operations to SAS IO Unit Control.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  02-10-10  02.00.04  Added comment to MPI2_TARGET_SSP_RSP_IU structure.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
+ *  08-11-10  02.00.06  Added defines that were missing for Diagnostic Buffer
+ *                      Post Request.
+ *  --------------------------------------------------------------------------
+
+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.
+ *  08-11-10  02.00.01  Removed PortGroups, DmaGroup, and ControlGroup from
+ *                      HBD Action request, replaced by AdditionalInfo field.
+ *  --------------------------------------------------------------------------
+
+
+mpi2_history.txt         Parts list history
+
+Filename     02.00.18
+----------   --------
+mpi2.h       02.00.18
+mpi2_cnfg.h  02.00.17
+mpi2_init.h  02.00.11
+mpi2_ioc.h   02.00.16
+mpi2_raid.h  02.00.05
+mpi2_sas.h   02.00.05
+mpi2_targ.h  02.00.04
+mpi2_tool.h  02.00.06
+mpi2_type.h  02.00.00
+mpi2_ra.h    02.00.00
+mpi2_hbd.h   02.00.01
+
+Filename     02.00.17  02.00.16  02.00.15  02.00.14  02.00.13  02.00.12
+----------   --------  --------  --------  --------  --------  --------
+mpi2.h       02.00.17  02.00.16  02.00.15  02.00.14  02.00.13  02.00.12
+mpi2_cnfg.h  02.00.16  02.00.15  02.00.14  02.00.13  02.00.12  02.00.11
+mpi2_init.h  02.00.10  02.00.10  02.00.09  02.00.08  02.00.07  02.00.07
+mpi2_ioc.h   02.00.15  02.00.15  02.00.14  02.00.13  02.00.12  02.00.11
+mpi2_raid.h  02.00.05  02.00.05  02.00.04  02.00.04  02.00.04  02.00.03
+mpi2_sas.h   02.00.05  02.00.04  02.00.03  02.00.03  02.00.02  02.00.02
+mpi2_targ.h  02.00.04  02.00.04  02.00.04  02.00.03  02.00.03  02.00.03
+mpi2_tool.h  02.00.06  02.00.05  02.00.04  02.00.04  02.00.04  02.00.03
+mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+mpi2_ra.h    02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+mpi2_hbd.h   02.00.01  02.00.00  02.00.00  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 --git a/sys/dev/raid/mps/mpi/mpi2_init.h b/sys/dev/raid/mps/mpi/mpi2_init.h
new file mode 100644
index 0000000..4c6ec98
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_init.h
@@ -0,0 +1,479 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_init.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 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.11
+ *
+ *  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.
+ *  02-10-10  02.00.09  Removed unused structure that had "#if 0" around it.
+ *  05-12-10  02.00.10  Added optional vendor-unique region to SCSI IO Request.
+ *  11-10-10  02.00.11  Added MPI2_SCSIIO_NUM_SGLOFFSETS 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;
+
+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 */
+
+#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */
+    MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
+#endif
+
+    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)
+
+/* number of SGLOffset fields */
+#define MPI2_SCSIIO_NUM_SGLOFFSETS                  (4)
+
+/* 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 --git a/sys/dev/raid/mps/mpi/mpi2_ioc.h b/sys/dev/raid/mps/mpi/mpi2_ioc.h
new file mode 100644
index 0000000..7dd0b36
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_ioc.h
@@ -0,0 +1,1565 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_ioc.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 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.16
+ *
+ *  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_).
+ *  02-10-10  02.00.14  Added SAS Quiesce Event structure and defines.
+ *                      Added PowerManagementControl Request structures and
+ *                      defines.
+ *  05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
+ *                      Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ *  11-10-10  02.00.16  Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
+ *  --------------------------------------------------------------------------
+ */
+
+#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) /* obsolete */
+#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)
+#define MPI2_EVENT_SAS_QUIESCE                      (0x0025)
+
+
+/* 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 */
+/*   this event is obsolete */
+
+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_UNSUPPORTED_PHY              (0x06)
+#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 */
+
+
+/* SAS Quiesce Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE
+{
+    U8                      ReasonCode;                 /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U16                     Reserved2;                  /* 0x02 */
+    U32                     Reserved3;                  /* 0x04 */
+} MPI2_EVENT_DATA_SAS_QUIESCE,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE,
+  Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t;
+
+/* SAS Quiesce Event data ReasonCode values */
+#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED                   (0x01)
+#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED                 (0x02)
+
+
+/* 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_COMPLETE             (0x0A)
+#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK    (0x0B)
+#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
+
+/* 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_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)
+
+
+/****************************************************************************
+*  PowerManagementControl message
+****************************************************************************/
+
+/* PowerManagementControl Request message */
+typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST
+{
+    U8                      Feature;                    /* 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                      Parameter1;                 /* 0x0C */
+    U8                      Parameter2;                 /* 0x0D */
+    U8                      Parameter3;                 /* 0x0E */
+    U8                      Parameter4;                 /* 0x0F */
+    U32                     Reserved5;                  /* 0x10 */
+    U32                     Reserved6;                  /* 0x14 */
+} MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST,
+  Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t;
+
+/* defines for the Feature field */
+#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND       (0x01)
+#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION   (0x02)
+#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK               (0x03)
+#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED               (0x04)
+#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC    (0x80)
+#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC    (0xFF)
+
+/* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */
+/* Parameter1 contains a PHY number */
+/* Parameter2 indicates power condition action using these defines */
+#define MPI2_PM_CONTROL_PARAM2_PARTIAL                  (0x01)
+#define MPI2_PM_CONTROL_PARAM2_SLUMBER                  (0x02)
+#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT            (0x03)
+/* Parameter3 and Parameter4 are reserved */
+
+/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION Feature */
+/* Parameter1 contains SAS port width modulation group number */
+/* Parameter2 indicates IOC action using these defines */
+#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP        (0x01)
+#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION        (0x02)
+#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP     (0x03)
+/* Parameter3 indicates desired modulation level using these defines */
+#define MPI2_PM_CONTROL_PARAM3_25_PERCENT               (0x00)
+#define MPI2_PM_CONTROL_PARAM3_50_PERCENT               (0x01)
+#define MPI2_PM_CONTROL_PARAM3_75_PERCENT               (0x02)
+#define MPI2_PM_CONTROL_PARAM3_100_PERCENT              (0x03)
+/* Parameter4 is reserved */
+
+/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */
+/* Parameter1 indicates desired PCIe link speed using these defines */
+#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS            (0x00)
+#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS            (0x01)
+#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS            (0x02)
+/* Parameter2 indicates desired PCIe link width using these defines */
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1                 (0x01)
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2                 (0x02)
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4                 (0x04)
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8                 (0x08)
+/* Parameter3 and Parameter4 are reserved */
+
+/* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */
+/* Parameter1 indicates desired IOC hardware clock speed using these defines */
+#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED           (0x01)
+#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED           (0x02)
+#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED        (0x04)
+#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED         (0x08)
+/* Parameter2, Parameter3, and Parameter4 are reserved */
+
+
+/* PowerManagementControl Reply message */
+typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY
+{
+    U8                      Feature;                    /* 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_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY,
+  Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t;
+
+
+#endif
diff --git a/sys/dev/raid/mps/mpi/mpi2_ra.h b/sys/dev/raid/mps/mpi/mpi2_ra.h
new file mode 100644
index 0000000..4d9e130
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_ra.h
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_ra.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2011 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 --git a/sys/dev/raid/mps/mpi/mpi2_raid.h b/sys/dev/raid/mps/mpi/mpi2_raid.h
new file mode 100644
index 0000000..f1f1988
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_raid.h
@@ -0,0 +1,332 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_raid.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_raid.h
+ *          Title:  MPI Integrated RAID messages and structures
+ *  Creation Date:  April 26, 2007
+ *
+ *    mpi2_raid.h Version:  02.00.05
+ *
+ *  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.
+ *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
+ *  --------------------------------------------------------------------------
+ */
+
+#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)
+#define MPI2_RAID_VOL_FLAGS_OP_MDC                  (0x00000004)
+
+
+/* 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 --git a/sys/dev/raid/mps/mpi/mpi2_sas.h b/sys/dev/raid/mps/mpi/mpi2_sas.h
new file mode 100644
index 0000000..a232d92
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_sas.h
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_sas.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_sas.h
+ *          Title:  MPI Serial Attached SCSI structures and definitions
+ *  Creation Date:  February 9, 2007
+ *
+ *  mpi2_sas.h Version:  02.00.05
+ *
+ *  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.
+ *  05-12-10  02.00.04  Modified some comments.
+ *  08-11-10  02.00.05  Added NCQ operations to SAS IO Unit Control.
+ *  --------------------------------------------------------------------------
+ */
+
+#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)
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+/* 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;                /* 0x30 */
+} 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)
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+/* 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_DEV_ENABLE_NCQ              (0x14)
+#define MPI2_SAS_OP_DEV_DISABLE_NCQ             (0x15)
+#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 --git a/sys/dev/raid/mps/mpi/mpi2_targ.h b/sys/dev/raid/mps/mpi/mpi2_targ.h
new file mode 100644
index 0000000..f52d578
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_targ.h
@@ -0,0 +1,473 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_targ.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_targ.h
+ *          Title:  MPI Target mode messages and structures
+ *  Creation Date:  September 8, 2006
+ *
+ *    mpi2_targ.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  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.
+ *  02-10-10  02.00.04  Added comment to MPI2_TARGET_SSP_RSP_IU structure.
+ *  --------------------------------------------------------------------------
+ */
+
+#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 */
+
+    /* start of Response or Sense Data (size may vary dynamically) */
+    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 --git a/sys/dev/raid/mps/mpi/mpi2_tool.h b/sys/dev/raid/mps/mpi/mpi2_tool.h
new file mode 100644
index 0000000..249bb87
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_tool.h
@@ -0,0 +1,467 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_tool.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_tool.h
+ *          Title:  MPI diagnostic tool structures and definitions
+ *  Creation Date:  March 26, 2007
+ *
+ *    mpi2_tool.h Version:  02.00.06
+ *
+ *  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.
+ *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
+ *  08-11-10  02.00.06  Added defines that were missing for Diagnostic Buffer
+ *                      Post Request.
+ *  --------------------------------------------------------------------------
+ */
+
+#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_DIAG_DATA_UPLOAD_TOOL          (0x02)
+#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 Diagnostic Data Upload request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_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                     Flags;                      /* 0x10 */
+    U32                     DataLength;                 /* 0x14 */
+    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x18 */
+} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+  Mpi2ToolboxDiagDataUploadRequest_t,
+  MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t;
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER
+{
+    U32                     DiagDataLength;             /* 00h */
+    U8                      FormatCode;                 /* 04h */
+    U8                      Reserved1;                  /* 05h */
+    U16                     Reserved2;                  /* 06h */
+} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
+  Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_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)
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+/* 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;
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+/* 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)
+
+/* values for the Flags field */
+#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL          (0x00000002)
+#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE        (0x00000001)
+
+
+/****************************************************************************
+*  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 --git a/sys/dev/raid/mps/mpi/mpi2_type.h b/sys/dev/raid/mps/mpi/mpi2_type.h
new file mode 100644
index 0000000..0ed736f
--- /dev/null
+++ b/sys/dev/raid/mps/mpi/mpi2_type.h
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpi/mpi2_type.h,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/*
+ *  Copyright (c) 2000-2011 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 --git a/sys/dev/raid/mps/mps.c b/sys/dev/raid/mps/mps.c
new file mode 100644
index 0000000..903d51c
--- /dev/null
+++ b/sys/dev/raid/mps/mps.c
@@ -0,0 +1,2298 @@
+/*-
+ * 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.
+ *
+ */
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps.c,v 1.14 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* Communications core for LSI MPT2 */
+
+/* TODO Move headers to mpsvar */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/globaldata.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/queue.h>
+#include <sys/kthread.h>
+#include <sys/endian.h>
+#include <sys/eventhandler.h>
+
+#include <sys/rman.h>
+
+#include <bus/pci/pcivar.h>
+
+#include <bus/cam/scsi/scsi_all.h>
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_sas.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+#include <dev/raid/mps/mps_table.h>
+
+static int mps_diag_reset(struct mps_softc *sc);
+static int mps_init_queues(struct mps_softc *sc);
+static int mps_message_unit_reset(struct mps_softc *sc);
+static int mps_transition_operational(struct mps_softc *sc);
+static void mps_startup(void *arg);
+static int mps_send_iocinit(struct mps_softc *sc);
+static int mps_attach_log(struct mps_softc *sc);
+static __inline void mps_complete_command(struct mps_command *cm);
+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 *);
+static int mps_reregister_events(struct mps_softc *sc);
+static void mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm);
+
+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_diag_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_message_unit_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_diag_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_diag_reset(sc);
+		} else if (state == MPI2_IOC_STATE_OPERATIONAL) {
+			/* Need to take ownership */
+			mps_message_unit_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) {
+			mps_dprint(sc, MPS_FAULT,
+			    "%s failed to transition ready\n", __func__);
+			return (error);
+		}
+	}
+
+	error = mps_send_iocinit(sc);
+	return (error);
+}
+
+/*
+ * XXX Some of this should probably move to mps.c
+ *
+ * The terms diag reset and hard reset are used interchangeably in the MPI
+ * docs to mean resetting the controller chip.  In this code diag reset
+ * cleans everything up, and the hard reset function just sends the reset
+ * sequence to the chip.  This should probably be refactored so that every
+ * subsystem gets a reset notification of some sort, and can clean up
+ * appropriately.
+ */
+int
+mps_reinit(struct mps_softc *sc)
+{
+	int error;
+	uint32_t db;
+
+	mps_printf(sc, "%s sc %p\n", __func__, sc);
+
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	if (sc->mps_flags & MPS_FLAGS_DIAGRESET) {
+		mps_printf(sc, "%s reset already in progress\n", __func__);
+		return 0;
+	}
+
+	/* make sure the completion callbacks can recognize they're getting
+	 * a NULL cm_reply due to a reset.
+	 */
+	sc->mps_flags |= MPS_FLAGS_DIAGRESET;
+
+	mps_printf(sc, "%s mask interrupts\n", __func__);
+	mps_mask_intr(sc);
+
+	error = mps_diag_reset(sc);
+	if (error != 0) {
+		panic("%s hard reset failed with error %d\n",
+		    __func__, error);
+	}
+
+	/* Restore the PCI state, including the MSI-X registers */
+	mps_pci_restore(sc);
+
+	/* Give the I/O subsystem special priority to get itself prepared */
+	mpssas_handle_reinit(sc);
+
+	/* reinitialize queues after the reset */
+	bzero(sc->free_queue, sc->fqdepth * 4);
+	mps_init_queues(sc);
+
+	/* get the chip out of the reset state */
+	error = mps_transition_operational(sc);
+	if (error != 0)
+		panic("%s transition operational failed with error %d\n",
+		    __func__, error);
+
+	/* Reinitialize the reply queue. This is delicate because this
+	 * function is typically invoked by task mgmt completion callbacks,
+	 * which are called by the interrupt thread.  We need to make sure
+	 * the interrupt handler loop will exit when we return to it, and
+	 * that it will recognize the indexes we've changed.
+	 */
+	sc->replypostindex = 0;
+	mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
+	mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, sc->replypostindex);
+
+	db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+	mps_printf(sc, "%s doorbell 0x%08x\n", __func__, db);
+
+	mps_printf(sc, "%s unmask interrupts post %u free %u\n", __func__,
+	    sc->replypostindex, sc->replyfreeindex);
+
+	mps_unmask_intr(sc);
+
+	mps_printf(sc, "%s restarting post %u free %u\n", __func__,
+	    sc->replypostindex, sc->replyfreeindex);
+
+	/* restart will reload the event masks clobbered by the reset, and
+	 * then enable the port.
+	 */
+	mps_reregister_events(sc);
+
+	/* the end of discovery will release the simq, so we're done. */
+	mps_printf(sc, "%s finished sc %p post %u free %u\n",
+	    __func__, sc,
+	    sc->replypostindex, sc->replyfreeindex);
+
+	sc->mps_flags &= ~MPS_FLAGS_DIAGRESET;
+
+	return 0;
+}
+
+/* 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);
+}
+
+static void
+mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
+{
+
+	mps_dprint(sc, MPS_TRACE, "%s SMID %u cm %p ccb %p\n", __func__,
+	    cm->cm_desc.Default.SMID, cm, cm->cm_ccb);
+
+	if (sc->mps_flags & MPS_FLAGS_ATTACH_DONE)
+		KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	if (++sc->io_cmds_active > sc->io_cmds_highwater)
+		sc->io_cmds_highwater++;
+
+	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);
+}
+
+/*
+ * 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 == NULL) {
+		mps_printf(sc, "%s NULL reply\n", __func__);
+		goto done;
+	}
+	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) {
+		mps_printf(sc,
+		    "%s error %d iocstatus 0x%x iocloginfo 0x%x type 0x%x\n",
+		    __func__, error, reply->IOCStatus, (u_int)reply->IOCLogInfo,
+		    reply->PortType);
+		error = ENXIO;
+	}
+	bcopy(reply, facts, sizeof(MPI2_PORT_FACTS_REPLY));
+done:
+	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_second;
+
+	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);
+}
+
+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 */
+                                &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 */
+                                &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 */
+                                &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 * sc->max_chains * 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 */
+                                &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 */
+                                &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 = kmalloc(sizeof(struct mps_chain) * sc->max_chains, M_MPT2,
+	    M_WAITOK | M_ZERO);
+	for (i = 0; i < sc->max_chains; 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);
+		sc->chain_free_lowwater++;
+	}
+
+	/* 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 */
+                                &sc->buffer_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate buffer 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 = kmalloc(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);
+
+		/* XXX Is a failure here a critical problem? */
+		if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) == 0)
+			if (i <= sc->facts->HighPriorityCredit)
+				mps_free_high_priority_command(sc, cm);
+			else
+				mps_free_command(sc, cm);
+		else {
+			panic("failed to allocate command %d\n", i);
+			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);
+}
+
+/* Get the driver parameter tunables.  Lowest priority are the driver defaults.
+ * Next are the global settings, if they exist.  Highest are the per-unit
+ * settings, if they exist.
+ */
+static void
+mps_get_tunables(struct mps_softc *sc)
+{
+	char tmpstr[80];
+
+	/* XXX default to some debugging for now */
+	sc->mps_debug = MPS_FAULT;
+#if 0 /* XXX swildner */
+	sc->disable_msix = 0;
+#endif
+	sc->enable_msi = 1;
+	sc->max_chains = MPS_CHAIN_FRAMES;
+
+	/*
+	 * Grab the global variables.
+	 */
+	TUNABLE_INT_FETCH("hw.mps.debug_level", &sc->mps_debug);
+#if 0 /* XXX swildner */
+	TUNABLE_INT_FETCH("hw.mps.disable_msix", &sc->disable_msix);
+#endif
+	TUNABLE_INT_FETCH("hw.mps.msi.enable", &sc->enable_msi);
+	TUNABLE_INT_FETCH("hw.mps.max_chains", &sc->max_chains);
+
+	/* Grab the unit-instance variables */
+	ksnprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
+	    device_get_unit(sc->mps_dev));
+	TUNABLE_INT_FETCH(tmpstr, &sc->mps_debug);
+
+#if 0 /* XXX swildner */
+	ksnprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.disable_msix",
+	    device_get_unit(sc->mps_dev));
+	TUNABLE_INT_FETCH(tmpstr, &sc->disable_msix);
+#endif
+
+	ksnprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.enable_msi",
+	    device_get_unit(sc->mps_dev));
+	TUNABLE_INT_FETCH(tmpstr, &sc->enable_msi);
+
+	ksnprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_chains",
+	    device_get_unit(sc->mps_dev));
+	TUNABLE_INT_FETCH(tmpstr, &sc->max_chains);
+}
+
+static void
+mps_setup_sysctl(struct mps_softc *sc)
+{
+	struct sysctl_ctx_list	*sysctl_ctx = NULL;
+	struct sysctl_oid	*sysctl_tree = NULL;
+	char tmpstr[80], tmpstr2[80];
+
+	/*
+	 * Setup the sysctl variable so the user can change the debug level
+	 * on the fly.
+	 */
+	ksnprintf(tmpstr, sizeof(tmpstr), "MPS controller %d",
+	    device_get_unit(sc->mps_dev));
+	ksnprintf(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;
+	sysctl_ctx = &sc->sysctl_ctx;
+	sysctl_tree = sc->sysctl_tree;
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "debug_level", CTLFLAG_RW, &sc->mps_debug, 0,
+	    "mps debug level");
+
+#if 0 /* XXX swildner */
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "disable_msix", CTLFLAG_RD, &sc->disable_msix, 0,
+	    "Disable the use of MSI-X interrupts");
+#endif
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "enable_msi", CTLFLAG_RD, &sc->enable_msi, 0,
+	    "Enable the use of MSI interrupts");
+
+	SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "firmware_version", CTLFLAG_RW, &sc->fw_version,
+	    strlen(sc->fw_version), "firmware version");
+
+	SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "driver_version", CTLFLAG_RW, MPS_DRIVER_VERSION,
+	    strlen(MPS_DRIVER_VERSION), "driver version");
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "io_cmds_active", CTLFLAG_RD,
+	    &sc->io_cmds_active, 0, "number of currently active commands");
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "io_cmds_highwater", CTLFLAG_RD,
+	    &sc->io_cmds_highwater, 0, "maximum active commands seen");
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "chain_free", CTLFLAG_RD,
+	    &sc->chain_free, 0, "number of free chain elements");
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "chain_free_lowwater", CTLFLAG_RD,
+	    &sc->chain_free_lowwater, 0,"lowest number of free chain elements");
+
+	SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "max_chains", CTLFLAG_RD,
+	    &sc->max_chains, 0,"maximum chain frames that will be allocated");
+
+#if __FreeBSD_version >= 900030
+	SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+	    OID_AUTO, "chain_alloc_fail", CTLFLAG_RD,
+	    &sc->chain_alloc_fail, "chain allocation failures");
+#endif //FreeBSD_version >= 900030
+}
+
+int
+mps_attach(struct mps_softc *sc)
+{
+	int i, error;
+
+	mps_get_tunables(sc);
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	lockinit(&sc->mps_lock, "MPT2SAS lock", 0, LK_CANRECURSE);
+	callout_init(&sc->periodic);
+	TAILQ_INIT(&sc->event_list);
+
+	if ((error = mps_transition_ready(sc)) != 0) {
+		mps_printf(sc, "%s failed to transition ready\n", __func__);
+		return (error);
+	}
+
+	sc->facts = kmalloc(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);
+
+	ksnprintf(sc->fw_version, sizeof(sc->fw_version),
+	    "%02d.%02d.%02d.%02d",
+	    sc->facts->FWVersion.Struct.Major,
+	    sc->facts->FWVersion.Struct.Minor,
+	    sc->facts->FWVersion.Struct.Unit,
+	    sc->facts->FWVersion.Struct.Dev);
+
+	mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version,
+	    MPS_DRIVER_VERSION);
+	mps_printf(sc, "IOCCapabilities: %b\n", (int)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_diag_reset(sc);
+		if ((error = mps_transition_ready(sc)) != 0)
+			return (error);
+	}
+
+	/*
+	 * Set flag if IR Firmware is loaded.
+	 */
+	if (sc->facts->IOCCapabilities &
+	    MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)
+		sc->ir_firmware = 1;
+
+	/*
+	 * Check if controller supports FW diag buffers and set flag to enable
+	 * each type.
+	 */
+	if (sc->facts->IOCCapabilities &
+	    MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
+		sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
+		    TRUE;
+	if (sc->facts->IOCCapabilities &
+	    MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
+		sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].enabled =
+		    TRUE;
+	if (sc->facts->IOCCapabilities &
+	    MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
+		sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].enabled =
+		    TRUE;
+
+	/*
+	 * Set flag if EEDP is supported and if TLR is supported.
+	 */
+	if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP)
+		sc->eedp_enabled = TRUE;
+	if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
+		sc->control_TLR = TRUE;
+
+	/*
+	 * 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->high_priority_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_printf(sc, "%s failed to alloc\n", __func__);
+		mps_free(sc);
+		return (error);
+	}
+
+	if (((error = mps_init_queues(sc)) != 0) ||
+	    ((error = mps_transition_operational(sc)) != 0)) {
+		mps_printf(sc, "%s failed to transition operational\n", __func__);
+		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 = kmalloc(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_printf(sc, "%s failed to get portfacts for port %d\n",
+			    __func__, i);
+			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_printf(sc, "%s failed to setup interrupts\n", __func__);
+		mps_free(sc);
+		return (error);
+	}
+
+	/*
+	 * The static page function currently read is ioc page8.  Others can be
+	 * added in future.
+	 */
+	mps_base_static_config_pages(sc);
+
+	/* 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;
+	}
+
+	/*
+	 * Allow IR to shutdown gracefully when shutdown occurs.
+	 */
+	sc->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final,
+	    mpssas_ir_shutdown, sc, SHUTDOWN_PRI_DEFAULT);
+
+	if (sc->shutdown_eh == NULL)
+		mps_dprint(sc, MPS_FAULT, "shutdown event registration "
+		    "failed\n");
+
+	mps_setup_sysctl(sc);
+
+	sc->mps_flags |= MPS_FLAGS_ATTACH_DONE;
+
+	return (error);
+}
+
+/* Run through any late-start handlers. */
+static void
+mps_startup(void *arg)
+{
+	struct mps_softc *sc;
+
+	sc = (struct mps_softc *)arg;
+
+	mps_lock(sc);
+	mps_unmask_intr(sc);
+	/* initialize device mapping tables */
+	mps_mapping_initialize(sc);
+	mpssas_startup(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;
+	mps_lock(sc);
+	if (sc->mps_flags & MPS_FLAGS_SHUTDOWN) {
+		mps_unlock(sc);
+		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);
+
+		mps_reinit(sc);
+	}
+
+	callout_reset(&sc->periodic, MPS_PERIODIC_DELAY * hz, mps_periodic, sc);
+	mps_unlock(sc);
+}
+
+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);
+#if 0 /* XXX swildner */
+	/* Lock must not be held for this */
+	callout_drain(&sc->periodic);
+#else
+	callout_stop(&sc->periodic);
+#endif
+
+	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_transition_ready(sc)) != 0) {
+		mps_unlock(sc);
+		return (error);
+	}
+	mps_unlock(sc);
+
+	if (sc->facts != NULL)
+		kfree(sc->facts, M_MPT2);
+
+	if (sc->pfacts != NULL)
+		kfree(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)
+		kfree(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);
+		}
+		kfree(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);
+
+	mps_mapping_free_memory(sc);
+
+	/* Deregister the shutdown function */
+	if (sc->shutdown_eh != NULL)
+		EVENTHANDLER_DEREGISTER(shutdown_final, sc->shutdown_eh);
+
+	lockuninit(&sc->mps_lock);
+
+	return (0);
+}
+
+static __inline void
+mps_complete_command(struct mps_command *cm)
+{
+	if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
+		cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
+
+	if (cm->cm_complete != NULL) {
+		mps_dprint(cm->cm_sc, MPS_TRACE,
+			   "%s cm %p calling cm_complete %p data %p reply %p\n",
+			   __func__, cm, cm->cm_complete, cm->cm_complete_data,
+			   cm->cm_reply);
+		cm->cm_complete(cm->cm_sc, cm);
+	}
+
+	if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP) {
+		mps_dprint(cm->cm_sc, MPS_TRACE, "%s: waking up %p\n",
+			   __func__, cm);
+		wakeup(cm);
+	}
+
+	if (cm->cm_sc->io_cmds_active != 0) {
+		cm->cm_sc->io_cmds_active--;
+	} else {
+		mps_dprint(cm->cm_sc, MPS_INFO, "Warning: io_cmds_active is "
+		    "out of sync - resynching to 0\n");
+	}
+}
+
+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_dprint(sc, MPS_TRACE, "%s\n", __func__);
+	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;
+	MPI2_DIAG_RELEASE_REPLY *rel_rep;
+	mps_fw_diagnostic_buffer_t *pBuffer;
+
+	sc = (struct mps_softc *)data;
+
+	pq = sc->replypostindex;
+	mps_dprint(sc, MPS_TRACE,
+	    "%s sc %p starting with replypostindex %u\n",
+	    __func__, sc, sc->replypostindex);
+
+	for ( ;; ) {
+		cm = NULL;
+		desc = &sc->post_queue[sc->replypostindex];
+		flags = desc->Default.ReplyFlags &
+		    MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+		if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+		 || (desc->Words.High == 0xffffffff))
+			break;
+
+		/* increment the replypostindex now, so that event handlers
+		 * and cm completion handlers which decide to do a diag
+		 * reset can zero it without it getting incremented again
+		 * afterwards, and we break out of this loop on the next
+		 * iteration since the reply post queue has been cleared to
+		 * 0xFF and all descriptors look unused (which they are).
+		 */
+		if (++sc->replypostindex >= sc->pqdepth)
+			sc->replypostindex = 0;
+
+		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)))) {
+				kprintf("%s: WARNING: reply %p out of range!\n",
+				       __func__, reply);
+				kprintf("%s: reply_frames %p, fqdepth %d, "
+				       "frame size %d\n", __func__,
+				       sc->reply_frames, sc->fqdepth,
+				       sc->facts->ReplyFrameSize * 4);
+				kprintf("%s: baddr %#x,\n", __func__, baddr);
+				panic("Reply address out of range");
+			}
+			if (desc->AddressReply.SMID == 0) {
+				if (((MPI2_DEFAULT_REPLY *)reply)->Function ==
+				    MPI2_FUNCTION_DIAG_BUFFER_POST) {
+					/*
+					 * If SMID is 0 for Diag Buffer Post,
+					 * this implies that the reply is due to
+					 * a release function with a status that
+					 * the buffer has been released.  Set
+					 * the buffer flags accordingly.
+					 */
+					rel_rep =
+					    (MPI2_DIAG_RELEASE_REPLY *)reply;
+					if (rel_rep->IOCStatus ==
+					    MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED)
+					    {
+						pBuffer =
+						    &sc->fw_diag_buffer_list[
+						    rel_rep->BufferType];
+						pBuffer->valid_data = TRUE;
+						pBuffer->owned_by_firmware =
+						    FALSE;
+						pBuffer->immediate = FALSE;
+					}
+				} else
+					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)
+			mps_complete_command(cm);
+
+		desc->Words.Low = 0xffffffff;
+		desc->Words.High = 0xffffffff;
+	}
+
+	if (pq != sc->replypostindex) {
+		mps_dprint(sc, MPS_TRACE,
+		    "%s sc %p writing postindex %d\n",
+		    __func__, sc, sc->replypostindex);
+		mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, sc->replypostindex);
+	}
+
+	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);
+
+	/*
+	 * This is the only place that the event/reply should be freed.
+	 * Anything wanting to hold onto the event data should have
+	 * already copied it into their own storage.
+	 */
+	mps_free_reply(sc, data);
+}
+
+static void
+mps_reregister_events_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if (cm->cm_reply)
+		mps_print_event(sc,
+			(MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply);
+
+	mps_free_command(sc, cm);
+
+	/* next, send a port enable */
+	mpssas_startup(sc);
+}
+
+/*
+ * 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 = kmalloc(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 == NULL) ||
+	    (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
+		error = ENXIO;
+	mps_print_event(sc, reply);
+	mps_dprint(sc, MPS_TRACE, "%s finished error %d\n", __func__, error);
+
+	mps_free_command(sc, cm);
+	return (error);
+}
+
+static int
+mps_reregister_events(struct mps_softc *sc)
+{
+	MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
+	struct mps_command *cm;
+	struct mps_event_handle *eh;
+	int error, i;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	/* first, reregister events */
+
+	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;
+	cm->cm_complete = mps_reregister_events_complete;
+
+	error = mps_map_command(sc, cm);
+
+	mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, error);
+	return (error);
+}
+
+int
+mps_deregister_events(struct mps_softc *sc, struct mps_event_handle *handle)
+{
+
+	TAILQ_REMOVE(&sc->event_list, handle, eh_list);
+	kfree(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;
+	uint32_t saved_buf_len, saved_address_low, saved_address_high;
+
+	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, (u_int)(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) {
+		/*
+		 * If this is a bi-directional request, need to account for that
+		 * here.  Save the pre-filled sge values.  These will be used
+		 * either for the 2nd SGL or for a single direction SGL.  If
+		 * cm_out_len is non-zero, this is a bi-directional request, so
+		 * fill in the OUT SGL first, then the IN SGL, otherwise just
+		 * fill in the IN SGL.  Note that at this time, when filling in
+		 * 2 SGL's for a bi-directional request, they both use the same
+		 * DMA buffer (same cm command).
+		 */
+		saved_buf_len = sge->FlagsLength & 0x00FFFFFF;
+		saved_address_low = sge->Address.Low;
+		saved_address_high = sge->Address.High;
+		if (cm->cm_out_len) {
+			sge->FlagsLength = cm->cm_out_len |
+			    ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+			    MPI2_SGE_FLAGS_END_OF_BUFFER |
+			    MPI2_SGE_FLAGS_HOST_TO_IOC |
+			    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
+			    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);
+		}
+		sge->FlagsLength = saved_buf_len |
+		    ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+		    MPI2_SGE_FLAGS_END_OF_BUFFER |
+		    MPI2_SGE_FLAGS_LAST_ELEMENT |
+		    MPI2_SGE_FLAGS_END_OF_LIST |
+		    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
+		    MPI2_SGE_FLAGS_SHIFT);
+		if (cm->cm_flags & MPS_CM_FLAGS_DATAIN) {
+			sge->FlagsLength |=
+			    ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
+			    MPI2_SGE_FLAGS_SHIFT);
+		} else {
+			sge->FlagsLength |=
+			    ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
+			    MPI2_SGE_FLAGS_SHIFT);
+		}
+		sge->Address.Low = saved_address_low;
+		sge->Address.High = saved_address_high;
+	}
+
+	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_64_BIT_ADDRESSING;
+	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.  Bi-directional requests are also handled
+	 * here.  In that case, both direction flags will be set.
+	 */
+	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_HOST_TO_IOC;
+		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_dprint(sc, MPS_INFO, "out of chain frames\n");
+			cm->cm_flags |= MPS_CM_FLAGS_CHAIN_FAILED;
+			mps_complete_command(cm);
+			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);
+}
+
+/*
+ * This is the routine to enqueue commands ansynchronously.
+ * Note that the only error path here is from bus_dmamap_load(), which can
+ * return EINPROGRESS if it is waiting for resources.  Other than this, it's
+ * assumed that if you have a command in-hand, then you have enough credits
+ * to use it.
+ */
+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);
+}
+
+/*
+ * This is the routine to enqueue commands synchronously.  An error of
+ * EINPROGRESS from mps_map_command() is ignored since the command will
+ * be executed and enqueued automatically.  Other errors come from msleep().
+ */
+int
+mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
+{
+	int error;
+
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	cm->cm_complete = NULL;
+	cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
+	error = mps_map_command(sc, cm);
+	if ((error != 0) && (error != EINPROGRESS))
+		return (error);
+	error = lksleep(cm, &sc->mps_lock, 0, "mpswait", timeout);
+	if (error == EWOULDBLOCK)
+		error = ETIMEDOUT;
+	return (error);
+}
+
+/*
+ * This is the routine to enqueue a command synchonously and poll for
+ * completion.  Its use should be rare.
+ */
+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_locked(sc);
+		DELAY(50 * 1000);
+		if (timeout++ > 1000) {
+			mps_dprint(sc, MPS_FAULT, "polling failed\n");
+			error = ETIMEDOUT;
+			break;
+		}
+	}
+
+	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 {
+		error = mps_wait_command(sc, cm, 0);
+		if (error) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Error %d reading config page\n", error);
+			mps_free_command(sc, cm);
+			return (error);
+		}
+		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);
+	}
+
+	/*
+	 * XXX KDM need to do more error recovery?  This results in the
+	 * device in question not getting probed.
+	 */
+	if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		params->status = MPI2_IOCSTATUS_BUSY;
+		goto done;
+	}
+
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (reply == NULL) {
+		params->status = MPI2_IOCSTATUS_BUSY;
+		goto done;
+	}
+	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;
+	}
+
+done:
+	mps_free_command(sc, cm);
+	if (params->callback != NULL)
+		params->callback(sc, params);
+
+	return;
+}
diff --git a/sys/dev/raid/mps/mps_config.c b/sys/dev/raid/mps/mps_config.c
new file mode 100644
index 0000000..44b70eb
--- /dev/null
+++ b/sys/dev/raid/mps/mps_config.c
@@ -0,0 +1,1390 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_config.c,v 1.1 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* TODO Move headers to mpsvar */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/sysctl.h>
+#include <sys/eventhandler.h>
+#include <sys/uio.h>
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_sas.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+
+/**
+ * mps_config_get_ioc_pg8 - obtain ioc page 8
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+    Mpi2IOCPage8_t *config_page)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
+	request->Header.PageNumber = 8;
+	request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
+	request->Header.PageNumber = 8;
+	request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
+	request->Header.PageLength = mpi_reply->Header.PageLength;
+	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
+
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
+ *   accordingly.  Currently, this page does not need to return to caller.
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	pMpi2ManufacturingPagePS_t page = NULL;
+	uint32_t *pPS_info;
+	uint8_t OEM_Value = 0;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+	request->Header.PageNumber = 10;
+	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+	request->Header.PageNumber = 10;
+	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
+	request->Header.PageLength = mpi_reply->Header.PageLength;
+	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+
+	/*
+	 * If OEM ID is unknown, fail the request.
+	 */
+	sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
+	OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
+	if (OEM_Value != MPS_WD_LSI_OEM) {
+		mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
+		    "(0x%x)\n", OEM_Value);
+		error = ENXIO;
+		goto out;
+	}
+
+	/*
+	 * Set the phys disks hide/expose value.
+	 */
+	pPS_info = (uint32_t *)&page->ProductSpecificInfo;
+	sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
+	sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
+	if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
+	    (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
+	    (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
+		mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
+		    "hide/expose: 0x%x\n", sc->WD_hide_expose);
+		error = ENXIO;
+		goto out;
+	}
+
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_base_static_config_pages - static start of day config pages.
+ * @sc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mps_base_static_config_pages(struct mps_softc *sc)
+{
+	Mpi2ConfigReply_t	mpi_reply;
+	int			retry;
+
+	retry = 0;
+	while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
+		retry++;
+		if (retry > 5) {
+			/* We need to Handle this situation */
+			/*FIXME*/
+			break;
+		}
+	}
+}
+
+/**
+ * mps_wd_config_pages - get info required to support WarpDrive.  This needs to
+ *    be called after discovery is complete to guarentee that IR info is there.
+ * @sc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mps_wd_config_pages(struct mps_softc *sc)
+{
+	Mpi2ConfigReply_t	mpi_reply;
+	pMpi2RaidVolPage0_t	raid_vol_pg0 = NULL;
+	Mpi2RaidPhysDiskPage0_t	phys_disk_pg0;
+	pMpi2RaidVol0PhysDisk_t	pRVPD;
+	uint32_t		stripe_size, phys_disk_page_address;
+	uint16_t		block_size;
+	uint8_t			index, stripe_exp = 0, block_exp = 0;
+
+	/*
+	 * Get the WD settings from manufacturing page 10 if using a WD HBA.
+	 * This will be used to determine if phys disks should always be
+	 * hidden, hidden only if part of a WD volume, or never hidden.  Also,
+	 * get the WD RAID Volume info and fail if volume does not exist or if
+	 * volume does not meet the requirements for a WD volume.  No retry
+	 * here.  Just default to HIDE ALWAYS if man Page10 fails, or clear WD
+	 * Valid flag if Volume info fails.
+	 */
+	sc->WD_valid_config = FALSE;
+	if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
+		if (mps_config_get_man_pg10(sc, &mpi_reply)) {
+			mps_dprint(sc, MPS_FAULT,
+			    "mps_config_get_man_pg10 failed! Using 0 (Hide "
+			    "Always) for WarpDrive hide/expose value.\n");
+			sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
+		}
+
+		/*
+		 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
+		 */
+		raid_vol_pg0 = kmalloc(sizeof(Mpi2RaidVolPage0_t) +
+		    (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
+		    M_MPT2, M_ZERO | M_NOWAIT);
+		if (!raid_vol_pg0) {
+			kprintf("%s: page alloc failed\n", __func__);
+			goto out;
+		}
+
+		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
+		    0x0000FFFF)) {
+			mps_dprint(sc, MPS_INFO,
+			    "mps_config_get_raid_volume_pg0 failed! Assuming "
+			    "WarpDrive IT mode.\n");
+			goto out;
+		}
+
+		/*
+		 * Check for valid WD configuration:
+		 *   volume type is RAID0
+		 *   number of phys disks in the volume is no more than 8
+		 */
+		if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
+		    (raid_vol_pg0->NumPhysDisks > 8)) {
+			mps_dprint(sc, MPS_FAULT,
+			    "Invalid WarpDrive configuration. Direct Drive I/O "
+			    "will not be used.\n");
+			goto out;
+		}
+
+		/*
+		 * Save the WD RAID data to be used during WD I/O.
+		 */
+		sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
+		    32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
+		sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
+		sc->DD_dev_handle = raid_vol_pg0->DevHandle;
+		sc->DD_stripe_size = raid_vol_pg0->StripeSize;
+		sc->DD_block_size = raid_vol_pg0->BlockSize;
+
+		/*
+		 * Find power of 2 of stripe size and set this as the exponent.
+		 * Fail if stripe size is 0.
+		 */
+		stripe_size = raid_vol_pg0->StripeSize;
+		for (index = 0; index < 32; index++) {
+			if (stripe_size & 1)
+				break;
+			stripe_exp++;
+			stripe_size >>= 1;
+		}
+		if (index == 32) {
+			mps_dprint(sc, MPS_FAULT,
+			    "RAID Volume's stripe size is 0. Direct Drive I/O "
+			    "will not be used.\n");
+			goto out;
+		}
+		sc->DD_stripe_exponent = stripe_exp;
+
+		/*
+		 * Find power of 2 of block size and set this as the exponent.
+		 * Fail if block size is 0.
+		 */
+		block_size = raid_vol_pg0->BlockSize;
+		for (index = 0; index < 16; index++) {
+			if (block_size & 1)
+				break;
+			block_exp++;
+			block_size >>= 1;
+		}
+		if (index == 16) {
+			mps_dprint(sc, MPS_FAULT,
+			    "RAID Volume's block size is 0. Direct Drive I/O "
+			    "will not be used.\n");
+			goto out;
+		}
+		sc->DD_block_exponent = block_exp;
+
+		/*
+		 * Loop through all of the volume's Phys Disks to map the phys
+		 * disk number into the columm map.  This is used during Direct
+		 * Drive I/O to send the request to the correct SSD.
+		 */
+		pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
+		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
+			sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
+			    pRVPD->PhysDiskNum;
+			pRVPD++;
+		}
+
+		/*
+		 * Get second RAID Volume Page0 using previous handle.  This
+		 * page should not exist.  If it does, must not proceed with WD
+		 * handling.
+		 */
+		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
+		    raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
+			if (mpi_reply.IOCStatus !=
+			    MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
+				mps_dprint(sc, MPS_FAULT,
+				    "Multiple RAID Volume Page0! Direct Drive "
+				    "I/O will not be used.\n");
+				goto out;
+			}
+		} else {
+			mps_dprint(sc, MPS_FAULT,
+			    "Multiple volumes! Direct Drive I/O will not be "
+			    "used.\n");
+			goto out;
+		}
+
+		/*
+		 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
+		 */
+		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
+			phys_disk_page_address =
+			    MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
+			    sc->DD_column_map[index].phys_disk_num;
+			if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
+			    &phys_disk_pg0, phys_disk_page_address)) {
+				mps_dprint(sc, MPS_FAULT,
+				    "mps_config_get_raid_pd_pg0 failed! Direct "
+				    "Drive I/O will not be used.\n");
+				goto out;
+			}
+			if (phys_disk_pg0.DevHandle == 0xFFFF) {
+				mps_dprint(sc, MPS_FAULT,
+				    "Invalid Phys Disk DevHandle! Direct Drive "
+				    "I/O will not be used.\n");
+				goto out;
+			}
+			sc->DD_column_map[index].dev_handle =
+			    phys_disk_pg0.DevHandle;
+		}
+		sc->WD_valid_config = TRUE;
+out:
+		if (raid_vol_pg0)
+			kfree(raid_vol_pg0, M_MPT2);
+	}
+}
+
+/**
+ * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+    Mpi2DriverMappingPage0_t *config_page, u16 sz)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	Mpi2DriverMappingPage0_t *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	memset(config_page, 0, sz);
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
+	request->PageAddress = sc->max_dpm_entries <<
+	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
+	request->PageAddress = sc->max_dpm_entries <<
+	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
+	request->ExtPageLength = mpi_reply->ExtPageLength;
+	cm->cm_length =  le16toh(request->ExtPageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, MIN(cm->cm_length, sz));
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @entry_idx: entry index in DPM Page0 to be modified
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+
+int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+    Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
+	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
+	request->PageAddress |= htole16(entry_idx);
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
+	request->ExtPageLength = mpi_reply->ExtPageLength;
+	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
+	request->PageAddress |= htole16(entry_idx);
+	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
+	cm->cm_sge = &request->PageBufferSGE;
+	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
+	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	bcopy(config_page, page, MIN(cm->cm_length,
+	    (sizeof(Mpi2DriverMappingPage0_t))));
+	cm->cm_data = page;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page written with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_get_sas_device_pg0 - obtain sas device page 0
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: device handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
+    *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	Mpi2SasDevicePage0_t *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
+	request->ExtPageLength = mpi_reply->ExtPageLength;
+	request->PageAddress = htole32(form | handle);
+	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, MIN(cm->cm_length,
+	    sizeof(Mpi2SasDevicePage0_t)));
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_get_bios_pg3 - obtain BIOS page 3
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+    Mpi2BiosPage3_t *config_page)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	Mpi2BiosPage3_t *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
+	request->Header.PageNumber = 3;
+	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
+	request->Header.PageNumber = 3;
+	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
+	request->Header.PageLength = mpi_reply->Header.PageLength;
+	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @page_address: form and handle value used to get page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
+    *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	Mpi2RaidVolPage0_t *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+	request->Header.PageNumber = 0;
+	request->Header.PageLength = mpi_reply->Header.PageLength;
+	request->Header.PageVersion = mpi_reply->Header.PageVersion;
+	request->PageAddress = page_address;
+	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, cm->cm_length);
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: volume handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
+    *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	Mpi2RaidVolPage1_t *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+	request->Header.PageNumber = 1;
+	request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+	request->Header.PageNumber = 1;
+	request->Header.PageLength = mpi_reply->Header.PageLength;
+	request->Header.PageVersion = mpi_reply->Header.PageVersion;
+	request->PageAddress = htole32(form | handle);
+	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, MIN(cm->cm_length,
+	    sizeof(Mpi2RaidVolPage1_t)));
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
+
+/**
+ * mps_config_get_volume_wwid - returns wwid given the volume handle
+ * @sc: per adapter object
+ * @volume_handle: volume handle
+ * @wwid: volume wwid
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
+{
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2RaidVolPage1_t raid_vol_pg1;
+
+	*wwid = 0;
+	if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
+	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
+		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
+		    raid_vol_pg1.WWID.Low);
+		return 0;
+	} else
+		return -1;
+}
+
+/**
+ * mps_config_get_pd_pg0 - obtain raid phys disk page 0
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @page_address: form and handle value used to get page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+    Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
+{
+	MPI2_CONFIG_REQUEST *request;
+	MPI2_CONFIG_REPLY *reply;
+	struct mps_command *cm;
+	Mpi2RaidPhysDiskPage0_t *page = NULL;
+	int error = 0;
+	u16 ioc_status;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	request->Header.PageNumber = 0;
+	request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_data = NULL;
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for header completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: header read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	/* We have to do free and alloc for the reply-free and reply-post
+	 * counters to match - Need to review the reply FIFO handling.
+	 */
+	mps_free_command(sc, cm);
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed @ line %d\n", __func__,
+		    __LINE__);
+		error = EBUSY;
+		goto out;
+	}
+	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+	request->Function = MPI2_FUNCTION_CONFIG;
+	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	request->Header.PageNumber = 0;
+	request->Header.PageLength = mpi_reply->Header.PageLength;
+	request->Header.PageVersion = mpi_reply->Header.PageVersion;
+	request->PageAddress = page_address;
+	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
+	cm->cm_sge = &request->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;
+	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
+	if (!page) {
+		kprintf("%s: page alloc failed\n", __func__);
+		error = ENOMEM;
+		goto out;
+	}
+	cm->cm_data = page;
+
+	error = mps_request_polled(sc, cm);
+	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: page read with error; iocstatus = 0x%x\n",
+		    __func__, ioc_status);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(page, config_page, MIN(cm->cm_length,
+	    sizeof(Mpi2RaidPhysDiskPage0_t)));
+out:
+	kfree(page, M_MPT2);
+	if (cm)
+		mps_free_command(sc, cm);
+	return (error);
+}
diff --git a/sys/dev/raid/mps/mps_ioctl.h b/sys/dev/raid/mps/mps_ioctl.h
new file mode 100644
index 0000000..e562992
--- /dev/null
+++ b/sys/dev/raid/mps/mps_ioctl.h
@@ -0,0 +1,387 @@
+/*-
+ * 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: src/sys/dev/mps/mps_ioctl.h,v 1.3 2012/01/26 18:17:21 ken Exp $
+ */
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_ioctl.h,v 1.3 2012/01/26 18:17:21 ken Exp $
+ */
+
+#ifndef _MPS_IOCTL_H_
+#define	_MPS_IOCTL_H_
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/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;
+};
+
+typedef struct mps_pci_bits
+{
+	union {
+		struct {
+			uint32_t	DeviceNumber	:5;
+			uint32_t	FunctionNumber	:3;
+			uint32_t	BusNumber	:24;
+		} bits;
+		uint32_t	AsDWORD;
+	} u;
+	uint32_t	PciSegmentId;
+} mps_pci_bits_t;
+
+/*
+ *  The following is the MPSIOCTL_GET_ADAPTER_DATA data structure.  This data
+ *  structure is setup so that we hopefully are properly aligned for both
+ *  32-bit and 64-bit mode applications.
+ *
+ *  Adapter Type - Value = 4 = SCSI Protocol through SAS-2 adapter
+ *
+ *  MPI Port Number - The PCI Function number for this device
+ *
+ *  PCI Device HW Id - The PCI device number for this device
+ *
+ */
+#define	MPSIOCTL_ADAPTER_TYPE_SAS2		4
+#define	MPSIOCTL_ADAPTER_TYPE_SAS2_SSS6200	5
+typedef struct mps_adapter_data
+{
+	uint32_t	StructureLength;
+	uint32_t	AdapterType;
+	uint32_t	MpiPortNumber;
+	uint32_t	PCIDeviceHwId;
+	uint32_t	PCIDeviceHwRev;
+	uint32_t	SubSystemId;
+	uint32_t	SubsystemVendorId;
+	uint32_t	Reserved1;
+	uint32_t	MpiFirmwareVersion;
+	uint32_t	BiosVersion;
+	uint8_t		DriverVersion[32];
+	uint8_t		Reserved2;
+	uint8_t		ScsiId;
+	uint16_t	Reserved3;
+	mps_pci_bits_t	PciInformation;
+} mps_adapter_data_t;
+
+
+typedef struct mps_update_flash
+{
+	uint64_t	PtrBuffer;
+	uint32_t	ImageChecksum;
+	uint32_t	ImageOffset;
+	uint32_t	ImageSize;
+	uint32_t	ImageType;
+} mps_update_flash_t;
+
+
+#define	MPS_PASS_THRU_DIRECTION_NONE	0
+#define	MPS_PASS_THRU_DIRECTION_READ	1
+#define	MPS_PASS_THRU_DIRECTION_WRITE	2
+#define	MPS_PASS_THRU_DIRECTION_BOTH	3
+
+typedef struct mps_pass_thru
+{
+	uint64_t	PtrRequest;
+	uint64_t	PtrReply;
+	uint64_t	PtrData;
+	uint32_t	RequestSize;
+	uint32_t	ReplySize;
+	uint32_t	DataSize;
+	uint32_t	DataDirection;
+	uint64_t	PtrDataOut;
+	uint32_t	DataOutSize;
+	uint32_t	Timeout;
+} mps_pass_thru_t;
+
+
+/*
+ * Event queue defines
+ */
+#define	MPS_EVENT_QUEUE_SIZE		(50) /* Max Events stored in driver */
+#define	MPS_MAX_EVENT_DATA_LENGTH	(48) /* Size of each event in Dwords */
+
+typedef struct mps_event_query
+{
+	uint16_t	Entries;
+	uint16_t	Reserved;
+	uint32_t	Types[4];
+} mps_event_query_t;
+
+typedef struct mps_event_enable
+{
+	uint32_t	Types[4];
+} mps_event_enable_t;
+
+/*
+ * Event record entry for ioctl.
+ */
+typedef struct mps_event_entry
+{
+	uint32_t	Type;
+	uint32_t	Number;
+	uint32_t	Data[MPS_MAX_EVENT_DATA_LENGTH];
+} mps_event_entry_t;
+
+typedef struct mps_event_report
+{
+	uint32_t	Size;
+	uint64_t	PtrEvents;
+} mps_event_report_t;
+
+
+typedef struct mps_pci_info
+{
+	uint32_t	BusNumber;
+	uint8_t		DeviceNumber;
+	uint8_t		FunctionNumber;
+	uint16_t	InterruptVector;
+	uint8_t		PciHeader[256];
+} mps_pci_info_t;
+
+
+typedef struct mps_diag_action
+{
+	uint32_t	Action;
+	uint32_t	Length;
+	uint64_t	PtrDiagAction;
+	uint32_t	ReturnCode;
+} mps_diag_action_t;
+
+#define	MPS_FW_DIAGNOSTIC_UID_NOT_FOUND	(0xFF)
+
+#define	MPS_FW_DIAG_NEW				(0x806E6577)
+
+#define	MPS_FW_DIAG_TYPE_REGISTER		(0x00000001)
+#define	MPS_FW_DIAG_TYPE_UNREGISTER		(0x00000002)
+#define	MPS_FW_DIAG_TYPE_QUERY			(0x00000003)
+#define	MPS_FW_DIAG_TYPE_READ_BUFFER		(0x00000004)
+#define	MPS_FW_DIAG_TYPE_RELEASE		(0x00000005)
+
+#define	MPS_FW_DIAG_INVALID_UID			(0x00000000)
+
+#define MPS_DIAG_SUCCESS			0
+#define MPS_DIAG_FAILURE			1
+
+#define	MPS_FW_DIAG_ERROR_SUCCESS		(0x00000000)
+#define	MPS_FW_DIAG_ERROR_FAILURE		(0x00000001)
+#define	MPS_FW_DIAG_ERROR_INVALID_PARAMETER	(0x00000002)
+#define	MPS_FW_DIAG_ERROR_POST_FAILED		(0x00000010)
+#define	MPS_FW_DIAG_ERROR_INVALID_UID		(0x00000011)
+#define	MPS_FW_DIAG_ERROR_RELEASE_FAILED	(0x00000012)
+#define	MPS_FW_DIAG_ERROR_NO_BUFFER		(0x00000013)
+#define	MPS_FW_DIAG_ERROR_ALREADY_RELEASED	(0x00000014)
+
+
+typedef struct mps_fw_diag_register
+{
+	uint8_t		ExtendedType;
+	uint8_t		BufferType;
+	uint16_t	ApplicationFlags;
+	uint32_t	DiagnosticFlags;
+	uint32_t	ProductSpecific[23];
+	uint32_t	RequestedBufferSize;
+	uint32_t	UniqueId;
+} mps_fw_diag_register_t;
+
+typedef struct mps_fw_diag_unregister
+{
+	uint32_t	UniqueId;
+} mps_fw_diag_unregister_t;
+
+#define	MPS_FW_DIAG_FLAG_APP_OWNED		(0x0001)
+#define	MPS_FW_DIAG_FLAG_BUFFER_VALID		(0x0002)
+#define	MPS_FW_DIAG_FLAG_FW_BUFFER_ACCESS	(0x0004)
+
+typedef struct mps_fw_diag_query
+{
+	uint8_t		ExtendedType;
+	uint8_t		BufferType;
+	uint16_t	ApplicationFlags;
+	uint32_t	DiagnosticFlags;
+	uint32_t	ProductSpecific[23];
+	uint32_t	TotalBufferSize;
+	uint32_t	DriverAddedBufferSize;
+	uint32_t	UniqueId;
+} mps_fw_diag_query_t;
+
+typedef struct mps_fw_diag_release
+{
+	uint32_t	UniqueId;
+} mps_fw_diag_release_t;
+
+#define	MPS_FW_DIAG_FLAG_REREGISTER	(0x0001)
+#define	MPS_FW_DIAG_FLAG_FORCE_RELEASE	(0x0002)
+
+typedef struct mps_diag_read_buffer
+{
+	uint8_t		Status;
+	uint8_t		Reserved;
+	uint16_t	Flags;
+	uint32_t	StartingOffset;
+	uint32_t	BytesToRead;
+	uint32_t	UniqueId;
+	uint64_t	PtrDataBuffer;
+} mps_diag_read_buffer_t;
+
+/*
+ * Register Access
+ */
+#define	REG_IO_READ	1
+#define	REG_IO_WRITE	2
+#define	REG_MEM_READ	3
+#define	REG_MEM_WRITE	4
+
+typedef struct mps_reg_access
+{
+	uint32_t	Command;
+	uint32_t	RegOffset;
+	uint32_t	RegData;
+} mps_reg_access_t;
+
+typedef struct mps_btdh_mapping
+{
+	uint16_t	TargetID;
+	uint16_t	Bus;
+	uint16_t	DevHandle;
+	uint16_t	Reserved;
+} mps_btdh_mapping_t;
+
+#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)
+
+#define	MPTIOCTL			('I')
+#define	MPTIOCTL_GET_ADAPTER_DATA	_IOWR(MPTIOCTL, 1,\
+    struct mps_adapter_data)
+#define	MPTIOCTL_UPDATE_FLASH		_IOWR(MPTIOCTL, 2,\
+    struct mps_update_flash)
+#define	MPTIOCTL_RESET_ADAPTER		_IO(MPTIOCTL, 3)
+#define	MPTIOCTL_PASS_THRU		_IOWR(MPTIOCTL, 4,\
+    struct mps_pass_thru)
+#define	MPTIOCTL_EVENT_QUERY		_IOWR(MPTIOCTL, 5,\
+    struct mps_event_query)
+#define	MPTIOCTL_EVENT_ENABLE		_IOWR(MPTIOCTL, 6,\
+    struct mps_event_enable)
+#define	MPTIOCTL_EVENT_REPORT		_IOWR(MPTIOCTL, 7,\
+    struct mps_event_report)
+#define	MPTIOCTL_GET_PCI_INFO		_IOWR(MPTIOCTL, 8,\
+    struct mps_pci_info)
+#define	MPTIOCTL_DIAG_ACTION		_IOWR(MPTIOCTL, 9,\
+    struct mps_diag_action)
+#define	MPTIOCTL_REG_ACCESS		_IOWR(MPTIOCTL, 10,\
+    struct mps_reg_access)
+#define	MPTIOCTL_BTDH_MAPPING		_IOWR(MPTIOCTL, 11,\
+    struct mps_btdh_mapping)
+
+#endif /* !_MPS_IOCTL_H_ */
diff --git a/sys/dev/raid/mps/mps_mapping.c b/sys/dev/raid/mps/mps_mapping.c
new file mode 100644
index 0000000..cb02154
--- /dev/null
+++ b/sys/dev/raid/mps/mps_mapping.c
@@ -0,0 +1,2265 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_mapping.c,v 1.1 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* TODO Move headers to mpsvar */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/sysctl.h>
+#include <sys/eventhandler.h>
+#include <sys/uio.h>
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_sas.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+#include <dev/raid/mps/mps_mapping.h>
+
+/**
+ * _mapping_clear_entry - Clear a particular mapping entry.
+ * @map_entry: map table entry
+ *
+ * Returns nothing.
+ */
+static inline void
+_mapping_clear_map_entry(struct dev_mapping_table *map_entry)
+{
+	map_entry->physical_id = 0;
+	map_entry->device_info = 0;
+	map_entry->phy_bits = 0;
+	map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
+	map_entry->dev_handle = 0;
+	map_entry->channel = -1;
+	map_entry->id = -1;
+	map_entry->missing_count = 0;
+	map_entry->init_complete = 0;
+	map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
+}
+
+/**
+ * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
+ * @enc_entry: enclosure table entry
+ *
+ * Returns nothing.
+ */
+static inline void
+_mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
+{
+	enc_entry->enclosure_id = 0;
+	enc_entry->start_index = MPS_MAPTABLE_BAD_IDX;
+	enc_entry->phy_bits = 0;
+	enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
+	enc_entry->enc_handle = 0;
+	enc_entry->num_slots = 0;
+	enc_entry->start_slot = 0;
+	enc_entry->missing_count = 0;
+	enc_entry->removal_flag = 0;
+	enc_entry->skip_search = 0;
+	enc_entry->init_complete = 0;
+}
+
+/**
+ * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
+ * @sc: per adapter object
+ * @enc_entry: enclosure table entry
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_mapping_commit_enc_entry(struct mps_softc *sc,
+    struct enc_mapping_table *et_entry)
+{
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	struct dev_mapping_table *mt_entry;
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2DriverMappingPage0_t config_page;
+
+	if (!sc->is_dpm_enable)
+		return 0;
+
+	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
+	memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+	dpm_entry += et_entry->dpm_entry_num;
+	dpm_entry->PhysicalIdentifier.Low =
+	    ( 0xFFFFFFFF & et_entry->enclosure_id);
+	dpm_entry->PhysicalIdentifier.High =
+	    ( et_entry->enclosure_id >> 32);
+	mt_entry = &sc->mapping_table[et_entry->start_index];
+	dpm_entry->DeviceIndex = htole16(mt_entry->id);
+	dpm_entry->MappingInformation = et_entry->num_slots;
+	dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
+	dpm_entry->MappingInformation |= et_entry->missing_count;
+	dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
+	dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
+	dpm_entry->Reserved1 = 0;
+
+	memcpy(&config_page.Entry, (u8 *)dpm_entry,
+	    sizeof(Mpi2DriverMap0Entry_t));
+	if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
+	    et_entry->dpm_entry_num)) {
+		kprintf("%s: write of dpm entry %d for enclosure failed\n",
+		    __func__, et_entry->dpm_entry_num);
+		dpm_entry->MappingInformation = le16toh(dpm_entry->
+		    MappingInformation);
+		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
+		dpm_entry->PhysicalBitsMapping =
+		    le32toh(dpm_entry->PhysicalBitsMapping);
+		return -1;
+	}
+	dpm_entry->MappingInformation = le16toh(dpm_entry->
+	    MappingInformation);
+	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
+	dpm_entry->PhysicalBitsMapping =
+	    le32toh(dpm_entry->PhysicalBitsMapping);
+	return 0;
+}
+
+/**
+ * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
+ * @sc: per adapter object
+ * @enc_entry: enclosure table entry
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+
+static int
+_mapping_commit_map_entry(struct mps_softc *sc,
+    struct dev_mapping_table *mt_entry)
+{
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2DriverMappingPage0_t config_page;
+
+	if (!sc->is_dpm_enable)
+		return 0;
+
+	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
+	memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+	dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
+	dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
+	    mt_entry->physical_id);
+	dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
+	dpm_entry->DeviceIndex = htole16(mt_entry->id);
+	dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
+	dpm_entry->PhysicalBitsMapping = 0;
+	dpm_entry->Reserved1 = 0;
+	dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
+	memcpy(&config_page.Entry, (u8 *)dpm_entry,
+	    sizeof(Mpi2DriverMap0Entry_t));
+	if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
+	    mt_entry->dpm_entry_num)) {
+		kprintf("%s: write of dpm entry %d for device failed\n",
+		    __func__, mt_entry->dpm_entry_num);
+		dpm_entry->MappingInformation = le16toh(dpm_entry->
+		    MappingInformation);
+		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
+		return -1;
+	}
+
+	dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
+	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
+	return 0;
+}
+
+/**
+ * _mapping_get_ir_maprange - get start and end index for IR map range.
+ * @sc: per adapter object
+ * @start_idx: place holder for start index
+ * @end_idx: place holder for end index
+ *
+ * The IR volumes can be mapped either at start or end of the mapping table
+ * this function gets the detail of where IR volume mapping starts and ends
+ * in the device mapping table
+ *
+ * Returns nothing.
+ */
+static void
+_mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx)
+{
+	u16 volume_mapping_flags;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+
+	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
+	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
+		*start_idx = 0;
+		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
+			*start_idx = 1;
+	} else
+		*start_idx = sc->max_devices - sc->max_volumes;
+	*end_idx = *start_idx + sc->max_volumes - 1;
+}
+
+/**
+ * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
+ * @sc: per adapter object
+ * @enc_id: enclosure logical identifier
+ *
+ * Returns the index of enclosure entry on success or bad index.
+ */
+static u8
+_mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id,
+    u64 phy_bits)
+{
+	struct enc_mapping_table *et_entry;
+	u8 enc_idx = 0;
+
+	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
+		et_entry = &sc->enclosure_table[enc_idx];
+		if ((et_entry->enclosure_id == le64toh(enc_id)) &&
+		    (!et_entry->phy_bits || (et_entry->phy_bits &
+		    le32toh(phy_bits))))
+			return enc_idx;
+	}
+	return MPS_ENCTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_enc_idx_from_handle - get enclosure index from handle
+ * @sc: per adapter object
+ * @enc_id: enclosure handle
+ *
+ * Returns the index of enclosure entry on success or bad index.
+ */
+static u8
+_mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle)
+{
+	struct enc_mapping_table *et_entry;
+	u8 enc_idx = 0;
+
+	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
+		et_entry = &sc->enclosure_table[enc_idx];
+		if (et_entry->missing_count)
+			continue;
+		if (et_entry->enc_handle == handle)
+			return enc_idx;
+	}
+	return MPS_ENCTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_high_missing_et_idx - get missing enclosure index
+ * @sc: per adapter object
+ *
+ * Search through the enclosure table and identifies the enclosure entry
+ * with high missing count and returns it's index
+ *
+ * Returns the index of enclosure entry on success or bad index.
+ */
+static u8
+_mapping_get_high_missing_et_idx(struct mps_softc *sc)
+{
+	struct enc_mapping_table *et_entry;
+	u8 high_missing_count = 0;
+	u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
+
+	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
+		et_entry = &sc->enclosure_table[enc_idx];
+		if ((et_entry->missing_count > high_missing_count) &&
+		    !et_entry->skip_search) {
+			high_missing_count =  et_entry->missing_count;
+			high_idx = enc_idx;
+		}
+	}
+	return high_idx;
+}
+
+/**
+ * _mapping_get_high_missing_mt_idx - get missing map table index
+ * @sc: per adapter object
+ *
+ * Search through the map table and identifies the device entry
+ * with high missing count and returns it's index
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_high_missing_mt_idx(struct mps_softc *sc)
+{
+	u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
+	u8 high_missing_count = 0;
+	u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
+	struct dev_mapping_table *mt_entry;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+
+	start_idx = 0;
+	end_idx = sc->max_devices;
+	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
+		start_idx = 1;
+	if (sc->ir_firmware)
+		_mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
+	if (start_idx == start_idx_ir)
+		start_idx = end_idx_ir + 1;
+	else
+		end_idx = start_idx_ir;
+	mt_entry = &sc->mapping_table[start_idx];
+	for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
+		if (mt_entry->missing_count > high_missing_count) {
+			high_missing_count =  mt_entry->missing_count;
+			high_idx = map_idx;
+		}
+	}
+	return high_idx;
+}
+
+/**
+ * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
+ * @sc: per adapter object
+ * @wwid: world wide unique ID of the volume
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid)
+{
+	u32 start_idx, end_idx, map_idx;
+	struct dev_mapping_table *mt_entry;
+
+	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+	mt_entry = &sc->mapping_table[start_idx];
+	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
+		if (mt_entry->physical_id == wwid)
+			return map_idx;
+
+	return MPS_MAPTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_mt_idx_from_id - get map table index from a device ID
+ * @sc: per adapter object
+ * @dev_id: device identifer (SAS Address)
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id)
+{
+	u32 map_idx;
+	struct dev_mapping_table *mt_entry;
+
+	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
+		mt_entry = &sc->mapping_table[map_idx];
+		if (mt_entry->physical_id == dev_id)
+			return map_idx;
+	}
+	return MPS_MAPTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
+ * @sc: per adapter object
+ * @wwid: volume device handle
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle)
+{
+	u32 start_idx, end_idx, map_idx;
+	struct dev_mapping_table *mt_entry;
+
+	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+	mt_entry = &sc->mapping_table[start_idx];
+	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
+		if (mt_entry->dev_handle == volHandle)
+			return map_idx;
+
+	return MPS_MAPTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_mt_idx_from_handle - get map table index from handle
+ * @sc: per adapter object
+ * @dev_id: device handle
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle)
+{
+	u32 map_idx;
+	struct dev_mapping_table *mt_entry;
+
+	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
+		mt_entry = &sc->mapping_table[map_idx];
+		if (mt_entry->dev_handle == handle)
+			return map_idx;
+	}
+	return MPS_MAPTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_free_ir_mt_idx - get first free index for a volume
+ * @sc: per adapter object
+ *
+ * Search through mapping table for free index for a volume and if no free
+ * index then looks for a volume with high mapping index
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_free_ir_mt_idx(struct mps_softc *sc)
+{
+	u8 high_missing_count = 0;
+	u32 start_idx, end_idx, map_idx;
+	u32 high_idx = MPS_MAPTABLE_BAD_IDX;
+	struct dev_mapping_table *mt_entry;
+
+	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+
+	mt_entry = &sc->mapping_table[start_idx];
+	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
+		if (!(mt_entry->device_info & MPS_MAP_IN_USE))
+			return map_idx;
+
+	mt_entry = &sc->mapping_table[start_idx];
+	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
+		if (mt_entry->missing_count > high_missing_count) {
+			high_missing_count = mt_entry->missing_count;
+			high_idx = map_idx;
+		}
+	}
+	return high_idx;
+}
+
+/**
+ * _mapping_get_free_mt_idx - get first free index for a device
+ * @sc: per adapter object
+ * @start_idx: offset in the table to start search
+ *
+ * Returns the index of map table entry on success or bad index.
+ */
+static u32
+_mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx)
+{
+	u32 map_idx, max_idx = sc->max_devices;
+	struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
+	u16 volume_mapping_flags;
+
+	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
+	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+	if (sc->ir_firmware && (volume_mapping_flags ==
+	    MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
+		max_idx -= sc->max_volumes;
+	for (map_idx  = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
+		if (!(mt_entry->device_info & (MPS_MAP_IN_USE |
+		    MPS_DEV_RESERVED)))
+			return map_idx;
+
+	return MPS_MAPTABLE_BAD_IDX;
+}
+
+/**
+ * _mapping_get_dpm_idx_from_id - get DPM index from ID
+ * @sc: per adapter object
+ * @id: volume WWID or enclosure ID or device ID
+ *
+ * Returns the index of DPM entry on success or bad index.
+ */
+static u16
+_mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits)
+{
+	u16 entry_num;
+	uint64_t PhysicalIdentifier;
+	Mpi2DriverMap0Entry_t *dpm_entry;
+
+	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+	PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
+	PhysicalIdentifier = (PhysicalIdentifier << 32) |
+	    dpm_entry->PhysicalIdentifier.Low;
+	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
+	    dpm_entry++)
+		if ((id == PhysicalIdentifier) &&
+		    (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
+		    (phy_bits & dpm_entry->PhysicalBitsMapping)))
+			return entry_num;
+
+	return MPS_DPM_BAD_IDX;
+}
+
+
+/**
+ * _mapping_get_free_dpm_idx - get first available DPM index
+ * @sc: per adapter object
+ *
+ * Returns the index of DPM entry on success or bad index.
+ */
+static u32
+_mapping_get_free_dpm_idx(struct mps_softc *sc)
+{
+	u16 entry_num;
+
+	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
+		if (!sc->dpm_entry_used[entry_num])
+			return entry_num;
+	}
+	return MPS_DPM_BAD_IDX;
+}
+
+/**
+ * _mapping_update_ir_missing_cnt - Updates missing count for a volume
+ * @sc: per adapter object
+ * @map_idx: map table index of the volume
+ * @element: IR configuration change element
+ * @wwid: IR volume ID.
+ *
+ * Updates the missing count in the map table and in the DPM entry for a volume
+ *
+ * Returns nothing.
+ */
+static void
+_mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx,
+    Mpi2EventIrConfigElement_t *element, u64 wwid)
+{
+	struct dev_mapping_table *mt_entry;
+	u8 missing_cnt, reason = element->ReasonCode;
+	u16 dpm_idx;
+	Mpi2DriverMap0Entry_t *dpm_entry;
+
+	if (!sc->is_dpm_enable)
+		return;
+	mt_entry = &sc->mapping_table[map_idx];
+	if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) {
+		mt_entry->missing_count = 0;
+	} else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
+		mt_entry->missing_count = 0;
+		mt_entry->init_complete = 0;
+	} else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) ||
+	    (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) {
+		if (!mt_entry->init_complete) {
+			if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
+				mt_entry->missing_count++;
+			else
+				mt_entry->init_complete = 1;
+		}
+		if (!mt_entry->missing_count)
+			mt_entry->missing_count++;
+		mt_entry->dev_handle = 0;
+	}
+
+	dpm_idx = mt_entry->dpm_entry_num;
+	if (dpm_idx == MPS_DPM_BAD_IDX) {
+		if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
+		    (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED))
+			dpm_idx = _mapping_get_dpm_idx_from_id(sc,
+			    mt_entry->physical_id, 0);
+		else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
+			return;
+	}
+	if (dpm_idx != MPS_DPM_BAD_IDX) {
+		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
+		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+		dpm_entry += dpm_idx;
+		missing_cnt = dpm_entry->MappingInformation &
+		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
+		if ((mt_entry->physical_id ==
+		    le64toh((u64)dpm_entry->PhysicalIdentifier.High |
+		    dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
+		    mt_entry->missing_count))
+			mt_entry->init_complete = 1;
+	} else {
+		dpm_idx = _mapping_get_free_dpm_idx(sc);
+		mt_entry->init_complete = 0;
+	}
+
+	if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) {
+		mt_entry->init_complete = 1;
+		mt_entry->dpm_entry_num = dpm_idx;
+		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
+		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+		dpm_entry += dpm_idx;
+		dpm_entry->PhysicalIdentifier.Low =
+		    (0xFFFFFFFF & mt_entry->physical_id);
+		dpm_entry->PhysicalIdentifier.High =
+		    (mt_entry->physical_id >> 32);
+		dpm_entry->DeviceIndex = map_idx;
+		dpm_entry->MappingInformation = mt_entry->missing_count;
+		dpm_entry->PhysicalBitsMapping = 0;
+		dpm_entry->Reserved1 = 0;
+		sc->dpm_flush_entry[dpm_idx] = 1;
+		sc->dpm_entry_used[dpm_idx] = 1;
+	} else if (dpm_idx == MPS_DPM_BAD_IDX) {
+		kprintf("%s: no space to add entry in DPM table\n", __func__);
+		mt_entry->init_complete = 1;
+	}
+}
+
+/**
+ * _mapping_add_to_removal_table - mark an entry for removal
+ * @sc: per adapter object
+ * @handle: Handle of enclosures/device/volume
+ *
+ * Adds the handle or DPM entry number in removal table.
+ *
+ * Returns nothing.
+ */
+static void
+_mapping_add_to_removal_table(struct mps_softc *sc, u16 handle,
+    u16 dpm_idx)
+{
+	struct map_removal_table *remove_entry;
+	u32 i;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+
+	remove_entry = sc->removal_table;
+
+	for (i = 0; i < sc->max_devices; i++, remove_entry++) {
+		if (remove_entry->dev_handle || remove_entry->dpm_entry_num !=
+		    MPS_DPM_BAD_IDX)
+			continue;
+		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+			if (dpm_idx)
+				remove_entry->dpm_entry_num = dpm_idx;
+			if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX)
+				remove_entry->dev_handle = handle;
+		} else if ((ioc_pg8_flags &
+		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING)
+			remove_entry->dev_handle = handle;
+		break;
+	}
+
+}
+
+/**
+ * _mapping_update_missing_count - Update missing count for a device
+ * @sc: per adapter object
+ * @topo_change: Topology change event entry
+ *
+ * Search through the topology change list and if any device is found not
+ * responding it's associated map table entry and DPM entry is updated
+ *
+ * Returns nothing.
+ */
+static void
+_mapping_update_missing_count(struct mps_softc *sc,
+    struct _map_topology_change *topo_change)
+{
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	u8 entry;
+	struct _map_phy_change *phy_change;
+	u32 map_idx;
+	struct dev_mapping_table *mt_entry;
+	Mpi2DriverMap0Entry_t *dpm_entry;
+
+	for (entry = 0; entry < topo_change->num_entries; entry++) {
+		phy_change = &topo_change->phy_details[entry];
+		if (!phy_change->dev_handle || (phy_change->reason !=
+		    MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
+			continue;
+		map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
+		    dev_handle);
+		phy_change->is_processed = 1;
+		if (map_idx == MPS_MAPTABLE_BAD_IDX) {
+			kprintf("%s: device is already removed from mapping "
+			    "table\n", __func__);
+			continue;
+		}
+		mt_entry = &sc->mapping_table[map_idx];
+		if (!mt_entry->init_complete) {
+			if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
+				mt_entry->missing_count++;
+			else
+				mt_entry->init_complete = 1;
+		}
+		if (!mt_entry->missing_count)
+			mt_entry->missing_count++;
+		_mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
+		mt_entry->dev_handle = 0;
+
+		if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
+		    sc->is_dpm_enable && !mt_entry->init_complete &&
+		    mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
+			dpm_entry =
+			    (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
+			    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+			dpm_entry += mt_entry->dpm_entry_num;
+			dpm_entry->MappingInformation = mt_entry->missing_count;
+			sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
+		}
+		mt_entry->init_complete = 1;
+	}
+}
+
+/**
+ * _mapping_find_enc_map_space -find map table entries for enclosure
+ * @sc: per adapter object
+ * @et_entry: enclosure entry
+ *
+ * Search through the mapping table defragment it and provide contiguous
+ * space in map table for a particular enclosure entry
+ *
+ * Returns start index in map table or bad index.
+ */
+static u32
+_mapping_find_enc_map_space(struct mps_softc *sc,
+    struct enc_mapping_table *et_entry)
+{
+	u16 vol_mapping_flags;
+	u32 skip_count, end_of_table, map_idx, enc_idx;
+	u16 num_found;
+	u32 start_idx = MPS_MAPTABLE_BAD_IDX;
+	struct dev_mapping_table *mt_entry;
+	struct enc_mapping_table *enc_entry;
+	unsigned char done_flag = 0, found_space;
+	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
+
+	skip_count = sc->num_rsvd_entries;
+	num_found = 0;
+
+	vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
+	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+
+	if (!sc->ir_firmware)
+		end_of_table = sc->max_devices;
+	else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
+		end_of_table = sc->max_devices;
+	else
+		end_of_table = sc->max_devices - sc->max_volumes;
+
+	for (map_idx = (max_num_phy_ids + skip_count);
+	    map_idx < end_of_table; map_idx++) {
+		mt_entry = &sc->mapping_table[map_idx];
+		if ((et_entry->enclosure_id == mt_entry->physical_id) &&
+		    (!mt_entry->phy_bits || (mt_entry->phy_bits &
+		    et_entry->phy_bits))) {
+			num_found += 1;
+			if (num_found == et_entry->num_slots) {
+				start_idx = (map_idx - num_found) + 1;
+				return start_idx;
+			}
+		} else
+			num_found = 0;
+	}
+	for (map_idx = (max_num_phy_ids + skip_count);
+	    map_idx < end_of_table; map_idx++) {
+		mt_entry = &sc->mapping_table[map_idx];
+		if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
+			num_found += 1;
+			if (num_found == et_entry->num_slots) {
+				start_idx = (map_idx - num_found) + 1;
+				return start_idx;
+			}
+		} else
+			num_found = 0;
+	}
+
+	while (!done_flag) {
+		enc_idx = _mapping_get_high_missing_et_idx(sc);
+		if (enc_idx == MPS_ENCTABLE_BAD_IDX)
+			return MPS_MAPTABLE_BAD_IDX;
+		enc_entry = &sc->enclosure_table[enc_idx];
+		/*VSP FIXME*/
+		enc_entry->skip_search = 1;
+		mt_entry = &sc->mapping_table[enc_entry->start_index];
+		for (map_idx = enc_entry->start_index; map_idx <
+		    (enc_entry->start_index + enc_entry->num_slots); map_idx++,
+		    mt_entry++)
+			mt_entry->device_info  &= ~MPS_DEV_RESERVED;
+		found_space = 0;
+		for (map_idx = (max_num_phy_ids +
+		    skip_count); map_idx < end_of_table; map_idx++) {
+			mt_entry = &sc->mapping_table[map_idx];
+			if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
+				num_found += 1;
+				if (num_found == et_entry->num_slots) {
+					start_idx = (map_idx - num_found) + 1;
+					found_space = 1;
+				}
+			} else
+				num_found = 0;
+		}
+
+		if (!found_space)
+			continue;
+		for (map_idx = start_idx; map_idx < (start_idx + num_found);
+		    map_idx++) {
+			enc_entry = sc->enclosure_table;
+			for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
+			    enc_idx++, enc_entry++) {
+				if (map_idx < enc_entry->start_index ||
+				    map_idx > (enc_entry->start_index +
+				    enc_entry->num_slots))
+					continue;
+				if (!enc_entry->removal_flag) {
+					enc_entry->removal_flag = 1;
+					_mapping_add_to_removal_table(sc, 0,
+					    enc_entry->dpm_entry_num);
+				}
+				mt_entry = &sc->mapping_table[map_idx];
+				if (mt_entry->device_info &
+				    MPS_MAP_IN_USE) {
+					_mapping_add_to_removal_table(sc,
+					    mt_entry->dev_handle, 0);
+					_mapping_clear_map_entry(mt_entry);
+				}
+				if (map_idx == (enc_entry->start_index +
+				    enc_entry->num_slots - 1))
+					_mapping_clear_enc_entry(et_entry);
+			}
+		}
+		enc_entry = sc->enclosure_table;
+		for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
+		    enc_idx++, enc_entry++) {
+			if (!enc_entry->removal_flag) {
+				mt_entry = &sc->mapping_table[enc_entry->
+				    start_index];
+				for (map_idx = enc_entry->start_index; map_idx <
+				    (enc_entry->start_index +
+				    enc_entry->num_slots); map_idx++,
+				    mt_entry++)
+					mt_entry->device_info |=
+					    MPS_DEV_RESERVED;
+				et_entry->skip_search = 0;
+			}
+		}
+		done_flag = 1;
+	}
+	return start_idx;
+}
+
+/**
+ * _mapping_get_dev_info -get information about newly added devices
+ * @sc: per adapter object
+ * @topo_change: Topology change event entry
+ *
+ * Search through the topology change event list and issues sas device pg0
+ * requests for the newly added device and reserved entries in tables
+ *
+ * Returns nothing
+ */
+static void
+_mapping_get_dev_info(struct mps_softc *sc,
+    struct _map_topology_change *topo_change)
+{
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2SasDevicePage0_t sas_device_pg0;
+	u8 entry, enc_idx, phy_idx;
+	u32 map_idx, index, device_info;
+	struct _map_phy_change *phy_change, *tmp_phy_change;
+	uint64_t sas_address;
+	struct enc_mapping_table *et_entry;
+	struct dev_mapping_table *mt_entry;
+	u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
+	int rc;
+
+	for (entry = 0; entry < topo_change->num_entries; entry++) {
+		phy_change = &topo_change->phy_details[entry];
+		if (phy_change->is_processed || !phy_change->dev_handle ||
+		    phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
+			continue;
+		if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
+		    &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+		    phy_change->dev_handle)) {
+			phy_change->is_processed = 1;
+			continue;
+		}
+
+		device_info = le32toh(sas_device_pg0.DeviceInfo);
+		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+			if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
+			    (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
+				rc = mpssas_get_sas_address_for_sata_disk(sc,
+				    &sas_address, phy_change->dev_handle,
+				    device_info);
+				if (rc) {
+					kprintf("%s: failed to compute the "
+					    "hashed SAS Address for SATA "
+					    "device with handle 0x%04x\n",
+					    __func__, phy_change->dev_handle);
+					sas_address =
+					    sas_device_pg0.SASAddress.High;
+					sas_address = (sas_address << 32) |
+					    sas_device_pg0.SASAddress.Low;
+				}
+				mps_dprint(sc, MPS_INFO, "SAS Address for SATA "
+					   "device = %jx\n", sas_address);
+			} else {
+				sas_address =
+					sas_device_pg0.SASAddress.High;
+				sas_address = (sas_address << 32) |
+					sas_device_pg0.SASAddress.Low;
+			}
+		} else {
+			sas_address = sas_device_pg0.SASAddress.High;
+			sas_address = (sas_address << 32) |
+			   sas_device_pg0.SASAddress.Low;
+		}
+		phy_change->physical_id = sas_address;
+		phy_change->slot = le16toh(sas_device_pg0.Slot);
+		phy_change->device_info =
+		    le32toh(sas_device_pg0.DeviceInfo);
+
+		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+			enc_idx = _mapping_get_enc_idx_from_handle(sc,
+			    topo_change->enc_handle);
+			if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
+				phy_change->is_processed = 1;
+				kprintf("%s: failed to add the device with "
+				    "handle 0x%04x because the enclosure is "
+				    "not in the mapping table\n", __func__,
+				    phy_change->dev_handle);
+				continue;
+			}
+			if (!((phy_change->device_info &
+			    MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
+			    (phy_change->device_info &
+			    (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
+			    MPI2_SAS_DEVICE_INFO_STP_TARGET |
+			    MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
+				phy_change->is_processed = 1;
+				continue;
+			}
+			et_entry = &sc->enclosure_table[enc_idx];
+			if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
+				continue;
+			if (!topo_change->exp_handle) {
+				map_idx	= sc->num_rsvd_entries;
+				et_entry->start_index = map_idx;
+			} else {
+				map_idx = _mapping_find_enc_map_space(sc,
+				    et_entry);
+				et_entry->start_index = map_idx;
+				if (et_entry->start_index ==
+				    MPS_MAPTABLE_BAD_IDX) {
+					phy_change->is_processed = 1;
+					for (phy_idx = 0; phy_idx <
+					    topo_change->num_entries;
+					    phy_idx++) {
+						tmp_phy_change =
+						    &topo_change->phy_details
+						    [phy_idx];
+						if (tmp_phy_change->reason ==
+						    add_code)
+							tmp_phy_change->
+							    is_processed = 1;
+					}
+					break;
+				}
+			}
+			mt_entry = &sc->mapping_table[map_idx];
+			for (index = map_idx; index < (et_entry->num_slots
+			    + map_idx); index++, mt_entry++) {
+				mt_entry->device_info = MPS_DEV_RESERVED;
+				mt_entry->physical_id = et_entry->enclosure_id;
+				mt_entry->phy_bits = et_entry->phy_bits;
+			}
+		}
+	}
+}
+
+/**
+ * _mapping_set_mid_to_eid -set map table data from enclosure table
+ * @sc: per adapter object
+ * @et_entry: enclosure entry
+ *
+ * Returns nothing
+ */
+static inline void
+_mapping_set_mid_to_eid(struct mps_softc *sc,
+    struct enc_mapping_table *et_entry)
+{
+	struct dev_mapping_table *mt_entry;
+	u16 slots = et_entry->num_slots, map_idx;
+	u32 start_idx = et_entry->start_index;
+	if (start_idx != MPS_MAPTABLE_BAD_IDX) {
+		mt_entry = &sc->mapping_table[start_idx];
+		for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
+			mt_entry->physical_id = et_entry->enclosure_id;
+	}
+}
+
+/**
+ * _mapping_clear_removed_entries - mark the entries to be cleared
+ * @sc: per adapter object
+ *
+ * Search through the removal table and mark the entries which needs to be
+ * flushed to DPM and also updates the map table and enclosure table by
+ * clearing the corresponding entries.
+ *
+ * Returns nothing
+ */
+static void
+_mapping_clear_removed_entries(struct mps_softc *sc)
+{
+	u32 remove_idx;
+	struct map_removal_table *remove_entry;
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	u8 done_flag = 0, num_entries, m, i;
+	struct enc_mapping_table *et_entry, *from, *to;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+
+	if (sc->is_dpm_enable) {
+		remove_entry = sc->removal_table;
+		for (remove_idx = 0; remove_idx < sc->max_devices;
+		    remove_idx++, remove_entry++) {
+			if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
+				dpm_entry = (Mpi2DriverMap0Entry_t *)
+				    ((u8 *) sc->dpm_pg0 +
+				    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+				dpm_entry += remove_entry->dpm_entry_num;
+				dpm_entry->PhysicalIdentifier.Low = 0;
+				dpm_entry->PhysicalIdentifier.High = 0;
+				dpm_entry->DeviceIndex = 0;
+				dpm_entry->MappingInformation = 0;
+				dpm_entry->PhysicalBitsMapping = 0;
+				sc->dpm_flush_entry[remove_entry->
+				    dpm_entry_num] = 1;
+				sc->dpm_entry_used[remove_entry->dpm_entry_num]
+				    = 0;
+				remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
+			}
+		}
+	}
+	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+		num_entries = sc->num_enc_table_entries;
+		while (!done_flag) {
+			done_flag = 1;
+			et_entry = sc->enclosure_table;
+			for (i = 0; i < num_entries; i++, et_entry++) {
+				if (!et_entry->enc_handle && et_entry->
+				    init_complete) {
+					done_flag = 0;
+					if (i != (num_entries - 1)) {
+						from = &sc->enclosure_table
+						    [i+1];
+						to = &sc->enclosure_table[i];
+						for (m = i; m < (num_entries -
+						    1); m++, from++, to++) {
+							_mapping_set_mid_to_eid
+							    (sc, to);
+							*to = *from;
+						}
+						_mapping_clear_enc_entry(to);
+						sc->num_enc_table_entries--;
+						num_entries =
+						    sc->num_enc_table_entries;
+					} else {
+						_mapping_clear_enc_entry
+						    (et_entry);
+						sc->num_enc_table_entries--;
+						num_entries =
+						    sc->num_enc_table_entries;
+					}
+				}
+			}
+		}
+	}
+}
+
+/**
+ * _mapping_add_new_device -Add the new device into mapping table
+ * @sc: per adapter object
+ * @topo_change: Topology change event entry
+ *
+ * Search through the topology change event list and updates map table,
+ * enclosure table and DPM pages for for the newly added devices.
+ *
+ * Returns nothing
+ */
+static void
+_mapping_add_new_device(struct mps_softc *sc,
+    struct _map_topology_change *topo_change)
+{
+	u8 enc_idx, missing_cnt, is_removed = 0;
+	u16 dpm_idx;
+	u32 search_idx, map_idx;
+	u32 entry;
+	struct dev_mapping_table *mt_entry;
+	struct enc_mapping_table *et_entry;
+	struct _map_phy_change *phy_change;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	uint64_t temp64_var;
+	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
+	u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
+	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
+
+	for (entry = 0; entry < topo_change->num_entries; entry++) {
+		phy_change = &topo_change->phy_details[entry];
+		if (phy_change->is_processed)
+			continue;
+		if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
+		    !phy_change->dev_handle) {
+			phy_change->is_processed = 1;
+			continue;
+		}
+		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+			enc_idx = _mapping_get_enc_idx_from_handle
+			    (sc, topo_change->enc_handle);
+			if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
+				phy_change->is_processed = 1;
+				kprintf("%s: failed to add the device with "
+				    "handle 0x%04x because the enclosure is "
+				    "not in the mapping table\n", __func__,
+				    phy_change->dev_handle);
+				continue;
+			}
+			et_entry = &sc->enclosure_table[enc_idx];
+			if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
+				phy_change->is_processed = 1;
+				if (!sc->mt_full_retry) {
+					sc->mt_add_device_failed = 1;
+					continue;
+				}
+				kprintf("%s: failed to add the device with "
+				    "handle 0x%04x because there is no free "
+				    "space available in the mapping table\n",
+				    __func__, phy_change->dev_handle);
+				continue;
+			}
+			map_idx = et_entry->start_index + phy_change->slot -
+			    et_entry->start_slot;
+			mt_entry = &sc->mapping_table[map_idx];
+			mt_entry->physical_id = phy_change->physical_id;
+			mt_entry->channel = 0;
+			mt_entry->id = map_idx;
+			mt_entry->dev_handle = phy_change->dev_handle;
+			mt_entry->missing_count = 0;
+			mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
+			mt_entry->device_info = phy_change->device_info |
+			    (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
+			if (sc->is_dpm_enable) {
+				dpm_idx = et_entry->dpm_entry_num;
+				if (dpm_idx == MPS_DPM_BAD_IDX)
+					dpm_idx = _mapping_get_dpm_idx_from_id
+					    (sc, et_entry->enclosure_id,
+					     et_entry->phy_bits);
+				if (dpm_idx == MPS_DPM_BAD_IDX) {
+					dpm_idx = _mapping_get_free_dpm_idx(sc);
+					if (dpm_idx != MPS_DPM_BAD_IDX) {
+						dpm_entry =
+						    (Mpi2DriverMap0Entry_t *)
+						    ((u8 *) sc->dpm_pg0 +
+						     hdr_sz);
+						dpm_entry += dpm_idx;
+						dpm_entry->
+						    PhysicalIdentifier.Low =
+						    (0xFFFFFFFF &
+						    et_entry->enclosure_id);
+						dpm_entry->
+						    PhysicalIdentifier.High =
+						    ( et_entry->enclosure_id
+						     >> 32);
+						dpm_entry->DeviceIndex =
+						    (U16)et_entry->start_index;
+						dpm_entry->MappingInformation =
+							et_entry->num_slots;
+						dpm_entry->MappingInformation
+						    <<= map_shift;
+						dpm_entry->PhysicalBitsMapping
+						    = et_entry->phy_bits;
+						et_entry->dpm_entry_num =
+						    dpm_idx;
+		/* FIXME Do I need to set the dpm_idxin mt_entry too */
+						sc->dpm_entry_used[dpm_idx] = 1;
+						sc->dpm_flush_entry[dpm_idx] =
+						    1;
+						phy_change->is_processed = 1;
+					} else {
+						phy_change->is_processed = 1;
+						kprintf("%s: failed to add the "
+						    "device with handle 0x%04x "
+						    "to persistent table "
+						    "because there is no free "
+						    "space available\n",
+						    __func__,
+						    phy_change->dev_handle);
+					}
+				} else {
+					et_entry->dpm_entry_num = dpm_idx;
+					mt_entry->dpm_entry_num = dpm_idx;
+				}
+			}
+			/* FIXME Why not mt_entry too? */
+			et_entry->init_complete = 1;
+		} else if ((ioc_pg8_flags &
+		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+			map_idx = _mapping_get_mt_idx_from_id
+			    (sc, phy_change->physical_id);
+			if (map_idx == MPS_MAPTABLE_BAD_IDX) {
+				search_idx = sc->num_rsvd_entries;
+				if (topo_change->exp_handle)
+					search_idx += max_num_phy_ids;
+				map_idx = _mapping_get_free_mt_idx(sc,
+				    search_idx);
+			}
+			if (map_idx == MPS_MAPTABLE_BAD_IDX) {
+				map_idx = _mapping_get_high_missing_mt_idx(sc);
+				if (map_idx != MPS_MAPTABLE_BAD_IDX) {
+					mt_entry = &sc->mapping_table[map_idx];
+					if (mt_entry->dev_handle) {
+						_mapping_add_to_removal_table
+						    (sc, mt_entry->dev_handle,
+						     0);
+						is_removed = 1;
+					}
+					mt_entry->init_complete = 0;
+				}
+			}
+			if (map_idx != MPS_MAPTABLE_BAD_IDX) {
+				mt_entry = &sc->mapping_table[map_idx];
+				mt_entry->physical_id = phy_change->physical_id;
+				mt_entry->channel = 0;
+				mt_entry->id = map_idx;
+				mt_entry->dev_handle = phy_change->dev_handle;
+				mt_entry->missing_count = 0;
+				mt_entry->device_info = phy_change->device_info
+				    | (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
+			} else {
+				phy_change->is_processed = 1;
+				if (!sc->mt_full_retry) {
+					sc->mt_add_device_failed = 1;
+					continue;
+				}
+				kprintf("%s: failed to add the device with "
+				    "handle 0x%04x because there is no free "
+				    "space available in the mapping table\n",
+				    __func__, phy_change->dev_handle);
+				continue;
+			}
+			if (sc->is_dpm_enable) {
+				if (mt_entry->dpm_entry_num !=
+				    MPS_DPM_BAD_IDX) {
+					dpm_idx = mt_entry->dpm_entry_num;
+					dpm_entry = (Mpi2DriverMap0Entry_t *)
+					    ((u8 *)sc->dpm_pg0 + hdr_sz);
+					dpm_entry += dpm_idx;
+					missing_cnt = dpm_entry->
+					    MappingInformation &
+					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
+					temp64_var = dpm_entry->
+					    PhysicalIdentifier.High;
+					temp64_var = (temp64_var << 32) |
+					   dpm_entry->PhysicalIdentifier.Low;
+					if ((mt_entry->physical_id ==
+					    temp64_var) && !missing_cnt)
+						mt_entry->init_complete = 1;
+				} else {
+					dpm_idx = _mapping_get_free_dpm_idx(sc);
+					mt_entry->init_complete = 0;
+				}
+				if (dpm_idx != MPS_DPM_BAD_IDX &&
+				    !mt_entry->init_complete) {
+					mt_entry->init_complete = 1;
+					mt_entry->dpm_entry_num = dpm_idx;
+					dpm_entry = (Mpi2DriverMap0Entry_t *)
+					    ((u8 *)sc->dpm_pg0 + hdr_sz);
+					dpm_entry += dpm_idx;
+					dpm_entry->PhysicalIdentifier.Low =
+					    (0xFFFFFFFF &
+					    mt_entry->physical_id);
+					dpm_entry->PhysicalIdentifier.High =
+					    (mt_entry->physical_id >> 32);
+					dpm_entry->DeviceIndex = (U16) map_idx;
+					dpm_entry->MappingInformation = 0;
+					dpm_entry->PhysicalBitsMapping = 0;
+					sc->dpm_entry_used[dpm_idx] = 1;
+					sc->dpm_flush_entry[dpm_idx] = 1;
+					phy_change->is_processed = 1;
+				} else if (dpm_idx == MPS_DPM_BAD_IDX) {
+						phy_change->is_processed = 1;
+						kprintf("%s: failed to add the "
+						    "device with handle 0x%04x "
+						    "to persistent table "
+						    "because there is no free "
+						    "space available\n",
+						    __func__,
+						    phy_change->dev_handle);
+				}
+			}
+			mt_entry->init_complete = 1;
+		}
+
+		phy_change->is_processed = 1;
+	}
+	if (is_removed)
+		_mapping_clear_removed_entries(sc);
+}
+
+/**
+ * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
+ * @sc: per adapter object
+ *
+ * Returns nothing
+ */
+static void
+_mapping_flush_dpm_pages(struct mps_softc *sc)
+{
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2DriverMappingPage0_t config_page;
+	u16 entry_num;
+
+	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
+		if (!sc->dpm_flush_entry[entry_num])
+			continue;
+		memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
+		memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
+		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
+		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+		dpm_entry += entry_num;
+		dpm_entry->MappingInformation = htole16(dpm_entry->
+		    MappingInformation);
+		dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
+		dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
+		    PhysicalBitsMapping);
+		memcpy(&config_page.Entry, (u8 *)dpm_entry,
+		    sizeof(Mpi2DriverMap0Entry_t));
+		/* TODO-How to handle failed writes? */
+		if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
+		    entry_num)) {
+			kprintf("%s: write of dpm entry %d for device failed\n",
+			     __func__, entry_num);
+		} else
+			sc->dpm_flush_entry[entry_num] = 0;
+		dpm_entry->MappingInformation = le16toh(dpm_entry->
+		    MappingInformation);
+		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
+		dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
+		    PhysicalBitsMapping);
+	}
+}
+
+/**
+ * _mapping_allocate_memory- allocates the memory required for mapping tables
+ * @sc: per adapter object
+ *
+ * Allocates the memory for all the tables required for host mapping
+ *
+ * Return 0 on success or non-zero on failure.
+ */
+int
+mps_mapping_allocate_memory(struct mps_softc *sc)
+{
+	uint32_t dpm_pg0_sz;
+
+	sc->mapping_table = kmalloc((sizeof(struct dev_mapping_table) *
+	    sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
+	if (!sc->mapping_table)
+		goto free_resources;
+
+	sc->removal_table = kmalloc((sizeof(struct map_removal_table) *
+	    sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
+	if (!sc->removal_table)
+		goto free_resources;
+
+	sc->enclosure_table = kmalloc((sizeof(struct enc_mapping_table) *
+	    sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT);
+	if (!sc->enclosure_table)
+		goto free_resources;
+
+	sc->dpm_entry_used = kmalloc((sizeof(u8) * sc->max_dpm_entries),
+	    M_MPT2, M_ZERO|M_NOWAIT);
+	if (!sc->dpm_entry_used)
+		goto free_resources;
+
+	sc->dpm_flush_entry = kmalloc((sizeof(u8) * sc->max_dpm_entries),
+	    M_MPT2, M_ZERO|M_NOWAIT);
+	if (!sc->dpm_flush_entry)
+		goto free_resources;
+
+	dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
+	    (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
+
+	sc->dpm_pg0 = kmalloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT);
+	if (!sc->dpm_pg0) {
+		kprintf("%s: memory alloc failed for dpm page; disabling dpm\n",
+		    __func__);
+		sc->is_dpm_enable = 0;
+	}
+
+	return 0;
+
+free_resources:
+	kfree(sc->mapping_table, M_MPT2);
+	kfree(sc->removal_table, M_MPT2);
+	kfree(sc->enclosure_table, M_MPT2);
+	kfree(sc->dpm_entry_used, M_MPT2);
+	kfree(sc->dpm_flush_entry, M_MPT2);
+	kfree(sc->dpm_pg0, M_MPT2);
+	kprintf("%s: device initialization failed due to failure in mapping "
+	    "table memory allocation\n", __func__);
+	return -1;
+}
+
+/**
+ * mps_mapping_free_memory- frees the memory allocated for mapping tables
+ * @sc: per adapter object
+ *
+ * Returns nothing.
+ */
+void
+mps_mapping_free_memory(struct mps_softc *sc)
+{
+	kfree(sc->mapping_table, M_MPT2);
+	kfree(sc->removal_table, M_MPT2);
+	kfree(sc->enclosure_table, M_MPT2);
+	kfree(sc->dpm_entry_used, M_MPT2);
+	kfree(sc->dpm_flush_entry, M_MPT2);
+	kfree(sc->dpm_pg0, M_MPT2);
+}
+
+
+static void
+_mapping_process_dpm_pg0(struct mps_softc *sc)
+{
+	u8 missing_cnt, enc_idx;
+	u16 slot_id, entry_num, num_slots;
+	u32 map_idx, dev_idx, start_idx, end_idx;
+	struct dev_mapping_table *mt_entry;
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
+	struct enc_mapping_table *et_entry;
+	u64 physical_id;
+	u32 phy_bits = 0;
+
+	if (sc->ir_firmware)
+		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+
+	dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
+	    dpm_entry++) {
+		physical_id = dpm_entry->PhysicalIdentifier.High;
+		physical_id = (physical_id << 32) |
+		    dpm_entry->PhysicalIdentifier.Low;
+		if (!physical_id) {
+			sc->dpm_entry_used[entry_num] = 0;
+			continue;
+		}
+		sc->dpm_entry_used[entry_num] = 1;
+		dpm_entry->MappingInformation = le16toh(dpm_entry->
+		    MappingInformation);
+		missing_cnt = dpm_entry->MappingInformation &
+		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
+		dev_idx = le16toh(dpm_entry->DeviceIndex);
+		phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
+		if (sc->ir_firmware && (dev_idx >= start_idx) &&
+		    (dev_idx <= end_idx)) {
+			mt_entry = &sc->mapping_table[dev_idx];
+			mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High;
+			mt_entry->physical_id = (mt_entry->physical_id << 32) |
+			    dpm_entry->PhysicalIdentifier.Low;
+			mt_entry->channel = MPS_RAID_CHANNEL;
+			mt_entry->id = dev_idx;
+			mt_entry->missing_count = missing_cnt;
+			mt_entry->dpm_entry_num = entry_num;
+			mt_entry->device_info = MPS_DEV_RESERVED;
+			continue;
+		}
+		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+			if (dev_idx <  (sc->num_rsvd_entries +
+			    max_num_phy_ids)) {
+				slot_id = 0;
+				if (ioc_pg8_flags &
+				    MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
+					slot_id = 1;
+				num_slots = max_num_phy_ids;
+			} else {
+				slot_id = 0;
+				num_slots = dpm_entry->MappingInformation &
+				    MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
+				num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
+			}
+			enc_idx = sc->num_enc_table_entries;
+			if (enc_idx >= sc->max_enclosures) {
+				kprintf("%s: enclosure entries exceed max "
+				    "enclosures of %d\n", __func__,
+				    sc->max_enclosures);
+				break;
+			}
+			sc->num_enc_table_entries++;
+			et_entry = &sc->enclosure_table[enc_idx];
+			physical_id = dpm_entry->PhysicalIdentifier.High;
+			et_entry->enclosure_id = (physical_id << 32) |
+			    dpm_entry->PhysicalIdentifier.Low;
+			et_entry->start_index = dev_idx;
+			et_entry->dpm_entry_num = entry_num;
+			et_entry->num_slots = num_slots;
+			et_entry->start_slot = slot_id;
+			et_entry->missing_count = missing_cnt;
+			et_entry->phy_bits = phy_bits;
+
+			mt_entry = &sc->mapping_table[dev_idx];
+			for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
+			    map_idx++, mt_entry++) {
+				if (mt_entry->dpm_entry_num !=
+				    MPS_DPM_BAD_IDX) {
+					kprintf("%s: conflict in mapping table "
+					    "for enclosure %d\n", __func__,
+					    enc_idx);
+					break;
+				}
+				physical_id = dpm_entry->PhysicalIdentifier.High;
+				mt_entry->physical_id = (physical_id << 32) |
+				    dpm_entry->PhysicalIdentifier.Low;
+				mt_entry->phy_bits = phy_bits;
+				mt_entry->channel = 0;
+				mt_entry->id = dev_idx;
+				mt_entry->dpm_entry_num = entry_num;
+				mt_entry->missing_count = missing_cnt;
+				mt_entry->device_info = MPS_DEV_RESERVED;
+			}
+		} else if ((ioc_pg8_flags &
+		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+			map_idx = dev_idx;
+			mt_entry = &sc->mapping_table[map_idx];
+			if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
+				kprintf("%s: conflict in mapping table for "
+				    "device %d\n", __func__, map_idx);
+				break;
+			}
+			physical_id = dpm_entry->PhysicalIdentifier.High;
+			mt_entry->physical_id = (physical_id << 32) |
+			    dpm_entry->PhysicalIdentifier.Low;
+			mt_entry->phy_bits = phy_bits;
+			mt_entry->channel = 0;
+			mt_entry->id = dev_idx;
+			mt_entry->missing_count = missing_cnt;
+			mt_entry->dpm_entry_num = entry_num;
+			mt_entry->device_info = MPS_DEV_RESERVED;
+		}
+	} /*close the loop for DPM table */
+}
+
+/*
+ * mps_mapping_check_devices - start of the day check for device availabilty
+ * @sc: per adapter object
+ * @sleep_flag: Flag indicating whether this function can sleep or not
+ *
+ * Returns nothing.
+ */
+void
+mps_mapping_check_devices(struct mps_softc *sc, int sleep_flag)
+{
+	u32 i;
+/*	u32 cntdn, i;
+	u32 timeout = 60;*/
+	struct dev_mapping_table *mt_entry;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	struct enc_mapping_table *et_entry;
+	u32 start_idx, end_idx;
+
+	/* We need to ucomment this when this function is called
+	 * from the port enable complete */
+#if 0
+	sc->track_mapping_events = 0;
+	cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+	do {
+		if (!sc->pending_map_events)
+			break;
+		if (sleep_flag == CAN_SLEEP)
+			pause("mps_pause", (hz/1000));/* 1msec sleep */
+		else
+			DELAY(500); /* 500 useconds delay */
+	} while (--cntdn);
+
+
+	if (!cntdn)
+		kprintf("%s: there are %d"
+		    " pending events after %d seconds of delay\n",
+		    __func__, sc->pending_map_events, timeout);
+#endif
+	sc->pending_map_events = 0;
+
+	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
+		et_entry = sc->enclosure_table;
+		for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
+			if (!et_entry->init_complete) {
+				if (et_entry->missing_count <
+				    MPS_MAX_MISSING_COUNT) {
+					et_entry->missing_count++;
+					if (et_entry->dpm_entry_num !=
+					    MPS_DPM_BAD_IDX)
+						_mapping_commit_enc_entry(sc,
+						    et_entry);
+				}
+				et_entry->init_complete = 1;
+			}
+		}
+		if (!sc->ir_firmware)
+			return;
+		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
+		mt_entry = &sc->mapping_table[start_idx];
+		for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
+			if (mt_entry->device_info & MPS_DEV_RESERVED
+			    && !mt_entry->physical_id)
+				mt_entry->init_complete = 1;
+			else if (mt_entry->device_info & MPS_DEV_RESERVED) {
+				if (!mt_entry->init_complete) {
+					if (mt_entry->missing_count <
+					    MPS_MAX_MISSING_COUNT) {
+						mt_entry->missing_count++;
+						if (mt_entry->dpm_entry_num !=
+						    MPS_DPM_BAD_IDX)
+						_mapping_commit_map_entry(sc,
+						    mt_entry);
+					}
+					mt_entry->init_complete = 1;
+				}
+			}
+		}
+	} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
+	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+		mt_entry = sc->mapping_table;
+		for (i = 0; i < sc->max_devices; i++, mt_entry++) {
+			if (mt_entry->device_info & MPS_DEV_RESERVED
+			    && !mt_entry->physical_id)
+				mt_entry->init_complete = 1;
+			else if (mt_entry->device_info & MPS_DEV_RESERVED) {
+				if (!mt_entry->init_complete) {
+					if (mt_entry->missing_count <
+					    MPS_MAX_MISSING_COUNT) {
+						mt_entry->missing_count++;
+						if (mt_entry->dpm_entry_num !=
+						    MPS_DPM_BAD_IDX)
+						_mapping_commit_map_entry(sc,
+						    mt_entry);
+					}
+					mt_entry->init_complete = 1;
+				}
+			}
+		}
+	}
+}
+
+
+/**
+ * mps_mapping_is_reinit_required - check whether event replay required
+ * @sc: per adapter object
+ *
+ * Checks the per ioc flags and decide whether reinit of events required
+ *
+ * Returns 1 for reinit of ioc 0 for not.
+ */
+int mps_mapping_is_reinit_required(struct mps_softc *sc)
+{
+	if (!sc->mt_full_retry && sc->mt_add_device_failed) {
+		sc->mt_full_retry = 1;
+		sc->mt_add_device_failed = 0;
+		_mapping_flush_dpm_pages(sc);
+		return 1;
+	}
+	sc->mt_full_retry = 1;
+	return 0;
+}
+
+/**
+ * mps_mapping_initialize - initialize mapping tables
+ * @sc: per adapter object
+ *
+ * Read controller persitant mapping tables into internal data area.
+ *
+ * Return 0 for success or non-zero for failure.
+ */
+int
+mps_mapping_initialize(struct mps_softc *sc)
+{
+	uint16_t volume_mapping_flags, dpm_pg0_sz;
+	uint32_t i;
+	Mpi2ConfigReply_t mpi_reply;
+	int error;
+	uint8_t retry_count;
+	uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+
+	/* The additional 1 accounts for the virtual enclosure
+	 * created for the controller
+	 */
+	sc->max_enclosures = sc->facts->MaxEnclosures + 1;
+	sc->max_expanders = sc->facts->MaxSasExpanders;
+	sc->max_volumes = sc->facts->MaxVolumes;
+	sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
+	sc->pending_map_events = 0;
+	sc->num_enc_table_entries = 0;
+	sc->num_rsvd_entries = 0;
+	sc->num_channels = 1;
+	sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
+	sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
+	sc->track_mapping_events = 0;
+
+	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
+		sc->is_dpm_enable = 0;
+
+	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
+		sc->num_rsvd_entries = 1;
+
+	volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
+	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+	if (sc->ir_firmware && (volume_mapping_flags ==
+	    MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
+		sc->num_rsvd_entries += sc->max_volumes;
+
+	error = mps_mapping_allocate_memory(sc);
+	if (error)
+		return (error);
+
+	for (i = 0; i < sc->max_devices; i++)
+		_mapping_clear_map_entry(sc->mapping_table + i);
+
+	for (i = 0; i < sc->max_enclosures; i++)
+		_mapping_clear_enc_entry(sc->enclosure_table + i);
+
+	for (i = 0; i < sc->max_devices; i++) {
+		sc->removal_table[i].dev_handle = 0;
+		sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX;
+	}
+
+	memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
+	memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
+
+	if (sc->is_dpm_enable) {
+		dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
+		    (sc->max_dpm_entries *
+		     sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
+		retry_count = 0;
+
+retry_read_dpm:
+		if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
+		    dpm_pg0_sz)) {
+			kprintf("%s: dpm page read failed; disabling dpm\n",
+			    __func__);
+			if (retry_count < 3) {
+				retry_count++;
+				goto retry_read_dpm;
+			}
+			sc->is_dpm_enable = 0;
+		}
+	}
+
+	if (sc->is_dpm_enable)
+		_mapping_process_dpm_pg0(sc);
+
+	sc->track_mapping_events = 1;
+	return 0;
+}
+
+/**
+ * mps_mapping_exit - clear mapping table and associated memory
+ * @sc: per adapter object
+ *
+ * Returns nothing.
+ */
+void
+mps_mapping_exit(struct mps_softc *sc)
+{
+	_mapping_flush_dpm_pages(sc);
+	mps_mapping_free_memory(sc);
+}
+
+/**
+ * mps_mapping_get_sas_id - assign a target id for sas device
+ * @sc: per adapter object
+ * @sas_address: sas address of the device
+ * @handle: device handle
+ *
+ * Returns valid ID on success or BAD_ID.
+ */
+unsigned int
+mps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle)
+{
+	u32 map_idx;
+	struct dev_mapping_table *mt_entry;
+
+	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
+		mt_entry = &sc->mapping_table[map_idx];
+		if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
+		    sas_address)
+			return mt_entry->id;
+	}
+
+	return MPS_MAP_BAD_ID;
+}
+
+/**
+ * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using
+ * only the dev handle.  This is just a wrapper function for the local function
+ * _mapping_get_mt_idx_from_handle.
+ * @sc: per adapter object
+ * @handle: device handle
+ *
+ * Returns valid ID on success or BAD_ID.
+ */
+unsigned int
+mps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle)
+{
+	return (_mapping_get_mt_idx_from_handle(sc, handle));
+}
+
+/**
+ * mps_mapping_get_raid_id - assign a target id for raid device
+ * @sc: per adapter object
+ * @wwid: world wide identifier for raid volume
+ * @handle: device handle
+ *
+ * Returns valid ID on success or BAD_ID.
+ */
+unsigned int
+mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle)
+{
+	u32 map_idx;
+	struct dev_mapping_table *mt_entry;
+
+	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
+		mt_entry = &sc->mapping_table[map_idx];
+		if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
+		    wwid)
+			return mt_entry->id;
+	}
+
+	return MPS_MAP_BAD_ID;
+}
+
+/**
+ * mps_mapping_get_raid_id_from_handle - find raid device in mapping table
+ * using only the volume dev handle.  This is just a wrapper function for the
+ * local function _mapping_get_ir_mt_idx_from_handle.
+ * @sc: per adapter object
+ * @volHandle: volume device handle
+ *
+ * Returns valid ID on success or BAD_ID.
+ */
+unsigned int
+mps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle)
+{
+	return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
+}
+
+/**
+ * mps_mapping_enclosure_dev_status_change_event - handle enclosure events
+ * @sc: per adapter object
+ * @event_data: event data payload
+ *
+ * Return nothing.
+ */
+void
+mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc,
+    Mpi2EventDataSasEnclDevStatusChange_t *event_data)
+{
+	u8 enc_idx, missing_count;
+	struct enc_mapping_table *et_entry;
+	Mpi2DriverMap0Entry_t *dpm_entry;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
+	u8 update_phy_bits = 0;
+	u32 saved_phy_bits;
+	uint64_t temp64_var;
+
+	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
+	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
+		goto out;
+
+	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
+	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
+
+	if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
+		if (!event_data->NumSlots) {
+			kprintf("%s: enclosure with handle = 0x%x reported 0 "
+			    "slots\n", __func__,
+			    le16toh(event_data->EnclosureHandle));
+			goto out;
+		}
+		temp64_var = event_data->EnclosureLogicalID.High;
+		temp64_var = (temp64_var << 32) |
+		    event_data->EnclosureLogicalID.Low;
+		enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
+		    event_data->PhyBits);
+		if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
+			et_entry = &sc->enclosure_table[enc_idx];
+			if (et_entry->init_complete &&
+			    !et_entry->missing_count) {
+				kprintf("%s: enclosure %d is already present "
+				    "with handle = 0x%x\n",__func__, enc_idx,
+				    et_entry->enc_handle);
+				goto out;
+			}
+			et_entry->enc_handle = le16toh(event_data->
+			    EnclosureHandle);
+			et_entry->start_slot = le16toh(event_data->StartSlot);
+			saved_phy_bits = et_entry->phy_bits;
+			et_entry->phy_bits |= le32toh(event_data->PhyBits);
+			if (saved_phy_bits != et_entry->phy_bits)
+				update_phy_bits = 1;
+			if (et_entry->missing_count || update_phy_bits) {
+				et_entry->missing_count = 0;
+				if (sc->is_dpm_enable &&
+				    et_entry->dpm_entry_num !=
+				    MPS_DPM_BAD_IDX) {
+					dpm_entry += et_entry->dpm_entry_num;
+					missing_count =
+					    (u8)(dpm_entry->MappingInformation &
+					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
+					if (!et_entry->init_complete && (
+					    missing_count || update_phy_bits)) {
+						dpm_entry->MappingInformation
+						    = et_entry->num_slots;
+						dpm_entry->MappingInformation
+						    <<= map_shift;
+						dpm_entry->PhysicalBitsMapping
+						    = et_entry->phy_bits;
+						sc->dpm_flush_entry[et_entry->
+						    dpm_entry_num] = 1;
+					}
+				}
+			}
+		} else {
+			enc_idx = sc->num_enc_table_entries;
+			if (enc_idx >= sc->max_enclosures) {
+				kprintf("%s: enclosure can not be added; "
+				    "mapping table is full\n", __func__);
+				goto out;
+			}
+			sc->num_enc_table_entries++;
+			et_entry = &sc->enclosure_table[enc_idx];
+			et_entry->enc_handle = le16toh(event_data->
+			    EnclosureHandle);
+			et_entry->enclosure_id = event_data->
+			    EnclosureLogicalID.High;
+			et_entry->enclosure_id = ( et_entry->enclosure_id <<
+			    32) | event_data->EnclosureLogicalID.Low;
+			et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
+			et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
+			et_entry->num_slots = le16toh(event_data->NumSlots);
+			et_entry->start_slot = le16toh(event_data->StartSlot);
+			et_entry->phy_bits = le32toh(event_data->PhyBits);
+		}
+		et_entry->init_complete = 1;
+	} else if (event_data->ReasonCode ==
+	    MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
+		enc_idx = _mapping_get_enc_idx_from_handle(sc,
+		    le16toh(event_data->EnclosureHandle));
+		if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
+			kprintf("%s: cannot unmap enclosure %d because it has "
+			    "already been deleted", __func__, enc_idx);
+			goto out;
+		}
+		et_entry = &sc->enclosure_table[enc_idx];
+		if (!et_entry->init_complete) {
+			if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
+				et_entry->missing_count++;
+			else
+				et_entry->init_complete = 1;
+		}
+		if (!et_entry->missing_count)
+			et_entry->missing_count++;
+		if (sc->is_dpm_enable && !et_entry->init_complete &&
+		    et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
+			dpm_entry += et_entry->dpm_entry_num;
+			dpm_entry->MappingInformation = et_entry->num_slots;
+			dpm_entry->MappingInformation <<= map_shift;
+			dpm_entry->MappingInformation |=
+			    et_entry->missing_count;
+			sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
+		}
+		et_entry->init_complete = 1;
+	}
+
+out:
+	_mapping_flush_dpm_pages(sc);
+	if (sc->pending_map_events)
+		sc->pending_map_events--;
+}
+
+/**
+ * mps_mapping_topology_change_event - handle topology change events
+ * @sc: per adapter object
+ * @event_data: event data payload
+ *
+ * Returns nothing.
+ */
+void
+mps_mapping_topology_change_event(struct mps_softc *sc,
+    Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+	struct _map_topology_change topo_change;
+	struct _map_phy_change *phy_change;
+	Mpi2EventSasTopoPhyEntry_t *event_phy_change;
+	u8 i, num_entries;
+
+	topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
+	topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
+	num_entries = event_data->NumEntries;
+	topo_change.num_entries = num_entries;
+	topo_change.start_phy_num = event_data->StartPhyNum;
+	topo_change.num_phys = event_data->NumPhys;
+	topo_change.exp_status = event_data->ExpStatus;
+	event_phy_change = event_data->PHY;
+	topo_change.phy_details = NULL;
+
+	if (!num_entries)
+		goto out;
+	phy_change = kmalloc(sizeof(struct _map_phy_change) * num_entries,
+	    M_MPT2, M_NOWAIT|M_ZERO);
+	topo_change.phy_details = phy_change;
+	if (!phy_change)
+		goto out;
+	for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
+		phy_change->dev_handle = le16toh(event_phy_change->
+		    AttachedDevHandle);
+		phy_change->reason = event_phy_change->PhyStatus &
+		    MPI2_EVENT_SAS_TOPO_RC_MASK;
+	}
+	_mapping_update_missing_count(sc, &topo_change);
+	_mapping_get_dev_info(sc, &topo_change);
+	_mapping_clear_removed_entries(sc);
+	_mapping_add_new_device(sc, &topo_change);
+
+out:
+	kfree(topo_change.phy_details, M_MPT2);
+	_mapping_flush_dpm_pages(sc);
+	if (sc->pending_map_events)
+		sc->pending_map_events--;
+}
+
+/**
+ * _mapping_check_update_ir_mt_idx - Check and update IR map table index
+ * @sc: per adapter object
+ * @event_data: event data payload
+ * @evt_idx: current event index
+ * @map_idx: current index and the place holder for new map table index
+ * @wwid_table: world wide name for volumes in the element table
+ *
+ * pass through IR events and find whether any events matches and if so
+ * tries to find new index if not returns failure
+ *
+ * Returns 0 on success and 1 on failure
+ */
+static int
+_mapping_check_update_ir_mt_idx(struct mps_softc *sc,
+    Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx,
+    u64 *wwid_table)
+{
+	struct dev_mapping_table *mt_entry;
+	u32 st_idx, end_idx, mt_idx = *map_idx;
+	u8 match = 0;
+	Mpi2EventIrConfigElement_t *element;
+	u16 element_flags;
+	int i;
+
+	mt_entry = &sc->mapping_table[mt_idx];
+	_mapping_get_ir_maprange(sc, &st_idx, &end_idx);
+search_again:
+	match = 0;
+	for (i = evt_idx + 1; i < event_data->NumElements; i++) {
+		element = (Mpi2EventIrConfigElement_t *)
+		    &event_data->ConfigElement[i];
+		element_flags = le16toh(element->ElementFlags);
+		if ((element_flags &
+		    MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) !=
+		    MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT)
+			continue;
+		if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED ||
+		    element->ReasonCode ==
+		    MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
+			if (mt_entry->physical_id == wwid_table[i]) {
+				match = 1;
+				break;
+			}
+		}
+	}
+
+	if (match) {
+		do {
+			mt_idx++;
+			if (mt_idx > end_idx)
+				return 1;
+			mt_entry = &sc->mapping_table[mt_idx];
+		} while (mt_entry->device_info & MPS_MAP_IN_USE);
+		goto search_again;
+	}
+	*map_idx = mt_idx;
+	return 0;
+}
+
+/**
+ * mps_mapping_ir_config_change_event - handle IR config change list events
+ * @sc: per adapter object
+ * @event_data: event data payload
+ *
+ * Returns nothing.
+ */
+void
+mps_mapping_ir_config_change_event(struct mps_softc *sc,
+    Mpi2EventDataIrConfigChangeList_t *event_data)
+{
+	Mpi2EventIrConfigElement_t *element;
+	int i;
+	u64 *wwid_table;
+	u32 map_idx, flags;
+	struct dev_mapping_table *mt_entry;
+	u16 element_flags;
+	u8 log_full_error = 0;
+
+	wwid_table = kmalloc(sizeof(u64) * event_data->NumElements, M_MPT2,
+	    M_NOWAIT | M_ZERO);
+	if (!wwid_table)
+		goto out;
+	element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+	flags = le32toh(event_data->Flags);
+	for (i = 0; i < event_data->NumElements; i++, element++) {
+		element_flags = le16toh(element->ElementFlags);
+		if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
+		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
+		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
+		    && (element->ReasonCode !=
+			MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
+			continue;
+		if ((element_flags &
+		    MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
+		    MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
+			mps_config_get_volume_wwid(sc,
+			    le16toh(element->VolDevHandle), &wwid_table[i]);
+			map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
+			    wwid_table[i]);
+			if (map_idx != MPS_MAPTABLE_BAD_IDX) {
+				mt_entry = &sc->mapping_table[map_idx];
+				mt_entry->device_info |= MPS_MAP_IN_USE;
+			}
+		}
+	}
+	if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
+		goto out;
+	else {
+		element = (Mpi2EventIrConfigElement_t *)&event_data->
+		    ConfigElement[0];
+		for (i = 0; i < event_data->NumElements; i++, element++) {
+			if (element->ReasonCode ==
+			    MPI2_EVENT_IR_CHANGE_RC_ADDED ||
+			    element->ReasonCode ==
+			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
+				map_idx = _mapping_get_ir_mt_idx_from_wwid
+				    (sc, wwid_table[i]);
+				if (map_idx != MPS_MAPTABLE_BAD_IDX) {
+					mt_entry = &sc->mapping_table[map_idx];
+					mt_entry->channel = MPS_RAID_CHANNEL;
+					mt_entry->id = map_idx;
+					mt_entry->dev_handle = le16toh
+					    (element->VolDevHandle);
+					mt_entry->device_info =
+					    MPS_DEV_RESERVED | MPS_MAP_IN_USE;
+					_mapping_update_ir_missing_cnt(sc,
+					    map_idx, element, wwid_table[i]);
+					continue;
+				}
+				map_idx = _mapping_get_free_ir_mt_idx(sc);
+				if (map_idx == MPS_MAPTABLE_BAD_IDX)
+					log_full_error = 1;
+				else if (i < (event_data->NumElements - 1)) {
+					log_full_error =
+					    _mapping_check_update_ir_mt_idx
+					    (sc, event_data, i, &map_idx,
+					     wwid_table);
+				}
+				if (log_full_error) {
+					kprintf("%s: no space to add the RAID "
+					    "volume with handle 0x%04x in "
+					    "mapping table\n", __func__, le16toh
+					    (element->VolDevHandle));
+					continue;
+				}
+				mt_entry = &sc->mapping_table[map_idx];
+				mt_entry->physical_id = wwid_table[i];
+				mt_entry->channel = MPS_RAID_CHANNEL;
+				mt_entry->id = map_idx;
+				mt_entry->dev_handle = le16toh(element->
+				    VolDevHandle);
+				mt_entry->device_info = MPS_DEV_RESERVED |
+				    MPS_MAP_IN_USE;
+				mt_entry->init_complete = 0;
+				_mapping_update_ir_missing_cnt(sc, map_idx,
+				    element, wwid_table[i]);
+			} else if (element->ReasonCode ==
+			    MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
+				map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
+				    wwid_table[i]);
+				if (map_idx == MPS_MAPTABLE_BAD_IDX) {
+					kprintf("%s: failed to remove a volume "
+					    "because it has already been "
+					    "removed\n", __func__);
+					continue;
+				}
+				_mapping_update_ir_missing_cnt(sc, map_idx,
+				    element, wwid_table[i]);
+			} else if (element->ReasonCode ==
+			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
+				map_idx = _mapping_get_mt_idx_from_handle(sc,
+				    le16toh(element->VolDevHandle));
+				if (map_idx == MPS_MAPTABLE_BAD_IDX) {
+					kprintf("%s: failed to remove volume "
+					    "with handle 0x%04x because it has "
+					    "already been removed\n", __func__,
+					    le16toh(element->VolDevHandle));
+					continue;
+				}
+				mt_entry = &sc->mapping_table[map_idx];
+				_mapping_update_ir_missing_cnt(sc, map_idx,
+				    element, mt_entry->physical_id);
+			}
+		}
+	}
+
+out:
+	_mapping_flush_dpm_pages(sc);
+	kfree(wwid_table, M_MPT2);
+	if (sc->pending_map_events)
+		sc->pending_map_events--;
+}
diff --git a/sys/dev/raid/mps/mps_mapping.h b/sys/dev/raid/mps/mps_mapping.h
new file mode 100644
index 0000000..07a48a4
--- /dev/null
+++ b/sys/dev/raid/mps/mps_mapping.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_mapping.h,v 1.1 2012/01/26 18:17:21 ken Exp $
+ */
+
+#ifndef _MPS_MAPPING_H
+#define _MPS_MAPPING_H
+
+/**
+ * struct _map_phy_change - PHY entries recieved in Topology change list
+ * @physical_id: SAS address of the device attached with the associate PHY
+ * @device_info: bitfield provides detailed info about the device
+ * @dev_handle: device handle for the device pointed by this entry
+ * @slot: slot ID
+ * @is_processed: Flag to indicate whether this entry is processed or not
+ */
+struct _map_phy_change {
+	uint64_t	physical_id;
+	uint32_t	device_info;
+	uint16_t	dev_handle;
+	uint16_t	slot;
+	uint8_t	reason;
+	uint8_t	is_processed;
+};
+
+/**
+ * struct _map_topology_change - entries to be removed from mapping table
+ * @dpm_entry_num: index of this device in device persistent map table
+ * @dev_handle: device handle for the device pointed by this entry
+ */
+struct _map_topology_change {
+	uint16_t	enc_handle;
+	uint16_t	exp_handle;
+	uint8_t	num_entries;
+	uint8_t	start_phy_num;
+	uint8_t	num_phys;
+	uint8_t	exp_status;
+	struct _map_phy_change *phy_details;
+};
+
+
+extern int
+mpssas_get_sas_address_for_sata_disk(struct mps_softc *ioc,
+    u64 *sas_address, u16 handle, u32 device_info);
+
+#endif
diff --git a/sys/dev/raid/mps/mps_pci.c b/sys/dev/raid/mps/mps_pci.c
new file mode 100644
index 0000000..961a8c3
--- /dev/null
+++ b/sys/dev/raid/mps/mps_pci.c
@@ -0,0 +1,344 @@
+/*-
+ * 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: src/sys/dev/mps/mps_pci.c,v 1.4 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */
+
+/* TODO Move headers to mpsvar */
+#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/eventhandler.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <sys/rman.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pci_private.h>
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+
+#include <sys/queue.h>
+#include <sys/kthread.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/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 *);
+#if 0 /* XXX swildner */
+static int	mps_alloc_msix(struct mps_softc *sc, int msgs);
+#endif
+
+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),
+
+	{ 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_SAS2308_1,
+	    0xffff, 0xffff, 0, "LSI SAS2308" },
+	// Add Customer specific vender/subdevice id before generic
+	// (0xffff) vender/subdevice id.
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+	    0x8086, 0x3516, 0, "Intel(R) Integrated RAID Module RMS25JB080" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+	    0x8086, 0x3517, 0, "Intel(R) Integrated RAID Module RMS25JB040" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+	    0x8086, 0x3518, 0, "Intel(R) Integrated RAID Module RMS25KB080" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+	    0x8086, 0x3519, 0, "Intel(R) Integrated RAID Module RMS25KB040" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+	    0xffff, 0xffff, 0, "LSI SAS2308" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
+	    0xffff, 0xffff, 0, "LSI SAS2308" },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
+	    0xffff, 0xffff, MPS_FLAGS_WD_AVAILABLE, "LSI SSS6200" },
+	{ 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_VENDOR);
+	}
+	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 */
+				&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 error;
+	u_int irq_flags;
+
+	dev = sc->mps_dev;
+#if 0 /* XXX swildner */
+	if ((sc->disable_msix == 0) &&
+	    ((msgs = pci_msix_count(dev)) >= MPS_MSI_COUNT))
+		error = mps_alloc_msix(sc, MPS_MSI_COUNT);
+#endif
+
+	sc->mps_irq_rid[0] = 0;
+	sc->mps_irq_type[0] = pci_alloc_1intr(dev, sc->enable_msi,
+	    &sc->mps_irq_rid[0], &irq_flags);
+	sc->mps_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &sc->mps_irq_rid[0],  irq_flags);
+	if (sc->mps_irq[0] == NULL) {
+		device_printf(dev, "Cannot allocate interrupt\n");
+		return (ENXIO);
+	}
+	error = bus_setup_intr(dev, sc->mps_irq[0], INTR_MPSAFE, mps_intr, sc,
+	    &sc->mps_intrhand[0], NULL);
+	if (error)
+		device_printf(dev, "Cannot setup interrupt\n");
+
+	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)
+{
+	if (sc->mps_parent_dmat != NULL) {
+		bus_dma_tag_destroy(sc->mps_parent_dmat);
+	}
+
+	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_irq_type[0] == PCI_INTR_TYPE_MSI)
+		pci_release_msi(sc->mps_dev);
+
+	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);
+}
+
+#if 0 /* XXX swildner */
+static int
+mps_alloc_msix(struct mps_softc *sc, int msgs)
+{
+	int error;
+
+	error = pci_alloc_msix(sc->mps_dev, &msgs);
+	return (error);
+}
+#endif
+
+int
+mps_pci_restore(struct mps_softc *sc)
+{
+	struct pci_devinfo *dinfo;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	dinfo = device_get_ivars(sc->mps_dev);
+	if (dinfo == NULL) {
+		mps_dprint(sc, MPS_FAULT, "%s: NULL dinfo\n", __func__);
+		return (EINVAL);
+	}
+
+	pci_cfg_restore(sc->mps_dev, dinfo);
+	return (0);
+}
diff --git a/sys/dev/raid/mps/mps_sas.c b/sys/dev/raid/mps/mps_sas.c
new file mode 100644
index 0000000..58b6dc4
--- /dev/null
+++ b/sys/dev/raid/mps/mps_sas.c
@@ -0,0 +1,3234 @@
+/*-
+ * 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.
+ */
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_sas.c,v 1.16 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* Communications core for LSI MPT2 */
+
+/* TODO Move headers to mpsvar */
+#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/eventhandler.h>
+#include <sys/globaldata.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+#include <sys/sbuf.h>
+
+#include <sys/rman.h>
+
+#include <machine/stdarg.h>
+
+#include <bus/cam/cam.h>
+#include <bus/cam/cam_ccb.h>
+#include <bus/cam/cam_xpt.h>
+#include <bus/cam/cam_debug.h>
+#include <bus/cam/cam_sim.h>
+#include <bus/cam/cam_xpt_sim.h>
+#include <bus/cam/cam_xpt_periph.h>
+#include <bus/cam/cam_periph.h>
+#include <bus/cam/scsi/scsi_all.h>
+#include <bus/cam/scsi/scsi_message.h>
+#if 0 /* XXX __FreeBSD_version >= 900026 */
+#include <bus/cam/scsi/smp_all.h>
+#endif
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_sas.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+#include <dev/raid/mps/mps_table.h>
+#include <dev/raid/mps/mps_sas.h>
+
+#define MPSSAS_DISCOVERY_TIMEOUT	20
+#define MPSSAS_MAX_DISCOVERY_TIMEOUTS	10 /* 200 seconds */
+
+/*
+ * static array to check SCSI OpCode for EEDP protection bits
+ */
+#define	PRO_R MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP
+#define	PRO_W MPI2_SCSIIO_EEDPFLAGS_INSERT_OP
+#define	PRO_V MPI2_SCSIIO_EEDPFLAGS_INSERT_OP
+static uint8_t op_code_prot[256] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
+	0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory");
+
+static struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *, int, uint16_t);
+#if 0 /* XXX unused */
+static void mpssas_discovery_timeout(void *data);
+#endif
+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_scsiio_timeout(void *data);
+static void mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm);
+static void mpssas_direct_drive_io(struct mpssas_softc *sassc,
+    struct mps_command *cm, union ccb *ccb);
+static void mpssas_action_scsiio(struct mpssas_softc *, union ccb *);
+static void mpssas_scsiio_complete(struct mps_softc *, struct mps_command *);
+static void mpssas_action_resetdev(struct mpssas_softc *, union ccb *);
+#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_complete(struct mps_softc *, struct mps_command *);
+static int  mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm);
+static int  mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type);
+static void mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb);
+static void mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb);
+static void mpssas_scanner_thread(void *arg);
+#if __FreeBSD_version >= 1000006
+static void mpssas_async(void *callback_arg, uint32_t code,
+			 struct cam_path *path, void *arg);
+#else
+static void mpssas_check_eedp(struct mpssas_softc *sassc);
+static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb);
+#endif
+static int mpssas_send_portenable(struct mps_softc *sc);
+static void mpssas_portenable_complete(struct mps_softc *sc,
+    struct mps_command *cm);
+
+static struct mpssas_target *
+mpssas_find_target_by_handle(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);
+}
+
+/* we need to freeze the simq during attach and diag reset, to avoid failing
+ * commands before device handles have been found by discovery.  Since
+ * discovery involves reading config pages and possibly sending commands,
+ * discovery actions may continue even after we receive the end of discovery
+ * event, so refcount discovery actions instead of assuming we can unfreeze
+ * the simq when we get the event.
+ */
+void
+mpssas_startup_increment(struct mpssas_softc *sassc)
+{
+	if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) {
+		if (sassc->startup_refcount++ == 0) {
+			/* just starting, freeze the simq */
+			mps_dprint(sassc->sc, MPS_INFO,
+			    "%s freezing simq\n", __func__);
+			xpt_freeze_simq(sassc->sim, 1);
+		}
+		mps_dprint(sassc->sc, MPS_TRACE, "%s refcount %u\n", __func__,
+		    sassc->startup_refcount);
+	}
+}
+
+void
+mpssas_startup_decrement(struct mpssas_softc *sassc)
+{
+	if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) {
+		if (--sassc->startup_refcount == 0) {
+			/* finished all discovery-related actions, release
+			 * the simq and rescan for the latest topology.
+			 */
+			mps_dprint(sassc->sc, MPS_INFO,
+			    "%s releasing simq\n", __func__);
+			sassc->flags &= ~MPSSAS_IN_STARTUP;
+			xpt_release_simq(sassc->sim, 1);
+			mpssas_rescan_target(sassc->sc, NULL);
+		}
+		mps_dprint(sassc->sc, MPS_TRACE, "%s refcount %u\n", __func__,
+		    sassc->startup_refcount);
+	}
+}
+
+/* LSI's firmware requires us to stop sending commands when we're doing task
+ * management, so refcount the TMs and keep the simq frozen when any are in
+ * use.
+ */
+struct mps_command *
+mpssas_alloc_tm(struct mps_softc *sc)
+{
+	struct mps_command *tm;
+
+	tm = mps_alloc_high_priority_command(sc);
+	if (tm != NULL) {
+		if (sc->sassc->tm_count++ == 0) {
+			mps_printf(sc, "%s freezing simq\n", __func__);
+			xpt_freeze_simq(sc->sassc->sim, 1);
+		}
+		mps_dprint(sc, MPS_TRACE, "%s tm_count %u\n", __func__,
+		    sc->sassc->tm_count);
+	}
+	return tm;
+}
+
+void
+mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm)
+{
+	if (tm == NULL)
+		return;
+
+	/* if there are no TMs in use, we can release the simq.  We use our
+	 * own refcount so that it's easier for a diag reset to cleanup and
+	 * release the simq.
+	 */
+	if (--sc->sassc->tm_count == 0) {
+		mps_printf(sc, "%s releasing simq\n", __func__);
+		xpt_release_simq(sc->sassc->sim, 1);
+	}
+	mps_dprint(sc, MPS_TRACE, "%s tm_count %u\n", __func__,
+	    sc->sassc->tm_count);
+
+	mps_free_high_priority_command(sc, tm);
+}
+
+
+void
+mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ)
+{
+	struct mpssas_softc *sassc = sc->sassc;
+	path_id_t pathid;
+	target_id_t targetid;
+	union ccb *ccb;
+
+	pathid = cam_sim_path(sassc->sim);
+	if (targ == NULL)
+		targetid = CAM_TARGET_WILDCARD;
+	else
+		targetid = targ - sassc->targets;
+
+	/*
+	 * Allocate a CCB and schedule a rescan.
+	 */
+	ccb = kmalloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO);
+
+	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid,
+		            targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+		mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n");
+		xpt_free_ccb(ccb);
+		return;
+	}
+
+	/* XXX Hardwired to scan the bus for now */
+	ccb->ccb_h.func_code = XPT_SCAN_BUS;
+	mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid);
+	mpssas_rescan(sassc, ccb);
+}
+
+static void
+mpssas_log_command(struct mps_command *cm, const char *fmt, ...)
+{
+	struct sbuf sb;
+	__va_list ap;
+	char str[192];
+	char path_str[64];
+
+	if (cm == NULL)
+		return;
+
+	sbuf_new(&sb, str, sizeof(str), 0);
+
+	__va_start(ap, fmt);
+
+	if (cm->cm_ccb != NULL) {
+		xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str,
+				sizeof(path_str));
+		sbuf_cat(&sb, path_str);
+		if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) {
+			scsi_command_string(&cm->cm_ccb->csio, &sb);
+			sbuf_printf(&sb, "length %d ",
+				    cm->cm_ccb->csio.dxfer_len);
+		}
+	}
+	else {
+		sbuf_printf(&sb, "(noperiph:%s%d:%u:%u:%u): ",
+		    cam_sim_name(cm->cm_sc->sassc->sim),
+		    cam_sim_unit(cm->cm_sc->sassc->sim),
+		    cam_sim_bus(cm->cm_sc->sassc->sim),
+		    cm->cm_targ ? cm->cm_targ->tid : 0xFFFFFFFF,
+		    cm->cm_lun);
+	}
+
+	sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID);
+	sbuf_vprintf(&sb, fmt, ap);
+	sbuf_finish(&sb);
+	kprintf("%s", sbuf_data(&sb));
+
+	__va_end(ap);
+}
+
+static void
+mpssas_lost_target(struct mps_softc *sc, struct mpssas_target *targ)
+{
+	struct mpssas_softc *sassc = sc->sassc;
+	path_id_t pathid = cam_sim_path(sassc->sim);
+	struct cam_path *path;
+
+	mps_printf(sc, "%s targetid %u\n", __func__, targ->tid);
+	if (xpt_create_path(&path, NULL, pathid, targ->tid, 0) != CAM_REQ_CMP) {
+		mps_printf(sc, "unable to create path for lost target %d\n",
+		    targ->tid);
+		return;
+	}
+
+	xpt_async(AC_LOST_DEVICE, path, NULL);
+	xpt_free_path(path);
+}
+
+/*
+ * 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.
+ */
+void
+mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mps_softc *sc;
+	struct mps_command *cm;
+	struct mpssas_target *targ = NULL;
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	/*
+	 * If this is a WD controller, determine if the disk should be exposed
+	 * to the OS or not.  If disk should be exposed, return from this
+	 * function without doing anything.
+	 */
+	sc = sassc->sc;
+	if ((sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) && (sc->WD_hide_expose ==
+	    MPS_WD_EXPOSE_ALWAYS)) {
+		return;
+	}
+
+	targ = mpssas_find_target_by_handle(sassc, 0, handle);
+	if (targ == NULL) {
+		/* FIXME: what is the action? */
+		/* We don't know about this device? */
+		kprintf("%s: invalid handle 0x%x \n", __func__, handle);
+		return;
+	}
+
+	targ->flags |= MPSSAS_TARGET_INREMOVAL;
+
+	cm = mpssas_alloc_tm(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "%s: command alloc failure\n", __func__);
+		return;
+	}
+
+	mpssas_lost_target(sc, targ);
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+	memset(req, 0, sizeof(*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_targ = targ;
+	cm->cm_data = NULL;
+	cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+	cm->cm_complete = mpssas_remove_device;
+	cm->cm_complete_data = (void *)(uintptr_t)handle;
+	mps_map_command(sc, cm);
+}
+
+static void
+mpssas_remove_device(struct mps_softc *sc, struct mps_command *tm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
+	MPI2_SAS_IOUNIT_CONTROL_REQUEST *req;
+	struct mpssas_target *targ;
+	struct mps_command *next_cm;
+	uint16_t handle;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
+	handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
+	targ = tm->cm_targ;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * task management commands don't have S/G lists.
+	 */
+	if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mps_printf(sc, "%s: cm_flags = %#x for remove of handle %#04x! "
+			   "This should not happen!\n", __func__, tm->cm_flags,
+			   handle);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	if (reply == NULL) {
+		/* XXX retry the remove after the diag reset completes? */
+		mps_printf(sc, "%s NULL reply reseting device 0x%04x\n",
+		    __func__, handle);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
+		mps_printf(sc, "IOCStatus = 0x%x while resetting device 0x%x\n",
+		   reply->IOCStatus, handle);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	mps_dprint(sc, MPS_INFO, "Reset aborted %u commands\n",
+	    (u_int)reply->TerminationCount);
+	mps_free_reply(sc, tm->cm_reply_data);
+	tm->cm_reply = NULL;	/* Ensures the the reply won't get re-freed */
+
+	/* Reuse the existing command */
+	req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)tm->cm_req;
+	memset(req, 0, sizeof(*req));
+	req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+	req->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
+	req->DevHandle = handle;
+	tm->cm_data = NULL;
+	tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	tm->cm_complete = mpssas_remove_complete;
+	tm->cm_complete_data = (void *)(uintptr_t)handle;
+
+	mps_map_command(sc, tm);
+
+	mps_dprint(sc, MPS_INFO, "clearing target %u handle 0x%04x\n",
+		   targ->tid, handle);
+	TAILQ_FOREACH_MUTABLE(tm, &targ->commands, cm_link, next_cm) {
+		union ccb *ccb;
+
+		mps_dprint(sc, MPS_INFO, "Completing missed command %p\n", tm);
+		ccb = tm->cm_complete_data;
+		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+		mpssas_scsiio_complete(sc, tm);
+	}
+}
+
+static void
+mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
+{
+	MPI2_SAS_IOUNIT_CONTROL_REPLY *reply;
+	uint16_t handle;
+	struct mpssas_target *targ;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply;
+	handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * task management commands don't have S/G lists.
+	 */
+	if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mps_printf(sc, "%s: cm_flags = %#x for remove of handle %#04x! "
+			   "This should not happen!\n", __func__, tm->cm_flags,
+			   handle);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	if (reply == NULL) {
+		/* most likely a chip reset */
+		mps_printf(sc, "%s NULL reply removing device 0x%04x\n",
+		    __func__, handle);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	mps_printf(sc, "%s on handle 0x%04x, IOCStatus= 0x%x\n", __func__,
+	    handle, reply->IOCStatus);
+
+	/*
+	 * Don't clear target if remove fails because things will get confusing.
+	 * Leave the devname and sasaddr intact so that we know to avoid reusing
+	 * this target id if possible, and so we can assign the same target id
+	 * to this device if it comes back in the future.
+	 */
+	if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) {
+		targ = tm->cm_targ;
+		targ->handle = 0x0;
+		targ->encl_handle = 0x0;
+		targ->encl_slot = 0x0;
+		targ->exp_dev_handle = 0x0;
+		targ->phy_num = 0x0;
+		targ->linkrate = 0x0;
+		targ->devinfo = 0x0;
+	}
+
+	mpssas_free_tm(sc, tm);
+}
+
+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);
+	setbit(events, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
+	setbit(events, MPI2_EVENT_IR_VOLUME);
+	setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK);
+	setbit(events, MPI2_EVENT_IR_OPERATION_STATUS);
+	setbit(events, MPI2_EVENT_LOG_ENTRY_ADDED);
+
+	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;
+#if __FreeBSD_version >= 1000006
+	cam_status status;
+#endif
+	int unit, error = 0;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	sassc = kmalloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO);
+	sassc->targets = kmalloc(sizeof(struct mpssas_target) *
+	    sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO);
+	sc->sassc = sassc;
+	sassc->sc = sc;
+
+	if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) {
+		mps_dprint(sc, MPS_FAULT, "Cannot allocate SIMQ\n");
+		error = ENOMEM;
+		goto out;
+	}
+
+	unit = device_get_unit(sc->mps_dev);
+	sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mps", sassc,
+	    unit, &sc->mps_lock, sc->num_reqs, sc->num_reqs, sassc->devq);
+	if (sassc->sim == NULL) {
+		mps_dprint(sc, MPS_FAULT, "Cannot allocate SIM\n");
+		error = EINVAL;
+		goto out;
+	}
+
+	TAILQ_INIT(&sassc->ev_queue);
+
+	/* Initialize taskqueue for Event Handling */
+	TASK_INIT(&sassc->ev_task, 0, mpssas_firmware_event_work, sc);
+	sassc->ev_tq = taskqueue_create("mps_taskq", M_NOWAIT | M_ZERO,
+	    taskqueue_thread_enqueue, &sassc->ev_tq);
+
+	/* Run the task queue with lowest priority */
+	taskqueue_start_threads(&sassc->ev_tq, 1, 255, -1, "%s taskq",
+	    device_get_nameunit(sc->mps_dev));
+
+	TAILQ_INIT(&sassc->ccb_scanq);
+	error = mps_kproc_create(mpssas_scanner_thread, sassc,
+	    &sassc->rescan_thread, 0, 0, "mps_scan%d", unit);
+	if (error) {
+		mps_printf(sc, "Error %d starting rescan thread\n", error);
+		goto out;
+	}
+
+	mps_lock(sc);
+	sassc->flags |= MPSSAS_SCANTHREAD;
+
+	/*
+	 * 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.
+	 */
+	if ((error = xpt_bus_register(sassc->sim, 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);
+	sc->sassc->startup_refcount = 0;
+
+	callout_init_mp(&sassc->discovery_callout);
+	sassc->discovery_timeouts = 0;
+
+	sassc->tm_count = 0;
+
+#if __FreeBSD_version >= 1000006
+	status = xpt_register_async(AC_ADVINFO_CHANGED, mpssas_async, sc, NULL);
+	if (status != CAM_REQ_CMP) {
+		mps_printf(sc, "Error %#x registering async handler for "
+			   "AC_ADVINFO_CHANGED events\n", status);
+	}
+#endif
+
+	mps_unlock(sc);
+
+	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;
+	mps_deregister_events(sc, sassc->mpssas_eh);
+
+	/*
+	 * Drain and free the event handling taskqueue with the lock
+	 * unheld so that any parallel processing tasks drain properly
+	 * without deadlocking.
+	 */
+	if (sassc->ev_tq != NULL)
+		taskqueue_free(sassc->ev_tq);
+
+	/* Make sure CAM doesn't wedge if we had to bail out early. */
+	mps_lock(sc);
+
+	/* Deregister our async handler */
+#if __FreeBSD_version >= 1000006
+	xpt_register_async(0, mpssas_async, sc, NULL);
+#endif
+
+	if (sassc->flags & MPSSAS_IN_STARTUP)
+		xpt_release_simq(sassc->sim, 1);
+
+	if (sassc->sim != NULL) {
+		xpt_bus_deregister(cam_sim_path(sassc->sim));
+		cam_sim_free(sassc->sim);
+	}
+
+	if (sassc->flags & MPSSAS_SCANTHREAD) {
+		sassc->flags |= MPSSAS_SHUTDOWN;
+		wakeup(&sassc->ccb_scanq);
+
+		if (sassc->flags & MPSSAS_SCANTHREAD) {
+			lksleep(&sassc->flags, &sc->mps_lock, 0,
+			       "mps_shutdown", 30 * hz);
+		}
+	}
+	mps_unlock(sc);
+
+	if (sassc->devq != NULL)
+		cam_simq_release(sassc->devq);
+
+	kfree(sassc->targets, M_MPT2);
+	kfree(sassc, M_MPT2);
+	sc->sassc = NULL;
+
+	return (0);
+}
+
+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 0 /* XXX unused */
+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_printf(sassc->sc,
+	    "Finished polling after discovery timeout at %d\n", ticks);
+
+	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(sc);
+}
+#endif
+
+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);
+	KKASSERT(lockstatus(&sassc->sc->mps_lock, curthread) != 0);
+
+	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;
+#if __FreeBSD_version >= 800001
+		/*
+		 * XXX KDM where does this number come from?
+		 */
+		cpi->maxio = 256 * 1024;
+#endif
+		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:
+		mps_printf(sassc->sc, "mpssas_action XPT_RESET_DEV\n");
+		mpssas_action_resetdev(sassc, ccb);
+		return;
+	case XPT_RESET_BUS:
+	case XPT_ABORT:
+	case XPT_TERM_IO:
+		mps_printf(sassc->sc, "mpssas_action faking success for "
+			   "abort or reset\n");
+		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
+	default:
+		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+		break;
+	}
+	xpt_done(ccb);
+
+}
+
+static void
+mpssas_announce_reset(struct mps_softc *sc, uint32_t ac_code,
+    target_id_t target_id, lun_id_t lun_id)
+{
+	path_id_t path_id = cam_sim_path(sc->sassc->sim);
+	struct cam_path *path;
+
+	mps_printf(sc, "%s code %x target %d lun %d\n", __func__,
+	    ac_code, target_id, lun_id);
+
+	if (xpt_create_path(&path, NULL,
+		path_id, target_id, lun_id) != CAM_REQ_CMP) {
+		mps_printf(sc, "unable to create path for reset "
+			   "notification\n");
+		return;
+	}
+
+	xpt_async(ac_code, path, NULL);
+	xpt_free_path(path);
+}
+
+static void
+mpssas_complete_all_commands(struct mps_softc *sc)
+{
+	struct mps_command *cm;
+	int i;
+	int completed;
+
+	mps_printf(sc, "%s\n", __func__);
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	/* complete all commands with a NULL reply */
+	for (i = 1; i < sc->num_reqs; i++) {
+		cm = &sc->commands[i];
+		cm->cm_reply = NULL;
+		completed = 0;
+
+		if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
+			cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
+
+		if (cm->cm_complete != NULL) {
+			mpssas_log_command(cm,
+			    "completing cm %p state %x ccb %p for diag reset\n",
+			    cm, cm->cm_state, cm->cm_ccb);
+
+			cm->cm_complete(sc, cm);
+			completed = 1;
+		}
+
+		if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP) {
+			mpssas_log_command(cm,
+			    "waking up cm %p state %x ccb %p for diag reset\n",
+			    cm, cm->cm_state, cm->cm_ccb);
+			wakeup(cm);
+			completed = 1;
+		}
+
+		if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) {
+			/* this should never happen, but if it does, log */
+			mpssas_log_command(cm,
+			    "cm %p state %x flags 0x%x ccb %p during diag "
+			    "reset\n", cm, cm->cm_state, cm->cm_flags,
+			    cm->cm_ccb);
+		}
+	}
+}
+
+void
+mpssas_handle_reinit(struct mps_softc *sc)
+{
+	int i;
+
+	/* Go back into startup mode and freeze the simq, so that CAM
+	 * doesn't send any commands until after we've rediscovered all
+	 * targets and found the proper device handles for them.
+	 *
+	 * After the reset, portenable will trigger discovery, and after all
+	 * discovery-related activities have finished, the simq will be
+	 * released.
+	 */
+	mps_printf(sc, "%s startup\n", __func__);
+	sc->sassc->flags |= MPSSAS_IN_STARTUP;
+	sc->sassc->flags |= MPSSAS_IN_DISCOVERY;
+	xpt_freeze_simq(sc->sassc->sim, 1);
+
+	/* notify CAM of a bus reset */
+	mpssas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD,
+	    CAM_LUN_WILDCARD);
+
+	/* complete and cleanup after all outstanding commands */
+	mpssas_complete_all_commands(sc);
+
+	mps_printf(sc, "%s startup %u tm %u after command completion\n",
+	    __func__, sc->sassc->startup_refcount, sc->sassc->tm_count);
+
+	/*
+	 * The simq was explicitly frozen above, so set the refcount to 0.
+	 * The simq will be explicitly released after port enable completes.
+	 */
+	sc->sassc->startup_refcount = 0;
+
+	/* zero all the target handles, since they may change after the
+	 * reset, and we have to rediscover all the targets and use the new
+	 * handles.
+	 */
+	for (i = 0; i < sc->facts->MaxTargets; i++) {
+		if (sc->sassc->targets[i].outstanding != 0)
+			mps_printf(sc, "target %u outstanding %u\n",
+			    i, sc->sassc->targets[i].outstanding);
+		sc->sassc->targets[i].handle = 0x0;
+		sc->sassc->targets[i].exp_dev_handle = 0x0;
+		sc->sassc->targets[i].outstanding = 0;
+		sc->sassc->targets[i].flags = MPSSAS_TARGET_INDIAGRESET;
+	}
+}
+static void
+mpssas_tm_timeout(void *data)
+{
+	struct mps_command *tm = data;
+	struct mps_softc *sc = tm->cm_sc;
+
+	mps_lock(sc);
+	mpssas_log_command(tm, "task mgmt %p timed out\n", tm);
+	mps_reinit(sc);
+	mps_unlock(sc);
+}
+
+static void
+mpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	unsigned int cm_count = 0;
+	struct mps_command *cm;
+	struct mpssas_target *targ;
+
+	callout_stop(&tm->cm_callout);
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
+	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
+	targ = tm->cm_targ;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * task management commands don't have S/G lists.
+	 */
+	if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mps_printf(sc, "%s: cm_flags = %#x for LUN reset! "
+			   "This should not happen!\n", __func__, tm->cm_flags);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	if (reply == NULL) {
+		mpssas_log_command(tm, "NULL reset reply for tm %p\n", tm);
+		if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
+			/* this completion was due to a reset, just cleanup */
+			targ->flags &= ~MPSSAS_TARGET_INRESET;
+			targ->tm = NULL;
+			mpssas_free_tm(sc, tm);
+		}
+		else {
+			/* we should have gotten a reply. */
+			mps_reinit(sc);
+		}
+		return;
+	}
+
+	mpssas_log_command(tm,
+	    "logical unit reset status 0x%x code 0x%x count %u\n",
+	    reply->IOCStatus, reply->ResponseCode,
+	    reply->TerminationCount);
+
+	/* See if there are any outstanding commands for this LUN.
+	 * This could be made more efficient by using a per-LU data
+	 * structure of some sort.
+	 */
+	TAILQ_FOREACH(cm, &targ->commands, cm_link) {
+		if (cm->cm_lun == tm->cm_lun)
+			cm_count++;
+	}
+
+	if (cm_count == 0) {
+		mpssas_log_command(tm,
+		    "logical unit %u finished recovery after reset\n",
+		    tm->cm_lun, tm);
+
+		mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
+		    tm->cm_lun);
+
+		/* we've finished recovery for this logical unit.  check and
+		 * see if some other logical unit has a timedout command
+		 * that needs to be processed.
+		 */
+		cm = TAILQ_FIRST(&targ->timedout_commands);
+		if (cm) {
+			mpssas_send_abort(sc, tm, cm);
+		}
+		else {
+			targ->tm = NULL;
+			mpssas_free_tm(sc, tm);
+		}
+	}
+	else {
+		/* if we still have commands for this LUN, the reset
+		 * effectively failed, regardless of the status reported.
+		 * Escalate to a target reset.
+		 */
+		mpssas_log_command(tm,
+		    "logical unit reset complete for tm %p, but still have %u command(s)\n",
+		    tm, cm_count);
+		mpssas_send_reset(sc, tm,
+		    MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
+	}
+}
+
+static void
+mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mpssas_target *targ;
+
+	callout_stop(&tm->cm_callout);
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
+	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
+	targ = tm->cm_targ;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * task management commands don't have S/G lists.
+	 */
+	if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mps_printf(sc, "%s: cm_flags = %#x for target reset! "
+			   "This should not happen!\n", __func__, tm->cm_flags);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	if (reply == NULL) {
+		mpssas_log_command(tm, "NULL reset reply for tm %p\n", tm);
+		if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
+			/* this completion was due to a reset, just cleanup */
+			targ->flags &= ~MPSSAS_TARGET_INRESET;
+			targ->tm = NULL;
+			mpssas_free_tm(sc, tm);
+		}
+		else {
+			/* we should have gotten a reply. */
+			mps_reinit(sc);
+		}
+		return;
+	}
+
+	mpssas_log_command(tm,
+	    "target reset status 0x%x code 0x%x count %u\n",
+	    reply->IOCStatus, reply->ResponseCode,
+	    reply->TerminationCount);
+
+	targ->flags &= ~MPSSAS_TARGET_INRESET;
+
+	if (targ->outstanding == 0) {
+		/* we've finished recovery for this target and all
+		 * of its logical units.
+		 */
+		mpssas_log_command(tm,
+		    "recovery finished after target reset\n");
+
+		mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
+		    CAM_LUN_WILDCARD);
+
+		targ->tm = NULL;
+		mpssas_free_tm(sc, tm);
+	}
+	else {
+		/* after a target reset, if this target still has
+		 * outstanding commands, the reset effectively failed,
+		 * regardless of the status reported.  escalate.
+		 */
+		mpssas_log_command(tm,
+		    "target reset complete for tm %p, but still have %u command(s)\n",
+		    tm, targ->outstanding);
+		mps_reinit(sc);
+	}
+}
+
+#define MPS_RESET_TIMEOUT 30
+
+static int
+mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mpssas_target *target;
+	int err;
+
+	target = tm->cm_targ;
+	if (target->handle == 0) {
+		mps_printf(sc, "%s null devhandle for target_id %d\n",
+		    __func__, target->tid);
+		return -1;
+	}
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
+	req->DevHandle = target->handle;
+	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+	req->TaskType = type;
+
+	if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) {
+		/* XXX Need to handle invalid LUNs */
+		MPS_SET_LUN(req->LUN, tm->cm_lun);
+		tm->cm_targ->logical_unit_resets++;
+		mpssas_log_command(tm, "sending logical unit reset\n");
+		tm->cm_complete = mpssas_logical_unit_reset_complete;
+	}
+	else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
+		/* Target reset method =  SAS Hard Link Reset / SATA Link Reset */
+		req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+		tm->cm_targ->target_resets++;
+		tm->cm_targ->flags |= MPSSAS_TARGET_INRESET;
+		mpssas_log_command(tm, "sending target reset\n");
+		tm->cm_complete = mpssas_target_reset_complete;
+	}
+	else {
+		mps_printf(sc, "unexpected reset type 0x%x\n", type);
+		return -1;
+	}
+
+	tm->cm_data = NULL;
+	tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+	tm->cm_complete_data = (void *)tm;
+
+	callout_reset(&tm->cm_callout, MPS_RESET_TIMEOUT * hz,
+	    mpssas_tm_timeout, tm);
+
+	err = mps_map_command(sc, tm);
+	if (err)
+		mpssas_log_command(tm,
+		    "error %d sending reset type %u\n",
+		    err, type);
+
+	return err;
+}
+
+
+static void
+mpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm)
+{
+	struct mps_command *cm;
+	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mpssas_target *targ;
+
+	callout_stop(&tm->cm_callout);
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
+	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
+	targ = tm->cm_targ;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * task management commands don't have S/G lists.
+	 */
+	if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mpssas_log_command(tm,
+		    "cm_flags = %#x for abort %p TaskMID %u!\n",
+		    tm->cm_flags, tm, req->TaskMID);
+		mpssas_free_tm(sc, tm);
+		return;
+	}
+
+	if (reply == NULL) {
+		mpssas_log_command(tm,
+		    "NULL abort reply for tm %p TaskMID %u\n",
+		    tm, req->TaskMID);
+		if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
+			/* this completion was due to a reset, just cleanup */
+			targ->tm = NULL;
+			mpssas_free_tm(sc, tm);
+		}
+		else {
+			/* we should have gotten a reply. */
+			mps_reinit(sc);
+		}
+		return;
+	}
+
+	mpssas_log_command(tm,
+	    "abort TaskMID %u status 0x%x code 0x%x count %u\n",
+	    req->TaskMID,
+	    reply->IOCStatus, reply->ResponseCode,
+	    reply->TerminationCount);
+
+	cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands);
+	if (cm == NULL) {
+		/* if there are no more timedout commands, we're done with
+		 * error recovery for this target.
+		 */
+		mpssas_log_command(tm,
+		    "finished recovery after aborting TaskMID %u\n",
+		    req->TaskMID);
+
+		targ->tm = NULL;
+		mpssas_free_tm(sc, tm);
+	}
+	else if (req->TaskMID != cm->cm_desc.Default.SMID) {
+		/* abort success, but we have more timedout commands to abort */
+		mpssas_log_command(tm,
+		    "continuing recovery after aborting TaskMID %u\n",
+		    req->TaskMID);
+
+		mpssas_send_abort(sc, tm, cm);
+	}
+	else {
+		/* we didn't get a command completion, so the abort
+		 * failed as far as we're concerned.  escalate.
+		 */
+		mpssas_log_command(tm,
+		    "abort failed for TaskMID %u tm %p\n",
+		    req->TaskMID, tm);
+
+		mpssas_send_reset(sc, tm,
+		    MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET);
+	}
+}
+
+#define MPS_ABORT_TIMEOUT 5
+
+static int
+mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mpssas_target *targ;
+	int err;
+
+	targ = cm->cm_targ;
+	if (targ->handle == 0) {
+		mps_printf(sc, "%s null devhandle for target_id %d\n",
+		    __func__, cm->cm_ccb->ccb_h.target_id);
+		return -1;
+	}
+
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
+	req->DevHandle = targ->handle;
+	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+
+	/* XXX Need to handle invalid LUNs */
+	MPS_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun);
+
+	req->TaskMID = cm->cm_desc.Default.SMID;
+
+	tm->cm_data = NULL;
+	tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+	tm->cm_complete = mpssas_abort_complete;
+	tm->cm_complete_data = (void *)tm;
+	tm->cm_targ = cm->cm_targ;
+	tm->cm_lun = cm->cm_lun;
+
+	callout_reset(&tm->cm_callout, MPS_ABORT_TIMEOUT * hz,
+	    mpssas_tm_timeout, tm);
+
+	targ->aborts++;
+
+	err = mps_map_command(sc, tm);
+	if (err)
+		mpssas_log_command(tm,
+		    "error %d sending abort for cm %p SMID %u\n",
+		    err, cm, req->TaskMID);
+	return err;
+}
+
+
+static void
+mpssas_scsiio_timeout(void *data)
+{
+	struct mps_softc *sc;
+	struct mps_command *cm;
+	struct mpssas_target *targ;
+
+	cm = (struct mps_command *)data;
+	sc = cm->cm_sc;
+
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	mps_printf(sc, "%s checking sc %p cm %p\n", __func__, sc, cm);
+
+	/*
+	 * 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_intr_locked(sc);
+	if (cm->cm_state == MPS_CM_STATE_FREE) {
+		mps_printf(sc, "SCSI command %p sc %p almost timed out\n", cm, sc);
+		return;
+	}
+
+	if (cm->cm_ccb == NULL) {
+		mps_printf(sc, "command timeout with NULL ccb\n");
+		return;
+	}
+
+	mpssas_log_command(cm, "command timeout cm %p ccb %p\n",
+	    cm, cm->cm_ccb);
+
+	targ = cm->cm_targ;
+	targ->timeouts++;
+
+	/* XXX first, check the firmware state, to see if it's still
+	 * operational.  if not, do a diag reset.
+	 */
+
+	cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT;
+	cm->cm_state = MPS_CM_STATE_TIMEDOUT;
+	TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery);
+
+	if (targ->tm != NULL) {
+		/* target already in recovery, just queue up another
+		 * timedout command to be processed later.
+		 */
+		mps_printf(sc, "queued timedout cm %p for processing by tm %p\n",
+		    cm, targ->tm);
+	}
+	else if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) {
+		mps_printf(sc, "timedout cm %p allocated tm %p\n",
+		    cm, targ->tm);
+
+		/* start recovery by aborting the first timedout command */
+		mpssas_send_abort(sc, targ->tm, cm);
+	}
+	else {
+		/* XXX queue this target up for recovery once a TM becomes
+		 * available.  The firmware only has a limited number of
+		 * HighPriority credits for the high priority requests used
+		 * for task management, and we ran out.
+		 *
+		 * Isilon: don't worry about this for now, since we have
+		 * more credits than disks in an enclosure, and limit
+		 * ourselves to one TM per target for recovery.
+		 */
+		mps_printf(sc, "timedout cm %p failed to allocate a tm\n",
+		    cm);
+	}
+
+}
+
+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 mpssas_lun *lun;
+	struct mps_command *cm;
+	uint8_t i, lba_byte, *ref_tag_addr;
+	uint16_t eedp_flags;
+
+	sc = sassc->sc;
+	mps_dprint(sc, MPS_TRACE, "%s ccb %p\n", __func__, ccb);
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	csio = &ccb->csio;
+	targ = &sassc->targets[csio->ccb_h.target_id];
+	if (targ->handle == 0x0) {
+		mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n",
+		    __func__, csio->ccb_h.target_id);
+		csio->ccb_h.status = CAM_TID_INVALID;
+		xpt_done(ccb);
+		return;
+	}
+	/*
+	 * If devinfo is 0 this will be a volume.  In that case don't tell CAM
+	 * that the volume has timed out.  We want volumes to be enumerated
+	 * until they are deleted/removed, not just failed.
+	 */
+	if (targ->flags & MPSSAS_TARGET_INREMOVAL) {
+		if (targ->devinfo == 0)
+			csio->ccb_h.status = CAM_REQ_CMP;
+		else
+			csio->ccb_h.status = CAM_SEL_TIMEOUT;
+		xpt_done(ccb);
+		return;
+	}
+
+	if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) {
+		mps_dprint(sc, MPS_TRACE, "%s shutting down\n", __func__);
+		csio->ccb_h.status = CAM_TID_INVALID;
+		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;
+	bzero(req, sizeof(*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;
+	}
+	req->Control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits;
+
+	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;
+
+	/*
+	 * Check if EEDP is supported and enabled.  If it is then check if the
+	 * SCSI opcode could be using EEDP.  If so, make sure the LUN exists and
+	 * is formatted for EEDP support.  If all of this is true, set CDB up
+	 * for EEDP transfer.
+	 */
+	eedp_flags = op_code_prot[req->CDB.CDB32[0]];
+	if (sc->eedp_enabled && eedp_flags) {
+		SLIST_FOREACH(lun, &targ->luns, lun_link) {
+			if (lun->lun_id == csio->ccb_h.target_lun) {
+				break;
+			}
+		}
+
+		if ((lun != NULL) && (lun->eedp_formatted)) {
+			req->EEDPBlockSize = lun->eedp_block_size;
+			eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+			    MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
+			    MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
+			req->EEDPFlags = eedp_flags;
+
+			/*
+			 * If CDB less than 32, fill in Primary Ref Tag with
+			 * low 4 bytes of LBA.  If CDB is 32, tag stuff is
+			 * already there.  Also, set protection bit.  FreeBSD
+			 * currently does not support CDBs bigger than 16, but
+			 * the code doesn't hurt, and will be here for the
+			 * future.
+			 */
+			if (csio->cdb_len != 32) {
+				lba_byte = (csio->cdb_len == 16) ? 6 : 2;
+				ref_tag_addr = (uint8_t *)&req->CDB.EEDP32.
+				    PrimaryReferenceTag;
+				for (i = 0; i < 4; i++) {
+					*ref_tag_addr =
+					    req->CDB.CDB32[lba_byte + i];
+					ref_tag_addr++;
+				}
+				req->CDB.EEDP32.PrimaryApplicationTagMask =
+				    0xFFFF;
+				req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) |
+				    0x20;
+			} else {
+				eedp_flags |=
+				    MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG;
+				req->EEDPFlags = eedp_flags;
+				req->CDB.CDB32[10] = (req->CDB.CDB32[10] &
+				    0x1F) | 0x20;
+			}
+		}
+	}
+
+	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;
+	cm->cm_lun = csio->ccb_h.target_lun;
+	cm->cm_ccb = ccb;
+
+	/*
+	 * If HBA is a WD and the command is not for a retry, try to build a
+	 * direct I/O message. If failed, or the command is for a retry, send
+	 * the I/O to the IR volume itself.
+	 */
+	if (sc->WD_valid_config) {
+		if (ccb->ccb_h.status != MPS_WD_RETRY) {
+			mpssas_direct_drive_io(sassc, cm, ccb);
+		} else {
+			ccb->ccb_h.status = CAM_REQ_INPROG;
+		}
+	}
+
+	callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000,
+	   mpssas_scsiio_timeout, cm);
+
+	targ->issued++;
+	targ->outstanding++;
+	TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
+
+	if ((sc->mps_debug & MPS_TRACE) != 0)
+		mpssas_log_command(cm, "%s cm %p ccb %p outstanding %u\n",
+		    __func__, cm, ccb, targ->outstanding);
+
+	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 ccb_scsiio *csio;
+	struct mpssas_softc *sassc;
+	struct scsi_vpd_supported_page_list *vpd_list = NULL;
+	u8 *TLR_bits, TLR_on;
+	int dir = 0, i;
+	u16 alloc_len;
+
+	mps_dprint(sc, MPS_TRACE,
+	    "%s cm %p SMID %u ccb %p reply %p outstanding %u\n",
+	    __func__, cm, cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply,
+	    cm->cm_targ->outstanding);
+
+	callout_stop(&cm->cm_callout);
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	sassc = sc->sassc;
+	ccb = cm->cm_complete_data;
+	csio = &ccb->csio;
+	rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply;
+	/*
+	 * XXX KDM if the chain allocation fails, does it matter if we do
+	 * the sync and unload here?  It is simpler to do it in every case,
+	 * assuming it doesn't cause problems.
+	 */
+	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);
+	}
+
+	cm->cm_targ->completed++;
+	cm->cm_targ->outstanding--;
+	TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link);
+
+	if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) {
+		TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
+		if (cm->cm_reply != NULL)
+			mpssas_log_command(cm,
+			    "completed timedout cm %p ccb %p during recovery "
+			    "ioc %x scsi %x state %x xfer %u\n",
+			    cm, cm->cm_ccb,
+			    rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
+			    rep->TransferCount);
+		else
+			mpssas_log_command(cm,
+			    "completed timedout cm %p ccb %p during recovery\n",
+			    cm, cm->cm_ccb);
+	} else if (cm->cm_targ->tm != NULL) {
+		if (cm->cm_reply != NULL)
+			mpssas_log_command(cm,
+			    "completed cm %p ccb %p during recovery "
+			    "ioc %x scsi %x state %x xfer %u\n",
+			    cm, cm->cm_ccb,
+			    rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
+			    rep->TransferCount);
+		else
+			mpssas_log_command(cm,
+			    "completed cm %p ccb %p during recovery\n",
+			    cm, cm->cm_ccb);
+	} else if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
+		mpssas_log_command(cm,
+		    "reset completed cm %p ccb %p\n",
+		    cm, cm->cm_ccb);
+	}
+
+	if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		/*
+		 * We ran into an error after we tried to map the command,
+		 * so we're getting a callback without queueing the command
+		 * to the hardware.  So we set the status here, and it will
+		 * be retained below.  We'll go through the "fast path",
+		 * because there can be no reply when we haven't actually
+		 * gone out to the hardware.
+		 */
+		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+
+		/*
+		 * Currently the only error included in the mask is
+		 * MPS_CM_FLAGS_CHAIN_FAILED, which means we're out of
+		 * chain frames.  We need to freeze the queue until we get
+		 * a command that completed without this error, which will
+		 * hopefully have some chain frames attached that we can
+		 * use.  If we wanted to get smarter about it, we would
+		 * only unfreeze the queue in this condition when we're
+		 * sure that we're getting some chain frames back.  That's
+		 * probably unnecessary.
+		 */
+		if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) {
+			xpt_freeze_simq(sassc->sim, 1);
+			sassc->flags |= MPSSAS_QUEUE_FROZEN;
+			mps_dprint(sc, MPS_INFO, "Error sending command, "
+				   "freezing SIM queue\n");
+		}
+	}
+
+	/* Take the fast path to completion */
+	if (cm->cm_reply == NULL) {
+		if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
+			if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0)
+				ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
+			else {
+				ccb->ccb_h.status = CAM_REQ_CMP;
+				ccb->csio.scsi_status = SCSI_STATUS_OK;
+			}
+			if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
+				ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+				sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
+				mps_dprint(sc, MPS_INFO,
+					   "Unfreezing SIM queue\n");
+			}
+		}
+
+		/*
+		 * There are two scenarios where the status won't be
+		 * CAM_REQ_CMP.  The first is if MPS_CM_FLAGS_ERROR_MASK is
+		 * set, the second is in the MPS_FLAGS_DIAGRESET above.
+		 */
+		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+			/*
+			 * Freeze the dev queue so that commands are
+			 * executed in the correct order with after error
+			 * recovery.
+			 */
+			ccb->ccb_h.status |= CAM_DEV_QFRZN;
+			xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
+		}
+		mps_free_command(sc, cm);
+		xpt_done(ccb);
+		return;
+	}
+
+	if (sc->mps_debug & MPS_TRACE)
+		mpssas_log_command(cm,
+		    "ioc %x scsi %x state %x xfer %u\n",
+		    rep->IOCStatus, rep->SCSIStatus,
+		    rep->SCSIState, rep->TransferCount);
+
+	/*
+	 * If this is a Direct Drive I/O, reissue the I/O to the original IR
+	 * Volume if an error occurred (normal I/O retry).  Use the original
+	 * CCB, but set a flag that this will be a retry so that it's sent to
+	 * the original volume.  Free the command but reuse the CCB.
+	 */
+	if (cm->cm_flags & MPS_CM_FLAGS_DD_IO) {
+		mps_free_command(sc, cm);
+		ccb->ccb_h.status = MPS_WD_RETRY;
+		mpssas_action_scsiio(sassc, ccb);
+		return;
+	}
+
+	switch (rep->IOCStatus & MPI2_IOCSTATUS_MASK) {
+	case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+		csio->resid = cm->cm_length - rep->TransferCount;
+		/* FALLTHROUGH */
+	case MPI2_IOCSTATUS_SUCCESS:
+	case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+
+		if ((rep->IOCStatus & MPI2_IOCSTATUS_MASK) ==
+		    MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR)
+			mpssas_log_command(cm, "recovered error\n");
+
+		/* Completion failed at the transport level. */
+		if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS |
+		    MPI2_SCSI_STATE_TERMINATED)) {
+			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+			break;
+		}
+
+		/* In a modern packetized environment, an autosense failure
+		 * implies that there's not much else that can be done to
+		 * recover the command.
+		 */
+		if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) {
+			ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+			break;
+		}
+
+		/*
+		 * CAM doesn't care about SAS Response Info data, but if this is
+		 * the state check if TLR should be done.  If not, clear the
+		 * TLR_bits for the target.
+		 */
+		if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) &&
+		    ((rep->ResponseInfo & MPI2_SCSI_RI_MASK_REASONCODE) ==
+		    MPS_SCSI_RI_INVALID_FRAME)) {
+			sc->mapping_table[csio->ccb_h.target_id].TLR_bits =
+			    (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
+		}
+
+		/*
+		 * Intentionally override the normal SCSI status reporting
+		 * for these two cases.  These are likely to happen in a
+		 * multi-initiator environment, and we want to make sure that
+		 * CAM retries these commands rather than fail them.
+		 */
+		if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) ||
+		    (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) {
+			ccb->ccb_h.status = CAM_REQ_ABORTED;
+			break;
+		}
+
+		/* Handle normal status and sense */
+		csio->scsi_status = rep->SCSIStatus;
+		if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD)
+			ccb->ccb_h.status = CAM_REQ_CMP;
+		else
+			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+
+		if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+			int sense_len, returned_sense_len;
+
+			returned_sense_len = min(rep->SenseCount,
+			    sizeof(struct scsi_sense_data));
+			if (returned_sense_len < ccb->csio.sense_len)
+				ccb->csio.sense_resid = ccb->csio.sense_len -
+					returned_sense_len;
+			else
+				ccb->csio.sense_resid = 0;
+
+			sense_len = min(returned_sense_len,
+			    ccb->csio.sense_len - ccb->csio.sense_resid);
+			bzero(&ccb->csio.sense_data,
+			      sizeof(&ccb->csio.sense_data));
+			bcopy(cm->cm_sense, &ccb->csio.sense_data, sense_len);
+			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+		}
+
+		/*
+		 * Check if this is an INQUIRY command.  If it's a VPD inquiry,
+		 * and it's page code 0 (Supported Page List), and there is
+		 * inquiry data, and this is for a sequential access device, and
+		 * the device is an SSP target, and TLR is supported by the
+		 * controller, turn the TLR_bits value ON if page 0x90 is
+		 * supported.
+		 */
+		if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) &&
+		    (csio->cdb_io.cdb_bytes[1] & SI_EVPD) &&
+		    (csio->cdb_io.cdb_bytes[2] == SVPD_SUPPORTED_PAGE_LIST) &&
+		    (csio->data_ptr != NULL) && (((uint8_t *)cm->cm_data)[0] ==
+		    T_SEQUENTIAL) && (sc->control_TLR) &&
+		    (sc->mapping_table[csio->ccb_h.target_id].device_info &
+		    MPI2_SAS_DEVICE_INFO_SSP_TARGET)) {
+			vpd_list = (struct scsi_vpd_supported_page_list *)
+			    csio->data_ptr;
+			TLR_bits = &sc->mapping_table[csio->ccb_h.target_id].
+			    TLR_bits;
+			*TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
+			TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON;
+			alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) +
+			    csio->cdb_io.cdb_bytes[4];
+			for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) {
+				if (vpd_list->list[i] == 0x90) {
+					*TLR_bits = TLR_on;
+					break;
+				}
+			}
+		}
+		break;
+	case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+	case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+		/*
+		 * If devinfo is 0 this will be a volume.  In that case don't
+		 * tell CAM that the volume is not there.  We want volumes to
+		 * be enumerated until they are deleted/removed, not just
+		 * failed.
+		 */
+		if (cm->cm_targ->devinfo == 0)
+			ccb->ccb_h.status = CAM_REQ_CMP;
+		else
+			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+		break;
+	case MPI2_IOCSTATUS_INVALID_SGL:
+		mps_print_scsiio_cmd(sc, cm);
+		ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
+		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_DATA_OVERRUN:
+		/* resid is ignored for this condition */
+		csio->resid = 0;
+		ccb->ccb_h.status = CAM_DATA_RUN_ERR;
+		break;
+	case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+	case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+		/*
+		 * Since these are generally external (i.e. hopefully
+		 * transient transport-related) errors, retry these without
+		 * decrementing the retry count.
+		 */
+		ccb->ccb_h.status = CAM_REQUEUE_REQ;
+		mpssas_log_command(cm,
+		    "terminated ioc %x scsi %x state %x xfer %u\n",
+		    rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
+		    rep->TransferCount);
+		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:
+		mpssas_log_command(cm,
+		    "completed ioc %x scsi %x state %x xfer %u\n",
+		    rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
+		    rep->TransferCount);
+		csio->resid = cm->cm_length;
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+		break;
+	}
+
+	if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
+		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+		sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
+		mps_dprint(sc, MPS_INFO, "Command completed, "
+			   "unfreezing SIM queue\n");
+	}
+
+	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		ccb->ccb_h.status |= CAM_DEV_QFRZN;
+		xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
+	}
+
+	mps_free_command(sc, cm);
+	xpt_done(ccb);
+}
+
+static void
+mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
+    union ccb *ccb) {
+	pMpi2SCSIIORequest_t	pIO_req;
+	struct mps_softc	*sc = sassc->sc;
+	uint64_t		virtLBA;
+	uint32_t		physLBA, stripe_offset, stripe_unit;
+	uint32_t		io_size, column;
+	uint8_t			*ptrLBA, lba_idx, physLBA_byte, *CDB;
+
+	/*
+	 * If this is a valid SCSI command (Read6, Read10, Read16, Write6,
+	 * Write10, or Write16), build a direct I/O message.  Otherwise, the I/O
+	 * will be sent to the IR volume itself.  Since Read6 and Write6 are a
+	 * bit different than the 10/16 CDBs, handle them separately.
+	 */
+	pIO_req = (pMpi2SCSIIORequest_t)cm->cm_req;
+	CDB = pIO_req->CDB.CDB32;
+
+	/*
+	 * Handle 6 byte CDBs.
+	 */
+	if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_6) ||
+	    (CDB[0] == WRITE_6))) {
+		/*
+		 * Get the transfer size in blocks.
+		 */
+		io_size = (cm->cm_length >> sc->DD_block_exponent);
+
+		/*
+		 * Get virtual LBA given in the CDB.
+		 */
+		virtLBA = ((uint64_t)(CDB[1] & 0x1F) << 16) |
+		    ((uint64_t)CDB[2] << 8) | (uint64_t)CDB[3];
+
+		/*
+		 * Check that LBA range for I/O does not exceed volume's
+		 * MaxLBA.
+		 */
+		if ((virtLBA + (uint64_t)io_size - 1) <=
+		    sc->DD_max_lba) {
+			/*
+			 * Check if the I/O crosses a stripe boundary.  If not,
+			 * translate the virtual LBA to a physical LBA and set
+			 * the DevHandle for the PhysDisk to be used.  If it
+			 * does cross a boundry, do normal I/O.  To get the
+			 * right DevHandle to use, get the map number for the
+			 * column, then use that map number to look up the
+			 * DevHandle of the PhysDisk.
+			 */
+			stripe_offset = (uint32_t)virtLBA &
+			    (sc->DD_stripe_size - 1);
+			if ((stripe_offset + io_size) <= sc->DD_stripe_size) {
+				physLBA = (uint32_t)virtLBA >>
+				    sc->DD_stripe_exponent;
+				stripe_unit = physLBA / sc->DD_num_phys_disks;
+				column = physLBA % sc->DD_num_phys_disks;
+				pIO_req->DevHandle =
+				    sc->DD_column_map[column].dev_handle;
+				cm->cm_desc.SCSIIO.DevHandle =
+				    pIO_req->DevHandle;
+
+				physLBA = (stripe_unit <<
+				    sc->DD_stripe_exponent) + stripe_offset;
+				ptrLBA = &pIO_req->CDB.CDB32[1];
+				physLBA_byte = (uint8_t)(physLBA >> 16);
+				*ptrLBA = physLBA_byte;
+				ptrLBA = &pIO_req->CDB.CDB32[2];
+				physLBA_byte = (uint8_t)(physLBA >> 8);
+				*ptrLBA = physLBA_byte;
+				ptrLBA = &pIO_req->CDB.CDB32[3];
+				physLBA_byte = (uint8_t)physLBA;
+				*ptrLBA = physLBA_byte;
+
+				/*
+				 * Set flag that Direct Drive I/O is
+				 * being done.
+				 */
+				cm->cm_flags |= MPS_CM_FLAGS_DD_IO;
+			}
+		}
+		return;
+	}
+
+	/*
+	 * Handle 10 or 16 byte CDBs.
+	 */
+	if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_10) ||
+	    (CDB[0] == WRITE_10) || (CDB[0] == READ_16) ||
+	    (CDB[0] == WRITE_16))) {
+		/*
+		 * For 16-byte CDB's, verify that the upper 4 bytes of the CDB
+		 * are 0.  If not, this is accessing beyond 2TB so handle it in
+		 * the else section.  10-byte CDB's are OK.
+		 */
+		if ((CDB[0] < READ_16) ||
+		    !(CDB[2] | CDB[3] | CDB[4] | CDB[5])) {
+			/*
+			 * Get the transfer size in blocks.
+			 */
+			io_size = (cm->cm_length >> sc->DD_block_exponent);
+
+			/*
+			 * Get virtual LBA.  Point to correct lower 4 bytes of
+			 * LBA in the CDB depending on command.
+			 */
+			lba_idx = (CDB[0] < READ_16) ? 2 : 6;
+			virtLBA = ((uint64_t)CDB[lba_idx] << 24) |
+			    ((uint64_t)CDB[lba_idx + 1] << 16) |
+			    ((uint64_t)CDB[lba_idx + 2] << 8) |
+			    (uint64_t)CDB[lba_idx + 3];
+
+			/*
+			 * Check that LBA range for I/O does not exceed volume's
+			 * MaxLBA.
+			 */
+			if ((virtLBA + (uint64_t)io_size - 1) <=
+			    sc->DD_max_lba) {
+				/*
+				 * Check if the I/O crosses a stripe boundary.
+				 * If not, translate the virtual LBA to a
+				 * physical LBA and set the DevHandle for the
+				 * PhysDisk to be used.  If it does cross a
+				 * boundry, do normal I/O.  To get the right
+				 * DevHandle to use, get the map number for the
+				 * column, then use that map number to look up
+				 * the DevHandle of the PhysDisk.
+				 */
+				stripe_offset = (uint32_t)virtLBA &
+				    (sc->DD_stripe_size - 1);
+				if ((stripe_offset + io_size) <=
+				    sc->DD_stripe_size) {
+					physLBA = (uint32_t)virtLBA >>
+					    sc->DD_stripe_exponent;
+					stripe_unit = physLBA /
+					    sc->DD_num_phys_disks;
+					column = physLBA %
+					    sc->DD_num_phys_disks;
+					pIO_req->DevHandle =
+					    sc->DD_column_map[column].
+					    dev_handle;
+					cm->cm_desc.SCSIIO.DevHandle =
+					    pIO_req->DevHandle;
+
+					physLBA = (stripe_unit <<
+					    sc->DD_stripe_exponent) +
+					    stripe_offset;
+					ptrLBA =
+					    &pIO_req->CDB.CDB32[lba_idx];
+					physLBA_byte = (uint8_t)(physLBA >> 24);
+					*ptrLBA = physLBA_byte;
+					ptrLBA =
+					    &pIO_req->CDB.CDB32[lba_idx + 1];
+					physLBA_byte = (uint8_t)(physLBA >> 16);
+					*ptrLBA = physLBA_byte;
+					ptrLBA =
+					    &pIO_req->CDB.CDB32[lba_idx + 2];
+					physLBA_byte = (uint8_t)(physLBA >> 8);
+					*ptrLBA = physLBA_byte;
+					ptrLBA =
+					    &pIO_req->CDB.CDB32[lba_idx + 3];
+					physLBA_byte = (uint8_t)physLBA;
+					*ptrLBA = physLBA_byte;
+
+					/*
+					 * Set flag that Direct Drive I/O is
+					 * being done.
+					 */
+					cm->cm_flags |= MPS_CM_FLAGS_DD_IO;
+				}
+			}
+		} else {
+			/*
+			 * 16-byte CDB and the upper 4 bytes of the CDB are not
+			 * 0.  Get the transfer size in blocks.
+			 */
+			io_size = (cm->cm_length >> sc->DD_block_exponent);
+
+			/*
+			 * Get virtual LBA.
+			 */
+			virtLBA = ((uint64_t)CDB[2] << 54) |
+			    ((uint64_t)CDB[3] << 48) |
+			    ((uint64_t)CDB[4] << 40) |
+			    ((uint64_t)CDB[5] << 32) |
+			    ((uint64_t)CDB[6] << 24) |
+			    ((uint64_t)CDB[7] << 16) |
+			    ((uint64_t)CDB[8] << 8) |
+			    (uint64_t)CDB[9];
+
+			/*
+			 * Check that LBA range for I/O does not exceed volume's
+			 * MaxLBA.
+			 */
+			if ((virtLBA + (uint64_t)io_size - 1) <=
+			    sc->DD_max_lba) {
+				/*
+				 * Check if the I/O crosses a stripe boundary.
+				 * If not, translate the virtual LBA to a
+				 * physical LBA and set the DevHandle for the
+				 * PhysDisk to be used.  If it does cross a
+				 * boundry, do normal I/O.  To get the right
+				 * DevHandle to use, get the map number for the
+				 * column, then use that map number to look up
+				 * the DevHandle of the PhysDisk.
+				 */
+				stripe_offset = (uint32_t)virtLBA &
+				    (sc->DD_stripe_size - 1);
+				if ((stripe_offset + io_size) <=
+				    sc->DD_stripe_size) {
+					physLBA = (uint32_t)(virtLBA >>
+					    sc->DD_stripe_exponent);
+					stripe_unit = physLBA /
+					    sc->DD_num_phys_disks;
+					column = physLBA %
+					    sc->DD_num_phys_disks;
+					pIO_req->DevHandle =
+					    sc->DD_column_map[column].
+					    dev_handle;
+					cm->cm_desc.SCSIIO.DevHandle =
+					    pIO_req->DevHandle;
+
+					physLBA = (stripe_unit <<
+					    sc->DD_stripe_exponent) +
+					    stripe_offset;
+
+					/*
+					 * Set upper 4 bytes of LBA to 0.  We
+					 * assume that the phys disks are less
+					 * than 2 TB's in size.  Then, set the
+					 * lower 4 bytes.
+					 */
+					pIO_req->CDB.CDB32[2] = 0;
+					pIO_req->CDB.CDB32[3] = 0;
+					pIO_req->CDB.CDB32[4] = 0;
+					pIO_req->CDB.CDB32[5] = 0;
+					ptrLBA = &pIO_req->CDB.CDB32[6];
+					physLBA_byte = (uint8_t)(physLBA >> 24);
+					*ptrLBA = physLBA_byte;
+					ptrLBA = &pIO_req->CDB.CDB32[7];
+					physLBA_byte = (uint8_t)(physLBA >> 16);
+					*ptrLBA = physLBA_byte;
+					ptrLBA = &pIO_req->CDB.CDB32[8];
+					physLBA_byte = (uint8_t)(physLBA >> 8);
+					*ptrLBA = physLBA_byte;
+					ptrLBA = &pIO_req->CDB.CDB32[9];
+					physLBA_byte = (uint8_t)physLBA;
+					*ptrLBA = physLBA_byte;
+
+					/*
+					 * Set flag that Direct Drive I/O is
+					 * being done.
+					 */
+					cm->cm_flags |= MPS_CM_FLAGS_DD_IO;
+				}
+			}
+		}
+	}
+}
+
+#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;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and SMP
+	 * commands require two S/G elements only.  That should be handled
+	 * in the standard request size.
+	 */
+	if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mps_printf(sc, "%s: cm_flags = %#x on SMP request!\n",
+			   __func__, cm->cm_flags);
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+		goto bailout;
+        }
+
+	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) {
+#ifdef OLD_MPS_PROBE
+		struct mpssas_target *parent_target;
+#endif
+
+		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;
+		}
+#ifdef OLD_MPS_PROBE
+		parent_target = mpssas_find_target_by_handle(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;
+#else /* OLD_MPS_PROBE */
+		if ((targ->parent_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, targ->parent_handle);
+			ccb->ccb_h.status = CAM_REQ_INVALID;
+			goto bailout;
+
+		}
+		if (targ->parent_sasaddr == 0x0) {
+			mps_printf(sc, "%s: handle %d parent handle %d does "
+				   "not have a valid SAS address!\n",
+				   __func__, targ->handle, targ->parent_handle);
+			ccb->ccb_h.status = CAM_REQ_INVALID;
+			goto bailout;
+		}
+
+		sasaddr = targ->parent_sasaddr;
+#endif /* OLD_MPS_PROBE */
+
+	}
+
+	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)
+{
+	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+	struct mps_softc *sc;
+	struct mps_command *tm;
+	struct mpssas_target *targ;
+
+	mps_dprint(sassc->sc, MPS_TRACE, __func__);
+	KKASSERT(lockstatus(&sassc->sc->mps_lock, curthread) != 0);
+
+	sc = sassc->sc;
+	tm = mps_alloc_command(sc);
+	if (tm == NULL) {
+		mps_printf(sc, "comand alloc failure in mpssas_action_resetdev\n");
+		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+		xpt_done(ccb);
+		return;
+	}
+
+	targ = &sassc->targets[ccb->ccb_h.target_id];
+	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->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;
+
+	tm->cm_data = NULL;
+	tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+	tm->cm_complete = mpssas_resetdev_complete;
+	tm->cm_complete_data = ccb;
+	mps_map_command(sc, tm);
+}
+
+static void
+mpssas_resetdev_complete(struct mps_softc *sc, struct mps_command *tm)
+{
+	MPI2_SCSI_TASK_MANAGE_REPLY *resp;
+	union ccb *ccb;
+
+	mps_dprint(sc, MPS_TRACE, __func__);
+	KKASSERT(lockstatus(&sc->mps_lock, curthread) != 0);
+
+	resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
+	ccb = tm->cm_complete_data;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * task management commands don't have S/G lists.
+	 */
+	if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+
+		req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
+
+		mps_printf(sc, "%s: cm_flags = %#x for reset of handle %#04x! "
+			   "This should not happen!\n", __func__, tm->cm_flags,
+			   req->DevHandle);
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+		goto bailout;
+	}
+
+	kprintf("%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__,
+	    resp->IOCStatus, resp->ResponseCode);
+
+	if (resp->ResponseCode == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) {
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
+		    CAM_LUN_WILDCARD);
+	}
+	else
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+
+bailout:
+
+	mpssas_free_tm(sc, tm);
+	xpt_done(ccb);
+}
+
+static void
+mpssas_poll(struct cam_sim *sim)
+{
+	struct mpssas_softc *sassc;
+
+	sassc = cam_sim_softc(sim);
+
+	if (sassc->sc->mps_debug & MPS_TRACE) {
+		/* frequent debug messages during a panic just slow
+		 * everything down too much.
+		 */
+		mps_printf(sassc->sc, "%s clearing MPS_TRACE\n", __func__);
+		sassc->sc->mps_debug &= ~MPS_TRACE;
+	}
+
+	mps_intr_locked(sassc->sc);
+}
+
+static void
+mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb)
+{
+	struct mpssas_softc *sassc;
+	char path_str[64];
+
+	if (done_ccb == NULL)
+		return;
+
+	sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
+
+	KKASSERT(lockstatus(&sassc->sc->mps_lock, curthread) != 0);
+
+	xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
+	mps_dprint(sassc->sc, MPS_INFO, "Completing rescan for %s\n", path_str);
+
+	xpt_free_path(done_ccb->ccb_h.path);
+	xpt_free_ccb(done_ccb);
+
+#if __FreeBSD_version < 1000006
+	/*
+	 * Before completing scan, get EEDP stuff for all of the existing
+	 * targets.
+	 */
+	mpssas_check_eedp(sassc);
+#endif
+
+}
+
+/* thread to handle bus rescans */
+static void
+mpssas_scanner_thread(void *arg)
+{
+	struct mpssas_softc *sassc;
+	struct mps_softc *sc;
+	union ccb	*ccb;
+
+	sassc = (struct mpssas_softc *)arg;
+	sc = sassc->sc;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	mps_lock(sc);
+	for (;;) {
+		lksleep(&sassc->ccb_scanq, &sc->mps_lock, 0, "mps_scanq", 0);
+		if (sassc->flags & MPSSAS_SHUTDOWN) {
+			mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
+			break;
+		}
+		ccb = (union ccb *)TAILQ_FIRST(&sassc->ccb_scanq);
+		if (ccb == NULL)
+			continue;
+		TAILQ_REMOVE(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+		xpt_action(ccb);
+	}
+
+	sassc->flags &= ~MPSSAS_SCANTHREAD;
+	wakeup(&sassc->flags);
+	mps_unlock(sc);
+	mps_dprint(sc, MPS_TRACE, "Scanner exiting\n");
+	mps_kproc_exit(0);
+}
+
+static void
+mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb)
+{
+	char path_str[64];
+
+	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+
+	KKASSERT(lockstatus(&sassc->sc->mps_lock, curthread) != 0);
+
+	if (ccb == NULL)
+		return;
+
+	xpt_path_string(ccb->ccb_h.path, path_str, sizeof(path_str));
+	mps_dprint(sassc->sc, MPS_INFO, "Queueing rescan for %s\n", path_str);
+
+	/* Prepare request */
+	ccb->ccb_h.ppriv_ptr1 = sassc;
+	ccb->ccb_h.cbfcnp = mpssas_rescan_done;
+	xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, MPS_PRIORITY_XPT);
+	TAILQ_INSERT_TAIL(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+	wakeup(&sassc->ccb_scanq);
+}
+
+#if __FreeBSD_version >= 1000006
+static void
+mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path,
+	     void *arg)
+{
+	struct mps_softc *sc;
+
+	sc = (struct mps_softc *)callback_arg;
+
+	switch (code) {
+	case AC_ADVINFO_CHANGED: {
+		struct mpssas_target *target;
+		struct mpssas_softc *sassc;
+		struct scsi_read_capacity_data_long rcap_buf;
+		struct ccb_dev_advinfo cdai;
+		struct mpssas_lun *lun;
+		lun_id_t lunid;
+		int found_lun;
+		uintptr_t buftype;
+
+		buftype = (uintptr_t)arg;
+
+		found_lun = 0;
+		sassc = sc->sassc;
+
+		/*
+		 * We're only interested in read capacity data changes.
+		 */
+		if (buftype != CDAI_TYPE_RCAPLONG)
+			break;
+
+		/*
+		 * We're only interested in devices that are attached to
+		 * this controller.
+		 */
+		if (xpt_path_path_id(path) != sassc->sim->path_id)
+			break;
+
+		/*
+		 * We should have a handle for this, but check to make sure.
+		 */
+		target = &sassc->targets[xpt_path_target_id(path)];
+		if (target->handle == 0)
+			break;
+
+		lunid = xpt_path_lun_id(path);
+
+		SLIST_FOREACH(lun, &target->luns, lun_link) {
+			if (lun->lun_id == lunid) {
+				found_lun = 1;
+				break;
+			}
+		}
+
+		if (found_lun == 0) {
+			lun = kmalloc(sizeof(struct mpssas_lun), M_MPT2,
+				     M_NOWAIT | M_ZERO);
+			if (lun == NULL) {
+				mps_dprint(sc, MPS_FAULT, "Unable to alloc "
+					   "LUN for EEDP support.\n");
+				break;
+			}
+			lun->lun_id = lunid;
+			SLIST_INSERT_HEAD(&target->luns, lun, lun_link);
+		}
+
+		bzero(&rcap_buf, sizeof(rcap_buf));
+		xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL);
+		cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
+		cdai.ccb_h.flags = CAM_DIR_IN;
+		cdai.buftype = CDAI_TYPE_RCAPLONG;
+		cdai.flags = 0;
+		cdai.bufsiz = sizeof(rcap_buf);
+		cdai.buf = (uint8_t *)&rcap_buf;
+		xpt_action((union ccb *)&cdai);
+		if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
+			cam_release_devq(cdai.ccb_h.path,
+					 0, 0, 0, FALSE);
+
+		if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
+		 && (rcap_buf.prot & SRC16_PROT_EN)) {
+			lun->eedp_formatted = TRUE;
+			lun->eedp_block_size = scsi_4btoul(rcap_buf.length);
+		} else {
+			lun->eedp_formatted = FALSE;
+			lun->eedp_block_size = 0;
+		}
+		break;
+	}
+	default:
+		break;
+	}
+}
+#else /* __FreeBSD_version >= 1000006 */
+
+static void
+mpssas_check_eedp(struct mpssas_softc *sassc)
+{
+	struct mps_softc *sc = sassc->sc;
+	struct ccb_scsiio *csio;
+	struct scsi_read_capacity_16 *scsi_cmd;
+	struct scsi_read_capacity_eedp *rcap_buf;
+	union ccb *ccb;
+	path_id_t pathid = cam_sim_path(sassc->sim);
+	target_id_t targetid;
+	lun_id_t lunid;
+	struct cam_periph *found_periph;
+	struct mpssas_target *target;
+	struct mpssas_lun *lun;
+	uint8_t	found_lun;
+
+	/*
+	 * Issue a READ CAPACITY 16 command to each LUN of each target.  This
+	 * info is used to determine if the LUN is formatted for EEDP support.
+	 */
+	for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
+		target = &sassc->targets[targetid];
+		if (target->handle == 0x0) {
+			continue;
+		}
+
+		lunid = 0;
+		do {
+			rcap_buf =
+			    kmalloc(sizeof(struct scsi_read_capacity_eedp),
+			    M_MPT2, M_NOWAIT | M_ZERO);
+			if (rcap_buf == NULL) {
+				mps_dprint(sc, MPS_FAULT, "Unable to alloc read "
+				    "capacity buffer for EEDP support.\n");
+				return;
+			}
+
+			ccb = kmalloc(sizeof(union ccb), M_TEMP,
+			    M_WAITOK | M_ZERO);
+
+			if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+			    pathid, targetid, lunid) != CAM_REQ_CMP) {
+				mps_dprint(sc, MPS_FAULT, "Unable to create "
+				    "path for EEDP support\n");
+				kfree(rcap_buf, M_MPT2);
+				xpt_free_ccb(ccb);
+				return;
+			}
+
+			/*
+			 * If a periph is returned, the LUN exists.  Create an
+			 * entry in the target's LUN list.
+			 */
+			if ((found_periph = cam_periph_find(ccb->ccb_h.path,
+			    NULL)) != NULL) {
+				/*
+				 * If LUN is already in list, don't create a new
+				 * one.
+				 */
+				found_lun = FALSE;
+				SLIST_FOREACH(lun, &target->luns, lun_link) {
+					if (lun->lun_id == lunid) {
+						found_lun = TRUE;
+						break;
+					}
+				}
+				if (!found_lun) {
+					lun = kmalloc(sizeof(struct mpssas_lun),
+					    M_MPT2, M_WAITOK | M_ZERO);
+					if (lun == NULL) {
+						mps_dprint(sc, MPS_FAULT,
+						    "Unable to alloc LUN for "
+						    "EEDP support.\n");
+						kfree(rcap_buf, M_MPT2);
+						xpt_free_path(ccb->ccb_h.path);
+						xpt_free_ccb(ccb);
+						return;
+					}
+					lun->lun_id = lunid;
+					SLIST_INSERT_HEAD(&target->luns, lun,
+					    lun_link);
+				}
+				lunid++;
+
+				/*
+				 * Issue a READ CAPACITY 16 command for the LUN.
+				 * The mpssas_read_cap_done function will load
+				 * the read cap info into the LUN struct.
+				 */
+				csio = &ccb->csio;
+				csio->ccb_h.func_code = XPT_SCSI_IO;
+				csio->ccb_h.flags = CAM_DIR_IN;
+				csio->ccb_h.retry_count = 4;
+				csio->ccb_h.cbfcnp = mpssas_read_cap_done;
+				csio->ccb_h.timeout = 60000;
+				csio->data_ptr = (uint8_t *)rcap_buf;
+				csio->dxfer_len = sizeof(struct
+				    scsi_read_capacity_eedp);
+				csio->sense_len = MPS_SENSE_LEN;
+				csio->cdb_len = sizeof(*scsi_cmd);
+				csio->tag_action = MSG_SIMPLE_Q_TAG;
+
+				scsi_cmd = (struct scsi_read_capacity_16 *)
+				    &csio->cdb_io.cdb_bytes;
+				bzero(scsi_cmd, sizeof(*scsi_cmd));
+				scsi_cmd->opcode = 0x9E;
+				scsi_cmd->service_action = SRC16_SERVICE_ACTION;
+				((uint8_t *)scsi_cmd)[13] = sizeof(struct
+				    scsi_read_capacity_eedp);
+
+				/*
+				 * Set the path, target and lun IDs for the READ
+				 * CAPACITY request.
+				 */
+				ccb->ccb_h.path_id =
+				    xpt_path_path_id(ccb->ccb_h.path);
+				ccb->ccb_h.target_id =
+				    xpt_path_target_id(ccb->ccb_h.path);
+				ccb->ccb_h.target_lun =
+				    xpt_path_lun_id(ccb->ccb_h.path);
+
+				ccb->ccb_h.ppriv_ptr1 = sassc;
+				xpt_action(ccb);
+			} else {
+				kfree(rcap_buf, M_MPT2);
+				xpt_free_path(ccb->ccb_h.path);
+				xpt_free_ccb(ccb);
+			}
+		} while (found_periph);
+	}
+}
+
+
+static void
+mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
+{
+	struct mpssas_softc *sassc;
+	struct mpssas_target *target;
+	struct mpssas_lun *lun;
+	struct scsi_read_capacity_eedp *rcap_buf;
+
+	if (done_ccb == NULL)
+		return;
+
+	rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr;
+
+	/*
+	 * Get the LUN ID for the path and look it up in the LUN list for the
+	 * target.
+	 */
+	sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
+	target = &sassc->targets[done_ccb->ccb_h.target_id];
+	SLIST_FOREACH(lun, &target->luns, lun_link) {
+		if (lun->lun_id != done_ccb->ccb_h.target_lun)
+			continue;
+
+		/*
+		 * Got the LUN in the target's LUN list.  Fill it in
+		 * with EEDP info.  If the READ CAP 16 command had some
+		 * SCSI error (common if command is not supported), mark
+		 * the lun as not supporting EEDP and set the block size
+		 * to 0.
+		 */
+		if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+		 || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) {
+			lun->eedp_formatted = FALSE;
+			lun->eedp_block_size = 0;
+			break;
+		}
+
+		if (rcap_buf->protect & 0x01) {
+			lun->eedp_formatted = TRUE;
+			lun->eedp_block_size = scsi_4btoul(rcap_buf->length);
+		}
+		break;
+	}
+
+	// Finished with this CCB and path.
+	kfree(rcap_buf, M_MPT2);
+	xpt_free_path(done_ccb->ccb_h.path);
+	xpt_free_ccb(done_ccb);
+}
+#endif /* __FreeBSD_version >= 1000006 */
+
+int
+mpssas_startup(struct mps_softc *sc)
+{
+	struct mpssas_softc *sassc;
+
+	/*
+	 * Send the port enable message and set the wait_for_port_enable flag.
+	 * This flag helps to keep the simq frozen until all discovery events
+	 * are processed.
+	 */
+	sassc = sc->sassc;
+	mpssas_startup_increment(sassc);
+	sc->wait_for_port_enable = 1;
+	mpssas_send_portenable(sc);
+	return (0);
+}
+
+static int
+mpssas_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 = mpssas_portenable_complete;
+	cm->cm_data = NULL;
+	cm->cm_sge = NULL;
+
+	mps_map_command(sc, cm);
+	mps_dprint(sc, MPS_TRACE,
+	    "mps_send_portenable finished cm %p req %p complete %p\n",
+	    cm, cm->cm_req, cm->cm_complete);
+	return (0);
+}
+
+static void
+mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm)
+{
+	MPI2_PORT_ENABLE_REPLY *reply;
+	struct mpssas_softc *sassc;
+	struct mpssas_target *target;
+	int i;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+	sassc = sc->sassc;
+
+	/*
+	 * Currently there should be no way we can hit this case.  It only
+	 * happens when we have a failure to allocate chain frames, and
+	 * port enable commands don't have S/G lists.
+	 */
+	if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
+		mps_printf(sc, "%s: cm_flags = %#x for port enable! "
+			   "This should not happen!\n", __func__, cm->cm_flags);
+	}
+
+	reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply;
+	if (reply == NULL)
+		mps_dprint(sc, MPS_FAULT, "Portenable NULL reply\n");
+	else if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
+	    MPI2_IOCSTATUS_SUCCESS)
+		mps_dprint(sc, MPS_FAULT, "Portenable failed\n");
+
+	mps_free_command(sc, cm);
+	if (sc->mps_ich.ich_arg != NULL) {
+		mps_dprint(sc, MPS_INFO, "disestablish config intrhook\n");
+		config_intrhook_disestablish(&sc->mps_ich);
+		sc->mps_ich.ich_arg = NULL;
+	}
+
+	/*
+	 * Get WarpDrive info after discovery is complete but before the scan
+	 * starts.  At this point, all devices are ready to be exposed to the
+	 * OS.  If devices should be hidden instead, take them out of the
+	 * 'targets' array before the scan.  The devinfo for a disk will have
+	 * some info and a volume's will be 0.  Use that to remove disks.
+	 */
+	mps_wd_config_pages(sc);
+	if (((sc->mps_flags & MPS_FLAGS_WD_AVAILABLE)
+	  && (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS))
+	 || (sc->WD_valid_config && (sc->WD_hide_expose ==
+	    MPS_WD_HIDE_IF_VOLUME))) {
+		for (i = 0; i < sassc->sc->facts->MaxTargets; i++) {
+			target = &sassc->targets[i];
+			if (target->devinfo) {
+				target->devinfo = 0x0;
+				target->encl_handle = 0x0;
+				target->encl_slot = 0x0;
+				target->handle = 0x0;
+				target->tid = 0x0;
+				target->linkrate = 0x0;
+				target->flags = 0x0;
+			}
+		}
+	}
+
+	/*
+	 * Done waiting for port enable to complete.  Decrement the refcount.
+	 * If refcount is 0, discovery is complete and a rescan of the bus can
+	 * take place.  Since the simq was explicitly frozen before port
+	 * enable, it must be explicitly released here to keep the
+	 * freeze/release count in sync.
+	 */
+	sc->wait_for_port_enable = 0;
+	sc->port_enable_complete = 1;
+	mpssas_startup_decrement(sassc);
+	xpt_release_simq(sassc->sim, 1);
+}
diff --git a/sys/dev/raid/mps/mps_sas.h b/sys/dev/raid/mps/mps_sas.h
new file mode 100644
index 0000000..f926dec
--- /dev/null
+++ b/sys/dev/raid/mps/mps_sas.h
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_sas.h,v 1.1 2012/01/26 18:17:21 ken Exp $
+ */
+
+struct mps_fw_event_work;
+
+struct mpssas_lun {
+	SLIST_ENTRY(mpssas_lun) lun_link;
+	lun_id_t	lun_id;
+	uint8_t		eedp_formatted;
+	uint32_t	eedp_block_size;
+};
+
+struct mpssas_target {
+	uint16_t	handle;
+	uint8_t		linkrate;
+	uint64_t	devname;
+	uint32_t	devinfo;
+	uint16_t	encl_handle;
+	uint16_t	encl_slot;
+	uint8_t		flags;
+#define MPSSAS_TARGET_INABORT	(1 << 0)
+#define MPSSAS_TARGET_INRESET	(1 << 1)
+#define MPSSAS_TARGET_INDIAGRESET (1 << 2)
+#define MPSSAS_TARGET_INREMOVAL	(1 << 3)
+#define MPSSAS_TARGET_INRECOVERY (MPSSAS_TARGET_INABORT | \
+    MPSSAS_TARGET_INRESET | MPSSAS_TARGET_INCHIPRESET)
+#define MPSSAS_TARGET_ADD       (1 << 29)
+#define MPSSAS_TARGET_REMOVE    (1 << 30)
+	uint16_t	tid;
+	SLIST_HEAD(, mpssas_lun) luns;
+	TAILQ_HEAD(, mps_command) commands;
+	struct mps_command *tm;
+	TAILQ_HEAD(, mps_command) timedout_commands;
+	uint16_t        exp_dev_handle;
+	uint16_t        phy_num;
+	uint64_t	sasaddr;
+	uint16_t	parent_handle;
+	uint64_t	parent_sasaddr;
+	uint32_t	parent_devinfo;
+	struct sysctl_ctx_list sysctl_ctx;
+	struct sysctl_oid *sysctl_tree;
+	TAILQ_ENTRY(mpssas_target) sysctl_link;
+	uint64_t        issued;
+	uint64_t        completed;
+	unsigned int    outstanding;
+	unsigned int    timeouts;
+	unsigned int    aborts;
+	unsigned int    logical_unit_resets;
+	unsigned int    target_resets;
+};
+
+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)
+#define	MPSSAS_SHUTDOWN		(1 << 4)
+#define	MPSSAS_SCANTHREAD	(1 << 5)
+	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;
+
+	u_int                   startup_refcount;
+	u_int                   tm_count;
+	struct proc             *sysctl_proc;
+
+	TAILQ_HEAD(, ccb_hdr) ccb_scanq;
+	struct thread		*rescan_thread;
+
+	struct taskqueue	*ev_tq;
+	struct task		ev_task;
+	TAILQ_HEAD(, mps_fw_event_work)	ev_queue;
+};
+
+MALLOC_DECLARE(M_MPSSAS);
+
+/*
+ * 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);
+}
+
+#define MPS_SET_SINGLE_LUN(req, lun)	\
+do {					\
+	bzero((req)->LUN, 8);		\
+	(req)->LUN[1] = lun;		\
+} while(0)
+
+void mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ);
+void mpssas_discovery_end(struct mpssas_softc *sassc);
+void mpssas_startup_increment(struct mpssas_softc *sassc);
+void mpssas_startup_decrement(struct mpssas_softc *sassc);
+
+struct mps_command * mpssas_alloc_tm(struct mps_softc *sc);
+void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm);
+void mpssas_firmware_event_work(void *arg, int pending);
diff --git a/sys/dev/raid/mps/mps_sas_lsi.c b/sys/dev/raid/mps/mps_sas_lsi.c
new file mode 100644
index 0000000..51b3916
--- /dev/null
+++ b/sys/dev/raid/mps/mps_sas_lsi.c
@@ -0,0 +1,862 @@
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_sas_lsi.c,v 1.1 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* Communications core for LSI MPT2 */
+
+/* TODO Move headers to mpsvar */
+#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/eventhandler.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+#include <sys/sbuf.h>
+
+#include <sys/rman.h>
+
+#include <machine/stdarg.h>
+
+#include <bus/cam/cam.h>
+#include <bus/cam/cam_ccb.h>
+#include <bus/cam/cam_debug.h>
+#include <bus/cam/cam_sim.h>
+#include <bus/cam/cam_xpt_sim.h>
+#include <bus/cam/cam_xpt_periph.h>
+#include <bus/cam/cam_periph.h>
+#include <bus/cam/scsi/scsi_all.h>
+#include <bus/cam/scsi/scsi_message.h>
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_sas.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_raid.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+#include <dev/raid/mps/mps_table.h>
+#include <dev/raid/mps/mps_sas.h>
+
+/* For Hashed SAS Address creation for SATA Drives */
+#define MPT2SAS_SN_LEN 20
+#define MPT2SAS_MN_LEN 40
+
+struct mps_fw_event_work {
+	u16			event;
+	void			*event_data;
+	TAILQ_ENTRY(mps_fw_event_work)	ev_link;
+};
+
+union _sata_sas_address {
+	u8 wwid[8];
+	struct {
+		u32 high;
+		u32 low;
+	} word;
+};
+
+/*
+ * define the IDENTIFY DEVICE structure
+ */
+struct _ata_identify_device_data {
+	u16 reserved1[10];	/* 0-9 */
+	u16 serial_number[10];	/* 10-19 */
+	u16 reserved2[7];	/* 20-26 */
+	u16 model_number[20];	/* 27-46*/
+	u16 reserved3[209];	/* 47-255*/
+};
+
+static void mpssas_fw_work(struct mps_softc *sc,
+    struct mps_fw_event_work *fw_event);
+static void mpssas_fw_event_free(struct mps_softc *,
+    struct mps_fw_event_work *);
+static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate);
+static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
+    Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
+    u32 devinfo);
+int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
+    u64 *sas_address, u16 handle, u32 device_info);
+static int mpssas_volume_add(struct mps_softc *sc,
+    Mpi2EventIrConfigElement_t *element);
+
+void
+mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
+    MPI2_EVENT_NOTIFICATION_REPLY *event)
+{
+	struct mps_fw_event_work *fw_event;
+	u16 sz;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+	mps_print_evt_sas(sc, event);
+	mpssas_record_event(sc, event);
+
+	fw_event = kmalloc(sizeof(struct mps_fw_event_work), M_MPT2,
+	     M_ZERO|M_NOWAIT);
+	if (!fw_event) {
+		kprintf("%s: allocate failed for fw_event\n", __func__);
+		return;
+	}
+	sz = le16toh(event->EventDataLength) * 4;
+	fw_event->event_data = kmalloc(sz, M_MPT2, M_ZERO|M_NOWAIT);
+	if (!fw_event->event_data) {
+		kprintf("%s: allocate failed for event_data\n", __func__);
+		kfree(fw_event, M_MPT2);
+		return;
+	}
+
+	bcopy(event->EventData, fw_event->event_data, sz);
+	fw_event->event = event->Event;
+	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
+	    event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||
+	    event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
+	    sc->track_mapping_events)
+		sc->pending_map_events++;
+
+	/*
+	 * When wait_for_port_enable flag is set, make sure that all the events
+	 * are processed. Increment the startup_refcount and decrement it after
+	 * events are processed.
+	 */
+	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
+	    event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
+	    sc->wait_for_port_enable)
+		mpssas_startup_increment(sc->sassc);
+
+	TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
+	taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
+
+}
+
+static void
+mpssas_fw_event_free(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
+{
+
+	kfree(fw_event->event_data, M_MPT2);
+	kfree(fw_event, M_MPT2);
+}
+
+/**
+ * _mps_fw_work - delayed task for processing firmware events
+ * @sc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
+{
+	struct mpssas_softc *sassc;
+	sassc = sc->sassc;
+
+	switch (fw_event->event) {
+	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 *)
+		    fw_event->event_data;
+
+		mps_mapping_topology_change_event(sc, fw_event->event_data);
+
+		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:
+				if (mpssas_add_device(sc,
+				    phy->AttachedDevHandle, phy->LinkRate)){
+					kprintf("%s: failed to add device with "
+					    "handle 0x%x\n", __func__,
+					    phy->AttachedDevHandle);
+					mpssas_prepare_remove(sassc, phy->
+					    AttachedDevHandle);
+				}
+				break;
+			case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
+				mpssas_prepare_remove(sassc, phy->
+				    AttachedDevHandle);
+				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;
+			}
+		}
+		/*
+		 * refcount was incremented for this event in
+		 * mpssas_evt_handler.  Decrement it here because the event has
+		 * been processed.
+		 */
+		mpssas_startup_decrement(sassc);
+		break;
+	}
+	case MPI2_EVENT_SAS_DISCOVERY:
+	{
+		MPI2_EVENT_DATA_SAS_DISCOVERY *data;
+
+		data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data;
+
+		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 stop event\n");
+			sassc->flags &= ~MPSSAS_IN_DISCOVERY;
+			mpssas_discovery_end(sassc);
+		}
+		break;
+	}
+	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+	{
+		Mpi2EventDataSasEnclDevStatusChange_t *data;
+		data = (Mpi2EventDataSasEnclDevStatusChange_t *)
+		    fw_event->event_data;
+		mps_mapping_enclosure_dev_status_change_event(sc,
+		    fw_event->event_data);
+		break;
+	}
+	case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+	{
+		Mpi2EventIrConfigElement_t *element;
+		int i;
+		u8 foreign_config;
+		Mpi2EventDataIrConfigChangeList_t *event_data;
+		struct mpssas_target *targ;
+		unsigned int id;
+
+		event_data = fw_event->event_data;
+		foreign_config = (le32toh(event_data->Flags) &
+		    MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
+
+		element =
+		    (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+		id = mps_mapping_get_raid_id_from_handle
+		    (sc, element->VolDevHandle);
+
+		mps_mapping_ir_config_change_event(sc, event_data);
+
+		for (i = 0; i < event_data->NumElements; i++, element++) {
+			switch (element->ReasonCode) {
+			case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
+			case MPI2_EVENT_IR_CHANGE_RC_ADDED:
+				if (!foreign_config) {
+					if (mpssas_volume_add(sc, element)) {
+						kprintf("%s: failed to add RAID "
+						    "volume with handle 0x%x\n",
+						    __func__, le16toh(element->
+						    VolDevHandle));
+					}
+				}
+				break;
+			case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
+			case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
+				/*
+				 * Rescan after volume is deleted or removed.
+				 */
+				if (!foreign_config) {
+					if (id == MPS_MAP_BAD_ID) {
+						kprintf("%s: could not get ID "
+						    "for volume with handle "
+						    "0x%04x\n", __func__,
+						    element->VolDevHandle);
+						break;
+					}
+
+					targ = &sassc->targets[id];
+					targ->handle = 0x0;
+					targ->encl_slot = 0x0;
+					targ->encl_handle = 0x0;
+					targ->exp_dev_handle = 0x0;
+					targ->phy_num = 0x0;
+					targ->linkrate = 0x0;
+					mpssas_rescan_target(sc, targ);
+					kprintf("RAID target id 0x%x removed\n",
+					    targ->tid);
+				}
+				break;
+			case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
+				/*
+				 * Phys Disk of a volume has been created.  Hide
+				 * it from the OS.
+				 */
+				mpssas_prepare_remove(sassc, element->
+				    PhysDiskDevHandle);
+				break;
+			case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
+				/*
+				 * Phys Disk of a volume has been deleted.
+				 * Expose it to the OS.
+				 */
+				if (mpssas_add_device(sc,
+				    element->PhysDiskDevHandle, 0)){
+					kprintf("%s: failed to add device with "
+					    "handle 0x%x\n", __func__,
+					    element->PhysDiskDevHandle);
+					mpssas_prepare_remove(sassc, element->
+					    PhysDiskDevHandle);
+				}
+				break;
+			}
+		}
+		/*
+		 * refcount was incremented for this event in
+		 * mpssas_evt_handler.  Decrement it here because the event has
+		 * been processed.
+		 */
+		mpssas_startup_decrement(sassc);
+		break;
+	}
+	case MPI2_EVENT_IR_VOLUME:
+	{
+		Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+
+		/*
+		 * Informational only.
+		 */
+		mps_dprint(sc, MPS_INFO, "Received IR Volume event:\n");
+		switch (event_data->ReasonCode) {
+		case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
+			mps_dprint(sc, MPS_INFO, "   Volume Settings "
+			    "changed from 0x%x to 0x%x for Volome with "
+			    "handle 0x%x", (u_int)event_data->PreviousValue,
+			    (u_int)event_data->NewValue,
+			    event_data->VolDevHandle);
+			break;
+		case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
+			mps_dprint(sc, MPS_INFO, "   Volume Status "
+			    "changed from 0x%x to 0x%x for Volome with "
+			    "handle 0x%x", (u_int)event_data->PreviousValue,
+			    (u_int)event_data->NewValue,
+			    event_data->VolDevHandle);
+			break;
+		case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
+			mps_dprint(sc, MPS_INFO, "   Volume State "
+			    "changed from 0x%x to 0x%x for Volome with "
+			    "handle 0x%x", (u_int)event_data->PreviousValue,
+			    (u_int)event_data->NewValue,
+			    event_data->VolDevHandle);
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	case MPI2_EVENT_IR_PHYSICAL_DISK:
+	{
+		Mpi2EventDataIrPhysicalDisk_t *event_data =
+		    fw_event->event_data;
+
+		/*
+		 * Informational only.
+		 */
+		mps_dprint(sc, MPS_INFO, "Received IR Phys Disk event:\n");
+		switch (event_data->ReasonCode) {
+		case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
+			mps_dprint(sc, MPS_INFO, "   Phys Disk Settings "
+			    "changed from 0x%x to 0x%x for Phys Disk Number "
+			    "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
+			    "%d", (u_int)event_data->PreviousValue,
+			    (u_int)event_data->NewValue, event_data->PhysDiskNum,
+			    event_data->PhysDiskDevHandle,
+			    event_data->EnclosureHandle, event_data->Slot);
+			break;
+		case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
+			mps_dprint(sc, MPS_INFO, "   Phys Disk Status changed "
+			    "from 0x%x to 0x%x for Phys Disk Number %d and "
+			    "handle 0x%x at Enclosure handle 0x%x, Slot %d",
+			    (u_int)event_data->PreviousValue, (u_int)event_data->NewValue,
+			    event_data->PhysDiskNum,
+			    event_data->PhysDiskDevHandle,
+			    event_data->EnclosureHandle, event_data->Slot);
+			break;
+		case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
+			mps_dprint(sc, MPS_INFO, "   Phys Disk State changed "
+			    "from 0x%x to 0x%x for Phys Disk Number %d and "
+			    "handle 0x%x at Enclosure handle 0x%x, Slot %d",
+			    (u_int)event_data->PreviousValue, (u_int)event_data->NewValue,
+			    event_data->PhysDiskNum,
+			    event_data->PhysDiskDevHandle,
+			    event_data->EnclosureHandle, event_data->Slot);
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	case MPI2_EVENT_IR_OPERATION_STATUS:
+	{
+		Mpi2EventDataIrOperationStatus_t *event_data =
+		    fw_event->event_data;
+
+		/*
+		 * Informational only.
+		 */
+		mps_dprint(sc, MPS_INFO, "Received IR Op Status event:\n");
+		mps_dprint(sc, MPS_INFO, "   RAID Operation of %d is %d "
+		    "percent complete for Volume with handle 0x%x",
+		    event_data->RAIDOperation, event_data->PercentComplete,
+		    event_data->VolDevHandle);
+		break;
+	}
+	case MPI2_EVENT_LOG_ENTRY_ADDED:
+	{
+		pMpi2EventDataLogEntryAdded_t	logEntry;
+		uint16_t			logQualifier;
+		uint8_t				logCode;
+
+		logEntry = (pMpi2EventDataLogEntryAdded_t)fw_event->event_data;
+		logQualifier = logEntry->LogEntryQualifier;
+
+		if (logQualifier == MPI2_WD_LOG_ENTRY) {
+			logCode = logEntry->LogData[0];
+
+			switch (logCode) {
+			case MPI2_WD_SSD_THROTTLING:
+				kprintf("WarpDrive Warning: IO Throttling has "
+				    "occurred in the WarpDrive subsystem. "
+				    "Check WarpDrive documentation for "
+				    "additional details\n");
+				break;
+			case MPI2_WD_DRIVE_LIFE_WARN:
+				kprintf("WarpDrive Warning: Program/Erase "
+				    "Cycles for the WarpDrive subsystem in "
+				    "degraded range. Check WarpDrive "
+				    "documentation for additional details\n");
+				break;
+			case MPI2_WD_DRIVE_LIFE_DEAD:
+				kprintf("WarpDrive Fatal Error: There are no "
+				    "Program/Erase Cycles for the WarpDrive "
+				    "subsystem. The storage device will be in "
+				    "read-only mode. Check WarpDrive "
+				    "documentation for additional details\n");
+				break;
+			case MPI2_WD_RAIL_MON_FAIL:
+				kprintf("WarpDrive Fatal Error: The Backup Rail "
+				    "Monitor has failed on the WarpDrive "
+				    "subsystem. Check WarpDrive documentation "
+				    "for additional details\n");
+				break;
+			default:
+				break;
+			}
+		}
+		break;
+	}
+	case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+	case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+	default:
+		mps_dprint(sc, MPS_TRACE,"Unhandled event 0x%0X\n",
+		    fw_event->event);
+		break;
+
+	}
+	mpssas_fw_event_free(sc, fw_event);
+}
+
+void
+mpssas_firmware_event_work(void *arg, int pending)
+{
+	struct mps_fw_event_work *fw_event;
+	struct mps_softc *sc;
+
+	sc = (struct mps_softc *)arg;
+	mps_lock(sc);
+	while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
+		TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
+		mpssas_fw_work(sc, fw_event);
+	}
+	mps_unlock(sc);
+}
+
+static int
+mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
+	char devstring[80];
+	struct mpssas_softc *sassc;
+	struct mpssas_target *targ;
+	Mpi2ConfigReply_t mpi_reply;
+	Mpi2SasDevicePage0_t config_page;
+	uint64_t sas_address, sata_sas_address;
+	uint64_t parent_sas_address = 0;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	u32 device_info, parent_devinfo = 0;
+	unsigned int id;
+	int ret;
+	int error = 0;
+
+	sassc = sc->sassc;
+	mpssas_startup_increment(sassc);
+	if ((mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page,
+	     MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+		kprintf("%s: error reading SAS device page0\n", __func__);
+		error = ENXIO;
+		goto out;
+	}
+
+	device_info = le32toh(config_page.DeviceInfo);
+
+	if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
+	 && (config_page.ParentDevHandle != 0)) {
+		Mpi2ConfigReply_t tmp_mpi_reply;
+		Mpi2SasDevicePage0_t parent_config_page;
+
+		if ((mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply,
+		     &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+		     le16toh(config_page.ParentDevHandle)))) {
+			kprintf("%s: error reading SAS device %#x page0\n",
+			       __func__, le16toh(config_page.ParentDevHandle));
+		} else {
+			parent_sas_address = parent_config_page.SASAddress.High;
+			parent_sas_address = (parent_sas_address << 32) |
+				parent_config_page.SASAddress.Low;
+			parent_devinfo = le32toh(parent_config_page.DeviceInfo);
+		}
+	}
+	/* TODO Check proper endianess */
+	sas_address = config_page.SASAddress.High;
+	sas_address = (sas_address << 32) |
+	    config_page.SASAddress.Low;
+
+	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
+		    == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
+		if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
+			ret = mpssas_get_sas_address_for_sata_disk(sc,
+			    &sata_sas_address, handle, device_info);
+			if (!ret)
+				id = mps_mapping_get_sas_id(sc,
+				    sata_sas_address, handle);
+			else
+				id = mps_mapping_get_sas_id(sc,
+				    sas_address, handle);
+		} else
+			id = mps_mapping_get_sas_id(sc, sas_address,
+			    handle);
+	} else
+		id = mps_mapping_get_sas_id(sc, sas_address, handle);
+
+	if (id == MPS_MAP_BAD_ID) {
+		kprintf("failure at %s:%d/%s()! Could not get ID for device "
+		    "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
+		    handle);
+		error = ENXIO;
+		goto out;
+	}
+	mps_vprintf(sc, "SAS Address from SAS device page0 = %jx\n",
+	    sas_address);
+	targ = &sassc->targets[id];
+	targ->devinfo = device_info;
+	targ->devname = le32toh(config_page.DeviceName.High);
+	targ->devname = (targ->devname << 32) |
+	    le32toh(config_page.DeviceName.Low);
+	targ->encl_handle = le16toh(config_page.EnclosureHandle);
+	targ->encl_slot = le16toh(config_page.Slot);
+	targ->handle = handle;
+	targ->parent_handle = le16toh(config_page.ParentDevHandle);
+	targ->sasaddr = mps_to_u64(&config_page.SASAddress);
+	targ->parent_sasaddr = le64toh(parent_sas_address);
+	targ->parent_devinfo = parent_devinfo;
+	targ->tid = id;
+	targ->linkrate = (linkrate>>4);
+	targ->flags = 0;
+	TAILQ_INIT(&targ->commands);
+	TAILQ_INIT(&targ->timedout_commands);
+	SLIST_INIT(&targ->luns);
+	mps_describe_devinfo(targ->devinfo, devstring, 80);
+	mps_vprintf(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);
+	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
+		mpssas_rescan_target(sc, targ);
+	mps_vprintf(sc, "Target id 0x%x added\n", targ->tid);
+out:
+	mpssas_startup_decrement(sassc);
+	return (error);
+
+}
+
+int
+mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
+    u64 *sas_address, u16 handle, u32 device_info)
+{
+	Mpi2SataPassthroughReply_t mpi_reply;
+	int i, rc, try_count;
+	u32 *bufferptr;
+	union _sata_sas_address hash_address;
+	struct _ata_identify_device_data ata_identify;
+	u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN];
+	u32 ioc_status;
+	u8 sas_status;
+
+	memset(&ata_identify, 0, sizeof(ata_identify));
+	try_count = 0;
+	do {
+		rc = mpssas_get_sata_identify(sc, handle, &mpi_reply,
+		    (char *)&ata_identify, sizeof(ata_identify), device_info);
+		try_count++;
+		ioc_status = le16toh(mpi_reply.IOCStatus)
+		    & MPI2_IOCSTATUS_MASK;
+		sas_status = mpi_reply.SASStatus;
+	} while ((rc == -EAGAIN || ioc_status || sas_status) &&
+	    (try_count < 5));
+
+	if (rc == 0 && !ioc_status && !sas_status) {
+		mps_dprint(sc, MPS_INFO, "%s: got SATA identify successfully "
+			   "for handle = 0x%x with try_count = %d\n",
+			   __func__, handle, try_count);
+	} else {
+		mps_dprint(sc, MPS_INFO, "%s: handle = 0x%x failed\n",
+			   __func__, handle);
+		return -1;
+	}
+	/* Copy & byteswap the 40 byte model number to a buffer */
+	for (i = 0; i < MPT2SAS_MN_LEN; i += 2) {
+		buffer[i] = ((u8 *)ata_identify.model_number)[i + 1];
+		buffer[i + 1] = ((u8 *)ata_identify.model_number)[i];
+	}
+	/* Copy & byteswap the 20 byte serial number to a buffer */
+	for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
+		buffer[MPT2SAS_MN_LEN + i] =
+			((u8 *)ata_identify.serial_number)[i + 1];
+		buffer[MPT2SAS_MN_LEN + i + 1] =
+			((u8 *)ata_identify.serial_number)[i];
+	}
+	bufferptr = (u32 *)buffer;
+	/* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
+	 * so loop through the first 56 bytes (7*8),
+	 * and then add in the last dword.
+	 */
+	hash_address.word.low  = 0;
+	hash_address.word.high = 0;
+	for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) {
+		hash_address.word.low += *bufferptr;
+		bufferptr++;
+		hash_address.word.high += *bufferptr;
+		bufferptr++;
+	}
+	/* Add the last dword */
+	hash_address.word.low += *bufferptr;
+	/* Make sure the hash doesn't start with 5, because it could clash
+	 * with a SAS address. Change 5 to a D.
+	 */
+	if ((hash_address.word.high & 0x000000F0) == (0x00000050))
+		hash_address.word.high |= 0x00000080;
+	*sas_address = (u64)hash_address.wwid[0] << 56 |
+	    (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 |
+	    (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
+	    (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] <<  8 |
+	    (u64)hash_address.wwid[7];
+	return 0;
+}
+
+static int
+mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
+    Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
+{
+	Mpi2SataPassthroughRequest_t *mpi_request;
+	Mpi2SataPassthroughReply_t *reply;
+	struct mps_command *cm;
+	char *buffer;
+	int error = 0;
+
+	buffer = kmalloc( sz, M_MPT2, M_NOWAIT | M_ZERO);
+	if (!buffer)
+		return ENOMEM;
+
+	if ((cm = mps_alloc_command(sc)) == NULL)
+		return (EBUSY);
+	mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
+	bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
+	mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
+	mpi_request->VF_ID = 0;
+	mpi_request->DevHandle = htole16(handle);
+	mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
+	    MPI2_SATA_PT_REQ_PT_FLAGS_READ);
+	mpi_request->DataLength = htole32(sz);
+	mpi_request->CommandFIS[0] = 0x27;
+	mpi_request->CommandFIS[1] = 0x80;
+	mpi_request->CommandFIS[2] =  (devinfo &
+	    MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
+	cm->cm_sge = &mpi_request->SGL;
+	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_data = buffer;
+	cm->cm_length = htole32(sz);
+	error = mps_request_polled(sc, cm);
+	reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
+	if (error || (reply == NULL)) {
+		/* FIXME */
+		/* If the poll returns error then we need to do diag reset */
+		kprintf("%s: poll for page completed with error %d",
+		    __func__, error);
+		error = ENXIO;
+		goto out;
+	}
+	bcopy(buffer, id_buffer, sz);
+	bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
+	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
+	    MPI2_IOCSTATUS_SUCCESS) {
+		kprintf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
+		    __func__, reply->IOCStatus);
+		error = ENXIO;
+		goto out;
+	}
+out:
+	mps_free_command(sc, cm);
+	kfree(buffer, M_MPT2);
+	return (error);
+}
+
+static int
+mpssas_volume_add(struct mps_softc *sc, Mpi2EventIrConfigElement_t *element)
+{
+	struct mpssas_softc *sassc;
+	struct mpssas_target *targ;
+	u64 wwid;
+	u16 handle = le16toh(element->VolDevHandle);
+	unsigned int id;
+	int error = 0;
+
+	sassc = sc->sassc;
+	mpssas_startup_increment(sassc);
+	mps_config_get_volume_wwid(sc, handle, &wwid);
+	if (!wwid) {
+		kprintf("%s: invalid WWID; cannot add volume to mapping table\n",
+		    __func__);
+		error = ENXIO;
+		goto out;
+	}
+
+	id = mps_mapping_get_raid_id(sc, wwid, handle);
+	if (id == MPS_MAP_BAD_ID) {
+		kprintf("%s: could not get ID for volume with handle 0x%04x and "
+		    "WWID 0x%016llx\n", __func__, handle,
+		    (unsigned long long)wwid);
+		error = ENXIO;
+		goto out;
+	}
+
+	targ = &sassc->targets[id];
+	targ->tid = id;
+	targ->handle = handle;
+	targ->devname = wwid;
+	TAILQ_INIT(&targ->commands);
+	TAILQ_INIT(&targ->timedout_commands);
+	SLIST_INIT(&targ->luns);
+	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
+		mpssas_rescan_target(sc, targ);
+	mps_dprint(sc, MPS_INFO, "RAID target id %d added (WWID = 0x%jx)\n",
+	    targ->tid, wwid);
+out:
+	mpssas_startup_decrement(sassc);
+	return (error);
+}
+
+/**
+ * mpssas_ir_shutdown - IR shutdown notification
+ * @sc: per adapter object
+ *
+ * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
+ * the host system is shutting down.
+ *
+ * Return nothing.
+ */
+void
+mpssas_ir_shutdown(struct mps_softc *sc)
+{
+	u16 volume_mapping_flags;
+	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
+	struct dev_mapping_table *mt_entry;
+	u32 start_idx, end_idx;
+	unsigned int id, found_volume = 0;
+	struct mps_command *cm;
+	Mpi2RaidActionRequest_t	*action;
+
+	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+	/* is IR firmware build loaded? */
+	if (!sc->ir_firmware)
+		return;
+
+	/* are there any volumes?  Look at IR target IDs. */
+	// TODO-later, this should be looked up in the RAID config structure
+	// when it is implemented.
+	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
+	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
+		start_idx = 0;
+		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
+			start_idx = 1;
+	} else
+		start_idx = sc->max_devices - sc->max_volumes;
+	end_idx = start_idx + sc->max_volumes - 1;
+
+	for (id = start_idx; id < end_idx; id++) {
+		mt_entry = &sc->mapping_table[id];
+		if ((mt_entry->physical_id != 0) &&
+		    (mt_entry->missing_count == 0)) {
+			found_volume = 1;
+			break;
+		}
+	}
+
+	if (!found_volume)
+		return;
+
+	if ((cm = mps_alloc_command(sc)) == NULL) {
+		kprintf("%s: command alloc failed\n", __func__);
+		return;
+	}
+
+	action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
+	action->Function = MPI2_FUNCTION_RAID_ACTION;
+	action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	mps_request_polled(sc, cm);
+
+	/*
+	 * Don't check for reply, just leave.
+	 */
+	if (cm)
+		mps_free_command(sc, cm);
+}
diff --git a/sys/dev/raid/mps/mps_table.c b/sys/dev/raid/mps/mps_table.c
new file mode 100644
index 0000000..c2344d7
--- /dev/null
+++ b/sys/dev/raid/mps/mps_table.c
@@ -0,0 +1,500 @@
+/*-
+ * 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: src/sys/dev/mps/mps_table.c,v 1.2 2012/01/26 18:17:21 ken Exp $
+ */
+
+/* Debugging tables for MPT2 */
+
+/* TODO Move headers to mpsvar */
+#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/eventhandler.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+
+#include <sys/rman.h>
+
+#include <machine/inttypes.h>
+
+#include <bus/cam/scsi/scsi_all.h>
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+#include <dev/raid/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)
+{
+	ksnprintf(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",
+	    (u_int)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_dprint_field(sc, MPS_EVENT, "EventContext: 0x%x\n",
+	    (u_int)event->EventContext);
+}
+
+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", (int)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",
+		    (int)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_dprint_field(sc, MPS_EVENT, "PhyBits: 0x%x\n",
+		    (u_int)data->PhyBits);
+		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), (u_int)buf->PhyInfo);
+	mps_dprint_field(sc, MPS_INFO, "AttachedDeviceInfo: %b,%s\n",
+	    (int)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_dprint_field(sc, MPS_INFO, "AttachedPhyInfo: 0x%x\n",
+	    (u_int)buf->AttachedPhyInfo);
+	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
+	    mps_describe_table(mps_phyinfo_reason_names,
+	    buf->AttachedPhyInfo & 0xf), (u_int)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), (u_int)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), (u_int)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];
+	kprintf("SGL for command %p\n", cm);
+
+	while (frame != NULL) {
+		flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT;
+		kprintf("seg%d flags=0x%x len=0x%x addr=0x%jx\n", i, flags,
+		    (u_int)(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;
+			kprintf("chain flags=0x%x len=0x%x Offset=0x%x "
+			    "Address=0x%x\n", sgc->Flags, sgc->Length,
+			    sgc->NextChainOffset, (u_int)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 --git a/sys/dev/raid/mps/mps_table.h b/sys/dev/raid/mps/mps_table.h
new file mode 100644
index 0000000..9c9f78c
--- /dev/null
+++ b/sys/dev/raid/mps/mps_table.h
@@ -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: src/sys/dev/mps/mps_table.h,v 1.1 2010/09/10 15:03:56 ken Exp $
+ */
+
+#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 --git a/sys/dev/raid/mps/mps_user.c b/sys/dev/raid/mps/mps_user.c
new file mode 100644
index 0000000..76ba6d9
--- /dev/null
+++ b/sys/dev/raid/mps/mps_user.c
@@ -0,0 +1,2399 @@
+/*-
+ * 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
+ */
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mps_user.c,v 1.10 2012/01/26 18:17:21 ken Exp $
+ */
+
+#include "opt_compat.h"
+
+/* TODO Move headers to mpsvar */
+#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/eventhandler.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/queue.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
+
+#include <sys/rman.h>
+#include <sys/device.h>
+
+#include <bus/cam/cam.h>
+#include <bus/cam/scsi/scsi_all.h>
+
+#include <dev/raid/mps/mpi/mpi2_type.h>
+#include <dev/raid/mps/mpi/mpi2.h>
+#include <dev/raid/mps/mpi/mpi2_ioc.h>
+#include <dev/raid/mps/mpi/mpi2_cnfg.h>
+#include <dev/raid/mps/mpi/mpi2_init.h>
+#include <dev/raid/mps/mpi/mpi2_tool.h>
+#include <dev/raid/mps/mps_ioctl.h>
+#include <dev/raid/mps/mpsvar.h>
+#include <dev/raid/mps/mps_table.h>
+#include <dev/raid/mps/mps_sas.h>
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcireg.h>
+
+static d_open_t		mps_open;
+static d_close_t	mps_close;
+static d_ioctl_t	mps_ioctl_devsw;
+
+static struct dev_ops mps_ops = {
+	{ "mps", 0, 0 },
+	.d_open =	mps_open,
+	.d_close =	mps_close,
+	.d_ioctl =	mps_ioctl_devsw,
+};
+
+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 int mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data);
+static void mps_user_get_adapter_data(struct mps_softc *sc,
+    mps_adapter_data_t *data);
+static void mps_user_read_pci_info(struct mps_softc *sc,
+    mps_pci_info_t *data);
+static uint8_t mps_get_fw_diag_buffer_number(struct mps_softc *sc,
+    uint32_t unique_id);
+static int mps_post_fw_diag_buffer(struct mps_softc *sc,
+    mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
+static int mps_release_fw_diag_buffer(struct mps_softc *sc,
+    mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
+    uint32_t diag_type);
+static int mps_diag_register(struct mps_softc *sc,
+    mps_fw_diag_register_t *diag_register, uint32_t *return_code);
+static int mps_diag_unregister(struct mps_softc *sc,
+    mps_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
+static int mps_diag_query(struct mps_softc *sc, mps_fw_diag_query_t *diag_query,
+    uint32_t *return_code);
+static int mps_diag_read_buffer(struct mps_softc *sc,
+    mps_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
+    uint32_t *return_code);
+static int mps_diag_release(struct mps_softc *sc,
+    mps_fw_diag_release_t *diag_release, uint32_t *return_code);
+static int mps_do_diag_action(struct mps_softc *sc, uint32_t action,
+    uint8_t *diag_action, uint32_t length, uint32_t *return_code);
+static int mps_user_diag_action(struct mps_softc *sc, mps_diag_action_t *data);
+static void mps_user_event_query(struct mps_softc *sc, mps_event_query_t *data);
+static void mps_user_event_enable(struct mps_softc *sc,
+    mps_event_enable_t *data);
+static int mps_user_event_report(struct mps_softc *sc,
+    mps_event_report_t *data);
+static int mps_user_reg_access(struct mps_softc *sc, mps_reg_access_t *data);
+static int mps_user_btdh(struct mps_softc *sc, mps_btdh_mapping_t *data);
+
+static MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls");
+
+/* 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)
+
+int
+mps_attach_user(struct mps_softc *sc)
+{
+	int unit;
+
+	unit = device_get_unit(sc->mps_dev);
+	sc->mps_cdev = make_dev(&mps_ops, 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 dev_open_args *ap)
+{
+
+	return (0);
+}
+
+static int
+mps_close(struct dev_close_args *ap)
+{
+
+	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 = kmalloc(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;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+
+	mps_lock(sc);
+	err = mps_wait_command(sc, cm, 0);
+
+	if (err) {
+		mps_printf(sc, "%s: invalid request: error %d\n",
+		    __func__, err);
+		goto Ret;
+	}
+
+	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)
+		kfree(buf, M_MPSUSER);
+	return (err);
+}
+
+static int
+mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
+{
+	MPI2_REQUEST_HEADER	*hdr, tmphdr;
+	MPI2_DEFAULT_REPLY	*rpl;
+	struct mps_command	*cm = NULL;
+	int			err = 0, dir = 0, sz;
+	uint8_t			function = 0;
+	u_int			sense_len;
+
+	/*
+	 * Only allow one passthru command at a time.  Use the MPS_FLAGS_BUSY
+	 * bit to denote that a passthru is being processed.
+	 */
+	mps_lock(sc);
+	if (sc->mps_flags & MPS_FLAGS_BUSY) {
+		mps_dprint(sc, MPS_INFO, "%s: Only one passthru command "
+		    "allowed at a single time.", __func__);
+		mps_unlock(sc);
+		return (EBUSY);
+	}
+	sc->mps_flags |= MPS_FLAGS_BUSY;
+	mps_unlock(sc);
+
+	/*
+	 * Do some validation on data direction.  Valid cases are:
+	 *    1) DataSize is 0 and direction is NONE
+	 *    2) DataSize is non-zero and one of:
+	 *        a) direction is READ or
+	 *        b) direction is WRITE or
+	 *        c) direction is BOTH and DataOutSize is non-zero
+	 * If valid and the direction is BOTH, change the direction to READ.
+	 * if valid and the direction is not BOTH, make sure DataOutSize is 0.
+	 */
+	if (((data->DataSize == 0) &&
+	    (data->DataDirection == MPS_PASS_THRU_DIRECTION_NONE)) ||
+	    ((data->DataSize != 0) &&
+	    ((data->DataDirection == MPS_PASS_THRU_DIRECTION_READ) ||
+	    (data->DataDirection == MPS_PASS_THRU_DIRECTION_WRITE) ||
+	    ((data->DataDirection == MPS_PASS_THRU_DIRECTION_BOTH) &&
+	    (data->DataOutSize != 0))))) {
+		if (data->DataDirection == MPS_PASS_THRU_DIRECTION_BOTH)
+			data->DataDirection = MPS_PASS_THRU_DIRECTION_READ;
+		else
+			data->DataOutSize = 0;
+	} else
+		return (EINVAL);
+
+	mps_dprint(sc, MPS_INFO, "%s: req 0x%jx %d  rpl 0x%jx %d "
+	    "data in 0x%jx %d data out 0x%jx %d data dir %d\n", __func__,
+	    data->PtrRequest, data->RequestSize, data->PtrReply,
+	    data->ReplySize, data->PtrData, data->DataSize,
+	    data->PtrDataOut, data->DataOutSize, data->DataDirection);
+
+	/*
+	 * copy in the header so we know what we're dealing with before we
+	 * commit to allocating a command for it.
+	 */
+	err = copyin(PTRIN(data->PtrRequest), &tmphdr, data->RequestSize);
+	if (err != 0)
+		goto RetFreeUnlocked;
+
+	if (data->RequestSize > (int)sc->facts->IOCRequestFrameSize * 4) {
+		err = EINVAL;
+		goto RetFreeUnlocked;
+	}
+
+	function = tmphdr.Function;
+	mps_dprint(sc, MPS_INFO, "%s: Function %02X MsgFlags %02X\n", __func__,
+	    function, tmphdr.MsgFlags);
+
+	/*
+	 * Handle a passthru TM request.
+	 */
+	if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
+		MPI2_SCSI_TASK_MANAGE_REQUEST	*task;
+
+		mps_lock(sc);
+		cm = mpssas_alloc_tm(sc);
+		if (cm == NULL) {
+			err = EINVAL;
+			goto Ret;
+		}
+
+		/* Copy the header in.  Only a small fixup is needed. */
+		task = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+		bcopy(&tmphdr, task, data->RequestSize);
+		task->TaskMID = cm->cm_desc.Default.SMID;
+
+		cm->cm_data = NULL;
+		cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+		cm->cm_complete = NULL;
+		cm->cm_complete_data = NULL;
+
+		err = mps_wait_command(sc, cm, 0);
+
+		if (err != 0) {
+			err = EIO;
+			mps_dprint(sc, MPS_FAULT, "%s: task management failed",
+			    __func__);
+		}
+		/*
+		 * Copy the reply data and sense data to user space.
+		 */
+		if (cm->cm_reply != NULL) {
+			rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
+			sz = rpl->MsgLength * 4;
+
+			if (sz > data->ReplySize) {
+				mps_printf(sc, "%s: reply buffer too small: %d, "
+				    "required: %d\n", __func__, data->ReplySize, sz);
+				err = EINVAL;
+			} else {
+				mps_unlock(sc);
+				copyout(cm->cm_reply, PTRIN(data->PtrReply),
+				    data->ReplySize);
+				mps_lock(sc);
+			}
+		}
+		mpssas_free_tm(sc, cm);
+		goto Ret;
+	}
+
+	mps_lock(sc);
+	cm = mps_alloc_command(sc);
+
+	if (cm == NULL) {
+		mps_printf(sc, "%s: no mps requests\n", __func__);
+		err = ENOMEM;
+		goto Ret;
+	}
+	mps_unlock(sc);
+
+	hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
+	bcopy(&tmphdr, hdr, data->RequestSize);
+
+	/*
+	 * Do some checking to make sure the IOCTL request contains a valid
+	 * request.  Then set the SGL info.
+	 */
+	mpi_init_sge(cm, hdr, (void *)((uint8_t *)hdr + data->RequestSize));
+
+	/*
+	 * Set up for read, write or both.  From check above, DataOutSize will
+	 * be 0 if direction is READ or WRITE, but it will have some non-zero
+	 * value if the direction is BOTH.  So, just use the biggest size to get
+	 * the cm_data buffer size.  If direction is BOTH, 2 SGLs need to be set
+	 * up; the first is for the request and the second will contain the
+	 * response data. cm_out_len needs to be set here and this will be used
+	 * when the SGLs are set up.
+	 */
+	cm->cm_data = NULL;
+	cm->cm_length = MAX(data->DataSize, data->DataOutSize);
+	cm->cm_out_len = data->DataOutSize;
+	cm->cm_flags = 0;
+	if (cm->cm_length != 0) {
+		cm->cm_data = kmalloc(cm->cm_length, M_MPSUSER, M_WAITOK |
+		    M_ZERO);
+		if (cm->cm_data == NULL) {
+			mps_dprint(sc, MPS_FAULT, "%s: alloc failed for IOCTL "
+			    "passthru length %d\n", __func__, cm->cm_length);
+		} else {
+			cm->cm_flags = MPS_CM_FLAGS_DATAIN;
+			if (data->DataOutSize) {
+				cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
+				err = copyin(PTRIN(data->PtrDataOut),
+				    cm->cm_data, data->DataOutSize);
+			} else if (data->DataDirection ==
+			    MPS_PASS_THRU_DIRECTION_WRITE) {
+				cm->cm_flags = MPS_CM_FLAGS_DATAOUT;
+				err = copyin(PTRIN(data->PtrData),
+				    cm->cm_data, data->DataSize);
+			}
+			if (err != 0)
+				mps_dprint(sc, MPS_FAULT, "%s: failed to copy "
+				    "IOCTL data from user space\n", __func__);
+		}
+	}
+	cm->cm_flags |= MPS_CM_FLAGS_SGE_SIMPLE;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+
+	/*
+	 * Set up Sense buffer and SGL offset for IO passthru.  SCSI IO request
+	 * uses SCSI IO descriptor.
+	 */
+	if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
+	    (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+		MPI2_SCSI_IO_REQUEST	*scsi_io_req;
+
+		scsi_io_req = (MPI2_SCSI_IO_REQUEST *)hdr;
+		/*
+		 * Put SGE for data and data_out buffer at the end of
+		 * scsi_io_request message header (64 bytes in total).
+		 * Following above SGEs, the residual space will be used by
+		 * sense data.
+		 */
+		scsi_io_req->SenseBufferLength = (uint8_t)(data->RequestSize -
+		    64);
+		scsi_io_req->SenseBufferLowAddress = cm->cm_sense_busaddr;
+
+		/*
+		 * Set SGLOffset0 value.  This is the number of dwords that SGL
+		 * is offset from the beginning of MPI2_SCSI_IO_REQUEST struct.
+		 */
+		scsi_io_req->SGLOffset0 = 24;
+
+		/*
+		 * Setup descriptor info.  RAID passthrough must use the
+		 * default request descriptor which is already set, so if this
+		 * is a SCSI IO request, change the descriptor to SCSI IO.
+		 * Also, if this is a SCSI IO request, handle the reply in the
+		 * mpssas_scsio_complete function.
+		 */
+		if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
+			cm->cm_desc.SCSIIO.RequestFlags =
+			    MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
+			cm->cm_desc.SCSIIO.DevHandle = scsi_io_req->DevHandle;
+
+			/*
+			 * Make sure the DevHandle is not 0 because this is a
+			 * likely error.
+			 */
+			if (scsi_io_req->DevHandle == 0) {
+				err = EINVAL;
+				goto RetFreeUnlocked;
+			}
+		}
+	}
+
+	mps_lock(sc);
+
+	err = mps_wait_command(sc, cm, 0);
+
+	if (err) {
+		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
+		    err);
+		mps_unlock(sc);
+		goto RetFreeUnlocked;
+	}
+
+	/*
+	 * Sync the DMA data, if any.  Then copy the data to user space.
+	 */
+	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 (cm->cm_flags & MPS_CM_FLAGS_DATAIN) {
+			mps_unlock(sc);
+			err = copyout(cm->cm_data,
+			    PTRIN(data->PtrData), data->DataSize);
+			mps_lock(sc);
+			if (err != 0)
+				mps_dprint(sc, MPS_FAULT, "%s: failed to copy "
+				    "IOCTL data to user space\n", __func__);
+		}
+	}
+
+	/*
+	 * Copy the reply data and sense data to user space.
+	 */
+	if (cm->cm_reply != NULL) {
+		rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
+		sz = rpl->MsgLength * 4;
+
+		if (sz > data->ReplySize) {
+			mps_printf(sc, "%s: reply buffer too small: %d, "
+			    "required: %d\n", __func__, data->ReplySize, sz);
+			err = EINVAL;
+		} else {
+			mps_unlock(sc);
+			copyout(cm->cm_reply, PTRIN(data->PtrReply),
+			    data->ReplySize);
+			mps_lock(sc);
+		}
+
+		if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
+		    (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+			if (((MPI2_SCSI_IO_REPLY *)rpl)->SCSIState &
+			    MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+				sense_len =
+				    MIN(((MPI2_SCSI_IO_REPLY *)rpl)->SenseCount,
+				    sizeof(struct scsi_sense_data));
+				mps_unlock(sc);
+				copyout(cm->cm_sense, cm->cm_req + 64, sense_len);
+				mps_lock(sc);
+			}
+		}
+	}
+	mps_unlock(sc);
+
+RetFreeUnlocked:
+	mps_lock(sc);
+
+	if (cm != NULL) {
+		if (cm->cm_data)
+			kfree(cm->cm_data, M_MPSUSER);
+		mps_free_command(sc, cm);
+	}
+Ret:
+	sc->mps_flags &= ~MPS_FLAGS_BUSY;
+	mps_unlock(sc);
+
+	return (err);
+}
+
+static void
+mps_user_get_adapter_data(struct mps_softc *sc, mps_adapter_data_t *data)
+{
+	Mpi2ConfigReply_t	mpi_reply;
+	Mpi2BiosPage3_t		config_page;
+
+	/*
+	 * Use the PCI interface functions to get the Bus, Device, and Function
+	 * information.
+	 */
+	data->PciInformation.u.bits.BusNumber = pci_get_bus(sc->mps_dev);
+	data->PciInformation.u.bits.DeviceNumber = pci_get_slot(sc->mps_dev);
+	data->PciInformation.u.bits.FunctionNumber =
+	    pci_get_function(sc->mps_dev);
+
+	/*
+	 * Get the FW version that should already be saved in IOC Facts.
+	 */
+	data->MpiFirmwareVersion = sc->facts->FWVersion.Word;
+
+	/*
+	 * General device info.
+	 */
+	data->AdapterType = MPSIOCTL_ADAPTER_TYPE_SAS2;
+	if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE)
+		data->AdapterType = MPSIOCTL_ADAPTER_TYPE_SAS2_SSS6200;
+	data->PCIDeviceHwId = pci_get_device(sc->mps_dev);
+	data->PCIDeviceHwRev = pci_read_config(sc->mps_dev, PCIR_REVID, 1);
+	data->SubSystemId = pci_get_subdevice(sc->mps_dev);
+	data->SubsystemVendorId = pci_get_subvendor(sc->mps_dev);
+
+	/*
+	 * Get the driver version.
+	 */
+	strcpy((char *)&data->DriverVersion[0], MPS_DRIVER_VERSION);
+
+	/*
+	 * Need to get BIOS Config Page 3 for the BIOS Version.
+	 */
+	data->BiosVersion = 0;
+	if (mps_config_get_bios_pg3(sc, &mpi_reply, &config_page))
+		kprintf("%s: Error while retrieving BIOS Version\n", __func__);
+	else
+		data->BiosVersion = config_page.BiosVersion;
+}
+
+static void
+mps_user_read_pci_info(struct mps_softc *sc, mps_pci_info_t *data)
+{
+	int	i;
+
+	/*
+	 * Use the PCI interface functions to get the Bus, Device, and Function
+	 * information.
+	 */
+	data->BusNumber = pci_get_bus(sc->mps_dev);
+	data->DeviceNumber = pci_get_slot(sc->mps_dev);
+	data->FunctionNumber = pci_get_function(sc->mps_dev);
+
+	/*
+	 * Now get the interrupt vector and the pci header.  The vector can
+	 * only be 0 right now.  The header is the first 256 bytes of config
+	 * space.
+	 */
+	data->InterruptVector = 0;
+	for (i = 0; i < sizeof (data->PciHeader); i++) {
+		data->PciHeader[i] = pci_read_config(sc->mps_dev, i, 1);
+	}
+}
+
+static uint8_t
+mps_get_fw_diag_buffer_number(struct mps_softc *sc, uint32_t unique_id)
+{
+	uint8_t	index;
+
+	for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
+		if (sc->fw_diag_buffer_list[index].unique_id == unique_id) {
+			return (index);
+		}
+	}
+
+	return (MPS_FW_DIAGNOSTIC_UID_NOT_FOUND);
+}
+
+static int
+mps_post_fw_diag_buffer(struct mps_softc *sc,
+    mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
+{
+	MPI2_DIAG_BUFFER_POST_REQUEST	*req;
+	MPI2_DIAG_BUFFER_POST_REPLY	*reply;
+	struct mps_command		*cm = NULL;
+	int				i, status;
+
+	/*
+	 * If buffer is not enabled, just leave.
+	 */
+	*return_code = MPS_FW_DIAG_ERROR_POST_FAILED;
+	if (!pBuffer->enabled) {
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Clear some flags initially.
+	 */
+	pBuffer->force_release = FALSE;
+	pBuffer->valid_data = FALSE;
+	pBuffer->owned_by_firmware = FALSE;
+
+	/*
+	 * Get a command.
+	 */
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "%s: no mps requests\n", __func__);
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Build the request for releasing the FW Diag Buffer and send it.
+	 */
+	req = (MPI2_DIAG_BUFFER_POST_REQUEST *)cm->cm_req;
+	req->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
+	req->BufferType = pBuffer->buffer_type;
+	req->ExtendedType = pBuffer->extended_type;
+	req->BufferLength = pBuffer->size;
+	for (i = 0; i < (sizeof(req->ProductSpecific) / 4); i++)
+		req->ProductSpecific[i] = pBuffer->product_specific[i];
+	mps_from_u64(sc->fw_diag_busaddr, &req->BufferAddress);
+	cm->cm_data = NULL;
+	cm->cm_length = 0;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_complete_data = NULL;
+
+	/*
+	 * Send command synchronously.
+	 */
+	status = mps_wait_command(sc, cm, 0);
+	if (status) {
+		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
+		    status);
+		status = MPS_DIAG_FAILURE;
+		goto done;
+	}
+
+	/*
+	 * Process POST reply.
+	 */
+	reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
+	if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
+		status = MPS_DIAG_FAILURE;
+		mps_dprint(sc, MPS_FAULT, "%s: post of FW  Diag Buffer failed "
+		    "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and "
+		    "TransferLength = 0x%x\n", __func__, reply->IOCStatus,
+		    (u_int)reply->IOCLogInfo, (u_int)reply->TransferLength);
+		goto done;
+	}
+
+	/*
+	 * Post was successful.
+	 */
+	pBuffer->valid_data = TRUE;
+	pBuffer->owned_by_firmware = TRUE;
+	*return_code = MPS_FW_DIAG_ERROR_SUCCESS;
+	status = MPS_DIAG_SUCCESS;
+
+done:
+	mps_free_command(sc, cm);
+	return (status);
+}
+
+static int
+mps_release_fw_diag_buffer(struct mps_softc *sc,
+    mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
+    uint32_t diag_type)
+{
+	MPI2_DIAG_RELEASE_REQUEST	*req;
+	MPI2_DIAG_RELEASE_REPLY		*reply;
+	struct mps_command		*cm = NULL;
+	int				status;
+
+	/*
+	 * If buffer is not enabled, just leave.
+	 */
+	*return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED;
+	if (!pBuffer->enabled) {
+		mps_dprint(sc, MPS_INFO, "%s: This buffer type is not supported "
+		    "by the IOC", __func__);
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Clear some flags initially.
+	 */
+	pBuffer->force_release = FALSE;
+	pBuffer->valid_data = FALSE;
+	pBuffer->owned_by_firmware = FALSE;
+
+	/*
+	 * Get a command.
+	 */
+	cm = mps_alloc_command(sc);
+	if (cm == NULL) {
+		mps_printf(sc, "%s: no mps requests\n", __func__);
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Build the request for releasing the FW Diag Buffer and send it.
+	 */
+	req = (MPI2_DIAG_RELEASE_REQUEST *)cm->cm_req;
+	req->Function = MPI2_FUNCTION_DIAG_RELEASE;
+	req->BufferType = pBuffer->buffer_type;
+	cm->cm_data = NULL;
+	cm->cm_length = 0;
+	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cm->cm_complete_data = NULL;
+
+	/*
+	 * Send command synchronously.
+	 */
+	status = mps_wait_command(sc, cm, 0);
+	if (status) {
+		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
+		    status);
+		status = MPS_DIAG_FAILURE;
+		goto done;
+	}
+
+	/*
+	 * Process RELEASE reply.
+	 */
+	reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
+	if ((reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) ||
+	    pBuffer->owned_by_firmware) {
+		status = MPS_DIAG_FAILURE;
+		mps_dprint(sc, MPS_FAULT, "%s: release of FW Diag Buffer "
+		    "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n",
+		    __func__, reply->IOCStatus, (u_int)reply->IOCLogInfo);
+		goto done;
+	}
+
+	/*
+	 * Release was successful.
+	 */
+	*return_code = MPS_FW_DIAG_ERROR_SUCCESS;
+	status = MPS_DIAG_SUCCESS;
+
+	/*
+	 * If this was for an UNREGISTER diag type command, clear the unique ID.
+	 */
+	if (diag_type == MPS_FW_DIAG_TYPE_UNREGISTER) {
+		pBuffer->unique_id = MPS_FW_DIAG_INVALID_UID;
+	}
+
+done:
+	return (status);
+}
+
+static int
+mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register,
+    uint32_t *return_code)
+{
+	mps_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				extended_type, buffer_type, i;
+	uint32_t			buffer_size;
+	uint32_t			unique_id;
+	int				status;
+
+	extended_type = diag_register->ExtendedType;
+	buffer_type = diag_register->BufferType;
+	buffer_size = diag_register->RequestedBufferSize;
+	unique_id = diag_register->UniqueId;
+
+	/*
+	 * Check for valid buffer type
+	 */
+	if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should not be found.  If it is, the ID is already in use.
+	 */
+	i = mps_get_fw_diag_buffer_number(sc, unique_id);
+	pBuffer = &sc->fw_diag_buffer_list[buffer_type];
+	if (i != MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * The buffer's unique ID should not be registered yet, and the given
+	 * unique ID cannot be 0.
+	 */
+	if ((pBuffer->unique_id != MPS_FW_DIAG_INVALID_UID) ||
+	    (unique_id == MPS_FW_DIAG_INVALID_UID)) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * If this buffer is already posted as immediate, just change owner.
+	 */
+	if (pBuffer->immediate && pBuffer->owned_by_firmware &&
+	    (pBuffer->unique_id == MPS_FW_DIAG_INVALID_UID)) {
+		pBuffer->immediate = FALSE;
+		pBuffer->unique_id = unique_id;
+		return (MPS_DIAG_SUCCESS);
+	}
+
+	/*
+	 * Post a new buffer after checking if it's enabled.  The DMA buffer
+	 * that is allocated will be contiguous (nsegments = 1).
+	 */
+	if (!pBuffer->enabled) {
+		*return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
+		return (MPS_DIAG_FAILURE);
+	}
+        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 */
+                                buffer_size,		/* maxsize */
+                                1,			/* nsegments */
+                                buffer_size,		/* maxsegsize */
+                                0,			/* flags */
+                                &sc->fw_diag_dmat)) {
+		device_printf(sc->mps_dev, "Cannot allocate FW diag buffer DMA "
+		    "tag\n");
+		return (ENOMEM);
+        }
+        if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
+	    BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
+		device_printf(sc->mps_dev, "Cannot allocate FW diag buffer "
+		    "memory\n");
+		return (ENOMEM);
+        }
+        bzero(sc->fw_diag_buffer, buffer_size);
+        bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map, sc->fw_diag_buffer,
+	    buffer_size, mps_memaddr_cb, &sc->fw_diag_busaddr, 0);
+	pBuffer->size = buffer_size;
+
+	/*
+	 * Copy the given info to the diag buffer and post the buffer.
+	 */
+	pBuffer->buffer_type = buffer_type;
+	pBuffer->immediate = FALSE;
+	if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
+		for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
+		    i++) {
+			pBuffer->product_specific[i] =
+			    diag_register->ProductSpecific[i];
+		}
+	}
+	pBuffer->extended_type = extended_type;
+	pBuffer->unique_id = unique_id;
+	status = mps_post_fw_diag_buffer(sc, pBuffer, return_code);
+
+	/*
+	 * In case there was a failure, free the DMA buffer.
+	 */
+	if (status == MPS_DIAG_FAILURE) {
+		if (sc->fw_diag_busaddr != 0)
+			bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
+		if (sc->fw_diag_buffer != NULL)
+			bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
+			    sc->fw_diag_map);
+		if (sc->fw_diag_dmat != NULL)
+			bus_dma_tag_destroy(sc->fw_diag_dmat);
+	}
+
+	return (status);
+}
+
+static int
+mps_diag_unregister(struct mps_softc *sc,
+    mps_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
+{
+	mps_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i;
+	uint32_t			unique_id;
+	int				status;
+
+	unique_id = diag_unregister->UniqueId;
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should be there.
+	 */
+	i = mps_get_fw_diag_buffer_number(sc, unique_id);
+	if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	pBuffer = &sc->fw_diag_buffer_list[i];
+
+	/*
+	 * Try to release the buffer from FW before freeing it.  If release
+	 * fails, don't free the DMA buffer in case FW tries to access it
+	 * later.  If buffer is not owned by firmware, can't release it.
+	 */
+	if (!pBuffer->owned_by_firmware) {
+		status = MPS_DIAG_SUCCESS;
+	} else {
+		status = mps_release_fw_diag_buffer(sc, pBuffer, return_code,
+		    MPS_FW_DIAG_TYPE_UNREGISTER);
+	}
+
+	/*
+	 * At this point, return the current status no matter what happens with
+	 * the DMA buffer.
+	 */
+	pBuffer->unique_id = MPS_FW_DIAG_INVALID_UID;
+	if (status == MPS_DIAG_SUCCESS) {
+		if (sc->fw_diag_busaddr != 0)
+			bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
+		if (sc->fw_diag_buffer != NULL)
+			bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
+			    sc->fw_diag_map);
+		if (sc->fw_diag_dmat != NULL)
+			bus_dma_tag_destroy(sc->fw_diag_dmat);
+	}
+
+	return (status);
+}
+
+static int
+mps_diag_query(struct mps_softc *sc, mps_fw_diag_query_t *diag_query,
+    uint32_t *return_code)
+{
+	mps_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i;
+	uint32_t			unique_id;
+
+	unique_id = diag_query->UniqueId;
+
+	/*
+	 * If ID is valid, query on ID.
+	 * If ID is invalid, query on buffer type.
+	 */
+	if (unique_id == MPS_FW_DIAG_INVALID_UID) {
+		i = diag_query->BufferType;
+		if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
+			*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+			return (MPS_DIAG_FAILURE);
+		}
+	} else {
+		i = mps_get_fw_diag_buffer_number(sc, unique_id);
+		if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+			*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+			return (MPS_DIAG_FAILURE);
+		}
+	}
+
+	/*
+	 * Fill query structure with the diag buffer info.
+	 */
+	pBuffer = &sc->fw_diag_buffer_list[i];
+	diag_query->BufferType = pBuffer->buffer_type;
+	diag_query->ExtendedType = pBuffer->extended_type;
+	if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
+		for (i = 0; i < (sizeof(diag_query->ProductSpecific) / 4);
+		    i++) {
+			diag_query->ProductSpecific[i] =
+			    pBuffer->product_specific[i];
+		}
+	}
+	diag_query->TotalBufferSize = pBuffer->size;
+	diag_query->DriverAddedBufferSize = 0;
+	diag_query->UniqueId = pBuffer->unique_id;
+	diag_query->ApplicationFlags = 0;
+	diag_query->DiagnosticFlags = 0;
+
+	/*
+	 * Set/Clear application flags
+	 */
+	if (pBuffer->immediate) {
+		diag_query->ApplicationFlags &= ~MPS_FW_DIAG_FLAG_APP_OWNED;
+	} else {
+		diag_query->ApplicationFlags |= MPS_FW_DIAG_FLAG_APP_OWNED;
+	}
+	if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
+		diag_query->ApplicationFlags |= MPS_FW_DIAG_FLAG_BUFFER_VALID;
+	} else {
+		diag_query->ApplicationFlags &= ~MPS_FW_DIAG_FLAG_BUFFER_VALID;
+	}
+	if (pBuffer->owned_by_firmware) {
+		diag_query->ApplicationFlags |=
+		    MPS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
+	} else {
+		diag_query->ApplicationFlags &=
+		    ~MPS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
+	}
+
+	return (MPS_DIAG_SUCCESS);
+}
+
+static int
+mps_diag_read_buffer(struct mps_softc *sc,
+    mps_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
+    uint32_t *return_code)
+{
+	mps_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i, *pData;
+	uint32_t			unique_id;
+	int				status;
+
+	unique_id = diag_read_buffer->UniqueId;
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should be there.
+	 */
+	i = mps_get_fw_diag_buffer_number(sc, unique_id);
+	if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	pBuffer = &sc->fw_diag_buffer_list[i];
+
+	/*
+	 * Make sure requested read is within limits
+	 */
+	if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
+	    pBuffer->size) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Copy the requested data from DMA to the diag_read_buffer.  The DMA
+	 * buffer that was allocated is one contiguous buffer.
+	 */
+	pData = (uint8_t *)(sc->fw_diag_buffer +
+	    diag_read_buffer->StartingOffset);
+	if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0)
+		return (MPS_DIAG_FAILURE);
+	diag_read_buffer->Status = 0;
+
+	/*
+	 * Set or clear the Force Release flag.
+	 */
+	if (pBuffer->force_release) {
+		diag_read_buffer->Flags |= MPS_FW_DIAG_FLAG_FORCE_RELEASE;
+	} else {
+		diag_read_buffer->Flags &= ~MPS_FW_DIAG_FLAG_FORCE_RELEASE;
+	}
+
+	/*
+	 * If buffer is to be reregistered, make sure it's not already owned by
+	 * firmware first.
+	 */
+	status = MPS_DIAG_SUCCESS;
+	if (!pBuffer->owned_by_firmware) {
+		if (diag_read_buffer->Flags & MPS_FW_DIAG_FLAG_REREGISTER) {
+			status = mps_post_fw_diag_buffer(sc, pBuffer,
+			    return_code);
+		}
+	}
+
+	return (status);
+}
+
+static int
+mps_diag_release(struct mps_softc *sc, mps_fw_diag_release_t *diag_release,
+    uint32_t *return_code)
+{
+	mps_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i;
+	uint32_t			unique_id;
+	int				status;
+
+	unique_id = diag_release->UniqueId;
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should be there.
+	 */
+	i = mps_get_fw_diag_buffer_number(sc, unique_id);
+	if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	pBuffer = &sc->fw_diag_buffer_list[i];
+
+	/*
+	 * If buffer is not owned by firmware, it's already been released.
+	 */
+	if (!pBuffer->owned_by_firmware) {
+		*return_code = MPS_FW_DIAG_ERROR_ALREADY_RELEASED;
+		return (MPS_DIAG_FAILURE);
+	}
+
+	/*
+	 * Release the buffer.
+	 */
+	status = mps_release_fw_diag_buffer(sc, pBuffer, return_code,
+	    MPS_FW_DIAG_TYPE_RELEASE);
+	return (status);
+}
+
+static int
+mps_do_diag_action(struct mps_softc *sc, uint32_t action, uint8_t *diag_action,
+    uint32_t length, uint32_t *return_code)
+{
+	mps_fw_diag_register_t		diag_register;
+	mps_fw_diag_unregister_t	diag_unregister;
+	mps_fw_diag_query_t		diag_query;
+	mps_diag_read_buffer_t		diag_read_buffer;
+	mps_fw_diag_release_t		diag_release;
+	int				status = MPS_DIAG_SUCCESS;
+	uint32_t			original_return_code;
+
+	original_return_code = *return_code;
+	*return_code = MPS_FW_DIAG_ERROR_SUCCESS;
+
+	switch (action) {
+		case MPS_FW_DIAG_TYPE_REGISTER:
+			if (!length) {
+				*return_code =
+				    MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = MPS_DIAG_FAILURE;
+				break;
+			}
+			if (copyin(diag_action, &diag_register,
+			    sizeof(diag_register)) != 0)
+				return (MPS_DIAG_FAILURE);
+			status = mps_diag_register(sc, &diag_register,
+			    return_code);
+			break;
+
+		case MPS_FW_DIAG_TYPE_UNREGISTER:
+			if (length < sizeof(diag_unregister)) {
+				*return_code =
+				    MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = MPS_DIAG_FAILURE;
+				break;
+			}
+			if (copyin(diag_action, &diag_unregister,
+			    sizeof(diag_unregister)) != 0)
+				return (MPS_DIAG_FAILURE);
+			status = mps_diag_unregister(sc, &diag_unregister,
+			    return_code);
+			break;
+
+		case MPS_FW_DIAG_TYPE_QUERY:
+			if (length < sizeof (diag_query)) {
+				*return_code =
+				    MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = MPS_DIAG_FAILURE;
+				break;
+			}
+			if (copyin(diag_action, &diag_query, sizeof(diag_query))
+			    != 0)
+				return (MPS_DIAG_FAILURE);
+			status = mps_diag_query(sc, &diag_query, return_code);
+			if (status == MPS_DIAG_SUCCESS)
+				if (copyout(&diag_query, diag_action,
+				    sizeof (diag_query)) != 0)
+					return (MPS_DIAG_FAILURE);
+			break;
+
+		case MPS_FW_DIAG_TYPE_READ_BUFFER:
+			if (copyin(diag_action, &diag_read_buffer,
+			    sizeof(diag_read_buffer)) != 0)
+				return (MPS_DIAG_FAILURE);
+			if (length < diag_read_buffer.BytesToRead) {
+				*return_code =
+				    MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = MPS_DIAG_FAILURE;
+				break;
+			}
+			status = mps_diag_read_buffer(sc, &diag_read_buffer,
+			    PTRIN(diag_read_buffer.PtrDataBuffer),
+			    return_code);
+			if (status == MPS_DIAG_SUCCESS) {
+				if (copyout(&diag_read_buffer, diag_action,
+				    sizeof(diag_read_buffer) -
+				    sizeof(diag_read_buffer.PtrDataBuffer)) !=
+				    0)
+					return (MPS_DIAG_FAILURE);
+			}
+			break;
+
+		case MPS_FW_DIAG_TYPE_RELEASE:
+			if (length < sizeof(diag_release)) {
+				*return_code =
+				    MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = MPS_DIAG_FAILURE;
+				break;
+			}
+			if (copyin(diag_action, &diag_release,
+			    sizeof(diag_release)) != 0)
+				return (MPS_DIAG_FAILURE);
+			status = mps_diag_release(sc, &diag_release,
+			    return_code);
+			break;
+
+		default:
+			*return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
+			status = MPS_DIAG_FAILURE;
+			break;
+	}
+
+	if ((status == MPS_DIAG_FAILURE) &&
+	    (original_return_code == MPS_FW_DIAG_NEW) &&
+	    (*return_code != MPS_FW_DIAG_ERROR_SUCCESS))
+		status = MPS_DIAG_SUCCESS;
+
+	return (status);
+}
+
+static int
+mps_user_diag_action(struct mps_softc *sc, mps_diag_action_t *data)
+{
+	int			status;
+
+	/*
+	 * Only allow one diag action at one time.
+	 */
+	if (sc->mps_flags & MPS_FLAGS_BUSY) {
+		mps_dprint(sc, MPS_INFO, "%s: Only one FW diag command "
+		    "allowed at a single time.", __func__);
+		return (EBUSY);
+	}
+	sc->mps_flags |= MPS_FLAGS_BUSY;
+
+	/*
+	 * Send diag action request
+	 */
+	if (data->Action == MPS_FW_DIAG_TYPE_REGISTER ||
+	    data->Action == MPS_FW_DIAG_TYPE_UNREGISTER ||
+	    data->Action == MPS_FW_DIAG_TYPE_QUERY ||
+	    data->Action == MPS_FW_DIAG_TYPE_READ_BUFFER ||
+	    data->Action == MPS_FW_DIAG_TYPE_RELEASE) {
+		status = mps_do_diag_action(sc, data->Action,
+		    PTRIN(data->PtrDiagAction), data->Length,
+		    &data->ReturnCode);
+	} else
+		status = EINVAL;
+
+	sc->mps_flags &= ~MPS_FLAGS_BUSY;
+	return (status);
+}
+
+/*
+ * Copy the event recording mask and the event queue size out.  For
+ * clarification, the event recording mask (events_to_record) is not the same
+ * thing as the event mask (event_mask).  events_to_record has a bit set for
+ * every event type that is to be recorded by the driver, and event_mask has a
+ * bit cleared for every event that is allowed into the driver from the IOC.
+ * They really have nothing to do with each other.
+ */
+static void
+mps_user_event_query(struct mps_softc *sc, mps_event_query_t *data)
+{
+	uint8_t	i;
+
+	mps_lock(sc);
+	data->Entries = MPS_EVENT_QUEUE_SIZE;
+
+	for (i = 0; i < 4; i++) {
+		data->Types[i] = sc->events_to_record[i];
+	}
+	mps_unlock(sc);
+}
+
+/*
+ * Set the driver's event mask according to what's been given.  See
+ * mps_user_event_query for explanation of the event recording mask and the IOC
+ * event mask.  It's the app's responsibility to enable event logging by setting
+ * the bits in events_to_record.  Initially, no events will be logged.
+ */
+static void
+mps_user_event_enable(struct mps_softc *sc, mps_event_enable_t *data)
+{
+	uint8_t	i;
+
+	mps_lock(sc);
+	for (i = 0; i < 4; i++) {
+		sc->events_to_record[i] = data->Types[i];
+	}
+	mps_unlock(sc);
+}
+
+/*
+ * Copy out the events that have been recorded, up to the max events allowed.
+ */
+static int
+mps_user_event_report(struct mps_softc *sc, mps_event_report_t *data)
+{
+	int		status = 0;
+	uint32_t	size;
+
+	mps_lock(sc);
+	size = data->Size;
+	if ((size >= sizeof(sc->recorded_events)) && (status == 0)) {
+		mps_unlock(sc);
+		if (copyout((void *)sc->recorded_events,
+		    PTRIN(data->PtrEvents), size) != 0)
+			status = EFAULT;
+		mps_lock(sc);
+	} else {
+		/*
+		 * data->Size value is not large enough to copy event data.
+		 */
+		status = EFAULT;
+	}
+
+	/*
+	 * Change size value to match the number of bytes that were copied.
+	 */
+	if (status == 0)
+		data->Size = sizeof(sc->recorded_events);
+	mps_unlock(sc);
+
+	return (status);
+}
+
+/*
+ * Record events into the driver from the IOC if they are not masked.
+ */
+void
+mpssas_record_event(struct mps_softc *sc,
+    MPI2_EVENT_NOTIFICATION_REPLY *event_reply)
+{
+	uint32_t	event;
+	int		i, j;
+	uint16_t	event_data_len;
+	boolean_t	sendAEN = FALSE;
+
+	event = event_reply->Event;
+
+	/*
+	 * Generate a system event to let anyone who cares know that a
+	 * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
+	 * event mask is set to.
+	 */
+	if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
+		sendAEN = TRUE;
+	}
+
+	/*
+	 * Record the event only if its corresponding bit is set in
+	 * events_to_record.  event_index is the index into recorded_events and
+	 * event_number is the overall number of an event being recorded since
+	 * start-of-day.  event_index will roll over; event_number will never
+	 * roll over.
+	 */
+	i = (uint8_t)(event / 32);
+	j = (uint8_t)(event % 32);
+	if ((i < 4) && ((1 << j) & sc->events_to_record[i])) {
+		i = sc->event_index;
+		sc->recorded_events[i].Type = event;
+		sc->recorded_events[i].Number = ++sc->event_number;
+		bzero(sc->recorded_events[i].Data, MPS_MAX_EVENT_DATA_LENGTH *
+		    4);
+		event_data_len = event_reply->EventDataLength;
+
+		if (event_data_len > 0) {
+			/*
+			 * Limit data to size in m_event entry
+			 */
+			if (event_data_len > MPS_MAX_EVENT_DATA_LENGTH) {
+				event_data_len = MPS_MAX_EVENT_DATA_LENGTH;
+			}
+			for (j = 0; j < event_data_len; j++) {
+				sc->recorded_events[i].Data[j] =
+				    event_reply->EventData[j];
+			}
+
+			/*
+			 * check for index wrap-around
+			 */
+			if (++i == MPS_EVENT_QUEUE_SIZE) {
+				i = 0;
+			}
+			sc->event_index = (uint8_t)i;
+
+			/*
+			 * Set flag to send the event.
+			 */
+			sendAEN = TRUE;
+		}
+	}
+
+	/*
+	 * Generate a system event if flag is set to let anyone who cares know
+	 * that an event has occurred.
+	 */
+	if (sendAEN) {
+//SLM-how to send a system event (see kqueue, kevent)
+//		(void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
+//		    "SAS", NULL, NULL, DDI_NOSLEEP);
+	}
+}
+
+static int
+mps_user_reg_access(struct mps_softc *sc, mps_reg_access_t *data)
+{
+	int	status = 0;
+
+	switch (data->Command) {
+		/*
+		 * IO access is not supported.
+		 */
+		case REG_IO_READ:
+		case REG_IO_WRITE:
+			mps_dprint(sc, MPS_INFO, "IO access is not supported. "
+			    "Use memory access.");
+			status = EINVAL;
+			break;
+
+		case REG_MEM_READ:
+			data->RegData = mps_regread(sc, data->RegOffset);
+			break;
+
+		case REG_MEM_WRITE:
+			mps_regwrite(sc, data->RegOffset, data->RegData);
+			break;
+
+		default:
+			status = EINVAL;
+			break;
+	}
+
+	return (status);
+}
+
+static int
+mps_user_btdh(struct mps_softc *sc, mps_btdh_mapping_t *data)
+{
+	uint8_t		bt2dh = FALSE;
+	uint8_t		dh2bt = FALSE;
+	uint16_t	dev_handle, bus, target;
+
+	bus = data->Bus;
+	target = data->TargetID;
+	dev_handle = data->DevHandle;
+
+	/*
+	 * When DevHandle is 0xFFFF and Bus/Target are not 0xFFFF, use Bus/
+	 * Target to get DevHandle.  When Bus/Target are 0xFFFF and DevHandle is
+	 * not 0xFFFF, use DevHandle to get Bus/Target.  Anything else is
+	 * invalid.
+	 */
+	if ((bus == 0xFFFF) && (target == 0xFFFF) && (dev_handle != 0xFFFF))
+		dh2bt = TRUE;
+	if ((dev_handle == 0xFFFF) && (bus != 0xFFFF) && (target != 0xFFFF))
+		bt2dh = TRUE;
+	if (!dh2bt && !bt2dh)
+		return (EINVAL);
+
+	/*
+	 * Only handle bus of 0.  Make sure target is within range.
+	 */
+	if (bt2dh) {
+		if (bus != 0)
+			return (EINVAL);
+
+		if (target > sc->max_devices) {
+			mps_dprint(sc, MPS_FAULT, "Target ID is out of range "
+			   "for Bus/Target to DevHandle mapping.");
+			return (EINVAL);
+		}
+		dev_handle = sc->mapping_table[target].dev_handle;
+		if (dev_handle)
+			data->DevHandle = dev_handle;
+	} else {
+		bus = 0;
+		target = mps_mapping_get_sas_id_from_handle(sc, dev_handle);
+		data->Bus = bus;
+		data->TargetID = target;
+	}
+
+	return (0);
+}
+
+static int
+mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag)
+{
+	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, reset_loop;
+
+	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 = kmalloc(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 = kmalloc(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 = kmalloc(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;
+	case MPTIOCTL_PASS_THRU:
+		/*
+		 * The user has requested to pass through a command to be
+		 * executed by the MPT firmware.  Call our routine which does
+		 * this.  Only allow one passthru IOCTL at one time.
+		 */
+		error = mps_user_pass_thru(sc, (mps_pass_thru_t *)arg);
+		break;
+	case MPTIOCTL_GET_ADAPTER_DATA:
+		/*
+		 * The user has requested to read adapter data.  Call our
+		 * routine which does this.
+		 */
+		error = 0;
+		mps_user_get_adapter_data(sc, (mps_adapter_data_t *)arg);
+		break;
+	case MPTIOCTL_GET_PCI_INFO:
+		/*
+		 * The user has requested to read pci info.  Call
+		 * our routine which does this.
+		 */
+		mps_lock(sc);
+		error = 0;
+		mps_user_read_pci_info(sc, (mps_pci_info_t *)arg);
+		mps_unlock(sc);
+		break;
+	case MPTIOCTL_RESET_ADAPTER:
+		mps_lock(sc);
+		sc->port_enable_complete = 0;
+		error = mps_reinit(sc);
+		mps_unlock(sc);
+		/*
+		 * Wait no more than 5 minutes for Port Enable to complete
+		 */
+		for (reset_loop = 0; (reset_loop < MPS_DIAG_RESET_TIMEOUT) &&
+		    (!sc->port_enable_complete); reset_loop++) {
+			DELAY(1000);
+		}
+		if (reset_loop == MPS_DIAG_RESET_TIMEOUT) {
+			kprintf("Port Enable did not complete after Diag "
+			    "Reset.\n");
+		}
+		break;
+	case MPTIOCTL_DIAG_ACTION:
+		/*
+		 * The user has done a diag buffer action.  Call our routine
+		 * which does this.  Only allow one diag action at one time.
+		 */
+		mps_lock(sc);
+		error = mps_user_diag_action(sc, (mps_diag_action_t *)arg);
+		mps_unlock(sc);
+		break;
+	case MPTIOCTL_EVENT_QUERY:
+		/*
+		 * The user has done an event query. Call our routine which does
+		 * this.
+		 */
+		error = 0;
+		mps_user_event_query(sc, (mps_event_query_t *)arg);
+		break;
+	case MPTIOCTL_EVENT_ENABLE:
+		/*
+		 * The user has done an event enable. Call our routine which
+		 * does this.
+		 */
+		error = 0;
+		mps_user_event_enable(sc, (mps_event_enable_t *)arg);
+		break;
+	case MPTIOCTL_EVENT_REPORT:
+		/*
+		 * The user has done an event report. Call our routine which
+		 * does this.
+		 */
+		error = mps_user_event_report(sc, (mps_event_report_t *)arg);
+		break;
+	case MPTIOCTL_REG_ACCESS:
+		/*
+		 * The user has requested register access.  Call our routine
+		 * which does this.
+		 */
+		mps_lock(sc);
+		error = mps_user_reg_access(sc, (mps_reg_access_t *)arg);
+		mps_unlock(sc);
+		break;
+	case MPTIOCTL_BTDH_MAPPING:
+		/*
+		 * The user has requested to translate a bus/target to a
+		 * DevHandle or a DevHandle to a bus/target.  Call our routine
+		 * which does this.
+		 */
+		error = mps_user_btdh(sc, (mps_btdh_mapping_t *)arg);
+		break;
+	default:
+		error = ENOIOCTL;
+		break;
+	}
+
+	if (mps_page != NULL)
+		kfree(mps_page, M_MPSUSER);
+
+	return (error);
+}
+
+#ifdef COMPAT_FREEBSD32
+
+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 dev_ioctl_args *ap)
+{
+	cdev_t dev = ap->a_head.a_dev;
+	u_long com = ap->a_cmd;
+	caddr_t arg = ap->a_data;
+	int flag = ap->a_fflag;
+
+#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));
+}
diff --git a/sys/dev/raid/mps/mpsvar.h b/sys/dev/raid/mps/mpsvar.h
new file mode 100644
index 0000000..17d853d
--- /dev/null
+++ b/sys/dev/raid/mps/mpsvar.h
@@ -0,0 +1,768 @@
+/*-
+ * 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: src/sys/dev/mps/mpsvar.h,v 1.9 2012/01/26 18:17:21 ken Exp $
+ */
+/*-
+ * Copyright (c) 2011 LSI Corp.
+ * 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.
+ *
+ * LSI MPT-Fusion Host Adapter FreeBSD
+ *
+ * $FreeBSD: src/sys/dev/mps/mpsvar.h,v 1.9 2012/01/26 18:17:21 ken Exp $
+ */
+
+#ifndef _MPSVAR_H
+#define _MPSVAR_H
+
+#define MPS_DRIVER_VERSION	"11.255.03.00-fbsd"
+
+#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	2048
+#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	 CAN_SLEEP			1
+#define  NO_SLEEP			0
+
+#define MPS_PERIODIC_DELAY	1	/* 1 second heartbeat/watchdog check */
+
+#define MPS_SCSI_RI_INVALID_FRAME	(0x00000002)
+
+/*
+ * host mapping related macro definitions
+ */
+#define MPS_MAPTABLE_BAD_IDX	0xFFFFFFFF
+#define MPS_DPM_BAD_IDX		0xFFFF
+#define MPS_ENCTABLE_BAD_IDX	0xFF
+#define MPS_MAX_MISSING_COUNT	0x0F
+#define MPS_DEV_RESERVED	0x20000000
+#define MPS_MAP_IN_USE		0x10000000
+#define MPS_RAID_CHANNEL	1
+#define MPS_MAP_BAD_ID		0xFFFFFFFF
+
+/*
+ * WarpDrive controller
+ */
+#define	MPS_CHIP_WD_DEVICE_ID	0x007E
+#define	MPS_WD_LSI_OEM		0x80
+#define	MPS_WD_HIDE_EXPOSE_MASK	0x03
+#define	MPS_WD_HIDE_ALWAYS	0x00
+#define	MPS_WD_EXPOSE_ALWAYS	0x01
+#define	MPS_WD_HIDE_IF_VOLUME	0x02
+#define	MPS_WD_RETRY		0x01
+#define	MPS_MAN_PAGE10_SIZE	0x5C	/* Hardcode for now */
+#define MPS_MAX_DISKS_IN_VOL	10
+
+/*
+ * WarpDrive Event Logging
+ */
+#define	MPI2_WD_LOG_ENTRY	0x8002
+#define	MPI2_WD_SSD_THROTTLING	0x0041
+#define	MPI2_WD_DRIVE_LIFE_WARN	0x0043
+#define	MPI2_WD_DRIVE_LIFE_DEAD	0x0044
+#define	MPI2_WD_RAIL_MON_FAIL	0x004D
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+/**
+ * struct dev_mapping_table - device mapping information
+ * @physical_id: SAS address for drives or WWID for RAID volumes
+ * @device_info: bitfield provides detailed info about the device
+ * @phy_bits: bitfields indicating controller phys
+ * @dpm_entry_num: index of this device in device persistent map table
+ * @dev_handle: device handle for the device pointed by this entry
+ * @channel: target channel
+ * @id: target id
+ * @missing_count: number of times the device not detected by driver
+ * @hide_flag: Hide this physical disk/not (foreign configuration)
+ * @init_complete: Whether the start of the day checks completed or not
+ */
+struct dev_mapping_table {
+	u64	physical_id;
+	u32	device_info;
+	u32	phy_bits;
+	u16	dpm_entry_num;
+	u16	dev_handle;
+	u8	reserved1;
+	u8	channel;
+	u16	id;
+	u8	missing_count;
+	u8	init_complete;
+	u8	TLR_bits;
+	u8	reserved2;
+};
+
+/**
+ * struct enc_mapping_table -  mapping information about an enclosure
+ * @enclosure_id: Logical ID of this enclosure
+ * @start_index: index to the entry in dev_mapping_table
+ * @phy_bits: bitfields indicating controller phys
+ * @dpm_entry_num: index of this enclosure in device persistent map table
+ * @enc_handle: device handle for the enclosure pointed by this entry
+ * @num_slots: number of slots in the enclosure
+ * @start_slot: Starting slot id
+ * @missing_count: number of times the device not detected by driver
+ * @removal_flag: used to mark the device for removal
+ * @skip_search: used as a flag to include/exclude enclosure for search
+ * @init_complete: Whether the start of the day checks completed or not
+ */
+struct enc_mapping_table {
+	u64	enclosure_id;
+	u32	start_index;
+	u32	phy_bits;
+	u16	dpm_entry_num;
+	u16	enc_handle;
+	u16	num_slots;
+	u16	start_slot;
+	u8	missing_count;
+	u8	removal_flag;
+	u8	skip_search;
+	u8	init_complete;
+};
+
+/**
+ * struct map_removal_table - entries to be removed from mapping table
+ * @dpm_entry_num: index of this device in device persistent map table
+ * @dev_handle: device handle for the device pointed by this entry
+ */
+struct map_removal_table{
+	u16	dpm_entry_num;
+	u16	dev_handle;
+};
+
+typedef struct mps_fw_diagnostic_buffer {
+	size_t		size;
+	uint8_t		extended_type;
+	uint8_t		buffer_type;
+	uint8_t		force_release;
+	uint32_t	product_specific[23];
+	uint8_t		immediate;
+	uint8_t		enabled;
+	uint8_t		valid_data;
+	uint8_t		owned_by_firmware;
+	uint32_t	unique_id;
+} mps_fw_diagnostic_buffer_t;
+
+struct mps_softc;
+struct mps_command;
+struct mpssas_softc;
+union ccb;
+struct mpssas_target;
+struct mps_column_map;
+
+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;
+	TAILQ_ENTRY(mps_command)	cm_recovery;
+	struct mps_softc		*cm_sc;
+	union ccb			*cm_ccb;
+	void				*cm_data;
+	u_int				cm_length;
+	u_int				cm_out_len;
+	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_lun;
+	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_DD_IO		(1 << 6)
+#define MPS_CM_FLAGS_USE_UIO		(1 << 7)
+#define MPS_CM_FLAGS_SMP_PASS		(1 << 8)
+#define	MPS_CM_FLAGS_CHAIN_FAILED	(1 << 9)
+#define	MPS_CM_FLAGS_ERROR_MASK		MPS_CM_FLAGS_CHAIN_FAILED
+	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_column_map {
+	uint16_t			dev_handle;
+	uint8_t				phys_disk_num;
+};
+
+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)
+#define MPS_FLAGS_DIAGRESET	(1 << 4)
+#define	MPS_FLAGS_ATTACH_DONE	(1 << 5)
+#define	MPS_FLAGS_WD_AVAILABLE	(1 << 6)
+	u_int				mps_debug;
+#if 0 /* XXX swildner */
+	u_int				disable_msix;
+#endif
+	u_int				enable_msi;
+	int				tm_cmds_active;
+	int				io_cmds_active;
+	int				io_cmds_highwater;
+	int				chain_free;
+	int				max_chains;
+	int				chain_free_lowwater;
+#if __FreeBSD_version >= 900030
+	uint64_t			chain_alloc_fail;
+#endif
+	struct sysctl_ctx_list		sysctl_ctx;
+	struct sysctl_oid		*sysctl_tree;
+	char                            fw_version[16];
+	struct mps_command		*commands;
+	struct mps_chain		*chains;
+	struct callout			periodic;
+
+	struct mpssas_softc		*sassc;
+
+	TAILQ_HEAD(, mps_command)	req_list;
+	TAILQ_HEAD(, mps_command)	high_priority_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 lock			mps_lock;
+	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];
+	int				mps_irq_type[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;
+
+	uint8_t				*fw_diag_buffer;
+	bus_addr_t			fw_diag_busaddr;
+	bus_dma_tag_t			fw_diag_dmat;
+	bus_dmamap_t			fw_diag_map;
+
+	uint8_t				ir_firmware;
+
+	/* static config pages */
+	Mpi2IOCPage8_t			ioc_pg8;
+
+	/* host mapping support */
+	struct dev_mapping_table	*mapping_table;
+	struct enc_mapping_table	*enclosure_table;
+	struct map_removal_table	*removal_table;
+	uint8_t				*dpm_entry_used;
+	uint8_t				*dpm_flush_entry;
+	Mpi2DriverMappingPage0_t	*dpm_pg0;
+	uint16_t			max_devices;
+	uint16_t			max_enclosures;
+	uint16_t			max_expanders;
+	uint8_t				max_volumes;
+	uint8_t				num_enc_table_entries;
+	uint8_t				num_rsvd_entries;
+	uint8_t				num_channels;
+	uint16_t			max_dpm_entries;
+	uint8_t				is_dpm_enable;
+	uint8_t				track_mapping_events;
+	uint32_t			pending_map_events;
+	uint8_t				mt_full_retry;
+	uint8_t				mt_add_device_failed;
+
+	/* FW diag Buffer List */
+	mps_fw_diagnostic_buffer_t
+				fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_COUNT];
+
+	/* Event Recording IOCTL support */
+	uint32_t			events_to_record[4];
+	mps_event_entry_t		recorded_events[MPS_EVENT_QUEUE_SIZE];
+	uint8_t				event_index;
+	uint32_t			event_number;
+
+	/* EEDP and TLR support */
+	uint8_t				eedp_enabled;
+	uint8_t				control_TLR;
+
+	/* Shutdown Event Handler */
+	eventhandler_tag		shutdown_eh;
+
+	/* To track topo events during reset */
+#define	MPS_DIAG_RESET_TIMEOUT	300000
+	uint8_t				wait_for_port_enable;
+	uint8_t				port_enable_complete;
+
+	/* WD controller */
+	uint8_t				WD_valid_config;
+	uint8_t				WD_hide_expose;
+
+	/* Direct Drive for WarpDrive */
+	uint8_t				DD_num_phys_disks;
+	uint16_t			DD_dev_handle;
+	uint32_t			DD_stripe_size;
+	uint32_t			DD_stripe_exponent;
+	uint32_t			DD_block_size;
+	uint16_t			DD_block_exponent;
+	uint64_t			DD_max_lba;
+	struct mps_column_map		DD_column_map[MPS_MAX_DISKS_IN_VOL];
+};
+
+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;
+};
+
+struct scsi_read_capacity_eedp
+{
+	uint8_t addr[8];
+	uint8_t length[4];
+	uint8_t protect;
+};
+
+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);
+		sc->chain_free--;
+		if (sc->chain_free < sc->chain_free_lowwater)
+			sc->chain_free_lowwater = sc->chain_free;
+	}
+#if __FreeBSD_version >= 900030
+	else
+		sc->chain_alloc_fail++;
+#endif
+	return (chain);
+}
+
+static __inline void
+mps_free_chain(struct mps_softc *sc, struct mps_chain *chain)
+{
+#if 0
+	bzero(chain->chain, 128);
+#endif
+	sc->chain_free++;
+	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_ccb = NULL;
+	cm->cm_targ = NULL;
+	cm->cm_max_segs = 0;
+	cm->cm_lun = 0;
+	cm->cm_state = MPS_CM_STATE_FREE;
+	TAILQ_FOREACH_MUTABLE(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_free_high_priority_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_ccb = NULL;
+	cm->cm_targ = NULL;
+	cm->cm_lun = 0;
+	cm->cm_state = MPS_CM_STATE_FREE;
+	TAILQ_FOREACH_MUTABLE(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->high_priority_req_list, cm, cm_link);
+}
+
+static __inline struct mps_command *
+mps_alloc_high_priority_command(struct mps_softc *sc)
+{
+	struct mps_command *cm;
+
+	cm = TAILQ_FIRST(&sc->high_priority_req_list);
+	if (cm == NULL)
+		return (NULL);
+
+	TAILQ_REMOVE(&sc->high_priority_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)
+{
+	lockmgr(&sc->mps_lock, LK_EXCLUSIVE);
+}
+
+static __inline void
+mps_unlock(struct mps_softc *sc)
+{
+	lockmgr(&sc->mps_lock, LK_RELEASE);
+}
+
+#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_vprintf(sc, args...)			\
+do {							\
+	if (bootverbose)				\
+		mps_printf(sc, ##args);			\
+} while (0)
+
+#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)				\
+		kprintf("\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 *sc);
+int mps_pci_restore(struct mps_softc *sc);
+
+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_restart(struct mps_softc *);
+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_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_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 *);
+void mpssas_record_event(struct mps_softc *sc,
+    MPI2_EVENT_NOTIFICATION_REPLY *event_reply);
+
+int mps_map_command(struct mps_softc *sc, struct mps_command *cm);
+int mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout);
+int mps_request_polled(struct mps_softc *sc, struct mps_command *cm);
+
+int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t
+    *mpi_reply, Mpi2BiosPage3_t *config_page);
+int mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
+    *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address);
+int mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *,
+    Mpi2IOCPage8_t *);
+int mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply);
+int mps_config_get_sas_device_pg0(struct mps_softc *, Mpi2ConfigReply_t *,
+    Mpi2SasDevicePage0_t *, u32 , u16 );
+int mps_config_get_dpm_pg0(struct mps_softc *, Mpi2ConfigReply_t *,
+    Mpi2DriverMappingPage0_t *, u16 );
+int mps_config_get_raid_volume_pg1(struct mps_softc *sc,
+    Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
+    u16 handle);
+int mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle,
+    u64 *wwid);
+int mps_config_get_raid_pd_pg0(struct mps_softc *sc,
+    Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page,
+    u32 page_address);
+void mpssas_ir_shutdown(struct mps_softc *sc);
+
+int mps_reinit(struct mps_softc *sc);
+void mpssas_handle_reinit(struct mps_softc *sc);
+
+void mps_base_static_config_pages(struct mps_softc *sc);
+void mps_wd_config_pages(struct mps_softc *sc);
+
+int mps_mapping_initialize(struct mps_softc *);
+void mps_mapping_topology_change_event(struct mps_softc *,
+    Mpi2EventDataSasTopologyChangeList_t *);
+int mps_mapping_is_reinit_required(struct mps_softc *);
+void mps_mapping_free_memory(struct mps_softc *sc);
+int mps_config_set_dpm_pg0(struct mps_softc *, Mpi2ConfigReply_t *,
+    Mpi2DriverMappingPage0_t *, u16 );
+void mps_mapping_exit(struct mps_softc *);
+void mps_mapping_check_devices(struct mps_softc *, int);
+int mps_mapping_allocate_memory(struct mps_softc *sc);
+unsigned int mps_mapping_get_sas_id(struct mps_softc *, uint64_t , u16);
+unsigned int mps_mapping_get_sas_id_from_handle(struct mps_softc *sc,
+    u16 handle);
+unsigned int mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid,
+    u16 handle);
+unsigned int mps_mapping_get_raid_id_from_handle(struct mps_softc *sc,
+    u16 volHandle);
+void mps_mapping_enclosure_dev_status_change_event(struct mps_softc *,
+    Mpi2EventDataSasEnclDevStatusChange_t *event_data);
+void mps_mapping_ir_config_change_event(struct mps_softc *sc,
+    Mpi2EventDataIrConfigChangeList_t *event_data);
+
+void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
+    MPI2_EVENT_NOTIFICATION_REPLY *event);
+void mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle);
+int mpssas_startup(struct mps_softc *sc);
+
+SYSCTL_DECL(_hw_mps);
+
+#define mps_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
+    kthread_create(func, farg, proc_ptr, fmtstr, arg)
+#define mps_kproc_exit(arg)	kthread_exit()
+
+#if defined(CAM_PRIORITY_XPT)
+#define MPS_PRIORITY_XPT	CAM_PRIORITY_XPT
+#else
+#define MPS_PRIORITY_XPT	5
+#endif
+#endif
-- 
1.7.7.2

